## -*- coding: utf-8 -*-
# Author: Barbara McGillivray
# Date: 25/04/2018
# Python version: 3
# Script version: 1.0
# Script for evaluating the candidate words for semantic change outputted by the Temporal
# Random Indexing semantic change detection algorithm against OED words, and checking their corpus neighbours against
# the words occurring in the OED definitions and quotations.

# NB: the bit about neighbours needs to be completed!!

# ----------------------------
# Initialization
# ----------------------------

# Import modules:

# import requests
import os
import csv
from nltk import word_tokenize
from nltk.corpus import stopwords
import datetime

now = datetime.datetime.now()
today_date = str(now)[:10]

stop_words = set(stopwords.words('english'))

# Parameters:

freq_filter = 100  # frequency filter for candidate words
method_values = ["point", "cum", "occ"]
pvalue_values = ["090", "095"] # NB: if simple_valley_baseline = "yes", this parameter is ignored
freq_threshold = 500  # Frequency threshold for allowing a word into the corpus dictionary
changepoint_detection_values = ["simple_valley", "mean_shift", "valley_var_1", "valley_var_2", "valley_var_4"]
year_window_values = ["greater", "2", "3"]  # this is the size of the window of years for matching changepoints to OED
# years;
# if "greater", then we match any changepoint that is >= OED year
lemmatization_values = ["yes", "no"]

# Directory and file names:

directory = os.path.join("/Users", "bmcgillivray", "Documents", "OneDrive", "The Alan Turing Institute",
                         "Visiting researcher Basile McGillivray - Documents")
dir_in = os.path.join(directory, "Evaluation", "OED")
dir_out = os.path.join(directory, "Evaluation", "output")

# create output directory if it doesn't exist:
if not os.path.exists(os.path.join(directory, "Evaluation", "output", str(today_date))):
    os.makedirs(os.path.join(directory, "Evaluation", "output", str(today_date)))

# Input files:
oed_senses_file_name = "oed.sense"
oed_quotations_file_name = "oed.quotation"
dict_file_name = "dict.sample.all"
neighbour_file_name = "neighborhood_100.csv"

file_out_all_name = "oed_evaluation_overview.csv"

# Read corpus neighbours:

neighbour_file = open(os.path.join(directory, "tri", "year", "v2", "neighborhood_100",
                                   neighbour_file_name), 'r')

row_count_neighbour = sum(1 for line in neighbour_file)
neighbour_file.close()

# read list of neighbours from corpus:

neighbour_file = open(os.path.join(directory, "tri", "year", "v2", "neighborhood_100",
                                   neighbour_file_name), 'r')
count_n = 0

neighbour_words = dict()  # maps a candidate and a year to the list of its top 100 corpus neighbours

for line in neighbour_file:
    count_n += 1
    print("Neighbour dictionary: count", str(count_n), " out of ",
          str(row_count_neighbour))
    fields = line.split("\t")
    word = fields[0]
    year = int(fields[1])
    neighbours = fields[2:102]
    neighbour_words[word, year] = neighbours

neighbour_file.close()

# Read corpus frequencies:

dict_file = open(os.path.join(directory, "tri", dict_file_name), 'r')
dict_reader = csv.reader(dict_file, delimiter='\t')  # , quotechar='|')

row_count = sum(1 for row in dict_reader)
dict_file.close()

dict_file = open(os.path.join(directory, "tri", dict_file_name), 'r')
dict_reader = csv.reader(dict_file, delimiter='\t')  # , quotechar='|')

count = 0

dict_words = list()  # maps a candidate's lemma_pos to the list of its corpus changepoints

for row in dict_reader:  # , max_col=5, max_row=max_number+1):
    count += 1
    if count > 1:
        print("Corpus dictionary: count", str(count), " out of ", str(row_count))
        word = row[0]
        freq = int(row[1])
        if freq > freq_threshold:
            dict_words.append(word)

dict_file.close()

# Read OED quotations and map them to each sense id:

oed_quotations_file = open(os.path.join(dir_in, oed_quotations_file_name), 'r')
oed_quotations_reader = csv.reader(oed_quotations_file, delimiter='\t')  # , quotechar='|')

row_count = sum(1 for row in oed_quotations_reader)
oed_quotations_file.close()

oed_quotations_file = open(os.path.join(dir_in, oed_quotations_file_name), 'r')
oed_quotations_reader = csv.reader(oed_quotations_file, delimiter='\t')  # , quotechar='|')

count = 0
oed_senseid2quotid = dict()  # map each OED sense id to the list of its quotation ids
oed_quotid2quot = dict()  # map each OED quotation id to its quotation

for row in oed_quotations_reader:  # , max_col=5, max_row=max_number+1):
    count += 1

    if count > 1:
        print("OED quotations: count", str(count), " out of ", str(row_count))
        # word = row[0]
        # lemma = row[1]
        oed_quotid = row[0]
        oed_senseid = row[1]
        oed_date = row[2]
        oed_quotation = row[3]
        oed_quotid2quot[oed_quotid] = oed_quotation

        if oed_senseid in oed_senseid2quotid:
            quotids = oed_senseid2quotid[oed_senseid]
            quotids.append(oed_quotid)
            oed_senseid2quotid[oed_senseid] = quotids
        else:
            oed_senseid2quotid[oed_senseid] = [oed_quotid]

oed_quotations_file.close()

# Read OED content:

oed_senses_file = open(os.path.join(dir_in, oed_senses_file_name), 'r')
oed_senses_reader = csv.reader(oed_senses_file, delimiter='\t')  # , quotechar='|')

row_count = sum(1 for row in oed_senses_reader)
oed_senses_file.close()

oed_senses_file = open(os.path.join(dir_in, oed_senses_file_name), 'r')
oed_senses_reader = csv.reader(oed_senses_file, delimiter='\t')  # , quotechar='|')

count = 0
oed_lemmapos2years = dict()  # maps OED lemma_pos that is also candidate to list of years from OED
oed_lemmapos2year2senseid = dict()  # maps OED lemma_pos (that is also candidate) and year to the list of its sense ids
oed_lemma2years = dict()  # maps OED lemma that is also candidate to list of years from OED
oed_lemma2year2senseid = dict()  # maps OED lemma that is also candidate and year to the list of its sense ids
oed_senseid2def = dict()  # maps OED sense id (of a lemma that is also candidate) to its definition

gold_standard_lemmapos = list()  # list of [words, pos] that have changed meaning according to the OED between 1995
# and 2014
# and that appear in the corpus above the frequency threshold
gold_standard_lemma = list()  # list of words that have changed meaning according to the OED between 1995 and 2014
# and that appear in the corpus above the frequency threshold

for row in oed_senses_file:  # , max_col=5, max_row=max_number+1):
    count += 1
    fields = row.split("\t")
    # print(str(fields))
    # print(str(type(fields)))
    # print(str(fields[3]))
    if count > 1:
        print("OED senses: count", str(count), " out of ", str(row_count))
        # word = row[0]
        # lemma = row[1]
        oed_senseid = fields[0]
        oed_lemma = fields[1]
        if oed_lemma != "NA":  # and oed_lemma == "blackberry":

            oed_postag = fields[2]
            oed_lemmapos = oed_lemma + "_" + oed_postag
            oed_startdate = int(fields[3])
            oed_definition = fields[4]
            oed_senseid2def[oed_senseid] = oed_definition

            if oed_startdate >= 1995 <= 2014 and oed_lemma in dict_words:

                gold_standard_lemmapos.append(oed_lemmapos)

                # OED lemma, pos pairs:

                if oed_lemmapos in oed_lemmapos2years:
                    years = oed_lemmapos2years[oed_lemmapos]
                    # years = oed_lemmapos2years[oed_lemma]
                    years.append(oed_startdate)
                    oed_lemmapos2years[oed_lemmapos] = years
                    # oed_lemmapos2years[oed_lemma] = years
                else:
                    oed_lemmapos2years[oed_lemmapos] = [oed_startdate]
                    # oed_lemmapos2years[oed_lemma] = [oed_startdate]

                if (oed_lemmapos, oed_startdate) in oed_lemmapos2year2senseid.keys():
                    senseids = oed_lemmapos2year2senseid[(oed_lemmapos, oed_startdate)]
                    senseids.append(oed_senseid)
                    oed_lemmapos2year2senseid[(oed_lemmapos, oed_startdate)] = senseids
                else:
                    oed_lemmapos2year2senseid[(oed_lemmapos, oed_startdate)] = [oed_senseid]

                # OED lemmas:

                gold_standard_lemma.append(oed_lemma)

                if oed_lemma in oed_lemma2years:
                    years = oed_lemma2years[oed_lemma]
                    # years = oed_lemmapos2years[oed_lemma]
                    years.append(oed_startdate)
                    oed_lemma2years[oed_lemma] = years
                    # oed_lemmapos2years[oed_lemma] = years
                else:
                    oed_lemma2years[oed_lemma] = [oed_startdate]
                    # oed_lemmapos2years[oed_lemma] = [oed_startdate]

                if oed_lemmapos in oed_lemmapos2years:
                    years = oed_lemmapos2years[oed_lemmapos]
                    # years = oed_lemmapos2years[oed_lemma]
                    years.append(oed_startdate)
                    oed_lemmapos2years[oed_lemmapos] = years
                    # oed_lemmapos2years[oed_lemma] = years
                else:
                    oed_lemmapos2years[oed_lemmapos] = [oed_startdate]
                    # oed_lemmapos2years[oed_lemma] = [oed_startdate]

                if (oed_lemma, oed_startdate) in oed_lemma2year2senseid.keys():
                    senseids = oed_lemma2year2senseid[(oed_lemma, oed_startdate)]
                    senseids.append(oed_senseid)
                    oed_lemma2year2senseid[(oed_lemma, oed_startdate)] = senseids
                else:
                    oed_lemma2year2senseid[(oed_lemma, oed_startdate)] = [oed_senseid]

oed_senses_file.close()

# Function that compares a list of change points from the corpus with a list of years from OED:

def compare_years(year_window_par, changepoints_list, oedyears_list):
    num_correct = 0
    matching_oedyears_list = list()

    for c in changepoints_list:
        print("\tChangepoint:" + str(c))
        for oedyear in oedyears_list:
            print("\t\tOed year:" + str(oedyear))
            # if int(changepoint) == int(oedyear) or int(changepoint) == int(oedyear) - 1
            # or int(changepoint) == int(oedyear) + 1:
            if year_window_par == "greater":
                if int(c) >= int(oedyear) >= 1995:
                    print("\t\t\tCorrect changepoint (greater) for ", l, ": ", str(c), str(oedyear))
                    num_correct = 1
                    matching_oedyears_list.append(oedyear)
            else:
                if (int(c) >= int(oedyear) - int(year_window_par) and int(c) <= int(oedyear) + int(
                        year_window_par)) \
                        and int(oedyear) >= 1995:
                    print("\t\t\tCorrect changepoint (window) for ", l, ": ", str(c), str(oedyear))
                    num_correct = 1
                    matching_oedyears_list.append(oedyear)

    return [num_correct, matching_oedyears_list]

# Function that calculates the overlap between corpus neighbours and OED definition+quotation for a given matching year:

def calculate_overlap(lemmatization, l, changepoint_year, matching_oed_years_list, oed_years_list):
    overlap = 0  # number of words shared between corpus neighbours of l at changeppoint_year
    # and preprocessed OED definition+quotation words at matching year
    oed_words = 0  # number of preprocessed OED definition+quotation words for matching years and l
    neigh_words = 0  # number of corpus neighbours of l
    overlaps = list()  # list of number of words shared between corpus neighbours of l at changeppoint_year
    # and preprocessed OED definition+quotation words in any year >= 1995
    max_overlap = 0  # maximum among number of words shared between corpus neighbours of l at changeppoint_year
    # and preprocessed OED definition+quotation words in any year >= 1995

    if lemmatization == "yes":
        lemma = l.split("_")[0]
        pos = l.split("_")[1]
    else:
        lemma = l

    if [lemma, changepoint_year] in neighbour_words:
        neighbours = neighbour_words[lemma, changepoint_year]

    # retrieve definitions of lemma (or lemma_pos) in OED for each of the years and for the matching years:

    oed_content_words_all_years = dict()  # maps a year to the list of words in each OED definitions+quotations for all
    # years for this lemma
    oed_content_words_matching_years = list()  # list of words in all OED definitions+quotations for the matching years
    # for this lemma

    for year in oed_years_list:

        if lemmatization == "yes":
            oed_senseids = oed_lemmapos2year2senseid[l, year]
        else:
            oed_senseids = oed_lemma2year2senseid[l, year]

        for oed_senseid in oed_senseids:

            oed_definition = oed_senseid2def[oed_senseid]
            oed_definition_words = word_tokenize(oed_definition)
            oed_words_list = list()

            for w in oed_definition_words:
                w = w.lower()
                if w not in stop_words:
                    oed_words_list.append(w)
                    if year in matching_oedyears:
                        oed_content_words_matching_years.append(w)

            # retrieve quotations of this sense id in OED:

            if oed_senseid in oed_senseid2quotid:
                quot_ids = oed_senseid2quotid[oed_senseid]
                for quotid in quot_ids:
                    if quotid in oed_quotid2quot:
                        quotation = oed_quotid2quot[quotid]
                        oed_quotation_words = word_tokenize(quotation)
                        for w in oed_quotation_words:
                            w = w.lower()
                            if w not in stop_words:
                                oed_words_list.append(w)

                            if year in matching_oedyears:
                                oed_content_words_matching_years.append(w)

            oed_content_words_all_years[year] = list(set(oed_words_list))

    oed_content_words_matching_years = list(set(oed_content_words_matching_years))

    # Compare corpus neighbours with OED:

    neighbours = neighbour_words[lemma, changepoint_year]
    neighbours = list(set(neighbours))

    for neighbour_word in neighbours:
        neigh_words += 1

        # if the neighbour word is contained in the OED definitions+quotations of l in the matching years:
        if neighbour_word in oed_content_words_matching_years:
            overlap += 1

        # if the neighbour word is contained the OED definitions+quotations of l in one (or more) of the years:

        for year in oed_years_list:
            overlap_year = 0
            if year in oed_content_words_all_years:
                oed_w = oed_content_words_all_years[year]
                if neighbour_word in oed_w:
                    overlap_year += 1

            if max_overlap < overlap_year:
                max_overlap = overlap_year

    return [overlap, oed_words, neigh_words, max_overlap]

# -----------------------------------------
# Write to output
# -----------------------------------------

with open(os.path.join(dir_out, file_out_all_name), "w") as output_all_file:
    writer_all_output = csv.writer(output_all_file, delimiter='\t', quotechar='|', quoting=csv.QUOTE_MINIMAL,
                                   lineterminator='\n')
    writer_all_output.writerow(['method', 'changepoint detection', 'significance', 'year_window', 'lemmatization',
                                'num correct', 'num candidates', 'num gold standard', 'Precision', 'Recall',
                                'F1-score'])

    for lemmatization in lemmatization_values:

        for changepoint_detection in changepoint_detection_values:
            if changepoint_detection.startswith("valley_var"):
                #method_values = ["point", "cum"]
                pvalue_values = ["0"]
            else:
                pvalue_values = ["090", "095"]

            for method in method_values:
                for pvalue in pvalue_values:

                    for year_window in year_window_values:

                        candidate_words_file_name = method + "_words_freq_" + str(freq_filter) + "pvalue-" + \
                                                    str(
                                                        pvalue) + "changepoint-detection_" + changepoint_detection + ".txt"

                        #if changepoint_detection.startswith("valley_var"):
                        #    candidate_words_file_name = method + "_words_for_lookup_freq_" + str(freq_filter) + \
                        #                                "changepoint-detection_" + changepoint_detection + ".txt"
                        # oed_words_file_name = method + "_" + pvalue + "_words_for_lookup_freq_" + str(freq_filter) + "_oed.tsv"

                        # Output files: candidate words for semantic change detection, checked against OED API:

                        file_out_name = method + '_words_freq-' + str(freq_filter) + "pvalue-" + str(
                            pvalue) + "_yearwindow-" + str(year_window) \
                                        + "lemmatization-" + lemmatization + "changepoint-detection_" + changepoint_detection + \
                                        "_oed_evaluation.tsv "
                        file_out_name_summary = method + "_words_freq-" + str(freq_filter) + "pvalue-" + str(
                            pvalue) + "_yearwindow-" + \
                                                str(
                                                    year_window) + "lemmatization-" + lemmatization + "changepoint-detection_" + \
                                                changepoint_detection + "_oed_evaluation_summary.txt"

                        # --------------------------------------------------------------
                        # Read word lists from different sources:
                        # --------------------------------------------------------------

                        # Read corpus changepoints for candidate words:

                        candidate_words_file = open(os.path.join(dir_out, candidate_words_file_name), 'r')

                        candidate_words_reader = csv.reader(candidate_words_file, delimiter='\t')  # , quotechar='|')

                        row_count = sum(1 for row in candidate_words_reader)
                        candidate_words_file.close()

                        candidate_words_file = open(os.path.join(dir_out, candidate_words_file_name), 'r')

                        candidate_words_reader = csv.reader(candidate_words_file, delimiter='\t')  # , quotechar='|')

                        count = 0

                        candidate2changepoints = dict()  # maps a candidate's lemma_pos to the list of its corpus changepoints

                        for row in candidate_words_reader:  # , max_col=5, max_row=max_number+1):
                            count += 1
                            if count > 1:
                                print("Corpus frequencies: count", str(count), " out of ", str(row_count))
                                word = row[0]
                                pos = row[1]
                                lemma = row[2]
                                lemmapos = lemma + "_" + pos
                                frequency = row[3]
                                changepoints = row[4]

                                if lemmatization == "yes":
                                    candidate2changepoints[lemmapos] = changepoints.split("_")
                                else:
                                    candidate2changepoints[lemma] = changepoints.split("_")
                                    # candidate2changepoints[lemma] = changepoints.split("_")

                        candidate_words_file.close()

                        # --------------------------------------------------------------
                        # Compare changepoint year of candidate words against OED years
                        # --------------------------------------------------------------

                        # Compare the corpus changepoints of a candidate lemma with its OED years:

                        correct_candidates = list()
                        candidates = list()
                        correct = 0

                        #correct_changepoints2overlap = dict() # maps a correct candidate and its correct changepoint to
                        # the number of overlapping words between its neighbours and the OED definition+quotation of
                        # its matching years

                        for l in candidate2changepoints:
                            changepoints = candidate2changepoints[l]
                            # print("Changepoints:", changepoints)
                            candidates.append(l)

                            if lemmatization == "yes":

                                if l in oed_lemmapos2years:
                                    print(l)
                                    oedyears = oed_lemmapos2years[l]
                                    # print("OED years:", oedyears)

                                    [correct, matching_oedyears] = compare_years(year_window, changepoints, oedyears)

                                    # correct candidates:

                                    if correct == 1:
                                        correct_candidates.append(l)

                                    # calculate overlap between corpus neighbours and OED definition+quotation:

                                    #for changepoint in changepoints:
                                    #    [overlap, oed_words, neigh_words, max_overlap] = calculate_overlap(
                                    #        lemmatization, l, changepoint, matching_oedyears, oedyears)

                            else:

                                if l in oed_lemma2years:
                                    print(l)
                                    oedyears = oed_lemma2years[l]
                                    # print("OED years:", oedyears)

                                    [correct, matching_oedyears] = compare_years(year_window, changepoints, oedyears)

                                    # correct candidates:

                                    if correct == 1:
                                        correct_candidates.append(l)

                                        # calculate overlap between corpus neighbours and OED definition+quotation:

                                        #for changepoint in changepoints:
                                        #    [overlap, oed_words, neigh_words, max_overlap] = calculate_overlap(
                                        #        lemmatization, l, changepoint, matching_oedyears, oedyears)

                        # Correct candidates:

                        correct_candidates = list(set(correct_candidates))

                        # --------------------------------------------------------------
                        # Calculate precision, recall, and F-score:
                        # --------------------------------------------------------------

                        print("Total number of correct candidates:", str(len(correct_candidates)))
                        print("Total number of candidates:", str(len(candidates)))
                        P = 0
                        if len(candidates) > 0:
                            P = len(correct_candidates) / len(candidates)
                        print("Precision:", P)
                        print("Total number of gold standard lemmapos:", str(len(gold_standard_lemmapos)))
                        R = len(correct_candidates) / len(gold_standard_lemmapos)
                        print("Recall:", R)
                        if (P + R) > 0:
                            F = 2 * P * R / float(P + R)
                        else:
                            F = 0

                        # -----------------------------
                        # Print to output files:
                        # -----------------------------

                        # List of correct candidates, and their years:

                        output_file = open(os.path.join(dir_out, file_out_name), "w")

                        if lemmatization == "yes":
                            writer_output = csv.writer(output_file, delimiter='\t', quotechar='|',
                                                       quoting=csv.QUOTE_MINIMAL,
                                                       lineterminator='\n')
                            writer_output.writerow(
                                ['correct_lemma', 'correct_pos', 'changepoints', 'oed_years'])

                            for correct in correct_candidates:
                                lemma = correct.split("_")[0]
                                pos = correct.split("_")[1]
                                if correct in candidate2changepoints and correct in oed_lemmapos2years:
                                    writer_output.writerow(
                                    [lemma, pos, candidate2changepoints[correct], oed_lemmapos2years[correct]])

                        else:
                            writer_output = csv.writer(output_file, delimiter='\t', quotechar='|',
                                                       quoting=csv.QUOTE_MINIMAL,
                                                       lineterminator='\n')
                            writer_output.writerow(['correct_lemma', 'changepoints', 'oed_years'])

                            for correct in correct_candidates:
                                lemma = correct
                                if correct in candidate2changepoints and correct in oed_lemma2years:
                                    writer_output.writerow(
                                    [lemma, candidate2changepoints[correct], oed_lemma2years[correct]])

                        output_file.close()

                        # Evaluation statistics:

                        output_file_summmary = open(os.path.join(dir_out, file_out_name_summary), "w")
                        output_file_summmary.write(
                            "Total number of correct candidates:" + str(len(correct_candidates)) + "\n")
                        output_file_summmary.write("Total number of candidates:" + str(len(candidates)) + "\n")
                        output_file_summmary.write(
                            "Total number of gold standard lemmapos:" + str(len(gold_standard_lemmapos)) + "\n")
                        output_file_summmary.write("Precision:" + str(P) + "\n")
                        output_file_summmary.write("Recall:" + str(R))
                        output_file_summmary.close()

                        writer_all_output.writerow(
                            [method, changepoint_detection, pvalue, year_window, lemmatization,
                             str(len(correct_candidates)), str(len(candidates)), str(len(gold_standard_lemmapos)), P, R,
                             F])

# ---------------------------------------------------------------------
# Compare OED vector for candidate words with their corpus neighbours
# ---------------------------------------------------------------------


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on Wed Oct 23 17:32:12 2019

@author: giles
"""

'''
Question 1
Can you remember how to check if a key exists in a dictionary?
Using the capitals dictionary below write some code to ask the user to input
a country, then check to see if that country is in the dictionary and if it is
print the capital. If not tell the user it's not there.
'''

capitals = {'France':'Paris','Spain':'Madrid','United Kingdom':'London',
            'India':'New Delhi','United States':'Washington DC','Italy':'Rome',
            'Denmark':'Copenhagen','Germany':'Berlin','Greece':'Athens',
            'Bulgaria':'Sofia','Ireland':'Dublin','Mexico':'Mexico City'}

#country = input("Enter the name of a country and ill try look it up.\n >>").capitalize()
#if country in capitals.keys():
#    print(f'{country} is in the dictionary, the capital city is {capitals[country]}')
#else:
#    print(f'{country} is not in the dictionary')

'''
Question 2
Write python code that will create a dictionary containing key, value pairs
that represent the first 12 values of the Fibonacci sequence
i.e {1:0,2:1,3:1,4:2,5:3,6:5,7:8 etc}
'''
##Create two lists, x = range 1-12, y = the beginning of the fib sequence [0,1]
#x = list(range(1,13))
#y = [0,1]
#
##Finish off the FIbonnaci list by iterating over it 10 times, apppending the sum of the last 2 digits
#for i in range(len(x)-2):
#    y.append(y[i]+y[i+1])
#
## Create a new dictionary using dictionary comprehension, zipping together list x and list y
#fib_dict = {k:v for (k,v) in zip(x,y)}
#print(fib_dict)

'''
Question 3
Create a dictionary to represent the open, high, low, close share price data
for 4 imaginary companies. 'Python DS', 'PythonSoft', 'Pythazon' and 'Pybook'
the 4 sets of data are [12.87, 13.23, 11.42, 13.10],[23.54,25.76,21.87,22.33],
[98.99,102.34,97.21,100.065],[203.63,207.54,202.43,205.24]
'''

##Store the data from the question as lists and list of lists.
#companies = ['Python DS','Pythonsoft', 'Pythazon','Pybook']
#key_names = ['Open','High','Low','Close']
#prices = [[12.87, 13.23, 11.42, 13.10],[23.54,25.76,21.87,22.33],
#          [98.99,102.34,97.21,100.065],[203.63,207.54,202.43,205.24]]
#
##Create dictionary
#share_dict = {}
#
##Iterate through this 4 times
#for i in range(len(key_names)):
#    #add ith 'company'key to the dictionary which contains a dictionary value comprised of keynames zipped with the ith price list.
#    share_dict[companies[i]] = dict(zip(key_names,prices[i]))
#
#print(share_dict)
'''
Question 4
Go to the python module web page and find a module that you like. Play with it,
read the documentation and try to implement it.
'''
#import pprint
#
#pprint.pprint(share_dict, compact=True)
#
#import math
#
#print('let\'s find the length of a hypotenuse in a right angled triangle')
#side1 = int(input('Enter first side integer'))
#side2 = int(input('Enter second side integer'))
#hypotenuse = math.hypot(side1,side2)
#print(f'the length of the hypotenuse is: {hypotenuse}')

'''
Question 5
Create a dictoinary containing as keys the letters from A-Z, the values should
be random numbers created from the random module. Can you draw a bar graph of
the results?
'''
#import string
#from random import randint
#import matplotlib.pyplot as plt
#
#letters = [x for x in string.ascii_uppercase]
#vals = [randint(1,100) for x in range(len(letters))]
#
#d_1 = {k:v for (k,v) in zip(letters,vals)}
#
#x,y = zip(*d_1.items())
#plt.bar(x,y)

'''
Question 6
Create a dictionary containing 4 suits of 13 cards
['Ace','2','3','4','5','6','7','8','9','10','Jack','Queen','King']
'''
suits = ['Hearts','Diamonds','Spades','Clubs']
values = ['Ace','2','3','4','5','6','7','8','9','10','Jack','Queen','King']

deck = {}

for i in range(len(suits)):
    deck[suits[i]] = values

print(deck)


from pages.models import Author
from wagtail_wordpress_import.block_builder_defaults import get_or_save_image

# See pages/models.py:
def header_image(imported_pages, data, items_cache):
    print("Importing header image")
    """use this for the import authors version"""
    lookup = f"wp_post_meta__{data}"
    for attachment in items_cache:
        thumbnail_id = attachment.get("wp:post_id")
        pages = imported_pages.filter(**{lookup: thumbnail_id})
        if pages.exists():
            image = get_or_save_image(attachment.get("guid"))
            pages.update(header_image=image)
            print("Attaching header images to pages:", pages)

# See pages/models.py:
def authors(imported_pages, data, tags_cache):
    print("Importing authors")
    # breakpoint()
    lookup = f"wp_post_meta__{data}"
    for author in tags_cache:
        author_login = author.get("wp:author_login")
        pages = imported_pages.filter(**{lookup: author_login})
        if pages:
            first_name = (
                author.get("wp:author_first_name")
                if author.get("wp:author_first_name")
                else "not"
            )
            last_name = (
                author.get("wp:author_last_name")
                if author.get("wp:author_last_name")
                else "known"
            )
            email_address = author.get("wp:author_email")
            obj, created = Author.objects.get_or_create(
                first_name=first_name,
                last_name=last_name,
                email_address=email_address,
            )
            if pages.exists():
                pages.update(author=obj)
                print("Attaching authors to pages:", pages)


#!/bin/env python
#-*- encoding: utf-8 -*-

import numpy as np
import pandas as pd
import os
import io
import codecs
import sys

reload(sys)
sys.setdefaultencoding('utf-8')

base_dir = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
sys.path.insert(0, base_dir)

import pickle
import csv
import tensorflow as tf
import functools
from tensorflow.contrib.learn import preprocessing
import mds_hparams
import pickle
import nlp_util_py3

MAX_SENTENCE_LEN = mds_hparams.FLAGS.max_len
MAX_NUM_UTTER = mds_hparams.FLAGS.max_num_utterance

tf.flags.DEFINE_string('input_dir', os.path.abspath('./data'), 'Input dictionary containing original .txt file')
tf.flags.DEFINE_string('output_dir', os.path.abspath('./data'), 'Output dictionary containing TFRecord file')
tf.flags.DEFINE_integer('min_word_freq', 1, 'minimum number of word frequency in the vocabulary')

FLAGS = tf.flags.FLAGS
# hack here because tf.flags.FLAG only parsed once automatically, and
# new flag defined in this file will not be contained due to parsed already
# in mds_hparams.py, thus we call it manually here
FLAGS._parse_flags()

TRAIN_PATH = os.path.join(FLAGS.input_dir, 'train_test.csv')
VALID_PATH = os.path.join(FLAGS.input_dir, 'mvalid_1000lad_comb.csv')
TEST_PATH = os.path.join(FLAGS.input_dir, 'task5_pad_comb.csv')

def create_file_iter(filename):
    with io.open(filename, 'r', encoding='utf-8') as f:
        for row in f:
            if len(row):
                yield row

def create_csv_iter(filename):
    """
        Return an iterator over a CSV file. Skips the header if necessary.
            """
    with open(filename) as csvfile:
        reader = csv.reader(csvfile)
        # Skip the header
        #next(reader)
        for row in reader:
            yield row

def tokenizer_fn(iterator):
    tknz_func = nlp_util_py3.NLPUtil.tokenize_via_jieba
    return (tknz_func(x) for x in iterator)

def create_vocab(input_iter, min_freq):
    print('begin ---')
    vp = preprocessing.VocabularyProcessor(
        max_document_length = MAX_SENTENCE_LEN * MAX_NUM_UTTER,
        min_frequency = min_freq,
        tokenizer_fn = tokenizer_fn)
    print('begin fit -----')
    vp.fit(input_iter)
    return vp

def transform_sentence(sequence, vocab_processor):
    '''
    Map a sentence into the integer vocabulary.
    '''
    return next(vocab_processor.transform([sequence])).tolist()

def create_example_train(row, vocab):
    '''
    Return a tensorflow.Example Protocol Buffer object.
    '''
    # list of utterance, response and label
    utters, res  = row[0:2]
    label = row[-1]
    utters_len = []
    utters_transformed = transform_sentence(utters, vocab)
    #print('xxxxxxxxx, debug, utters=%s' % (utters))
    #print('xxxxxxxxx, debug, utters_transformed=%s' % (utters_transformed))
    res_transformed = transform_sentence(res, vocab)[0:MAX_SENTENCE_LEN]

    #print('xxxxxxxxx, debug, res=%s' % (res))
    #print('xxxxxxxxx, debug, res_transformed=%s' % (res_transformed))
    #utters_len = len(next(vocab._tokenizer([utters])))
    #res_len = len(next(vocab._tokenizer([res])))
    tmp = len(utters_transformed)/MAX_SENTENCE_LEN
    for i in range(tmp):
        utters_len.append(MAX_SENTENCE_LEN)
    res_len = len(res_transformed)
    label = int(float(label))

    #print ("utters_len:",str(utters_len))
    #print ("res_len:",str(res_len))
    #print  str(label)

    #create example
    example = tf.train.Example()
    example.features.feature['utters'].int64_list.value.extend(utters_transformed)
    example.features.feature['utters_len'].int64_list.value.extend(utters_len)
    example.features.feature['res'].int64_list.value.extend(res_transformed)
    example.features.feature['res_len'].int64_list.value.extend([res_len])
    example.features.feature['label'].int64_list.value.extend([label])
    #print('Successfully built')
    #print('example=%s' % (example))
    return example

def create_example_test(row, vocab):
    '''
    Create validation/test set
    Return a tensorflow.Example Protocol Buffer object.
    '''
    utters, res  = row[0:2]
    distractors = row[2:]
    utters_len = []

    utters_transformed = transform_sentence(utters,vocab)
    res_transformed = transform_sentence(res,vocab)[0:MAX_SENTENCE_LEN]
    #print(len(next(vocab._tokenizer([utters]))))
    #print(len(next(vocab._tokenizer([res]))))
    tmp = len(utters_transformed)/MAX_SENTENCE_LEN
    for i in range(tmp):
        utters_len.append(MAX_SENTENCE_LEN)
    res_len = len(res_transformed)

    #create example
    example = tf.train.Example()
    example.features.feature['utters'].int64_list.value.extend(utters_transformed)
    example.features.feature['utters_len'].int64_list.value.extend(utters_len)
    example.features.feature['res'].int64_list.value.extend(res_transformed)
    example.features.feature['res_len'].int64_list.value.extend([res_len])

    #print ("utters_len:",str(utters_len))
    #print ("res_len:",str(res_len))

    #add distractor
    dis_sample_cnt = len(distractors)
    #print('dis_sample_cnt', str(dis_sample_cnt))
    for i in xrange(dis_sample_cnt):
        dis_key = 'distractor_{}'.format(i)
        dis_len_key = 'distractor_{}_len'.format(i)
        dis_item = distractors[i:i+1]
        distractor = dis_item[0]

        #dis_len = len(next(vocab._tokenizer([distractor])))
        dis_len = MAX_SENTENCE_LEN
        example.features.feature[dis_len_key].int64_list.value.extend([dis_len])
        distractor_transformed = transform_sentence(distractor, vocab)[0:MAX_SENTENCE_LEN]
        dis_len = len(distractor_transformed)
        example.features.feature[dis_key].int64_list.value.extend(distractor_transformed)

    #print('example=%s' % (example))
    return example

def create_tfrecord_file(input_fname, output_fname, example_fn):
    '''
    Create a TFRecords file for the given input data and
    example transofmration function
    '''
    print('Creating tfRecords file at {}...'.format(output_fname))
    with tf.python_io.TFRecordWriter(output_fname) as writer:
        for i, row in enumerate(create_csv_iter(input_fname)):
            x = example_fn(row)
            writer.write(x.SerializeToString())
    print('Finish writing to {}'.format(output_fname))

def write_vocabulary(vocab_processor, outfile):
    '''
    Write the vocabulary to a file, one word one line
    '''
    vocab_size = len(vocab_processor.vocabulary_)
    vocab_list = [vocab_processor.vocabulary_._reverse_mapping[id_]
        for id_ in xrange(vocab_size)]
    with codecs.open(outfile, 'w') as wfd:
        wfd.write('\n'.join(vocab_list))
    print('Saved vocabulary to {}'.format(outfile))

if __name__ == '__main__':
    print('Createing Vocabulary...')
    #input_fpath = './data/train_10000.txt'
    output_fdir = './data/'
    #input_iter = create_file_iter('./data/train_3000000.txt')
    #input_iter = create_csv_iter('./data/train_test.csv')
    #input_iter = (x[0] + '|' + x[1] for x in input_iter)
    #print('Create vocab...')
    #vocab = create_vocab(input_iter,min_freq = 1)
    #print('The total vocabulary size: {}'.format(len(vocab.vocabulary_)))

    #create vocabulary.txt file
    #write_vocabulary(vocab, os.path.join(output_fdir, 'vocabulary.txt'))

    #Save the vocab processor as a pickle format
    #vocab.save(os.path.join(FLAGS.output_dir, 'vocab_processor.bin'))
    vocab = preprocessing.VocabularyProcessor.restore(os.path.join(FLAGS.output_dir, 'vocab_processor.bin'))
    #Create train.tfRecords
    #create_tfrecord_file(
    #    input_fname = TRAIN_PATH,
    #    output_fname = os.path.join(FLAGS.output_dir, 'train.tfrecords'),
    #    example_fn = functools.partial(create_example_train, vocab = vocab))

    #Create valid.tfRecords
    create_tfrecord_file(
        input_fname = VALID_PATH,
        output_fname = os.path.join(FLAGS.output_dir, 'valid_1000.tfrecords'),
        example_fn = functools.partial(create_example_test, vocab = vocab))

    #create test.tfRecords
    create_tfrecord_file(
        input_fname = TEST_PATH,
        output_fname = os.path.join(FLAGS.output_dir, 'task5.tfrecords'),
        example_fn = functools.partial(create_example_test, vocab = vocab))


from pathlib import Path

import pytest
from PyPDF2 import PdfFileReader

from pdfmerge2.exceptions import PathNotExistsError, FilesNotFoundInDirectoryError
from pdfmerge2.merger import Merger
from .helpers import create_args, get_contents_names

def test_merge_from_path(resources_path):
    args = create_args()
    merger = Merger(**args)

    merger.merge_files()

    assert merger.merged_file_path.name in get_contents_names(resources_path)
    with merger.merged_file_path.open(mode='rb') as merged_file:
        reader = PdfFileReader(merged_file)
        assert 12 == len(reader.pages)

def test_merge_to_output_not_exist(resources_path):
    output_path = resources_path.joinpath("new_output")
    args = create_args(output=output_path)
    merger = Merger(**args)

    merger.merge_files()

    assert merger.merged_file_path.name in get_contents_names(output_path)
    with merger.merged_file_path.open(mode='rb') as merged_file:
        reader = PdfFileReader(merged_file)
        assert 12 == len(reader.pages)

def test_merge_specified_files(resources_path):
    args = create_args(pdf_files=['pdf1', 'pdf2'])
    merger = Merger(**args)

    merger.merge_files()

    assert merger.merged_file_path.name in get_contents_names(resources_path)
    with merger.merged_file_path.open(mode='rb') as merged_file:
        reader = PdfFileReader(merged_file)
        assert 6 == reader.numPages

def test_bad_path():
    args = create_args(path=Path("asd/qwe"))
    merger = Merger(**args)

    with pytest.raises(PathNotExistsError):
        merger.merge_files()

def test_file_not_found():
    args = create_args(pdf_files=['bad_file1', 'bad_file2'])
    merger = Merger(**args)

    with pytest.raises(FileNotFoundError):
        merger.merge_files()

def test_files_in_path_not_found(resources_path):
    args = create_args(path=resources_path.joinpath("output"))
    merger = Merger(**args)

    with pytest.raises(FilesNotFoundInDirectoryError):
        merger.merge_files()


import random
import itertools
# import tabulate
from prettytable import PrettyTable
import pygame
import time

screen_width = 800
screen_height = 600
screen_fps = 60

white = (255, 255, 255)
aqua = (127, 255, 212)
brick = (156, 102, 31)
dark_green = (100, 102, 31)
black = (0, 0, 0)
khaki = (240, 230, 140)
dark_khaki = (200, 190, 140)

pygame.init()
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Game Title")
clock = pygame.time.Clock()

pygame.font.init()

weapons = {'Fist': {'+atk': 0, 'Cost': 10},
           'Wooden Sword': {'+atk': 2, 'Cost': 20},
           'Rusty Sword': {'+atk': 4, 'Cost': 30},
           'Iron Sword': {'+atk': 6, 'Cost': 40},
           'Steel Sword': {'+atk': 8, 'Cost': 50},
           'Sword of Crushing Puss': {'+atk': 100, 'Cost': 10000}}

armor = {"Travelers Cloths": {'+def': 0, 'Cost': 10},
         'Cloth Armor': {'+def': 2, 'Cost': 100},
         'Leather Armor': {'+def': 4, 'Cost': 150},
         'Iron Armor': {'+def': 6, 'Cost': 200},
         'Mail Armor': {'+def': 8, 'Cost': 250},
         'Steel Armor': {'+def': 10, 'Cost': 300}}

class Player:
    def __init__(self, name, curweap=None, curarmor=None):
        if curweap is None:
            curweap = random.choice(list(weapons.keys()))
        if curarmor is None:
            curarmor = random.choice(list(armor.keys()))
        self.name = name
        self.maxhealth = 100
        self.health = self.maxhealth
        self.base_attack = 14
        self.base_defense = 5
        self.critical = .05
        self.gold = 10000
        self.pots = 1
        self.curweap = curweap
        self.weap = []
        self.curarmor = curarmor
        self.armor = []
        self.location = 'D2'
        self.game_over = False

    @property
    def attack(self):
        attack = self.base_attack + weapons[player.curweap]['+atk']
        return attack

player = Player("Tomer")

def main():
    print(input("Select 1 for Weapons or 2 for Armor"))
    option = input("-> ")
    if option is '1':
        weapons_store()
    elif option is '2':
        armor_store()
    else:
        main()

def weapons_store():
    weapon_name = max(map(len, weapons)) + 2
    weapon_atk = len(str(max(int(d['+atk']) for d in weapons.values()))) + 2
    weapon_cost = len(str(max(int(d['Cost']) for d in weapons.values())))

    print("{:<{weapon_name}} {:<{weapon_atk}} {:<{weapon_cost}}".format('Weapon', 'Atk', 'Cost', weapon_name=weapon_name, weapon_atk=weapon_atk, weapon_cost=weapon_cost))
    for (k1, v1) in weapons.items():
        Atk = v1["+atk"]
        Cost = v1["Cost"]
        print("{:<{weapon_name}} {:<{weapon_atk}} {:<{weapon_cost}}".format(k1, Atk, Cost, weapon_name=weapon_name, weapon_atk=weapon_atk, weapon_cost=weapon_cost))
    option = input("You have %s gold. What would you like to buy?" % player.gold)
    if option is not None:
        player.curweap = list(armor.keys())[(int(option) - 1)] ##get the key the corresponds to the number typed in
        print(player.curweap)
    main()

def armor_store():
    armor_name = max(map(len, armor)) + 2
    armor_def = len(str(max(int(d['+def']) for d in armor.values()))) + 2
    armor_cost = len(str(max(int(d['Cost']) for d in armor.values())))

    print("{:<{armor_name}} {:<{armor_def}} {:<{armor_cost}}".format('Armor', 'Def', 'Cost', armor_name=armor_name, armor_def=armor_def, armor_cost=armor_cost))
    for (k1, v1) in enumerate(armor.items()):
        Def = v1["+def"]
        Cost = v1["Cost"]
        print("{:<{armor_name}} {:<{armor_def}} {:<{armor_cost}}".format(k1, Def, Cost, armor_name=armor_name, armor_def=armor_def, armor_cost=armor_cost))
    option = input("You have %s gold. What would you like to buy?" % player.gold)
    if option is not None:
        player.curarmor = list(armor.keys())[(int(option) - 1)] ##get the key the corresponds to the number typed in
        print(player.curarmor)
    main()

# main()
# weapon_name = max(map(len, weapons)) + 2
# x = input('weapons or armor?')
# if x is '1':
#     y = str('weapons')
# else: y = str('armor')
# print(y)
# print(y+'_name')
#
# print("{:<5} {:<23} {:^5} {:^6}".format('Num', 'Name', 'Atk', 'Cost'))
# for num, (k, v) in enumerate(weapons.items(), start=1):
#     print("{:<4}: {: <22} :{:^5}: {:^5}".format(num, k, v['+atk'], v['Cost']))

def text_objects(text, font):
    text_surface = font.render(text, True, black)
    return text_surface, text_surface.get_rect()

def message_display(text):
    my_font = pygame.font.SysFont('ariel.ttf', 30)
    text_surface, text_rect = text_objects(text, my_font)
    text_rect.center = (screen_width/2, screen_height/2)
    screen.blit(text_surface, text_rect)

    pygame.display.update()

    time.sleep(5)

def button(msg, x, y, w, h, ic, ac, action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    if x + w > mouse[0] > x and y + h > mouse[1] > y:
        pygame.draw.rect(screen, ac, (x, y, w, h))
        if click[0] == 1 and action != None:
            action()
    else:
        pygame.draw.rect(screen, ic, (x, y, w, h))

    small_text = pygame.font.SysFont('ariel', 20)
    text_surface, text_rect = text_objects(msg, small_text)
    text_rect.center = ((x + (w / 2)), (y + (h / 2)))
    screen.blit(text_surface, text_rect)

def game_intro():

    intro = True

    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        screen.fill(white)
        med_text = pygame.font.SysFont('ariel.ttf', 30)
        text_surface, text_rect = text_objects("Ohai", med_text)
        text_rect.center = (screen_width/2, screen_height/2)
        screen.blit(text_surface, text_rect)

        button('New Game', 250, 350, 100, 50, khaki, aqua, game_loop)
        button('Options', 450, 350, 100, 50, khaki, aqua, quit_game)

        pygame.display.update()
        clock.tick(15)

def quit_game():
    pygame.quit()
    quit()

def game_loop():

    game_exit = False

    while game_exit is False:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_exit = True
        screen.fill(white)
        message_display('Hi')
        pygame.display.flip()

game_intro()
pygame.quit()


file_news_title = "inputs/news_title.txt"
file_news_dict = "inputs/news_dict.txt"
file_company_category = "inputs/company_category.txt"
news_title = open(file_news_title,"r",encoding="utf-8")
news_dict = open(file_news_dict,"r",encoding="utf-8")
company_category = open(file_company_category,"r",encoding="utf-8")
list1 = input().split(",")
industry = list1[0]
total_num = list1[1]
num_each_round = list1[2].split(":")

title = []
for i, d in enumerate(news_dict):  # 先將關鍵字照長度排列
    title.append([d[0:-2],d[-2:-1]])
title.sort(key=lambda k:len(k[0]),reverse=True)
# print(title)
company_list=[]
index = -1
for i, d in enumerate(company_category):  # 找出關注的公司
    index = d.find(" ")
    if d[index+1:-1] == industry:
        company_list.append(d[0:index])
# print(company_list)
para = []
for i, d in enumerate(news_title):  # 將新聞標題轉成list
    d = d.replace(" ","")
    d = d.replace("\n","")
    para.append(d)

news = []
index = -1
for i ,d in enumerate(para):  # 建立新的list放要關注的新聞標題
    for j in range(len(company_list)):
        index =  d.find(company_list[j])
        if index != -1:
            news.append(d)
# print(news)
company_times = []  # 計算每個標題中專注的公司與其出現次數
for i,d in enumerate(news):
    for j in range(len(company_list)):
        appear_time = d.count(company_list[j])
        if appear_time != 0:
            company_times.append([company_list[j],appear_time,i])
# print(company_times)

for i in range(len(news)):
    for j in range(len(title)):
        index = -1
        while news[i].find(title[j][0],index+1) != -1:
            index = news[i].find(title[j][0], index + 1)
            print(index)
            news[i] = news[i][0:index-1]+"/"+title[j][0]+"/"+news[i][index+len(title[j][0]):]
            index += 1
print(news)


from collections import namedtuple

Region = namedtuple('Region', 'name lat lon')
regions = [
    Region(name='MED', lat=(30, 45.99854660342), lon=(-6, 36.500480651855)),
]

def from_coordinates(lon, lat):
    if not lat['min'] < lat['max']:
        lat['min'], lat['max'] = lat['max'], lat['min']

    if not lon['min'] < lon['max']:
        lon['min'], lon['max'] = lon['max'], lon['min']

    for r in regions:
        if (r.lat[0] <= lat['min'] and lat['max'] <= r.lat[1]) and (
                r.lon[0] <= lon['min'] and lon['max'] <= r.lon[1]):
            return r.name
    else:
        print('Could not figure out the region from the supplied coordinates')


import numpy as np
import matplotlib.pyplot as plt
from matplotlib import dates as mdates
import math

def showPredictedRatings(player):
    ageList, predictedRatingList = [], []
    for age in range(15, 40):
        ageList.append(age)
        predictedRating = player.calculateRating(age)
        predictedRatingList.append(predictedRating)
    ageArray = np.array(ageList)
    predictedRatingArray = np.array(predictedRatingList)
    x, y = ageArray, predictedRatingArray
    plt.plot(x, y)
    for xy in zip(x, y):
        plt.text(
            xy[0] - 0.5,
            xy[1],
            int(xy[1]),
            {
                'weight': 'bold',
                'size'  : 10,
            }
        )
    plt.title(
        'Predicted Ratings for {} over time'.format(player.name),
        fontdict = {
            'weight': 'bold'
        }
    )
    plt.xlabel('Age')
    plt.ylabel('Predicted Rating')
    plt.axvline(
        x[np.argmax(y)],
        color = 'lightgray',
        linestyle = '--'
    )
    plt.show()

def plotPlayer(player, axes, config, date = None):
    labelsOn, positionTextRotated, projectionOn, scaleForOverallRatingOn = [value for value in list(config.values())]
    blank = True if player is None else False
    axes.set(aspect='equal')
    frameSize = 2.5
    frameSize = frameSize * 100 if scaleForOverallRatingOn else frameSize

    if not blank:
        ### Calculate vertices
        skillDistribution = player.getSkillDistribution(player.getAgeOnDate(date))
        playerRating = player.ratings[date]['rating'] if date is not None else player.rating
        points = {}
        for j, (skill, value) in enumerate(skillDistribution.items()):
            if scaleForOverallRatingOn:
                value *= playerRating
            angle = 2 / len(skillDistribution) * j * np.pi
            pointX = value * np.sin(angle)
            pointY = value * np.cos(angle)
            points[skill] = {'x': pointX, 'y': pointY}
            if labelsOn:
                sidePointX = frameSize * np.sin(angle)
                sidePointY = frameSize * np.cos(angle)
                # labelOffset = 37.5 if scaleForOverallRatingOn else 0.375
                # labelX = (value + labelOffset) * np.sin(angle)
                # labelY = (value + labelOffset) * np.cos(angle)
                labelX = 290 * np.sin(angle)
                labelY = 290 * np.cos(angle)
                axes.plot((0, sidePointX), (0, sidePointY), color = 'blue', linewidth = 0.25)
                labelText = "{}\n{}".format(skill.capitalize(), int(value)) if scaleForOverallRatingOn else "{0}\n{1:.1%}".format(skill, value)
                axes.text(labelX, labelY, labelText, horizontalalignment = 'center', verticalalignment = 'center', fontdict = {'family': 'arial', 'size': 15})
        pointsList = list(points.values())
        pointsList.append(pointsList[0]) ### Duplicate first point as last point to complete the shape

        ### Add edges between vertices
        for j in range(len(pointsList) - 1):
            axes.plot(
                (pointsList[j]['x'], pointsList[j + 1]['x']),
                (pointsList[j]['y'], pointsList[j + 1]['y']),
                color = 'black'
            )

        ### Add rating projection to plot
        if projectionOn and player.age != player.peakAge:
            projectedSkillDistribution = player.getSkillDistribution(player.peakAge)
            projectedPlayerRating = player.getRating(age = player.peakAge)
            projectedPoints = {}
            for j, (skill, projectedValue) in enumerate(projectedSkillDistribution.items()):
                if scaleForOverallRatingOn:
                    projectedValue *= projectedPlayerRating
                angle = 2 / len(projectedSkillDistribution) * j * np.pi
                projectedPointX = projectedValue * np.sin(angle)
                projectedPointY = projectedValue * np.cos(angle)
                projectedPoints[skill] = {'x': projectedPointX, 'y': projectedPointY}
            projectedPointsList = list(projectedPoints.values())
            projectedPointsList.append(projectedPointsList[0]) ### Duplicate first point as last point to complete the shape

            ### Add edges between vertices
            projectedLineColour = 'green' if player.age < player.peakAge else 'red'

            for j in range(len(projectedPointsList) - 1):
                axes.plot(
                    (projectedPointsList[j]['x'], projectedPointsList[j + 1]['x']),
                    (projectedPointsList[j]['y'], projectedPointsList[j + 1]['y']),
                    color = projectedLineColour,
                    linestyle = 'dotted'
                )

    if not blank:
        xPoints = [point['x'] for point in pointsList]
        yPoints = [point['y'] for point in pointsList]
    else:
        xPoints = [frameSize, frameSize, -frameSize, -frameSize]
        yPoints = [frameSize, -frameSize, -frameSize, frameSize]
    axes.fill(xPoints, yPoints, color = 'lightgray')

    ### Frame plot/s with grey border
    # axes.plot((-frameSize, frameSize), (frameSize, frameSize), color = "lightgray")
    # axes.plot((frameSize, frameSize), (-frameSize, frameSize), color = "lightgray")
    # axes.plot((-frameSize, frameSize), (-frameSize, -frameSize), color = "lightgray")
    # axes.plot((-frameSize, -frameSize), (-frameSize, frameSize), color = "lightgray")

    ### Miscellaneous config
    axes.set_xlim(-frameSize, frameSize)
    axes.set_ylim(-frameSize, frameSize)
    axes.axis('off')
    if not blank and not labelsOn:
        axes.plot(0, 0, 'o')

    ### Add corner text
    # if not blank:
    #     cornerFontDict = {
    #         'family': 'arial',
    #         'size': 9,
    #         'weight': 'bold'
    #     }
    #     axes.text(
    #         -0.975 * frameSize,
    #         0.95 * frameSize,
    #         '{}\n{}'.format(player.name[0], player.name[1]),
    #         horizontalalignment = 'left',
    #         verticalalignment = 'top',
    #         fontdict = (lambda a, b: a.update(b) or a)(copy.deepcopy(cornerFontDict), {'size': 10})
    #     )
    #     axes.text(
    #         0.975 * frameSize,
    #         0.95 * frameSize,
    #         'Age: {}\nRating: {}'.format(int(player.age), int(player.rating)),
    #         horizontalalignment = 'right',
    #         verticalalignment = 'top',
    #         fontdict = cornerFontDict
    #     )
    #     axes.text(
    #         0.975 * frameSize,
    #         -0.95 * frameSize,
    #         'Peak Age: {}\nPeak Rating: {}'.format(int(player.peakAge), int(player.peakRating)),
    #         horizontalalignment = 'right',
    #         verticalalignment = 'bottom',
    #         fontdict = cornerFontDict
    #     )
    #     poSuDict = player.getPositionSuitabilities()
    #     bestPosition = player.getBestPosition()
    #     if not positionTextRotated:
    #         positionText = ''
    #         for position in sorted(poSuDict, key = poSuDict.get, reverse = True):
    #             suitability = poSuDict[position]
    #             if suitability >= 0.975:
    #                 positionText += '{0}: {1:.1%}\n'.format(
    #                     playerConfig['positions'][position]['realName'],
    #                     suitability
    #                 )
    #         if positionText == '':
    #             positionText = '{0}: {1:.1%}'.format(
    #                 playerConfig['positions'][bestPosition]['realName'],
    #                 poSuDict[bestPosition]
    #             )
    #         else:
    #             positionText = positionText.rstrip()
    #         axes.text(
    #             -0.975 * frameSize,
    #             -0.95 * frameSize,
    #             positionText,
    #             horizontalalignment = 'left',
    #             verticalalignment = 'bottom',
    #             fontdict = cornerFontDict
    #         )
    #     else:
    #         realPositionName = playerConfig['positions'][bestPosition]['realName']
    #         positionText = realPositionName.replace(' ', '\n')
    #         axes.text(
    #             -0.975 * frameSize,
    #             -0.95 * frameSize,
    #             positionText,
    #             horizontalalignment = 'left',
    #             verticalalignment = 'bottom',
    #             fontdict = cornerFontDict,
    #             rotation = 90
    #         )

def showSkillDistribution(players, date = None, labels = None, projection = False, scaleForOverallRating = True):
    if not isinstance(players, list):
        players = [players]
    numPlayers = len(players)
    if numPlayers > 10:
        print("Too many players")
        return
    if labels is None:
        if numPlayers > 2:
            labels = False
        else:
            labels = True
    positionTextRotated = True if numPlayers > 2 else False
    plotConfig = {
        'labelsOn': labels,
        'positionTextRotated': positionTextRotated,
        'projectionOn': projection,
        'scaleForOverallRatingOn': scaleForOverallRating
    }
    rows = 1 if numPlayers < 3 else 2
    cols = math.ceil(numPlayers / rows)
    fig, axes = plt.subplots(nrows = rows, ncols = cols)
    if numPlayers == 1:
        plotPlayer(players[0], axes, plotConfig, date)
    elif numPlayers == 2:
        for i in range(cols):
            plotPlayer(players[i], axes[i], plotConfig, date)
    else:
        p = 0
        for i in range(rows):
            for j in range(cols):
                if p < numPlayers:
                    plotPlayer(players[p], axes[i][j], plotConfig, date)
                else:
                    plotPlayer(None, axes[i][j], plotConfig, date)
                p += 1

    # ### Show plot
    # plt.show()
    plt.tight_layout()
    return fig

def showPlayerForm(player):
    fig = plt.figure()
    fig.add_subplot(111)
    x = list(player.forms.keys())
    y = list(player.forms.values())
    x = mdates.date2num(x)
    plt.axis('off')
    plt.plot_date(x, y, 'b-')
    return fig

def showPlayerDevelopment(player, date = None):
    fig = plt.figure()
    fig.add_subplot(111)
    if date is not None:
        x = range(len([k for k in player.ratings.keys() if k <= date]))
        yR = [v['rating'] for k, v in player.ratings.items() if k <= date]
        yPR = [v['peakRating'] for k, v in player.ratings.items() if k <= date]
    else:
        x = range(len(player.ratings.keys()))
        yR = [v['rating'] for v in player.ratings.values()]
        yPR = [v['peakRating'] for v in player.ratings.values()]
    plt.title('Development Graph', fontsize = 14)
    plt.xlabel('Day', fontsize = 12, labelpad = 8)
    plt.ylabel('Rating', fontsize = 12, labelpad = 8)
    fadeRange = 10
    for plot, colorTuple in zip([yR, yPR], [[0, 0, 1], [0.68, 0.85, 0.90]]):
        for i in range(0, fadeRange + 1):
            for y, strength in zip([plot[0], plot[-1]], [1 - (i / fadeRange), 0 + (i / fadeRange)]):
                plt.gca().axhline(
                    y,
                    (1 / fadeRange) * i - (1 / fadeRange), ### xmin
                    (1 / fadeRange) * i, ### xmax
                    color = colorTuple + [strength],
                    linestyle = '--',
                    linewidth = strength
                )
    plt.plot(x, yR, 'b-')
    plt.plot(x, yPR, color = 'lightblue', linestyle = 'solid')
    return fig


# -*- coding: utf-8 -*-
"""
@create: 2022-07-22 17:54:46.

@author: ppolxda

@desc: sql Api
"""
from contextlib import asynccontextmanager
from functools import partial
from functools import wraps
from inspect import signature
from typing import Awaitable
from typing import Callable
from typing import List
from typing import Optional
from typing import Type
from typing import TypeVar
from typing import Union

from sqlalchemy import delete
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.ext.asyncio import async_sessionmaker
from sqlalchemy.orm import load_only

from .. import models as mm
from .. import schemas as sa
from .base import BackendBase

def session_begin(session_maker: async_sessionmaker[AsyncSession]):
    """事务上下文管理."""
    __session_maker = session_maker

    @asynccontextmanager
    async def _session_begin():
        async with __session_maker() as session:
            try:
                assert isinstance(session, AsyncSession)
                yield session
            except Exception as ex:
                await session.rollback()
                raise ex
            else:
                await session.commit()

    return _session_begin

def find_filed_idx(field: str, func: Callable[..., Awaitable]) -> int:
    """Find session index in function call parameter."""
    func_params = signature(func).parameters
    try:
        # func_params is an ordered dict -- this is the "recommended" way of getting the position
        session_args_idx = tuple(func_params).index(field)
    except ValueError:
        raise ValueError(
            f"Function {func.__qualname__} has no `{field}` argument"
        ) from None

    return session_args_idx

find_session_idx = partial(find_filed_idx, "session")
RT = TypeVar("RT")

def provide_db(func: Callable[..., Awaitable[RT]]) -> Callable[..., Awaitable[RT]]:
    """参数动态注入装饰器."""
    session_args_idx = find_session_idx(func)

    @wraps(func)
    async def wrapper(self: "DBBackend", *args, **kwargs) -> RT:
        if "session" in kwargs or session_args_idx < len(args):
            return await func(self, *args, **kwargs)
        else:
            async with self.session_begin() as session:
                return await func(self, *args, session=session, **kwargs)

    return wrapper

class DBBackendClient(object):
    """DBBackendClient."""

    def __init__(
        self,
        async_session: async_sessionmaker[AsyncSession],
        project: str = "default",
        default_template: Optional[dict] = None,
        query_max_limit: int = 1000,
    ):
        """init."""
        super().__init__()
        if default_template is None:
            default_template = {}

        self.project_name = project
        self.async_session = async_session
        self.default_template = default_template
        self.session_begin = session_begin(self.async_session)
        self.query_max_limit = query_max_limit

    @provide_db
    async def _clean_all(self, session: Optional[AsyncSession] = None):
        """Clean database, This api only use for test."""
        assert session
        for tbl in reversed(mm.Base.metadata.sorted_tables):
            await session.execute(delete(tbl))
            await session.commit()

    @provide_db
    async def _get_template_list(
        self,
        tid: Optional[str] = None,
        version_id: Optional[str] = None,
        project: Optional[str] = None,
        template_name: Optional[str] = None,
        template_type: Optional[str] = None,
        limit: int = 10,
        offset: int = 0,
        session: Optional[AsyncSession] = None,
    ) -> List[sa.TemplateInfo]:
        """Get templates."""
        query = (
            select(mm.Templates)
            .options(
                load_only(
                    mm.Templates.created_at,
                    mm.Templates.updated_at,
                    mm.Templates.tid,
                    mm.Templates.version_id,
                    mm.Templates.template_name,
                    mm.Templates.template_type,
                    mm.Templates.project,
                )
            )
            .order_by(mm.Templates.created_at.desc())
            .limit(min(limit, self.query_max_limit))
            .offset(offset)
        )
        query = self.pick_condition(
            query, tid, version_id, project, template_name, template_type
        )
        assert session
        results = await session.execute(query)
        return [sa.TemplateInfo.from_orm(i) for i in results.scalars()]

    @provide_db
    async def _get_templates_version_list(
        self,
        tid: str,
        project: Optional[str] = None,
        limit: int = 10,
        offset: int = 0,
        session: Optional[AsyncSession] = None,
    ) -> List[sa.TemplateInfo]:
        query = (
            select(mm.TemplatesVersion)
            .options(
                load_only(
                    mm.TemplatesVersion.created_at,
                    mm.TemplatesVersion.updated_at,
                    mm.TemplatesVersion.tid,
                    mm.TemplatesVersion.version_id,
                    mm.TemplatesVersion.template_name,
                    mm.TemplatesVersion.template_type,
                    mm.TemplatesVersion.project,
                )
            )
            .order_by(mm.TemplatesVersion.created_at.desc())
            .limit(min(limit, self.query_max_limit))
            .offset(offset)
        )
        query = self.pick_condition(
            query, tid, None, project, None, None, class_=mm.TemplatesVersion
        )

        assert session
        results = await session.execute(query)
        return [sa.TemplateInfo.from_orm(i) for i in results.scalars()]

    @provide_db
    async def _is_template_exist(
        self,
        tid: str,
        version_id: Optional[str] = None,
        project: Optional[str] = None,
        session: Optional[AsyncSession] = None,
    ) -> bool:
        """Get templates."""
        query = select(mm.Templates.tid).limit(1)
        query = self.pick_condition(query, tid, version_id, project)

        assert session
        results = await session.execute(query)
        tmpl = results.scalars().first()
        return True if tmpl else False

    @provide_db
    async def _get_template(
        self,
        tid: str,
        project: Optional[str] = None,
        session: Optional[AsyncSession] = None,
        lock: bool = False,
    ) -> Optional[mm.Templates]:
        """Get templates."""
        query = select(mm.Templates).limit(1)
        query = self.pick_condition(query, tid, None, project)
        if lock:
            query = query.with_for_update()

        assert session
        results = await session.execute(query)
        tmp = results.scalars().first()
        if not tmp:
            return None
        return tmp

    @provide_db
    async def _get_template_version(
        self,
        tid: str,
        version_id: str,
        project: Optional[str] = None,
        session: Optional[AsyncSession] = None,
        lock: bool = False,
    ) -> Optional[mm.TemplatesVersion]:
        """Get templates."""
        query = select(mm.TemplatesVersion).limit(1)
        query = self.pick_condition(
            query, tid, version_id, project, class_=mm.TemplatesVersion
        )
        if lock:
            query = query.with_for_update()

        assert session
        results = await session.execute(query)
        tmp = results.scalars().first()
        if not tmp:
            return None
        return tmp

    @provide_db
    async def _lock_template_versions(
        self,
        tid: str,
        project: str,
        session: Optional[AsyncSession] = None,
    ) -> List[mm.TemplatesVersion]:
        """Get templates."""
        query = (
            select(mm.TemplatesVersion)
            .options(
                load_only(
                    mm.TemplatesVersion.created_at, mm.TemplatesVersion.version_id
                )
            )
            .where(
                mm.TemplatesVersion.tid == tid,
                mm.TemplatesVersion.project == project,
            )
            .with_for_update()
        )

        assert session
        results = await session.execute(query)
        return [i for i in results.scalars()]

    def pick_condition(
        self,
        query,
        tid: Optional[str] = None,
        version_id: Optional[str] = None,
        project: Optional[str] = None,
        template_name: Optional[str] = None,
        template_type: Optional[str] = None,
        class_: Union[Type[mm.Templates], Type[mm.TemplatesVersion]] = mm.Templates,
    ):
        """Pick template Query conndition."""
        if tid:
            query = query.where(class_.tid == tid)

        if not project:
            project = self.project_name

        if project:
            query = query.where(class_.project == project)

        if version_id:
            query = query.where(class_.version_id == version_id)

        if template_name:
            query = query.where(class_.template_name == template_name)

        if template_type:
            query = query.where(class_.template_type == template_type)
        return query

    @provide_db
    async def _put_template(
        self,
        tid: str,
        version_id: str,
        template_name: str,
        template_type: str,
        report: dict,
        project: Optional[str] = None,
        session: Optional[AsyncSession] = None,
    ) -> sa.BaseTemplateId:
        """Put templates."""
        assert session
        # 更新或创建template
        project = self.project_name if not project else project
        add_list: List[Union[mm.TemplatesVersion, mm.Templates]] = [
            mm.TemplatesVersion(
                tid=tid,
                version_id=version_id,
                project=project,
                template_name=template_name,
                template_type=template_type,
                template_config=report,
            ),
        ]
        templage = await self._get_template(tid, session=session, lock=True)
        if templage:
            templage.project = project
            templage.version_id = version_id
            templage.template_name = template_name
            templage.template_type = template_type
            templage.template_config = report

        else:
            add_list.append(
                mm.Templates(
                    tid=tid,
                    version_id=version_id,
                    project=project,
                    template_name=template_name,
                    template_type=template_type,
                    template_config=report,
                )
            )

        session.add_all(add_list)
        return sa.BaseTemplateId(
            tid=tid,
            version_id=version_id,
        )

    @provide_db
    async def _delete_template(
        self,
        tid: str,
        version_id: Optional[str] = None,
        project: Optional[str] = None,
        session: Optional[AsyncSession] = None,
    ):
        """Delete templates version."""
        assert session
        project = self.project_name if not project else project
        # if tid not exist, do not anything
        template = await self._get_template(
            tid, project=project, lock=True, session=session
        )
        if not template:
            return

        if version_id:
            query = delete(mm.TemplatesVersion).where(
                mm.TemplatesVersion.tid == tid,
                mm.TemplatesVersion.version_id == version_id,
                mm.TemplatesVersion.project == project,
            )
            await session.execute(query)

            versions = await self._lock_template_versions(tid, project, session=session)
            versions = sorted(
                iter(i for i in versions if i.version_id != version_id),
                key=lambda x: x.created_at,
            )

            # if version table empty, all file deleted
            if versions:
                last_version = await self._get_template_version(
                    tid, versions[-1].version_id, project=project, session=session
                )
                assert last_version
                template.version_id = last_version.version_id
                template.template_type = last_version.template_type
                template.template_name = last_version.template_name
                template.template_config = last_version.template_config

            else:
                query = delete(mm.Templates).where(
                    mm.Templates.tid == tid,
                    mm.Templates.project == project,
                )
                await session.execute(query)

        else:
            query = delete(mm.TemplatesVersion).where(
                mm.TemplatesVersion.tid == tid,
                mm.TemplatesVersion.project == project,
            )
            await session.execute(query)

            query = delete(mm.Templates).where(
                mm.Templates.tid == tid,
                mm.Templates.project == project,
            )
            await session.execute(query)

class DBBackend(DBBackendClient, BackendBase):
    """DBBackend."""

    async def clean_all(self):
        """Clean database, This api only use for test."""
        await self._clean_all()

    async def is_template_exist(
        self,
        tid: str,
        version_id: Optional[str] = None,
        project: Optional[str] = None,
    ) -> bool:
        """Is templates Exist."""
        project = self.project_name if not project else project
        r = await self._is_template_exist(tid, version_id, project)
        return r

    async def get_templates_list(
        self,
        tid: Optional[str] = None,
        version_id: Optional[str] = None,
        project: Optional[str] = None,
        template_name: Optional[str] = None,
        template_type: Optional[str] = None,
        limit: int = 10,
        offset: int = 0,
    ) -> List[sa.TemplateInfo]:
        """Get templates list."""
        project = self.project_name if not project else project
        r = await self._get_template_list(
            tid, version_id, project, template_name, template_type, limit, offset
        )
        return r

    async def get_templates_version_list(
        self,
        tid: str,
        project: Optional[str] = None,
        limit: int = 10,
        offset: int = 0,
    ) -> List[sa.TemplateInfo]:
        """Get templates version list."""
        project = self.project_name if not project else project
        r = await self._get_templates_version_list(tid, project, limit, offset)
        return r

    async def get_template(
        self,
        tid: str,
        version_id: Optional[str] = None,
        project: Optional[str] = None,
    ) -> Optional[sa.TemplateConfigInfo]:
        """Get templates."""
        project = self.project_name if not project else project
        if version_id:
            r = await self._get_template_version(tid, version_id, project)
        else:
            r = await self._get_template(tid, project)

        if not r:
            return None

        y = sa.TemplateConfigInfo.from_orm(r)
        y.report = r.template_config if r.template_config else {}
        return y

    async def put_template(
        self,
        template_name: str,
        template_type: str,
        report: dict,
        tid: Optional[str] = None,
        project: Optional[str] = None,
    ) -> sa.BaseTemplateId:
        """Put templates."""
        if not report:
            if self.default_template:
                report = self.default_template
            else:
                report = {}

        if tid is None:
            tid = await self.gen_uuid_object_key(project=project)

        # 创建template
        version_id = self.gen_uuid()
        project = self.project_name if not project else project
        r = await self._put_template(
            tid, version_id, template_name, template_type, report, project
        )
        return r

    async def delete_template(
        self,
        tid: str,
        version_id: Optional[str] = None,
        project: Optional[str] = None,
    ):
        """Delete templates version."""
        project = self.project_name if not project else project
        r = await self._delete_template(tid, version_id, project)
        return r


keys = {
    'a': 2,
    'b': 2,
    'c': 2,
    'd': 3,
    'e': 3,
    'f': 3,
    'g': 4,
    'h': 4,
    'i': 4,
    'j': 5,
    'k': 5,
    'l': 5,
    'm': 6,
    'n': 6,
    'o': 6,
    'p': 7,
    'q': 7,
    'r': 7,
    's': 7,
    't': 8,
    'u': 8,
    'v': 8,
    'w': 9,
    'x': 9,
    'y': 9,
    'z': 9,
    ' ': 0
}
words = []
num_read_lines = int(input())
num_valid = 0

def coconut(s):
    global num_valid
    valid = True
    for q in range(len(key_presses)):
        if keys.get(word[q]) != key_presses[q]:
            valid = False
            break
    if valid:
        num_valid += 1

for i in range(num_read_lines):
    words.append(input())

key_presses = [int(n) for n in input()]

for word in words:
    if len(word) == len(key_presses):
        coconut(word)

print(str(num_valid))


import cgi
import json
import logging
import operator
import re
import urlparse
logging.basicConfig(format='%(process)-6d %(levelname)-8s %(message)s', level=logging.DEBUG)
logger = logging.getLogger(__name__)

__author__ = 'Stephen McGregor <s.mcgregor@griffith.edu.au>'
__description__ = """Modular, self documenting API server using Python"""
__version__ = '0.0.31'
__license__ = 'MIT'

def filter_by_list(fdict, flist):
	def inner(key):
		return key[0] in flist
	return dict(filter(inner, fdict.items()))

class __Route(object):
	def __init__(self, path, version="v1", notAPI=False):
		if notAPI:
			self.path = path
		else:
			self.path = '/' + '/'.join(['api', version, path.lstrip('/')])
		self.priority = 10

	def __eq__(self, *args):
		return False

	def __lt__(self, other_route):
		return self.priority < other_route.priority

	def __gt__(self, other_route):
		return self.priority > other_route.priority

class StringRoute(__Route):
	def __init__(self, path, **kwargs):
		super(StringRoute, self).__init__(path, **kwargs)
		self.priority = 1

	def __eq__(self, wsgi_path):
		return self.path == wsgi_path

class RegexRoute(__Route):
	def __init__(self, path, **kwargs):
		super(RegexRoute, self).__init__(path, **kwargs)
		self.path = "^" + self.path
		self.regex = re.compile(self.path)
		self.priority = 14

	def __eq__(self, wsgi_path):
		return self.regex.match(wsgi_path)

class Request(object):
	def __init__(self, environ):
		self.headers = {'content-type': 'text/html'}
		self.status = '200 OK'
		self.method = environ['REQUEST_METHOD']
		self._ENV = environ
		self._GET = self.__split_get()
		self._POST = self.__split_post()

	def set_status(self, status):
		self.status = status

	def set_header(self, header, value):
		self.headers.update({header: value})

	def __split_get(self):
		return urlparse.parse_qs(self._ENV.get('QUERY_STRING', ''), keep_blank_values=True)

	def __split_post(self):
		safe_env = filter_by_list(self._ENV, ['CONTENT_LENGTH', 'CONTENT_TYPE', 'REQUEST_METHOD'])
		return cgi.FieldStorage(fp=self._ENV['wsgi.input'], environ=safe_env, keep_blank_values=1)

class Engine(object):
	_instance = None
	def __new__(cls, *args, **kwargs):
		if not cls._instance:
			cls._instance = super(Engine, cls).__new__(cls, *args, **kwargs)
		return cls._instance

	def __init__(self):
		if not hasattr(self, 'routes'):
			self.routes = []

	def register(self, path_handler, handler=None):
		'''Route decorator, @application_instance.register(..)'''

		def wrapper(handler):
			func_handler = path_handler

			if isinstance(path_handler, str):
				func_handler = StringRoute(path_handler)

			logger.info("Registered route %s to %s", func_handler.path, handler.__name__)

			self.routes.append((func_handler, handler()))

			self.routes = sorted(self.routes, key=operator.itemgetter(0))
		return wrapper

	def wsgi(self, environ, start_response):
		'''WSGI compliant callable, only ever called from __call__'''

		path = environ['PATH_INFO']

		for path_handler in self.routes:
			if path_handler[0] == path:
				try:
					handler = path_handler[1]
					req = Request(environ)

					if hasattr(handler, 'do_' + req.method):
						func_output = getattr(handler, 'do_' + req.method)(req)
					else:
						start_response('405 Method Not Allowed', [('content-type', 'text/html')])
						return (repr(req.method) + ' Method Not Allowed',)

					if type(func_output) == dict:
						func_output = json.dumps(func_output)
						req.set_header('content-type', 'application/json')
					elif type(func_output) == list:
						func_output = ''.join(func_output)
					elif type(func_output) == unicode:
						func_output = func_output.encode('utf8')

					start_response(req.status, req.headers.items())
					return func_output
				except Exception as e:
					import traceback
					logger.error("%s\t%s", e, traceback.format_exc())
					start_response('500 Internal Server Error', [('content-type', 'text/plain')])
					return "An incident has been recorded:\n" + repr(e)

		start_response('404 Not Found', [('content-type', 'text/html')])
		return ('Not Found',)

	def __call__(self, environ, start_response):
		return self.wsgi(environ, start_response)

	def run(self, host="0.0.0.0", port=8000):
		'''Run this instance of engine using simple_server'''
		from wsgiref.simple_server import make_server
		srv = make_server(host, port, self)
		try:
			srv.serve_forever()
		except KeyboardInterrupt:
			logger.critical("Got CTRL + C. Sent shutdown to server.")

if __name__ == '__main__':
	app = Engine()
	@app.register(StringRoute('/'))
	class IndexRoute(object):
		def do_GET(self, request):
			return {'status': 'working'}
	app.run()


import traceback

from typing import Dict
import bundle
import fhir_client
import json
import logger_util
import pathlib
import random

class Uploader:
  """Uploads FHIR resources to either OpenMRS or any other FHIR Server."""

  def __init__(self, client: fhir_client.FhirClient):
    self.fhir_client = client
    self.logger = logger_util.create_logger(self.__class__.__module__,
                                            self.__class__.__name__)

  def fetch_location(self) -> Dict[str, str]:
    """Get map of all location_id/location_name stored in sink.

    Returns:
      Dictionary of location_id/location_name
    """
    location_map = {}
    try:
      entries = self.fhir_client.get_resource('Location')['entry']
      for entry in entries:
        location_id = entry['resource']['id']
        location_name = entry['resource']['name']
        location_map[location_id] = location_name
      return location_map
    except KeyError:
      self.logger.warning('No locations found in sink. Using Unknown Location.')
      return {'8d6c993e-c2cc-11de-8d13-0010c6dffd0f': 'Unknown Location'}

  def _upload_resource(self, resource: str, data: Dict[str, str]):
    """Used to POST when OpenMRS is the target sink."""
    self.fhir_client.post_single_resource(resource, data)
    return self.fhir_client.response['id']

  def upload_openmrs_bundle(self, json_file: pathlib.Path,
      locations: Dict[str, str]):
    """Uploads FHIR Bundle to OpenMRS via Patients, Encounters, Observations.

    As the OpenMRS FHIR Module does not support uploading Bundle transactions,
    the Bundle is uploaded in 3 steps. First the Patient resource is uploaded,
    then the encounters, then the observations. Before uploading each resource,
    we have to manipulate the JSON for that resource into a form OpenMRS will
    accept.

    As OpenMRS does not support PUT requests, each time we POST a resource, a
    new ID for that resource is generated. This means we need to track the new
    id for each resource. Some resources depend on the other resources' new id.
    For example, before POSTing Encounter resource, we need to update it with
    the new Patient id generated by OpenMRS for the Encounter upload to work.

    Args:
      json_file: The JSON file that needs to be uploaded.
      locations: dictionary of location_id/location_name
    """

    try:
      each_bundle = _convert_to_bundle(json_file)
      each_bundle.extract_resources()
      self.logger.info('Uploading %s' % each_bundle.file_name)

      each_bundle.openmrs_patient.openmrs_convert()
      each_bundle.openmrs_patient.base.new_id = self._upload_resource(
          resource='Patient', data=each_bundle.openmrs_patient.base.json)

      self.logger.debug('New Patient ID is %s' %
                        each_bundle.openmrs_patient.base.new_id)

      for openmrs_encounter in each_bundle.openmrs_encounters:
        location = random.choice(list(locations.items()))
        openmrs_encounter.openmrs_convert(
            each_bundle.openmrs_patient.base.new_id, location)
        openmrs_encounter.base.new_id = self._upload_resource(
            resource='Encounter', data=openmrs_encounter.base.json)

      for openmrs_observation in each_bundle.openmrs_observations:
        openmrs_observation.openmrs_convert(
            each_bundle.openmrs_patient.base.new_id,
            each_bundle.openmrs_encounters)
        openmrs_observation.new_id = self._upload_resource(
            resource='Observation', data=openmrs_observation.base.json)

      self.logger.info('Successfully uploaded %s' % each_bundle.file_name)
      each_bundle.save_mapping()

    except ValueError:
      self.logger.error('Error uploading %s.\n%s' %
                        (json_file.as_posix(), traceback.format_exc()))

  def upload_bundle(self, json_file: pathlib.PosixPath):
    """Upload bundle to a FHIR Server via a POST request."""
    try:
      each_bundle = _convert_to_bundle(json_file)
      self.logger.info('Uploading %s' % each_bundle.file_name)
      self.fhir_client.post_bundle(data=each_bundle.bundle_dict)
      self.logger.info('Successfully uploaded %s' % each_bundle.file_name)

    except ValueError:
      self.logger.error('Error uploading %s.\n%s' %
                        (json_file.as_posix(), traceback.format_exc()))

def _convert_to_bundle(json_file: pathlib.Path) -> bundle.Bundle:
  """Loads content of the given file to create a Bundle object.

  Args:
   json_file: A JSON file that need to be converted to a Bundle resource.

  Returns:
    Bundle object
  """
  with open(json_file) as f:
    data = json.loads(f.read())
    return bundle.Bundle(json_file, data)


import netCDF4
import numpy as np
import matplotlib.pyplot as plt
from psutil import virtual_memory
import matplotlib.colors as mcolors
from matplotlib.patches import Rectangle
from matplotlib.collections import PatchCollection

plt.rcParams['font.family'] = 'Times New Roman'

def print_available_memory():
    mem = virtual_memory()
    available_gb = mem.available / 1024 / 1024 / 1024
    total_gb = mem.total / 1024 / 1024 / 1024
    print('Available memory: {:.2f} GB / {:.2f} GB ({:.2f} %)'.format(
        available_gb, total_gb, available_gb / total_gb * 100))

print_available_memory()

with netCDF4.Dataset('./GEBCO_2022.nc', 'r') as dataset:
    lon = dataset.variables['lon'][:]
    lat = dataset.variables['lat'][:]
    elevation = dataset.variables['elevation'][:]

step = 5
lon = lon[::step]
lat = lat[::step]
elevation = elevation[::step, ::step]

fig, ax = plt.subplots(figsize=(12, 12))

min_elevation, max_elevation = -11000, 10000
num_levels = (max_elevation - min_elevation) // 1000 + 1

levels = np.arange(min_elevation, max_elevation + 1000, 1000)
custom_cmap = plt.get_cmap('viridis', len(levels) - 1)
norm = mcolors.BoundaryNorm(levels, ncolors=len(levels) - 1)

im = ax.imshow(np.flipud(elevation), extent=(lon[0], lon[-1], lat[-1], lat[0]), cmap=custom_cmap, norm=norm, label='elevation')

red_mask = np.logical_and(elevation >= -10, elevation < 0)

rectangles=[]

for i in range(red_mask.shape[0] - 1):
    for j in range(red_mask.shape[1] - 1):
        if red_mask[i, j]:
            rect = Rectangle((lon[j], lat[-1 - i]), lon[j + 1] - lon[j], lat[-1 - i] - lat[-2 - i], edgecolor='none', facecolor='red')
            rectangles.append(rect)

pc = PatchCollection(rectangles, match_original=True)
ax.add_collection(pc)

ax.set_xlabel('longitude', fontsize=20)
ax.set_ylabel('latitude', fontsize=20)
ax.tick_params(labelsize=16)
ax.set_title('GEBCO_2022 ({}% resolution of original)'.format(
    round(100/step, 1)), fontsize=24)

cbar = fig.colorbar(im, ax=ax, label='elevation (m)', shrink=0.8, pad=0.05, boundaries=levels, ticks=levels)
cbar.ax.set_ylabel('elevation (m)', fontsize=20)
cbar.ax.tick_params(labelsize=16)
plt.subplots_adjust(bottom=0.15)
plt.tight_layout()

print_available_memory()

plt.savefig('glob_elv_gebco.png', dpi=1200)
#plt.show()

# Calculate the difference between latitudes and longitudes
lat_diff = np.diff(lat)
lon_diff = np.diff(lon)

# Convert latitudes and longitudes to radians
lat_rad = np.deg2rad(lat)
lon_rad = np.deg2rad(lon)

# Calculate the differences between adjacent latitudes and longitudes in radians
lat_diff_rad = np.deg2rad(lat_diff)
lon_diff_rad = np.deg2rad(lon_diff)

# Calculate the tile areas using spherical law of cosines
tile_areas = np.outer(lat_diff_rad, lon_diff_rad) * (6371.0 ** 2) * np.outer(np.cos(lat_rad[:-1]), np.ones_like(lon_diff))

# Calculate the mean and standard deviation of the tile areas
tile_areas_mean = np.mean(tile_areas)
tile_areas_std = np.std(tile_areas)

print(f"Tile area mean: {tile_areas_mean:.6f} km^2")
print(f"Tile area standard deviation: {tile_areas_std:.6f} km^2")

# Count the number of tiles with elevation between -10 and 0

num_tiles = np.sum((elevation >= -0.1) & (elevation < 0.1))
print(f"Number of tiles with elevation 0: {num_tiles}")

num_tiles = np.sum((elevation >= -10) & (elevation < 0))
print(f"Number of tiles with elevation between -10 and 0: {num_tiles}")

num_tiles = np.sum((elevation >= -20) & (elevation < -10))
print(f"Number of tiles with elevation between -20 and -10: {num_tiles}")

num_tiles = np.sum((elevation >= -30) & (elevation < -20))
print(f"Number of tiles with elevation between -30 and -20: {num_tiles}")

num_tiles = np.sum((elevation >= -40) & (elevation < -30))
print(f"Number of tiles with elevation between -40 and -30: {num_tiles}")

num_tiles = np.sum((elevation >= -50) & (elevation < -40))
print(f"Number of tiles with elevation between -50 and -40: {num_tiles}")

num_tiles = np.sum((elevation >= -60) & (elevation < -50))
print(f"Number of tiles with elevation between -60 and -50: {num_tiles}")

num_tiles = np.sum((elevation >= -70) & (elevation < -60))
print(f"Number of tiles with elevation between -70 and -60: {num_tiles}")

num_tiles = np.sum((elevation >= -80) & (elevation < -70))
print(f"Number of tiles with elevation between -80 and -70: {num_tiles}")

num_tiles = np.sum((elevation >= -90) & (elevation < -80))
print(f"Number of tiles with elevation between -90 and -80: {num_tiles}")

num_tiles = np.sum((elevation >= -100) & (elevation < -90))
print(f"Number of tiles with elevation between -100 and -90: {num_tiles}")

# Plot histogram of elevation values in the range -100 to -10 m
mask = np.logical_and(elevation >= -100, elevation < 0)
elevation_subset = elevation[mask]

plt.figure()
plt.hist(elevation_subset.flatten(), bins=50, color='b', edgecolor='k', alpha=0.7)
plt.xlabel('Elevation (m)', fontsize=20)
plt.ylabel('Frequency', fontsize=20)
plt.title('Histogram of Elevation Values', fontsize=24)
plt.tick_params(labelsize=16)
plt.grid(True)

plt.tight_layout()

plt.savefig('elevation_histogram_subset.png', dpi=1200)
#plt.show()


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

parser = argparse.ArgumentParser()
parser.add_argument('--mode',type=str,default='train',help='test or train,ex: --mode train')
parser.add_argument('--log',type = str, default='mnist_log/4_layer_tanh_sigmoid/train.log')
args = parser.parse_args()

def read_trainlog(logpath):

    epoch_list =  []
    iter_list = []
    loss_list = []
    acc_list = []
    batch_size = None
    for line in open(logpath,'r').readlines():
        line = line.strip()
        spt = line.split(' , ')
        epoch_list.append(int(spt[0].split(':')[-1]))
        iter_list.append(int(spt[1].split(':')[-1]))
        loss_list.append(float(spt[2].split(':')[-1]))
        acc_list.append(float(spt[3].split(':')[-1]))
        batch_size = int(spt[4].split(':')[-1])
    return epoch_list,iter_list,loss_list,acc_list,batch_size

def read_testlog(logpath):
    epoch_list =  []
    acc_list = []
    batch_size = None
    for line in open(logpath,'r').readlines():
        line = line.strip()
        spt = line.split(' , ')
        epoch_list.append(int(spt[0].split(':')[-1]))
        acc_list.append(float(spt[1].split(':')[-1]))
        batch_size = int(spt[2].split(':')[-1])

    return epoch_list,acc_list,batch_size

if __name__ == '__main__':
    data = None
    if args.mode == 'train':
        epoch_list,iter_list,loss_list,acc_list,batch_size = read_trainlog(args.log)
        max_epoch = np.max(epoch_list)+1
        acc_epoch_array = np.zeros((max_epoch,1))
        loss_epoch_array = np.zeros((max_epoch,1))
        for i,epoch in enumerate(epoch_list):
            acc_epoch_array[epoch] += acc_list[i]
            loss_epoch_array[epoch] += loss_list[i]
        iter_num = np.max(iter_list)
        acc_epoch_array /= iter_num
        loss_epoch_array /= iter_num

        color_set = 'r' if 'relu' in args.log else 'b'

        # plot
        epoch_array = np.linspace(start=0,stop= max_epoch-1,num = max_epoch ).reshape(-1,1)
        plt.subplots_adjust(hspace=0.5)
        plt.subplot(2,1,1)
        plt.plot(epoch_array,acc_epoch_array,c=color_set)
        plt.xlabel('epoch')
        plt.ylabel('accuracy')
        plt.title('Train accuracy')
        plt.subplot(2,1,2)
        plt.plot(epoch_array,loss_epoch_array,c=color_set)
        plt.xlabel('epoch')
        plt.ylabel('loss')
        plt.title('Train loss')
        plt.show()

    elif args.mode == 'test':
        epoch_list,acc_list,batch_size =read_testlog(args.log)

        color_set = 'r' if 'relu' in args.log else 'b'

        # plot
        plt.subplots_adjust(hspace=0.5)
        plt.subplot(1,1,1)
        plt.plot(epoch_list,acc_list,c=color_set)
        plt.xlabel('epoch')
        plt.ylabel('accuracy')
        plt.title('Test accuracy')
        plt.show()

    print('ggpd')