import csv
import re
from random import gauss
from typing import List
from matplotlib.patches import Patch

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.lines import Line2D

lbl_font = {
    'family': 'DejaVu Sans',
    'weight': 'normal',
    'size': 8
}

# Size in bytes
storage = {
    "TinkerGraph": {
        "jackson-databind": {"Program Size": 1510177, "Uncompressed": 230708501, "Compressed (tar.lz)": 35882737},
        "gremlin-driver": {"Program Size": 247808, "Uncompressed": 44098404, "Compressed (tar.lz)": 6692506},
        "neo4j": {"Program Size": 141312, "Uncompressed": 14532096, "Compressed (tar.lz)": 2230272}
    },
    "OverflowDB": {
        "jackson-databind": {"Program Size": 1510177, "Uncompressed": 47513600, "Compressed (tar.lz)": 24806855},
        "gremlin-driver": {"Program Size": 247808, "Uncompressed": 9121792, "Compressed (tar.lz)": 4615893},
        "neo4j": {"Program Size": 141312, "Uncompressed": 3035136, "Compressed (tar.lz)": 1661492}
    }
}

# Check memory with sudo pmap -d 668466|tail -n 1

remote_db = {
    # Initial
    # Storage: 195628
    # KAFKA | REST | GSQL | Zookeeper | GPE
    # (409 + 404 + 162) + 125 + 102 + 81.368 + 70.648
    "TigerGraph": {
        # KAFKA | GSQL | GSE | Zookeeper | GPE | RESTPP
        "jackson-databind": {"Initial Storage": 195632 * 1024, "Storage": 403456 * 1024,
                             "Initial Memory": ((409 + 404 + 162) + 125 + 102 + 81.368 + 70.648) * 1024 ** 2,
                             "Memory": ((1225 + 420 + 304) + 1145 + 772 + 335 + 190 + 168) * 1024 ** 2},
        # GSQL | KAFKA | GSE | GPE | RESTPP | Zookeeper
        "gremlin-driver": {"Initial Storage": 195632 * 1024, "Storage": 258768 * 1024,
                           "Initial Memory": ((409 + 404 + 162) + 125 + 102 + 81.368 + 70.648) * 1024 ** 2,
                           "Memory": (1462 + (998 + 421 + 301) + 732 + 121 + 169 + 349) * 1024 ** 2},
        # GSQL | KAFKA | GSE | Zookeeper | RESTPP | GPE
        "neo4j": {"Initial Storage": 195632 * 1024, "Storage": 236112 * 1024,
                  "Initial Memory": ((409 + 404 + 162) + 125 + 102 + 81.368 + 70.648) * 1024 ** 2,
                  "Memory": (1383 + (982 + 426 + 278) + 697 + 195 + 174 + 107) * 1024 ** 2}
    },
    # Neo4j base storage size = 513740
    # PID: 578724
    # Base memory: 2054820K
    "Neo4j": {
        "jackson-databind": {
            "Initial Storage": 513740 * 1024,
            "Storage": 1619824 * 1024,
            "Initial Memory": 2054820 * 1024,
            "Memory": 5851804 * 1024
        },
        "gremlin-driver": {
            "Initial Storage": 513740 * 1024,
            "Storage": 564796 * 1024,
            "Initial Memory": 2054820 * 1024,
            "Memory": 3592587336
        },
        "neo4j": {
            "Initial Storage": 513740 * 1024,
            "Storage": 530456 * 1024,
            "Initial Memory": 2054820 * 1024,
            "Memory": 2154218136
        },
    },
    # For neptune, the initial and storage are swapped since the only metric is free local storage
    "Neptune": {
        "jackson-databind": {"Initial Storage": 8735408128, "Storage": 155460653056 - 155393799360,
                             "Memory": 19925262336 - 13653.88671875 * (1024 ** 2)},
        "gremlin-driver": {"Initial Storage": 8735408128, "Storage": 155471020032 - 155461988352,
                           "Memory": 19693785088 - 14311255754},
        "neo4j": {"Initial Storage": 8735408128, "Storage": 155481133056 - 155476795392,
                  "Memory": 19680649216 - 14407446528},
    },
}

class Benchmark:
    def __init__(self, plume_version, file_name, phase, database, compiling_and_unpacking, soot, program_structure,
                 base_cpg, db_read, db_write, df_pass, cache_hits, cache_misses, connect_deserialize,
                 disconnect_serialize):
        self.plume_version = plume_version
        self.file_name = file_name
        self.phase = phase
        self.database = database
        self.compiling_and_unpacking = compiling_and_unpacking
        self.soot = soot
        self.program_structure = program_structure
        self.base_cpg = base_cpg
        self.db_read = db_read
        self.db_write = db_write
        self.df_pass = df_pass
        self.cache_hits = cache_hits
        self.cache_misses = cache_misses
        self.connect_deserialize = connect_deserialize
        self.disconnect_serialize = disconnect_serialize

    def total_time(self):
        return self.compiling_and_unpacking + self.soot + self.program_structure + self.base_cpg + self.df_pass

    def __str__(self):
        return "Benchmark({}, {}, {})".format(self.file_name, self.database, self.total_time())

    def __repr__(self):
        return str(self)

class DataFlowResult:
    def __init__(self, commit, file_name, q1_time, q2_time, q3_time):
        self.commit = commit
        self.file_name = file_name
        self.q1_time = q1_time
        self.q2_time = q2_time
        self.q3_time = q3_time

    def __str__(self):
        return "DataFlowResult({}, {}, {})".format(self.commit, self.file_name, [self.q1_time, self.q2_time, self.q3_time])

    def __repr__(self):
        return str(self)

def avg(rs: List[Benchmark], phase: str):
    return np.mean([r.total_time() for r in rs if r.phase == phase])

def stdd(rs: List[Benchmark], phase: str):
    return np.std([r.total_time() for r in rs if r.phase == phase])

def str_to_ns(ns, unit='s'):
    nanos = np.timedelta64(ns, 'ns')
    unit_time = np.timedelta64(1, unit)
    return nanos / unit_time

intervals = (
    ('h', 3.6e+6),
    ('m', 60 * 1000),
    ('s', 1000),
    ('ms', 1),
)

storage_units = (
    ('Gb', 1024 ** 3),
    ('Mb', 1024 ** 2),
    ('kb', 1024),
    ('b', 1),
)

def display_time(ms, granularity=2):
    result = []

    for name, count in intervals:
        value = ms // count
        if value:
            ms -= value * count
            if value == 1:
                name = name.rstrip('s')
            result.append("{:.0f}{}".format(value, name))
    return ''.join(result[:granularity])

def display_storage(ms, granularity=2):
    result = []

    for name, count in storage_units:
        value = ms // count
        if value:
            ms -= value * count
            if value == 1:
                name = name.rstrip('s')
            result.append("{:.0f}{}".format(value, name))
    return ''.join(result[:granularity])

def ns_to_s(ns):
    return ns * 1e-9

def repo_commit_deltas():
    fig, (ax1, ax2, ax3) = plt.subplots(3, 1, sharex=True, sharey=True)
    fig.suptitle("Changes Since Last Commit Per Commit")
    ax1.set_title("Class Changes Per Project")
    ax2.set_title("Method Changes Per Project")
    ax3.set_title("Field Changes Per Project")

    x = [0, 1, 2, 3]
    classes = [
        [7, 8, 9, 13],  # Jackson
        [18, 32, 120, 34],  # Gremlin
        [3, 4, 11, 12]  # Neo4j
    ]
    methods = [
        [3, 1, 1, 10],  # Jackson
        [139, 29, 8, 11],  # Gremlin
        [4, 4, 22, 8],  # Neo4j
    ]
    fields = [
        [46, 49, 70, 98],  # Jackson
        [123, 191, 191, 197],  # Gremlin
        [13, 21, 108, 121],  # Neo4j
    ]
    plt.xticks(x, ["Commit 1", "Commit 2", "Commit 3", "Commit 4"])
    markers = ['o', 'o', 'o']
    projects = {'Jackson Databind': 'b', 'Gremlin Driver': 'g', 'Neo4j Community': 'r'}

    i = 0
    for p, col in projects.items():
        ax1.plot(x, classes[i], color=col, marker=markers[0])
        ax2.plot(x, methods[i], color=col, marker=markers[1])
        ax3.plot(x, fields[i], color=col, marker=markers[2])
        i += 1

    custom_lines = [Line2D([0], [0], color=projects['Jackson Databind'], lw=4, label='Jackson Databind'),
                    Line2D([0], [0], color=projects['Gremlin Driver'],
                           lw=4, label='Gremlin Driver'),
                    Line2D([0], [0], color=projects['Neo4j Community'], lw=4, label='Neo4j Community')]
    # plt.legend(handles=custom_lines)
    fig.set_size_inches(9, 6)
    fig.text(0.5, 0.1, 'Commit', ha='center')
    fig.text(0.04, 0.5, 'Number of Changes Since Last Commit',
             va='center', rotation='vertical')
    plt.legend(loc="lower center", ncol=3, bbox_to_anchor=(-.05, -.8,
               1.1, .01), mode="expand", handles=custom_lines)
    fig.subplots_adjust(bottom=0.18)
    fig.savefig("./results/project_deltas.pdf")

def avg_db_build_update(rs: List[Benchmark]):
    dbs = set([r.database for r in rs])
    fs = set([r.file_name for r in rs])

    cols = {
        'TinkerGraph': 'tab:blue',
        'OverflowDB': 'tab:green',
        'TigerGraph': 'tab:orange',
        'Neo4j': 'tab:purple',
        'Neptune': 'tab:olive'
    }

    # Map (File, Database) -> AVG
    avg_build = {}
    avg_update = {}
    avg_disupdt = {}
    for db in dbs:
        for f in fs:
            avg_build[(f, db)] = np.mean(
                [str_to_ns(r.total_time()) for r in rs if
                 r.file_name == f and r.database == db and ("BUILD" in r.phase or "INIT" in r.phase)])
            avg_update[(f, db)] = np.mean(
                [str_to_ns(r.total_time()) for r in rs if
                 r.file_name == f and r.database == db and "UPDATE" in r.phase])
            avg_disupdt[(f, db)] = np.mean(
                [str_to_ns(r.total_time()) for r in rs if
                 r.file_name == f and r.database == db and "DISCUPT" in r.phase])
    fig, ax = plt.subplots()
    ax.set_title("Average Operation Time Per Database")
    ax.set_xlabel("GitHub Repository")
    ax.set_ylabel("Time Elapsed (Logarithmic)")
    plt.yscale('log')
    plt.yticks([])
    plt.xticks([0.345, 1.345, 2.345],
               ['jackson-databind', 'gremlin-driver', 'community/neo4j'])

    def plot_as_bars(xs: dict, hatch, offset_text=0):
        data = {}
        for ((f, db), avg) in xs.items():
            if db not in data.keys():
                data[db] = [0, 0, 0]
            if "jackson" in f:
                data[db][0] = avg
            elif "gremlin" in f:
                data[db][1] = avg
            elif "neo4j" in f:
                data[db][2] = avg

        x = np.arange(3)
        for i, (db, avg) in enumerate(data.items()):
            inc = 1.0 / len(data.items()) - 0.02
            ax.bar(x + i * inc, avg, width=inc - 0.03, label=db, edgecolor='w',
                   hatch=hatch, color=cols[db])
            for j, v in enumerate(avg):
                ax.text(j + i * inc - 0.15 + offset_text, v + 1 *
                        gauss(0, 1), display_time(v * 1000), font=lbl_font)

    total = {}
    for k, v in avg_update.items():
        total[k] = v + avg_disupdt[k]

    plot_as_bars(avg_build, "\\")
    plot_as_bars(avg_disupdt, ".", 0.15)
    plot_as_bars(avg_update, '//')

    legend_elements = [
        Patch(facecolor='white', edgecolor='k', hatch='//',
              label='Online Update'),
        Patch(facecolor='white', edgecolor='k', hatch='.',
              label='Disconnected Update'),
        Patch(facecolor='white', edgecolor='k', hatch='\\',
              label='Full Build')]

    for db, c in cols.items():
        legend_elements.append(Line2D([0], [0], color=c, label=db, lw=4))
    ymin, ymax = ax.get_ylim()
    plt.ylim([ymin, ymax + ymax * 0.10])
    fig.set_size_inches(10, 6)
    plt.legend(handles=legend_elements, loc=[0.125, -0.25], ncol=4)
    plt.tight_layout()

    fig.savefig("./results/db_avg_operation_stats.pdf")

def program_sizes():
    fig, ax = plt.subplots()
    ax.set_title("Initial Commit Code Statistics")
    ax.set_xlabel("GitHub Repository")
    ax.set_ylabel("Count")
    cols = {
        'Classes': 'tab:orange',
        'Methods': 'tab:purple',
        'Fields': 'tab:blue'
    }

    def plot_program_sizes(data, bottom):
        x = np.arange(3)
        inc = 1.0 / len(data) - 0.03
        if bottom is None:
            for i, (l, c) in enumerate(cols.items()):
                ax.bar(x + i * inc, data[i], width=0.3,
                       label=l,  color=c, edgecolor='k')
        else:
            for i, (l, c) in enumerate(cols.items()):
                ax.bar(x + i * inc, data[i], width=0.3,
                       label=l, bottom=bottom[i], color=c, hatch='//')

        # for k in range(len(data)):
        #     if bottom is None:
        #         for i, v in enumerate(data[k]):
        #             ax.text(i + i * inc, v + 100, str(v))
        #     else:
        #         for i, v in enumerate(data[k]):
        #             ax.text(i + i * inc, v + 100 + bottom[k][i], str(v))

    app_data = [
        # FasterXML/jackson-databind | apache/tinkerpop/gremlin-driver | neo4j/neo4j
        [701, 119, 40],  # Application Classes
        [7839, 1020, 491],  # Application Methods
        [2060, 519, 220]  # Application Fields
    ]
    lib_data = [
        [161, 133, 140],  # Library Classes
        [18106 - 7839, 9445 - 1020, 2680 - 491],  # Library Methods
        [2813, 2150, 363]  # Library Fields
    ]

    plot_program_sizes(app_data, None)
    plot_program_sizes(lib_data, app_data)
    plt.xticks([0.3, 1.3, 2.3],
               ['jackson-databind', 'gremlin-driver', 'community/neo4j'])

    legend_elements = []
    for lb, c in cols.items():
        legend_elements.append(Line2D([0], [0], color=c, label=lb, lw=4))
    legend_elements.extend([Patch(facecolor='white', edgecolor='k', hatch='//',
                                  label='External'),
                           Patch(facecolor='white', edgecolor='k', hatch='',
                                 label='Application')])

    plt.legend(handles=legend_elements)
    plt.tight_layout()

    fig.savefig("./results/jar_code_stats.pdf")

def graph_sizes():
    fig, ax = plt.subplots()
    ax.set_title("Initial Commit Graph Statistics")
    ax.set_xlabel("GitHub Repository")
    ax.set_ylabel("Count")
    data = [
        # FasterXML/jackson-databind | apache/tinkerpop/gremlin-driver | neo4j/neo4j
        [555867, 132543, 42907],  # Vertices
        [3017313, 504138, 172136],  # Edges
    ]
    x = np.arange(3)
    vs = [d for d in data[0]]
    es = [d for d in data[1]]
    ax.bar(x + 0.00, vs, width=0.25, label="Vertices")
    ax.bar(x + 0.25, es, width=0.25, label="Edges")
    for i, v in enumerate(vs):
        ax.text(i - 0.15, v + 100000, str(v))
    for i, v in enumerate(es):
        ax.text(i + 0.10, v + 100000, str(v))
    plt.xticks([0.125, 1.125, 2.125],
               ['jackson-databind', 'gremlin-driver', 'community/neo4j'])
    plt.legend()
    plt.ylim([0, max(es) + 300000])
    fig.savefig("./results/jar_graph_stats.pdf")

def update_build_perf(db: str, ax, rs: List[Benchmark]):
    ax.set_title(db)
    init, init_std = avg(rs, "INITIAL"), stdd(rs, "INITIAL")
    b0, db0 = avg(rs, "BUILD0"), stdd(rs, "BUILD0")
    b1, db1 = avg(rs, "BUILD1"), stdd(rs, "BUILD1")
    b2, db2 = avg(rs, "BUILD2"), stdd(rs, "BUILD2")
    b3, db3 = avg(rs, "BUILD3"), stdd(rs, "BUILD3")
    u0, du0 = avg(rs, "UPDATE0"), stdd(rs, "UPDATE0")
    u1, du1 = avg(rs, "UPDATE1"), stdd(rs, "UPDATE1")
    u2, du2 = avg(rs, "UPDATE2"), stdd(rs, "UPDATE2")
    u3, du3 = avg(rs, "UPDATE3"), stdd(rs, "UPDATE3")
    d0, dd0 = avg(rs, "DISCUPT0"), stdd(rs, "DISCUPT0")
    d1, dd1 = avg(rs, "DISCUPT1"), stdd(rs, "DISCUPT1")
    d2, dd2 = avg(rs, "DISCUPT2"), stdd(rs, "DISCUPT2")
    d3, dd3 = avg(rs, "DISCUPT3"), stdd(rs, "DISCUPT3")

    bs = [ns_to_s(t) for t in [b0, b1, b2, b3]]
    us = [ns_to_s(t) for t in [u0, u1, u2, u3]]
    ds = [ns_to_s(t) for t in [d0, d1, d2, d3]]
    ax.errorbar([0], [ns_to_s(t) for t in [init]], [ns_to_s(t) for t in [init_std]], color='g', marker='o',
                linestyle='None', label="Initial Build")
    ax.errorbar([1, 2, 3, 4], bs, [ns_to_s(t) for t in [db0, db1, db2, db3]],
                color='r', marker='x', linestyle='None', label="Full Build")
    ax.errorbar([1, 2, 3, 4], us, [ns_to_s(t) for t in [du0, du1, du2, du3]],
                color='b', marker='x', linestyle='None', label="Online Update")
    ax.errorbar([1, 2, 3, 4], ds, [ns_to_s(t) for t in [dd0, dd1, dd2, dd3]],
                color='m', marker='x', linestyle='None', label="Disconnected Update")
    # Add text
    ax.text(0.05, ns_to_s(init), display_time(ns_to_s(init) * 1000), color="g")
    for i, v in enumerate([ns_to_s(t) for t in [b0, b1, b2, b3]]):
        ax.text(i + 1.05, v, display_time(v * 1000), color="r")
    for i, v in enumerate([ns_to_s(t) for t in [u0, u1, u2, u3]]):
        ax.text(i + 1.05, v, display_time(v * 1000), color="b")
    for i, v in enumerate([ns_to_s(t) for t in [d0, d1, d2, d3]]):
        ax.text(i + .55, v, display_time(v * 1000), color="m")

def plot_build_updates(f):
    fig, ax = plt.subplots(nrows=len(dbs), ncols=1, sharex=True, squeeze=False, figsize=(9, 2.5 * len(dbs)),
                           tight_layout=False)
    i = 0
    for ((fname, db), r) in results_per_db_jar.items():
        if f == fname:
            update_build_perf(db, ax[i, 0], r)
            i += 1
    plt.xticks([0, 1, 2, 3, 4], ["Commit 0", "Commit 1",
               "Commit 2", "Commit 3", "Commit 4"])
    fig.suptitle(f, y=.925)
    fig.text(0.04, 0.5, 'Time Elapsed (s)', va='center', rotation='vertical')
    plt.legend(loc="lower center", ncol=4,
               bbox_to_anchor=(-.05, -0.45, 1.1, .102), mode="expand")
    fig.savefig("./results/build_updates_{}.pdf".format(f.split("/")[-1]))

def avg_dataflow_query(rs: List[DataFlowResult]):
    import re

    fig, axes = plt.subplots(3, 1, sharex=True, sharey=True)
    fig.suptitle("Data-Flow Query Response Statistics")

    fs = ['jackson-databind', 'gremlin-driver', 'community/neo4j']

    cols = {
        'String Parameter to External Call': 'tab:orange',
        'String Parameter to Log or Print Call': 'tab:purple',
        'Simple Constant Detection': 'tab:blue'
    }

    iss = [1, 2, 3, 4, 5]
    split_data = {}
    for i in iss:
        split_data[i] = {}
    for i in iss:
        for f in fs:
            split_data[i][f] = { 'q1': [], 'q2': [], 'q3': [] }

    for r in rs:
        i = int(re.search(r'\d+', r.file_name).group())
        if "g" in r.file_name:
            r.commit
            split_data[i]["gremlin-driver"]['q1'].append(r.q1_time)
            split_data[i]["gremlin-driver"]['q2'].append(r.q2_time)
            split_data[i]["gremlin-driver"]['q3'].append(r.q3_time)
        elif "n" in r.file_name:
            split_data[i]["community/neo4j"]['q1'].append(r.q1_time)
            split_data[i]["community/neo4j"]['q2'].append(r.q2_time)
            split_data[i]["community/neo4j"]['q3'].append(r.q3_time)
        elif "j" in r.file_name:
            split_data[i]["jackson-databind"]['q1'].append(r.q1_time)
            split_data[i]["jackson-databind"]['q2'].append(r.q2_time)
            split_data[i]["jackson-databind"]['q3'].append(r.q3_time)

    for i, fs in split_data.items():
        for f, qs in fs.items():
            for q_name, q_list in qs.items():
                qs[q_name] = (np.mean(q_list), np.std(q_list))

    xs = [1, 2, 3, 4, 5]

    for f_num, f in enumerate(fs):
        ax = axes[f_num]
        ax.set_title(f)
        ax.set_yscale('log')

        init_x = []
        q1_init_b_y, q2_init_b_y, q3_init_b_y = [], [], []
        other_x = []
        q1_build_y, q2_build_y, q3_build_y = [], [], []
        for x in xs:
            if x == 1:
                init_x.append(x)
                q1_init_b_y.append(split_data[x][f]['q1'])
                q2_init_b_y.append(split_data[x][f]['q2'])
                q3_init_b_y.append(split_data[x][f]['q3'])
            else:
                other_x.append(x)
                q1_build_y.append(split_data[x][f]['q1'])
                q2_build_y.append(split_data[x][f]['q2'])
                q3_build_y.append(split_data[x][f]['q3'])

        ax.bar(list(map(lambda x: x + -0.25, init_x)), list(map(lambda x: x[0], q1_init_b_y)), capsize=2, width = 0.25, yerr=list(map(lambda x: x[1], q1_init_b_y)), color=list(cols.values())[0])
        ax.bar(list(map(lambda x: x + 0.00, init_x)), list(map(lambda x: x[0], q2_init_b_y)), capsize=2, width = 0.25, yerr=list(map(lambda x: x[1], q2_init_b_y)), color=list(cols.values())[1])
        ax.bar(list(map(lambda x: x + 0.25, init_x)), list(map(lambda x: x[0], q3_init_b_y)), capsize=2, width = 0.25, yerr=list(map(lambda x: x[1], q3_init_b_y)), color=list(cols.values())[2])

        ax.bar(list(map(lambda x: x + -0.25, other_x)), list(map(lambda x: x[0], q1_build_y)), capsize=2, width = 0.25, yerr=list(map(lambda x: x[1], q1_build_y)), color=list(cols.values())[0])
        ax.bar(list(map(lambda x: x + 0.00, other_x)), list(map(lambda x: x[0], q2_build_y)), capsize=2, width = 0.25, yerr=list(map(lambda x: x[1], q2_build_y)), color=list(cols.values())[1])
        ax.bar(list(map(lambda x: x + 0.25, other_x)), list(map(lambda x: x[0], q3_build_y)), capsize=2, width = 0.25, yerr=list(map(lambda x: x[1], q3_build_y)), color=list(cols.values())[2])

        if f_num < 1:
            y_adjust = 2.5e11
            init_mul = 1.15
        elif f_num < 2:
            y_adjust = -0.15e9
            init_mul = 3.25
        else:
            y_adjust = 1e9
            init_mul = -1

        if f_num < 2:
            mid_adjust = 0
        else:
            mid_adjust = 1.5e10

        for i, v in enumerate(list(map(lambda x: x[0], q1_init_b_y))):
            ax.text(i + 0.7, v - y_adjust * init_mul, display_time(ns_to_s(v) * 1000))
        for i, v in enumerate(list(map(lambda x: x[0], q2_init_b_y))):
            ax.text(i + 1.05, v, display_time(ns_to_s(v) * 1000))
        for i, v in enumerate(list(map(lambda x: x[0], q3_init_b_y))):
            ax.text(i + 1.15, v + 0.5e8, display_time(ns_to_s(v) * 1000))
        for i, v in enumerate(list(map(lambda x: x[0], q1_build_y))):
            ax.text(i + 0.525 + 1, v - y_adjust + mid_adjust, display_time(ns_to_s(v) * 1000))
        for i, v in enumerate(list(map(lambda x: x[0], q2_build_y))):
            ax.text(i + 0.85 + 1, v + 2.7e8, display_time(ns_to_s(v) * 1000))
        for i, v in enumerate(list(map(lambda x: x[0], q3_build_y))):
            ax.text(i + 1.15 + 1, v + 0.5e8, display_time(ns_to_s(v) * 1000))

        # ymin, ymax = ax.get_ylim()
        # ax.set_ylim([ymin * 1.1, ymax * 1.1])
        ax.set_yticks([])
        # ax.set_xlabel("Commit")
        if f_num == 1:
            ax.set_ylabel("Time (Logarithmic)")

    # fig.text(0.5, 0.05, 'Commit', ha='center')
    # fig.text(0.1, 0.5, 'Time (ns)', va='center', rotation='vertical')

    plt.xticks(xs, ["Initial", "Commit 1", "Commit 2", "Commit 3", "Commit 4"])
    legend_elements = []
    for db, c in cols.items():
        legend_elements.append(Line2D([0], [0], color=c, label=db, lw=4))
    fig.set_size_inches(10, 6)
    plt.legend(handles=legend_elements, loc=[0.01, -0.55], ncol=3)
    plt.tight_layout()

    fig.savefig("./results/db_avg_dataflow_stats.pdf")

def plot_cache_results(rs: List[Benchmark]):
    phases = {
        "BUILD": '//',
        "UPDATE": '*',
        "DISCUPT": '.'
    }

    fs = set([x.file_name for x in rs])
    # Plot per phase
    fig, ax = plt.subplots()
    ax.set_title("Cache Metrics Per Project")
    ax.set_xlabel("GitHub Repository")
    ax.set_ylabel("Cache Operation Count (%)")
    i = 0
    xs = np.arange(3)
    for j, (p, hatch) in enumerate(phases.items()):
        avg_cache_hits = []
        avg_cache_misses = []
        for f in fs:
            avg_cache_hits.append(np.average(
                [r.cache_hits for r in rs if r.file_name == f and p in r.phase]))
            avg_cache_misses.append(np.average(
                [r.cache_misses for r in rs if r.file_name == f and p in r.phase]))

        perc_hits = np.array([])
        perc_misses = np.array([])
        for a in range(len(fs)):
            perc_hits = np.append(
                perc_hits, avg_cache_hits[a] / (avg_cache_hits[a] + avg_cache_misses[a]))
            perc_misses = np.append(
                perc_misses, avg_cache_misses[a] / (avg_cache_hits[a] + avg_cache_misses[a]))

        perc_hits = np.multiply(perc_hits, 100)
        perc_misses = np.multiply(perc_misses, 100)
        for x in xs:
            ax.bar(x + 0.00 + j * 0.3, perc_hits[x], width=0.45/len(xs), color='tab:blue', hatch=hatch, edgecolor='w')
            ax.bar(x + 0.15 + j * 0.3, perc_misses[x], width=0.45/len(xs), color='tab:orange', hatch=hatch, edgecolor='w')
        for x, v in enumerate(perc_hits):
            ax.text(x + 0.00 + j * 0.3 - 0.08, v, str("{:.2f}%".format(v)))
        for x, v in enumerate(perc_misses):
            ax.text(x + 0.15 + j * 0.3 - 0.08, v, str("{:.2f}%".format(v)))
        i += 1

    fmap = {
        'apache/tinkerpop/gremlin-driver':'gremlin-driver',
        'neo4j/neo4j': 'community/neo4j',
        'FasterXML/jackson-databind': 'jackson-databind'
    }
    xlabs = []
    for f in fs:
        xlabs.append(fmap[f])
    plt.xticks([0.45, 1.45, 2.45], xlabs)
    custom_lines = [
        Line2D([0], [0], color='tab:blue', lw=4, label='Cache Hits'),
        Line2D([0], [0], color='tab:orange', lw=4, label='Cache Misses'),
        Patch(facecolor='white', edgecolor='k', hatch='*',
              label='Online Update'),
        Patch(facecolor='white', edgecolor='k', hatch='.',
              label='Disconnected Update'),
        Patch(facecolor='white', edgecolor='k', hatch='//',
              label='Full Build')
    ]
    fig.set_size_inches(9, 6)
    plt.legend(handles=custom_lines, loc=[-0.035, -0.2], ncol=5)
    plt.tight_layout()
    fig.savefig("./results/cache_metrics.pdf")

def plot_inmem_storage():
    fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True, squeeze=False, figsize=(9, 2.5 * 2),
                             tight_layout=False)
    fig.suptitle("In-Memory Database Storage Footprint")
    inmemdbs = ["TinkerGraph", "OverflowDB"]
    progs = ["jackson-databind", "gremlin-driver", "neo4j"]
    data = []
    for inmem in inmemdbs:
        inmem_storage = storage[inmem]
        p_data = []
        ucom_data = []
        com_data = []
        for p in progs:
            p_data.append(inmem_storage[p]["Program Size"])
            ucom_data.append(inmem_storage[p]["Uncompressed"])
            com_data.append(inmem_storage[p]["Compressed (tar.lz)"])
        data.append([p_data, ucom_data, com_data])

    x = np.arange(3)

    def plot_storage(ax, data, title):
        ax.set_title(title)
        ax.bar(x + 0.00, data[0], width=0.25, label="JAR Size")
        ax.bar(x + 0.25, data[1], width=0.25, label="Uncompressed CPG")
        ax.bar(x + 0.50, data[2], width=0.25, label="Compressed CPG (tar.lz)")
        ax.set_yscale('log')
        ymin, ymax = ax.get_ylim()
        ax.set_ylim([ymin, ymax * 1.5])
        ax.set_yticks([])
        for i, v in enumerate(data[0]):
            ax.text(i - 0.15, v + 10000, display_storage(v))
        for i, v in enumerate(data[1]):
            ax.text(i + 0.10, v + 10000, display_storage(v))
        for i, v in enumerate(data[2]):
            ax.text(i + 0.35, v + 10000, display_storage(v))

    fig.text(0.04, 0.5, 'Bytes (logarithmic)',
             va='center', rotation='vertical')
    fig.text(0.5, 0.1, 'GitHub Repository', ha='center')
    fig.subplots_adjust(bottom=0.18)
    for j, d in enumerate(inmemdbs):
        plot_storage(axes[j, 0], data[j], d)
    plt.legend(loc="lower center", ncol=3,
               bbox_to_anchor=(0, -.5, 1, .01), mode="expand")
    fmap = {
        'gremlin-driver':'gremlin-driver',
        'neo4j': 'community/neo4j',
        'jackson-databind': 'jackson-databind'
    }
    xlabs = []
    for f in progs:
        xlabs.append(fmap[f])
    plt.xticks([0.25, 1.25, 2.25], xlabs)
    fig.savefig("./results/inmem_storage_footprint.pdf")

def plot_remote_storage():
    fig, axes = plt.subplots(nrows=3, ncols=1, sharex=True, squeeze=False, figsize=(9, 2.5 * 3),
                             tight_layout=False)
    fig.suptitle("Remote Database Storage Footprint")
    remote_dbs = ["TigerGraph", "Neo4j", "Neptune"]
    progs = ["jackson-databind", "gremlin-driver", "neo4j"]
    data = []
    for remote in remote_dbs:
        remote_storage = remote_db[remote]
        initial = []
        used = []
        reserved = []
        for p in progs:
            if remote == "Neptune":
                used.append(remote_storage[p]["Storage"])
                reserved.append(
                    remote_storage[p]["Initial Storage"] - remote_storage[p]["Storage"])
            else:
                initial.append(remote_storage[p]["Initial Storage"])
                used.append(remote_storage[p]["Storage"] -
                            remote_storage[p]["Initial Storage"])
        data.append([initial, used, reserved])

    x = np.arange(3)

    def plot_storage(ax, data, title):
        ax.set_title(title)
        if title == "Neptune":
            for i, v in enumerate(data[2]):
                ax.text(i + 0.15, v, display_storage(v), color="tab:green")
            for i, v in enumerate(data[1]):
                ax.text(i + 0.15, v, display_storage(v), color="tab:orange")
        else:
            for i, v in enumerate(data[0]):
                ax.text(i + 0.15, v, display_storage(v), color="tab:blue")
            for i, v in enumerate(data[1]):
                ax.text(i - 0.15, v + data[0][i] + 10000,
                        display_storage(v), color="tab:orange")
        # ax.set_yscale('log')
        ax.set_yticks([])
        if title == "Neptune":
            ax.bar(x, [0, 0, 0], width=0.25,
                   label="Initial Size", color="tab:blue")
            ax.bar(x, data[1], width=0.25,
                   label="Used Size", color="tab:orange")
            ax.bar(x, data[2], width=0.25, label="Reserved Size",
                   color="tab:green", bottom=data[1])
        else:
            ax.bar(x, data[0], width=0.25,
                   label="Initial size", color="tab:blue")
            ax.bar(x, data[1], width=0.25, label="Used Size",
                   color="tab:orange", bottom=data[0])
            ax.bar(x, [0, 0, 0], width=0.25,
                   label="Reserved Size", color="tab:green")

        ymin, ymax = ax.get_ylim()
        ax.set_ylim([ymin, ymax * 1.25])

    fig.text(0.05, 0.5, 'Bytes', va='center', rotation='vertical')
    fig.text(0.51, 0.1, 'GitHub Repository', ha='center')
    fig.subplots_adjust(bottom=0.2)
    for j, d in enumerate(remote_dbs):
        plot_storage(axes[j, 0], data[j], d)
    plt.legend(loc="lower center", ncol=3, bbox_to_anchor=(
        0, -0.9, 1, .01), mode="expand")
    fmap = {
        'gremlin-driver':'gremlin-driver',
        'neo4j': 'community/neo4j',
        'jackson-databind': 'jackson-databind'
    }
    xlabs = []
    for f in progs:
        xlabs.append(fmap[f])
    plt.xticks(x, xlabs)
    fig.savefig("./results/remote_storage_footprint.pdf")

def plot_remote_memory():
    fig, ax = plt.subplots()
    ax.set_title("Remote Database Maximum Memory Footprint")
    ax.set_xlabel("GitHub Repository")
    ax.set_ylabel("Bytes")
    cols = {
        'TigerGraph': 'tab:orange',
        'Neo4j': 'tab:purple',
        'Neptune': 'tab:olive'
    }
    progs = ["jackson-databind", "gremlin-driver", "neo4j"]

    data = []
    for remote in cols.keys():
        remote_storage = remote_db[remote]
        initial = []
        for p in progs:
            initial.append(remote_storage[p]["Memory"])
        data.append([initial])

    x = np.arange(3)
    for i, (db, col) in enumerate(cols.items()):
        for j, v in enumerate(data[i][0]):
            ax.text(j + i * 0.25 - 0.2, v, display_storage(v))
        ax.bar(x + i * 0.25, data[i][0], width=0.25, label=db, color=col)

    fmap = {
        'gremlin-driver':'gremlin-driver',
        'neo4j': 'community/neo4j',
        'jackson-databind': 'jackson-databind'
    }
    xlabs = []
    for f in progs:
        xlabs.append(fmap[f])
    plt.xticks([0.25, 1.25, 2.25], xlabs)

    plt.legend(loc=[0.15, -0.225], ncol=3)
    plt.tight_layout()
    fig.savefig("./results/remote_memory_footprint.pdf")

tracer_files = {
    "OverflowDB": {
        "jackson-databind": "Memory_Maxes_OverflowDbDriver_jackson-databind.csv",
        "gremlin-driver": "Memory_Maxes_OverflowDbDriver_gremlin-driver.csv",
        "neo4j": "Memory_Maxes_OverflowDbDriver_neo4j.csv"
    },
    "TinkerGraph": {
        "jackson-databind": "Memory_Maxes_TinkerGraphDriver_jackson-databind.csv",
        "gremlin-driver": "Memory_Maxes_TinkerGraphDriver_gremlin-driver.csv",
        "neo4j": "Memory_Maxes_TinkerGraphDriver_neo4j.csv"
    },
    "Neo4j": {
        "jackson-databind": "Memory_Maxes_Neo4jDriver_jackson-databind.csv",
        "gremlin-driver": "Memory_Maxes_Neo4jDriver_gremlin-driver.csv",
        "neo4j": "Memory_Maxes_Neo4jDriver_neo4j.csv"
    },
    "Neptune": {
        "jackson-databind": "Memory_Maxes_NeptuneDriver_jackson-databind.csv",
        "gremlin-driver": "Memory_Maxes_NeptuneDriver_gremlin-driver.csv",
        "neo4j": "Memory_Maxes_NeptuneDriver_neo4j.csv"
    },
    "TigerGraph": {
        "jackson-databind": "Memory_Maxes_TigerGraphDriver_jackson-databind.csv",
        "gremlin-driver": "Memory_Maxes_TigerGraphDriver_gremlin-driver.csv",
        "neo4j": "Memory_Maxes_TigerGraphDriver_neo4j.csv"
    }
}

def plot_process_memory():
    fig, ax = plt.subplots()
    ax.set_title("Process Memory Max Footprint")
    ax.set_xlabel("GitHub Repository")
    ax.set_ylabel("Bytes")
    plt.xticks([0.345, 1.345, 2.345],
               ['jackson-databind', 'gremlin-driver', 'community/neo4j'])

    cols = {
        'TinkerGraph': 'tab:blue',
        'OverflowDB': 'tab:green',
        'TigerGraph': 'tab:orange',
        'Neo4j': 'tab:purple',
        'Neptune': 'tab:olive'
    }

    def plot_memory(db, x, y, e, offset=0, f_num=0):
        ax.bar(x + offset, y, yerr=e, width=inc,
               ecolor='tab:pink', color=cols[db])
        for i, v in enumerate(y):
            y_offset = 2.5e8
            if f_num % 2 == 0:
                y_offset *= -1
            ax.text(i + offset - 0.1, v + y_offset, display_storage(v))

    def extract_mem_use(trace_file):
        with open('./results/{}'.format(trace_file)) as csv_file:
            csv_reader = csv.DictReader(csv_file, delimiter=',')
            heap_entries = []
            use_entries = []
            for row in csv_reader:
                # heap_entries.append(int(''.join(re.findall('[0-9]+', str(row["Size [B]"])))))
                use_entries.append(
                    int(''.join(re.findall('[0-9]+', str(row["Used [B]"])))))
        return (heap_entries, use_entries)

    j = 0
    inc = 1.0 / len(tracer_files.items()) - 0.025
    offset = 0
    for k, (d, f) in enumerate(tracer_files.items()):
        _, use1 = extract_mem_use(f["jackson-databind"])
        _, use2 = extract_mem_use(f["gremlin-driver"])
        _, use3 = extract_mem_use(f["neo4j"])
        data = [np.average(use1), np.average(use2), np.average(use3)]
        dev = [np.std(use1), np.std(use2), np.std(use3)]
        plot_memory(d, np.arange(3), data, dev, offset, k)
        offset += inc

        j += 1
    legend_elements = []

    for db, c in cols.items():
        legend_elements.append(Line2D([0], [0], color=c, label=db, lw=4))
    fig.set_size_inches(9, 6)
    plt.legend(handles=legend_elements, loc=[0.08, -0.2], ncol=5)
    plt.tight_layout()
    fig.savefig("./results/process_memory_footprint.pdf")

with open('./results/aws_results.csv') as csv_file:
    csv_reader = csv.DictReader(csv_file, delimiter=',')
    results = []
    for row in csv_reader:
        results.append(Benchmark(
            plume_version=str(row["PLUME_VERSION"]),
            file_name=str(row["FILE_NAME"]),
            phase=str(row["PHASE"]),
            database=str(row["DATABASE"]),
            compiling_and_unpacking=int(row["COMPILING_AND_UNPACKING"]),
            soot=int(row["SOOT"]),
            program_structure=int(row["PROGRAM_STRUCTURE_BUILDING"]),
            base_cpg=int(row["BASE_CPG_BUILDING"]),
            db_write=int(row["DATABASE_WRITE"]),
            db_read=int(row["DATABASE_READ"]),
            df_pass=int(row["DATA_FLOW_PASS"]),
            cache_hits=int(row["CACHE_HITS"]),
            cache_misses=int(row["CACHE_MISSES"]),
            connect_deserialize=int(row["CONNECT_DESERIALIZE"]),
            disconnect_serialize=int(row["DISCONNECT_SERIALIZE"])
        ))

with open('./results/dataflow_queries.csv') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    df_results = []
    for row in csv_reader:
        df_results.append(DataFlowResult(
            commit=str(row[0]),
            file_name=str(row[1]),
            q1_time=int(row[2]),
            q2_time=int(row[3]),
            q3_time=int(row[4])
        ))

results_per_db_jar = {}
fs = set([x.file_name for x in results])
dbs = set([x.database for x in results])
for r in results:
    # Get (File, Database) -> [Results]
    if (r.file_name, r.database) not in results_per_db_jar.keys():
        results_per_db_jar[(r.file_name, r.database)] = [r]
    else:
        results_per_db_jar[(r.file_name, r.database)].append(r)
# Plot stats of programs
program_sizes()
graph_sizes()
repo_commit_deltas()
# Plot results
for f in fs:
    plot_build_updates(f)
plot_cache_results(results)
avg_db_build_update(results)
avg_dataflow_query(df_results)
plot_inmem_storage()
plot_remote_storage()
plot_remote_memory()
plot_process_memory()
plt.clf()


import uuid

from datetime import datetime
from db.db_mongo import MotorClient
from bson import ObjectId

from services_abc.likes_abc import BaseLikesService
from core.config import api_settings as setting
from services.utils import UtilsService

class MongoLikesService(BaseLikesService, UtilsService):
    """read/write docs to likes collection."""

    def __init__(self, client: MotorClient):
        self.client = client.client_mongodb
        self.db = self.client[setting.mongodb_db]
        self.collection = self.db[setting.mongodb_coll_likes]

    async def id_details(self, like_id: str) -> dict | None:
        """Show a like by its UUID."""
        id = ObjectId(like_id)
        like = await self.collection.find_one({'_id': id})
        return like

    async def read_likes(
        self,
        user_id: uuid.UUID,
        movie_id: uuid.UUID | None = None,
        size: int = setting.default_page_size,
        page: int = 1,
    ) -> dict:
        """Load likes from user_id or movie_id."""
        if movie_id is not None:
            find = {'movie_id': movie_id}
        else:
            find = {'user_id': user_id}
        return await self.read_to_paginate(size, page, find)

    async def add_like(self, user_id: uuid.UUID, movie_id: uuid.UUID,
                       rating: int) -> dict:
        """Add or modified like."""
        new = {
            'user_id': user_id,
            'movie_id': movie_id,
            'like': rating,
            'created': datetime.now(),
            'modified': datetime.now(),
        }
        update = {
            'like': rating,
            'modified': datetime.now(),
        }
        new_like = await self.add_or_update_doc(user_id, movie_id, update, new)
        await self.add_like_to_review(user_id, movie_id, rating)
        return new_like

    async def delete_like(self, user_id: uuid.UUID, movie_id: uuid.UUID) -> dict | None:
        """delete the like."""
        return await self.delete_doc(user_id, movie_id)

    async def info_likes(self, movie_id: uuid.UUID) -> dict:
        """info likes."""
        cnt = await self.collection.count_documents({'movie_id': movie_id})
        avg = 0
        cursor = self.collection.find({'movie_id': movie_id})
        async for doc in cursor:
            avg += doc['like']
        avg = round(avg / cnt, 1)
        return {'count_likes': cnt, 'raiting': avg}


import os
import pandas as pd
import numpy as np
import preprocess as prepro
from joblib import load

class Predict:
    MODEL_PATH = "Model/"

    def __init__(self):
        self.X, self.y = prepro.load_training_data()
        self.clf = self.load_model().fit(self.X, self.y)
        self.gender_type = {
            0: "Femme",
            1: "Homme"
        }

    def load_model(self, path=MODEL_PATH):
        return load(os.path.join(path, "lr.joblib"))

    def predict_gender(self, X_to_pred: dict):
        X_df = pd.DataFrame([X_to_pred])
        X_df = prepro.preprocess(X_df)
        # Get the columns dummies not inquire
        X_df = X_df.reindex(labels=self.X.columns, axis=1).fillna(0)
        prediction = self.clf.predict_proba(X_df)
        text_res = f"L'algorithme prédit que vous êtes un(e) {self.gender_type[np.argmax(prediction)]} avec une " \
                   f"probabilité de {round(max(prediction[0])*100, 2)}% "
        return text_res


#!/usr/bin/env python
from GENIutils import *
from operator import attrgetter

VIDFailureExplained = []
HATFailureExplained = []

def main():
    userInput = raw_input("Collection (1) | Convergence (2): ")

    if(userInput == "1"):
        collectData()

    elif(userInput == "2"):
        getConvergence()

def collectData():
    userInput = raw_input("Test name: ")
    testName = str(userInput)
    cmdList = []

    # Information from credentials file needed for operation
    clientTrafficSource = getConfigInfo("MTP Utilities", "endNodeTrafficSource")
    endNodeNamingSyntax = getConfigInfo("MTP Utilities", "endNodeName")
    codeDirectory = getConfigInfo("MTP Utilities", "localCodeDirectory")
    codeDestination = getConfigInfo("GENI Credentials", "remoteCodeDirectory")
    RSPEC = getConfigInfo("Local Utilities", "RSPEC")
    GENIDict = buildDictonary(RSPEC)
    remoteWorkingDirectory = os.path.join(codeDestination, os.path.basename(codeDirectory)).replace("\\", "/")

    # Create a new directory in which the test results will be stored (MTP_Test is added at the end of the directory name for consistency)
    newDir = "./{}".format(testName)
    os.makedirs(newDir)

    # Support commands for other commands
    enterDirectory = "cd {0} &&".format(remoteWorkingDirectory)

    # Commands to run for a Meshed Tree Switch
    copyLogFile = "{0} cp mtpd_1.log {1} && cp mtpd_2.log {2}"
    createDir =  "{0} mkdir {1}_files"
    moveLogFile = "{0} mv *.log {1}_files/"
    zipFiles =  "{0} zip -r {1}_files.zip {1}_files/"

    # Commands to run for a client node
    createTrafficLog = "sudo python TrafficGenerator.py -a results.pcap"
    copyTrafficLog = "cp trafficResult.txt {1}"

    for currentRemoteNode in GENIDict:
        cmdList[:] = []
        needToCollectData = False

        if(endNodeNamingSyntax not in currentRemoteNode):
            logFileName = "{0}.log".format(currentRemoteNode)
            removeMtpdFiles = "{0} sudo rm mtpd*.log".format(enterDirectory)
            logFileName_tree2 = "{0}_tree2.log".format(currentRemoteNode)
            updated_copyLogFile = copyLogFile.format(enterDirectory, logFileName, logFileName_tree2)
            updated_createDir = createDir.format(enterDirectory, currentRemoteNode)
            updated_moveLogFile = moveLogFile.format(enterDirectory, currentRemoteNode)
            updated_zipFiles = zipFiles.format(enterDirectory, currentRemoteNode)

            cmdList.extend([updated_copyLogFile, removeMtpdFiles, updated_createDir, updated_moveLogFile, updated_zipFiles])
            trafficFileLocation = str(os.path.join(remoteWorkingDirectory, currentRemoteNode + "_files.zip").replace("\\", "/"))
            needToCollectData = True

        elif(endNodeNamingSyntax in currentRemoteNode and currentRemoteNode != clientTrafficSource):
            logFileName = "{0}_traffic.log".format(currentRemoteNode)
            updated_copyTrafficLog = copyTrafficLog.format(enterDirectory, logFileName)
            updated_createDir = createDir.format("", currentRemoteNode)
            updated_moveLogFile = moveLogFile.format("", logFileName, currentRemoteNode)
            updated_zipFiles = zipFiles.format("", currentRemoteNode)

            cmdList.extend([createTrafficLog, updated_copyTrafficLog, updated_createDir, updated_moveLogFile, updated_zipFiles])
            trafficFileLocation = str(os.path.join(currentRemoteNode + "_files.zip").replace("\\", "/"))
            needToCollectData = True

        if(needToCollectData):
            localLocation = str(os.path.join(newDir, currentRemoteNode + "_files.zip").replace("\\", "/"))
            open(localLocation, 'a').close()

            orchestrateRemoteCommands(currentRemoteNode, GENIDict, cmdList) # Create the zip file
            getGENIFile(currentRemoteNode, GENIDict, trafficFileLocation, localLocation) # Grab the zip file

    # Extract everything in the newly-created directory and discard the zip files
    for root, dirs, files in os.walk(newDir):
        for filename in files:
            if(filename.endswith(".zip")):
                absFileLocation = os.path.join(os.path.abspath(newDir).replace("\\", "/"), filename).replace("\\", "/")
                unzip = zipfile.ZipFile(absFileLocation)
                unzip.extractall(newDir)
                unzip.close()
                os.remove(absFileLocation)

    return

def getConvergence():
    dirList = []
    VIDFailureConvergenceTimes = []
    HATFailureConvergenceTimes = []
    logEntries = defaultdict(list)
    clientTrafficEntries = {}

    endNodeNamingSyntax = getConfigInfo("MTP Utilities", "endNodeName")

    userInput = raw_input("Test name: ")
    testDir = str(userInput)
    fileName = "{0}.csv".format(testDir)
    outputFile = open(fileName, "w+")

    for root, dirs, files in os.walk(testDir):
        for name in dirs:
            dirList.append(os.path.join(root, name).replace("\\", "/"))

    for eachRoot in dirList:
        nodeName = re.search('(?<=/)(.*)(?=_files)', eachRoot).group(0)

        if(endNodeNamingSyntax not in nodeName):
            for root, dirs, files in os.walk(eachRoot):
                for file in files:
                    if(".log" in file):
                        filterMTPLog(os.path.join(root, file).replace("\\", "/"), nodeName, logEntries)
        else:
            for root, dirs, files in os.walk(eachRoot):
                for file in files:
                    if(".log" in file):
                        filterClientLog(os.path.join(root, file).replace("\\", "/"), nodeName, clientTrafficEntries)

    outputLogInfo(outputFile, logEntries)

    VIDFailureConvergenceTimes = analyzeVIDFailures(logEntries)
    HATFailureConvergenceTimes = analyzeHATFailures(logEntries)
    outputConvergenceInfo(outputFile, VIDFailureConvergenceTimes, HATFailureConvergenceTimes)

    outputClientInfo(outputFile, clientTrafficEntries)
    outputOverviewInfo(outputFile)

    outputFile.close()

    return

def outputLogInfo(outputFile, logEntries):
    testSortList = []
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"
    outputHeader = "Time Stamp,Log Source,Interface,Message Type,Action\n"
    outputFormat = "{0},{1},{2},{3},{4}"
    failureWritten = False

    outputFile.write("==========LINK FAILURE INFO==========\n\n-LINK FAILURE LOGS-\n" + outputHeader)

    for messageType in logEntries:
        for entry in logEntries[messageType]:
            addMsgType = entry + "|{0}".format(messageType)
            entrySections = addMsgType.split("|")
            formattedEntry = outputFormat.format(entrySections[0], entrySections[5], entrySections[1], entrySections[6], entrySections[4])
            testSortList.append(formattedEntry + "\n")

    sortedList = sorted(testSortList, key=lambda line: datetime.datetime.strptime(line.split(",")[0][:-3], timeStampFormat))

    for item in sortedList:
        if("Link Failure" in item):
            failureWritten = True

        if(failureWritten):
            outputFile.write(item)

    return

def outputConvergenceInfo(outputFile, VIDFailureConvergenceTimes, HATFailureConvergenceTimes):
    linkFailureResultOutputHeader = "Failure,Interface Failure Time,Final Converged Stamp,Result"

    outputFile.write("\n-PVID TREE LINK FAILURE RESULTS-\n")
    outputFile.write(linkFailureResultOutputHeader + "\n")
    for individualInterfaceFailure in VIDFailureConvergenceTimes:
        convergenceTime =  individualInterfaceFailure[3] - individualInterfaceFailure[2]
        updatedStart = "'{0}'".format(individualInterfaceFailure[2])
        updatedEnd = "'{0}'".format(individualInterfaceFailure[3])
        outputFile.write("{0} failing on {1},{2},{3},{4} seconds\n".format(individualInterfaceFailure[1], individualInterfaceFailure[0], updatedStart, updatedEnd, convergenceTime.total_seconds()))

    outputFile.write("\n-HAT LINK FAILURE RESULTS-\n")
    outputFile.write(linkFailureResultOutputHeader + "\n")
    convergenceTime =  HATFailureConvergenceTimes[3] - HATFailureConvergenceTimes[2]
    updatedStart = "'{0}'".format(HATFailureConvergenceTimes[2])
    updatedEnd = "'{0}'".format(HATFailureConvergenceTimes[3])
    outputFile.write("{0} failing on {1},{2},{3},{4} seconds\n".format(HATFailureConvergenceTimes[1], HATFailureConvergenceTimes[0], updatedStart, updatedEnd, convergenceTime.total_seconds()))

    return

def outputClientInfo(outputFile, clientTrafficEntries):
    outputFile.write("\n-CLIENT TRAFFIC OVERVIEW-\nClient,Result\n")
    for message in clientTrafficEntries:
        outputFile.write("{0},{1}".format(message, clientTrafficEntries[message]))

    return

def outputOverviewInfo(outputFile):
    outputFile.write("\n-PVID TREE FAILURE OVERVIEW-\nMessage\n")
    for message in VIDFailureExplained:
        outputFile.write(message + "\n")

    outputFile.write("\n-HAT FAILURE OVERVIEW-\nMessage\n")
    for message in HATFailureExplained:
        outputFile.write(message + "\n")

    return

def filterMTPLog(logFile, nodeName, logCollection):
    VIDFailure  = "7"
    linkFailure = "8"
    HATUpdate   = "9"
    HATFailure  = "10"

    with open(logFile, "r") as readFile:
        for line in readFile:
            updatedLine = line.rstrip() + "|{}".format(nodeName)
            logSections = updatedLine.split("|")

            logDirection   = logSections[2]
            logType        = logSections[3]
            logDescription = logSections[4]

            if(logType == linkFailure):
                logCollection["Link Failure"].append(updatedLine)

            elif(logType == VIDFailure):
                if("Deleted From CPVID Table" in logDescription):
                    logCollection["CPVID Deletion"].append(updatedLine)

                elif("Deleted From VID Table" in logDescription):
                    logCollection["VID Deletion"].append(updatedLine)

                elif("Failed From VID Table [1MH]" in logDescription):
                    logCollection["Missed Hello's VID Failure"].append(updatedLine)

                elif("Failed From CPVID Table [1MH]" in logDescription):
                    logCollection["Missed Hello's CPVID Failure"].append(updatedLine)

                elif("Failed From VID Table [int]" in logDescription):
                    logCollection["Interface VID Failure"].append(updatedLine)

                elif("Failed From CPVID Table [int]" in logDescription):
                    logCollection["Interface CPVID Failure"].append(updatedLine)

                elif("Upgraded to PVID" in logDescription):
                    logCollection["New PVID"].append(updatedLine)

            elif(logType == "3" and "Added to CPVID Table" in logDescription):
                logCollection["CPVID Addition"].append(updatedLine)

            elif(logType == HATFailure):
                if("Failed From Main Host Table [int" in logDescription):
                    logCollection["Interface HAT Main Failure"].append(updatedLine)

                elif("Failed From Main Host Table [1MH" in logDescription):
                    logCollection["Missed Hello's HAT Main Failure"].append(updatedLine)

                elif("Deleted from Main Host Table" in logDescription):
                    logCollection["HAT Main Deletion"].append(updatedLine)

            elif(logType == HATUpdate):
                if("updated main path cost to" in logDescription):
                    logCollection["HAT Update"].append(updatedLine)

    return logCollection

def filterClientLog(logFile, nodeName, logCollection):
    with open(logFile, "r") as readFile:
        logCollection[nodeName] = readFile.read()

    return logCollection

def extractLogEntryInfo(logEntry):
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"

    currentEntry = logEntry.split("|")
    entryTimeStamp = datetime.datetime.strptime(currentEntry[0][:-3], timeStampFormat)
    entryInterface = currentEntry[1]
    entryMessage = currentEntry[4]
    entryNode = currentEntry[5]

    return entryTimeStamp, entryInterface, entryMessage, entryNode

def analyzeHATFailures(logEntries):
    failureTimeStamps = []
    singleFailureInfo = []
    allFailuresInfo = []
    combinedList = []
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"
    limit = datetime.timedelta(hours=0, minutes=0, seconds=8, microseconds=000000)

    for linkFailures in logEntries["Link Failure"]: # For each interface that was failed, we need to determine what happened in the topology
        singleFailureInfo[:] = []
        linkFailureTime, failedInterface, failureMsg, nodeWithFailure = extractLogEntryInfo(linkFailures)
        HATFailureExplained.append("{0} had an interface failure on {1}".format(nodeWithFailure, failedInterface))

        failureTimeStamps.append(linkFailureTime)

        failedHostEntries = checkInterfaceFailures(logEntries["Interface HAT Main Failure"], linkFailureTime, failedInterface, nodeWithFailure, isHATCheck = True)

        if(failedHostEntries):
            failureTimeStamps += failedHostEntries.values()

    combinedList += logEntries["Missed Hello's HAT Main Failure"] + logEntries["HAT Main Deletion"] + logEntries["HAT Update"]

    sortedList = sorted(combinedList, key=lambda line: datetime.datetime.strptime(line.split("|")[0][:-3], timeStampFormat))
    for item in sortedList[:]:
        timediff = datetime.datetime.strptime(item.split("|")[0][:-3], timeStampFormat) - failureTimeStamps[0]

        if(timediff > limit):
            sortedList.remove(item)

    for item in sortedList:
        print(item)
        logTime, logInterface, logMsg, logNode = extractLogEntryInfo(item)

        failureTimeStamps.append(logTime)

        if("Deleted from Main Host Table" in logMsg):
            HATFailureExplained.append("{2} deleted {0} from interface {1}".format(logMsg.split(" ")[0], logInterface, logNode))

        elif("Failed From Main Host Table [1MH" in logMsg):
            HATFailureExplained.append("{2} lost the primary host entry for {0} from interface {1} not receiving Hello messages".format(logMsg.split(" ")[0], logInterface, logNode))

        elif("updated" in logMsg):
            HATFailureExplained.append("{2} updated the cost for host {0} for interface {1}".format(logMsg.split(" ")[0], logInterface, logNode))

        else:
            HATFailureExplained.append("unknown log: {0}".format(logMsg))

    failureTimeStamps.sort()
    singleFailureInfo.extend([nodeWithFailure, failedInterface, linkFailureTime, failureTimeStamps[-1]])

    return singleFailureInfo

def analyzeVIDFailures(logEntries):
    failureTimeStamps = []
    singleFailureInfo = []
    allFailuresInfo = []
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"

    for linkFailures in logEntries["Link Failure"]: # For each interface that was failed, we need to determine what happened in the topology
        singleFailureInfo[:] = []

        currentLinkFailure = linkFailures.split("|")
        linkFailureTime = datetime.datetime.strptime(currentLinkFailure[0][:-3], timeStampFormat)
        failedInterface = currentLinkFailure[1]
        nodeWithFailure = currentLinkFailure[5]
        VIDFailureExplained.append("{0} had an interface failure on {1}".format(nodeWithFailure, failedInterface))

        failureTimeStamps.append(linkFailureTime)

        # Due to the occurance of an interface failure or a node failure, find the PVID or CPVIDs that were lost as a result
        failedPVID, PVIDFailureTime = checkInterfaceFailures(logEntries["Interface VID Failure"], linkFailureTime, failedInterface, nodeWithFailure)
        failedCPVID, CPVIDFailureTime = checkInterfaceFailures(logEntries["Interface CPVID Failure"], linkFailureTime, failedInterface, nodeWithFailure)

        if(failedPVID):
            failureTimeStamps.append(PVIDFailureTime)

        if(failedCPVID):
            failureTimeStamps.append(CPVIDFailureTime)

        # On the other side of an interface failure or a node failure, find the VIDs CPVIDs that were lost as a result
        failedHellosPVID, PVIDHelloFailureTime = checkVIDHelloFailures(logEntries["Missed Hello's VID Failure"], linkFailureTime, failedPVID, failedCPVID = failedCPVID)
        failedHellosCPVID, CPVIDHelloFailureTime = checkVIDHelloFailures(logEntries["Missed Hello's CPVID Failure"], linkFailureTime, failedPVID, failedCPVID = failedCPVID)

        if(failedHellosPVID):
            failureTimeStamps.append(PVIDHelloFailureTime)

        if(failedHellosCPVID):
            failureTimeStamps.append(CPVIDHelloFailureTime)

        # When a link failure occurs, MTP Advertisment Deletion messages will be sent to nearest neighbors, and those VIDs will be deleted
        timeStampsVID = checkVIDDeletions(logEntries["VID Deletion"], linkFailureTime, failedPVID, failedHellosPVID)
        timeStampsCPVID = checkCPVIDDeletions(logEntries["CPVID Deletion"], linkFailureTime, failedPVID, failedHellosPVID)

        if(timeStampsVID):
            failureTimeStamps += timeStampsVID

        if(timeStampsCPVID):
            failureTimeStamps += timeStampsCPVID

        VIDAdditionTimestamps = checkVIDAdditions(logEntries["New PVID"], logEntries["CPVID Addition"], linkFailureTime, failedPVID, failedHellosPVID)

        if(VIDAdditionTimestamps):
            failureTimeStamps += VIDAdditionTimestamps

        failureTimeStamps.sort()
        singleFailureInfo.extend([nodeWithFailure, failedInterface, linkFailureTime, failureTimeStamps[-1]])
        allFailuresInfo.append(singleFailureInfo)

    return allFailuresInfo

def checkInterfaceFailures(logCategory, linkFailureTime, failedInterface, nodeWithFailure, isHATCheck = False):
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"

    if(isHATCheck):
        failedEntry = {}
    else:
        failedEntry = ""
        entryFailureTime = ""

    for entry in logCategory:
        currentEntry = entry.split("|")
        entryTimeStamp = datetime.datetime.strptime(currentEntry[0][:-3], timeStampFormat)
        entryInterface = currentEntry[1]
        entryMessage = currentEntry[4]
        entryNode = currentEntry[5]

        timeStampDifference = entryTimeStamp - linkFailureTime

        # If the VID/CPVID has failed due to the carelessness of a failed interface (2/4 failed VID scenarios)
        if(nodeWithFailure == entryNode and failedInterface == entryInterface and "-1 day" not in str(timeStampDifference)):
            messageContent = entryMessage.split(" ")

            if("{1}" in messageContent[1]):
                failedEntry = messageContent[0]
                entryFailureTime = entryTimeStamp
                VIDFailureExplained.append("{2} lost PVID {0} from interface {1} failing".format(failedEntry, failedInterface, nodeWithFailure))

            elif("CPVID" in messageContent[3]):
                failedEntry = messageContent[0]
                entryFailureTime = entryTimeStamp
                VIDFailureExplained.append("{2} lost CPVID {0} from interface {1} failing".format(failedEntry, failedInterface, nodeWithFailure))

            elif("Main Host Table" in entryMessage):
                failedEntry[messageContent[0]] = entryTimeStamp
                HATFailureExplained.append("{2} lost the primary host entry for {0} from interface {1} failing".format(messageContent[0], failedInterface, nodeWithFailure))

    if(isHATCheck):
        return failedEntry
    else:
        return failedEntry, entryFailureTime

def checkVIDHelloFailures(logCategory, linkFailureTime, failedPrimaryEntry, failedCPVID = None, isHATCheck = False):
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"
    failedVID = ""
    VIDfailureTime = ""

    for entry in logCategory:
        currentEntry = entry.split("|")
        entryTimeStamp = datetime.datetime.strptime(currentEntry[0][:-3], timeStampFormat)
        entryInterface = currentEntry[1]
        entryMessage = currentEntry[4]
        entryNode = currentEntry[5]

        timeStampDifference = entryTimeStamp - linkFailureTime
        validFailureLog = "-1 day" not in str(timeStampDifference)

        if(not isHATCheck):
            if(failedCPVID and validFailureLog):
                messageContent = entryMessage.split(" ")
                if("{1}" in messageContent[1] and failedCPVID == messageContent[0]):
                    failedVID = messageContent[0]
                    VIDfailureTime = entryTimeStamp
                    VIDFailureExplained.append("{2} lost PVID {0} from interface {1} not receiving Hello messages".format(failedVID, entryInterface, entryNode))

            if(failedPrimaryEntry and validFailureLog):
                messageContent = entryMessage.split(" ")
                if(failedPrimaryEntry == messageContent[0]):
                    failedVID = messageContent[0]
                    VIDfailureTime = entryTimeStamp
                    VIDFailureExplained.append("{2} lost CPVID {0} from interface {1} not receiving Hello messages".format(failedVID, entryInterface, entryNode))

    return failedVID, VIDfailureTime

def checkVIDDeletions(logCategory, linkFailureTime, failedPVID, failedHellosPVID):
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"
    farthestTimeStamp = []

    for entry in logCategory:
        currentEntry = entry.split("|")
        entryTimeStamp = datetime.datetime.strptime(currentEntry[0][:-3], timeStampFormat)
        entryInterface = currentEntry[1]
        entryMessage = currentEntry[4]
        entryNode = currentEntry[5]

        timeStampDifference = entryTimeStamp - linkFailureTime
        validFailureLog = "-1 day" not in str(timeStampDifference)

        messageContent = entryMessage.split(" ")
        if("{1}" in messageContent[1]):
            if(failedPVID):
                formattedFailedPVID = "[{0}]".format(failedPVID)
                if(messageContent[6] == formattedFailedPVID):
                    farthestTimeStamp.append(entryTimeStamp)
                    VIDFailureExplained.append("{2} deleted PVID {0} from interface {1} because VID {3} failed".format(messageContent[0], entryInterface, entryNode, failedPVID))

            if(failedHellosPVID):
                formattedFailedHellosPVID = "[{0}]".format(failedHellosPVID)
                if(messageContent[6] == formattedFailedHellosPVID):
                    farthestTimeStamp.append(entryTimeStamp)
                    VIDFailureExplained.append("{2} deleted PVID {0} from interface {1} because VID {3} failed".format(messageContent[0], entryInterface, entryNode, failedHellosPVID))

    return farthestTimeStamp

def checkCPVIDDeletions(logCategory, linkFailureTime, failedPVID, failedHellosPVID):
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"
    farthestTimeStamp = []

    for entry in logCategory:
        currentEntry = entry.split("|")
        entryTimeStamp = datetime.datetime.strptime(currentEntry[0][:-3], timeStampFormat)
        entryInterface = currentEntry[1]
        entryMessage = currentEntry[4]
        entryNode = currentEntry[5]

        timeStampDifference = entryTimeStamp - linkFailureTime
        validFailureLog = "-1 day" not in str(timeStampDifference)

        messageContent = entryMessage.split(" ")
        if(failedPVID):
            formattedFailedPVID = "[{0}]".format(failedPVID)
            if(messageContent[5] == formattedFailedPVID):
                farthestTimeStamp.append(entryTimeStamp)
                VIDFailureExplained.append("{2} deleted CPVID {0} from interface {1} because VID {3} failed".format(messageContent[0], entryInterface, entryNode, failedPVID))

        if(failedHellosPVID):
            formattedFailedHellosPVID = "[{0}]".format(failedHellosPVID)
            if(messageContent[5] == formattedFailedHellosPVID):
                farthestTimeStamp.append(entryTimeStamp)
                VIDFailureExplained.append("{2} deleted CPVID {0} from interface {1} because VID {3} failed".format(messageContent[0], entryInterface, entryNode, failedHellosPVID))

    return farthestTimeStamp

def checkVIDAdditions(newPVIDs, newCPVIDs, linkFailureTime, failedPVID, failedHellosPVID):
    timeStampFormat = "%Y-%m-%d %H:%M:%S.%f"
    farthestTimeStamp = []
    upgradedVIDs = []

    for entry in newPVIDs:
        entryTimeStamp, entryInterface, entryMessage, entryNode = extractLogEntryInfo(entry)

        timeStampDifference = entryTimeStamp - linkFailureTime
        validFailureLog = "-1 day" not in str(timeStampDifference)

        messageContent = entryMessage.split(" ")
        if(failedPVID):
            formattedFailedPVID = "[{0}]".format(failedPVID)
            if(messageContent[4] == formattedFailedPVID):
                farthestTimeStamp.append(entryTimeStamp)
                upgradedVIDs.append((messageContent[0], entryNode))
                VIDFailureExplained.append("{2} Upgraded VID {0} from interface {1} to PVID because VID {3} failed".format(messageContent[0], entryInterface, entryNode, failedPVID))

        if(failedHellosPVID):
            formattedFailedHellosPVID = "[{0}]".format(failedHellosPVID)
            if(messageContent[5] == formattedFailedHellosPVID):
                farthestTimeStamp.append(entryTimeStamp)
                upgradedVIDs.append((messageContent[0], entryNode))
                VIDFailureExplained.append("{2} Upgraded VID {0} from interface {1} to PVID because VID {3} failed".format(messageContent[0], entryInterface, entryNode, failedHellosPVID))

    for entry in newCPVIDs:
        entryTimeStamp, entryInterface, entryMessage, entryNode = extractLogEntryInfo(entry)

        timeStampDifference = entryTimeStamp - linkFailureTime
        validFailureLog = "-1 day" not in str(timeStampDifference)
        messageContent = entryMessage.split(" ")

        for VIDs in upgradedVIDs:
            if(messageContent[0] == VIDs[0] and validFailureLog):
                farthestTimeStamp.append(entryTimeStamp)
                VIDFailureExplained.append("{2} Added CPVID {0} from interface {1} because {3} upgraded its PVID".format(messageContent[0], entryInterface, entryNode, VIDs[1]))

    return farthestTimeStamp

if __name__ == "__main__":
    main()


if __name__ == '__main__':
    n = int(input())
    student_marks = {}
    for _ in range(n):
        name, *line = input().split()
        scores = list(map(float, line))
        student_marks[name] = scores
    query_name = input()

sum = 0;
newList = []
newList1 = []
if (query_name in student_marks):
    newList.append(student_marks[query_name])

# print(newList)
newList1 = newList[0]
# print(newList1)

for i in newList1:
    sum = sum + i
avg = round((sum / 3), 2)
print('%.2f' % avg)


# File handling with python
# To check existance of file ==> os.path.isfile(fname)

import os
import sys

file_name = "first1_file.txt"
if os.path.isfile(file_name):
    print("File Exists", file_name)
    f = open("first_file.txt", "a+")
    data = "Hello there, this is first_file\n"
    f.writelines(data)
    print(f.tell())
    f.seek(0)
    data_read = f.read()
    print("Read_data : ", data_read)
    f.close()
else:
    print("File does not exists : ", file_name)
    sys.exit(0)  # To terminate program 0-Normal termination


import argparse
import os

import numpy as np
import onnxruntime
from onnxruntime.quantization import CalibrationDataReader, QuantFormat, quantize_dynamic, QuantType, quantize_static
import torchvision.datasets as datasets

np.random.seed(0)

class ImageNetCalibrationDataReader(CalibrationDataReader):
    def __init__(self, dataset_path, model_path, transform, num_samples):
        self.train_path = os.path.join(dataset_path, 'train')
        self.model_path = model_path
        self.transform = transform
        self.num_samples = num_samples
        self.preprocess_flag = True
        self.enum_data_dicts = []

    def get_next(self):
        if self.preprocess_flag:
            self.preprocess_flag = False
            session = onnxruntime.InferenceSession(self.model_path, None, providers=['CPUExecutionProvider'])
            nchw_data_list = self.preprocess_func()
            input_name = session.get_inputs()[0].name
            self.enum_data_dicts = iter([{input_name: nchw_data} for nchw_data in nchw_data_list])
        return next(self.enum_data_dicts, None)

    def preprocess_func(self):
        train_dataset = datasets.ImageFolder(self.train_path, self.transform)
        sample_idxs = np.random.choice(len(train_dataset), self.num_samples)
        nchw_data = [train_dataset[i][0].numpy() for i in sample_idxs]
        nchw_data = np.array(nchw_data) # shape = [num_samples, c, h, w]
        return np.expand_dims(nchw_data, axis=1) # shape = [num_samples, batch_size=1, c, h, w]

class DummyCalibrationDataReader(CalibrationDataReader):

    def __init__(self, model_path, num_samples) -> None:
        self.model_path = model_path
        self.num_samples = num_samples
        self.enum_data_dicts = iter([{self.input_name: data} for data in self.preprocess_func()])

    def get_next(self):
        return next(self.enum_data_dicts, None)

    @property
    def input_shape(self):
        try:
            return self._input_shape
        except:
            sess = onnxruntime.InferenceSession(self.model_path, providers=['CPUExecutionProvider'])
            self._input_shape = sess.get_inputs()[0].shape
        return self._input_shape

    @property
    def input_name(self):
        try:
            return self._input_name
        except:
            sess = onnxruntime.InferenceSession(self.model_path, providers=['CPUExecutionProvider'])
            self._input_name = sess.get_inputs()[0].name
        return self._input_name

    def preprocess_func(self):
        return np.random.rand(self.num_samples, 1, *self.input_shape[1:]).astype(np.float32)

def onnx_quantize_static_pipeline(input_path, output_path, calib_data_reader=None, remove_opt=True, **kwargs):
    if calib_data_reader is None:
        calib_data_reader = DummyCalibrationDataReader(input_path, num_samples=30)
    kwargs['quant_format'] = kwargs.get('quant_format', QuantFormat.QOperator)
    quantize_static(input_path, output_path, calib_data_reader, **kwargs)
    if remove_opt:
        try:
            os.remove(input_path.replace('.onnx', '-opt.onnx'))
        except:
            pass
    print(f'Successfully quantize model to {output_path}.')

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--model', required=True, type=str, help='float32 onnx model to quantize')
    parser.add_argument('--output_path', required=True, type=str)
    parser.add_argument('--weight_type', choices=['uint8', 'int8'], default='int8', type=str, help='quantization output data type')
    parser.add_argument('--quant_dynamic', action='store_true', help='use dynamic range quantization, default false: use static quantization.')
    parser.add_argument('--per_channel', action='store_true', help='per channel quant, useful only in static quantization')
    args = parser.parse_args()
    input_path = args.model
    output_path = args.output_path

    if args.quant_dynamic:
        quantize_dynamic(input_path, output_path)
        print(f'Successfully dynamic quantize model to {output_path}.')

    else:
        quant_args = dict(
            per_channel = args.per_channel,
            weight_type = QuantType.QInt8 if args.weight_type == 'int8' else QuantType.QUInt8
        )
        onnx_quantize_static_pipeline(args.model, args.output_path, **quant_args)

if __name__ == '__main__':
    main()


class Node(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

s = Node(3)
s.left = Node(4)
s.left.left = Node(1)
s.left.right = Node(2)
s.right = Node(5)

t = Node(4)
t.left = Node(1)
t.right = Node(2)

def isSubtree(s, t):
    """
    :type s: TreeNode
    :type t: TreeNode
    :rtype: bool
    """
    if not s:
        return False

    def helper(st, tt):
        if not st and not tt:
            return True
        elif (not st and tt) or (not tt and st):
            return False
        else:
            if st.val == tt.val:
                if st:
                    return True and helper(st.left, tt.left) and helper(st.right, tt.right)
                else:
                    return True
            else:
                return False

    l = isSubtree(s.left, t)
    r = isSubtree(s.right, t)
    if l or r:
        return True
    sel = helper(s, t)
    return sel

print(isSubtree(s,t))

算法题/求一棵树是否包含某棵子树.py

求一棵树是否包含某棵子树.py


# https://school.programmers.co.kr/learn/courses/30/lessons/181925

def solution(numLog):
    check_dict = {1: "w", -1: "s", 10: "d", -10: "a"}

    result = ""

    for i in range(1, len(numLog)):
        result += check_dict[(numLog[i] - numLog[i - 1])]

    return result


import sys
input = sys.stdin.readline

def solution(phone):
    phone.sort()
    for i in range(len(phone) - 1):
        if phone[i] == phone[i + 1][:len(phone[i])]:
            return 'NO'
    return 'YES'

for _ in range(int(input())):
    print(solution([input().rstrip() for _ in range(int(input()))]))


import Validate
import app
import pymysql
class Create:
    def __init__(self, cnx):
        self.cnx = cnx

    def delegate(self):
        print("What do you want to create? Please chose from the following options, or press Q to go back:")
        print("Location, Growth Equity Firm, Venture Capital Firm, Portfolio Company, Sector, Investment, Partner")
        user_in = input("Create: ")
        if user_in.lower() == "q":
            return app.main(self.cnx)
        v = Validate.Validate(self.cnx)
        while not v.validateInput(user_in, ["Location", "Growth Equity Firm", "Venture Capital Firm",
                                            "Portfolio Company", "Sector", "Investment", "Partner"]):
            print("Invalid Input Please try again with the options below, or enter Q to go back")
            print("Location, Growth Equity Firm, Venture Capital Firm, Portfolio Company, Sector, Investment, Partner")
            user_in = input("Create: ")
            if user_in.lower() == "q":
                return app.main(self.cnx)

        user_in = user_in.lower()
        if user_in == "location":
            return self.addLocation()
        elif user_in == "growth equity firm":
            return self.addGrowthEquity()
        elif user_in == "venture capital firm":
            return self.addVC()
        elif user_in == "portfolio company":
            return self.addPortfolio()
        elif user_in == "sector":
            return self.addSector()
        elif user_in == "investment":
            return self.addInvestment()
        elif user_in == "partner":
            return self.addPartner()

    def addLocation(self):
        c = self.cnx.cursor()
        arr = self.validateCreateInputValue(["Location ID: ", "State: ", "City: "], "location", "locationID",
                                      "Location ID already exists try again or press Q to return to home")
        if not arr:
            return
        else:
            sql_statement = "INSERT INTO location (locationID, state, city) VALUES (" + arr[0] + ", '" \
                            + arr[1] + "', '" + arr[2] + "')"
            c.execute(sql_statement)
            self.cnx.commit()
            print("Location inserted into table\n")
            c.close()

    def addVC(self):
        c = self.cnx.cursor()

        arr = self.validateCreateInputValue(["Firm ID: ", "Name: ", "Location ID: "], "vc_firms", "firmID",
                                            "Firm ID already exists try again or press Q to return to home")
        if not arr:
            print("Back to homepage")
        else:
            try:
                sql_statement = "INSERT INTO vc_firms (firmID, name, locationID) VALUES (" + arr[0] + ", '" \
                                + arr[1] + "', " + arr[2] + ")"
                c.execute(sql_statement)
                self.cnx.commit()
                print('VC Firm inserted into table!\n')
                c.close()
            except pymysql.err.IntegrityError:
                print("Create Failed!, Check foreign key provided (locationID) to see if it exists.\n")

    def addPartner(self):
        c = self.cnx.cursor()
        arr = self.validateCreateInputValue(["Partner ID: ", "Name: ", "Contact: ", "Firm ID: "], "partners",
                                            "partnerID",
                                            "Partner ID already exists try again or press Q to return to home")
        if not arr:
            print("Back to homepage")
        else:
            try:
                sql_statement = "INSERT INTO partners (partnerID, firmID, name, contact) VALUES (" + arr[0] + ", " \
                                + arr[3] + ", '" + arr[1] + "', '" + arr[2] + "')"
                c.execute(sql_statement)
                self.cnx.commit()
                print('Partner inserted into table!\n')
                c.close()
            except pymysql.err.IntegrityError:
                print("Create Failed!, Check foreign key provided (firmID) to see if it exists.\n")

    def addGrowthEquity(self):
        c = self.cnx.cursor()
        arr = self.validateCreateInputValue(["Firm ID: ", "Name: ", "Location ID: "], "growth_equity_firms", "firmID",
                                            "Firm ID already exists try again or press Q to return to home")

        if not arr:
            print("Back to homepage")
        else:
            try:
                sql_statement = "INSERT INTO growth_equity_firms (firmID, name, locationID) VALUES (" + arr[0] + ", '" \
                                + arr[1] + "', " + arr[2] + ")"
                c.execute(sql_statement)
                self.cnx.commit()
                print('Growth Equity Firm inserted into table!\n')
                c.close()
            except pymysql.err.IntegrityError:
                print("Create Failed!, Check foreign key provided (locationID) to see if it exists.\n")

    def addSector(self):
        c = self.cnx.cursor()
        arr = self.validateCreateInputValue(["Sector ID: ", "Industry: ", "Type (VC/GE)",
                                             "Fund Size: ", "firmID: "], "sector",
                                            "sectorID",
                                            "Sector ID already exists try again or press Q to return to home")
        if not arr:
            print("Back to homepage")
        else:
            try:
                sql_statement = ""
                b = True
                while b:
                    if arr[2].lower() == "vc":
                        sql_statement = "INSERT INTO sector (sectorID, industry, vc_firm_id, ge_firm_id, fund_size) " \
                                    "VALUES (" + arr[0] + ", '" + arr[1] + "', " + arr[4] + ", null, " + arr[3] + ")"
                        b = False
                    elif arr[2].lower() == "ge":
                        sql_statement = "INSERT INTO sector (sectorID, industry, vc_firm_id, ge_firm_id, fund_size) " \
                                        "VALUES (" + arr[0] + ", '" + arr[1] + "', null, " + arr[4] + ", " \
                                        + arr[3] + ")"
                        b = False
                    elif arr[2].lower() == 'q':
                        return
                    else:
                        arr[2] = input("Invalid Type please re-eneter (VC/GE): ")

                c.execute(sql_statement)
                self.cnx.commit()
                print('Sector inserted into table!\n')
                c.close()
            except pymysql.err.IntegrityError:
                print("Create Failed! Check foreign key provided (firmID) to see if it exists.\n")

    def addInvestment(self):
        c = self.cnx.cursor()

        arr = self.validateCreateInputValue(["Investment ID: ", "Amount: ", "Series: ", "Date: "], "investment",
                                            "investmentID",
                                            "Investment ID already exists try again or press Q to return to home")
        if not arr:
            print("Back to homepage")
        else:
            sql_statement = "INSERT INTO investment (investmentID, amount, series, date) VALUES (" + arr[0] + ", " \
                            + arr[1] + ", '" + arr[2] + "', '" + arr[3] + "')"
            c.execute(sql_statement)
            self.cnx.commit()
            print('Investment inserted into table!\n')
            c.close()

    def addPortfolio(self):
        c = self.cnx.cursor()

        arr = self.validateCreateInputValue(["Portfolio ID: ", "Name: ", "Investment ID: ", "Sector ID: "],
                                            "portfolio_companies",
                                            "portID",
                                            "Portfolio ID already exists try again or press Q to return to home")
        if not arr:
            print("Back to homepage")
        else:
            try:
                sql_statement = "INSERT INTO portfolio_companies (portID, name, investmentID, sectorID) VALUES ("\
                                + arr[0] + ", '" + arr[1] + "', " + arr[2] + ", " + arr[3] + ")"
                c.execute(sql_statement)
                self.cnx.commit()
                print('Portfolio inserted into table!\n')
                c.close()
            except pymysql.err.IntegrityError:
                print("Create Failed! Check foreign keys provided (investmentID, sectorID) to see if they exist.\n")

    # Validate the inputs to see if they exist
    def validateCreateInputValue(self, arr, table, column, message):
        try:
            identifier = input(arr[0])
            v = Validate.Validate(self.cnx)
            while not v.validateUnique(table, column, identifier,
                                       message):
                identifier = input(arr[0])
                if identifier == 'Q':
                    return []
        except ValueError:
            print("Cannot input a string as an ID, must be an int, try again")
            return []

        tempArr = [""] * len(arr)
        tempArr[0] = identifier
        for val in range(1, len(arr)):
            tempArr[val] = input(arr[val])

        return tempArr


from .base import *

from .base import env

DEBUG = True

SECRET_KEY = env(
    "DJANGO_SECRET_KEY",
    default="ASADFSDAasdfadfASDFASFSADASDF",
)

ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1"]

EMAIL_BACKEND = "djcelery_email.backends.CeleryEmailBackend"
EMAIL_HOST = env("EMAIL_HOST", default="mailhog")
EMAIL_PORT = env("EMAIL_PORT")
DEFAULT_FROM_EMAIL = "ahmed@gmail.com"
DOMAIN = env("DOMAIN")
SITE_NAME = "Auth API"


from nav.models import Path, Route, Street

def handle_uploaded_file(csv_file):
    """Process content from user file and insert/update data in the database

    Args:
    -----
        csv_file:
            uploaded by user CSV file, ';' separator has to be used
    """
    file_data = csv_file.read().decode("utf-8")
    lines = file_data.split("\n")
    for i, line in enumerate(lines):
        if i == 0:
            continue  # skip header
        line = line.strip()
        street_names = line.split(";")
        if len(street_names) < 3:  # we need start, destination and at least one middle street
            continue

        names = []
        start = None
        destination = None
        for j, street_name in enumerate(street_names):
            street_name = Street.prepare_name(street_name)
            if len(street_name) == 0:
                continue
            if j == 0:
                start, _ = Street.objects.get_or_create(name=street_name)
            elif j == 1:
                destination, _ = Street.objects.get_or_create(name=street_name)
            else:
                street, _ = Street.objects.get_or_create(name=street_name)
                names.append(street_name)
        if destination is None or start is None or len(names) == 0:
            return
        route, _ = Route.objects.get_or_create(start=start,
                                               destination=destination,
                                               name=Route.prepare_name(start.name, destination.name))
        route_path_text = Path.prepare_path_text(names)
        route_path_index = Path.prepare_path_index(route_path_text)

        Path.objects.update_or_create(route=route,
                                      path_index=route_path_index,
                                      path_text=route_path_text)


#!/usr/bin/env python
# coding: utf-8

# In[ ]:

import requests
import urllib.request, json
from bs4 import BeautifulSoup
from anytree import Node, RenderTree, search
from fpdf import FPDF
import matplotlib.pyplot as plt
import re
import matplotlib as mpl
import networkx as nx

def read_from_mirror():
    URL ='https://bangaloremirror.indiatimes.com/bangalore/others/karnataka-covid-19-tracker/articleshow/74892676.cms'
    r = requests.get(URL)
    soup = BeautifulSoup(r.content, "html.parser")
    tags = soup.find_all('div',{'class': 'Normal'})
#    gulf = ['Dubai','Saudi','Mecca']
#    delhi = ['Delhi', 'Jamaat','Manipur','Colombo','Trivandrum']
#    eu = ['Edinburgh','UK',"Switzerland","Greece","Germany","Netherland","London","Spain",'Scotland','France','Paris','Madrid','Amsterdam','Athens']
#    usa = ['USA','Brazil','Guyana', 'New']
    #bengaluru = Node("Bangalore",parent=Local,desc="Resident Of bangalore")
    return tags

# In[ ]:

def get_parent(line):
    val = ''
    patt = re.compile(r'con\w+ of P(( |-)?\d+)')
    mat = patt.search(line)
    if (mat != None):
        val = re.findall('\d+',mat.group(1))[0]
    return val

def get_age_and_place(line):
    resident_of = 'na'
    age = 'na'
    gender = 'na'
    gendp = re.compile(r'male|femal|girl|boy')
    agep = re.compile(r'(\d+)(-| )(year|-year)|month')
    placep = re.compile(r'(from|resident of) (\w+)')
    mat = gendp.search(line)
    if (mat != None):
        gender = mat.group()
    #gender = mat.group()
    mat = agep.search(line)
    if mat != None:
        age = mat.group(1)
    mat = placep.search(line)
    if (mat != None):
        resident_of = mat.group(2)

    if (resident_of in ['Bengaluru','Bangalore','Hosakote','Benglauru','Hoskote']):
        resident_of =  'Bangalore'
    if (resident_of in ['Nanjangudu','Mysore','Nanjangud','Nanjungud','Mysuru','Nanjanagudu']):
        resident_of = 'Mysore'
    if (resident_of in ['Kalburgi','Kalaburagi', 'Kalaburgi', 'Kalburagi']):
        resident_of = 'Kalburgi'
    if (resident_of in ['Mandya', 'Malavalli']):
        resident_of = 'Mandya'
    if (resident_of in ['Kasargod','Kochi','Kannur','Kerala']):
        resident_of = 'Kerala'
    if (resident_of in ['Gadag','Mudhol','Hubballi','Dharwad']):
        resident_of = 'Hubballi'
    if (resident_of in ['Batkal','Bhatkal','Bhatkal']):
        resdient_of = 'Bhatkal'
    if (resident_of in ['Bagalkot','Bagalkote']):
        resident_of = 'Bagalkote'
    if (resident_of in ['Ballari', 'Hospet']):
        resident_of = 'Ballari'
    return (age,gender,resident_of)

def get_patient(line):
    patient = ''
    pat = re.compile(r'Pat\w+ number (\d+)' )
    mat = pat.search(line)
    if (mat == None):
        pat =re.compile(r'(\d+) is a')
        mat = pat.search(line)
    if mat != None:
        patient = re.findall('\d+',mat.group(1))[0]
    return patient

def get_travel(line):
    gulf = ['Dubai','Saudi','Mecca']
    delhi = ['Delhi', 'Jamaat','Manipur','Colombo','Trivandrum']
    eu = ['Edinburgh','UK',"Switzerland","Greece","Germany","Netherland","London","Spain",'Scotland','France','Paris','Madrid','Amsterdam','Athens']
    usa = ['USA','Brazil','Guyana', 'New']
    #bengaluru = Node("Bangalore",parent=Local,desc="Resident Of bangalore")

    travel = 'Local'
    pat = re.compile(r'travel history to (the )?(\w+)')
    mat = pat.search(line)
    if (mat == None):
        mat = re.compile(r'returned (to India )?from (\w+)').search(line)
    if (mat == None):
        mat = re.compile(r'(the )?(phar\w+)').search(line)
    if (mat != None):
        travel = mat.group(2)

    if (travel in gulf):
        travel = "Gulf"
    elif (travel in eu):
        travel = 'Europe'
    elif (travel in usa):
        travel = "America"
    elif (travel in delhi):
        travel = 'Delhi'
    elif (travel in ['pharma','pharmaceutical']):
        travel = 'Pharma'
    else:
        travel = 'Local'

#    print(travel, line)
    return travel

# In[ ]:

def get_count_from_travel(rnode, travel,disp=False):
    (primary_carrier,total_impact,spread_count) = (0,0,0)
    for pre, fill, node in RenderTree(rnode):
        if (node.depth < 4):
            primary_carrier += 1
        if (node.depth >= 4):
            spread_count += 1
        total_impact += 1
        if(disp):
            print("%s%s %s-%s-%s %s" % (pre, node.name,node.age,node.gender,node.loc,node.travel))
    return (total_impact, primary_carrier, spread_count)

# In[ ]:

def print_node(loc='',travel=''):
    rnode = root
    rdepth = 3
    sdepth = 2
    (uknown_total, uknown_primary, uknown_spread) = (0,0,0)
    (travel_total, travel_primar, travel_spread, primary_carriers, primary_travel) = (0,0,0,0,0)
    total_cases = 0
    total_spread = 0

    if loc != '':
        rnode = search.find(root, lambda node: node.name == loc)
    if (rnode != root):
            rdepth = 3
            sdepth = 2
    for pre, fill, node in RenderTree(rnode):
        if (str.isdigit(node.name)):
            total_cases += 1

        if (node.depth == rdepth):
            primary_carriers += 1

        if (node.name == 'Local'):
                (t, p, s) = get_count_from_travel(node, 'Local')
                uknown_total += t
                uknown_primary += p
                uknown_spread += s
        if( node.name == travel ):
            (t,p,s) = get_count_from_travel(node, travel, True)
            travel_total += t
            travel_primar += p
            travel_spread += s
            if (node.depth == sdepth):
                primary_travel += 1
                    #print("%s%s %s-%s-%s %s" % (pre, node.name,node.age,node.gender,node.loc,node.travel))
        if node.depth > sdepth+1:
            total_spread += 1
        if ( travel == ''):
            print("%s%s %s-%s-%s %s" % (pre, node.name,node.age,node.gender,node.loc,node.travel))

    print("Total Cases in %s: \t\t\t\t %s" %(loc,total_cases))
    print("Total Primar carriers in %s: \t\t\t %s" %(loc,primary_carriers))
    print("Total Impact due to travel in %s: \t\t %s" %(loc,total_cases - uknown_total))
    print("Total Spread in %s from Primary carriers: \t %s" %(loc,total_spread))
    print("Total Unknown Local cases in %s: \t\t %s" %(loc,uknown_total))
    print("Total Spread from uknown Local cases in %s: \t %s" %(loc,uknown_spread))

    print("Impact in %s due to Travel from %s...."%(loc,travel))
    print("\tTotal Impact    : \t %s" %(travel_total))
    print("\tPrimary Carrier : \t %s" % travel_primar)
    print("\tTotal Spread    : \t %s" %(travel_spread))

# In[ ]:

def add_node(p,cp,age,gender,loc,travel):

    #Add localtion if does not exist.
    loc_node = search.find(root, lambda node: node.name == loc)
    if (loc_node == None):
#        print("Adding location %s node to" %loc,root)
        loc_node = Node(loc,parent=root,age='',gender='',loc='',travel='')

    #Under loc, add local if no travel, else create under travel.
    if (cp == ''):
        travel_his = search.find(loc_node,lambda node: node.name == travel)
        if (travel_his == None):
            #Adding travel
#            print("Adding new node with travel ", p,loc_node, travel)
            travel_his = Node(travel,parent=loc_node,age='',gender='',loc='',travel='')
        par = travel_his
    else:
        par = search.find(root, lambda node: node.name == cp)
#    print("Adding patient %s to " % p,par,cp,loc)
    Node(p,parent=par,age=age,gender=gender,loc=loc,travel=travel)

# In[ ]:

def sort_dict(tlist):
    for item in sorted(tlist.keys()):
        add_node(tlist[item]['p'],
                 tlist[item]['par'],
                 tlist[item]['age'],
                 tlist[item]['gender'],
                 tlist[item]['loc'],
                 tlist[item]['travel'])

        #print(item)
#        print("Patient no %d contact of %s aged %s from %s has travel to %s" %(item,tlist[item]['par'],
#                                                                               tlist[item]['age'],
#                                                                               tlist[item]['loc'],
#                                                                               tlist[item]['travel']))

# In[ ]:

def add_to_graph(tlist,cont=''):
#    G=nx.DiGraph()
#    G = nx.generators.directed.random_k_out_graph(3, 1, 0.05)
#    G = nx.star_graph(2000)

    for item in sorted(tlist.keys()):
        contact = tlist[item]['par']
        patient = tlist[item]['p']
        if (contact == ''):
            print_graph(G,tlist,patient)
#            G.add_node(patient)
#            for item in sorted(tlist.keys()):
#                c = tlist[item]['par']
#                p = tlist[item]['p']
#                if (c == patient):
#                    G.add_edges_from([(p,patient)])
        else:
            continue
#        if (cont != '' and  contact != cont):
#            continue
#        if (contact != ''):
#            G.add_edges_from([(contact,patient)])
#        else:
#            G.add_node(patient)
#    nx.draw(G,with_labels=True)
#    pos = nx.spring_layout(G)
#    colors = range(20)
#    nx.draw(G, pos, with_labels=True)
#    plt.show()
#    nx.draw_graphviz(G)
#    print_graph(G)

# In[ ]:

def populate_data():
    total_count = 1
    local_spread = 1
#    root = Node("Covid-19",desc='Karnataka',age='',gender='',loc='',travel='')
#    Bang = Node('Bangalore', parent=root, desc='Resident of Bangalore',age='',gender='',loc='',travel='')
    i = 0
    p_list = {}
    tags = read_from_mirror()
    for tag in tags:

        if "Patient" in tag.text:
            r1 = tag.text.split('\n')
            for line in r1:

                spread = False
                area_root = root
                par = None
                p = get_patient(line)
                if (p != ''):
                    total_count += 1
                    i += 1
                else:
                    continue
                cp = get_parent(line)
                if (cp != ''):
                    local_spread += 1
                    spread = True
                travel = get_travel(line)
                (age,gender,loc) = get_age_and_place(line)
                p_list.update({int(p):{'p':p,"par":cp,"age":age,"gender":gender,"loc":loc,"travel":travel}})
                #add_node(p,cp,age,gender,loc,travel)
    #            if (i == 10):
    #                break
    sort_dict(p_list)
    return p_list

# In[ ]:

def print_graph(G,tlist,parent):
#    G = nx.DiGraph()
#    G.clear()
#    G.add_node(patient)

    for item in sorted(tlist.keys()):
        c = tlist[item]['par']
        p = tlist[item]['p']
        if (c == parent):
            G.add_edges_from([(parent,p)])
            print_graph(G,tlist,p)

#    plt.figure(figsize=(18,18))
#    graph_pos = nx.spring_layout(G)
#    nx.draw(G, with_labels=True)
#    plt.show()
#    nx.draw_networkx_nodes(G, graph_pos, node_size=10, node_color='blue', alpha=0.3)
#    nx.draw_networkx_edges(G, graph_pos)
#    nx.draw_networkx_labels(G, graph_pos, font_size=8, font_family='sans-serif')

#    plt.show()
    #plt.savefig("plot.p

# In[109]:

def print_g(G,patient,from_loc,relabel_list):
    if (len(G)<=2):
        return
#    graph_pos = nx.spring_layout(G)
#    nx.draw(G, with_labels=True)
#    plt.show()
    plt.figure(figsize=(18,18))
    plt.axis(False)
#    nx.draw_networkx_nodes(G, graph_pos, node_size=10, node_color='blue', alpha=0.3)
#    nx.draw_networkx_edges(G, graph_pos)
#    nx.draw_networkx_labels(G, graph_pos, font_size=8, font_family='sans-serif')
    nx.relabel_nodes(G, relabel_list, copy=False)
    nx.draw_spring(G,with_labels=True,edge_color="r",width=4,node_color="#A0CBE2",node_size=3000,arrowsize=18,font_size=16)
    name = "imagfiles/"+patient + "_from_" + from_loc + ".pdf"
    plt.savefig(name,dpi=150)
#    plt.show()

# In[112]:

def display_graph(tlist,cont_filter='',loc_filter=''):
    G=nx.DiGraph()
#    G = nx.generators.directed.random_k_out_graph(3, 1, 0.05)
#    G = nx.star_graph(2000)
#    relabel_list = {}
    for item in sorted(tlist.keys()):
        contact = tlist[item]['par']
        patient = tlist[item]['p']
        loc = tlist[item]['loc']
        travel = tlist[item]['travel']
        if (loc_filter != '' and loc_filter != loc):
            continue
        if (contact == ''):
            G.clear()
            relabel_list = {}
            G.add_node(patient)
            relabel_list.update({patient:"patient no:"+ patient+"-"+loc+"-acquired-from-"+travel})
            print_graph(G,tlist,patient)
            print_g(G,patient,tlist[item]['loc'],relabel_list)

        else:
            continue

# In[ ]:

root = Node("Covid-19",desc='Karnataka',age='',gender='',loc='',travel='')
p_list = populate_data()

# In[ ]:

print_node(loc='Bangalore', travel='')

# In[113]:

display_graph(p_list)

# In[ ]:

import PyPDF2 as pypdf
import os
import re

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    '''
    alist.sort(key=natural_keys) sorts in human order
    http://nedbatchelder.com/blog/200712/human_sorting.html
    (See Toothy's implementation in the comments)
    '''
    return [ atoi(c) for c in re.split(r'(\d+)', text) ]

def merge_files():

    writer = pypdf.PdfFileWriter()
    files = entries = os.listdir('ImagFiles/')

    files.sort(key=natural_keys)
#    print(sfiles)
    for file in files:
        infile = open("ImagFiles/"+file,"rb")
        print("reading from ",file)
        reader = pypdf.PdfFileReader(infile)
        for page in range(reader.getNumPages()):
            writer.addPage(reader.getPage(page))
        # write everything in the writer to a file
    with open("ImagFiles/May3_graph.pdf","wb") as outFile:
        writer.write(outFile)
    outFile.close()

# In[114]:

merge_files()

# In[ ]:

# In[ ]:

# In[ ]: