#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys

#sys.path.append("../../../Asset Wealth")

import os
import functools
import time
from csv import DictReader
import json
import multiprocessing as mp
import pandas as pd
import numpy as np

import ee

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from pydrive.files import ApiRequestError

# from data_utils import truncate

# from config import csv_path
# from config import gdrive_dir_s2
# from config import download_path_s2
# from config import country_code_map

###Quick Guide
#Initialize Drive to download files
#https://pythonhosted.org/PyDrive/quickstart.html
#start script on remote machine
#label csv at least needs: 'TIF_name' (the name of the file, otherwise generate a name), 'LATNUM', 'LONGNUM',
#'URBAN_RURA'
#apply_async may start thousands of tasks - that's why it's programmed to wait after 'parallel_dls' for the last download
#to end and for 60 mins after the last download has ended, because earlier downloads may take longer!
#Also, when using this apply_async you may create thousands of tasks for the google earth engine which are still running
#after the program terminated. (Not sure why pool.join does not wait for all workers to finish...).
#you may want to manually delete all tasks on the remote machine with 'earthengine task cancel all'
#downloaded!

###Options###
##Paths
# label_csv = '/mnt/datadisk/data/Projects/water/inputs/water_labels.csv'
label_csv = '/mnt/datadisk/data/Projects/water/inputs/Moz_Grid_Points_10km.csv'
img_p = '/mnt/datadisk/data/Sentinel2/moz_grid/'
# img_p = '/mnt/datadisk/data/Sentinel2/moz_grid/'
#used to debug locally: set to False for actual DL
testing = False
##Parameter
#these should be identical and probably 5010 (yields 10x10km tiles)
#note: these should be a little bit bigger than the radius you actually want since GEE sometimes cuts it a few pixels
#early
urban_radius = 5010  # meter
rural_radius = 5010  # meter
#20 is suggested
MAX_CLOUD_PROBABILITY = 20  # %
#the minimum year of the questionnaire to download files
min_year = 2012
#Google stuff
gdrive_dir_s2 = '1P4FpvICI0S9vRs8mNvHxzqooK7zPGGnP'
#make sure that you have enough space on disk (parallel-dls*img_size)
parallel_dls = 150
#wait for 6 hours to complete all tasks and download them
final_waiting_time = 6
###Special Settings
##Downloads S2 images for specified country and year at places where there have been surveys
#use country name or False
download_country = 'Mozambique'
#specify year (only active if download country is given)
download_year = 2018
# Paths
# Path to Label Data
# csv_dir = csv_path
# Directory where the sentinel images are stored
# Path to txt files which contains all surveys for which all images are already retrieved
# sentinel_done = base_p + "sentinel_done.txt"

def bounding_box(loc:ee.Geometry.Point, urban_rural:int, urban_radius:int, rural_radius:int):
    '''Function to get a square around point of interest.
    Rural : 10 km Radius
    Urban : 2 km Radius

    Args:
        loc(ee.Geometry.Point): Geolocation of cluster (from DHS survey)
        urban_rural(int):       Binary encoding for type of region: 0 = urban, 1 = rural
        urban_radius(int):      Radius around coordinates for Urban regions in meter
        rural_radius(int):      Radius around coordinates for Rural regions in meter
    Returns:
        intermediate_box (ee.Geometry):     bounding box around cluster coordinates
                                            with a size of 10x10km for rural/ 2x2km for Urban
    '''
    if urban_rural == 0 or urban_rural == '0':
        size = urban_radius
        ur = 'u'
    else:
        size = rural_radius
        ur = 'r'

    intermediate_buffer = loc.buffer(size)  # buffer radius, half your box width in m
    intermediate_box = intermediate_buffer.bounds()  # Draw a bounding box around the circle
    return (intermediate_box, ur)

#
def maskClouds(img:ee.Image, MAX_CLOUD_PROBABILITY:int):
    '''Masking of clouds.

    Args:
        img(ee.Image):              Sentinel-2 image retrieved from ee
        MAX_CLOUD_PROBABILITY(int): %

    Returns:
        ee.Image: CloudMasked GoogleEarthEngine image
    '''
    clouds = ee.Image(img.get('cloud_mask')).select('probability')
    isNotCloud = clouds.lt(MAX_CLOUD_PROBABILITY)
    return img.updateMask(isNotCloud)

def get_image(cluster:pd.Series, urban_radius:int, rural_radius:int, country_code:str, MAX_CLOUD_PROBABILITY:int, drive):
    '''Extract Information about cluster to get Sentinel-2 image for corresponding year and coordinates.

    Args:
        cluster(pd.Series):    Information about the Cluster (cluster number, coordinates, survey name, etc.)
        survey_name(str):           Name of the survey (COUNTRY_YEAR)
        urban_radius(int):          Radius around coordinates for Urban regions in meter
        rural_radius(int):          Radius around coordinates for Rural regions in meter
        country_code(str):          ISO code for survey country (COUNTRY)
        MAX_CLOUD_PROBABILITY(int): %

    Returns:
        Requests Image from Earth Engine. Files are named by the following pattern:
            Latitude_Longitude_begin-end_COUNTRY_r/u_sidelength
            coordinates: 4 Nachkommastellen
            date format: YYYYMMDD
            country: Official 3 letters acronym (ISO)
            Rural/Urban: u or r
            side length: Sidelength (size) of tile in km with one decimal place.
    '''
    # Get images collections
    s2Sr = ee.ImageCollection('COPERNICUS/S2')
    s2Clouds = ee.ImageCollection('COPERNICUS/S2_CLOUD_PROBABILITY')
    # Get time span
    year = int(float(cluster["DHSYEAR"]))
    if int(year) < 2016:
        START_DATE = ee.Date('2015-06-01')
        END_DATE = ee.Date('2016-07-01')
        # date_range = '20150601-20160701'
    else:
        START_DATE = ee.Date(str(int(year)) + '-01-01')
        END_DATE = ee.Date(str(int(year)) + '-12-31')
        # date_range = str(year) + '0101-' + str(year) + '1231'
    # Point of interest (longitude, latidude)
    lat_float = float(cluster["LATNUM"])
    lon_float = float(cluster["LONGNUM"])
    loc = ee.Geometry.Point([lon_float, lat_float])
    # Region of interest
    region, ur = bounding_box(loc, cluster['URBAN_RURA'], urban_radius, rural_radius)
    # cluster_no = int(round(float(cluster["DHSCLUST"]), 0))
    s2Sr = s2Sr.filterBounds(region).filterDate(START_DATE, END_DATE)
    s2Clouds = s2Clouds.filterBounds(region).filterDate(START_DATE, END_DATE)

    # Join S2 with cloud probability dataset to add cloud mask.
    s2SrWithCloudMask = ee.Join.saveFirst('cloud_mask').apply(
        primary=s2Sr,
        secondary=s2Clouds,
        condition=ee.Filter.equals(
            leftField='system:index', rightField='system:index')
    )

    maskCloudsWithProb = functools.partial(maskClouds, MAX_CLOUD_PROBABILITY=MAX_CLOUD_PROBABILITY)
    s2CloudMasked = ee.ImageCollection(s2SrWithCloudMask).map(maskCloudsWithProb).median()
    s2CloudMasked = s2CloudMasked.select(['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B8A', 'B9', 'B10' \
                                             , 'B11', 'B12']).clip(region)

    filename = cluster['TIF_name'][:-4]
    # if ur == 'u':
    #     filename = str(truncate(lat_float, 4)) + '_' + \
    #                str(truncate(lon_float, 4)) + '_' + \
    #                str(date_range) + '_' + \
    #                str(country_code) + '_' + \
    #                ur + '_' + \
    #                str(float(urban_radius / 1000))
    # else:
    #     filename = str(truncate(lat_float, 4)) + '_' + \
    #                str(truncate(lon_float, 4)) + '_' + \
    #                str(date_range) + '_' + \
    #                str(country_code) + '_' + \
    #                ur + '_' + \
    #                str(float(rural_radius / 1000))
    task = ee.batch.Export.image.toDrive(**{
        'image': s2CloudMasked,
        'description': filename,
        'folder': 'sentinel',
        'scale': 10})
    # print('Create', filename)
    t1 = time.time()
    task.start()
    while task.active():  # request status of task
        # print('Polling for task (id: {}).'.format(task.id))
        status = task.status()
        print(status['description'], status['state'], (time.time() - t1)/60, 'mins')
        time.sleep(60*5)  # set sleep timer for 5 sec if task is still active
    # print('created', filename, (time.time() - t1)/60)
    print('\n --------\ncreated', status['description'], status['id'], status['state'], (time.time() - t1)/60, 'mins')
    return loc

def download_local(survey_dir:str, drive):
    '''Download images from GoogleDrive folder.

    Args:
        survey_dir(str): Output directory for download
    '''
    # folder which want to download from Drive
    folder_id = gdrive_dir_s2

    if survey_dir[-1] != '/':
        survey_dir = survey_dir + '/'

    if not os.path.exists(survey_dir):
        os.mkdir(survey_dir)
    try:
        file_list = drive.ListFile({'q': "'{}' in parents and trashed=false".format(folder_id)}).GetList()
        for i, file1 in enumerate(sorted(file_list, key=lambda x: x['title']), start=1):
            print('     Downloading {} from GDrive ({}/{})'.format(file1['title'], i, len(file_list)))
            title = file1['title']
            print('     dl', survey_dir + title)
            if not os.path.exists(survey_dir + title):
                file1.GetContentFile(survey_dir + title)
                file1.Delete()
            else:
                print('     This should not happen!')
                count = 1
                title2 = title
                while os.path.exists(survey_dir + title2):
                    title2 = title[:-4] + '_' + str(count) + '.tif'
                    count += 1
                print('     dl name', survey_dir + title2)
                file1.GetContentFile(survey_dir + title)
                file1.Delete()
    except ApiRequestError:
        print('file (probably) has already been downloaded!')
        pass

def main(drive):
    if not testing:
        download_local(img_p, drive)
    #list of available files
    for (dirrpath, dirrnames, filenames) in os.walk(img_p):
        print('available images', dirrpath, len(filenames))
        #only these folder are needed

    df = pd.read_csv(label_csv)
    print('DF in\n', df)
    print(df.columns)
    #if GRID.csv manipulate and save
    if not "country" in df.columns:
        df['country'] = download_country
        df['DHSYEAR'] = download_year
        df['TIF_name'] = download_country + '_GRID_' + str(download_year) + '_' + \
                         df['id'].astype(str).str.zfill(8) + '.tif'
        #this is a dummy for legacy - does not mean it is urban!!!
        df['URBAN_RURA'] = 0
        df.to_csv(label_csv[:-4] + '_GRID_DL.csv')
    #manipulating df to represent desired country to download specified year
    elif download_country:
        df = df[df['country'] == download_country]
        if download_year:
            df['DHSYEAR'] = download_year
            df['TIF_name'] = df['TIF_name'].str[:-4] + '_' + str(download_year) + '.tif'
    # setting min year
    elif min_year:
        print('Using minimal year of', min_year)
        df = df[df['DHSYEAR'] >= min_year]
    print('\nDF after manipulating\n', df)
    #make sure it didnt get downloaded yet
    df['TIF_name'] = df['TIF_name'].apply(lambda x: x if x not in filenames else np.NaN)
    df = df[df['TIF_name'].notna()]
    # print(df["DHSYEAR"])
    # y = df.iloc[0]["DHSYEAR"]
    # print(y, type(y), int(float(y)))
    # input()
    pool = mp.Pool()
    len_clusters = len(df)
    t1 = time.time()
    t2 = time.time()
    print('\nDownloading', len_clusters, 'clusters')
    print('\nFinal DF \n', df)
    print('\nFile names and years\n', df[["TIF_name", "DHSYEAR"]])
    if len_clusters > 0:
        for i, (ind, cluster) in enumerate(df.iterrows()):
            # print(i, cluster, type(cluster))
            # print('\n')
            #debugging!
            # get_image(cluster, urban_radius, rural_radius, False, MAX_CLOUD_PROBABILITY,
            #                                         drive)
            #does not return error messages... Be careful!
            res = pool.apply_async(get_image, args=(cluster, urban_radius, rural_radius, False, MAX_CLOUD_PROBABILITY,
                                                    drive))
            if i != 0 and not i % parallel_dls or not (i + 1) % len_clusters:
                print(f'\rStarting {i+1} / {len_clusters}')
                #wait for one process to finish (it is random which gets started first!)
                #so not all downloads are started simultaneously (won't work!)
                #since it's random, there may be lots of processes still running, while new ones are started
                #you cannot see the old processes anymore, so it might take a long time until any of the new processes gets
                #actually started on gee (depends on parallel_dls)
                res.wait()
                # loc = res.get()
                # print('asd', loc)
                download_local(img_p, drive)
                rt30 = (time.time() - t2) / 3600
                t2 = time.time()
                rt = (t2 - t1)/3600
                try:
                    eta = rt/i * (len_clusters - i)# + 1
                except ZeroDivisionError:
                    eta = 'NaN'
                print(f'\rRunning time: {rt}h, running time for these {parallel_dls} tiles: {rt30}h, ETA: {eta}h or {eta/24} days')

        #wait 60 mins to ensure everything is downloaded - there are for sure more elegant ways to do this
        print(f'\rRunning time: {rt}h, ETA: {final_waiting_time}h ensuring everything is downloaded')
        time.sleep(60*60*final_waiting_time)
        print('downloading a last time')
        download_local(img_p, drive)
        print('finished')
        pool.close()
    else:
        print('Nothing left to download')
    # pool.join()
    # loc = get_image(cluster, urban_radius, rural_radius, False, MAX_CLOUD_PROBABILITY)
    # download files to local machine
    # if float(cluster["DHSCLUST"]) % 2 == 0:
    # download_local(os.path.join(img_p, survey_name))

if __name__ == "__main__":
    ###Initialize everything
    # authenticate once on the (remote) machine you are working on!!!
    # ee.Authenticate()
    print(f'Downloading urban tiles with a diameter of {urban_radius*2}m')
    print(f'Downloading rural tiles with a diameter of {rural_radius*2}m')

    #https://developers.google.com/earth-engine/cloud/highvolume used in
    # https://gorelick.medium.com/fast-er-downloads-a2abd512aa26
    # ee.Initialize(
    #     credentials=credentials,
    #     project=project,
    #     opt_url='https://earthengine-highvolume.googleapis.com'
    # )
    if not testing:
        ee.Initialize(
            opt_url='https://earthengine-highvolume.googleapis.com')

        # ee.Initialize()
        print('initialized2')
        gauth = GoogleAuth()
        # only works on remote machine
        gauth.LocalWebserverAuth()
        drive = GoogleDrive(gauth)
    else:
        drive = False
    #old stuff
    # gauth.LoadCredentialsFile("mycreds.txt")
    # drive = GoogleDrive(gauth)
    # for remote usage (does not work?!)
    # gauth.CommandLineAuth()
    main(drive)


#!/usr/bin/env python

#
# The purpose of the script is to parse the DeepLearning.java file and emit
# code related to parameters.
#
# Currently pieces of R code get emitted and need to be pasted in manually to the R file.
#

import sys
import os
import shutil
import signal
import time
import random
import getpass
import re
import subprocess

class Blob:
    def __init__(self, n, help):
        self.n = n
        self.help = help

def read_deeplearning_file(deeplearning_file):
    """
    Read deep learning file and generate R parameter stub stuff.

    @param deeplearning_file: Java source code file
    @return: none
    """
    try:
        nlist = []
        in_api = False
        help = None

        f = open(deeplearning_file, "r")
        s = f.readline()
        lineno = 0
        while (len(s) != 0):
            lineno = lineno + 1
            stripped = s.strip()
            if (len(stripped) == 0):
                s = f.readline()
                continue
            if (stripped.startswith("@API")):
                # print("")
                if (in_api):
                    assert(False)
                in_api = True

                match_groups = re.search("help\s*=\s*\"([^\"]*)\"", stripped)
                if (match_groups == None):
                    print("Missing help")
                    sys.exit(1)
                help = match_groups.group(1)
                # print(help)
                s = f.readline()
                continue
            if (in_api):
                skip = False
                if "checkpoint" in stripped:
                    skip = True
                if "expert_mode" in stripped:
                    skip = True
                # if "activation" in stripped:
                #     skip = True
                # if "initial_weight_distribution" in stripped:
                #     skip = True
                # if "loss" in stripped:
                #     skip = True
                # if "score_validation_sampling" in stripped:
                #     skip = True

                if (skip):
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public boolean (\S+) = (\S+);", s)
                if (match_groups is not None):
                    t = "boolean"
                    n = match_groups.group(1)
                    v = match_groups.group(2)
                    print("  parms = .addBooleanParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n, v)
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public Activation (\S+) = (\S+);", s)
                if (match_groups is not None):
                    t = "string"
                    n = match_groups.group(1)
                    v = match_groups.group(2)
                    print("  parms = .addStringParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n, v)
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public int\[\] (\S+) = .*;", s)
                if (match_groups is not None):
                    t = "int array"
                    n = match_groups.group(1)
                    print("  parms = .addIntArrayParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n)
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public int (\S+) = .*;", s)
                if (match_groups is not None):
                    t = "int"
                    n = match_groups.group(1)
                    print("  parms = .addIntParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n)
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public double (\S+) = (\S+);", s)
                if (match_groups is not None):
                    t = "double"
                    n = match_groups.group(1)
                    v = match_groups.group(2)
                    print("  parms = .addDoubleParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n, v)
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public float (\S+) = (\S+);", s)
                if (match_groups is not None):
                    t = "float"
                    n = match_groups.group(1)
                    v = match_groups.group(2)
                    print("  parms = .addFloatParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n, v)
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public double\[\] (\S+);", s)
                if (match_groups is not None):
                    t = "double array"
                    n = match_groups.group(1)
                    print("  parms = .addDoubleArrayParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n)
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public long (\S+) = new Random.*;", s)
                if (match_groups is not None):
                    t = "long"
                    n = match_groups.group(1)
                    v = -1
                    print("  parms = .addLongParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n, v)
                    in_api = False
                    s = f.readline()
                    continue

                match_groups = re.search("public long (\S+) = (\S+);", s)
                if (match_groups is not None):
                    t = "long"
                    n = match_groups.group(1)
                    v = match_groups.group(2)
                    print("  parms = .addLongParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, n, v)
                    in_api = False
                    s = f.readline()
                    continue

                if (stripped == "public InitialWeightDistribution initial_weight_distribution = InitialWeightDistribution.UniformAdaptive;"):
                    t = "string"
                    n = "initial_weight_distribution"
                    print("  parms = .addStringParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, "initial_weight_distribution", "UniformAdaptive")
                    in_api = False
                    s = f.readline()
                    continue

                if (stripped == "public Loss loss = Loss.CrossEntropy;"):
                    t = "string"
                    n = "loss"
                    print("  parms = .addStringParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, "loss", "CrossEntropy")
                    in_api = False
                    s = f.readline()
                    continue

                if (stripped == "public ClassSamplingMethod score_validation_sampling = ClassSamplingMethod.Uniform;"):
                    t = "string"
                    n = "score_validation_sampling"
                    print("  parms = .addStringParm(parms, k=\"{}\", v={})".format(n,n))
                    nlist.append(Blob(n, help))
                    # print(t, "score_validation_sampling", "Uniform")
                    in_api = False
                    s = f.readline()
                    continue

                print("ERROR: No match group found on line ", lineno)
                sys.exit(1)

            s = f.readline()
        f.close()

        print("")
        print("")

        for blob in nlist:
            print("  {},".format(blob.n))

        print("")
        print("")

        for blob in nlist:
            print("        \item{\code{" + blob.n + "}: " + blob.help + "}")

    except IOError as e:
        print("")
        print("ERROR: Failure reading test list: " + deeplearning_file)
        print("       (errno {0}): {1}".format(e.errno, e.strerror))
        print("")
        sys.exit(1)

def main(argv):
    read_deeplearning_file("./src/main/java/hex/deeplearning/DeepLearning.java")

if __name__ == "__main__":
    main(sys.argv)


import random
import os

def func3(dna):
    f  = open('tune/travatar.ini','w')
    data = ['[tm_file]', 'travatar-model/model/rule-table.gz', '', '[lm_file]', 'lm/lm.blm', '', '[binarize]', 'right', '', '[weight_vals]', ]
    weight_name = ['lfreq', 'fgel','egfl','egfp','lm','p', 'w','fgep','parse','unk']

    for i in range(10):
        data.append(weight_name[i]+'='+str(float(dna[i])))

    for i in range(len(data)):
        f.write(data[i]+'\n')

    f.flush()
    f.close()

    os.system("./run-pseudogen.sh -f tune/travatar.ini<./dev.reducedtree 2>>hyp_dev.anno")
    os.system("./test-pseudogen.sh -r dev.entok -h hyp_dev.anno >result.txt")
    f = open('result.txt')
    score = f.readline()
    f.close()
    b = float(score.split('\t')[0].split('=')[1])
    r = float(score.split('\t')[1].split('=')[1])
    os.system("java -Xmx2G -jar tools/meteor-1.5/meteor-*.jar hyp_dev.anno dev.entok -norm -writeAlignments >result.txt")
    f = open('result.txt')
    score = f.readlines()
    #print(score[-1].split('            ')[1][:-1])
    f.close()
    m= float(score[-1].split('            ')[1][:-1])
    print(b,r,m)
    return b*0.5+r*0.3+m*0.2

def ensure_bounds(vec, bounds):

    vec_new = []

    for i in range(len(vec)):

        if vec[i] < bounds[i][0]:
            vec_new.append(bounds[i][0])

        if vec[i] > bounds[i][1]:
            vec_new.append(bounds[i][1])

        if bounds[i][0] <= vec[i] <= bounds[i][1]:
            vec_new.append(vec[i])

    return vec_new

def main(cost_func, bounds, popsize, mutate, recombination, maxiter):
    best_fl = open('best_bleu.txt','w')

    population = []
    for i in range(0,popsize):
        indv = []
        for j in range(len(bounds)):
            indv.append(random.uniform(bounds[j][0],bounds[j][1]))
        population.append(indv)
    print(population)

    for i in range(1,maxiter+1):
        print ('GENERATION:',i)

        gen_scores = [] # score keeping

        for j in range(0, popsize):

            canidates = list(range(0,popsize))
            canidates.remove(j)
            random_index = random.sample(canidates, 3)

            x_1 = population[random_index[0]]
            x_2 = population[random_index[1]]
            x_3 = population[random_index[2]]
            x_t = population[j]

            x_diff = [x_2_i - x_3_i for x_2_i, x_3_i in zip(x_2, x_3)]

            v_donor = [x_1_i + mutate * x_diff_i for x_1_i, x_diff_i in zip(x_1, x_diff)]
            v_donor = ensure_bounds(v_donor, bounds)

            v_trial = []
            for k in range(len(x_t)):
                crossover = random.random()
                if crossover <= recombination:
                    v_trial.append(v_donor[k])

                else:
                    v_trial.append(x_t[k])

            score_trial  = cost_func(v_trial)
            score_target = cost_func(x_t)

            if score_trial > score_target:
                population[j] = v_trial
                gen_scores.append(score_trial)
                print ('   >',score_trial, v_trial)

            else:
                print ('   >',score_target, x_t)
                gen_scores.append(score_target)

        gen_avg = sum(gen_scores) / popsize                         # current generation avg. fitness
        gen_best = max(gen_scores)                                  # fitness of best individual
        gen_sol = population[gen_scores.index(max(gen_scores))]     # solution of best individual
        best_fl.write(str(gen_best))
        best_fl.write('\n')
        print ('      > GENERATION AVERAGE:',gen_avg)
        print ('      > GENERATION BEST:',gen_best)
        print ('         > BEST SOLUTION:',gen_sol,'\n')
    best_fl.flush()
    best_fl.close()
    return gen_sol

cost_func = func3                  # Cost function
bounds = [(-0.01,0.01),(-0.01,0.01),(-0.01,0.01),(-0.01,0.01),(-0.01,0.01),(-0.01,0.01),(-0.01,0.01),(-0.01,0.01),(-0.01,0.01),(-0.01,0.01)]            # Bounds [(x1_min, x1_max), (x2_min, x2_max),...]
popsize = 20                       # Population size, must be >= 4
mutate = 0.5                        # Mutation factor [0,2]
recombination = 0.95                # Recombination rate [0,1]
maxiter = 30                        # Max number of generations (maxiter)

main(cost_func, bounds, popsize, mutate, recombination, maxiter)


import parse

FILENAME = "day19/sample.txt"
TEMPLATE = "Blueprint {index:d}: Each ore robot costs {ore_robot_ore_cost:d} ore. Each clay robot costs {clay_robot_ore_cost:d} ore. Each obsidian robot costs {obsidian_robot_ore_cost:d} ore and {obsidian_robot_clay_cost:d} clay. Each geode robot costs {geode_robot_ore_cost:d} ore and {geode_robot_obsidian_cost:d} obsidian."
MATERIALS = {"ore", "clay", "obsidian", "geode"}

MINUTES = 16

def load_costs(filename):
    with open(filename) as file:
        costs = [parse.parse(TEMPLATE, line.strip()) for line in file.readlines()]

    blueprints = []
    for cost in costs:
        blueprint = {"index": cost["index"]}
        for robot_material in MATERIALS:
            blueprint[robot_material] = {}
            for cost_material in MATERIALS:
                if f"{robot_material}_robot_{cost_material}_cost" in cost:
                    robot_cost = cost[f"{robot_material}_robot_{cost_material}_cost"]
                else:
                    robot_cost = 0

                blueprint[robot_material][cost_material] = robot_cost
        blueprints.append(blueprint)

    return blueprints

def get_move(robots, materials, blueprint, minutes_remaining=MINUTES, moves=None):
    if moves is None:
        moves = []

    branches = []

    for robot_material in MATERIALS:
        # We have one build action per turn, so we don't need any more than the max blueprint materials
        if robot_material != "geode":
            materials_needed = max(
                [blueprint[material][robot_material] for material in MATERIALS]
            )
            if robots[robot_material] >= materials_needed:
                continue

        can_build_robot = True
        material_times = {}
        for component_material in MATERIALS:
            if blueprint[robot_material][component_material] == 0:
                continue
            elif robots[component_material] == 0:
                can_build_robot = False
                break

            material_times[component_material] = (
                blueprint[robot_material][component_material]
                - materials[component_material]
            ) // robots[component_material]

        if can_build_robot:
            build_time = max(material_times.values()) + 1

            if build_time > minutes_remaining:
                can_build_robot = False
                break

            # Try to branch on building this
            branch_robots = robots.copy()
            branch_materials = materials.copy()
            branch_moves = moves.copy()

            branch_robots[robot_material] += 1
            branch_materials = {
                material: materials[material] + (robots[material] * build_time)
                for material in MATERIALS
            }
            branch_moves.append((robot_material, minutes_remaining))

            moves, score = get_move(
                branch_robots,
                branch_materials,
                blueprint,
                minutes_remaining - build_time,
                branch_moves,
            )
            branches.append((moves, score))

    if branches:
        return max(branches, key=lambda branch: branch[1])
    else:  # No more robots to build, so just collect materials
        return moves, materials["geode"] + (robots["geode"] * minutes_remaining)

def mine(blueprint):
    print(f"Evaluating blueprint {blueprint['index']}...")
    robots = {material: 1 if material == "ore" else 0 for material in MATERIALS}
    materials = {material: 0 for material in MATERIALS}

    moves, score = get_move(robots, materials, blueprint)
    print(f"Move sequence: {moves}")
    print(f"Best score: {score}")

    return score * blueprint["index"]

if __name__ == "__main__":
    blueprints = load_costs(FILENAME)
    best_scores = [mine(blueprint) for blueprint in blueprints]
    print(sum(best_scores))


numbers = [*map(int, open("input.txt").read().strip().split(','))]

history = {
    0: list()
}
for i, n in enumerate(numbers):
    history[n] = [i+1]
    # print(i+1, n)

last = n
turn = len(numbers)+1
while turn <= 2020:
    if last in history and len(history[last]) >= 2:
        # spoken twice or more
        h = history[last][-2:][::-1]
        last = h[0] - h[1]
        if last in history:
            history[last].append(turn)
        else:
            history[last] = [turn]
    else: # spoken once
        last = 0
        history[0].append(turn)
    # print(turn, last)
    turn += 1

print([k for k,v in history.items() if 2020 in v])


keep_going = 'y'
budgetValue = float (input('Enter the total you have budgeted.'))
while keep_going =='y':
    expence = float(input('Enter your expense: '))
    budgetValue = budgetValue - expence
    print('Your current balence is: ', '$', budgetValue)
    keep_going = input('Would you like to continue? Press y for yes')

print('Your final value is:', budgetValue)


# --------------------------------------------------
#                    Preamble
# --------------------------------------------------

print("Reading in Imports... \n")

import scipy.ndimage as ndimg
import numpy as np
import yaml
import io

# Read YAML file
with open("../config.yaml", 'r') as stream:
    config = yaml.safe_load(stream)

# --------------------------------------------------

density_file_dm = '/global/cscratch1/sd/james12/Illustris_TNG_Data/TNG_Density_Cubes/simple_density_cubes/density_cube_snap_099_full_1024_dm.npy'
density_file_all_species = "/global/cscratch1/sd/james12/Illustris_TNG_Data/TNG_Density_Cubes/simple_density_cubes/density_cube_snap_099_full_1024_all_species.npy"

save_dir = "/global/cscratch1/sd/james12/NEXUS_analysis/quartiles/"

# --------------------------------------------------

def calc_structure_bools(density_file, type_flag):

    """
    Function that takes in a density cube file and
    returns 4 boolean filters, one for each quartile.

    Returns:
        q1_bool: (ndarray, dtype=bool) for voids
        q2_bool: (ndarray, dtype=bool) for walls
        q3_bool: (ndarray, dtype=bool) for filaments
        q4_bool: (ndarray, dtype=bool) for nodes
    """

    # total_volume = config["xmax"] ** 3
    # volume_per_cell = total_volume / (config["nx"]**3)

    print("Loading in Density File... \n")

    density_cube = np.load(density_file)
    smoothed_density = ndimg.gaussian_filter(density_cube, sigma=1)
    # mass_cube = density_cube * volume_per_cell
    # smoothed_mass = ndimg.gaussian_filter(mass_cube, sigma=0.5)

    print("Computing Mass Quartiles... \n")

    q1, q2, q3 = np.quantile(smoothed_density, [0.77, 0.95, 0.998]) #voids, walls, filaments, nodes

    print("Creating Boolean Filters... \n")

    structure_class = np.zeros(shape=smoothed_density.shape)
    structure_class[np.where (smoothed_density<q1)] = 0
    structure_class[np.where ((smoothed_density<q2) & (smoothed_density>q1))] = 1
    structure_class[np.where ((smoothed_density<q3) & (smoothed_density>q2))] = 2
    structure_class[np.where (smoothed_density>q3)] = 3

    q1_bool = structure_class == 0
    q2_bool = structure_class == 1
    q3_bool = structure_class == 2
    q4_bool = structure_class == 3

    print("Saving Boolean Filters... \n")

    if type_flag == "dm":
        np.save(save_dir + "snap_099_full_1024_dm_q1_bool_voids.npy", q1_bool)
        np.save(save_dir + "snap_099_full_1024_dm_q2_bool_walls.npy", q2_bool)
        np.save(save_dir + "snap_099_full_1024_dm_q3_bool_filaments.npy", q3_bool)
        np.save(save_dir + "snap_099_full_1024_dm_q4_bool_nodes.npy", q4_bool)

    elif type_flag == "all":
        # np.save(save_dir + "snap_099_full_1024_all_species_q1_bool_nodes.npy", q1_bool)
        # np.save(save_dir + "snap_099_full_1024_all_species_q2_bool_voids.npy", q2_bool)
        # np.save(save_dir + "snap_099_full_1024_all_species_q3_bool_walls.npy", q3_bool)
        # np.save(save_dir + "snap_099_full_1024_all_species_q4_bool_filaments.npy", q4_bool)
        print('skip')

if __name__ == "__main__":
    calc_structure_bools(density_file_dm, "dm")
    # calc_structure_bools(density_file_all_species, "all")


from tkinter import *
import json
from tkinter.ttk import *
import tkinter.filedialog as filedialog
import pathlib
import sys, inspect
from os import walk, mkdir
from os import path as osPath
from src.properties import renderProperties
from src.protocols import close
from src.codeGenerator import GenerateCode
from src.menuHandler import *
from src.keyBindings import *

class program(Tk):
    def __init__(self,*args, **kwargs):
        Tk.__init__(self, *args, **kwargs)
        import tkinter.ttk
        iOut = inspect.getmembers(sys.modules[tkinter.ttk.__name__])
        self.widgets = [e for e in iOut if inspect.isclass(e[1])]
        self.tkFile = ""
        self.geometry("500x500")
        self.tabParent = Notebook(self)
        self.fileFrame = Frame(self)
        self.fileFrame.pack(side=LEFT, anchor=NE)
        self.tabParent.pack(side=LEFT, fill=BOTH, expand=1)
        self.tabs = {}
        self.fileDict = {}
        self.cacheDict = {}
        self.tabEntities = {}
        self.tabEntities['canvas'] = {}
        self.tabEntities['canvas']['entities'] = {}
        self.widgetContainer = Frame(self)
        self.widgetContainer.pack(side=RIGHT)
        self.widgetParent = Frame(self.widgetContainer)
        self.widgetParent.pack(side=TOP)
        self.propertiesParent = Frame(self.widgetContainer)
        self.propertiesParent.pack(side=BOTTOM)
        self.renderDirectoryFiles()
        self.canvasEntities = list()
        self.menu = Menu(self)
        self.bind()
        createMenu(self, self.menu)
        close(self, self._quit)
    def _quit(self):
        try:
            with open(self.dirPath + '/tk_project/.cache/components.json', 'w') as f:

                json.dump(self.cacheDict, f)
                f.close()
        except:
            try:
                with open(self.dirPath + '/.cache/components.json') as f:
                    json.dump(self.cacheDict, f)
                    f.close()
            except:
                self.quit()
                return
        GenerateCode(self.cacheDict)
        self.quit()
    def renderDirectoryFiles(self, dirPath=''):
        self.tabParent.destroy()
        self.fileFrame.destroy()

        self.tabParent = Notebook(self)
        self.fileFrame = Frame(self)
        self.fileFrame.pack(side=LEFT, anchor=NE)
        self.tabParent.pack(side=LEFT, fill=BOTH, expand=1)
        if len(dirPath) != 0:
            self.dirPath = dirPath
        else:
            self.dirPath = self.openFileDialog()
        folderTabData = self.breakPaths(self.dirPath)
        self.fileDict = folderTabData
        self.fileFrameEntities = self.renderBlock(self.fileFrame, self.fileDict)
        self.fileDict = {}
        self.cacheDict = {}
        self.tabEntities = {}
        self.tabEntities['canvas'] = {}
        self.tabEntities['canvas']['entities'] = {}
        try:
            self.openTkCanvas()
        except:
            pass
    def renderBlock(self, parent, fileDict):
        index = 0
        output = {}
        keys = list(fileDict.keys())
        for key in keys:
            if key == 'files':
                output[key] = list()
                for file in fileDict['files']:
                    tempButton = Button(parent, text= file, command=lambda path=fileDict['dir'], f=file: self.addTab(path, f))
                    output[key].append(tempButton)
                    index+=1
                    tempButton.grid(row=index+1, sticky=W, padx=(10,))
            elif key == 'dir':
                pass
            else:
                temp =  {}
                temp['frameParent'] = Frame(parent)
                temp['self'] = Button(parent, text=key, command=lambda frame=temp['frameParent'], i=index: self.activate(frame, i))
                if parent != self.fileFrame:
                    temp['self'].grid(row=index, sticky=W, padx=(10,))
                else:
                    temp['self'].grid(row=index, sticky=W)

                index+=2
                temp.update(self.renderBlock(temp['frameParent'], fileDict[key]))

                output = temp

        return output
    def activate(self, frame, index):
        if frame.winfo_ismapped() == 0:
            frame.grid(row=index+1)
        else:
            frame.grid_forget()

    def breakPaths(self, path):
        output = {}
        for (p, dirs, files) in walk(path):
            for e in dirs:
                output[e] = self.breakPaths(str(path) + '/' + e)
            output['dir'] = p
            output['files'] = files
            break
        return output
    def addTab(self,path, name):
        filePath = osPath.join(path, name)
        self.tabEntities[filePath] = {}
        tabFrame = Frame(self.tabParent)
        self.tabEntities[filePath]['self'] = tabFrame
        self.tabParent.add(tabFrame, text=name)
        self.tabEntities[filePath]['text'] = Text(tabFrame, tabs=('8m',))
        self.tabEntities[filePath]['text'].pack(fill=BOTH, expand=1)
        self.tabEntities[filePath]['save'] = Button(tabFrame, text="save", command=lambda p=filePath: self.saveFile(p))
        self.tabEntities[filePath]['save'].pack()
        with open(filePath, "r") as func:
            try:
                text = func.readlines()
                for line in text:
                    self.tabEntities[filePath]['text'].insert(END, line)
            except UnicodeDecodeError:
                self.tabEntities[name]['text'].insert(END, "can't open this file")
    def saveFile(self, filePath):
        #wText is the text widget
        text = self.tabEntities[filePath]['text'].get('1.0', END)
        with open(filePath, "w+") as f:
            f.write(text)
            f.close()
    def createTkinterProject(self, filePath):
        templateText = list()
        with open("templates/empty_window.py", "r") as f:
            templateText = f.readlines()
            f.close()
        mkdir(filePath + '/tk_project')
        mkdir(filePath + '/tk_project/.cache')
        with open(filePath + "/tk_project" + "/main.py", "w+") as f:
            f.writelines(templateText)
            f.close()

        with open(filePath + "/tk_project/.cache/components.json", "w+") as f:
            f.close()
        self.renderDirectoryFiles()
        self.tkFile = filePath + "/tk_project/main.py"
        self.tkFileCache = filePath + "/tk_project/.cache/components.json"
        self.createTkCanvas(self.tkFile)

    def openFileDialog(self):
        folderPath = filedialog.askdirectory(title="open folder")
        return folderPath
    def openTkCanvas(self):
        try:
            tkFileCache = self.dirPath+ "/.cache/components.json"
            with open(tkFileCache, 'r') as f:
                try:
                    cacheDict = json.load(f)
                except json.decoder.JSONDecodeError:
                    cachDict = {}
                self.cacheDict = cacheDict
                for key in list(cacheDict.keys()):
                    if key != '':
                        self.createTkCanvas(key)
                f.close()
        except:
            tkFileCache = self.dirPath+ "/tk_project/.cache/components.json"
            with open(tkFileCache, 'r') as f:
                try:
                    cacheDict = json.load(f)
                except json.decoder.JSONDecodeError:
                    cachDict = {}
                self.cacheDict = cacheDict
                for key in list(cacheDict.keys()):
                    if key != '':
                        self.createTkCanvas(key)
                f.close()

    def createTkCanvas(self, filePath):
        tkCanvas = Frame(self.tabParent)
        CanvasName = filePath.split('/')[len(filePath.split('/'))-1]
        if CanvasName in list(self.tabEntities['canvas']['entities'].keys()):
            CanvasName = "{}/{}~design".format(filePath.split('/')[len(filePath.split())-2],filePath.split('/')[len(filePath.split())-1])
        else:
            CanvasName +='~design'
        self.tabParent.add(tkCanvas, text=CanvasName)
        self.tabEntities['canvas'][filePath] = {}
        self.tabEntities['canvas'][filePath]['self'] = tkCanvas
        self.tabEntities['canvas'][filePath]['children'] = []
        self.tabEntities['canvas']['entities'][CanvasName] = filePath
        try:
            fileComponents = self.cacheDict[filePath]
            self.renderTkWidgets(fileComponents)
            self.renderWidgetGallery()
            self.cacheDict[filePath]['parent']['self'] = {'type': 'Frame', "text": CanvasName}
        except KeyError:
            self.cacheDict[filePath] = {}
            self.renderWidgetGallery()
            self.cacheDict[filePath]['parent'] = {}
            self.cacheDict[filePath]['parent']['self'] = {'type': 'Frame', 'text': CanvasName}
    def renderTkWidgets(self, fileComponents):
        filePath = [e for e in list(self.cacheDict.keys()) if self.cacheDict[e] == fileComponents][0]

        canvas = self.tabEntities['canvas'][filePath]['self']
        for key in list(fileComponents.keys()):
            if key != "parent":
                widget = [e[1] for e in self.widgets if fileComponents[key]['type'] == e[0]][0]
                w = widget(canvas, text= fileComponents[key]['self']['text'])
                w.bind('<B1-Motion>', lambda e, index=key: self.moveWidgetWithCursor(e, index))
                w.place(x= fileComponents[key]['placeProps']['x'], y=fileComponents[key]['placeProps']['y'])
                w.bind('<Button-1>', lambda e, widget=w,k=key ,parent=self: renderProperties(widget,k, parent))
                self.tabEntities['canvas'][filePath]['children'].append((int(key), w))

    def renderWidgetGallery(self):
        objWidgets = list(map(lambda e: Button(self.widgetParent, text=e[0], command= lambda a=e[0]: self.addWidgetToCanvas(a)), self.widgets))
        for widget in objWidgets:
            widget.pack(side=TOP)
    def moveWidgetWithCursor(self, event, index):

        activeTabName = self.tabParent.tab(self.tabParent.select(), "text")
        filePath = self.tabEntities['canvas']['entities'][activeTabName]
        widget = event.widget
        parent = Widget._nametowidget(self, widget.winfo_parent())
        parent = Widget._nametowidget(self, parent.winfo_parent())
        xpos, ypos = self.winfo_pointerx()- self.winfo_x()-8-parent.winfo_x(), self.winfo_pointery()- self.winfo_y()-50-parent.winfo_y()-23
        widget.place_forget()
        widget.place(x=xpos, y=ypos)
        self.cacheDict[filePath][str(index)]['placeProps'].pop('relx', None)
        self.cacheDict[filePath][str(index)]['placeProps'].pop('rely', None)
        self.cacheDict[filePath][str(index)]['placeProps']['x'], self.cacheDict[filePath][str(index)]['placeProps']['y'] = xpos, ypos

    def addWidgetToCanvas(self, widgetName):
        activeTabName = self.tabParent.tab(self.tabParent.select(), "text")
        try:
            filePath = self.tabEntities['canvas']['entities'][activeTabName]
        except KeyError:
            return
        indexes = [b[0] for b in self.tabEntities['canvas'][filePath]['children']]
        try:
            index = max(indexes) + 1
        except ValueError:
            index = 0
        widget = [e[1] for e in self.widgets if e[0] == widgetName][0]
        w = widget(self.tabEntities['canvas'][filePath]['self'], text="text here")
        w.bind('<B1-Motion>', lambda event, e=index: self.moveWidgetWithCursor(event, e))
        w.bind('<Button-1>', lambda e, widget=w, parent=self: renderProperties(widget, parent))
        w.place(relx=0.5, rely=0.5, anchor='center')
        widgetDict = {
            'type': widgetName,
            'self': {
                'text': "text here"
            },
            'placeProps': {'relx': 0.5, 'rely': 0.5, 'anchor': NW}
        }
        self.tabEntities['canvas'][filePath]['children'].append((index, widgetDict))
        self.cacheDict[filePath][str(index)] = widgetDict

test = program()

test.mainloop()


from sqlglot import exp, parse_one

from sqlmesh.core.dialect import (
    JinjaQuery,
    JinjaStatement,
    Model,
    format_model_expressions,
    parse,
    select_from_values_for_batch_range,
    text_diff,
)

def test_format_model_expressions():
    x = format_model_expressions(
        parse(
            """
    MODEL(
    name a.b,
    kind full,
    references (
     a,
     (b, c) as d,
     )
    )
    ;

    @DEF(x
    , 1);

    SELECT
    *,
    CAST(a AS int),
    CAST(b AS int) AS b,
    CAST(c + 1 AS int) AS c,
    d::int,
    e::int as e,
    (f + 1)::int as f,
    sum(g + 1)::int as g,
    CAST(h AS int), -- h
    CAST(i AS int) AS i, -- i
    CAST(j + 1 AS int) AS j, -- j
    k::int, -- k
    l::int as l, -- l
    (m + 1)::int as m, -- m
    sum(n + 1)::int as n, -- n
    o,
    p + 1,
    """
        )
    )
    assert (
        x
        == """MODEL (
  name a.b,
  kind FULL,
  references (a, (b, c) AS d)
);

@DEF(x, 1);

SELECT
  *,
  a::INT AS a,
  b::INT AS b,
  CAST(c + 1 AS INT) AS c,
  d::INT AS d,
  e::INT AS e,
  (
    f + 1
  )::INT AS f,
  SUM(g + 1)::INT AS g,
  h::INT AS h, /* h */
  i::INT AS i, /* i */
  CAST(j + 1 AS INT) AS j, /* j */
  k::INT AS k, /* k */
  l::INT AS l, /* l */
  (
    m + 1
  )::INT AS m, /* m */
  SUM(n + 1)::INT AS n, /* n */
  o AS o,
  p + 1"""
    )

    x = format_model_expressions(
        parse(
            """
            MODEL(name a.b, kind FULL);
            JINJA_QUERY_BEGIN; /* comment */ SELECT * FROM x WHERE y = {{ 1 }}; /* comment */ JINJA_END;"""
        )
    )
    assert (
        x
        == """MODEL (
  name a.b,
  kind FULL
);

JINJA_QUERY_BEGIN;
/* comment */ SELECT * FROM x WHERE y = {{ 1 }}; /* comment */
JINJA_END;"""
    )

def test_macro_format():
    assert parse_one("@EACH(ARRAY(1,2), x -> x)").sql() == "@EACH(ARRAY(1, 2), x -> x)"

def test_format_body_macros():
    assert (
        format_model_expressions(
            parse(
                """
    Model ( name foo );
    @WITH(TRUE) x AS (SELECT 1)
    SELECT col::int
    FROM foo @ORDER_BY(@include_order_by)
    @EACH( @columns,
    item -> @'@iteaoeuatnoehutoenahuoanteuhonateuhaoenthuaoentuhaeotnhaoem'),      @'@foo'
    """
            )
        )
        == """MODEL (
  name foo
);

@WITH(TRUE) x AS (
  SELECT
    1
)
SELECT
  col::INT AS col
FROM foo
@ORDER_BY(@include_order_by)
  @EACH(@columns, item -> @'@iteaoeuatnoehutoenahuoanteuhonateuhaoenthuaoentuhaeotnhaoem'),
  @'@foo'"""
    )

def test_text_diff():
    assert """@@ -1,3 +1,3 @@

 SELECT
-  *
-FROM x
+  1
+FROM y""" in text_diff(
        parse_one("SELECT * FROM x"), parse_one("SELECT 1 FROM y")
    )

def test_parse():
    expressions = parse(
        """
        MODEL (
            kind full,
            dialect "hive",
        );

        CACHE TABLE x as SELECT 1 as Y;

        JINJA_QUERY_BEGIN;

        SELECT * FROM x WHERE y = {{ 1 }} ;

        JINJA_END;

        JINJA_STATEMENT_BEGIN;

        {{ side_effect() }};

        JINJA_END;
    """
    )

    assert len(expressions) == 4
    assert isinstance(expressions[0], Model)
    assert isinstance(expressions[1], exp.Cache)
    assert isinstance(expressions[2], JinjaQuery)
    assert isinstance(expressions[3], JinjaStatement)

def test_parse_jinja_with_semicolons():
    expressions = parse(
        """
        CREATE TABLE a as SELECT 1;
        CREATE TABLE b as SELECT 1;

        JINJA_STATEMENT_BEGIN;

        {% call set_sql_header(config) %}
            CREATE OR REPLACE TEMP MACRO add(a, b) AS a + b;
        {%- endcall %}

        JINJA_END;

        DROP TABLE a;
        DROP TABLE b;
    """
    )

    assert len(expressions) == 5
    assert isinstance(expressions[0], exp.Create)
    assert isinstance(expressions[1], exp.Create)
    assert isinstance(expressions[2], JinjaStatement)
    assert isinstance(expressions[3], exp.Drop)
    assert isinstance(expressions[4], exp.Drop)

def test_seed():
    expressions = parse(
        """
        MODEL (
            kind SEED (
                path '..\..\..\data\data.csv',
            ),
        );
    """
    )
    assert len(expressions) == 1
    assert "../../../data/data.csv" in expressions[0].sql()

def select_from_values_for_batch_range_json():
    values = [(1, "2022-01-01", '{"foo":"bar"}'), (2, "2022-01-01", '{"foo":"qaz"}')]
    columns_to_types = {
        "id": exp.DataType.build("int"),
        "ds": exp.DataType.build("text"),
        "json_col": exp.DataType.build("json"),
    }
    assert select_from_values_for_batch_range(values, columns_to_types, 0, len(values)).sql() == (
        """SELECT CAST(id AS INT) AS id, CAST(ds AS TEXT) AS ds, CAST(json_col AS JSON) AS json_col """
        """FROM """
        """(VALUES (1, '2022-01-01', PARSE_JSON('{"foo":"bar"}')), (2, '2022-01-01', PARSE_JSON('{"foo":"qaz"}'))) """
        """AS t(id, ds, json_col)"""
    )


import re
import asyncio
from pathlib import Path
from dataclasses import dataclass

from adb_shell.adb_device_async import AdbDeviceTcpAsync
from adb_shell.auth.sign_pythonrsa import PythonRSASigner
from adb_shell.auth.keygen import keygen
from adb_shell.exceptions import TcpTimeoutException

from googletv.constants import (
    ADB_MAX_RETRIES,
    ADB_RETRY_INTERVAL,
    ADB_MAX_TIMEOUTS,
    APP_ATV_LAUNCHER,
    APP_NETFLIX,
    APP_NLZIET,
    APP_PLEX,
    APP_TVHEADEND,
    APP_VLC,
    APP_YOUTUBE,
    APP_NAMES,
    CMD_DUMPSYS_ACTIVITY,
    CMD_DUMPSYS_DISPLAY,
    CMD_DUMPSYS_ERROR,
    CMD_DUMPSYS_MEDIA_SESSION,
    CMD_DUMPSYS_POWER,
    REGEX_ACTIVITY_RESUMED,
    REGEX_ACTIVITY,
    REGEX_ASLEEP,
    REGEX_AWAKE,
    REGEX_PLAYBACK_STATE,
    REGEX_SCREEN_OFF,
    REGEX_SCREEN_ON,
    REGEX_SESSION,
    REGEX_WAKE_LOCK_SIZE,
    STATE_IDLE,
    STATE_OFF,
    STATE_PAUSED,
    STATE_PLAYING,
)
from googletv.exception import GoogleTvException
from googletv.search import search_nested

class AdbKey:
    def __init__(self, file_path: str) -> None:
        self._file_path = file_path

        self._public_key: str | None = None
        self._private_key: str | None = None

    @property
    def public_key_path(self) -> str:
        return f"{self._file_path}.pub"

    @property
    def private_key_path(self) -> str:
        return self._file_path

    @property
    def public_key(self) -> str:
        if self._public_key is None:
            with open(f"{self._file_path}.pub", "r") as f:
                self._public_key = f.read()

        return self._public_key

    @property
    def private_key(self) -> str:
        if self._private_key is None:
            with open(self._file_path, "r") as f:
                self._private_key = f.read()

        return self._private_key

    @property
    def exists(self) -> bool:
        for path in (self.private_key_path, self.public_key_path):
            if not Path(path).is_file():
                return False

        return True

    @staticmethod
    def generate(file_path: str) -> "AdbKey":
        keygen(file_path)
        return AdbKey(file_path)

@dataclass(frozen=True)
class DeviceState:
    awake: bool | None = None
    screen_on: bool | None = None
    app: str | None = None
    playback_state: str | None = None

class GoogleTv:
    def __init__(self, adb_key: AdbKey, host: str, port: int = 5555) -> None:
        self._adb = AdbDeviceTcpAsync(host, port)
        self._adb_key = adb_key

        self._state = DeviceState()
        self._timeout_counter = 0

    @property
    def available(self) -> bool:
        return self._adb.available

    @property
    def state(self) -> DeviceState:
        return self._state

    async def connect(self) -> None:
        signer = PythonRSASigner(self._adb_key.public_key, self._adb_key.private_key)
        await self._adb.connect(rsa_keys=[signer])

    async def close(self) -> None:
        await self._adb.close()

    async def reconnect(self) -> None:
        await self.close()
        await self.connect()

    async def update(self) -> None:
        dumpsys_power = await self._send_command(CMD_DUMPSYS_POWER)
        awake = self._parse_awake(dumpsys_power)
        if not awake:
            new_state = DeviceState(
                awake=awake,
                screen_on=False,
                playback_state=STATE_OFF,
            )
        else:
            dumpsys_display = await self._send_command(CMD_DUMPSYS_DISPLAY)
            dumpsys_activity = await self._send_command(CMD_DUMPSYS_ACTIVITY)
            dumpsys_media_session = await self._send_command(CMD_DUMPSYS_MEDIA_SESSION)

            app = self._parse_app(dumpsys_activity)
            if app:
                playback_state = self._parse_playback_state(
                    dumpsys_power, dumpsys_media_session, app
                )
            else:
                playback_state = None

            app_name = APP_NAMES.get(app, app) if app else None

            new_state = DeviceState(
                awake=self._parse_awake(dumpsys_power),
                screen_on=self._parse_screen_on(dumpsys_display),
                app=app_name,
                playback_state=playback_state,
            )

        self._state = new_state

    async def _send_command(
        self,
        command: str,
        retries: int = ADB_MAX_RETRIES,
        retry_interval: float = ADB_RETRY_INTERVAL,
    ) -> str:
        for _ in range(retries):
            if self._timeout_counter >= ADB_MAX_TIMEOUTS:
                await self.reconnect()

            try:
                result = await self._adb.shell(command)
            except TcpTimeoutException:
                self._timeout_counter += 1
                await asyncio.sleep(retry_interval)
                continue

            self._timeout_counter = 0

            if CMD_DUMPSYS_ERROR not in result:
                return result

            await asyncio.sleep(retry_interval)

        raise GoogleTvException(f"Failed to send command {command}")

    def _parse_awake(self, dumpsys_power: str) -> bool | None:
        if re.search(REGEX_AWAKE, dumpsys_power):
            return True
        if re.search(REGEX_ASLEEP, dumpsys_power):
            return False
        return None

    def _parse_screen_on(self, dumpsys_display: str) -> bool | None:
        if re.search(REGEX_SCREEN_ON, dumpsys_display):
            return True
        if re.search(REGEX_SCREEN_OFF, dumpsys_display):
            return False
        return None

    def _parse_app(self, dumpsys_activity: str) -> str | None:
        matches = search_nested(
            (REGEX_ACTIVITY, REGEX_ACTIVITY_RESUMED), dumpsys_activity
        )
        if matches:
            return matches[0].group("app")

        return None

    def _parse_playback_state(
        self, dumpsys_power: str, dumpsys_media_session: str, app: str
    ) -> str | None:
        wl_match = re.search(REGEX_WAKE_LOCK_SIZE, dumpsys_power)
        if not wl_match:
            return None

        ms_matches = search_nested(
            (REGEX_SESSION, app, REGEX_PLAYBACK_STATE), dumpsys_media_session
        )
        if not ms_matches:
            return None

        wake_lock_size = int(wl_match.group("wake_lock_size"))
        media_session_state = int(ms_matches[2].group("state"))

        # ATV Launcher
        if app in [APP_ATV_LAUNCHER, None]:
            return STATE_IDLE

        # Netflix
        elif app == APP_NETFLIX:
            if media_session_state == 2:
                return STATE_PAUSED
            elif media_session_state == 3:
                return STATE_PLAYING
            else:
                return STATE_IDLE

        # NLZIET
        elif app == APP_NLZIET:
            if wake_lock_size == 1:
                return STATE_PAUSED
            elif wake_lock_size == 2:
                return STATE_PLAYING
        # Plex
        elif app == APP_PLEX:
            if media_session_state == 3:
                if wake_lock_size == 1:
                    return STATE_PAUSED
                else:
                    return STATE_PLAYING
            else:
                return STATE_IDLE

        # TVheadend
        elif app == APP_TVHEADEND:
            if wake_lock_size == 5:
                return STATE_PAUSED
            elif wake_lock_size == 6:
                return STATE_PLAYING
            else:
                return STATE_IDLE

        # VLC
        elif app == APP_VLC:
            if media_session_state == 2:
                return STATE_PAUSED
            elif media_session_state == 3:
                return STATE_PLAYING
            else:
                return STATE_IDLE

        # YouTube
        elif app == APP_YOUTUBE:
            if media_session_state == 2:
                return STATE_PAUSED
            elif media_session_state == 3:
                return STATE_PLAYING
            else:
                return STATE_IDLE

        # Get the state from `media_session_state`
        elif media_session_state:
            if media_session_state == 2:
                return STATE_PAUSED
            elif media_session_state == 3:
                return STATE_PLAYING
            else:
                return STATE_IDLE

        # Get the state from `wake_lock_size`
        else:
            if wake_lock_size == 1:
                return STATE_PAUSED
            elif wake_lock_size == 2:
                return STATE_PLAYING
            else:
                return STATE_IDLE

        return None


import json

from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton

from botController import BotController
from bot_utils import BotUtils

class CidadeController:
    __bot_util__ = BotUtils.get_instance()
    __bot_controller__ = BotController.get_instance()

    def buscar_cidade(self, cidade_id):
        request = self.__bot_util__.send_get(path=f'/cidade/{cidade_id}/')
        cidade = json.loads(request.content)

        return cidade

    def buscar_cidades(self):
        request = self.__bot_util__.send_get(path='/cidade/')

        a_json_object = json.loads(request.content)
        list_from_json = a_json_object["results"]
        return list_from_json

    def escolher_cidade_info(self, chat_id):
        cidades = self.get_botoes_cidade()
        message = self.__bot_controller__.bot.send_message(text='Deseja ver informações de qual cidade?',
                                                           chat_id=chat_id, reply_markup=cidades)
        self.__bot_controller__.bot.register_callback_query_handler(func=lambda call: message.id == call.message.id,
                                                                    callback=self.__show_info_cidade__)

    def get_botoes_cidade(self):
        cidades = self.buscar_cidades()

        markup = InlineKeyboardMarkup()
        markup.row_width = 2

        for cidade in cidades:
            data = json.dumps({'id': cidade['pk'], 'nome': cidade['nome']})
            label = f'{cidade["nome"]}'
            markup.add(InlineKeyboardButton(text=label, callback_data=data))

        return markup

    def __info_detalhada_cidade__(self, cidade):
        info = f'*::::::::::  {cidade["nome"]} ::::::::::*\n' \
               f'Governante: {cidade["governante"]["nome"]}\n' \
               f'Tesouro: {cidade["tesouro"]} peças de ouro'

        info = self.__bot_util__.escape_chars(info)
        return info

    def __show_info_cidade__(self, call):
        chat_id = call.message.chat.id

        dados = json.loads(call.data)
        id_cidade = dados['id']

        cidade = self.buscar_cidade(cidade_id=id_cidade)
        info_cidade = self.__info_detalhada_cidade__(cidade=cidade)
        self.__bot_controller__.bot.send_message(text=info_cidade, chat_id=chat_id, parse_mode='MarkdownV2')


#AUTHOR: duhack
#GITHUB: https://github.com/duhack

import discord
import time
import datetime
import mysql.connector
from discord.ext import commands
from discord.utils import get

embedColor = 0x0047b3 # KOLOR WYSYŁANYCH WIADOMOŚCI

configMysql = {
    'user': '', #uzytkownik bazy danych
    'password': '', #haslo do bazy danych
    'host': '', #ip bazy danych
    'database': '', #baza danych
}
rankSynchro = 832616480339394640 # id nadawanej rangi na discordzie (do wyciągnięcia przez tryb developerski)

connection = mysql.connector.connect(**configMysql)
cursor = connection.cursor()

start_time = time.time()

class Commands(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def synchronizacja(self, ctx, code = None):
        embed = None
        if code is not None:
            sql_select_Query = "select * from `synchronizacja-dsc` WHERE code='"+code+"'"
            cursor.execute(sql_select_Query)
            records = cursor.fetchall()
            znaleziono = False
            for row in records:
                znaleziono = True
                if str(row[2]) == "nie":
                    cursor.execute("select `nick` from players WHERE uid='"+str(row[0])+"'")
                    records_nick = cursor.fetchall()
                    member = ctx.author
                    avatar = str(member.avatar_url)
                    role = get(member.guild.roles, id=rankSynchro)
                    await member.add_roles(role)
                    embed = discord.Embed(title="Synchronizacja konta", description="Synchronizacja konta przebiegła prawidłowo, otrzymujesz rangę Zweryfikowany.", color=embedColor)
                    embed.add_field(name="Serwer", value=records_nick[0][0])
                    embed.add_field(name="Discord", value=member)
                    embed.set_thumbnail(url=avatar)
                    sql = "UPDATE `synchronizacja-dsc` SET used = %s, account_discord = %s, avatar = %s WHERE code=%s"
                    val = ("tak", member.id, str(member.avatar_url)[0:-15]+'.png?size=1024', code)
                    cursor.execute(sql, val)
                    connection.commit()
                else:
                    embed = discord.Embed(title="Synchronizacja konta", description="Ten klucz został już zrealizowany!", color=embedColor)
            if znaleziono == False:
                embed = discord.Embed(title="Synchronizacja konta", description="Podany kod jest nieprawidłowy!", color=embedColor)
            cursor.close()
        else:
            embed = discord.Embed(title="Synchronizacja konta", description="Aby użyć tej komendy wykonaj wygeneruj klucz w grze (**/discord**),\n \n a następnie wpisz go w tej formie: **!synchronizacja <KOD>**\n \n Aby sprawdzić status twojej synchronizacji - użyj komendy w grze (**/discord-status**)", color=embedColor)
        if not embed == None:
            await ctx.send(embed=embed)

def setup(bot):
    bot.add_cog(Commands(bot))


import pandas as pd
import plotly.graph_objects as go
import dash
from dash import html
from dash import dcc
from dash.dependencies import Input, Output
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# Load data for multiple global indices
df = pd.read_csv('data/Global_index.csv')
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)

# Interpolate null values
df = df.interpolate()

symbols = df.columns

def moving_average(df, symbol, window_size):
      ma = df[symbol].rolling(window=window_size).mean()
      return ma

app = dash.Dash(__name__)

app.layout = html.Div(
      [
            html.Div(
                  [
                        dcc.Dropdown(
                              id='symbol-dropdown',
                              options=[{'label': symbol, 'value': symbol} for symbol in symbols],
                              value='S&P_original',
                              style={'width': '80%'}
                        ),
                        dcc.Dropdown(
                              id='compare-dropdown',
                              options=[{'label': symbol, 'value': symbol} for symbol in symbols],
                              value='FTSE_100',
                              style={'width': '80%'}
                        ),
                  ],
                  style={'display': 'flex', 'align-items': 'center', 'justify-content': 'center'}
            ),
            dcc.RadioItems(
                  id='moving-average-radio',
                  options=[
                        {'label': 'None', 'value': 0},
                        {'label': '7 Days', 'value': 7},
                        {'label': '15 Days', 'value': 15},
                        {'label': '30 Days', 'value': 30},
                  ],
                  value=0
            ),
            dcc.Graph(id='line-chart', figure={}),
      ]
)

@app.callback(Output('line-chart', 'figure'),
                  [Input('symbol-dropdown', 'value'),
                        Input('compare-dropdown', 'value'),
                        Input('moving-average-radio', 'value')])
def update_line_chart(symbol, compare_symbol, moving_average_window):
      fig = make_subplots(specs=[[{"secondary_y": True}]])

      # Add trace for selected index
      fig.add_trace(go.Scatter(x=df.index, y=df[symbol], name=symbol), secondary_y=False)

      # Add trace for comparison index
      fig.add_trace(go.Scatter(x=df.index, y=df[compare_symbol], name=compare_symbol), secondary_y=True)

      if moving_average_window != 0:
            # Add trace for selected index moving average
            ma = moving_average(df, symbol, moving_average_window)
            fig.add_trace(go.Scatter(x=df.index, y=ma, name='{}-Day MA ({})'.format(moving_average_window, symbol)),
                              secondary_y=False)

            # Add trace for comparison index moving average
            ma_compare = moving_average(df, compare_symbol, moving_average_window)
            fig.add_trace(go.Scatter(x=df.index, y=ma_compare, name='{}-Day MA ({})'.format(moving_average_window, compare_symbol)),
                              secondary_y=True)

      fig.update_layout(
            height=400,
            width=1250,
            xaxis=dict(title='Date'),
            yaxis=dict(title=symbol,
                        showgrid=False),
            yaxis2=dict(title=compare_symbol,
                              overlaying='y',
                              side='right'),
            hovermode='x',
            title='{} vs {} Price'.format(symbol, compare_symbol),
            # title='Global Index Comparison'

      )

      return fig

if __name__ == "__main__":
      app.run_server(debug=True)


import csv
import enchant
import nltk.classify.util
from nltk.classify import NaiveBayesClassifier
import pickle
def newPreprocess(string):
    chars = "!@#$%^&*(){}[]:;""''<>,./?|\\1234567890"
    for c in chars:
        string = string.replace(c,"")
    return string
def removeNonEnglishWords(string,d):
    ret=""
    splits = string.split()
    for each in splits:
        if d.check(each):
            ret = ret+" "+each
    return ret
def word_feats(words):
    return dict([(word, True) for word in words])
classVariables={}
negids=[]
posids=[]
netids=[]
count=0
with open("C:/Users/MAHATHI/Downloads/trainingandtestdata/training.1600000.processed.noemoticon.csv", "r") as csvfile:
    spamreader = csv.reader(csvfile, dialect='excel')
    for row in spamreader:
        d = enchant.Dict("en_US")
        if(count>2000):
            break
        count = count + 1
        cleanedString = newPreprocess(row[5])
        englishString = removeNonEnglishWords(cleanedString,d)
        if(row[0]=='0'):
            negids.append(englishString.split())
        elif(row[0]=='2'):
            netids.append(englishString.split())
        elif(row[0]=='4'):
            posids.append(englishString.split())
    negfeats = [(word_feats(f), 'neg') for f in negids]
    posfeats = [(word_feats(f), 'pos') for f in posids]
    netfeats = [(word_feats(f), 'net') for f in netids]
    negcutoff = int(len(negfeats)*3/4)
    poscutoff = int(len(posfeats)*3/4)
    netcutoff = int(len(netfeats)*3/4)
    trainfeats = negfeats[:negcutoff] + posfeats[:poscutoff]
    testfeats = negfeats[negcutoff:] + posfeats[poscutoff:]
    print('train on %d instances, test on %d instances' % (len(trainfeats), len(testfeats)))

    classifier = NaiveBayesClassifier.train(trainfeats)
    f = open('C:/Users/MAHATHI/Downloads/trainingandtestdata/my_classifier.pickle', 'wb')
    pickle.dump(classifier, f)
    f.close()


#!/usr/bin/env python3
import sys
import taintedstr
import coverage
import linecache
import imp
import os
import pickle

import pygmalion.fuzz as fuzz

def records(f):
    try:
        while not f.closed:
            yield pickle.load(f)
    except EOFError:
        raise StopIteration

if __name__ == "__main__":
    m_file = sys.argv[1]
    mod_obj = imp.new_module('example')
    mod_obj.__file__ = m_file
    mod_obj._MODULE_SOURCE_CODE = open(m_file).read()
    code = compile(mod_obj._MODULE_SOURCE_CODE, os.path.basename(m_file), 'exec')
    exec(code, mod_obj.__dict__)
    # (size, mtime, lines, fullname)
    linecache.updatecache(m_file)
    #linecache.cache[os.path.basename(m_file)] = linecache.cache[m_file]

    fin = sys.stdin.buffer if len(sys.argv) < 3 else open(sys.argv[2], 'rb')
    fout = sys.stdout if len(sys.argv) < 3 else open("%s.tmp" % sys.argv[2], 'w')
    valid_n = 0
    cov = coverage.Coverage()
    cov.start()
    for j,(i, t) in enumerate(records(fin)):
        try:
            print(j, repr(i))
            v = mod_obj.main(taintedstr.tstr(i))
            print("\t=>",v)
            valid_n += 1
        except:
            pass
        print("%", cov.report(file=fout), ' at ', t, 'seconds')
            #print('Error')
    print("Valid:", valid_n)
    cov.stop()
    cov.save()
    print(cov.report(file=fout))
    cov.html_report(directory='coverage')


from hamcrest import ( assert_that,
                       contains_exactly,
                       empty,
                       equal_to,
                       has_entries )
from unittest import TestCase
import requests

from ycmd.utils import ReadFile
from ycmd.tests.java import setUpModule, tearDownModule # noqa
from ycmd.tests.java import PathToTestFile, SharedYcmd
from ycmd.tests.test_utils import ( CombineRequest,
                                    ParameterMatcher,
                                    SignatureMatcher,
                                    SignatureAvailableMatcher,
                                    WaitUntilCompleterServerReady,
                                    WithRetry )

def ProjectPath( *args ):
  return PathToTestFile( 'extra_confs',
                         'simple_extra_conf_project',
                         'src',
                         *args )

def RunTest( app, test ):
  """
  Method to run a simple signature help test and verify the result

  test is a dictionary containing:
    'request': kwargs for BuildRequest
    'expect': {
       'response': server response code (e.g. httplib.OK)
       'data': matcher for the server response json
    }
  """
  contents = ReadFile( test[ 'request' ][ 'filepath' ] )

  app.post_json( '/event_notification',
                 CombineRequest( test[ 'request' ], {
                                 'event_name': 'FileReadyToParse',
                                 'contents': contents,
                                 } ),
                 expect_errors = True )

  # We ignore errors here and we check the response code ourself.
  # This is to allow testing of requests returning errors.
  response = app.post_json( '/signature_help',
                            CombineRequest( test[ 'request' ], {
                              'contents': contents
                            } ),
                            expect_errors = True )

  assert_that( response.status_code,
               equal_to( test[ 'expect' ][ 'response' ] ) )

  print( response.json )
  assert_that( response.json, test[ 'expect' ][ 'data' ] )

class SignatureHelpTest( TestCase ):
  @WithRetry()
  @SharedYcmd
  def test_SignatureHelp_MethodTrigger( self, app ):
    RunTest( app, {
      'description': 'Trigger after (',
      'request': {
        'filetype'  : 'java',
        'filepath'  : ProjectPath( 'SignatureHelp.java' ),
        'line_num'  : 9,
        'column_num': 17,
      },
      'expect': {
        'response': requests.codes.ok,
        'data': has_entries( {
          'errors': empty(),
          'signature_help': has_entries( {
            'activeSignature': 0,
            'activeParameter': 0,
            'signatures': contains_exactly(
              SignatureMatcher( 'unique(double d) : void',
                                [ ParameterMatcher( 7, 15 ) ] )
            ),
          } ),
        } )
      }
    } )

  @WithRetry()
  @SharedYcmd
  def test_SignatureHelp_ArgTrigger( self, app ):
    RunTest( app, {
      'description': 'Trigger after ,',
      'request': {
        'filetype'  : 'java',
        'filepath'  : ProjectPath( 'SignatureHelp.java' ),
        'line_num'  : 5,
        'column_num': 23,
      },
      'expect': {
        'response': requests.codes.ok,
        'data': has_entries( {
          'errors': empty(),
          'signature_help': has_entries( {
            'activeSignature': 1,
            'activeParameter': 1,
            'signatures': contains_exactly(
              SignatureMatcher( 'test(int i, String s) : void',
                                [ ParameterMatcher( 5, 10 ),
                                  ParameterMatcher( 12, 20 ) ] ),
              SignatureMatcher( 'test(String s, String s1) : void',
                                [ ParameterMatcher( 5, 13 ),
                                  ParameterMatcher( 15, 24 ) ] )
            ),
          } ),
        } )
      }
    } )

  @WithRetry()
  @SharedYcmd
  def test_SignatureHelp_Constructor( self, app ):
    RunTest( app, {
      'description': 'Constructor',
      'request': {
        'filetype'  : 'java',
        'filepath'  : ProjectPath( 'SignatureHelp.java' ),
        'line_num'  : 17,
        'column_num': 41,
      },
      'expect': {
        'response': requests.codes.ok,
        'data': has_entries( {
          'errors': empty(),
          'signature_help': has_entries( {
            'activeSignature': 0,
            'activeParameter': 0,
            'signatures': contains_exactly(
              SignatureMatcher( 'SignatureHelp(String signature)',
                                [ ParameterMatcher( 14, 30 ) ] )
            ),
          } ),
        } )
      }
    } )

  @SharedYcmd
  def test_Signature_Help_Available( self, app ):
    request = { 'filepath' : ProjectPath( 'SignatureHelp.java' ) }
    app.post_json( '/event_notification',
                   CombineRequest( request, {
                     'event_name': 'FileReadyToParse',
                     'filetype': 'java'
                   } ),
                   expect_errors = True )
    WaitUntilCompleterServerReady( app, 'java' )

    response = app.get( '/signature_help_available',
                        { 'subserver': 'java' } ).json
    assert_that( response, SignatureAvailableMatcher( 'YES' ) )