import os
import pickle
import csv
import json
from copy import copy
import numpy as np

import datetime
from scipy.spatial.distance import jaccard, euclidean

def get_files(root_path):
  dat_files = set()
  for (root, dirs, files) in os.walk(root_path, topdown=True):
    for file in files:
        dat_files.add(root_path + file)

  dat_files = list(dat_files)
  return dat_files

OMNI = 'omni'
PARTIAL = 'partial'
NO_REC = 'no_rec'
rec_policy_keys = [OMNI, PARTIAL, NO_REC]
#WORKING_DIR = '/Users/guyaridor/Desktop/ExAnteFilterBubble/data/'
WORKING_DIR = '/media/IntentMedia/rec_data/merged_results/'
DATA_DIR = '/media/IntentMedia/rec_data/sim_results/'
data_files = get_files(DATA_DIR)

def d(i,j, N):
    return min(abs(i-j), abs(j-i), abs(j-i-N), abs(i-j-N))

def div_fun(CiT, T, N):
    div_score = 0.0
    for i in range(len(CiT)):
        for j in range(len(CiT)):
            if i == j: continue
            div_score = div_score + d(CiT[i],CiT[j], N)#euclidean( iota(CiT[i], N), iota(CiT[j], N) )
    return div_score*(1.0/(T*(T-1))) / N

def homogeneity(C1, C2, type_sim="jaccard"):
    if type_sim == "jaccard":
        return 1 - jaccard(C1, C2)
    return None

def follow_rec(Ci, Rec, N, T):
    s = 0.0
    for i in range(len(Ci)):
        if Ci[i] == Rec[i]:
            s += 1
    return s / T

def parse_pickle_key(key):
    key = eval(key)
    dat = {
        'N': float(key[0]),
        'T': float(key[1]),
        'rho': key[2],
        'beta': key[3],
        'sigma': key[4],
        'alpha': key[5],
        'epsilon': key[6]
        #'pop_idx': pop_idx
    }
    return dat

print("STARTING TIME PATH")
INDIVIDUAL_FIELD_NAMES =['pop_idx', 'regime', 'rho', 'beta', 'epsilon', 'alpha', 'N', 'T', 'sigma', 't', 'follow_recommendation', 'mean_consumption_dist', 'median_consumption_dist', 'sd_consumption_dist', 'cur_utility', 'average_cumulative_utility', 'utility_difference', 'local_move_05', 'local_move_025', 'local_move_10', 'instantaneous_welfare_average']
with open(WORKING_DIR + 'time_path.csv', 'w') as rec_csv:
    data_writer = csv.DictWriter(rec_csv, fieldnames=INDIVIDUAL_FIELD_NAMES)
    data_writer.writeheader()
    for file in data_files:
        print(file)
        print("@ {}".format(datetime.datetime.now()))
        df = None
        with open(file, 'r') as fp:
            df = json.load(fp)
        for key, value in df.items():
            for pop_idx in range(len(value)):
                dat = parse_pickle_key(key)
                N = dat['N']
                dat['pop_idx'] = pop_idx
                cur = value[pop_idx]
                consumption = cur['Consumption']
                welfare = cur['Welfare']
                for policy in rec_policy_keys:
                    consumption_arr = np.array(consumption[policy])
                    welfare_arr = np.array(welfare[policy])
                    dat['regime'] = policy
                    if policy == PARTIAL:
                        follow_rec_arr = np.array(cur['Rec'][policy])

                    cum_welfare = 0
                    for t in range(int(dat['T'])) :
                        dat['t'] = t

                        # consumption dist average
                        l = len(consumption_arr[t, :])
                        if t != 0:
                            distance = [d(consumption_arr[t, cur], consumption_arr[t-1, cur], N) for cur in range(l)]
                            dat['mean_consumption_dist'] = np.mean(distance)
                            dat['median_consumption_dist'] = np.median(distance)
                            dat['sd_consumption_dist'] = np.std(distance)
                            dat['local_move_05'] =  np.mean([dist < (dat['N'] * 0.05)  for dist in distance])
                            dat['local_move_025'] = np.mean([dist < (dat['N'] * 0.025)  for dist in distance])
                            dat['local_move_10'] =  np.mean([dist < (dat['N'] * 0.1)  for dist in distance])

                        # cumulative welfare avg
                        dat['instantaneous_welfare_average'] = np.mean(welfare_arr[t, :])

                        # instantaneous (at time t) welfare avg
                        cum_welfare += np.mean(welfare_arr[t, :])
                        dat['average_cumulative_utility'] = float(cum_welfare)/dat['T']

                        cur_dat = copy(dat)
                        data_writer.writerow(cur_dat)

INDIVIDUAL_FIELD_NAMES =['pop_idx', 'indiv_idx', 'regime', 'welfare', 'diversity_score', 'rho', 'beta', 'epsilon', 'follow_recommendation', 'N', 'T', 'sigma', 'alpha', 'nr_pop', 'nr_ind']
with open(WORKING_DIR + 'rec_data.csv', 'w') as rec_csv:
    data_writer = csv.DictWriter(rec_csv, fieldnames=INDIVIDUAL_FIELD_NAMES)
    data_writer.writeheader()
    for file in data_files:
        print(file)
        print("@ {}".format(datetime.datetime.now()))
        df = None
        with open(file, 'r') as fp:
            df = json.load(fp)

        for key, value in df.items():
            for pop_idx in range(len(value)):
                dat = parse_pickle_key(key)
                T = dat['T']
                N = dat['N']
                dat['pop_idx'] = pop_idx
                cur = value[pop_idx]
                welfare = cur['Welfare']
                consumption = cur['Consumption']
                for policy in rec_policy_keys:
                    dat['regime'] = policy
                    for indiv_idx in range(len(welfare[policy])):
                        dat['indiv_idx'] = indiv_idx
                        welfare_arr = np.array(welfare[policy])
                        dat['welfare'] = np.sum(welfare_arr[:,indiv_idx]) / T
                        consumption_arr = np.array(consumption[policy])
                        dat['diversity_score'] = div_fun(consumption_arr[:,indiv_idx], T, N)
                        dat['follow_recommendation'] = False
                        if policy == PARTIAL:
                            follow_rec_arr = np.array(cur['Rec'][policy])
                            dat['follow_recommendation'] = follow_rec(consumption_arr[:,indiv_idx], follow_rec_arr[:,indiv_idx], T, N)
                        data_writer.writerow(copy(dat))

print("STARTING HOMOGENEITY")
INDIVIDUAL_FIELD_NAMES =['pop_idx', 'regime', 'rho', 'beta', 'N', 'T', 'sigma', 'jaccard', 'beta', 'alpha', 'epsilon', 'nr_pop', 'nr_ind']
with open(WORKING_DIR + 'homogeneity_data.csv', 'w') as rec_csv:
    data_writer = csv.DictWriter(rec_csv, fieldnames=INDIVIDUAL_FIELD_NAMES)
    data_writer.writeheader()
    for file in data_files:
        print(file)
        print("@ {}".format(datetime.datetime.now()))
        df = None
        with open(file, 'r') as fp:
            df = json.load(fp)
        for key, value in df.items():
            for pop_idx in range(len(value)):
                dat = parse_pickle_key(key)
                T = dat['T']
                N = dat['N']
                cur = value[pop_idx]
                consumption = cur['Consumption']
                for policy in rec_policy_keys:
                    dat['regime'] = policy
                    consumption_arr = np.array(consumption[policy])
                    iter_size = len(consumption_arr[0,:])
                    tot = 0.0
                    for indiv_idx1 in range(iter_size):
                        for indiv_idx2 in range(iter_size):
                            if indiv_idx1 == indiv_idx2: continue
                            c1 = consumption_arr[:,indiv_idx1]
                            c2 = consumption_arr[:,indiv_idx2]
                            dist = homogeneity(c1, c2, "jaccard")
                            tot += dist
                    tot /= (iter_size * (iter_size - 1))
                    dat['jaccard'] = tot
                    cur_dat = copy(dat)
                    data_writer.writerow(cur_dat)


# -*- coding: utf-8 -*-
import scrapy
'''以JSON格式导出爬取内容'''

class QuetosExtractSpider(scrapy.Spider):
    name = 'quetos_extract'

    def start_requests(self):
        urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):

        """下面代码的含义是，将html中<div class="quote">内包含的
        <text><author><tags>都保存到items中"""

        for quote in response.css('div.quote'):
            yield {
                'text': quote.css('span.text::text').extract_first(),
                'author': quote.css('small.author::text').extract_first(),
                'tags': quote.css('div.tags a.tag::text').extract(),
            }

        """
        并且在外加命令 scrapy crawl quotes -o quotes.json 后
        保存到名为quotes.json的文件中
        """


"""
Based on:

https://devcenter.heroku.com/articles/getting-started-with-django
"""

from settings import *
import os

DEBUG = False

# Parse database configuration from $DATABASE_URL
import dj_database_url

DATABASES = {'default': dj_database_url.config() }

WSGI_APPLICATION = 'pdxtrees.wsgi_deploy.application'

SECRET_KEY = os.environ.get('SECRET_KEY')

AWS_S3_ACCESS_KEY_ID = os.environ.get('AWS_S3_ACCESS_KEY_ID')
AWS_S3_SECRET_ACCESS_KEY = os.environ.get('AWS_S3_SECRET_ACCESS_KEY')

# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# Allow all host headers
ALLOWED_HOSTS = ['*']

# Static asset configuration
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = 'static'
STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)


# coding:utf-8
from __future__ import unicode_literals

from django import forms

from .models import Student

class StudentForm(forms.ModelForm):
    def clean_qq(self):
        cleaned_data = self.cleaned_data['qq']
        if not cleaned_data.isdigit():
            raise forms.ValidationError('必须是数字！')

        return int(cleaned_data)

    class Meta:
        model = Student
        fields = (
            'name', 'sex', 'profession',
            'email', 'qq', 'phone'
        )


# 读取数据
import pandas as pd

def load_wingsize():
    """

    :return: the wing span limitations for each gate
    """
    data = pd.read_excel("./data/wingsizelimit.xls", sheet_name=None)
    sheet_data = data['sheet1']
    wingsize = {}
    for i in sheet_data.index:
        # print(sheet_data['gate'][i], end=' ')
        # print(sheet_data['size_limit'][i])
        wingsize[str(sheet_data['gate'][i])] = sheet_data['size_limit'][i]
    # print(wingsize)
    return wingsize

def load_airlinsgate():
    """

    :return: the available gates for each airline
    """
    airlines_data = pd.read_csv("./data/airlinesgate.csv", header=0, usecols=["airlines"])
    airlines = {}
    with open("./data/airlinesgate.csv", 'r') as gate:
        lines = gate.readlines()
        counter = 0
        gate_data = []
        for i in lines:
            counter += 1
            temp = i.split(',')
            gate_set = []
            for j in temp:
                j = j.strip()
                if j != "":
                    gate_set.append(j)
            gate_set.pop(0)
            gate_data.append(gate_set)
    wingsize = load_wingsize()
    gate_list = list(wingsize.keys())
    temp = gate_list[73:116]
    temp.extend(gate_list[128:139])
    for i in range(0, counter-1):
        if gate_data[i+1] not in ['cargo', 'general', 'corporate']:
            airlines[airlines_data['airlines'][i]] = gate_data[i+1]
        else:
            airlines[airlines_data['airlines'][i]] = temp
    # print(airlines)
    return airlines

def load_traffic(filename):
    """

    :param filename: the file which is calculated now
    :return: the data of flights
    """
    data = pd.read_csv(filename)
    data = data.to_dict(orient='list')
    # print(data)
    n = len(data['data'])
    for i in range(n):
        if data['arrivee'][i] == 'ZBTJ':
            data['callsign'][i] = data['callsign'][i] + ' ar'
        else:
            data['callsign'][i] = data['callsign'][i] + ' de'
    return data

def load_taxitime(regulation):
    """

    :param regulation: PN or NP
    :return: the taxiing time of each gate
    """
    data = pd.read_excel("./data/mintaxitime.xlsx", sheet_name=None, header=2)
    sheet_data = data['sheet1']
    # print(sheet_data['DEP-16R'])
    taxitime = {}
    for i in sheet_data.index:
        if regulation == 1:
            taxitime[sheet_data['Gate'][i]] = [sheet_data['DEP-16R'][i],
                                               sheet_data['ARR-16L'][i], sheet_data['ARR-16R'][i]]
        elif regulation == 2:
            taxitime[sheet_data['Gate'][i]] = [sheet_data['DEP-16R.1'][i],
                                               sheet_data['ARR-16L.1'][i], sheet_data['ARR-16R.1'][i]]
        elif regulation == 3:
            taxitime[sheet_data['Gate'][i]] = [sheet_data['DEP-16R.2'][i],
                                               sheet_data['ARR-16L.2'][i], sheet_data['ARR-16R.2'][i]]
        else:
            taxitime[sheet_data['Gate'][i]] = [sheet_data['DEP-16R.3'][i],
                                               sheet_data['ARR-16L.3'][i], sheet_data['ARR-16R.3'][i]]
    wingsize = load_wingsize()
    gate_list = list(wingsize.keys())
    taxiingtime = {}
    for gate in gate_list:
        taxiingtime[str(gate)] = taxitime[str(gate)]
    return taxiingtime


"""
This variables and constants are using in
the main file - main.py. Each section
is dived by following comment.
"""

from math import ceil
from pygame import init, display, FULLSCREEN

# display
init()

display_info = display.Info()
width = display_info.current_w
height = display_info.current_h
screen_mode = FULLSCREEN

FPS = 600

# objects
walls_width = height // 200

menu_coord_x = ceil(width * 0.775)
menu_bar_x = menu_coord_x + 0.75 * walls_width
menu_bar_y = walls_width
menu_bar_width = width - menu_coord_x - 2 * walls_width
menu_bar_height = height - 2 * walls_width

menu_bar_draw = [menu_bar_x, menu_bar_y, menu_bar_width, menu_bar_height]
menu_bar_rect = [menu_bar_x, 0, width, height]

walls_coord = {
    "left": [(0, 0), (0, height), walls_width],
    "right": [(width, 0), (width, height), walls_width],
    "bottom": [(0, height), (width, height), walls_width],
    "top": [(0, 0), (width, 0), walls_width],
    "menu": [(menu_coord_x, 0), (menu_coord_x, height), walls_width // 2],
}

funnel_width = width - menu_bar_width
funnel_hole_width = ceil(funnel_width * 0.025)
funnel_hole_height = ceil(funnel_hole_width * 0.25)
funnel_height = ceil(height * 0.325)
funnel_wall_width = walls_width // 2

funnel_coord_left = {
    "top": [
        (0, 0),
        (
            funnel_width // 2 - funnel_hole_width,
            funnel_height // 2 - funnel_hole_height,
        ),
        funnel_wall_width,
    ],
    "vertical": [
        (
            funnel_width // 2 - funnel_hole_width,
            funnel_height // 2 - funnel_hole_height,
        ),
        (
            funnel_width // 2 - funnel_hole_width,
            funnel_height // 2 + funnel_hole_height,
        ),
        funnel_wall_width,
    ],
    "bottom": [
        (
            funnel_width // 2 - funnel_hole_width,
            funnel_height // 2 + funnel_hole_height,
        ),
        (0, funnel_height),
        funnel_wall_width,
    ],
}
funnel_coord_right = {
    "top": [
        (funnel_width, 0),
        (
            funnel_width // 2 + funnel_hole_width,
            funnel_height // 2 - funnel_hole_height,
        ),
        funnel_wall_width,
    ],
    "vertical": [
        (
            funnel_width // 2 + funnel_hole_width,
            funnel_height // 2 - funnel_hole_height,
        ),
        (
            funnel_width // 2 + funnel_hole_width,
            funnel_height // 2 + funnel_hole_height,
        ),
        funnel_wall_width,
    ],
    "bottom": [
        (
            funnel_width // 2 + funnel_hole_width,
            funnel_height // 2 + funnel_hole_height,
        ),
        (funnel_width, funnel_height),
        funnel_wall_width,
    ],
}

pins_step = ceil(width * 0.03125)
pins_radius = ceil(width * 0.005)

pins_width = width - menu_bar_width
pins_height = ceil((height - funnel_height) * 0.55)

pins_row = pins_width // ceil(pins_step * 0.75)
pins_column = pins_height // ceil(pins_step * 0.45)

# widgets
sliders_type = {
    "ball_amount": {"min": 1, "max": 20, "step": 2, "initial": 5},
    "ball_mass": {"min": 1, "max": 100, "step": 10, "initial": 5},
    "ball_radius": {
        "min": 2,
        "max": ceil(funnel_hole_width * 0.75),
        "step": 1,
        "initial": 5,
    },
    "ball_elasticity": {
        "min": 0.1,
        "max": 5,
        "step": 0.5,
        "initial": 0.1,
    },
    "friction": {
        "min": 1.0,
        "max": 10.0,
        "step": 1,
        "initial": 1.0,
    },
    "wall_elasticity": {"min": 0.8, "max": 13, "step": 0.2, "initial": 0.8},
    "gravity": {"min": -5000, "max": 10000, "step": 300, "initial": 300},
}

text_widget = [
    "Amount of balls",
    "Value of ball's mass",
    "Value of ball's radius",
    "Value of ball's elasticity",
    "Value of ball's friction",
    "Value of wall's elasticity",
    "Value of gravity",
    "Press LMB to spawn balls",
    "Hold RMB to create a wall",
    "Press BACKSPACE to reset",
    "Press ESC to exit"
]
pos_x_text = ceil(width * 0.81725)
pos_x_slider = ceil(width * 0.825)
pos_y_step = height * 0.0725

font_size = ceil(width * 0.015)
handle_radius = ceil(width * 0.005)
slider_width = width // 8

# color
background_color = (0, 0, 0)
walls_color = (128, 128, 128, 255)
menu_color = ()

slider_color = (40, 40, 40)
slider_handler_color = (200, 200, 200)
text_color = (128, 128, 128)

funnel_wall_color = (128, 128, 128, 255)
pins_color = (85, 85, 85, 255)

# parameters
parameters = {
    key: value["initial"] for key, value in sliders_type.items()
}


from PyQt5.QtWidgets import *

from controller_lsa_dummy.lsa_model import LsaModel

class LsaWidget(QFrame):

    def __init__(self, parent: QWidget = None) -> None:
        super().__init__(parent)

        self.initUi()

    def initUi(self):
        self.tableView = QTableView()
        self.setLayout(QVBoxLayout())
        self.layout().addWidget(self.tableView)

        self.tableView.setShowGrid(False)
        self.tableView.verticalHeader().hide()
        self.tableView.horizontalHeader().hide()
        self.tableView.setSelectionBehavior(QTableView.SelectRows)
        self.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.tableView.setStyleSheet(
            "QListView {padding: 8;}"
            "QListView::item {margin: 8;}"
            "QListview::item:selected {background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #369, stop:1 #147); color: white;}")

        self.model = LsaModel()
        self.tableView.setModel(self.model)


import numpy as np
from matplotlib import pyplot as plt
from matplotlib import ticker
from PIL import Image
from statistics import mean
from collections import Counter
def threshold(imageArray):

    balanceAr = []
    newAr = imageArray
    from statistics import mean
    for eachRow in imageArray:
        for eachPix in eachRow:
            avgNum = mean(eachPix[:3])
            balanceAr.append(avgNum)

    balance = mean(balanceAr)
    for eachRow in newAr:
        for eachPix in eachRow:
            if mean(eachPix[:3]) > balance:
                eachPix[0] =255
                eachPix[1] =255
                eachPix[2] =255
                eachPix[3] =255

            else:
                eachPix[0] =0
                eachPix[1] =0
                eachPix[2] =0
                eachPix[3] =255
    return (newAr)
def createExample():
    with open('numArEx.txt','a') as fp:
        numbersWeHave=range(0,10)
        decimalWeHave=range(1,10)
        for number in numbersWeHave:
            for decimal in decimalWeHave:
#                print(str(number)+"."+str(decimal))
                imageFilePath='images/numbers/'+str(number)+'.'+str(decimal)+'.png'
                i=Image.open(imageFilePath)
                iar=np.array(i)
                iarl=iar.tolist()
                fp.write(str(number)+'::'+str(iarl)+'\n')

        return("done")
#  createExample()
def matchExample(pngFile):
    matchedAr=[]
    img=Image.open(pngFile)
    iar=np.array(img)
    iarl=iar.tolist()

    with open('numArEx.txt','r') as fp:
        lines=fp.read().split('\n')

#        print(lines)
        for line in lines:
            try:

                line_split=line.split('::')
                numb=line_split[0]
                ar=line_split[1]
                InQuestion=str(iarl)
                checkEx=ar.split("],")
                InQEx=InQuestion.split("],")
                x=0
                while(x<len(checkEx)):
                    if(checkEx[x]==InQEx[x]):
                        matchedAr.append(int(numb))
                    x+=1
            except Exception as e:
                print(str(e))

        y=Counter(matchedAr)
        Xaxis=[]
        Yaxis=[]
        for key,value in y.items():
            Xaxis.append(key)
            Yaxis.append(value)
    fig = plt.figure()
    ax1 = plt.subplot2grid((4,4),(0,0), rowspan=1, colspan=4)
    ax2 = plt.subplot2grid((4,4),(2,0), rowspan=3,colspan=4)

    ax1.imshow(iar)
    ax2.bar(Xaxis,Yaxis)
    plt.ylim(400)
    xloc = plt.MaxNLocator(12)
    ax2.xaxis.set_major_locator(xloc)
    plt.show()

#

print(matchExample("images/test.png"))


import os
import sys
from .math.fibonacci import Fibonacci

def find_all():
    print()

def check_all():
    print()

class Abc:
    prop: str

my_list = [
    1, 2, 3,
    4, 5, 6,
]

result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)

# Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest.
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

spam(ham[1], {eggs: 2})


from random import choice, sample
from datetime import timedelta, date
cooking = []
washing = []

print("#+title: Rota")
print("#+options:  h:2 num:nil toc:t")
print("\n")
def create_rota(d):
    for i in range(0, 7):
        avail_cook = ["Noam", "Laura", "Louis", "David", "Nat", "Störm"]

        if(i==0):
            cook_day=sample(avail_cook, 2)
        # no cooks two days in a row
        if(i>0):
            # remove already cooking
            for c in cooking[i-1]:
                if c in avail_cook:
                    avail_cook.remove(c)
            cook_day=sample(avail_cook, 2)
        # store cooks for the day
        cooking.append(cook_day)

    for i in range(0, 7):

        avail_wash = ["Noam", "Laura", "Louis", "David", "Nat", "Soko", "Sonny", "Störm"]
        cook_day=cooking[i]
        # no washers who are cooking
        for c in cook_day:
            if c in avail_wash:
                avail_wash.remove(c)
        print("* ", d.strftime("%d %b %Y %A"))
        print("- Cooking: ", cook_day[0], "and ", cook_day[1])
        cooking.append(cook_day)

        wash_day = sample(avail_wash, 3)

        print("- Washing: ", wash_day[0], ", ", wash_day[1]," and ", wash_day[2])
        washing.append(wash_day)
        d+=timedelta(days=1)

d1 = date.today()
for i in range (0, 100):
#     print("Week ", i, ". Starting on ", d1.strftime("%a %d %b %Y"))
#     print("----------\n")
    create_rota(d1)
    d1+=timedelta(days=7)
#     print("\n")


from pathlib import Path
import pandas as pd
import numpy as np

ROOT_DIRECTORY = Path("/code_execution")
DATA_DIRECTORY = Path("/data")
QRY_VIDEOS_DIRECTORY = DATA_DIRECTORY / "query"
OUTPUT_FILE = ROOT_DIRECTORY / "subset_query_descriptors.npz"
QUERY_SUBSET_FILE = DATA_DIRECTORY / "query_subset.csv"

def generate_query_descriptors(query_video_ids) -> np.ndarray:
    raise NotImplementedError(
        "This script is just a template. You should adapt it with your own code."
    )
    video_ids = ...
    descriptors = ...
    timestamp_intervals = ...
    return video_ids, descriptors, timestamp_intervals

def main():
    # Loading subset of query images
    query_subset = pd.read_csv(QUERY_SUBSET_FILE)
    query_subset_video_ids = query_subset.video_id.values.astype("U")

    # Generation of query descriptors happens here
    query_video_ids, query_descriptors, query_timestamps = generate_query_descriptors(
        query_subset_video_ids
    )

    np.savez(
        OUTPUT_FILE,
        video_ids=query_video_ids,
        features=query_descriptors,
        timestamps=query_timestamps,
    )

if __name__ == "__main__":
    main()


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

__version__ = "0.5.4"
__author__ = "Abien Fred Agarap"

from dataset.normalize_data import list_files
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import confusion_matrix
import tensorflow as tf

def load_data(dataset):
    """Returns a tuple containing the features and labels
    in a dataset.

    Parameter
    ---------
    dataset : numpy.ndarray
      A NumPy array file containing the dataset to be loaded.

    Returns
    -------
    features : ndarray
        A numpy.ndarray with the features in the dataset as its elements.
    labels : ndarray
        A numpy.ndarray with the labels in the dataset as its elements.

    Examples
    --------
    >>> dataset = 'train_data.npy'
    >>> features, labels = data.load_data(dataset=dataset)
    >>> features
    array([[ 6.,  0.,  2., ...,  6.,  1.,  1.],
           [ 6.,  0.,  2., ...,  6.,  1.,  1.],
           [ 9.,  0.,  3., ...,  9.,  1.,  2.],
           ...,
           [ 7.,  3.,  7., ...,  1.,  1.,  1.],
           [ 6.,  0.,  2., ...,  6.,  1.,  1.],
           [ 8.,  0.,  2., ...,  2.,  1.,  1.]], dtype=float32)
    >>> labels
    array([ 1.,  1.,  1., ...,  0.,  1.,  1.], dtype=float32)

    """

    # load the data into memory
    data = np.load(dataset)

    # get the labels from the dataset
    labels = data[:, 17]
    labels = labels.astype(np.float32)

    # get the features from the dataset
    data = np.delete(arr=data, obj=[17], axis=1)
    data = data.astype(np.float32)

    return data, labels

def plot_confusion_matrix(phase, path, class_names):
    """Plots the confusion matrix using matplotlib.

    Parameter
    ---------
    phase : str
      String value indicating for what phase is the confusion matrix, i.e. training/validation/testing
    path : str
      Directory where the predicted and actual label NPY files reside
    class_names : str
      List consisting of the class names for the labels

    Returns
    -------
    conf : array, shape = [num_classes, num_classes]
      Confusion matrix
    accuracy : float
      Predictive accuracy
    """

    # list all the results files
    files = list_files(path=path)

    labels = np.array([])

    for file in files:
        labels_batch = np.load(file)
        labels = np.append(labels, labels_batch)

        if (files.index(file) / files.__len__()) % 0.2 == 0:
            print(
                "Done appending {}% of {}".format(
                    (files.index(file) / files.__len__()) * 100, files.__len__()
                )
            )

    labels = np.reshape(labels, newshape=(labels.shape[0] // 4, 4))

    print("Done appending NPY files.")

    # get the predicted labels
    predictions = labels[:, :2]

    # get the actual labels
    actual = labels[:, 2:]

    # create a TensorFlow session
    with tf.Session() as sess:

        # decode the one-hot encoded labels to single integer
        predictions = sess.run(tf.argmax(predictions, 1))
        actual = sess.run(tf.argmax(actual, 1))

    # get the confusion matrix based on the actual and predicted labels
    conf = confusion_matrix(y_true=actual, y_pred=predictions)

    # create a confusion matrix plot
    plt.imshow(conf, cmap=plt.cm.Purples, interpolation="nearest")

    # set the plot title
    plt.title("Confusion Matrix for {} Phase".format(phase))

    # legend of intensity for the plot
    plt.colorbar()

    tick_marks = np.arange(len(class_names))
    plt.xticks(tick_marks, class_names, rotation=45)
    plt.yticks(tick_marks, class_names)

    plt.tight_layout()
    plt.ylabel("Actual label")
    plt.xlabel("Predicted label")

    # show the plot
    plt.show()

    # get the accuracy of the phase
    accuracy = (conf[0][0] + conf[1][1]) / labels.shape[0]

    # return the confusion matrix and the accuracy
    return conf, accuracy


from typing import List

class Solution:
    def trap(self, height: List[int]) -> int:
        if len(height) <= 2:
            return 0

        result = 0

        left_max = height[0]
        right_max = height[-1]

        left = 1
        right = len(height) - 1

        while left <= right:
            if height[left] > left_max:
                left_max = height[left]

            if height[right] > right_max:
                right_max = height[right]

            if left_max <= right_max:
                result += left_max - height[left]
                left += 1
            else:
                result += right_max - height[right]
                right -= 1
        return result


import time

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.common.exceptions import NoSuchElementException

from utils.scrolling import infinite_scroll
from utils.placeClass import Place

place = Place()

place.link = "https://www.google.com/maps/place/Masged+and+Madraset+Soltan+Hassn/@30.0328679,31.2562843,17z/data=!3m1!4b1!4m6!3m5!1s0x145840ac1c97a4f7:0x8412ca0f201c9352!8m2!3d30.0328679!4d31.2562843!16s%2Fg%2F12hm9lhq7?authuser=0&hl=en"

# path =  r'./utils/chromedriver.exe'

# Automatically install and use the latest Chrome driver
path = ChromeDriverManager().install()

def fill_place_details(place,driver_path=path):
    """
    modifies the place object which is the parameter to add description, type, image, open close times to it.

    :param place: The place object which will be modified.
    :type place: object
    :param driver_path: The path of the chrome driver.
    :type driver_path: String

    """
    # creating the driver
    options = webdriver.ChromeOptions()
    options.add_experimental_option('excludeSwitches', ['enable-logging'])
    options.add_argument("--headless")
    driver = webdriver.Chrome(executable_path=driver_path, options=options)

    try:
        # fetch the link
        driver.get(place.link)
        # find an element to make sure that the page has loaded before scrolling
        descriptionDiv = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "PYvSYb")))
    except TimeoutException:
        descriptionDiv = False
    except Exception as e:
        descriptionDiv = False

    # scrolls the page
    # infinite_scroll(driver,'ipilje')

    if descriptionDiv:
        try:
            # find the span that contains description inside the description div
            # descriptionSpan = descriptionDiv.find_element(By.CSS_SELECTOR,'span')
            # put the description inside description field
            place.description = descriptionDiv.text
        except NoSuchElementException:
            place.description = ""

    try:
        # find the button containing the type
        typeBtn = driver.find_element(By.CLASS_NAME,'DkEaL')
        # set the type field to be the text inside the btn
        place.type = typeBtn.text
    except:
        place.type = ""

    try:
        # find the btn containing the img
        imgBtn = driver.find_element(By.CSS_SELECTOR,'.aoRNLd.kn2E5e.NMjTrf.lvtCsd')
    except:
        imgBtn = False

    if imgBtn:
        # find the img inside the image btn
        image = imgBtn.find_element(By.TAG_NAME,'img')
        # set the image field to be the img link inside the img
        place.image = image.get_attribute('src')

    # find the open close times
    try:

        try:
            # find the div that contains the code which shows the table
            showTableDiv = WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.  CLASS_NAME, "OqCZI")))
        except:
            showTableDiv = WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.  CLASS_NAME, "OyjIsf")))

        # will move the mouse cursor to the element and then perform a click on the element It  can be useful when you want to simulate more complex user interactions on the page
        ActionChains(driver).move_to_element(showTableDiv).click(showTableDiv).perform()

        # find open close times table
        open_close_table = driver.find_element(By.CSS_SELECTOR,'.eK4R0e.fontBodyMedium')

        # find all rows in the table
        open_close_table_rows = open_close_table.find_elements(By.CLASS_NAME,'y0skZc')
        # loop over the table rows
        for row in open_close_table_rows:
             # find the table data contains day inside the row
             day_table_data = WebDriverWait(row, 10).until(EC.presence_of_element_located ((By.     CLASS_NAME, 'ylH6lf')))
             # find all the div elemnts inside this td
             day_table_data_divs = day_table_data.find_elements(By.CSS_SELECTOR,'div')
             # get the text of the first to be the day
             day = day_table_data_divs[0].text
             # define an array to store the times in it
             times = []
             # find the open close times table data
             open_close_table_data = row.find_element(By.CLASS_NAME,'mxowUb')
             # find all the ordered lists inside this list
             open_close_ordered_lists = open_close_table_data.find_elements(By.CLASS_NAME, 'G8aQO')
             # loop over the ordered list to find open close times
             for open_close_time in open_close_ordered_lists:
               # find the time
               open_close = open_close_time.text.replace('\u202f',' ').split('?')
               open_close_text = open_close[0]

               if open_close_text != "Closed":
                 time = open_close_text.split('–')
               else:
                time = "Closed"

               # add this list to times list
               times.append(time)
               place.open_close_times[day] = times
    except:
      place.open_close_times = {}

# fill_place_details(place,path)

# print(place.description)
# print(place.type)
# print(place.image)
# print(place.open_close_times)


from typing import Tuple

import gym
from imitation.rewards.reward_nets import RewardNet
import numpy as np
import torch

from reward_preprocessing.env import maze, mountain_car  # noqa: F401

class MazeRewardNet(RewardNet):
    def __init__(self, size: int, maze_name: str = "EmptyMaze", **kwargs):
        env = gym.make(f"reward_preprocessing/{maze_name}{size}-v0", **kwargs)
        self.rewards = env.rewards
        super().__init__(
            observation_space=env.observation_space, action_space=env.action_space
        )

    def forward(
        self,
        state: torch.Tensor,
        action: torch.Tensor,
        next_state: torch.Tensor,
        done: torch.Tensor,
    ):
        np_state = state.detach().cpu().numpy()
        np_next_state = next_state.detach().cpu().numpy()
        rewards = self.rewards[np_state, np_next_state]
        return torch.as_tensor(rewards, device=state.device)

    def preprocess(
        self,
        state: np.ndarray,
        action: np.ndarray,
        next_state: np.ndarray,
        done: np.ndarray,
    ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
        """Preprocess a batch of input transitions and convert it to PyTorch tensors.

        The output of this function is suitable for its forward pass,
        so a typical usage would be ``model(*model.preprocess(transitions))``.
        """
        state_th = torch.as_tensor(state, device=self.device, dtype=torch.long)
        action_th = torch.as_tensor(action, device=self.device)
        next_state_th = torch.as_tensor(
            next_state, device=self.device, dtype=torch.long
        )
        done_th = torch.as_tensor(done, device=self.device)

        assert state_th.shape == next_state_th.shape
        return state_th, action_th, next_state_th, done_th

class MountainCarRewardNet(RewardNet):
    def __init__(self, **kwargs):
        self.env = gym.make("imitation/MountainCar-v0", **kwargs).unwrapped
        super().__init__(self.env.observation_space, self.env.action_space)

    def forward(
        self,
        state: torch.Tensor,
        action: torch.Tensor,
        next_state: torch.Tensor,
        done: torch.Tensor,
    ) -> torch.Tensor:
        reward = (state[:, 0] > 0.5).float() - 1.0
        shaping = torch.tensor(
            [self.env._shaping(x, y) for x, y in zip(state, next_state)]
        )
        return reward + shaping


from __future__ import print_function

import copy
import warnings

import graphviz
import matplotlib.pyplot as plt
import numpy as np
from graph import feed_forward_layers, DrawNN

def plot_time(begin, end, filename, generation_time):
    """ Plots the population's average and best fitness. """
    if plt is None:
        warnings.warn(
            "This display is not available due to a missing optional dependency (matplotlib)")
        return
    generation = range(begin, end)
    plt.plot(generation, generation_time, 'b-', label="seconds")
    plt.title("Population's average and best fitness")
    plt.xlabel("Generations")
    plt.ylabel("Generation time")
    plt.grid()
    plt.legend(loc="best")
    plt.savefig(filename)

    plt.close()
def plot_large_stats(statistics, ylog=False, view=False, filename='avg_fitness.svg', generations=1, begin=0, end=4):
    """ Plots the population's average and best fitness. """
    if plt is None:
        warnings.warn(
            "This display is not available due to a missing optional dependency (matplotlib)")
        return

    generation = range(begin, end)
    best_fitness = [c.fitness for c in statistics.most_fit_genomes][begin:end]
    avg_fitness = np.array(statistics.get_fitness_mean())[begin:end]
    stdev_fitness = np.array(statistics.get_fitness_stdev())[begin:end]

    plt.figure(figsize=(end-begin, 10))
    plt.plot(generation, avg_fitness, 'b-', label="average")
    plt.plot(generation, avg_fitness - stdev_fitness, 'g-.', label="-1 sd")
    plt.plot(generation, avg_fitness + stdev_fitness, 'g-.', label="+1 sd")
    plt.plot(generation, best_fitness, 'r-', label="best")

    plt.title("Population's average and best fitness")
    plt.xlabel("Generations")
    plt.ylabel("Fitness")
    plt.xticks(np.arange(begin, end))
    plt.grid()
    plt.legend(loc="best")
    if ylog:
        plt.gca().set_yscale('symlog')

    plt.savefig(filename)
    if view:
        plt.show()

    plt.close()

def plot_stats(statistics, ylog=False, view=False, filename='avg_fitness.svg', generations=1, begin=0, end=4):
    """ Plots the population's average and best fitness. """
    if plt is None:
        warnings.warn(
            "This display is not available due to a missing optional dependency (matplotlib)")
        return

    generation = range(begin, end)
    best_fitness = [c.fitness for c in statistics.most_fit_genomes][begin:end]
    avg_fitness = np.array(statistics.get_fitness_mean())[begin:end]
    stdev_fitness = np.array(statistics.get_fitness_stdev())[begin:end]

    plt.plot(generation, avg_fitness, 'b-', label="average")
    plt.plot(generation, avg_fitness - stdev_fitness, 'g-.', label="-1 sd")
    plt.plot(generation, avg_fitness + stdev_fitness, 'g-.', label="+1 sd")
    plt.plot(generation, best_fitness, 'r-', label="best")

    plt.title("Population's average and best fitness")
    plt.xlabel("Generations")
    plt.ylabel("Fitness")
    plt.grid()
    plt.legend(loc="best")
    if ylog:
        plt.gca().set_yscale('symlog')

    plt.savefig(filename)
    if view:
        plt.show()

    plt.close()

def plot_spikes(spikes, view=False, filename=None, title=None):
    """ Plots the trains for a single spiking neuron. """
    t_values = [t for t, I, v, u, f in spikes]
    v_values = [v for t, I, v, u, f in spikes]
    u_values = [u for t, I, v, u, f in spikes]
    I_values = [I for t, I, v, u, f in spikes]
    f_values = [f for t, I, v, u, f in spikes]

    fig = plt.figure()
    plt.subplot(4, 1, 1)
    plt.ylabel("Potential (mv)")
    plt.xlabel("Time (in ms)")
    plt.grid()
    plt.plot(t_values, v_values, "g-")

    if title is None:
        plt.title("Izhikevich's spiking neuron model")
    else:
        plt.title("Izhikevich's spiking neuron model ({0!s})".format(title))

    plt.subplot(4, 1, 2)
    plt.ylabel("Fired")
    plt.xlabel("Time (in ms)")
    plt.grid()
    plt.plot(t_values, f_values, "r-")

    plt.subplot(4, 1, 3)
    plt.ylabel("Recovery (u)")
    plt.xlabel("Time (in ms)")
    plt.grid()
    plt.plot(t_values, u_values, "r-")

    plt.subplot(4, 1, 4)
    plt.ylabel("Current (I)")
    plt.xlabel("Time (in ms)")
    plt.grid()
    plt.plot(t_values, I_values, "r-o")

    if filename is not None:
        plt.savefig(filename)

    if view:
        plt.show()
        plt.close()
        fig = None

    return fig

def plot_species(statistics, view=False, filename='speciation.svg'):
    """ Visualizes speciation throughout evolution. """
    if plt is None:
        warnings.warn(
            "This display is not available due to a missing optional dependency (matplotlib)")
        return

    species_sizes = statistics.get_species_sizes()
    num_generations = len(species_sizes)
    curves = np.array(species_sizes).T

    fig, ax = plt.subplots()
    ax.stackplot(range(num_generations), *curves)

    plt.title("Speciation")
    plt.ylabel("Size per Species")
    plt.xlabel("Generations")
    plt.savefig(filename)

    if view:
        plt.show()

    plt.close()

def draw_net2(config, genome, view=False, filename=None, node_names=None, show_disabled=True, prune_unused=False,
              node_colors=None, fmt='svg'):
    layers = feed_forward_layers(inputs=config.genome_config.input_keys, outputs=config.genome_config.output_keys, connections=[
                                 i.key for i in genome.connections.values()])
    neurons_per_layer = [len(layer) for layer in layers]
    neurons_per_layer.insert(0, len(config.genome_config.input_keys))
    neurons_per_layer.append(len(config.genome_config.output_keys))
    nn = DrawNN(neurons_per_layer, filename + "topology.png")
    layers = [list(l) for l in layers]
    layers.insert(0, config.genome_config.input_keys)
    layers.append(config.genome_config.output_keys)
    print(layers)
    nn.draw(layers, genome)

def draw_net(config, genome, view=False, filename=None, node_names=None, show_disabled=True, prune_unused=False,
             node_colors=None, fmt='svg'):
    """ Receives a genome and draws a neural network with arbitrary topology. """
    # Attributes for network nodes.
    if graphviz is None:
        warnings.warn(
            "This display is not available due to a missing optional dependency (graphviz)")
        return

    if node_names is None:
        node_names = {}

    assert type(node_names) is dict

    if node_colors is None:
        node_colors = {}

    assert type(node_colors) is dict

    node_attrs = {
        'shape': 'circle',
        'fontsize': '9',
        'height': '0.2',
        'width': '0.2'}

    dot = graphviz.Digraph(format=fmt, node_attr=node_attrs)

    inputs = set()
    for k in config.genome_config.input_keys:
        inputs.add(k)
        name = node_names.get(k, str(k))
        input_attrs = {'style': 'filled',
                       'shape': 'box'}
        input_attrs['fillcolor'] = node_colors.get(k, 'lightgray')
        dot.node(name, _attributes=input_attrs)

    outputs = set()
    for k in config.genome_config.output_keys:
        outputs.add(k)
        name = node_names.get(k, str(k))
        node_attrs = {'style': 'filled'}
        node_attrs['fillcolor'] = node_colors.get(k, 'lightblue')

        dot.node(name, _attributes=node_attrs)

    if prune_unused:
        connections = set()
        for cg in genome.connections.values():
            if cg.enabled or show_disabled:
                connections.add((cg.in_node_id, cg.out_node_id))

        used_nodes = copy.copy(outputs)
        pending = copy.copy(outputs)
        while pending:
            new_pending = set()
            for a, b in connections:
                if b in pending and a not in used_nodes:
                    new_pending.add(a)
                    used_nodes.add(a)
            pending = new_pending
    else:
        used_nodes = set(genome.nodes.keys())

    for n in used_nodes:
        if n in inputs or n in outputs:
            continue

        attrs = {'style': 'filled',
                 'fillcolor': node_colors.get(n, 'white')}
        dot.node(str(n), _attributes=attrs)

    for cg in genome.connections.values():
        if cg.enabled or show_disabled:
            # if cg.input not in used_nodes or cg.output not in used_nodes:
            #    continue
            input, output = cg.key
            a = node_names.get(input, str(input))
            b = node_names.get(output, str(output))
            style = 'solid' if cg.enabled else 'dotted'
            color = 'green' if cg.weight > 0 else 'red'
            width = str(0.1 + abs(cg.weight / 5.0))
            dot.edge(a, b, _attributes={
                     'style': style, 'color': color, 'penwidth': width})

    dot.render(filename + "digraph", view=view)
    draw_net2(config, genome, False, node_names=node_names, filename=filename)
    return dot

def graph_per_stage(config, map_number, genome, stats_reporter, generations, total_maps, generation_time):
    node_names = {
        0: 'direccion',
        1: 'velocidad',
        -1: 'Sensor Proximidad frontal',
        -2: 'Sensor Proximidad frontal derecho',
        -3: 'Sensor Proximidad frontal izquierdo',
        -4: 'Sensor Proximidad derecho',
        -5: 'Sensor Proximidad izquierdo',
        -6: 'Sensor Proximidad trasero',
        -7: 'Sensor Proximidad trasero derecho',
        -8: 'Sensor Proximidad trasero izquierdo',
    }
    draw_net(config, genome, False, node_names=node_names,
             filename=f'./graficos/{map_number}/')

    begin = int((map_number - 1) * (generations / total_maps))
    end = int((map_number) * (generations / total_maps))

    plot_stats(stats_reporter, ylog=False, view=True,
               filename=f'./graficos/{map_number}/avg_fitness.svg', begin=begin, end=end)
    plot_large_stats(stats_reporter, ylog=False, view=True,
                     filename=f'./graficos/{map_number}/large_avg_fitness.svg', begin=begin, end=end)
    plot_time(begin, end, filename=f'./graficos/{map_number}/time.svg', generation_time=generation_time)


#!/usr/bin/python3
def uppercase(str):
    """
    a function that prints a string in uppercase followed by a new line
    """
    out_str = ""
    for s in str:
        if ord(s) >= 97 and ord(s) < 123:
            out_str += chr(ord(s) - 32)
        else:
            out_str += s
    print(out_str.format())