# -*- coding: utf-8 -*-
from __future__ import absolute_import
import json
import logging

from tornado.escape import json_encode
from tornado.escape import json_decode
from tornado.escape import utf8

from .constant import *

logger = logging.getLogger('server.' + __name__)

class JsonStream:

    def __init__(self, stream, address):
        self._stream = stream
        self._address = address
        self._stream.read_until(bDELIMITER, self.on_read)

    async def on_read(self, data):
        try:
            if data:
                dict_ = json_decode(data)
            await self.on_read_json(dict_)
        except Exception as e:
            logger.error('Error occurs during decoding data from device.\n\
                          {}'.format(e), exc_info=True)
        self._stream.read_until(bDELIMITER, self.on_read)

    def on_read_json(self, dict_):
        pass

    def send_json(self, dict_):
        if not self._stream.closed():
            self._stream.write(utf8(json_encode(dict_) + DELIMITER))


from urllib.request import urlopen
import plotly.graph_objs as go
import plotly.express as px
import pandas as pd
import plotly
import json
import os

data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..\..', 'data'))
usa_data_dir = os.path.join(data_dir, 'usa')

csv_dir = os.path.join(usa_data_dir, 'csv')
csv_data = os.path.join(csv_dir, 'us-counties.csv')
df = pd.read_csv(csv_data, sep=',', header=0)

# Filtering by latest date
df = df.loc[df['date'] == '2020-08-04']
# Filling empty cells
df = df.fillna(0)
# Removing rows where fips is 0
df = df.loc[df['fips'] != 0]
df = df.loc[df['state'] == 'New York']

geojson_url = 'https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json'
with urlopen(geojson_url) as response:
    counties = json.load(response)

maps_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..\..', 'maps'))
result_html = os.path.join(maps_dir, 'ny-counties-coronavirus-heatmap.html')

fig = px.choropleth_mapbox(df,
                           geojson=counties,
                           locations='fips',
                           color='deaths',
                           hover_data=["county", "state", "deaths", "cases"],
                           color_continuous_scale="Jet",
                           range_color=(0, 30),
                           mapbox_style="carto-positron",
                           zoom=6.0, center={"lat": 42.723, "lon": -75.762},
                           opacity=0.5,
                           labels={'county': 'County', 'state': 'State'}
                           )
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
plotly.offline.plot(fig, filename=result_html)

state_data = os.path.join(csv_dir, 'us-states.csv')
state_code_data = os.path.join(csv_dir, 'us-agr-exports-2011.csv')
df_state = pd.read_csv(state_data, sep=',', header=0)
junk_data = pd.read_csv(state_code_data, sep=',', header=0)
df_code = junk_data[['code', 'state']]
plot_data = df_state.merge(df_code, on=['state'], how='left')
plot_data = plot_data.loc[plot_data['date'] == '2020-08-04']
print(plot_data)
states_plot = os.path.join(maps_dir, 'usa-states-coronavirus-heatmap.html')

plot_data['text'] = 'State: ' + plot_data['state'].astype(str) + '
' + \
    'Cases: ' + plot_data['cases'].astype(str) + '
' + \
    'Deaths: ' + plot_data['deaths'].astype(str)

# Color-scales: https://plotly.com/python/v3/colorscales/
# Maps Reference: https://plotly.com/python/choropleth-maps/
fig = go.Figure(data=go.Choropleth(
    locations=plot_data['code'],
    z=plot_data['deaths'],
    locationmode='USA-states',
    colorscale=[
        [0.0, 'rgb(165,0,38)'],
        [0.1111111111111111, 'rgb(215,48,39)'],
        [0.2222222222222222, 'rgb(244,109,67)'],
        [0.3333333333333333, 'rgb(253,174,97)'],
        [0.4444444444444444, 'rgb(254,224,144)'],
        [0.5555555555555556, 'rgb(224,243,248)'],
        [0.6666666666666666, 'rgb(171,217,233)'],
        [0.7777777777777778, 'rgb(116,173,209)'],
        [0.8888888888888888, 'rgb(69,117,180)'],
        [1.0, 'rgb(49,54,149)']
    ],
    text=plot_data['text'],  # hover text
    colorbar_title='Deaths'
))

fig.update_layout(
    title_text='2020 Coronavirus Deaths in USA',
    geo=dict(
        scope='usa',
        projection=go.layout.geo.Projection(type='albers usa')
    )
)

plotly.offline.plot(fig, filename=states_plot)


from Bio.Seq import Seq
import os
def parse_query_results(path):
    """
    This fucntion will p[arse the query results
    :param path: The path of the file that contains the query results
    :return: An array that contains the results described in the file
    """
    file = open(path,"r")
    results = []
    for line in file:
        split_by_tab = line.split("\t")
        dictionary = {}
        dictionary["qseqid"] = split_by_tab[0]
        dictionary["sseqid"] = split_by_tab[1]
        dictionary["pident"] = split_by_tab[2]
        dictionary["length"] = split_by_tab[3]
        dictionary["mismatch"] = split_by_tab[4]
        dictionary["gapopen"] = split_by_tab[5]
        dictionary["qstart"] = split_by_tab[6]
        dictionary["qend"] = split_by_tab[7]
        dictionary["sstart"] = split_by_tab[8]
        dictionary["send"] = split_by_tab[9]
        dictionary["evalue"] = split_by_tab[10]
        dictionary["bitscore"] = split_by_tab[11][:-1]

        results.append(dictionary)
    return results

def get_pairs(query_results):
    """
    This function will build and return the pairs of (miRNA,host) for every full match
    :param query_results:The given array of results
    :return: An array of pairs
    """
    pairs = []
    for res in query_results:
        pident = float(res["pident"])
        if pident == 100:
            miRNA = res['qseqid']
            host = res["sseqid"]

            try:
                index_semicolon = host.index(";")
                index = host.index("|")
                pre = host[:index_semicolon]
                post = host[index]
                host = "%s%s" % (pre,post)

            except(ValueError):
                pass
            pairs.append((miRNA, host))
    return pairs

def get_3_tag_UTR(host_header,file_name):
    """
    This function will return the sequence that the given header describes (in the mRNA file)
    :param host_header: The given host header
    :return: The sequence that the given header describes (in the mRNA file)
    """
    mRNA_path_file = r"%s\Resources\%s.fasta" %(os.path.dirname(os.path.abspath(__file__)),file_name)
    mRNA_file = open(mRNA_path_file,"r")
    string_to_find = ">%s" % host_header
    start_sequence_assembly = False
    stop_search = False
    sequence = ""

    for line in mRNA_file:
        if stop_search:
            return sequence
        if start_sequence_assembly:
                if line[0] == ">":
                    stop_search = True
                else:
                    sequence = "%s%s" % (sequence,line[:-1])
        else:
            if string_to_find in line:
                start_sequence_assembly = True
    if sequence!= "":
        return sequence

    return None # Should not get here

def get_cbr_miRNA_That_Met_threshold(query_results_cbr):
    """
    This function will add the 'is_conserved' key to the dictionaries
    :param query_results_cbr: the list of dictionaries
    :return: None
    """
    for query_res in query_results_cbr:
        pident = float(query_res['pident'])
        if  pident == 100:
            query_res['is_conserved'] = True
        else:
            query_res['is_conserved'] = False

def get_miRNA_and_host_sequences(pairs,miRNA_flie_name,mRNA_file_name):
    """
    This function will find the sequences of all the host mRNAs and will add them to the pairs array
    :param pairs: [(miRNA,mRNA)]
    :return: [(miRNA,(mRNA,sequence))]
    """
    new_pairs = []
    leng = len(pairs)
    count = 1
    for pair in pairs:
        print("%d/%d" % (leng,count))
        count+=1
        host_header = pair[1]
        host_sequence = get_3_tag_UTR(host_header,mRNA_file_name)
        miRNA_header = pair[0]
        miRNA_sequence = get_3_tag_UTR(miRNA_header, miRNA_flie_name)
        new_pairs.append(((miRNA_header,miRNA_sequence),(host_header,host_sequence)))
    return new_pairs

def get_seed(sequence):
    """
    This function will return the seed of the sequence
    :param sequence: The sequence
    :return: The seed of the sequence
    """
    return sequence[1:8]

def is_seed_criteria_met(miRNA,mRNA):
    """
    This function will check if the seed criteria is met
    :param miRNA: The miRNA sequence
    :param mRNA: The mRNA sequence
    :return: True IFF the seed criteria is met
    """
    if mRNA == "Sequence unavailable":
        return "unknown"
    miRNA_seed = get_seed(miRNA)
    miRNA_seed = miRNA_seed.replace("U","T")
    miRNA_seq = Seq(miRNA_seed)
    miRNA_seed = miRNA_seq.reverse_complement()
    return miRNA_seed._data in mRNA

def is_seed_criteria_met_in_pairs(pairs):
    """
    This function will return a dictionary that contains weather the seed criteria is met.
    This process occurs for every pair in the pairs' list
    :param pairs: The given pairs list
    :return: A dictionary that contains weather the seed criteria is met.
    """
    res = []
    for pair in pairs:
        dictionary = {}
        miRNA_seq = pair[0][1]
        mRNA_seq = pair[1][1]
        is_target = is_seed_criteria_met(miRNA_seq,mRNA_seq)
        dictionary["miRNA_name"] = pair[0][0]
        dictionary["miRNA_seq"] = pair[0][1]
        dictionary["Host_name"] = pair[1][0]
        dictionary["Host_seq"] = pair[1][1]
        dictionary["is_target"] = is_target
        res.append(dictionary)
    return res

def parse_results_to_csv(query_results):
    """
    This function will parse the results and save them in a csv file name 'results.csv'
    :param query_results: The given data to save
    :return: None
    """
    with open('results.csv', 'w') as file:
        file.write("")
    with open('results.csv','a') as file:
        header = ""
        for key in query_results[0].keys():
            header = "%s%s," % (header,key)
        header = "%s\n" % header
        file.write(header)

    for parse_dictionary in query_results:
        with open('results.csv','a') as f:
            line = ""
            for key in parse_dictionary.keys():
                line = "%s%s," % (line, parse_dictionary[key])
            line = "%s\n" % line
            f.write(line)

def get_all_cell_dictionaries(path_cel,path_cel_pre):
    """
    This function will return all the C.elegans miRNA's
    :param path_cel: The path to the C.elegans miRNA's files
    :param path_cel_pre: The path to the pre-mature C.elegans miRNA's files
    :return: A dictionary containing all the C.elegans miRNA's
    """
    cel_file = open(path_cel,'r')

    all_cell_dictionary = []
    odd = True
    name = None
    seq = None
    for line in cel_file:
        if odd:
            name = line[1:-1]
            odd = False
        else:
            cell_dictionary = {}
            seq = line[:-1]
            odd = True
            cell_dictionary['C.elegans mature name'] = name
            cell_dictionary['C.elegans mature sequence'] = seq
            all_cell_dictionary.append(cell_dictionary)

    odd = True
    name = None
    seq = None
    cel_file_pre = open(path_cel_pre, 'r')
    all_cell_pre_dictionary = []
    for line in cel_file_pre:
        if odd:
            name = line[1:-1]
            odd = False
        else:
            cell_dictionary = {}
            seq = line[:-1]
            odd = True
            cell_dictionary['C.elegans pre-miRNA name'] = name
            cell_dictionary['C.elegans pre-mRNA sequence'] = seq
            all_cell_pre_dictionary.append(cell_dictionary)

    combined = []

    for i in range(len(all_cell_dictionary)):
        for j in range(len(all_cell_pre_dictionary)):
            pre_name = all_cell_pre_dictionary[j]['C.elegans pre-miRNA name']
            pre_seq = all_cell_pre_dictionary[j]['C.elegans pre-mRNA sequence']
            cel_name = all_cell_dictionary[i]['C.elegans mature name']
            cel_seq = all_cell_dictionary[i]['C.elegans mature sequence']
            if pre_name[:pre_name.rindex('_')] == cel_name[:cel_name.rindex('_')]:
                dict = {}
                dict['C.elegans pre-miRNA name'] = pre_name
                dict['C.elegans pre-miRNA sequence'] = pre_seq
                dict['C.elegans mature name'] = cel_name
                dict['C.elegans mature sequence'] = cel_seq
                combined.append(dict)

    return combined

def add_host_data(all_cell_dictionary, final_pairs_mRNA):
    """
    This function will add the host data to the given cel dictionary
    :param all_cell_dictionary: The cell dictionary
    :param final_pairs_mRNA: The host data
    :return: None
    """
    for i in range(len(all_cell_dictionary)):
        cell_dictionary = all_cell_dictionary[i]
        name = cell_dictionary['C.elegans mature name']
        host_exists = False
        for j in range(len(final_pairs_mRNA)):
            if final_pairs_mRNA[j]["miRNA_name"] == name:
                host_exists = True
                host_name = final_pairs_mRNA[j]["Host_name"]
                is_target = final_pairs_mRNA[j]["is_target"]
                cell_dictionary["Host gene name"] = host_name
                if is_target == True:
                    cell_dictionary["Targets the host gene"] = 'yes'
                elif is_target == False:
                    cell_dictionary["Targets the host gene"] = 'no'
                else:
                    cell_dictionary["Targets the host gene"] = 'unknown'
        if not host_exists:
            cell_dictionary["Host gene name"] = "-"
            cell_dictionary["Targets the host gene"] = '-'

def add_cbr_data(all_cell_dictionary, query_results_cbr):
    """
    This function will add the C.briggsae data to the given cel dictionary
    :param all_cell_dictionary: The cell dictionary
    :param query_results_cbr: The C.briggsae data
    :return: None
    """
    for i in range(len(all_cell_dictionary)):
        cell_dictionary = all_cell_dictionary[i]
        name = cell_dictionary['C.elegans mature name']
        cbr_exists = False
        for j in range(len(query_results_cbr)):
            if query_results_cbr[j]["qseqid"] == name:
                cbr_exists = True
                cbr_name = query_results_cbr[j]["sseqid"]
                if query_results_cbr[j]["is_conserved"]:
                    cell_dictionary["Conserved in C.briggsae"] = cbr_name
                else:
                    cell_dictionary["Conserved in C.briggsae"] = False
        if not cbr_exists:
            cell_dictionary["Conserved in C.briggsae"] = "-"

if __name__ == "__main__":

    path_mRNA = "%s\%s" %(os.path.dirname(os.path.abspath(__file__)),r"Resources\res_blastn_compact_mRNA.fasta")
    path_cbr = "%s\%s" %(os.path.dirname(os.path.abspath(__file__)),r"Resources\res_blastn_compact_cbr.fasta")
    path_cel = "%s\%s" %(os.path.dirname(os.path.abspath(__file__)),r"Resources\cel.fasta")
    path_cel_pre = "%s\%s" %(os.path.dirname(os.path.abspath(__file__)),r"Resources\cel-pre.fasta")

    print("parsing query result")
    query_results_mRNA = parse_query_results(path_mRNA)
    query_results_cbr = parse_query_results(path_cbr)

    print("get pairs")
    pairs_mRNA = get_pairs(query_results_mRNA)
    get_cbr_miRNA_That_Met_threshold(query_results_cbr)

    print("get host")
    new_pairs_mRNA = get_miRNA_and_host_sequences(pairs_mRNA,"cel","mRNA")

    print("Updating seed criteria")
    final_pairs_mRNA = is_seed_criteria_met_in_pairs(new_pairs_mRNA)

    print("Gathering data")
    all_cell_dictionary = get_all_cell_dictionaries(path_cel,path_cel_pre)
    add_host_data(all_cell_dictionary,final_pairs_mRNA)
    add_cbr_data(all_cell_dictionary,query_results_cbr)
    parse_results_to_csv(all_cell_dictionary)


from wiredtiger import stat
from wtdataset import SimpleDataSet
from wtscenario import make_scenarios
from rollback_to_stable_util import test_rollback_to_stable_base

def mod_val(value, char, location, nbytes=1):
    return value[0:location] + char + value[location+nbytes:]

# test_rollback_to_stable04.py
# Test that rollback to stable always replaces the on-disk value with a full update
# from the history store.
class test_rollback_to_stable04(test_rollback_to_stable_base):

    format_values = [
        ('column', dict(key_format='r', value_format='S')),
        ('column_fix', dict(key_format='r', value_format='8t')),
        ('row_integer', dict(key_format='i', value_format='S')),
    ]

    in_memory_values = [
        ('no_inmem', dict(in_memory=False)),
        ('inmem', dict(in_memory=True))
    ]

    prepare_values = [
        ('no_prepare', dict(prepare=False)),
        ('prepare', dict(prepare=True))
    ]

    dryrun_values = [
        ('no_dryrun', dict(dryrun=False)),
        ('dryrun', dict(dryrun=True))
    ]

    evict = [
        ('no_evict', dict(evict=False)),
        ('evict', dict(evict=True))
    ]

    scenarios = make_scenarios(format_values, in_memory_values, prepare_values, dryrun_values, evict)
    def conn_config(self):
        config = 'cache_size=500MB,statistics=(all),verbose=(rts:5)'
        if self.in_memory:
            config += ',in_memory=true'
        return config

    def test_rollback_to_stable(self):
        nrows = 1000

        # Create a table.
        uri = "table:rollback_to_stable04"
        ds_config = ',log=(enabled=false)' if self.in_memory else ''
        ds = SimpleDataSet(self, uri, 0,
            key_format=self.key_format, value_format=self.value_format, config=ds_config)
        ds.populate()

        if self.value_format == '8t':
            value_a = 97 # 'a'
            value_b = 98 # 'b'
            value_c = 99 # 'c'
            value_d = 100 # 'd'

            # No modifies in FLCS; do ordinary updates instead.
            value_modQ = 81 # 'Q'
            value_modR = 82 # 'R'
            value_modS = 83 # 'S'
            value_modT = 84 # 'T'
            value_modW = 87 # 'W'
            value_modX = 88 # 'X'
            value_modY = 89 # 'Y'
            value_modZ = 90 # 'Z'
        else:
            value_a = "aaaaa" * 100
            value_b = "bbbbb" * 100
            value_c = "ccccc" * 100
            value_d = "ddddd" * 100

            value_modQ = mod_val(value_a, 'Q', 0)
            value_modR = mod_val(value_modQ, 'R', 1)
            value_modS = mod_val(value_modR, 'S', 2)
            value_modT = mod_val(value_c, 'T', 3)
            value_modW = mod_val(value_d, 'W', 4)
            value_modX = mod_val(value_a, 'X', 5)
            value_modY = mod_val(value_modX, 'Y', 6)
            value_modZ = mod_val(value_modY, 'Z', 7)

        # Pin oldest and stable to timestamp 10.
        self.conn.set_timestamp('oldest_timestamp=' + self.timestamp_str(10) +
            ',stable_timestamp=' + self.timestamp_str(10))

        # Perform a combination of modifies and updates.
        self.large_updates(uri, value_a, ds, nrows, self.prepare, 20)
        self.large_modifies(uri, 'Q', ds, 0, 1, nrows, self.prepare, 30)
        self.large_modifies(uri, 'R', ds, 1, 1, nrows, self.prepare, 40)
        self.large_modifies(uri, 'S', ds, 2, 1, nrows, self.prepare, 50)

        # Evict the pages to disk
        if self.evict:
            self.evict_cursor(uri, nrows, value_modS)

        self.large_updates(uri, value_b, ds, nrows, self.prepare, 60)
        self.large_updates(uri, value_c, ds, nrows, self.prepare, 70)
        self.large_modifies(uri, 'T', ds, 3, 1, nrows, self.prepare, 80)
        self.large_updates(uri, value_d, ds, nrows, self.prepare, 90)
        self.large_modifies(uri, 'W', ds, 4, 1, nrows, self.prepare, 100)
        self.large_updates(uri, value_a, ds, nrows, self.prepare, 110)
        self.large_modifies(uri, 'X', ds, 5, 1, nrows, self.prepare, 120)
        self.large_modifies(uri, 'Y', ds, 6, 1, nrows, self.prepare, 130)
        self.large_modifies(uri, 'Z', ds, 7, 1, nrows, self.prepare, 140)

        # Verify data is visible and correct.
        self.check(value_a, uri, nrows, None, 21 if self.prepare else 20)
        self.check(value_modQ, uri, nrows, None, 31 if self.prepare else 30)
        self.check(value_modR, uri, nrows, None, 41 if self.prepare else 40)
        self.check(value_modS, uri, nrows, None, 51 if self.prepare else 50)
        self.check(value_b, uri, nrows, None, 61 if self.prepare else 60)
        self.check(value_c, uri, nrows, None, 71 if self.prepare else 70)
        self.check(value_modT, uri, nrows, None, 81 if self.prepare else 80)
        self.check(value_d, uri, nrows, None, 91 if self.prepare else 90)
        self.check(value_modW, uri, nrows, None, 101 if self.prepare else 100)
        self.check(value_a, uri, nrows, None, 111 if self.prepare else 110)
        self.check(value_modX, uri, nrows, None, 121 if self.prepare else 120)
        self.check(value_modY, uri, nrows, None, 131 if self.prepare else 130)
        self.check(value_modZ, uri, nrows, None, 141 if self.prepare else 140)

        # Pin stable to timestamp 40 if prepare otherwise 30.
        if self.prepare:
            self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(40))
        else:
            self.conn.set_timestamp('stable_timestamp=' + self.timestamp_str(30))

        # Checkpoint to ensure the data is flushed, then rollback to the stable timestamp.
        if not self.in_memory:
            self.session.checkpoint()
        self.conn.rollback_to_stable('dryrun={}'.format('true' if self.dryrun else 'false'))

        # Check that the correct data is seen at and after the stable timestamp.
        self.check(value_modQ, uri, nrows, None, 30)
        if self.dryrun:
            self.check(value_modZ, uri, nrows, None, 150)
            self.check(value_a, uri, nrows, None, 20)
        else:
            self.check(value_modQ, uri, nrows, None, 150)
            self.check(value_a, uri, nrows, None, 20)

        stat_cursor = self.session.open_cursor('statistics:', None, None)
        calls = stat_cursor[stat.conn.txn_rts][2]
        hs_removed = stat_cursor[stat.conn.txn_rts_hs_removed][2]
        hs_removed_dryrun = stat_cursor[stat.conn.txn_rts_hs_removed_dryrun][2]
        hs_sweep = stat_cursor[stat.conn.txn_rts_sweep_hs_keys][2]
        hs_sweep_dryrun = stat_cursor[stat.conn.txn_rts_sweep_hs_keys_dryrun][2]
        keys_removed = stat_cursor[stat.conn.txn_rts_keys_removed][2]
        keys_restored = stat_cursor[stat.conn.txn_rts_keys_restored][2]
        pages_visited = stat_cursor[stat.conn.txn_rts_pages_visited][2]
        upd_aborted = stat_cursor[stat.conn.txn_rts_upd_aborted][2]
        upd_aborted_dryrun = stat_cursor[stat.conn.txn_rts_upd_aborted_dryrun][2]
        stat_cursor.close()

        self.assertEqual(calls, 1)
        self.assertEqual(keys_removed, 0)
        self.assertEqual(keys_restored, 0)
        self.assertGreater(pages_visited, 0)
        if self.dryrun:
            self.assertEqual(upd_aborted + hs_removed + hs_sweep, 0)
            self.assertGreaterEqual(upd_aborted_dryrun + hs_removed_dryrun + hs_sweep_dryrun, nrows * 11)
        elif self.in_memory:
            self.assertEqual(upd_aborted, nrows * 11)
            self.assertEqual(hs_removed + hs_sweep, 0)
            self.assertEqual(upd_aborted_dryrun + hs_removed_dryrun + hs_sweep_dryrun, 0)
        else:
            self.assertGreaterEqual(upd_aborted + hs_removed + hs_sweep, nrows * 11)
            self.assertEqual(upd_aborted_dryrun + hs_removed_dryrun + hs_sweep_dryrun, 0)

if __name__ == '__main__':
    wttest.run()


import ismrmrd
import os
import itertools
import logging
import numpy as np
import numpy.fft as fft
import ctypes
import mrdhelper
from datetime import datetime

# Folder for debug output files
debugFolder = "/tmp/share/debug"

def groups(iterable, predicate):
    group = []
    for item in iterable:
        group.append(item)

        if predicate(item):
            yield group
            group = []

def conditionalGroups(iterable, predicateAccept, predicateFinish):
    group = []
    try:
        for item in iterable:
            if item is None:
                break

            if predicateAccept(item):
                group.append(item)

            if predicateFinish(item):
                yield group
                group = []
    finally:
        iterable.send_close()

def process(connection, config, metadata):
    logging.info("Config: \n%s", config)
    logging.info("Metadata: \n%s", metadata)

    # Discard phase correction lines and accumulate lines until "ACQ_LAST_IN_SLICE" is set
    for group in conditionalGroups(connection, lambda acq: not acq.is_flag_set(ismrmrd.ACQ_IS_PHASECORR_DATA), lambda acq: acq.is_flag_set(ismrmrd.ACQ_LAST_IN_SLICE)):
        image = process_group(group, config, metadata)

        logging.debug("Sending image to client:\n%s", image)
        connection.send_image(image)

def process_group(group, config, metadata):
    # Create folder, if necessary
    if not os.path.exists(debugFolder):
        os.makedirs(debugFolder)
        logging.debug("Created folder " + debugFolder + " for debug output files")

    # Format data into single [cha RO PE] array
    data = [acquisition.data for acquisition in group]
    data = np.stack(data, axis=-1)

    logging.debug("Raw data is size %s" % (data.shape,))
    np.save(debugFolder + "/" + "raw.npy", data)

    # Fourier Transform
    data = fft.fftshift(data, axes=(1, 2))
    data = fft.ifft2(data)
    data = fft.ifftshift(data, axes=(1, 2))

    # Sum of squares coil combination
    data = np.abs(data)
    data = np.square(data)
    data = np.sum(data, axis=0)
    data = np.sqrt(data)

    logging.debug("Image data is size %s" % (data.shape,))
    np.save(debugFolder + "/" + "img.npy", data)

    # Normalize and convert to int16
    data *= 32767/data.max()
    data = np.around(data)
    data = data.astype(np.int16)

    # Remove phase oversampling
    nRO = np.size(data,0)
    data = data[int(nRO/4):int(nRO*3/4),:]
    logging.debug("Image without oversampling is size %s" % (data.shape,))
    np.save(debugFolder + "/" + "imgCrop.npy", data)

    # Format as ISMRMRD image data
    image = ismrmrd.Image.from_array(data, acquisition=group[0])
    image.image_index = 1

    # Set field of view
    image.field_of_view = (ctypes.c_float(metadata.encoding[0].reconSpace.fieldOfView_mm.x),
                            ctypes.c_float(metadata.encoding[0].reconSpace.fieldOfView_mm.y),
                            ctypes.c_float(metadata.encoding[0].reconSpace.fieldOfView_mm.z))

    # Set ISMRMRD Meta Attributes
    meta = ismrmrd.Meta({'DataRole':               'Image',
                         'ImageProcessingHistory': ['FIRE', 'PYTHON'],
                         'WindowCenter':           '16384',
                         'WindowWidth':            '32768'})

    # Add image orientation directions to MetaAttributes if not already present
    if meta.get('ImageRowDir') is None:
        meta['ImageRowDir'] = ["{:.18f}".format(image.getHead().read_dir[0]), "{:.18f}".format(image.getHead().read_dir[1]), "{:.18f}".format(image.getHead().read_dir[2])]

    if meta.get('ImageColumnDir') is None:
        meta['ImageColumnDir'] = ["{:.18f}".format(image.getHead().phase_dir[0]), "{:.18f}".format(image.getHead().phase_dir[1]), "{:.18f}".format(image.getHead().phase_dir[2])]

    xml = meta.serialize()
    logging.debug("Image MetaAttributes: %s", xml)
    logging.debug("Image data has %d elements", image.data.size)

    image.attribute_string = xml
    return image


import streamlit as st
import base64
import os
from nbanalyzer import *
from PIL import Image
import time

script_directory = os.getcwd()
PROGRESS_BAR_CUSTOM_COLOR = '#f63366'

ordinal = lambda n: "%d%s" % (n,"tsnrhtdd"[(n//10%10!=1)*(n%10<4)*n%10::4])

def load_data(year: int, stat_type: str):
    if stat_type == 'play-by-play':
        return get_players_data(year, stat_type, 1)
    elif stat_type == 'advanced_box_score':
        return get_advanced_metrics(year)

    return get_players_data(year, stat_type, 0)

def filedownload(df):
    csv = df.to_csv(index=False)
    b64 = base64.b64encode(csv.encode()).decode()  # strings <-> bytes conversions
    href = f'Download CSV File'
    return href

def translate_stat_type(stat_type):
    if stat_type == 'per_game':
        return 'Per Game'
    elif stat_type == 'totals':
        return 'Total'
    elif stat_type == 'per_minute':
        return 'Per 36 Minutes'
    elif stat_type == 'advanced':
        return 'Advanced'
    elif stat_type == 'per_poss':
        return 'Per 100 Possessions'
    elif stat_type == 'play-by-play':
        return 'Play-by-Play'
    elif stat_type == 'advanced_box_score':
        return 'Advanced Box Score'
    return 'None'

def main():
    st.set_option('deprecation.showPyplotGlobalUse', False)
    icon = Image.open(os.path.join(script_directory, 'favicon.ico'))
    st.set_page_config('NBA Stats Explorer', icon)

    st.markdown(' ' ,
        unsafe_allow_html=True)
    st.title('NBA Stats Explorer')

    st.markdown("""
      This app performs simple webscraping of NBA player stats data!
    * **Python libraries:** base64, matplotlib, pandas, plotly, streamlit
    * **Data source:** [Basketball-reference.com](https://www.basketball-reference.com/).
    """)

    st.sidebar.header('User Input Features')
    selected_year = st.sidebar.selectbox('Year', list(reversed(range(1977,2023))))
    selected_stat = st.sidebar.selectbox('Player Stats', STAT_TYPES, format_func=translate_stat_type)
    playerstats = load_data(selected_year, selected_stat)

    # Sidebar - Team selection
    sorted_unique_team = sorted(playerstats.Tm.unique())
    selected_team = st.sidebar.multiselect('Team', sorted_unique_team, sorted_unique_team)

    # Sidebar - Position selection
    unique_pos = ['C','PF','SF','PG','SG']
    selected_pos = st.sidebar.multiselect('Position', unique_pos, unique_pos)

    # Filtering data
    df_selected_team = playerstats[(playerstats.Tm.isin(selected_team)) & (playerstats.Pos.isin(selected_pos))]

    st.header('Displaying Players\' ' + translate_stat_type(selected_stat) + ' Stats of Selected Team(s)')
    st.write('Data Dimension: ' + str(df_selected_team.shape[0]) + ' rows and ' + str(df_selected_team.shape[1]) + ' columns.')
    st.dataframe(df_selected_team)
    st.markdown(filedownload(df_selected_team), unsafe_allow_html=True)

    if selected_year < 2022:
        best_players = get_mvp_voting(selected_year, 5)
    else:
        best_players = ['Nikola Jokić', 'Joel Embiid', 'Chris Paul', 'Stephen Curry', 'Kevin Durant', 'Giannis Antetokounmpo',
            'Ja Morant', 'Luka Dončić', 'Devin Booker', 'DeMar DeRozan', 'Jimmy Butler']

    with st.spinner('Loading season summary...'):
        st.header(f'{selected_year} Season Summary')
        st.write(f"""
            The {selected_year} season was the {ordinal(selected_year - 1946)} of the [National Basketball Association](https://en.wikipedia.org/wiki/National_Basketball_Association).
            As usual, we have to analyze its vast data and explore player performances to decide which players performed the best!
        """)

        if selected_year < 2022:
            with st.expander(f'{selected_year} NBA MVP'):
                st.write(f"""
                    ### MVP
                    This season's MVP was **{best_players[0]}** who won the prize against the likes of {best_players[1]}, {best_players[2]}
                    and {best_players[3]}.
                """)

        with st.expander(f'Intercorrelation Matrix Heatmap - {selected_year}'):
            st.markdown("""
                ### Intercorrelation Matrix Heatmap
                The matrix is calculated from a cross-tabulation and shows how statistically similar all pairs of variables are in their
                distributions across the various samples. The table below shows the intercorrelations between per game player stats.
            """)
            with st.spinner('Loading heatmap...'):
                draw_intercorrelation_heatmap(selected_year)
                st.pyplot()

        with st.expander(f'Scoring - {selected_year}'):
            st.markdown("""
                ### Points per 75 possessions x TS% Scatter Plot
                The scatter plot is used to analyze the relation between \"inflation adjusted\" scoring and efficiency from players across the league.
            """)
            with st.spinner('Loading scatter plot'):
                st.write(gen_scoring_efficiency_plot(selected_year, best_players))

        if selected_year >= 1980:
            with st.expander(f'Shooting - {selected_year}'):
                st.markdown("""
                    ### 3-Point Attempts x 3P% Scatter Plot
                    The scatter plot is used to analyze the relation between 3-Point Field Goal attempts per 100 possessions and 3-Point Field Goal
                    Percentage from players across the league as well as observe the evolution of shooting along the decades.
                """)
                with st.spinner('Loading scatter plot'):
                    st.write(gen_shooting_efficiency_plot(selected_year))

            with st.expander(f'Playmaking - {selected_year}'):
                st.markdown("""
                    ### Offensive Load x Box Creation Scatter Plot
                    The scatter plot is used to analyze the relation between a per 100 estimate of the number of true shots created for teammates and
                    the percentage of possessions a player is directly or indirectly involved in a true shooting attempt, or commits a turnover.
                """)
                with st.spinner('Loading scatter plot'):
                    st.write(gen_playmaking_plot(selected_year))

            with st.expander('Player Finder'):
                st.markdown("""
                    ### Player Finder
                    Player Finder is a tool to explore the database and see how specific players are performing relative to the league in 5 major categories
                    **Scoring, Efficiency, Shooting, Creation and Load**. Try it out and see how your favorite NBA star is doing :triumph::basketball:.
                """)
                st.markdown(f"""

                """, unsafe_allow_html=True)
                advanced_box_score = get_advanced_metrics(selected_year)
                selected_player = st.selectbox('Player Name', advanced_box_score['Player'])

                showed_name = False

                if selected_player != '':
                    with st.spinner('Loading player summary'):
                        for stat in ADVANCED_BOX_SCORE_COLS[3:]:
                            result = get_player_percentile_from_advanced_stat(advanced_box_score, selected_player, stat)
                            if result.empty:
                                break
                            if not showed_name:
                                player_name = result.iloc[0]['Player']
                                st.markdown(f'#### {player_name} {selected_year} Summary')
                                showed_name = True
                            player_stat = int(result.iloc[0][stat] * 100)
                            st.markdown(f'{stat} - {ordinal(player_stat)} Percentile')
                            st.progress(player_stat)

        if selected_year >= 1997:
            with st.expander(f'Impact - {selected_year}'):
                st.markdown("""
                    ### Impact metrics
                    Impact metrics are used to measure a player's impact on the success of a given team. In this selection:
                    * **On-Off**: Average difference between the Plus/Minus when player is on the court vs. off the court.
                    * **OnCourt**: Plus/Minus Per 100 Possessions (On Court only).
                    * **BPM**: A box score estimate of the points per 100 possessions a player contributed above a league-average player, translated to an average team.
                """)
                st.write(gen_on_off_plot(selected_year, best_players))

if __name__ == '__main__':
    main()


from base.game_2048 import game_2048
import copy

class game_2048_power_state_custom_score(game_2048):
    def get_state(self):
        state = self.board.flatten()
        powers_state = []
        for el in state:
            power = 0
            while el > 1:
                power += 1
                el /= 2
            powers_state.append(power)

        # set the state to be used in get_score
        return powers_state

    def get_score(self, with_potential=True):
        if not with_potential:
            return self.score

        # Worked really really really bad with this :)
        # if self.is_game_over():
        #     return self.board.max() - 2048

        potential = 0
        for i in range(0, 4):  # 4 possible moves
            game_clone = copy.copy(self)
            game_clone.do_game_round(i)
            # potential += game_clone.get_score(with_potential=False) - self.score
            potential = max(potential, game_clone.get_score(with_potential=False) - self.score)

        # Divide by for because
        # 1. Divide 2 because the potential is calculated twice (for both opposite directions)
        # for example: up and down (cam do both moves if one is possible)

        return potential // 2  # A bit bad too so
        # return self.score + potential // 2


import os.path
import warnings
from collections import defaultdict
from itertools import chain

from . import builtin
from .. import options as opts
from .file_types import static_file
from .path import relname
from ..backends.compdb import writer as compdb
from ..backends.make import writer as make
from ..backends.ninja import writer as ninja
from ..build_inputs import build_input, Edge
from ..exceptions import ToolNotFoundError
from ..file_types import *
from ..iterutils import (first, flatten, iterate, listify, slice_dict, uniques,
                         unlistify)
from ..languages import known_formats
from ..objutils import convert_each, convert_one
from ..platforms import known_native_object_formats
from ..shell import posix as pshell

build_input('link_options')(lambda: {
    'dynamic': defaultdict(list), 'static': defaultdict(list)
})

class Link(Edge):
    msbuild_output = True
    extra_kwargs = ()

    def __init__(self, context, name, files, libs, packages, link_options,
                 lang=None, extra_deps=None, description=None):
        build = context.build
        name = relname(context, name)
        self.name = self.__name(name)

        self.user_libs = libs
        forward_opts = opts.ForwardOptions.recurse(self.user_libs)
        self.libs = self.user_libs + forward_opts.libs

        self.user_packages = packages
        self.packages = self.user_packages + forward_opts.packages

        self.user_files = files
        self.files = self.user_files + flatten(
            getattr(i, 'extra_objects', []) for i in self.user_files
        )

        if ( len(self.files) == 0 and
             not any(isinstance(i, WholeArchive) for i in self.user_libs) ):
            raise ValueError('need at least one source file')

        self.user_options = link_options

        formats = uniques(i.format for i in chain(self.files, self.libs,
                                                  self.packages))
        if len(formats) > 1:
            raise ValueError('cannot link multiple object formats')
        self.format = formats[0]

        self.input_langs = uniques(chain(
            (i.lang for i in self.files if i.lang is not None),
            (j for i in self.libs for j in iterate(i.lang))
        ))
        if not lang and not self.input_langs:
            raise ValueError('unable to determine language')

        self.langs = [lang] if lang else self.input_langs
        self.linker = self.__find_linker(context.env, formats[0], self.langs)

        # Forward any necessary options to the compile step.
        if hasattr(self.linker, 'compile_options'):
            compile_opts = self.linker.compile_options(self)
        else:
            compile_opts = opts.option_list()
        compile_opts.extend(forward_opts.compile_options)
        for i in self.files:
            if hasattr(i.creator, 'add_extra_options'):
                i.creator.add_extra_options(compile_opts)

        extra_options = self.linker.pre_output(context, name, self)
        self._fill_options(context.env, extra_options, forward_opts)

        output = self.linker.output_file(name, self)
        primary = first(output)

        primary.package_deps.extend(self.packages)
        self._fill_output(output)

        options = self.options
        public_output = self.linker.post_output(context, options, output, self)
        primary.post_install = self.linker.post_install(options, output, self)

        super().__init__(build, output, public_output, extra_deps, description)
        build['defaults'].add(self.public_output)

    @classmethod
    def convert_args(cls, context, name, files, kwargs):
        lang = kwargs.get('lang')

        convert_each(kwargs, 'libs', context['library'],
                     kind=cls._preferred_lib, lang=lang)
        convert_each(kwargs, 'packages', context['package'], lang=lang)

        kwargs['link_options'] = pshell.listify(kwargs.get('link_options'),
                                                type=opts.option_list)

        intdir = ('{}.int/'.format(cls.__name(name))
                  if context.build['project']['intermediate_dirs'] else None)
        intdir = kwargs.pop('intermediate_dir', intdir)

        files = context['object_files'](
            files, includes=kwargs.pop('includes', None),
            pch=kwargs.pop('pch', None),
            options=kwargs.pop('compile_options', None),
            libs=kwargs['libs'], packages=kwargs['packages'], lang=lang,
            directory=intdir,
            extra_deps=kwargs.pop('extra_compile_deps', None)
        )

        return files, kwargs

    def _get_linkers(self, env, langs):
        yielded = False
        for i in langs:
            try:
                linker = env.builder(i).linker(self.mode)
                if linker:
                    yielded = True
                    yield linker
            except ToolNotFoundError:
                pass
        if not yielded:
            fmt = ('native' if self.format in known_native_object_formats
                   else self.format)
            src_lang = known_formats[fmt].src_lang
            yield env.builder(src_lang).linker(self.mode)

    @classmethod
    def __name(cls, name):
        head, tail = os.path.split(name)
        return os.path.join(head, cls._prefix + tail)

    def __find_linker(self, env, format, langs):
        for linker in self._get_linkers(env, langs):
            if linker.can_link(format, langs):
                return linker
        raise ValueError('unable to find linker')

class DynamicLink(Link):
    desc_verb = 'link'
    base_mode = 'dynamic'
    mode = 'executable'
    msbuild_mode = 'Application'
    _preferred_lib = 'shared'
    _prefix = ''

    extra_kwargs = ('entry_point', 'module_defs')

    def __init__(self, *args, entry_point=None, module_defs=None, **kwargs):
        self.entry_point = entry_point
        self.module_defs = module_defs
        super().__init__(*args, **kwargs)

    @classmethod
    def convert_args(cls, context, name, files, kwargs):
        convert_one(kwargs, 'module_defs', context['module_def_file'])
        return super().convert_args(context, name, files, kwargs)

    @property
    def options(self):
        return self._internal_options + self.user_options

    def flags(self, global_options=None):
        return self.linker.flags(self.options, global_options, self.raw_output)

    def lib_flags(self, global_options=None):
        return self.linker.lib_flags(self.options, global_options)

    def _fill_options(self, env, extra_options, forward_opts):
        self._internal_options = opts.option_list(
            opts.entry_point(self.entry_point) if self.entry_point else None,
            opts.module_def(self.module_defs) if self.module_defs else None
        )

        if self.linker.needs_libs:
            linkers = self._get_linkers(env, self.input_langs)
            self._internal_options.collect(
                (i.always_libs(i is self.linker) for i in linkers),
                (opts.lib(i) for i in self.libs)
            )

        if self.linker.needs_package_options:
            self._internal_options.collect(i.link_options(self.linker)
                                           for i in self.packages)

        self._internal_options.collect(extra_options,
                                       forward_opts.link_options)

    def _fill_output(self, output):
        first(output).runtime_deps.extend(
            i.runtime_file for i in self.libs if i.runtime_file
        )

class SharedLink(DynamicLink):
    desc_verb = 'shared-link'
    mode = 'shared_library'
    msbuild_mode = 'DynamicLibrary'
    _prefix = 'lib'

    extra_kwargs = DynamicLink.extra_kwargs + ('version', 'soversion')

    def __init__(self, *args, version=None, soversion=None, **kwargs):
        self.version = version
        self.soversion = soversion
        if (self.version is None) != (self.soversion is None):
            raise ValueError('specify both version and soversion or neither')
        super().__init__(*args, **kwargs)

class StaticLink(Link):
    desc_verb = 'static-link'
    base_mode = 'static'
    mode = 'static_library'
    msbuild_mode = 'StaticLibrary'
    _preferred_lib = 'static'
    _prefix = 'lib'

    extra_kwargs = ('static_link_options',)

    def __init__(self, *args, static_link_options=None, **kwargs):
        self.user_static_options = static_link_options
        super().__init__(*args, **kwargs)

    @classmethod
    def convert_args(cls, context, name, files, kwargs):
        kwargs['static_link_options'] = pshell.listify(
            kwargs.get('static_link_options'), type=opts.option_list
        )
        return super().convert_args(context, name, files, kwargs)

    @property
    def options(self):
        return self._internal_options + self.user_static_options

    def flags(self, global_options=None):
        # Only pass the static-link options to the static linker. The other
        # options are forwarded on to the dynamic linker when this library is
        # used.
        return self.linker.flags(self.options, global_options, self.raw_output)

    def _fill_options(self, env, extra_options, forward_opts):
        self._internal_options = extra_options

    def _fill_output(self, output):
        primary = first(output)
        primary.forward_opts = opts.ForwardOptions(
            link_options=self.user_options,
            libs=self.user_libs,
            packages=self.user_packages,
        )
        if hasattr(self.linker, 'forwarded_compile_options'):
            primary.forward_opts.compile_options.extend(
                self.linker.forwarded_compile_options(self)
            )

        primary.linktime_deps.extend(self.user_libs)

@builtin.function()
@builtin.type(Executable)
def executable(context, name, files=None, **kwargs):
    if files is None and 'libs' not in kwargs:
        dist = kwargs.pop('dist', True)
        params = [('format', context.env.target_platform.object_format),
                  ('lang', context.build['project']['lang'])]
        return static_file(context, Executable, name, dist, params, kwargs)
    files, kwargs = DynamicLink.convert_args(context, name, files, kwargs)
    return DynamicLink(context, name, files, **kwargs).public_output

@builtin.function()
@builtin.type(SharedLibrary, extra_in_type=DualUseLibrary)
def shared_library(context, name, files=None, **kwargs):
    if isinstance(name, DualUseLibrary):
        if files is not None or not set(kwargs.keys()) <= {'format', 'lang'}:
            raise TypeError('unexpected arguments')
        return name.shared

    if files is None and 'libs' not in kwargs:
        # XXX: What to do for pre-built shared libraries for Windows, which has
        # a separate DLL file?
        dist = kwargs.pop('dist', True)
        params = [('format', context.env.target_platform.object_format),
                  ('lang', context.build['project']['lang'])]
        return static_file(context, SharedLibrary, name, dist, params, kwargs)
    files, kwargs = SharedLink.convert_args(context, name, files, kwargs)
    return SharedLink(context, name, files, **kwargs).public_output

@builtin.function()
@builtin.type(StaticLibrary, extra_in_type=DualUseLibrary)
def static_library(context, name, files=None, **kwargs):
    if isinstance(name, DualUseLibrary):
        if files is not None or not set(kwargs.keys()) <= {'format', 'lang'}:
            raise TypeError('unexpected arguments')
        return name.static

    if files is None and 'libs' not in kwargs:
        dist = kwargs.pop('dist', True)
        params = [('format', context.env.target_platform.object_format),
                  ('lang', context.build['project']['lang'])]
        return static_file(context, StaticLibrary, name, dist, params, kwargs)
    files, kwargs = StaticLink.convert_args(context, name, files, kwargs)
    return StaticLink(context, name, files, **kwargs).public_output

@builtin.function()
@builtin.type(Library, extra_in_type=DualUseLibrary)
def library(context, name, files=None, *, kind=None, **kwargs):
    explicit_kind = False

    if kind is not None:
        explicit_kind = True
    elif context.env.library_mode.shared and context.env.library_mode.static:
        kind = 'dual'
    elif context.env.library_mode.shared:
        kind = 'shared'
    elif context.env.library_mode.static:
        kind = 'static'

    if isinstance(name, DualUseLibrary):
        if files is not None or not set(kwargs.keys()) <= {'format', 'lang'}:
            raise TypeError('unexpected arguments')
        return name if kind == 'dual' else getattr(name, kind)

    if files is None and 'libs' not in kwargs:
        dist = kwargs.pop('dist', True)
        params = [('format', context.env.target_platform.object_format),
                  ('lang', context.build['project']['lang'])]
        file_type = StaticLibrary

        if explicit_kind:
            if kind == 'shared':
                file_type = SharedLibrary
            elif kind == 'dual':
                raise ValueError(
                    "can't create dual-use libraries from an existing file"
                )

        # XXX: Try to detect if a string refers to a shared lib?
        return static_file(context, file_type, name, dist, params, kwargs)

    if kind is None:
        raise ValueError('unable to create library: both shared and static ' +
                         'modes disabled')

    shared_kwargs = slice_dict(kwargs, SharedLink.extra_kwargs)
    static_kwargs = slice_dict(kwargs, StaticLink.extra_kwargs)
    shared_kwargs.update(kwargs)
    static_kwargs.update(kwargs)

    if kind == 'dual':
        shared_files, shared_kwargs = SharedLink.convert_args(
            context, name, files, shared_kwargs
        )
        shared = SharedLink(context, name, shared_files, **shared_kwargs)
        if not shared.linker.builder.can_dual_link:
            warnings.warn('dual linking not supported with {}'
                          .format(shared.linker.brand))
            return shared.public_output

        static_files, static_kwargs = StaticLink.convert_args(
            context, name, shared_files, static_kwargs
        )
        static = StaticLink(context, name, static_files, **static_kwargs)
        return DualUseLibrary(shared.public_output, static.public_output)
    elif kind == 'shared':
        files, kw = SharedLink.convert_args(context, name, files,
                                            shared_kwargs)
        return SharedLink(context, name, files, **kw).public_output
    else:  # kind == 'static'
        files, kw = StaticLink.convert_args(context, name, files,
                                            static_kwargs)
        return StaticLink(context, name, files, **kw).public_output

@builtin.function()
@builtin.type(WholeArchive, extra_in_type=StaticLibrary)
def whole_archive(context, name, *args, **kwargs):
    if isinstance(name, StaticLibrary):
        if len(args) or len(kwargs):
            raise TypeError('unexpected arguments')
        return WholeArchive(name)
    else:
        return WholeArchive(context['static_library'](name, *args, **kwargs))

@builtin.function()
def global_link_options(context, options, family='native', mode='dynamic'):
    for i in iterate(family):
        context.build['link_options'][mode][i].extend(pshell.listify(options))

def _get_flags(backend, rule, build_inputs, buildfile):
    variables = {}
    cmd_kwargs = {}

    linker = rule.linker
    if hasattr(linker, 'flags_var') or hasattr(linker, 'libs_var'):
        gopts = build_inputs['link_options'][rule.base_mode][linker.family]

    if hasattr(linker, 'flags_var'):
        global_ldflags, ldflags = backend.flags_vars(
            linker.flags_var,
            linker.global_flags + linker.flags(gopts, mode='global'),
            buildfile
        )
        cmd_kwargs['flags'] = ldflags
        flags = rule.flags(gopts)
        if flags:
            variables[ldflags] = [global_ldflags] + flags

    if hasattr(linker, 'libs_var'):
        global_ldlibs, ldlibs = backend.flags_vars(
            linker.libs_var,
            linker.global_libs + linker.lib_flags(gopts, mode='global'),
            buildfile
        )
        cmd_kwargs['libs'] = ldlibs
        lib_flags = rule.lib_flags(gopts)
        if lib_flags:
            variables[ldlibs] = [global_ldlibs] + lib_flags

    if hasattr(rule, 'manifest'):
        var = backend.var('manifest')
        cmd_kwargs['manifest'] = var
        variables[var] = rule.manifest

    return variables, cmd_kwargs

@make.rule_handler(StaticLink, DynamicLink, SharedLink)
def make_link(rule, build_inputs, buildfile, env):
    linker = rule.linker
    variables, cmd_kwargs = _get_flags(make, rule, build_inputs, buildfile)

    output_params = []
    if linker.num_outputs == 'all':
        output_vars = make.qvar('@')
    else:
        output_vars = []
        for i in range(linker.num_outputs):
            v = make.var(str(i + 2))
            output_vars.append(v)
            output_params.append(rule.output[i])

    recipename = make.var('RULE_{}'.format(linker.rule_name.upper()))
    if not buildfile.has_variable(recipename):
        buildfile.define(recipename, [linker(
            make.var('1'), output_vars, **cmd_kwargs
        )])

    files = rule.files
    if hasattr(linker, 'transform_input'):
        files = linker.transform_input(files)

    package_build_deps = flatten(i.deps for i in rule.packages)
    module_defs = listify(getattr(rule, 'module_defs', None))
    manifest = listify(getattr(rule, 'manifest', None))
    make.multitarget_rule(
        build_inputs, buildfile,
        targets=rule.output,
        deps=(rule.files + rule.libs + package_build_deps + module_defs +
              manifest + rule.extra_deps),
        order_only=make.directory_deps(rule.output),
        recipe=make.Call(recipename, files, *output_params),
        variables=variables
    )

@ninja.rule_handler(StaticLink, DynamicLink, SharedLink)
def ninja_link(rule, build_inputs, buildfile, env):
    linker = rule.linker
    variables, cmd_kwargs = _get_flags(ninja, rule, build_inputs, buildfile)
    if rule.description:
        variables['description'] = rule.description

    if linker.num_outputs == 'all':
        output_vars = ninja.var('out')
    elif linker.num_outputs == 1:
        output_vars = ninja.var('output')
        variables[output_vars] = rule.output[0]
    else:
        output_vars = []
        for i in range(linker.num_outputs):
            v = ninja.var('output{}'.format(i + 1))
            output_vars.append(v)
            variables[v] = rule.output[i]

    if hasattr(linker, 'transform_input'):
        input_var = ninja.var('input')
        variables[input_var] = linker.transform_input(rule.files)
    else:
        input_var = ninja.var('in')

    if not buildfile.has_rule(linker.rule_name):
        buildfile.rule(name=linker.rule_name, command=linker(
            input_var, output_vars, **cmd_kwargs
        ), description=rule.desc_verb + ' => ' + first(output_vars))

    package_build_deps = flatten(i.deps for i in rule.packages)
    module_defs = listify(getattr(rule, 'module_defs', None))
    manifest = listify(getattr(rule, 'manifest', None))
    buildfile.build(
        output=rule.output,
        rule=linker.rule_name,
        inputs=rule.files,
        implicit=(rule.libs + package_build_deps + module_defs + manifest +
                  rule.extra_deps),
        variables=variables
    )

@compdb.rule_handler(StaticLink, DynamicLink, SharedLink)
def compdb_link(rule, build_inputs, buildfile, env):
    linker = rule.linker
    cmd_kwargs = {}

    if hasattr(linker, 'flags_var') or hasattr(linker, 'libs_var'):
        gopts = build_inputs['link_options'][rule.base_mode][linker.family]
    if hasattr(linker, 'flags_var'):
        cmd_kwargs['flags'] = (linker.global_flags +
                               linker.flags(gopts, mode='global') +
                               rule.flags(gopts))
    if hasattr(linker, 'libs_var'):
        cmd_kwargs['libs'] = (linker.global_libs +
                              linker.lib_flags(gopts, mode='global') +
                              rule.lib_flags(gopts))
    if hasattr(rule, 'manifest'):
        cmd_kwargs['manifest'] = rule.manifest

    file = rule.files[0] if len(rule.files) else rule.user_libs[0]
    in_files = rule.files
    if hasattr(linker, 'transform_input'):
        in_files = linker.transform_input(in_files)
    output = unlistify(rule.output if linker.num_outputs == 'all'
                       else rule.output[0:linker.num_outputs])
    buildfile.append(
        arguments=linker(in_files, output, **cmd_kwargs),
        file=file, output=first(rule.public_output)
    )

try:
    from .compile import CompileHeader
    from ..backends.msbuild import writer as msbuild

    def _parse_compiler_cflags(compiler, global_options):
        return compiler.parse_flags(msbuild.textify_each(
            compiler.global_flags +
            compiler.flags(global_options[compiler.lang], mode='global')
        ))

    def _parse_file_cflags(file, global_options, include_compiler=False):
        compiler = file.creator.compiler
        gopts = global_options[compiler.lang]
        cflags = file.creator.flags(gopts)
        if include_compiler:
            cflags = (compiler.global_flags +
                      compiler.flags(gopts, mode='global') +
                      cflags)

        return compiler.parse_flags(msbuild.textify_each(cflags))

    def _parse_ldflags(rule, global_options):
        linker = rule.linker
        gopts = global_options[rule.base_mode][linker.family]
        primary = first(rule.output)

        ldflags = [linker.global_flags + linker.flags(gopts) +
                   rule.flags(gopts)]
        if hasattr(rule.linker, 'libs_var'):
            ldflags.append(linker.global_libs + linker.lib_flags(gopts) +
                           rule.lib_flags(gopts))

        link_options = linker.parse_flags(
            *[msbuild.textify_each(i) for i in ldflags]
        )
        if hasattr(primary, 'import_lib'):
            link_options['import_lib'] = primary.import_lib

        return link_options

    @msbuild.rule_handler(DynamicLink, SharedLink, StaticLink)
    def msbuild_link(rule, build_inputs, solution, env):
        if ( any(i not in ['c', 'c++', 'rc'] for i in rule.input_langs) or
             rule.linker.flavor != 'msvc' ):
            raise ValueError('msbuild backend currently only supports c/c++ ' +
                             'with msvc')

        global_compile_opts = build_inputs['compile_options']
        global_link_opts = build_inputs['link_options']

        # Parse compilation flags; if there's only one set of them (i.e. the
        # command_var is the same for every compiler), we can apply these to
        # all the files at once. Otherwise, we need to apply them to each file
        # individually so they all get the correct options.
        obj_creators = [i.creator for i in rule.files]
        compilers = uniques(i.compiler for i in obj_creators)

        if len(uniques(i.command_var for i in compilers)) == 1:
            common_compile_options = _parse_compiler_cflags(
                compilers[0], global_compile_opts
            )
        else:
            common_compile_options = None

        deps = chain(
            (i.creator.file for i in rule.files),
            chain.from_iterable(i.creator.include_deps for i in rule.files),
            chain.from_iterable(i.creator.extra_deps for i in rule.files),
            filter(None, (getattr(i.creator, 'pch_source', None)
                          for i in rule.files)),
            rule.libs, rule.extra_deps
        )

        def get_source(file):
            # Get the source file for this compilation rule; it's either a
            # regular source file or a PCH source file.
            if isinstance(file.creator, CompileHeader):
                return file.creator.pch_source
            return file.creator.file

        # MSBuild doesn't build anything if it thinks there are no object files
        # to link. This is a problem for building libraries with no sources
        # that link to a whole-archive (a fairly-common way of making a shared
        # library out of a static one). To get around this, explicitly add the
        # whole-archive as an object file to link, in addition to passing
        # `/WHOLEARCHIVE:foo` as usual.
        objs = []
        if not rule.files:
            for i in rule.libs:
                if isinstance(i, WholeArchive):
                    objs.append(i.library)

        # Create the project file.
        project = msbuild.VcxProject(
            env, name=rule.name,
            mode=rule.msbuild_mode,
            output_file=first(rule.output),
            files=[{
                'name': get_source(i),
                'options': _parse_file_cflags(
                    i, global_compile_opts,
                    include_compiler=(common_compile_options is None)
                ),
            } for i in rule.files],
            objs=objs,
            compile_options=common_compile_options,
            link_options=_parse_ldflags(rule, global_link_opts),
            dependencies=solution.dependencies(deps),
        )
        solution[first(rule.public_output)] = project
except ImportError:  # pragma: no cover
    pass


#
# Python based OpenWhisk action that sleeps for the specified number
# of milliseconds before returning.
# The function actually sleeps slightly longer than requested.
#
# @param parm Object with Number property sleepTimeInMs
# @returns Object with String property msg describing how long the function slept
#
import sys
import time

def main(parm):
    sleepTimeInMs = parm.get("sleepTimeInMs", 1)
    print("Specified sleep time is {} ms.".format(sleepTimeInMs))

    result = { "msg": "Terminated successfully after around {} ms.".format(sleepTimeInMs) }

    time.sleep(sleepTimeInMs/1000.0)

    print(result['msg'])
    return result


import numpy as np
import pandas as pd
from os.path import join, dirname
from copy import deepcopy

from sostrades_core.tools.base_functions.exp_min import compute_dfunc_with_exp_min, compute_func_with_exp_min

from climateeconomics.core.core_resources.resource_model.resource_model import ResourceModel
from energy_models.core.stream_type.resources_models.resource_glossary import ResourceGlossary
from climateeconomics.core.tools.Hubbert_Curve import compute_Hubbert_regression

class OrderOfMagnitude():
    KILO = 'k'
    # USD_PER_USton = 'USD/USton'
    # MILLION_TONNES='million_tonnes'

    magnitude_factor = {
        KILO: 10 ** 3
        # USD_PER_USton:1/0.907
        # MILLION_TONNES: 10**6
    }

class PlatinumResourceModel(ResourceModel):
    """
    Resource pyworld3
    General implementation of a resource pyworld3, to be inherited by specific models for each type of resource
    """

    resource_name=ResourceGlossary.Platinum['name']

    def configure_parameters(self, inputs_dict):
        super().configure_parameters(inputs_dict)
        self.regression_stop = inputs_dict['regression_stop']
        self.world_consumption = inputs_dict['world_consumption']
        self.resource_max_price = inputs_dict['resource_max_price']

    #Units conversion

    #To convert from 1E6 oil_barrel to Mt
    conversion_factor = 1

    def convert_demand(self, demand):
        self.resource_demand=demand
        self.resource_demand[self.resource_name]=demand[self.resource_name]#*self.conversion_factor

    def get_global_demand(self, demand):
        global_demand = self.world_consumption['total']
        self.resource_demand=demand
        self.resource_demand[self.resource_name]=demand[self.resource_name] + global_demand
        self.conversion_factor = 1

    def compute_predictable_production(self):
        '''
        For each resource_type inside resource pyworld3, compute predictable production through Hubbert regression function
        '''
        centered_resource_production_data = self.resource_production_data.loc[self.resource_production_data['years'] <= self.regression_stop]
        for resource_type in self.sub_resource_list:
            self.predictable_production[resource_type] = compute_Hubbert_regression(
                centered_resource_production_data, self.production_years, self.production_start, resource_type)

    def compute_price(self):
        """
        price function depends on the ratio use_stock/demand
        price(ratio) = (price_max - price_min)(1-ratio) + price_min
        """

        # dataframe initialization
        self.resource_price['price'] = np.insert(np.zeros(len(self.years)-1), 0, self.resource_price_data.loc[0, 'price'])
        resource_price_dict = self.resource_price.to_dict()
        self.resource_demand = self.resources_demand[['years', self.resource_name]]
        self.get_global_demand(self.resource_demand)

        demand = deepcopy(self.resource_demand[self.resource_name].values)
        demand_limited = compute_func_with_exp_min(
            np.array(demand), 1.0e-10)

        self.ratio_usable_demand = np.maximum(self.use_stock[self.sub_resource_list[0]].values / demand_limited, 1E-15)

        for year_cost in self.years[1:] :

            resource_price_dict['price'][year_cost] = \
                    (self.resource_max_price - self.resource_price_data.loc[0, 'price']) *\
                        (1- self.ratio_usable_demand[year_cost - self.year_start]) + self.resource_price_data.loc[0, 'price']

        self.resource_price= pd.DataFrame.from_dict(resource_price_dict)

    def get_d_price_d_demand (self, year_start, year_end, nb_years, grad_use, grad_price):
        ascending_price_resource_list = list(
            self.resource_price_data.sort_values(by=['price'])['resource_type'])

        demand = deepcopy(self.resource_demand[self.resource_name].values)
        demand_limited = compute_func_with_exp_min(np.array(demand), 1.0e-10)
        grad_demand_limited = compute_dfunc_with_exp_min(np.array(demand), 1.0e-10)

        self.ratio_usable_demand = np.maximum(self.use_stock[self.sub_resource_list[0]].values / demand_limited, 1E-15)
        # # ------------------------------------------------
        # # price is cst *u/v function with u = use and v = demand
        # # price gradient is cst * (u'v - uv') / v^2
        for year_demand in range(year_start + 1, year_end + 1):
            for resource_type in ascending_price_resource_list:

                for year in range(year_start + 1, year_demand + 1):
                    #grad_price = cst * u'v  / v^2 (cst < 0)
                    if self.use_stock[self.sub_resource_list[0]][year_demand]/demand_limited[year_demand - year_start] > 1E-15 :
                        grad_price[year_demand - year_start, year - year_start] = \
                            - grad_use[resource_type][year_demand - year_start, year - year_start]
                        ## grad_price -= cst *  uv'  / v^2 (cst < 0)
                        if year == year_demand :
                                grad_price[year_demand - year_start, year - year_start] +=   self.use_stock[self.sub_resource_list[0]][year_demand]\
                                        * self.conversion_factor / demand_limited[year_demand - year_start]
                        grad_price[year_demand - year_start, year - year_start] = grad_price[year_demand - year_start, year - year_start] *\
                            (self.resource_max_price - self.resource_price_data.loc[0, 'price']) *\
                            grad_demand_limited[year_demand - year_start]/ demand_limited[year_demand - year_start]

        return grad_price


from PIL import Image
from gcbmanimation.util.tempfile import TempFileManager
Image.MAX_IMAGE_PIXELS = None

class Frame:
    '''
    Represents a presentation-format image that can be included in an animation.
    A frame usually applies to a particular year and points to an image file on disk.

    Arguments:
    'year' -- the year this Frame applies to.
    'path' -- the path to the image file this Frame represents.
    '''

    def __init__(self, year, path, scale=None):
        self._year = year
        self._path = path
        self._scale = scale

    @property
    def year(self):
        '''The year this Frame applies to.'''
        return self._year

    @property
    def path(self):
        '''The path to the Frame's image file.'''
        return self._path

    @property
    def scale(self):
        '''
        The scale (in metres per pixel) of the image, where None means
        unknown or not applicable.
        '''
        return self._scale

    @property
    def size(self):
        '''The width and height of the image.'''
        return Image.open(self._path).size

    def composite(self, frame, send_to_bottom=False):
        '''
        Combines another RGBA Frame with this one using their alpha channels.

        Arguments:
        'frame' -- the frame to combine with this one.
        'send_to_bottom' -- use the other frame as the background instead of
            this one.

        Returns the merged image as a new Frame with the same year as this one.
        '''
        out_path = TempFileManager.mktmp(suffix=".png")
        this_image = Image.open(self._path)
        other_image = Image.open(frame.path)

        if send_to_bottom:
            Image.alpha_composite(other_image, this_image).save(out_path)
        else:
            Image.alpha_composite(this_image, other_image).save(out_path)

        return Frame(self._year, out_path, self._scale)

    def merge_horizontal(self, *frames):
        '''
        Merges one or more Frames horizontally with this one.

        Arguments:
        'frames' -- one or more Frames to merge horizontally.

        Returns the merged image as a new Frame with the same year as this one.
        '''
        images = [Image.open(self._path)] + [Image.open(frame.path) for frame in frames]
        widths, heights = zip(*(image.size for image in images))

        total_width = sum(widths)
        max_height = max(heights)

        merged_image = Image.new("RGBA", (total_width, max_height), color=(255, 255, 255, 255))

        x_offset = 0
        for image in images:
            merged_image.paste(image, (x_offset, 0))
            x_offset += image.size[0]

        out_path = TempFileManager.mktmp(suffix=".png")
        merged_image.save(out_path)

        return Frame(self._year, out_path, scale=None)

    def resize(self, max_width, max_height):
        '''
        Resizes the image as closely as possible to the specified width and height
        while preserving the aspect ratio.

        Arguments:
        'max_width' -- the new maximum width.
        'max_height' -- the new maximum height.

        Returns the resized image as a new Frame with the same year as this one
        and updated scale reflecting the new pixel size in metres.
        '''
        original_width, original_height = self.size
        aspect_ratio = original_width / original_height

        if aspect_ratio > 1:
            new_width = max_width
            new_height = int(new_width / aspect_ratio)
            if new_height > max_height:
                new_height = max_height
                new_width = int(new_height * aspect_ratio)
        else:
            new_height = max_height
            new_width = int(new_height * aspect_ratio)
            if new_width > max_width:
                new_width = max_width
                new_height = int(new_width / aspect_ratio)

        out_path = TempFileManager.mktmp(suffix=".png")
        Image.open(self.path).resize((new_width, new_height), Image.ANTIALIAS).save(out_path)
        new_scale = self._scale * (original_width / new_width) if self._scale else None

        return Frame(self._year, out_path, new_scale)