import inspect
import os
import shutil
import subprocess

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from src.utils.logging_config import log

class GraphExporter:
    GAME_LOGS_DATA_WORLD = '../datasets/retrosheets/game-logs_combined/game_logs_data-world.csv'
    GAME_LOGS_ABBREVIATIONS = '../datasets/retrosheets/game-logs_combined/TEAMABR.TXT'
    TEX_TEMPLATE_SLIDE = '../slides/graphs/tex/_template/slide.template'
    TEX_TEMPLATE_SECTION = '../slides/graphs/tex/_template/section.template'
    TEX_TEMPLATE_SUBSECTION = '../slides/graphs/tex/_template/subsection.template'
    TEX_TEMPLATE_MAIN = '../slides/graphs/tex/_template/main.template'
    TEX_OUTPUT_NAME = 'ss23_visualization_mlb.tex'

    OUTPUT_DIR = '../slides/graphs/img'
    OUTPUT_PDF = '../slides/pdf'
    OUTPUT_BEAMER = '../slides/graphs/tex/src/generated'

    START_YEAR = 1900

    def __init__(self):
        self.plots = []
        self.tex_slides = ''
        self._dtypeDict = {
            'date': str,
            'number_of_game': np.uint32,
            'day_of_week': str,
            'v_name': str,
            'v_league': str,
            'v_game_number': np.int32,
            'h_name': str,
            'h_league': str,
            'h_game_number': np.int32,
            'v_score': np.int32,
            'h_score': np.int32,
            'length_outs': np.int32,
            'day_night': str,
            'completion': str,
            'forefeit': str,
            'protest': str,
            'park_id': str,
            'attendance': np.int32,
            'length_minutes': np.int32,
            'v_line_score': str,
            'h_line_score': str,
            'v_at_bats': np.int32,
            'v_hits': np.int32,
            'v_doubles': np.int32,
            'v_triples': np.int32,
            'v_homeruns': np.int32,
            'v_rbi': np.int32,
            'v_sacrifice_hits': np.int32,
            'v_sacrifice_flies': np.int32,
            'v_hit_by_pitch': np.int32,
            'v_walks': np.int32,
            'v_intentional walks': np.int32,
            'v_strikeouts': np.int32,
            'v_stolen_bases': np.int32,
            'v_caught_stealing': np.int32,
            'v_grounded_into_double': np.int32,
            'v_first_catcher_interference': np.int32,
            'v_left_on_base': np.int32,
            'v_pitchers_used': np.int32,
            'v_individual_earned_runs': np.int32,
            'v_team_earned_runs': np.int32,
            'v_wild_pitches': np.int32,
            'v_balks': np.int32,
            'v_putouts': np.int32,
            'v_assists': np.int32,
            'v_errors': np.int32,
            'v_passed_balls': np.int32,
            'v_double_plays': np.int32,
            'v_triple_plays': np.int32,
            'h_at_bats': np.int32,
            'h_hits': np.int32,
            'h_doubles': np.int32,
            'h_triples': np.int32,
            'h_homeruns': np.int32,
            'h_rbi': np.int32,
            'h_sacrifice_hits': np.int32,
            'h_sacrifice_flies': np.int32,
            'h_hit_by_pitch': np.int32,
            'h_walks': np.int32,
            'h_intentional walks': np.int32,
            'h_strikeouts': np.int32,
            'h_stolen_bases': np.int32,
            'h_caught_stealing': np.int32,
            'h_grounded_into_double': np.int32,
            'h_first_catcher_interference': np.int32,
            'h_left_on_base': np.int32,
            'h_pitchers_used': np.int32,
            'h_individual_earned_runs': np.int32,
            'h_team_earned_runs': np.int32,
            'h_wild_pitches': np.int32,
            'h_balks': np.int32,
            'h_putouts': np.int32,
            'h_assists': np.int32,
            'h_errors': np.int32,
            'h_passed_balls': np.int32,
            'h_double_plays': np.int32,
            'h_triple_plays': np.int32,
            'hp_umpire_id': str,
            'hp_umpire_name': str,
            '1b_umpire_id': str,
            '1b_umpire_name': str,
            '2b_umpire_id': str,
            '2b_umpire_name': str,
            '3b_umpire_id': str,
            '3b_umpire_name': str,
            'lf_umpire_id': str,
            'lf_umpire_name': str,
            'rf_umpire_id': str,
            'rf_umpire_name': str,
            'v_manager_id': str,
            'v_manager_name': str,
            'h_manager_id': str,
            'h_manager_name': str,
            'winning_pitcher_id': str,
            'winning_pitcher_name': str,
            'losing_pitcher_id': str,
            'losing_pitcher_name': str,
            'saving_pitcher_id': str,
            'saving_pitcher_name': str,
            'winning_rbi_batter_id': str,
            'winning_rbi_batter_id_name': str,
            'v_starting_pitcher_id': str,
            'v_starting_pitcher_name': str,
            'h_starting_pitcher_id': str,
            'h_starting_pitcher_name': str,
            'v_player_1_id': str,
            'v_player_1_name': str,
            'v_player_1_def_pos': np.int32,
            'v_player_2_id': str,
            'v_player_2_name': str,
            'v_player_2_def_pos': np.int32,
            'v_player_3_id': str,
            'v_player_3_name': str,
            'v_player_3_def_pos': np.int32,
            'v_player_4_id': str,
            'v_player_4_name': str,
            'v_player_4_def_pos': np.int32,
            'v_player_5_id': str,
            'v_player_5_name': str,
            'v_player_5_def_pos': np.int32,
            'v_player_6_id': str,
            'v_player_6_name': str,
            'v_player_6_def_pos': np.int32,
            'v_player_7_id': str,
            'v_player_7_name': str,
            'v_player_7_def_pos': np.int32,
            'v_player_8_id': str,
            'v_player_8_name': str,
            'v_player_8_def_pos': np.int32,
            'v_player_9_id': str,
            'v_player_9_name': str,
            'v_player_9_def_pos': np.int32,
            'h_player_1_id': str,
            'h_player_1_name': str,
            'h_player_1_def_pos': np.int32,
            'h_player_2_id': str,
            'h_player_2_name': str,
            'h_player_2_def_pos': np.int32,
            'h_player_3_id': str,
            'h_player_3_name': str,
            'h_player_3_def_pos': np.int32,
            'h_player_4_id': str,
            'h_player_4_name': str,
            'h_player_4_def_pos': np.int32,
            'h_player_5_id': str,
            'h_player_5_name': str,
            'h_player_5_def_pos': np.int32,
            'h_player_6_id': str,
            'h_player_6_name': str,
            'h_player_6_def_pos': np.int32,
            'h_player_7_id': str,
            'h_player_7_name': str,
            'h_player_7_def_pos': np.int32,
            'h_player_8_id': str,
            'h_player_8_name': str,
            'h_player_8_def_pos': np.int32,
            'h_player_9_id': str,
            'h_player_9_name': str,
            'h_player_9_def_pos': np.int32,
            'additional_info': str,
            'acquisition_info': str
        }
        self._df = self._read_game_logs()

    def _read_game_logs(self):
        log.info('started reading csv dataset')

        debug_row_count = os.environ.get('VIS_ROW_COUNT')
        log.debug("reading data from %s entries", self.GAME_LOGS_DATA_WORLD)

        if debug_row_count is not None:
            log.info("debug flag set, only reading %s entries", debug_row_count)
            df = pd.read_csv(self.GAME_LOGS_DATA_WORLD,
                             converters={col: self._process_value for col in self._dtypeDict.keys()},
                             nrows=int(debug_row_count))
        else:
            df = pd.read_csv(self.GAME_LOGS_DATA_WORLD,
                             converters={col: self._process_value for col in self._dtypeDict.keys()})
        log.info('finished reading csv dataset')

        df = self._sanitize_df(df)
        df = self._add_custom_fields(df)

        return df

    def _process_value(self, value):
        if value == '':
            return
        else:
            return value

    def _sanitize_df(self, gamelog_df):
        gamelog_df = self._empty_flags_for_empty_cells(gamelog_df)
        gamelog_df = self._remove_first_incomplete_years(gamelog_df)
        return gamelog_df

    def _empty_flags_for_empty_cells(self, gamelog_df):
        # deal with null / empty values
        placeholder = '-12345'
        # fill empty cells with placeholder
        gamelog_df = gamelog_df.fillna(placeholder)
        # necessary to cast with type dictionary
        gamelog_df = gamelog_df.astype(self._dtypeDict)
        # after cast insert nan value, for an early fail in later processing if list
        # is not properly sanitized
        gamelog_df = gamelog_df.replace(int(placeholder), np.nan)
        gamelog_df = gamelog_df.replace(placeholder, None)
        return gamelog_df

    def _remove_first_incomplete_years(self, gameslog_df):
        # return gameslog_df[int(gameslog_df['date']) >= 18900000]
        return gameslog_df[gameslog_df['date'].apply(lambda x: int(x[:4])) >= self.START_YEAR]
        # return gameslog_df[gameslog_df['date_year'] >= 1890]

    def _add_custom_fields(self, gamelog_df):
        gamelog_df = self._append_date_summaries(gamelog_df)
        gamelog_df = self._append_team_ids_translation(gamelog_df)
        gamelog_df = self._append_team_duration(gamelog_df)
        return gamelog_df

    def _append_date_summaries(self, gamelog_df):
        """
        appends new values to input dataframe
        - date_year: year in which the game took place
        - date_decade: decade in wich the game took place
        :param gamelog_df: input dataframe
        :return: appended dataframe
        """
        # create a new column containing just the year - easier for later processing
        gamelog_df['date'] = pd.to_datetime(gamelog_df['date'])
        gamelog_df = pd.concat([gamelog_df, gamelog_df['date'].apply(lambda x: x.year).rename('date_year')], axis=1)
        gamelog_df = pd.concat(
            [gamelog_df, gamelog_df['date'].apply(lambda x: str(x.year)[:3] + '0s').rename('date_decade')], axis=1)
        return gamelog_df

    def _append_team_ids_translation(self, gamelog_df):
        """
        appends new values to input dataframe
        - v_name_translate: city and full name of the visiting team combined
        - h_name_translate: city and full name of the home team combined
        :param gamelog_df: input dataframe
        :return: appended dataframe
        """
        # translate team ids
        abreviations_df = pd.read_csv(self.GAME_LOGS_ABBREVIATIONS)
        team_mapping = dict(zip(abreviations_df['team'], abreviations_df['city'] + ' - ' + abreviations_df['nickname']))
        gamelog_df = pd.concat([gamelog_df, gamelog_df['v_name'].map(team_mapping).rename('v_name_translate')], axis=1)
        gamelog_df = pd.concat([gamelog_df, gamelog_df['h_name'].map(team_mapping).rename('h_name_translate')], axis=1)

        return gamelog_df

    def _append_team_duration(self, gamelog_df):
        """
        appends new values to input dataframe
        - date_h_duration: years which the home team existed
        - date_v_duration: years which the visiting team existed
        :param gamelog_df: input dataframe
        :return: appended dataframe
        """
        abreviations_df = pd.read_csv(self.GAME_LOGS_ABBREVIATIONS)
        duration_mapping = dict(
            zip(abreviations_df['team'], abreviations_df['last_year'] - abreviations_df['first_year']))
        gamelog_df = pd.concat([gamelog_df, gamelog_df['h_name'].map(duration_mapping).rename('date_h_duration')],
                               axis=1)
        gamelog_df = pd.concat([gamelog_df, gamelog_df['v_name'].map(duration_mapping).rename('date_v_duration')],
                               axis=1)

        first_year_mapping = dict(zip(abreviations_df['team'], abreviations_df['first_year']))
        gamelog_df = pd.concat([gamelog_df, gamelog_df['h_name'].map(first_year_mapping).rename('date_h_first_year')],
                               axis=1)
        gamelog_df = pd.concat([gamelog_df, gamelog_df['v_name'].map(first_year_mapping).rename('date_v_first_year')],
                               axis=1)

        last_year_mapping = dict(zip(abreviations_df['team'], abreviations_df['last_year']))
        gamelog_df = pd.concat([gamelog_df, gamelog_df['h_name'].map(last_year_mapping).rename('date_h_last_year')],
                               axis=1)
        gamelog_df = pd.concat([gamelog_df, gamelog_df['v_name'].map(last_year_mapping).rename('date_v_last_year')],
                               axis=1)

        return gamelog_df

    def _export_graph(self, plotting_func, df):
        callback_package_name = inspect.getmodule(plotting_func).__package__.replace(".", "/")
        callback_file_name = os.path.splitext(os.path.basename(inspect.getfile(plotting_func)))[0]
        callback_func_name = plotting_func.__name__

        output_dir = self.OUTPUT_DIR + '/' + callback_package_name + '/' + callback_file_name + '/'
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        markdown_plot_description = plotting_func(df)

        output_file = os.path.realpath(output_dir + callback_func_name)
        log.info('writing plot: %s', output_file)

        plt.savefig(output_file)
        plt.show()

        return output_file

    def _build_tex_slide(self, img_path):
        latex_slide_template = self._load_str_content(self.TEX_TEMPLATE_SLIDE)
        img_name = os.path.basename(img_path).replace('_', '\_') + '.png'
        return latex_slide_template % (img_name, img_path)

    def append_graph(self, plotting_func):
        img_path = self._export_graph(plotting_func, self._df)
        self.tex_slides += self._build_tex_slide(img_path)

    def append_section(self, section):
        latex_chapter_template = self._load_str_content(self.TEX_TEMPLATE_SECTION)
        self.tex_slides += latex_chapter_template % section

    def append_subsection(self, subsection):
        latex_chapter_template = self._load_str_content(self.TEX_TEMPLATE_SUBSECTION)
        self.tex_slides += latex_chapter_template % subsection

    def _load_str_content(self, file_path):
        file_content = ''
        with open(file_path, 'r') as file:
            file_content = file.read()
        return file_content

    def _write_latex(self, output_dir, tex_content):
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        output_file = output_dir + "/" + self.TEX_OUTPUT_NAME
        with open(output_file, 'w') as file:
            log.info("writing tex content to: %s", output_file)
            file.write(tex_content)

        return os.path.abspath(output_file)

    def _compile_tex_file(self, tex_file):
        dir = os.path.dirname(tex_file)
        subprocess.run(["pdflatex", tex_file], cwd=dir)
        subprocess.run(["pdflatex", tex_file], cwd=dir)
        return tex_file.replace(".tex", ".pdf")

    def build_presentation(self):
        latex_main_template = self._load_str_content(self.TEX_TEMPLATE_MAIN)
        main_latex = latex_main_template % self.tex_slides
        tex_file = self._write_latex(self.OUTPUT_BEAMER, main_latex)
        beamer_output = self._compile_tex_file(tex_file)

        log.debug("beamer output: %s", beamer_output)
        log.debug("copy to: %s", self.OUTPUT_PDF)
        shutil.copy(beamer_output, self.OUTPUT_PDF)


import gzip
import pickle
import re

import numpy as np
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
from nltk.stem.wordnet import WordNetLemmatizer
from scipy import io

import nltk

try:
    nltk.data.find('tokenizers/punkt')
except LookupError:
    nltk.download('punkt')
try:
    nltk.data.find('corpora/stopwords')
except LookupError:
    nltk.download('stopwords')

try:
    nltk.data.find('corpora/stopwords')
except LookupError:
    nltk.download('stopwords')

try:
    nltk.data.find('corpora/wordnet')
except LookupError:
    nltk.download('wordnet')

lem = WordNetLemmatizer()
stem = PorterStemmer()

stop_words = stopwords.words('english')

def processText(text):
    # Remove punctuations
    text = re.sub('[^a-zA-Z]', ' ', text)

    # Convert to lowercase
    text = text.lower()

    # remove tags
    text = re.sub("</?.*?>", " <> ", text)

    #remove special characters and digits
    text = re.sub("(\\d|\\W)+", " ", text)

    ##Convert to list from string
    text = text.split()

    ##Stemming
    ps = PorterStemmer()

    # Lemmatisation
    lem = WordNetLemmatizer()
    text = [lem.lemmatize(word) for word in text if not word in stop_words]
    text = [word for word in text if len(word)>2]
    # text = " ".join(text)
    return text

def processTextParagraph(text):
    return " ".join(processText(text))

def num(s):
    try:
        return float(s)
    except ValueError:
        return 0

def parse(path):
  g = gzip.open(path, 'r')
  for l in g:
    yield eval(l)

#mtx format
def save_data(data_vector,data_rating,output_file,output_label,output_data,comment=""):
    print("Writing vector as mtx file")
    io.mmwrite(output_file, data_vector, comment=comment)

    f = open(output_label, 'w')
    f.write("%d\n" % len(data_rating))

    print("Writing Class label")
    with open(output_label, 'a') as f:
        for item in data_rating:
            f.write("%s\n" % item)
    f.close()
def save_data2(data,data_vector,data_rating,output_file,output_label,output_data,comment=""):
    print("Started Writing data")
    pickle.dump(data, open(output_data, "wb"))

    print("Writing vector as mtx file")
    io.mmwrite(output_file, data_vector, comment=comment)

    f = open(output_label, 'w')
    f.write("%d\n" % len(data_rating))

    print("Writing Class label")
    with open(output_label, 'a') as f:
        for item in data_rating:
            f.write("%s\n" % item)
    f.close()

def save_data_mat(home_dir,data_vector,data_rating):
    import scipy as sp
    #sp.io.savemat(home_dir+"data_mat.mat",mdict={'data': data})
    sp.io.savemat(home_dir + "data_vector_mat.mat", mdict={'data_vector': data_vector})
    sp.io.savemat(home_dir + "data_rating_mat.mat", mdict={'data_rating': data_rating})

def save_data_mat2(home_dir,data,data_vector,data_rating):
    import scipy as sp
    sp.io.savemat(home_dir+"data_mat.mat",mdict={'data': data})
    sp.io.savemat(home_dir + "data_vector_mat.mat", mdict={'data_vector': data_vector})
    sp.io.savemat(home_dir + "data_rating_mat.mat", mdict={'data_rating': data_rating})

def save_data_txt(home_dir,data_vector,data_rating):
    #np.savetxt(home_dir + "data_txt.txt", data, delimiter='\t',fmt='%s'),
    np.savetxt(home_dir + "data_vector_txt.txt", data_vector, delimiter='\t')
    np.savetxt(home_dir + "data_rating_txt.txt", data_rating, delimiter='\t',fmt='%s')

def save_data_txt2(home_dir,data,data_vector,data_rating):
    np.savetxt(home_dir + "data_txt.txt", data, delimiter='\t',fmt='%s'),
    np.savetxt(home_dir + "data_vector_txt.txt", data_vector, delimiter='\t')
    np.savetxt(home_dir + "data_rating_txt.txt", data_rating, delimiter='\t',fmt='%s')

def save_vector_mtx2(home_dir,dataset_name,data_vector):
    filename=home_dir+dataset_name+"_vector.mtx"
    m, n = data_vector.shape
    header = np.array([[m, n, m * n]])

    with open(filename, 'wb') as f:
        np.savetxt(f, header, fmt='%d %d %d')

    with open(filename, 'a+') as f:
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                f.write("%d %d %f\n" % (i, j, data_vector[i - 1, j - 1]))

def save_data_rating_numpy(home_dir,data,data_rating):
    np.save(home_dir+"data_np",data)
    np.save(home_dir+"data_rating_np",data_rating)

def save_vector_rating_numpy(home_dir,data_vector,data_rating):
    np.save(home_dir+"data_vector_np",data_vector)
    np.save(home_dir+"data_rating_np",data_rating)

def save_vector_scipy(output_dir,data_vector):
    import scipy.sparse
    scipy.sparse.save_npz(output_dir+'data_vector.npz', data_vector)

def load_data(home_dir):
    data=np.load(home_dir+"data_np.npy")
    data_rating = np.load(home_dir + "data_rating_np.npy")
    data_vector = np.load(home_dir + "data_vector_np.npy")

    return (data,data_rating,data_vector)

def create_graph(home_dir):
    (data,data_rating,data_vector)=load_data(home_dir)

    n=data.shape[0]
    indexes=np.random.choice(n, min(1000,n))
    print(indexes)

    print("Data count: ", data.shape)
    print("Vector count: ", data_vector.shape)
    print("Rating count: ", data_rating.shape)

    data=data[indexes]
    data_rating = data_rating[indexes]
    data_vector = data_vector[indexes]

    print("Data count: ", data.shape)
    print("Vector count: ", data_vector.shape)
    print("Rating count: ", data_rating.shape)

    from sklearn.neighbors import kneighbors_graph
    import networkx as nx
    import scipy as sp

    mode='distance'
    metric='cosine'
    #metric = 'euclidean'

    k=5
    sparse_graph = kneighbors_graph(data_vector, k, mode=mode, metric=metric, include_self=False)

    if (mode == 'distance'):
        #sparse_graph.data = 1.0 / (1.0 + sparse_graph.data)  # poincare
        #sparse_graph.data = 1.0 - sparse_graph.data
        sparse_graph.data = sparse_graph.data+1e-10
        #sparse_graph.eliminate_zeros()

    print('Saving graph ----')
    graph = home_dir + 'graph.npz'
    gephi = home_dir + "graph_gephi.gexf"

    sp.sparse.save_npz(graph, sparse_graph)
    print('Graph saving Done')

    custom_labels=[]
    for i in range(data_rating.shape[0]):
        custom_labels.append(str(data_rating[i])+"->"+data[i][:50])

    print(custom_labels)

    threshold=3.0
    if("Imdb" in home_dir): threshold=5.0

    for i in range(data_rating.shape[0]):
        if(data_rating[i]>threshold):
            data_rating[i]=1
        else:
            data_rating[i] = 0

    labels = dict(zip(range(data_rating.shape[0]), data_rating))
    G = nx.from_scipy_sparse_matrix(sparse_graph)
    nx.set_node_attributes(G, labels, 'labels')
    print("Writing gephi")
    nx.write_gexf(G, gephi)

    return

def load_model(model_name):
    from gensim.models.doc2vec import Doc2Vec
    import numpy as np

    model = Doc2Vec.load(model_name)
    vectors = np.zeros((model.corpus_count, model.vector_size), np.float)
    print(vectors.shape)
    for i in range(model.corpus_count):
        vectors[i] = model.docvecs[i]
    print(vectors.shape)

    return vectors

if __name__ == '__main__':
    # home_dir = "/Users/sid/Purdue/Research/GCSSL/Dataset/Imdb/aclImdb/"
    # #home_dir = "/Users/sid/Purdue/Research/GCSSL/Dataset/Yelp/"
    # #home_dir = "/Users/sid/Purdue/Research/GCSSL/Dataset/DBpedia/dbpedia_csv/"
    # #home_dir = "/Users/sid/Purdue/Research/GCSSL/Dataset/AmazonReview/"
    # create_graph(home_dir)

    home_dir = "/Users/siddharthashankardas/Purdue/Dataset/Imdb/aclImdb/word2vec/"
    #home_dir = "/Users/sid/Purdue/Research/GCSSL/Dataset/Yelp/"
    #home_dir = "/Users/sid/Purdue/Research/GCSSL/Dataset/DBpedia/dbpedia_csv/"
    #home_dir = "/Users/sid/Purdue/Research/GCSSL/Dataset/AmazonReview/"
    #create_graph(home_dir)
    #load_model("Models/imdb_d2v.model")
    #data=[['This','is'],['not','meh']]
    data=np.random.rand(5,5)
    data_rating=np.random.rand(5,1)
    data_vector=np.random.rand(5,10)
    save_data_txt(home_dir, data,data_vector,data_rating)


import discord
from discord.ext import commands

class MinecraftCog(commands.Cog):

    def __init__(self, client):
        self.client = client

    @commands.command(name="minecraft")
    @commands.cooldown(1, 3, commands.BucketType.user)
    async def minecraft(self, ctx):
        await ctx.send("https://tenor.com/view/minecraft-gif-9643254")
        await ctx.send("https://tenor.com/view/minecraft-sonic-minecraft-sonic-sonic3d-sonic3d-blast-gif-19349494")

def setup(client):
    client.add_cog(MinecraftCog(client))


from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np
from argparse import ArgumentParser

def parse_args():
    ap = ArgumentParser()
    ap.add_argument(
        "-e",
        "--epochs",
        type=float,
        default=100,
        help="# of epochs"
    )
    ap.add_argument(
        "-a",
        "--alpha",
        type=float,
        default=0.01,
        help="Learning rate"
    )
    ap.add_argument(
        "-b",
        "--batch-size",
        type=int,
        default=32,
        help="Size of SGD mini-batches"
    )
    return vars(ap.parse_args())

def generate_2_class_classification_problem():
    X, y = make_blobs(
        n_samples=1000,
        n_features=2,
        centers=2,
        cluster_std=1.5,
        random_state=1
    )
    y = y.reshape((y.shape[0], 1))
    # Insert a column of 1s as the last entry in the feature matrix to treat the
    # bias as a trainable parameter
    X = np.c_[X, np.ones(X.shape[0])]
    return X, y

def sigmoid_activation(x):
    return 1.0 / (1 + np.exp(-x))

def predict(X, W):
    preds = sigmoid_activation(X.dot(W))
    preds[preds <= 0.5] = 0
    preds[preds > 0] = 1
    return preds

def next_batch(X, y, batch_size):
    for i in np.arange(0, X.shape[0], batch_size):
        yield (X[i:(i + batch_size)], y[i:(i + batch_size)])

def plot_classification(test_X, test_y):
    plt.style.use("ggplot")
    plt.figure()
    plt.title("data")
    plt.scatter(
        test_X[:, 0],
        test_X[:, 1],
        marker="o",
        c=test_y.ravel().tolist(),
        s=30
    )

def plot_losses(epochs_count, losses):
    plt.style.use("ggplot")
    plt.figure()
    plt.plot(np.arange(0, epochs_count), losses)
    plt.title("Training loss")
    plt.xlabel("Epoch #")
    plt.ylabel("Loss")
    plt.show()

args = parse_args()
epochs_count = args["epochs"]
batch_size = args["batch_size"]
learning_rate = args["alpha"]
X, y = generate_2_class_classification_problem()
train_X, test_X, train_y, test_y = train_test_split(
    X,
    y,
    test_size=0.5,
    random_state=42
)
W = np.random.randn(X.shape[1], 1)
losses = []
print("[INFO] Training")
for epoch in np.arange(0, epochs_count):
    total_epoch_loss = []
    for batch_X, batch_y in next_batch(train_X, train_y, batch_size):
        preds = sigmoid_activation(batch_X.dot(W))
        error = preds - batch_y
        # Perform gradient descent update on a single batch rather than epoch
        gradient = batch_X.T.dot(error)
        W += -learning_rate * gradient
        total_epoch_loss.append(np.sum(error ** 2))
    loss = np.average(total_epoch_loss)
    losses.append(loss)
    if epoch == 0 or (epoch + 1) % 5 == 0:
        print(f"[INFO] epoch={int(epoch + 1)}, loss={loss:.7f}")
print("[INFO] Evaluating")
preds = predict(test_X, W)
print(classification_report(test_y, preds))
plot_classification(test_X, test_y)
plot_losses(epochs_count, losses)


def translation_word(word, model):
    import json
    import requests

    def translate(word):
        url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null'
        type = ['auto', 'EN2ZH_CN', 'ZH_CN2EN'][model]
        key = {
            'type': type,
            'i': word,
            "doctype": "json",
            "version": "2.1",
            "keyfrom": "fanyi.web",
            "ue": "UTF-8",
            "action": "FY_BY_CLICKBUTTON",
            "typoResult": "true"
        }
        response = requests.post(url, data=key)
        if response.status_code == 200:
            return response.text
        else:
            return None

    def get_reuslt(repsonse):
        result = json.loads(repsonse)
        fanyi = result['translateResult'][-1][-1]['tgt']  # or ['src']
        return fanyi

    fanyi = get_reuslt(translate(word))
    return fanyi

def is_Chinese(question):
    for ch in question:
        if '\u4e00' <= ch <= '\u9fff':
            return True
    return False


from builtins import str
import logging

from django.conf import settings
from MySQLdb.cursors import DictCursor

from bq_data_access.v2.feature_id_utils import FeatureProviderFactory
from bq_data_access.v2.user_data import UserDataQueryHandler
from bq_data_access.v2.data_access import submit_tcga_job, get_submitted_job_results

from cohorts.metadata_helpers import get_sql_connection
from google_helpers.bigquery.service import get_bigquery_service

def user_feature_handler(feature_id, cohort_id_array):
    include_tcga = False
    user_studies = ()
    for cohort_id in cohort_id_array:
        try:
            db = get_sql_connection()
            cursor = db.cursor(DictCursor)

            cursor.execute("SELECT project_id FROM cohorts_samples WHERE cohort_id = %s GROUP BY project_id", (cohort_id,))
            for row in cursor.fetchall():
                if row['project_id'] is None:
                    include_tcga = True
                else:
                    user_studies += (row['project_id'],)

        except Exception as e:
            if db: db.close()
            if cursor: cursor.close()
            raise e

    user_feature_id = None
    if feature_id.startswith('USER:'):
        # Try and convert it with a shared ID to a TCGA queryable id
        user_feature_id = feature_id
        feature_id = UserDataQueryHandler.convert_feature_id(feature_id)
        if feature_id is None:
            # Querying user specific data, don't include TCGA
            include_tcga = False

    return {
        'converted_feature_id': feature_id,
        'include_tcga': include_tcga,
        'user_studies': user_studies,
        'user_feature_id': user_feature_id
    }

def submit_jobs_with_user_data(params_array):
    bigquery_service = get_bigquery_service()
    provider_array = []

    cohort_settings = settings.GET_BQ_COHORT_SETTINGS()

    # Submit jobs
    for parameter_object in params_array:
        feature_id = parameter_object.feature_id
        cohort_id_array = parameter_object.cohort_id_array

        user_data = user_feature_handler(feature_id, cohort_id_array)

        if user_data['include_tcga']:
            job_item = submit_tcga_job(parameter_object, bigquery_service, cohort_settings)
            provider_array.append(job_item)

        if len(user_data['user_studies']) > 0:
            converted_feature_id = user_data['converted_feature_id']
            user_feature_id = user_data['user_feature_id']
            logging.debug("user_feature_id: {0}".format(user_feature_id))
            provider = UserDataQueryHandler(converted_feature_id, user_feature_id=user_feature_id)

            # The UserDataQueryHandler instance might not generate a BigQuery query and job at all given the combination
            # of cohort(s) and feature identifiers. The provider is not added to the array, and therefore to the
            # polling loop below, if it would not submit a BigQuery job.
            if provider.is_queryable(cohort_id_array):
                job_reference = provider.get_data_job_reference(cohort_id_array, cohort_settings.dataset_id, cohort_settings.table_id)

                logging.info("Submitted USER {job_id}: {fid} - {cohorts}".format(job_id=job_reference['jobId'], fid=feature_id,
                                                                                cohorts=str(cohort_id_array)))
                provider_array.append({
                    'feature_id': feature_id,
                    'provider': provider,
                    'ready': False,
                    'job_reference': job_reference['job_reference'],
                    'tables_used': job_reference['tables_queried']
                })
            else:
                logging.debug("No UserFeatureDefs for '{0}'".format(converted_feature_id))

    return provider_array

# This code was part of the V1 data_access code, pulled out of V2 data_access.py, and only used in
# the V1 Pairwise analysis.

def get_feature_vector(feature_id, cohort_id_array):
    include_tcga = False
    user_studies = ()
    for cohort_id in cohort_id_array:
        try:
            db = get_sql_connection()
            cursor = db.cursor(DictCursor)

            cursor.execute("SELECT project_id FROM cohorts_samples WHERE cohort_id = %s GROUP BY project_id", (cohort_id,))
            for row in cursor.fetchall():
                if row['project_id'] is None:
                    include_tcga = True
                else:
                    user_studies += (row['project_id'],)

        except Exception as e:
            if db: db.close()
            if cursor: cursor.close()
            raise e

    #  ex: feature_id 'CLIN:Disease_Code'
    user_feature_id = None
    if feature_id.startswith('USER:'):
        # Try and convert it with a shared ID to a TCGA queryable id
        user_feature_id = feature_id
        feature_id = UserDataQueryHandler.convert_user_feature_id(feature_id)
        if feature_id is None:
            # Querying user specific data, don't include TCGA
            include_tcga = False

    items = []
    type = None
    result = []
    cohort_settings = settings.GET_BQ_COHORT_SETTINGS()
    if include_tcga:
        provider = FeatureProviderFactory.from_feature_id(feature_id)
        result = provider.get_data(cohort_id_array, cohort_settings.dataset_id, cohort_settings.table_id)

        # ex: result[0]
        # {'aliquot_id': None, 'case_id': u'TCGA-BH-A0B1', 'sample_id': u'TCGA-BH-A0B1-10A', 'value': u'BRCA'}
        for data_point in result:
            data_item = {key: data_point[key] for key in ['case_id', 'sample_id', 'aliquot_id']}
            value = provider.process_data_point(data_point)
            # TODO refactor missing value logic
            if value is None:
                value = 'NA'
            data_item['value'] = value
            items.append(data_item)

        type = provider.get_value_type()

    if len(user_studies) > 0:
        # Query User Data
        user_provider = UserDataQueryHandler(feature_id, user_feature_id=user_feature_id)
        user_result = user_provider.get_data(cohort_id_array, cohort_settings.dataset_id, cohort_settings.table_id)
        result.extend(user_result)

        for data_point in user_result:
            data_item = {key: data_point[key] for key in ['case_id', 'sample_id', 'aliquot_id']}
            value = provider.process_data_point(data_point)
            # TODO refactor missing value logic
            if value is None:
                value = 'NA'
            data_item['value'] = value
            items.append(data_item)

        if not type:
            type = user_provider.get_value_type()

    return type, items

def get_feature_vectors_with_user_data(params_array, poll_retry_limit=20, skip_formatting_for_plot=False):
    provider_array = submit_jobs_with_user_data(params_array)

    project_id = settings.BIGQUERY_PROJECT_ID
    result = get_submitted_job_results(provider_array, project_id, poll_retry_limit, skip_formatting_for_plot)

    return result


import sys
sys.setrecursionlimit(60000)

def solution(n):
    memory = [-1 for i in range(60001)]

    def dp(n):
        if memory[n] != -1: return memory[n]
        if n == 0: return 1
        if n == 1: return 1
        memory[n] = (dp(n-1) + dp(n-2)) % 1000000007
        return memory[n]

    return dp(n)


n = int(input())
lst = [input() for _ in range(n)]
lst.sort()
cnt = 0
for i in range(n):
    flag = 0
    for j in range(i+1, n):
        # if lst[i][0] == lst[j][0]:
        if lst[i] in lst[j][0:len(lst[i])]:
            flag = 1
            break
    if not flag:
        cnt += 1
print(cnt)


from Test_Case_1.Necessary_Packages.Necessary_Packages_Import import *

def handle_mobile_number_field():
    # Mobile number field checking
    try:
        mobile_field = WebDriverWait(driver, 10, poll_frequency=1).until(
            EC.visibility_of_element_located((By.CSS_SELECTOR, "input#mobile_number")))
        mobile_field.send_keys("45875487")
        print("Mobile number entered successfully!")
    except Exception as e:
        print("Mobile number field exception: ", type(e).__name__)


# -*- coding: utf-8 -*-
"""
Created on Mon Jul 17 22:39:24 2017

@author: kunal
"""

import simplekml

def userInputLatAndLong(lat,long):
    kml=simplekml.Kml()
    kml.newpoint(name="Sample",coords=[(lat,long)])
    kml.save("D:\\pythonscripts\\point.kml")

userLat=input("Please enter the desired value of latitude :")
userLong=input("Please enter the desired value of longitude : ")
userInputLatAndLong(userLat,userLong)


from pathlib import Path

import torch
# from torch.autograd.grad_mode import F
from torch.utils.data import Dataset
import datasets.transforms_video as T

import os
from PIL import Image
import json
import numpy as np
import random

from pycocotools import mask as coco_mask

class MeViSDataset(Dataset):
    """
    A dataset class for the MeViS dataset which was first introduced in the paper:
    "MeViS: A Large-scale Benchmark for Video Segmentation with Motion Expressions"
    """

    def __init__(self, img_folder: Path, ann_file: Path, transforms, return_masks: bool,
                 num_frames: int, max_skip: int):
        self.img_folder = img_folder
        self.ann_file = ann_file
        self._transforms = transforms
        self.return_masks = return_masks  # not used
        self.num_frames = num_frames
        self.max_skip = max_skip
        # create video meta data
        self.prepare_metas()

        mask_json = os.path.join(str(self.img_folder) + '/mask_dict.json')
        print(f'Loading masks form {mask_json} ...')
        with open(mask_json) as fp:
            self.mask_dict = json.load(fp)

        print('\n video num: ', len(self.videos), ' clip num: ', len(self.metas))
        print('\n')

    def prepare_metas(self):
        # read expression data
        with open(str(self.ann_file), 'r') as f:
            subset_expressions_by_video = json.load(f)['videos']
        self.videos = list(subset_expressions_by_video.keys())

        self.metas = []
        for vid in self.videos:
            # vid_meta = subset_metas_by_video[vid]
            vid_data = subset_expressions_by_video[vid]
            vid_frames = sorted(vid_data['frames'])
            vid_len = len(vid_frames)

            for exp_id, exp_dict in vid_data['expressions'].items():
                for frame_id in range(0, vid_len, self.num_frames):
                    meta = {}
                    meta['video'] = vid
                    meta['exp'] = exp_dict['exp']
                    meta['obj_id'] = [int(x) for x in exp_dict['obj_id']]
                    meta['anno_id'] = [str(x) for x in exp_dict['anno_id']]
                    meta['frames'] = vid_frames
                    meta['frame_id'] = frame_id
                    meta['category'] = 0
                    self.metas.append(meta)

    @staticmethod
    def bounding_box(img):
        rows = np.any(img, axis=1)
        cols = np.any(img, axis=0)
        rmin, rmax = np.where(rows)[0][[0, -1]]
        cmin, cmax = np.where(cols)[0][[0, -1]]
        return rmin, rmax, cmin, cmax  # y1, y2, x1, x2

    def __len__(self):
        return len(self.metas)

    def __getitem__(self, idx):
        instance_check = False
        while not instance_check:
            meta = self.metas[idx]  # dict

            video, exp, anno_id, category, frames, frame_id = \
                meta['video'], meta['exp'], meta['anno_id'], meta['category'], meta['frames'], meta['frame_id']
            # clean up the caption
            exp = " ".join(exp.lower().split())
            category_id = 0
            vid_len = len(frames)

            num_frames = self.num_frames
            # random sparse sample
            sample_indx = [frame_id]
            if self.num_frames != 1:
                # local sample
                sample_id_before = random.randint(1, 3)
                sample_id_after = random.randint(1, 3)
                local_indx = [max(0, frame_id - sample_id_before), min(vid_len - 1, frame_id + sample_id_after)]
                sample_indx.extend(local_indx)

                # global sampling
                if num_frames > 3:
                    all_inds = list(range(vid_len))
                    global_inds = all_inds[:min(sample_indx)] + all_inds[max(sample_indx):]
                    global_n = num_frames - len(sample_indx)
                    if len(global_inds) > global_n:
                        select_id = random.sample(range(len(global_inds)), global_n)
                        for s_id in select_id:
                            sample_indx.append(global_inds[s_id])
                    elif vid_len >= global_n:  # sample long range global frames
                        select_id = random.sample(range(vid_len), global_n)
                        for s_id in select_id:
                            sample_indx.append(all_inds[s_id])
                    else:
                        select_id = random.sample(range(vid_len), global_n - vid_len) + list(range(vid_len))
                        for s_id in select_id:
                            sample_indx.append(all_inds[s_id])
            sample_indx.sort()

            # read frames and masks
            imgs, labels, boxes, masks, valid = [], [], [], [], []
            for j in range(self.num_frames):
                frame_indx = sample_indx[j]
                frame_name = frames[frame_indx]
                img_path = os.path.join(str(self.img_folder), 'JPEGImages', video, frame_name + '.jpg')
                # mask_path = os.path.join(str(self.img_folder), 'Annotations', video, frame_name + '.png')
                img = Image.open(img_path).convert('RGB')
                # h, w = img.shape
                mask = np.zeros(img.size[::-1], dtype=np.float32)
                for x in anno_id:
                    frm_anno = self.mask_dict[x][frame_indx]
                    if frm_anno is not None:
                        mask += coco_mask.decode(frm_anno)

                # create the target
                label = torch.tensor(category_id)

                if (mask > 0).any():
                    y1, y2, x1, x2 = self.bounding_box(mask)
                    box = torch.tensor([x1, y1, x2, y2]).to(torch.float)
                    valid.append(1)
                else:  # some frame didn't contain the instance
                    box = torch.tensor([0, 0, 0, 0]).to(torch.float)
                    valid.append(0)
                mask = torch.from_numpy(mask)

                # append
                imgs.append(img)
                labels.append(label)
                masks.append(mask)
                boxes.append(box)

            # transform
            w, h = img.size
            labels = torch.stack(labels, dim=0)
            boxes = torch.stack(boxes, dim=0)
            boxes[:, 0::2].clamp_(min=0, max=w)
            boxes[:, 1::2].clamp_(min=0, max=h)
            masks = torch.stack(masks, dim=0)
            target = {
                'frames_idx': torch.tensor(sample_indx),  # [T,]
                'labels': labels,  # [T,]
                'boxes': boxes,  # [T, 4], xyxy
                'masks': masks,  # [T, H, W]
                'valid': torch.tensor(valid),  # [T,]
                'caption': exp,
                'orig_size': torch.as_tensor([int(h), int(w)]),
                'size': torch.as_tensor([int(h), int(w)])
            }

            # "boxes" normalize to [0, 1] and transform from xyxy to cxcywh in self._transform
            imgs, target = self._transforms(imgs, target)
            imgs = torch.stack(imgs, dim=0)  # [T, 3, H, W]

            # FIXME: handle "valid", since some box may be removed due to random crop
            if torch.any(target['valid'] == 1):  # at leatst one instance
                instance_check = True
            else:
                idx = random.randint(0, self.__len__() - 1)

        return imgs, target

def make_coco_transforms(image_set, max_size=640):
    normalize = T.Compose([
        T.ToTensor(),
        T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

    scales = [288, 320, 352, 392, 416, 448, 480, 512]

    if image_set == 'train':
        return T.Compose([
            T.RandomHorizontalFlip(),
            T.PhotometricDistort(),
            T.RandomSelect(
                T.Compose([
                    T.RandomResize(scales, max_size=max_size),
                    T.Check(),
                ]),
                T.Compose([
                    T.RandomResize([400, 500, 600]),
                    T.RandomSizeCrop(384, 600),
                    T.RandomResize(scales, max_size=max_size),
                    T.Check(),
                ])
            ),
            normalize,
        ])

    # we do not use the 'val' set since the annotations are inaccessible
    if image_set == 'val':
        return T.Compose([
            T.RandomResize([360], max_size=640),
            normalize,
        ])

    raise ValueError(f'unknown {image_set}')

def build(image_set, args):
    root = Path(args.rovos_path)
    assert root.exists(), f'provided YTVOS path {root} does not exist'
    PATHS = {
        "train": (root / "train", root / "train" / "meta_expressions.json"),
        "val": (root / "valid", root / "meta_expressions" / "val" / "meta_expressions.json"),  # not used actually
    }
    img_folder, ann_file = PATHS['train']
    dataset = ROVOSDataset(img_folder, ann_file, transforms=make_coco_transforms(image_set, max_size=args.max_size), return_masks=args.masks,
                           num_frames=args.num_frames, max_skip=args.max_skip)
    return dataset

if __name__ == '__main__':
    root = Path('data/mevis_release')
    image_set = 'train'
    PATHS = {
        "train": (root / "train", root / "train" / "meta_expressions.json"),
    }
    img_folder, ann_file = PATHS['train']

    dataset = ROVOSDataset(img_folder, ann_file, transforms=T.ToTensor(), return_masks=True, num_frames=5, max_skip=3)

    img, meta = dataset[0]


import config
import time
import random

def record(r):
    # ADD OUR OWN DATA
    r['report-time'] = str(int(time.time()))

    # SANITIZE
    out = {}
    for (k,v) in r.iteritems():
        v = v.replace('\t','    ').replace('\n','\t').replace('\r','\t')
        out[k] = v
    data = ""
    for (k,v) in out.iteritems():
        data += "%s = %s \n" % (k,v)

    # CALCULATE FILENAME
    base = config.config('error-base')
    if not base:
        base = '../../error'

    filename = "%s/error_%u_%u.txt" % (base,time.time(),random.getrandbits(32))

    # WRITE IT
    f = open(filename,"wb")
    print >>f,data.encode('utf-8')
    f.close()


# -*- coding: utf-8 -*-

import xml.etree.ElementTree as ET

import cv2
import numpy as np
from const import DEFAULT_WIDTH, IMAGE_SIZE
from rendering import render_entity

class Bunch:
    """Dummy class"""
    def __init__(self, **kwds):
        self.__dict__.update(kwds)

def get_real_bbox(entity_bbox, entity_type, entity_size, entity_angle):
    assert entity_type != "none"
    center = (int(entity_bbox[1] * IMAGE_SIZE), int(entity_bbox[0] * IMAGE_SIZE))
    M = cv2.getRotationMatrix2D(center, entity_angle, 1)
    unit = min(entity_bbox[2], entity_bbox[3]) * IMAGE_SIZE / 2
    delta = DEFAULT_WIDTH * 1.5 / IMAGE_SIZE
    if entity_type == "circle":
        radius = unit * entity_size
        real_bbox = [center[1] * 1.0 / IMAGE_SIZE, center[0] * 1.0 / IMAGE_SIZE, 2 * radius / IMAGE_SIZE + delta, 2 * radius / IMAGE_SIZE + delta]
    else:
        if entity_type == "triangle":
            dl = int(unit * entity_size)
            homo_pts = np.array([[center[0], center[1] - dl, 1],
                                 [center[0] + int(dl / 2.0 * np.sqrt(3)), center[1] + int(dl / 2.0), 1],
                                 [center[0] - int(dl / 2.0 * np.sqrt(3)), center[1] + int(dl / 2.0), 1]],
                                np.int32)
        if entity_type == "square":
            dl = int(unit / 2 * np.sqrt(2) * entity_size)
            homo_pts = np.array([[center[0] - dl, center[1] - dl, 1],
                                 [center[0] - dl, center[1] + dl, 1],
                                 [center[0] + dl, center[1] + dl, 1],
                                 [center[0] + dl, center[1] - dl, 1]],
                                np.int32)
        if entity_type == "pentagon":
            dl = int(unit * entity_size)
            homo_pts = np.array([[center[0], center[1] - dl, 1],
                                 [center[0] - int(dl * np.cos(np.pi / 10)), center[1] - int(dl * np.sin(np.pi / 10)), 1],
                                 [center[0] - int(dl * np.sin(np.pi / 5)), center[1] + int(dl * np.cos(np.pi / 5)), 1],
                                 [center[0] + int(dl * np.sin(np.pi / 5)), center[1] + int(dl * np.cos(np.pi / 5)), 1],
                                 [center[0] + int(dl * np.cos(np.pi / 10)), center[1] - int(dl * np.sin(np.pi / 10)), 1]],
                                np.int32)
        if entity_type == "hexagon":
            dl = int(unit * entity_size)
            homo_pts = np.array([[center[0], center[1] - dl, 1],
                                 [center[0] - int(dl / 2.0 * np.sqrt(3)), center[1] - int(dl / 2.0), 1],
                                 [center[0] - int(dl / 2.0 * np.sqrt(3)), center[1] + int(dl / 2.0), 1],
                                 [center[0], center[1] + dl, 1],
                                 [center[0] + int(dl / 2.0 * np.sqrt(3)), center[1] + int(dl / 2.0), 1],
                                 [center[0] + int(dl / 2.0 * np.sqrt(3)), center[1] - int(dl / 2.0), 1]],
                                np.int32)
        after_pts = np.dot(M, homo_pts.T)
        min_x = min(after_pts[1, :]) / IMAGE_SIZE
        max_x = max(after_pts[1, :]) / IMAGE_SIZE
        min_y = min(after_pts[0, :]) / IMAGE_SIZE
        max_y = max(after_pts[0, :]) / IMAGE_SIZE
        real_bbox = [(min_x + max_x) / 2, (min_y + max_y) / 2, max_x - min_x + delta, max_y - min_y + delta]
    return list(np.round(real_bbox, 4))

def get_mask(entity_bbox, entity_type, entity_size, entity_angle):
    dummy_entity = Bunch()
    dummy_entity.bbox = entity_bbox
    dummy_entity.type = Bunch(get_value=lambda : entity_type)
    dummy_entity.size = Bunch(get_value=lambda : entity_size)
    dummy_entity.color = Bunch(get_value=lambda : 0)
    dummy_entity.angle = Bunch(get_value=lambda : entity_angle)
    mask = render_entity(dummy_entity) / 255
    return mask

# ref: https://www.kaggle.com/stainsby/fast-tested-rle
# ref: https://www.kaggle.com/paulorzp/run-length-encode-and-decode
def rle_encode(img):
    '''
    img: numpy array, 1 - mask, 0 - background
    Returns run length as string formated
    '''
    pixels = img.flatten()
    pixels = np.concatenate([[0], pixels, [0]])
    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
    runs[1::2] -= runs[::2]
    return "[" + ",".join(str(x) for x in runs) + "]"

def rle_decode(mask_rle, shape):
    '''
    mask_rle: run-length as string formated (start length)
    shape: (height,width) of array to return
    Returns numpy array, 1 - mask, 0 - background
    '''
    s = mask_rle[1:-1].split(",")
    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]
    starts -= 1
    ends = starts + lengths
    img = np.zeros(shape[0] * shape[1], dtype=np.uint8)
    for lo, hi in zip(starts, ends):
        img[lo:hi] = 1
    return img.reshape(shape)


### Module imports ###
import os
import requests
import shutil
import subprocess

### Global Variables ###

### Class declarations ###

### Function declarations ###
def download_and_extract(url, save_path):
    """
    Download and extract zip file to folder

    Args:
        url: url to download zip file
        save_path: folder to save data
    """
    local_filename = url.split('/')[-1]
    file_path = os.path.join(save_path, local_filename)
    folder_path = os.path.join(save_path, '.'.join(local_filename.split('.')[:-1]))
    # download file
    with requests.get(url, stream=True) as r:
        with open(file_path, 'wb') as f:
            shutil.copyfileobj(r.raw, f)

    # create folder to extract
    if not os.path.exists(folder_path):
        os.makedirs(folder_path)

    # unzip
    subprocess.run(['unzip', file_path, '-d', folder_path])

    # remove zip file
    subprocess.run(['rm', file_path])

if __name__ == '__main__':
    download_and_extract('http://data.vision.ee.ethz.ch/cvl/DIV2K/DIV2K_train_HR.zip', 'data')
    download_and_extract('http://data.vision.ee.ethz.ch/cvl/DIV2K/DIV2K_valid_HR.zip', 'data')


from tkinter import *
from tkinter import ttk
from animation import Animate
from menuBar import menuBar
from Email import email
from sortings import *
from sortings.bubble import bubbleSort
from sortings.insertion import insertionSort
from sortings.mergeSort import mergeSort
from sortings.quick import quickSort
from sortings.selection import selectionSort

def start_animation():
    algo = sort_algo.get()
    list = array.get().split(" ")
    for idx, item in enumerate(list):
        list[idx] = int(item)
    print(algo)
    print(list)
    array.delete(0, END)

    if algo == "Insertion Sort":
        insertionSort(list)

    elif algo == "Selection Sort":
        selectionSort(list)

    elif algo == "Bubble Sort":
        bubbleSort(list)

    elif algo == "Quick Sort":
        quickSort(list)

    elif algo == "Merge Sort":
        mergeSort(list)

if __name__ == "__main__":
    root = Tk()
    root.geometry("1500x600")
    # root.resizable(False, False)

    # Creating Menubar
    menu = menuBar(root)
    # Adding Menubar to our software (root window)
    root.config(menu=menu)

    # Creating Select Box to choose sort Algo
    ttk.Label(root, text="Select Sort Method : ").grid(row=0, column=0, padx=10, pady=25)
    sort_algo = StringVar()
    sortChoosen = ttk.Combobox(root, width=30, textvariable=sort_algo)
    sortChoosen['values'] = ('Insertion Sort', 'Selection Sort', 'Bubble Sort', 'Quick Sort', 'Merge Sort')
    sortChoosen.grid(row=0, column=1)
    sortChoosen.current(0)

    # Enter List to sort
    ttk.Label(root, text="Enter Space Seperated Numbers : ").grid(row=1, column=0, padx=10, pady=5)
    array = ttk.Entry(root, width=33)
    array.grid(row=1, column=1)

    animation_button = ttk.Button(root, text="Start Animation", width=30, command=start_animation)
    animation_button.grid(row=2, column=0, pady=15)

    # Separator object
    separator = ttk.Separator(root, orient='vertical')
    separator.place(relx=0.37, rely=0, relwidth=0.2, relheight=1)

    # Adding Email Functionality
    email(root)

    root.mainloop()


"""
Helper for drawing convolutional neural network weights.

This may be removed in the future.
"""
import numpy as np
import ubelt as ub
try:
    import torch  # NOQA
except ImportError:
    print('warning: torch not available')
    torch = None

def make_conv_images(conv, color=None, norm_per_feat=True):
    """
    Convert convolutional weights to a list of visualize-able images

    Args:
        conv (torch.nn.Conv2d): a torch convolutional layer
        color (bool): if True output images are colorized
        norm_per_feat (bool): if True normalizes over each feature separately,
            otherwise normalizes all features together.

    Returns:
        ndarray:

    TODO:
        - [ ] better normalization options

    Example:
        >>> # xdoctest: +REQUIRES(module:torch)
        >>> conv = torch.nn.Conv2d(3, 9, (5, 7))
        >>> weights_tohack = conv.weight[0:7].data.numpy()
        >>> weights_flat = make_conv_images(conv, norm_per_feat=False)
        >>> # xdoctest: +REQUIRES(--show)
        >>> import kwimage
        >>> import kwplot
        >>> stacked = kwimage.stack_images_grid(weights_flat, chunksize=5, overlap=-1)
        >>> kwplot.imshow(stacked)
        >>> kwplot.show_if_requested()

    Ignore:
        >>> # xdoctest: +REQUIRES(module:torch)
        >>> import torchvision
        >>> conv = torchvision.models.resnet50(pretrained=True).conv1
        >>> #conv = torchvision.models.vgg11(pretrained=True).features[0]
        >>> weights_flat = make_conv_images(conv, norm_per_feat=False)
        >>> # xdoctest: +REQUIRES(--show)
        >>> import kwplot
        >>> import kwimage
        >>> stacked = kwplot.stack_images_grid(weights_flat, chunksize=8, overlap=-1)
        >>> kwplot.autompl()
        >>> kwplot.imshow(stacked)
        >>> kwplotwil.show_if_requested()
    """
    # get relavent data out of pytorch module
    weights = conv.weight.data.cpu().numpy()
    in_channels = conv.in_channels
    # out_channels = conv.out_channels
    spatial_dims = list(conv.kernel_size)
    n_space_dims = len(spatial_dims)

    if color is None:
        # color if possible
        color = (in_channels == 3)

    # Normalize layer weights between 0 and 1
    if norm_per_feat:
        # if normaxis=0 norm over output channels
        minval = weights.min(axis=(0, 1), keepdims=True)
        maxval = weights.max(axis=(0, 1), keepdims=True)
    else:
        minval = weights.min()
        maxval = weights.max()

    weights_norm = (weights - minval) / (maxval - minval)

    # If there are 3 input channels, we can visualize features in a colorspace
    if color:
        # Move colorable channels to the end (handle 1, 2 and 3d convolution)
        ifeat_axes = [0]
        color_axes = [1]
        space_axes = list(range(2, 2 + n_space_dims))
        axes = ifeat_axes + space_axes + color_axes
        weights_norm = weights_norm.transpose(*axes)
        color_dims = [in_channels]
    else:
        color_dims = []

    # flatten all non-spacetime/color dimensions
    weights_flat = weights_norm.reshape(-1, *(spatial_dims + color_dims))
    return weights_flat

def plot_convolutional_features(conv, limit=144, colorspace='rgb', fnum=None,
                                nCols=None, voxels=False, alpha=.2,
                                labels=False, normaxis=None, _hack_2drows=False):
    """Plots the convolutional layers to a matplotlib pyplot.

    The convolutional filters (kernels) are stored into a grid and saved to disk
    as a Maplotlib figure.  The convolutional filters, if it has one channel,
    will be stored as an intensity imgage.  If a colorspace is specified and
    there are three input channels, the convolutional filters will be
    represented as an RGB image.

    In the event that 2 or 4+ filters are
    displayed, the different channels will be flattened and showed as distinct
    outputs in the grid.

    TODO:
        - [ ] refactor to use make_conv_images

    Args:
        conv (torch.nn.modules.conv._ConvNd): torch convolutional layer with weights to draw

        limit (int): the limit on the number of filters drawn in the
            figure, achieved by simply dropping any filters past the limit
            starting at the first filter.  Detaults to 144.

        colorspace (str): the colorspace seen by the convolutional filter
            (if applicable), so we can convert to rgb for display.

        voxels (bool): if True, and we have a 3d conv, show the voxels

        alpha (float): only applicable if voxels=True

        stride (list): only applicable if voxels=True

    Returns:
        matplotlib.figure.Figure: fig - a Matplotlib figure

    References:
        https://matplotlib.org/devdocs/gallery/mplot3d/voxels.html

    Example:
        >>> # xdoctest: +REQUIRES(module:torch)
        >>> conv = torch.nn.Conv2d(3, 9, (5, 7))
        >>> plot_convolutional_features(conv, colorspace=None, fnum=None, limit=2)

    Example:
        >>> # xdoctest: +REQUIRES(--comprehensive)
        >>> # xdoctest: +REQUIRES(module:torch)
        >>> import torchvision
        >>> # 2d uncolored gray-images
        >>> conv = torch.nn.Conv3d(1, 2, (3, 4, 5))
        >>> plot_convolutional_features(conv, colorspace=None, fnum=1, limit=2)

        >>> # 2d colored rgb-images
        >>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=1, limit=2)

        >>> # 2d uncolored rgb-images
        >>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
        >>> plot_convolutional_features(conv, colorspace=None, fnum=1, limit=2)

        >>> # 3d gray voxels
        >>> conv = torch.nn.Conv3d(1, 2, (6, 4, 5))
        >>> plot_convolutional_features(conv, colorspace=None, fnum=1, voxels=True,
        >>>                             limit=2)

        >>> # 3d color voxels
        >>> conv = torch.nn.Conv3d(3, 2, (6, 4, 5))
        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=1,
        >>>                             voxels=True, alpha=1, limit=3)

        >>> # hack the nice resnet weights into 3d-space
        >>> # xdoctest: +REQUIRES(--network)
        >>> import torchvision
        >>> model = torchvision.models.resnet50(pretrained=True)
        >>> conv = torch.nn.Conv3d(3, 1, (7, 7, 7))
        >>> weights_tohack = model.conv1.weight[0:7].data.numpy()
        >>> # normalize each weight for nice colors, then place in the conv3d
        >>> for w in weights_tohack:
        ...     w[:] = (w - w.min()) / (w.max() - w.min())
        >>> weights_hacked = weights_tohack.transpose(1, 0, 2, 3)[None, :]
        >>> conv.weight.data[:] = torch.FloatTensor(weights_hacked)

        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=1, voxels=True, alpha=.6)

        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=2, voxels=False, alpha=.9)

    Example:
        >>> # xdoctest: +REQUIRES(--network)
        >>> # xdoctest: +REQUIRES(module:torch)
        >>> import torchvision
        >>> model = torchvision.models.resnet50(pretrained=True)
        >>> conv = model.conv1
        >>> plot_convolutional_features(conv, colorspace='rgb', fnum=None)

    """
    import kwplot
    kwplot.autompl()
    import matplotlib.pyplot as plt

    # get relavent data out of pytorch module
    weights = conv.weight.data.cpu().numpy()
    in_channels = conv.in_channels
    # out_channels = conv.out_channels
    kernel_size = conv.kernel_size
    conv_dim = len(kernel_size)

    # TODO: use make_conv_images in the 2d case here

    if voxels:
        # use up to 3 spatial dimensions
        spatial_axes = list(kernel_size[-3:])
    else:
        # use only 2 spatial dimensions
        spatial_axes = list(kernel_size[-2:])
    color_axes = []

    output_axis = 0

    # If there are 3 input channels, we can visualize features in a colorspace
    if colorspace is not None and in_channels == 3:
        # Move colorable channels to the end (handle 1, 2 and 3d convolution)
        axes = [0] + list(range(2, 2 + conv_dim)) + [1]
        weights = weights.transpose(*axes)
        color_axes = [in_channels]
        output_axis = 0
    else:
        pass

    # Normalize layer weights between 0 and 1
    if normaxis is None:
        minval = weights.min()
        maxval = weights.max()
    else:
        # if normaxis=0 norm over output channels
        minval = weights.min(axis=output_axis, keepdims=True)
        maxval = weights.max(axis=output_axis, keepdims=True)

    weights_norm = (weights - minval) / (maxval - minval)

    if _hack_2drows:
        # To agree with jason's visualization for a paper figure
        if not voxels:
            weights_norm = weights_norm.transpose(1, 0, 2, 3)

    # flatten everything but the spatial and requested color dims
    weights_flat = weights_norm.reshape(-1, *(spatial_axes + color_axes))

    num_plots = min(weights_flat.shape[0], limit)
    dim = int(np.ceil(np.sqrt(num_plots)))

    if voxels:
        from mpl_toolkits.mplot3d import Axes3D  # NOQA
        filled = np.ones(spatial_axes, dtype=np.bool)
        # np.ones(spatial_axes)
        # d, h, w = np.indices(spatial_axes)

    fnum = kwplot.ensure_fnum(fnum)
    fig = kwplot.figure(fnum=fnum)
    fig.clf()
    if nCols is None:
        nCols = dim
    pnum_ = kwplot.PlotNums(nCols=nCols, nSubplots=num_plots)

    def plot_kernel3d(i):
        img = weights_flat[i]

        # fig = kwplot.figure(fnum=fnum, pnum=pnum_[i])
        ax = fig.add_subplot(*pnum_[i], projection='3d')
        # ax = fig.gca(projection='3d')

        alpha_ = (filled * alpha)[..., None]
        colors = img

        if not color_axes:
            import kwimage
            # transform grays into colors
            grays = kwimage.atleast_nd(img, 4)
            colors = np.concatenate([grays, grays, grays], axis=3)

        if colorspace and color_axes:
            import kwimage
            # convert into RGB
            for d in range(len(colors)):
                colors[d] = kwimage.convert_colorspace(colors[d],
                                                       src_space=colorspace,
                                                       dst_space='rgb')
        facecolors = np.concatenate([colors, alpha_], axis=3)

        # shuffle dims so height is upwards and depth move away from us.
        dim_labels = ['d', 'h', 'w']
        axes = [2, 0, 1]

        dim_labels = list(ub.take(dim_labels, axes))
        facecolors = facecolors.transpose(*(axes + [3]))
        filled_ = filled.transpose(*axes)
        spatial_axes_ = list(ub.take(spatial_axes, axes))

        # ax.voxels(filled_, facecolors=facecolors, edgecolors=facecolors)
        if False:
            ax.voxels(filled_, facecolors=facecolors, edgecolors='k')
        else:
            # hack to show "occluded" voxels
            # stride = [1, 3, 1]
            stride = [2, 2, 2]
            slices = tuple(slice(None, None, s) for s in stride)
            spatial_axes2 = list(np.array(spatial_axes_) * stride)
            filled2 = np.zeros(spatial_axes2, dtype=np.bool)
            facecolors2 = np.empty(spatial_axes2 + [4], dtype=np.float32)
            filled2[slices] = filled_
            facecolors2[slices] = facecolors
            edgecolors2 = [0, 0, 0, alpha]
            # 'k'
            # edgecolors2 = facecolors2

            # Shrink the gaps, which let you see occluded voxels
            x, y, z = np.indices(np.array(filled2.shape) + 1).astype(float) // 2
            x[0::2, :, :] += 0.05
            y[:, 0::2, :] += 0.05
            z[:, :, 0::2] += 0.05
            x[1::2, :, :] += 0.95
            y[:, 1::2, :] += 0.95
            z[:, :, 1::2] += 0.95

            ax.voxels(x, y, z, filled2, facecolors=facecolors2, edgecolors=edgecolors2)

        for xyz, dlbl in zip(['x', 'y', 'z'], dim_labels):
            getattr(ax, 'set_' + xyz + 'label')(dlbl)

        for xyz in ['x', 'y', 'z']:
            getattr(ax, 'set_' + xyz + 'ticks')([])

        ax.set_aspect('equal')
        if not labels or i < num_plots - 1:
            # show axis only on the last plot
            ax.grid(False)
            plt.axis('off')

    for i in ub.ProgIter(range(num_plots), desc='plot conv layer',
                         enabled=False):
        if voxels:
            plot_kernel3d(i)
        else:
            img = weights_flat[i]
            kwplot.imshow(img, fnum=fnum, pnum=pnum_[i],
                          interpolation='nearest', colorspace=colorspace)
    return fig


from flask import request, jsonify
from flask_restful import Resource
from data import db_session
from data.products import Products

class ProductsListResource(Resource):
    def get(self):
        sess = db_session.create_session()
        try:
            types = request.args.get('types', type=str)
            if types:
                types = types.lower().split(',')
            else:
                types = ''
            price = request.args.get('price', type=str)
            if price:
                price = range(*map(int, request.args.get('price', type=str).split('-')))
            else:
                price = range(0, 10 ** 6)
            order = request.args.get('order')
            if not order:
                order = '0'
            sorting_orders = {
                '0': lambda x: x.price,
                '1': lambda x: -x.price,
                '2': lambda x: x.name
            }
            products = filter(lambda x: x.price in price and all([i in [j.name.lower() for j in x.categories] for i in types]),
                              sess.query(Products).all())
            products = list(sorted(products, key=sorting_orders[order]))
            if not products:
                return jsonify({'error': 'no products found'})
        except KeyError:
            return jsonify({'error': 'Bad request'})
        return jsonify(
            {
                'products':
                    [item.to_dict(only=('id', 'name', 'stringed_categories', 'image', 'price', 'about', 'specs')) for item in
                     products]
            }
        )

class ProductResource(Resource):
    def get(self, product_id):
        sess = db_session.create_session()
        product = sess.query(Products).get(product_id)
        if not product:
            return jsonify({'error': 'no product with such name'})
        return jsonify(
            {
                'product': product.to_dict(only=('id', 'name', 'stringed_categories', 'image', 'price', 'about', 'specs'))
            }
        )


import math
import random
import collections
import numpy as np

import cnn
from core import Game, Player, InvalidPlayError
from serialize import Tree

C = math.sqrt(2)  # Exploration parameter.
E = 0.05  # Epsilon greedy exploration parameter.
PLAYOUTS = 500  # Simulation playouts for Monte Carlo Tree Search.

class AIPlayer(Player):
    def __init__(self, name, pawns=None, tree=Tree(), lazy=False, debug=False):
        self.tree = tree
        self.lazy = lazy
        self.debug = debug
        super().__init__(name, pawns=pawns)

    def turn_options(self, game):
        state = game.compact_state()
        if self.lazy:
            try:
                options = self.tree[state]["options"]
            except KeyError:
                options = super().turn_options(game)
                self.tree.set_options(state, options)
        else:
            options = super().turn_options(game)
        if self.debug:
            for new_state, winner in options:
                game.set_state(new_state)
                game.print_state()
                try:
                    print(self.tree.dict[new_state])
                except KeyError:
                    print("No dict info")
            game.set_state(state)
        return options

    def select_func(self, options):
        states = []
        values = []
        for state, winner in options:
            if winner:
                return state
            states.append(state)
        return self.policy_func(states)

    def value_func(self, state):
        """Win probability."""
        val = None
        try:
            n = self.tree[state]["tries"]
            w = self.tree[state]["wins"]
            if n:
                val = w/n
        except KeyError:
            pass
        return val

    def policy_func(self, states):
        """Greedy."""
        max_val = 0
        selection = states[0]
        for state in states:
            val = self.value_func(state)
            if val and (val > max_val):
                selection = state
                max_val = val
        return selection

class RandomPlayer(AIPlayer):
    def setup(self, game):
        for pawn in self.pawns:
            self.active_pawn = pawn
            choices = pawn.placement_options(game)
            space = random.choice(choices)
            self.place(space)

    def turn(self, game):
        pawns = list(self.pawns).copy()
        random.shuffle(pawns)
        for pawn in pawns:
            self.active_pawn = pawn
            spaces = game.board.copy()
            random.shuffle(spaces)
            moved = False
            for move_space in spaces:
                try:
                    self.move(move_space)
                    if self.winner:
                        return
                    moved = True
                    break
                except InvalidPlayError:
                    pass
            if moved:
                for build_space in spaces:
                    try:
                        self.build(build_space)
                        return
                    except InvalidPlayError:
                        pass
        game.turns.remove(self)

class EpsilonGreedyPlayer(AIPlayer):
    def __init__(self, name, e=E, **kwargs):
        self.e = e
        super().__init__(name, **kwargs)

    def policy_func(self, states):
        if random.random() < self.e:
            random.shuffle(states)
            selection = states[0]
            return selection
        return super().policy_func(states)

class UCTPlayer(AIPlayer):
    def __init__(self, name, c=C, **kwargs):
        self.c = c
        super().__init__(name, **kwargs)

    def policy_func(self, states):
        total = 0
        max_uct = 0
        selection = None
        state_dict = {}
        untried_states = []
        for state in states:
            val = self.value_func(state)
            if val:
                n = self.tree[state]["tries"]
                total += n
                state_dict[state] = {"val": val, "n": n}
            else:
                untried_states.append(state)
        if untried_states:
            return self.untried_policy(untried_states)
        for state in state_dict:
            val = state_dict[state]["val"]
            n = state_dict[state]["n"]
            uct = val+math.pow(1.0*math.log(total)/n, 1/self.c)
            if uct > max_uct:
                selection = state
                max_uct = uct
        return selection

    def untried_policy(self, states):
        return states[0]

class MCTSPlayer(AIPlayer):
    def __init__(self, name, c=C, playouts=PLAYOUTS, **kwargs):
        self.c = c
        self.playouts = playouts
        super().__init__(name, **kwargs)

    def tree_sim(self, state, player_names):
        players = []
        for name in player_names:
            players.append(UCTPlayer(name, tree=self.tree, c=self.c))
        game = Game(players)
        game.set_state(state)
        for player in game.play():
            yield game

    def random_sim(self, state, player_names):
        players = []
        for name in player_names:
            players.append(RandomPlayer(name, tree=self.tree))
        game = Game(players)
        game.set_state(state)
        game.next_player()
        for player in game.play():
            pass
        return game.winner().name

    def search(self, game):
        orig_state = game.compact_state()
        orig_player_names = [player.name for player in game.turns]
        # simulate playouts
        for _ in range(self.playouts):
            states = []
            # choose_uct until reaching untried state or end
            for sim in self.tree_sim(orig_state, orig_player_names):
                player_name = sim.active_player().name
                sim_state = sim.compact_state()
                states.append((player_name, sim_state))
                self.tree.add_try(sim_state)
                if self.tree[sim_state]["tries"] == 1:
                    break
            # if untried state, random playout from leaf
            winner = sim.winner()
            if winner:
                winner_name = winner.name
            else:
                sim_player_names = [player.name for player in sim.turns]
                winner_name = self.random_sim(states[-1][1], sim_player_names)
            # update tree for all states from root option to leaf
            for player_name, state in states:
                if winner_name == player_name:
                    self.tree.add_win(state)

    def setup_options(self, game):
        self.search(game)
        return super().setup_options(game)

    def turn_options(self, game):
        self.search(game)
        return super().turn_options(game)

    def policy_func(self, states):
        # act greedily
        return super().policy_func(states)

class ThompsonSamplingPlayer(AIPlayer):
    def value_func(self, state):
        val = None
        try:
            n = self.tree[state]["tries"]
            w = self.tree[state]["wins"]
            if n:
                l = n - w
                val = np.random.beta(w+1, l+1)
        except KeyError:
            pass
        return val

class CNNPlayer(ThompsonSamplingPlayer):
    def __init__(self, name, model=None, **kwargs):
        self.model = model
        if not self.model:
            self.model = cnn.load_model()
        super().__init__(name, **kwargs)

    def policy_func(self, states):
        max_val = 0
        selection = None
        untried_states = []
        for state in states:
            val = self.value_func(state)
            if not val:
                untried_states.append(state)
            elif val > max_val:
                selection = state
                max_val = val
        if untried_states:
            return cnn.max_state(untried_states, self.model)
        return selection

class UctCnnPlayer(UCTPlayer):
    def __init__(self, name, c=C, model=None, **kwargs):
        self.model = model
        if not self.model:
            self.model = cnn.load_model()
        super().__init__(name, c=c, **kwargs)

    def untried_policy(self, states):
        return cnn.max_state(states, self.model)

class MctsCnnPlayer(MCTSPlayer):
    def __init__(self, name, model=None, **kwargs):
        self.model = model
        if not self.model:
            self.model = cnn.load_model()
        super().__init__(name, **kwargs)

    def tree_sim(self, state, player_names):
        players = []
        for name in player_names:
            players.append(CNNPlayer(name, tree=self.tree, model=self.model))
        game = Game(players)
        game.set_state(state)
        for player in game.play():
            yield game


#from sklearn import *
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import csv
import numpy as np
import re
from sklearn.naive_bayes import GaussianNB
from sklearn.feature_extraction import DictVectorizer

def fixText(text):
    row = []
    z = text.find(',')
    if z == 0:
        row.append('')
    else:
        row.append(text[:z])
    for x in range(len(text)):
        if text[x] != ',':
            pass
        else:
            if x == (len(text) - 1):
                row.append('')
            else:
                if ',' in text[(x + 1):]:
                    y = text.find(',', (x + 1))
                    c = text[(x + 1):y]
                else:
                    c = text[(x + 1):]
                row.append(c)
    return row

def createTuple(oldFile):
# oldFile is filename (e.g. 'sheet.csv')
    f1 = open(oldFile, "r")
    tup = []
    while 1:
        text = f1.readline()
        if text == "":
            break
        else:
            pass
        if text[-1] == '\n':
            text = text[:-1]
        else:
            pass
        row = fixText(text)
        tup.append(row)
    return tup

def incomeTrans(tup):
    for row in tup:
        for i in range(0, len(row) - 2):
            if(bool(re.search(regex, row[i])) == True):
                if(bool(re.search(regex, row[i + 1])) == True):
                    # join the strings
                    seq = (row[i], row[i + 1])
                    row[i] = ','.join(seq)
                    # pop out useless string
                    row.pop(i + 1)
                    break
                elif(bool(re.search(regex, row[i + 2])) == True):
                    seq = (row[i], row[i + 1], row[i + 2])
                    row[i] = ','.join(seq)
                    # pop out useless string
                    row.pop(i + 1)
                    row.pop(i + 1)
                    break
    return tup

def appUseTrans(tup):
    regex = '\"'

    for row in tup:
        count = 0
        templist = []
        index = 0
        length = len(row)
        for i in range(0, length):
            if (row[i].startswith(regex) and not(row[i].endswith(regex))):
                count += 1
                templist.append(row[i])
                index = i
            elif (row[i].endswith(regex) and not(row[i].startswith(regex))):
                templist.append(row[i])
                row[index] = ','.join(templist)
                # delete useless data
                #print(count, index)
                # print(row)
                # reset
                count = 0
                templist = []
                #print (row[index])

            elif (not(count == 0)):
                count += 1
                templist.append(row[i])
                # print(templist)
    for row in tup:
        for z in range(0, len(row)):
            if (row[0] == '3882027944'):
                row.pop(8)
                row.pop(8)
                # print(row)
                break
            if (row[0] == '3878526543'):
                row.pop(4)
                row.pop(4)
                row.pop(4)
                # print(row)
                break
            if (row[0] == '3878262512'):
                row.pop(8)
                row.pop(8)
                # print(row)
                break

    return tup

# app category
def createAppCategory(tup):
    appCategory = {}  # 'App': 'ID'
    counter = 0
    appCategory.update(
        {'A specific website or app (please provide the answer)': str(counter)})
    counter += 1
    appCategory.update({'-': str(counter)})
    for row in tup:
        for i in range(0, len(row)):
            if (row[2] == 'A specific website or app (please provide the answer)'):
                if len(appCategory) == 0:
                    counter += 1
                    appCategory[row[3]] = str(counter)
                    # print("ID: %d, %s" %(counter,row[3]))
                    break
                else:
                    for j in range(0, len(appCategory)):
                        if (not(row[3] in appCategory.keys())):
                            counter += 1
                            # print("ID: %d, %s" %(counter,row[3]))
                            appCategory[row[3]] = str(counter)
                            # print(row[3])
                            break

    return appCategory

def createIncomeCategory(tup):
    incomeCategory = {}  # 'incomeRange': 'ID'
    counter = -1
    for row in tup:
        for i in range(0, len(row)):
            if len(incomeCategory) == 0:
                counter += 1
                # print("ID: %d, %s" % (counter, row[7]))
                incomeCategory.update({row[7]: str(counter)})
                break
            else:
                for j in range(0, len(incomeCategory)):
                    if (not(row[7] in incomeCategory.keys())):
                        counter += 1
                        # print("ID: %d, %s" % (counter, row[7]))
                        # print(row)
                        incomeCategory.update({row[7]: str(counter)})
                        # print(row[3])
                        break
    return incomeCategory

def createCheckOrNotCategory(tup):
    checkOrNotCategory = {}  # 'CheckOrNot': 'ID'
    counter = -1
    for row in tup:
        for i in range(0, len(row)):
            if len(checkOrNotCategory) == 0:
                counter += 1
                # print("ID: %d, %s" % (counter, row[1]))
                checkOrNotCategory.update({row[1]: str(counter)})
                break
            else:
                for j in range(0, len(checkOrNotCategory)):
                    if (not(row[1] in checkOrNotCategory.keys())):
                        counter += 1
                        # print("ID: %d, %s" % (counter, row[1]))
                        checkOrNotCategory.update({row[1]: str(counter)})
                        break
    return checkOrNotCategory

def createHowCheckCategory(tup):
    howCheckCategory = {}  # 'HowCheck': 'ID'
    counter = -1
    for row in tup:
        for i in range(0, len(row)):
            if len(howCheckCategory) == 0:
                counter += 1
                # print("ID: %d, %s" % (counter, row[2]))
                howCheckCategory.update({row[2]: str(counter)})
                break
            else:
                for j in range(0, len(howCheckCategory)):
                    if (not(row[2] in howCheckCategory.keys())):
                        counter += 1
                        # print("ID: %d, %s" % (counter, row[2]))
                        howCheckCategory.update({row[2]: str(counter)})
                        break
    return howCheckCategory

def createWatchCheckCategory(tup):
    watchCheck = {}  # 'WatchCheck': 'ID'
    counter = -1
    for row in tup:
        for i in range(0, len(row)):
            if len(watchCheck) == 0:
                counter += 1
                # print("ID: %d, %s" % (counter, row[4]))
                watchCheck.update({row[4]: str(counter)})
                break
            else:
                for j in range(0, len(watchCheck)):
                    if (not(row[4] in watchCheck.keys())):
                        counter += 1
                        # print("ID: %d, %s" % (counter, row[4]))
                        watchCheck.update({row[4]: str(counter)})
                        break
    return watchCheck

def createAgeCategory(tup):
    age = {}  # 'Age': 'ID'
    counter = -1
    for row in tup:
        for i in range(0, len(row)):
            if len(age) == 0:
                counter += 1
                # print("ID: %d, %s" % (counter, row[5]))
                age.update({row[5]: str(counter)})
                break
            else:
                for j in range(0, len(age)):
                    if (not(row[5] in age.keys())):
                        counter += 1
                        # print("ID: %d, %s" % (counter, row[5]))
                        age.update({row[5]: str(counter)})
                        break
    return age

def createGenderCategory(tup):
    gender = {'Gender': 'ID'}
    counter = -1
    for row in tup:
        for i in range(0, len(row)):
            if len(gender) == 0:
                counter += 1
                # print("ID: %d, %s" % (counter, row[6]))
                gender.update({row[6]: str(counter)})
                break
            else:
                for j in range(0, len(gender)):
                    if (not(row[6] in gender.keys())):
                        counter += 1
                        # print("ID: %d, %s" % (counter, row[6]))
                        gender.update({row[6]: str(counter)})
                        break
    return gender

def createRegionCategory(tup):
    region = {'Region': 'ID'}
    counter = -1
    for row in tup:
        for i in range(0, len(row)):
            if len(region) == 0:
                counter += 1
                # print("ID: %d, %s" % (counter, row[8]))
                region.update({row[8]: str(counter)})
                break
            else:
                for j in range(0, len(region)):
                    if (not(row[8] in region.keys())):
                        counter += 1
                        # print("ID: %d, %s" % (counter, row[8]))
                        region.update({row[8]: str(counter)})
                        break
    return region

def categoryTrans(tup):
    appCategory = createAppCategory(tup)
    incomeCategory = createIncomeCategory(tup)
    checkOrNotCategory = createCheckOrNotCategory(tup)
    howCheckCategory = createHowCheckCategory(tup)
    watchCheckCategory = createWatchCheckCategory(tup)
    ageCategory = createAgeCategory(tup)
    genderCategory = createGenderCategory(tup)
    regionCategory = createRegionCategory(tup)

    for row in tup:
        for i in range(0, len(row)):
            if(row[0] == 'RespondentID'):
                row[0] = '0'
            if(row[1] in checkOrNotCategory.keys()):
                row[1] = checkOrNotCategory[row[1]]
            elif(row[2] in howCheckCategory.keys()):
                row[2] = howCheckCategory[row[2]]
            elif(row[3] in appCategory.keys()):
                row[3] = appCategory[row[3]]
            elif(row[4] in watchCheckCategory.keys()):
                row[4] = watchCheckCategory[row[4]]
            elif(row[5] in ageCategory.keys()):
                row[5] = ageCategory[row[5]]
            elif(row[6] in genderCategory.keys()):
                row[6] = genderCategory[row[6]]
            elif(row[7] in incomeCategory.keys()):
                row[7] = incomeCategory[row[7]]
            elif(row[8] in regionCategory.keys()):
                row[8] = regionCategory[row[8]]
    return tup
def printCSV(tup):
    print('\n'.join(['\t'.join(['{:}'.format(item) for item in row])
    for row in categoryTrans(tup)]))

regex = '\"'
tup = createTuple('weather-check.csv')
tup = incomeTrans(tup)
# the last data table
final_data_table = appUseTrans(tup)
numericTable = categoryTrans(final_data_table)
for row in numericTable:
    for i in range(0, len(row)):
        row[i] = int(row[i])

attributeRange = [4, 5, 6, 7, 8]
attr = np.array([[l[i] for i in attributeRange] for l in numericTable])
classRange = [2]
classAttr = np.array([[l[i] for i in classRange] for l in numericTable])
# print(np.asarray(attr))
# print out the numeric table
#for rows in categoryTrans(final_data_table):
#    for i in range(0, len(rows)):
#        print(rows[i],"\t")
#    print("\n")

printCSV(final_data_table)

#gnb = GaussianNB()
#clf = gnb.fit(attr, classAttr)
#for row in attr:
#    print(clf.predict(row))
# print("Number of mislabeled points out of a total %d points : %d"
#    % (numericTable.shape[0],(classAttr != y_pred).sum()))


import numpy as np
from sklearn.cluster import KMeans
import cv2

class PaletteGenerator():
    def __init__(self, img):
        self.img = cv2.imread(img)
        img_rgb = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)
        img_resized = cv2.resize(img_rgb, (300,300), interpolation = cv2.INTER_AREA)
        self.img_array = img_resized.reshape(-1,3)

    def palette(self):
        self.cluster =  KMeans(n_clusters=5)
        x = self.cluster.fit(self.img_array)
        p = np.zeros(shape=(50,300, 3), dtype=np.uint8)
        step = 300 / x.cluster_centers_.shape[0]
        lst = enumerate(x.cluster_centers_)
        for i, center in lst:
            p[:, int(i * step):int((i + 1) * step), :] = center
        return p