#!/usr/bin/python

import numpy as np
import matplotlib.pyplot as plt
import re

sq_list = [1, 2, 5, 10];
models = ["pcs", "traffic", "epidemic", "airport"];
locktypes = ["mutexes", "spinlocks"];
parttypes = ["rr", "pg", "block"];

warped_data_path = "."

def filenames():
    for sq in sq_list:
        for pt in parttypes:
            filename = "1n10wt{}sq25ssp100gvtp_{}.csv".format(sq, pt)
            yield filename

def filter_total_lines(f):
    for line in f:
        if "Total" in line:
            yield line

def addPlotXY(plots, title, xlab, ylab, lines):
    new_plot = {"title": title, "xlabel": xlab, "ylabel": ylab, "lines": lines}
    plots.append(new_plot)

def addLineXY(lines, xvals, yvals, leg):
    new_line = {"xvals": xvals, "yvals": yvals, "legend_title": leg}
    lines.append(new_line)

def autolabel(rects):
    # attach some text labels
    for rect in rects:
        height = rect.get_height()
        plt.text(rect.get_x()+rect.get_width()/2.0, 1.05*height, '%.02f'%float(height), ha='center', va='bottom')

def main():

    plots = list()

    ##
    ## Increasing LTSF Queues
    ##

    event_rate_lines = list()
    efficiency_lines = list()
    trollback_lines = list()
    prollback_lines = list()
    srollback_lines = list()
    speedup_lines = list()
    memory_lines = list()
    memi_lines = list()
    rb_length_lines = list()

    for m in models:

        sq_x = list()
        time_y = list()
        comm_y = list()
        proc_y = list()
        prb_y = list()
        srb_y = list()
        mem_y = list()
        time_single = 0
        mem_single = 0

        f = filenames()
        for filename in f:
            # obtain configs from filename
            nodes, wt, sq, ssp, gvtp = re.findall(r'\d+', filename)

            if ("rr" in filename or "block" in filename):
                continue

            with open("{}/{}/mutexes/{}".format(warped_data_path, m, filename)) as plotpoint:
                ydata = np.genfromtxt(filter_total_lines(plotpoint), delimiter=",",
                    names=['node', 'time', 'objects', 'localp', 'remotep', 'localn', 'remoten',
                           'prollbacks', 'srollbacks', 'coasted','cancelled', 'processed',
                            'committed', 'memory'])

            sq_x.append(sq)

            if sq == '1':
                mem_single = np.mean(ydata['memory'])
                time_single = np.mean(ydata['time'])

            time_y.append(np.mean(ydata['time']))
            comm_y.append(np.mean(ydata['committed']))
            proc_y.append(np.mean(ydata['processed']))
            prb_y.append(np.mean(ydata['prollbacks']))
            srb_y.append(np.mean(ydata['srollbacks']))
            mem_y.append(np.mean(ydata['memory']))

        speedup = [time_single / a for a in time_y]
        rollbacks = [a + b for a, b in zip(prb_y, srb_y)]
        event_rate = [a / b for a, b in zip(comm_y, time_y)]
        efficiency = [a / b * 100 for a, b in zip(comm_y, proc_y)]
        mem_increase = [(a - mem_single) / a * 100 for a in mem_y]
        rb_length = [(a - b) / (c + d) for a, b, c, d in zip(proc_y, comm_y, prb_y, srb_y)]

        addLineXY(memory_lines, sq_x, mem_y, m)
        addLineXY(memi_lines, sq_x, mem_increase, m)
        addLineXY(efficiency_lines, sq_x, efficiency, m)
        addLineXY(event_rate_lines, sq_x, event_rate, m)
        addLineXY(trollback_lines, sq_x, rollbacks, m)
        addLineXY(prollback_lines, sq_x, prb_y, m)
        addLineXY(srollback_lines, sq_x, srb_y, m)
        addLineXY(speedup_lines, sq_x, speedup, m)
        addLineXY(rb_length_lines, sq_x, rb_length, m)

    addPlotXY(plots, "", "# LTSF Queues", "Average Peak Memory", memory_lines)
    addPlotXY(plots, "", "# LTSF Queues", "% Memory Increase", memi_lines)
    addPlotXY(plots, "", "# LTSF Queues", "Total Rollbacks", trollback_lines)
#    addPlotXY(plots, "", "# LTSF Queues", "Primary Rollbacks", prollback_lines)
#    addPlotXY(plots, "", "# LTSF Queues", "Secondary Rollbacks", srollback_lines)
    addPlotXY(plots, "", "# LTSF Queues", "Efficiency (%)", efficiency_lines)
    addPlotXY(plots, "", "# LTSF Queues", "Event Rate", event_rate_lines)
    addPlotXY(plots, "", "# LTSF Queues", "Speedup", speedup_lines)
    addPlotXY(plots, "", "# LTSF Queues", "Rollback Length", rb_length_lines)


    ##
    ##  Spinlocks vs Mutexes
    ##

    one_times_by_model_mut = list()
    two_times_by_model_mut = list()
    five_times_by_model_mut = list()
    ten_times_by_model_mut = list()

    one_times_by_model_sp = list()
    two_times_by_model_sp = list()
    five_times_by_model_sp = list()
    ten_times_by_model_sp = list()

    for m in models:
        for lt in locktypes:
            f = filenames()
            for filename in f:
                # obtain configs from filename
                nodes, wt, sq, ssp, gvtp = re.findall(r'\d+', filename)

                if "rr" in filename or "block" in filename:
                    continue

                with open("{}/{}/{}/{}".format(warped_data_path, m, lt, filename)) as plotpoint:
                    ydata = np.genfromtxt(filter_total_lines(plotpoint), delimiter=",",
                        names=['node', 'time', 'objects', 'localp', 'remotep', 'localn', 'remoten',
                               'prollbacks', 'srollbacks', 'coasted','cancelled', 'processed',
                                'committed', 'memory'])

                if lt == "mutexes":
                    if sq == '1':
                        one_times_by_model_mut.append(np.mean(ydata['time']))
                    elif sq == '2':
                        two_times_by_model_mut.append(np.mean(ydata['time']))
                    elif sq == '5':
                        five_times_by_model_mut.append(np.mean(ydata['time']))
                    else:
                        ten_times_by_model_mut.append(np.mean(ydata['time']))

                elif lt == "spinlocks":
                    if sq == '1':
                        one_times_by_model_sp.append(np.mean(ydata['time']))
                    elif sq == '2':
                        two_times_by_model_sp.append(np.mean(ydata['time']))
                    elif sq == '5':
                        five_times_by_model_sp.append(np.mean(ydata['time']))
                    else:
                        ten_times_by_model_sp.append(np.mean(ydata['time']))

    one_speedup_by_model = [a / b for a, b in zip(one_times_by_model_mut, one_times_by_model_sp)]
    two_speedup_by_model = [a / b for a, b in zip(two_times_by_model_mut, two_times_by_model_sp)]
    five_speedup_by_model = [a / b for a, b in zip(five_times_by_model_mut, five_times_by_model_sp)]
    ten_speedup_by_model = [a / b for a, b in zip(ten_times_by_model_mut, ten_times_by_model_sp)]

    index = np.arange(4)
    index = 2*index
    bar_width = 0.40
    rects1 = plt.bar(index, one_speedup_by_model, bar_width,
            color='g', label='1 LTSF Queue', alpha=0.7)
    rects2 = plt.bar(index+bar_width, two_speedup_by_model, bar_width,
            color='b', label = '2 LTSF Queues', alpha=0.7)
    rects3 = plt.bar(index+2*bar_width, five_speedup_by_model, bar_width,
            color='r', label = '5 LTSF Queues', alpha=0.7)
    rects4 = plt.bar(index+3*bar_width, ten_speedup_by_model, bar_width,
            color='c', label = '10 LTSF Queues', alpha=0.7)

    autolabel(rects1)
    autolabel(rects2)
    autolabel(rects3)
    autolabel(rects4)
    plt.xlim(-bar_width, len(index)+10*bar_width)
    plt.xlabel('Model')
    plt.ylabel('Speedup')
    plt.ylim(0, 2.0)
    plt.xticks(index+2*bar_width, ('PCS', 'Traffic', 'Epidemic', 'Airport'))
    plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.10), ncol=4, fancybox=True, shadow=True)
    plt.grid()
    plt.show()


    ##
    ## Partitioning among LTSF Queues
    ##

    one_times_by_model_rr = list()
    two_times_by_model_rr = list()
    five_times_by_model_rr = list()
    ten_times_by_model_rr = list()

    one_times_by_model_pg = list()
    two_times_by_model_pg = list()
    five_times_by_model_pg = list()
    ten_times_by_model_pg = list()

    one_rbs_by_model_rr = list()
    two_rbs_by_model_rr = list()
    five_rbs_by_model_rr = list()
    ten_rbs_by_model_rr = list()

    one_rbs_by_model_pg = list()
    two_rbs_by_model_pg = list()
    five_rbs_by_model_pg = list()
    ten_rbs_by_model_pg = list()

    for m in models:
        f = filenames()
        for filename in f:
            # obtain configs from filename
            nodes, wt, sq, ssp, gvtp = re.findall(r'\d+', filename)

            if "block" in filename:
                continue

            with open("{}/{}/mutexes/{}".format(warped_data_path, m, filename)) as plotpoint:
                ydata = np.genfromtxt(filter_total_lines(plotpoint), delimiter=",",
                    names=['node', 'time', 'objects', 'localp', 'remotep', 'localn', 'remoten',
                           'prollbacks', 'srollbacks', 'coasted','cancelled', 'processed',
                           'committed', 'memory'])

            rbs = np.mean(ydata['srollbacks'])# + np.mean(ydata['srollbacks'])

            if "rr" in filename:
                if sq == '1':
                    one_times_by_model_rr.append(np.mean(ydata['time']))
                    one_rbs_by_model_rr.append(rbs)
                elif sq == '2':
                    two_times_by_model_rr.append(np.mean(ydata['time']))
                    two_rbs_by_model_rr.append(rbs)
                elif sq == '5':
                    five_times_by_model_rr.append(np.mean(ydata['time']))
                    five_rbs_by_model_rr.append(rbs)
                else:
                    ten_times_by_model_rr.append(np.mean(ydata['time']))
                    ten_rbs_by_model_rr.append(rbs)

            elif "pg" in filename:
                if sq == '1':
                    one_times_by_model_pg.append(np.mean(ydata['time']))
                    one_rbs_by_model_pg.append(rbs)
                elif sq == '2':
                    two_times_by_model_pg.append(np.mean(ydata['time']))
                    two_rbs_by_model_pg.append(rbs)
                elif sq == '5':
                    five_times_by_model_pg.append(np.mean(ydata['time']))
                    five_rbs_by_model_pg.append(rbs)
                else:
                    ten_times_by_model_pg.append(np.mean(ydata['time']))
                    ten_rbs_by_model_pg.append(rbs)

    one_speedup_by_model    = [a / b for a, b in zip(one_times_by_model_rr, one_times_by_model_pg)]
    two_speedup_by_model    = [a / b for a, b in zip(two_times_by_model_rr, two_times_by_model_pg)]
    five_speedup_by_model   = [a / b for a, b in zip(five_times_by_model_rr, five_times_by_model_pg)]
    ten_speedup_by_model    = [a / b for a, b in zip(ten_times_by_model_rr, ten_times_by_model_pg)]

    rects1 = plt.bar(index, one_speedup_by_model, bar_width,
            color='g', label='1 LTSF Queue', alpha=0.7)
    rects2 = plt.bar(index+bar_width, two_speedup_by_model, bar_width,
            color='b', label = '2 LTSF Queues', alpha=0.7)
    rects3 = plt.bar(index+2*bar_width, five_speedup_by_model, bar_width,
            color='r', label = '5 LTSF Queues', alpha=0.7)
    rects4 = plt.bar(index+3*bar_width, ten_speedup_by_model, bar_width,
            color='c', label = '10 LTSF Queues', alpha=0.7)

    autolabel(rects1)
    autolabel(rects2)
    autolabel(rects3)
    autolabel(rects4)
    plt.xlim(-bar_width, len(index)+10*bar_width)
    plt.xlabel('Model')
    plt.ylabel('Speedup')
    plt.xticks(index+2*bar_width, ('PCS', 'Traffic', 'Epidemic', 'Airport'))
    plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.10), ncol=4, fancybox=True, shadow=True)
    plt.grid()
    plt.show()


    times_by_model_rr = list()
    times_by_model_pg = list()
    times_by_model_block = list()

    rbs_by_model_rr = list()
    rbs_by_model_pg = list()
    rbs_by_model_block = list()

    comm_by_model_rr = list()
    comm_by_model_pg = list()
    comm_by_model_block = list()

    proc_by_model_rr = list()
    proc_by_model_pg = list()
    proc_by_model_block = list()

    for m in models:
        f = filenames()
        for filename in f:
            # obtain configs from filename
            nodes, wt, sq, ssp, gvtp = re.findall(r'\d+', filename)

            if "block" in filename and sq != '10':
                continue

            with open("{}/{}/mutexes/{}".format(warped_data_path, m, filename)) as plotpoint:
                ydata = np.genfromtxt(filter_total_lines(plotpoint), delimiter=",",
                    names=['node', 'time', 'objects', 'localp', 'remotep', 'localn', 'remoten',
                           'prollbacks', 'srollbacks', 'coasted','cancelled', 'processed',
                           'committed', 'memory'])

            rbs = np.mean(ydata['srollbacks']) + np.mean(ydata['srollbacks'])
            comm = np.mean(ydata['committed'])
            proc = np.mean(ydata['processed'])

            if "rr" in filename:
                if sq == '10':
                    times_by_model_rr.append(np.mean(ydata['time']))
                    rbs_by_model_rr.append(rbs)
                    comm_by_model_rr.append(comm)
                    proc_by_model_rr.append(proc)
            elif "pg" in filename:
                if sq == '10':
                    times_by_model_pg.append(np.mean(ydata['time']))
                    rbs_by_model_pg.append(rbs)
                    comm_by_model_pg.append(comm)
                    proc_by_model_pg.append(proc)
            elif "block" in filename:
                if sq == '10':
                    times_by_model_block.append(np.mean(ydata['time']))
                    rbs_by_model_block.append(rbs)
                    comm_by_model_block.append(comm)
                    proc_by_model_block.append(proc)

    bar_width = 0.60

    rects1 = plt.bar(index-bar_width, times_by_model_rr, bar_width,
            color='g', label='Round-Robin', alpha=0.7)
    rects2 = plt.bar(index, times_by_model_pg, bar_width,
            color='b', label = 'Profile-Guided', alpha=0.7)
    rects3 = plt.bar(index+bar_width, times_by_model_block, bar_width,
            color='r', label = 'Block', alpha=0.7)

    autolabel(rects1)
    autolabel(rects2)
    autolabel(rects3)
    plt.xlim(-2*bar_width, len(index)+7*bar_width)
    plt.xlabel('Model')
    plt.ylabel('Simulation Time (s)')
    plt.xticks(index+0.5*bar_width, ('PCS', 'Traffic', 'Epidemic', 'Airport'))
    plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.10), ncol=4, fancybox=True, shadow=True)
    plt.grid()
    plt.show()

    rects1 = plt.bar(index-bar_width, rbs_by_model_rr, bar_width,
            color='g', label='Round-Robin', alpha=0.7)
    rects2 = plt.bar(index, rbs_by_model_pg, bar_width,
            color='b', label = 'Profile-Guided', alpha=0.7)
    rects3 = plt.bar(index+bar_width, rbs_by_model_block, bar_width,
            color='r', label = 'Block', alpha=0.7)

    autolabel(rects1)
    autolabel(rects2)
    autolabel(rects3)
    plt.xlim(-2*bar_width, len(index)+7*bar_width)
    plt.xlabel('Model')
    plt.ylabel('Rollbacks')
    plt.xticks(index+0.5*bar_width, ('PCS', 'Traffic', 'Epidemic', 'Airport'))
    plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.10), ncol=4, fancybox=True, shadow=True)
    plt.grid()
    plt.show()


    efficiency_by_model_rr = [a / b * 100 for a, b in zip(comm_by_model_rr, proc_by_model_rr)]
    efficiency_by_model_block = [a / b * 100 for a, b in zip(comm_by_model_block, proc_by_model_block)]
    efficiency_by_model_pg = [a / b * 100 for a, b in zip(comm_by_model_pg, proc_by_model_pg)]

    rects1 = plt.bar(index-bar_width, efficiency_by_model_rr, bar_width,
            color='g', label='Round-Robin', alpha=0.7)
    rects2 = plt.bar(index, efficiency_by_model_pg, bar_width,
            color='b', label = 'Profile-Guided', alpha=0.7)
    rects3 = plt.bar(index+bar_width, efficiency_by_model_block, bar_width,
            color='r', label = 'Block', alpha=0.7)

    autolabel(rects1)
    autolabel(rects2)
    autolabel(rects3)
    plt.xlim(-2*bar_width, len(index)+7*bar_width)
    plt.xlabel('Model')
    plt.ylim(0, 110)
    plt.ylabel('Efficiency (%)')
    plt.xticks(index+0.5*bar_width, ('PCS', 'Traffic', 'Epidemic', 'Airport'))
    plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.10), ncol=4, fancybox=True, shadow=True)
    plt.grid()
    plt.show()


    for i, p in enumerate(plots):
        fig = plt.figure(i)
        plt.title(p["title"])
        plt.xlabel(p["xlabel"], fontsize=20)
        plt.ylabel(p["ylabel"], fontsize=20)
        
        legend_entries = list()
        for l in p["lines"]:
            plt.plot(l["xvals"], l["yvals"], marker='o')
            legend_entries.append(l["legend_title"])

        plt.grid()
        plt.legend(legend_entries, loc='upper center', bbox_to_anchor=(0.5, 1.10), ncol=4, fancybox=True, shadow=True)

    plt.show()



if __name__ == '__main__':
    main()


