import numpy as np
from numpy.lib import recfunctions as rfn
from scipy.io.arff import loadarff
from sklearn.model_selection import StratifiedKFold
from sklearn.preprocessing import MinMaxScaler
from algorithms import *
from P3_algorithms import *
from numpy.random import uniform
import time
import pandas as pd
import pyinstrument as py

dataset_ionosphere = 'Datasets/ionosphere.arff'
dataset_parkinson = 'Datasets/parkinsons.arff'
dataset_heart = 'Datasets/spectf-heart.arff'

"""Load one specific dataset.

    Returns:
        It returns both dataset features and target

    Parameters:
    filename -- file of type .arff to load

    """
def load_arff(filename):
    dataset = loadarff(filename)[0]
    if filename == dataset_ionosphere:
        target = dataset['class']
        dataset_features = rfn.drop_fields(dataset, 'class').view(np.float64).reshape(dataset.shape+(-1,))
    else:
        target = dataset['Class']
        dataset_features = rfn.drop_fields(dataset, 'Class').view(np.float64).reshape(dataset.shape+(-1,))
    return dataset_features, target

"""Executes algorithms of P1 for given dataset.

    Returns:
        It returns results obtained for each of the algorithms
        Results: Rows: partition-i. Cols: T-clas,T-red,Agr,T

    Parameters:
    dataset -- dataset name
    dataset_features -- dataset features
    dataset target -- dataset target

    """
def execution_results_P1(dataset, dataset_features, dataset_target):
    print('Algorithms belonging to P1')
    i = 0   # Indicates partition
    skf = StratifiedKFold(n_splits = 5) # cross-validation
    # Optimization
    entryRange_x = range(4)
    entryRange_y = range(7)
    dataset_1NN = [[0 for x in entryRange_x] for y in entryRange_y]
    dataset_GR = [[0 for x in entryRange_x] for y in entryRange_y]
    dataset_LS = [[0 for x in entryRange_x] for y in entryRange_y]

    print("File: ", dataset)
    split_indexes = skf.split(dataset_features,dataset_target)
    for trainIndex , testIndex in split_indexes:
        onennTime = 0
        greedyTime = 0
        localSTime = 0
        n = testIndex.shape[0]
        onennRight = 0
        greedyRight = 0
        lsRight = 0
        # Time for weights calc
        startTime = time.time()
        greedyWeights = greedyRelief(dataset_features[trainIndex],dataset_target[trainIndex])
        greedyTime += time.time() - startTime
        ini_uniform_weights = np.random.uniform(0.0,1.0,dataset_features.shape[1])
        # Time for waeights calc
        startTime = time.time()
        lsWeights = localSearch(ini_uniform_weights,dataset_features[trainIndex],dataset_target[trainIndex])
        localSTime += time.time() - startTime

        for element in testIndex:
            startTime = time.time()
            if one_nn(dataset_features[trainIndex],dataset_target[trainIndex],dataset_features[element]) == dataset_target[element]:
                onennRight +=1
            onennTime += time.time()-startTime

            startTime = time.time()
            if weighted_onenn(greedyWeights,dataset_features[trainIndex],dataset_target[trainIndex],dataset_features[element]) == dataset_target[element]:
                greedyRight +=1
            greedyTime += time.time() -startTime

            startTime = time.time()
            if weighted_onenn(lsWeights,dataset_features[trainIndex],dataset_target[trainIndex],dataset_features[element]) == dataset_target[element]:
                lsRight += 1
            localSTime += time.time() - startTime

        # Save results
        dataset_1NN[i][0] = onennRight/n
        dataset_1NN[i][1] = 0 #its always 0 in this case
        dataset_1NN[i][2] = 0.5*(onennRight/n)
        dataset_1NN[i][3] = onennTime
        dataset_GR[i][0]  = greedyRight/n
        dataset_GR[i][1]  = reduction_rate(greedyWeights)
        dataset_GR[i][2]  = (greedyRight/n+reduction_rate(greedyWeights))/2
        dataset_GR[i][3]  = greedyTime
        dataset_LS[i][0]  = lsRight/n
        dataset_LS[i][1]  = reduction_rate(lsWeights)
        dataset_LS[i][2]  = (lsRight/n+reduction_rate(lsWeights))/2
        dataset_LS[i][3]  = localSTime
        i+=1
        print("Partition ",i)

    return dataset_1NN, dataset_GR, dataset_LS

"""Executes algorithms of P2 for given dataset.

    Returns:
        It returns results obtained for each of the algorithms
        Results: Rows: partition-i. Cols: T-clas,T-red,Agr,T

    Parameters:
    dataset -- dataset name
    dataset_features -- dataset features
    dataset target -- dataset target

    """
def execution_results_P3(dataset, dataset_features, dataset_target):
    print('Algorithms belonging to P3')
    "Indicates partition"
    i = 0
    "Cross Validation"
    skf = StratifiedKFold(n_splits = 5)
    "Optimization"
    entryRange_x = range(4)
    entryRange_y = range(7)
    "Basic Multi - Start search"
    dataset_BMB = [[0 for x in entryRange_x] for y in entryRange_y]
    "Simulated annealing"
    dataset_ES = [[0 for x in entryRange_x] for y in entryRange_y]
    "Iterative local search"
    dataset_ILS = [[0 for x in entryRange_x] for y in entryRange_y]
    "Hybrid between ILS - ES"
    dataset_hybrid = [[0 for x in entryRange_x] for y in entryRange_y]

    "BMB convergence"
    convergence_BMB = [[0] for y in range(5)]
    "ES convergence"
    convergence_ES = [[0] for y in range(5)]
    "ILS convergence"
    convergence_ILS = [[0] for y in range(5)]
    "ILS - ES convergence"
    convergence_HYBRID = [[0] for y in range(5)]

    print("File: ", dataset)
    split_indexes = skf.split(dataset_features,dataset_target)
    for trainIndex , testIndex in split_indexes:
        n = testIndex.shape[0]

        print('BMB\n')

        start = time.time()
        dataset_BMB[i][0],dataset_BMB[i][1], convergence_BMB[i] = bmb(dataset_features,dataset_target,trainIndex,testIndex)
        dataset_BMB[i][2] = 0.5*(dataset_BMB[i][0] + dataset_BMB[i][1])
        dataset_BMB[i][3] = time.time()-start

        print('ES\n')

        start = time.time()
        dataset_ES[i][0],dataset_ES[i][1], convergence_ES[i] = simulated_annealing(dataset_features,dataset_target,trainIndex,testIndex)
        dataset_ES[i][2] = 0.5*(dataset_ES[i][0] + dataset_ES[i][1])
        dataset_ES[i][3] = time.time()-start

        print('ILS\n')

        start = time.time()
        dataset_ILS[i][0],dataset_ILS[i][1], convergence_ILS[i] = ils(dataset_features,dataset_target,trainIndex,testIndex)
        dataset_ILS[i][2] = 0.5*(dataset_ILS[i][0] + dataset_ILS[i][1])
        dataset_ILS[i][3] = time.time()-start

        print('ILS-ES\n')

        start = time.time()
        dataset_hybrid[i][0],dataset_hybrid[i][1], convergence_HYBRID[i] = hybrid_ils_es(dataset_features,dataset_target,trainIndex,testIndex)
        dataset_hybrid[i][2] = 0.5*(dataset_hybrid[i][0] + dataset_hybrid[i][1])
        dataset_hybrid[i][3] = time.time()-start

        i+=1
        print("Partition ",i)

    return dataset_BMB, dataset_ES, dataset_ILS, dataset_hybrid, convergence_BMB, convergence_ES, convergence_ILS, convergence_HYBRID

"""Prints out medium values.

    Parameters:
    d1_algoritmo -- algorithm for which we're gonna print medium values

    """
def print_media(d1_algoritmo):
    for j in range(3):
        lista = []
        for i in range(5):
            lista.append(d1_algoritmo[i][j])
        media = np.mean(lista)
        d1_algoritmo[5][j] = media
        print("%.2f" % media, end=" & ")
    lista = []
    for i in range(5):
        lista.append(d1_algoritmo[i][3])
    media = np.mean(lista)
    d1_algoritmo[5][3] = media
    if len(str(media)) == 8:
        print("%.4f" % media, end="")
    else:
        print("%.5f" % media, end="")

"""Prints out standard desviation values.

    Parameters:
    d_algoritmo -- algorithm for which we're gonna print std values

    """
def print_desviacion(d_algoritmo):
    for j in range(3):
        lista = []
        for i in range(5):
            lista.append(d_algoritmo[i][j])
        desviacion = np.std(lista)
        d_algoritmo[6][j] = desviacion
        print("%.2f" % desviacion, end=" & ")
    lista = []
    for i in range(5):
        lista.append(d_algoritmo[i][3])
    desviacion = np.std(lista)
    d_algoritmo[6][j] = desviacion
    if len(str(desviacion)) == 8:
        print("%.4f" % desviacion, end="")
    else:
        print("%.5f" % desviacion, end="")

"""Prints out results obtained by executing this file.

    Parameters:
    d_algoritmo -- 1st algorithm
    d2_algoritmo -- 2nd algorithm
    d3_algoritmo -- 3rd algorithm

    """
def print_out(d1_algoritmo, d2_algoritmo, d3_algoritmo):
    print("Partition  \t Ionosphere \t \t \t     Parkinsons \t \t \t Spectf-heart \t")
    print("   \tT_clas - T_red - Agr - T\t\tT_clas - T_red - Agr - T \t\tT_clas - T_red - Agr - T ")
    entryRange = [0,1,2,3,4]
    for i in entryRange:
        print(i, end="&\t ")
        for j in range(3):
            print("%.2f" % d1_algoritmo[i][j], end=" & ")
        print("%.5f" % d1_algoritmo[i][3], end=" & ")
        print("\t",end="")
        for j in range(3):
            print("%.2f" % d2_algoritmo[i][j], end=" & ")
        print("%.5f" % d2_algoritmo[i][3], end=" & ")
        print("\t\t",end="")
        for j in range(3):
            print("%.2f" % d3_algoritmo[i][j],end=" & ")
        print("%.5f" % d3_algoritmo[i][3], end=" \\ ")
        print("\n",end="")

    print('Media', end="&\t ")
    print_media(d1_algoritmo)
    print("\t",end="")
    print_media(d2_algoritmo)
    print("\t\t",end="")
    print_media(d3_algoritmo)
    print("\n",end=" \\ ")

    print('Std', end="&\t ")
    print_desviacion(d1_algoritmo)
    print("\t",end="")
    print_desviacion(d2_algoritmo)
    print("\t\t",end="")
    print_desviacion(d3_algoritmo)
    print("\n",end=" \\ ")

"""Creating CSV files of algorithms results for making charts.

    Parameters:
    arr -- array 2d
    counter -- counter for saving name file

    """
def create_csv(arr, counter):
    dataset = pd.DataFrame({'T_Class': arr[:, 0], 'T_Red': arr[:, 1], 'Agr':arr[:,2], 'Tiempo':arr[:,3], 'Algoritmo':nombres[counter].split(sep='_')[1]})
    dataset.to_csv('Archivos_CSV/' + nombres[counter])

"Loading datasets"
ionosphere_features, ionosphere_target = load_arff(dataset_ionosphere)
parkinson_features, parkinson_target = load_arff(dataset_parkinson)
heart_features, heart_target = load_arff(dataset_heart)

"Normalizing data"
ionosphere_features = MinMaxScaler().fit_transform(ionosphere_features)
parkinson_features = MinMaxScaler().fit_transform(parkinson_features)
heart_features = MinMaxScaler().fit_transform(heart_features)

# ionosphere_1nn, ionosphere_gr, ionosphere_ls = execution_results_P1(dataset_ionosphere, ionosphere_features, ionosphere_target)
# ionosphere_1nn, ionosphere_gr, ionosphere_ls = execution_results_P1(dataset_parkinson, parkinson_features, parkinson_target)
# ionosphere_1nn, ionosphere_gr, ionosphere_ls = execution_results_P1(dataset_heart, heart_features, heart_target)

ionosphere_BMB, ionosphere_ES, ionosphere_ILS, ionosphere_HYBRID, \
ionosphere_convergence_BMB, ionosphere_convergence_ES, ionosphere_convergence_ILS, \
ionosphere_convergence_HYBRID = execution_results_P3(dataset_ionosphere, ionosphere_features, ionosphere_target)

parkinson_BMB, parkinson_ES, parkinson_ILS, parkinson_HYBRID, \
parkinson_convergence_BMB, parkinson_convergence_ES, parkinson_convergence_ILS, \
parkinson_convergence_HYBRID = execution_results_P3(dataset_parkinson, parkinson_features, parkinson_target)

heart_spectf_BMB, heart_spectf_ES, heart_spectf_ILS, heart_spectf_HYBRID, \
heart_spectf_convergence_BMB, heart_spectf_convergence_ES, heart_spectf_convergence_ILS, \
heart_spectf_convergence_HYBRID = execution_results_P3(dataset_heart, heart_features, heart_target)

# Printing out
print("Finished algorithms\n")
print("\nResults for BMB")
print_out(ionosphere_BMB, parkinson_BMB, heart_spectf_BMB)
print("\nResults for ES")
print_out(ionosphere_ES, parkinson_ES, heart_spectf_ES)
print("\nResults for ILS")
print_out(ionosphere_ILS, parkinson_ILS, heart_spectf_ILS)
print("\nResults for HYBRID ILS - ES")
print_out(ionosphere_HYBRID, parkinson_HYBRID, heart_spectf_HYBRID)

# resultados = [ionosphere_BMB, ionosphere_ES, ionosphere_ILS, ionosphere_HYBRID, \
# parkinson_BMB, parkinson_ES, parkinson_ILS, parkinson_HYBRID, \
# heart_spectf_BMB, heart_spectf_ES, heart_spectf_ILS, heart_spectf_HYBRID]

# nombres = ['ionosphere_BMB', 'ionosphere_ES', 'ionosphere_ILS', 'ionosphere_HYBRID', \
# 'parkinson_BMB', 'parkinson_ES', 'parkinson_ILS', 'parkinson_HYBRID', \
# 'heartspectf_BMB', 'heartspectf_ES', 'heartspectf_ILS', 'heartspectf_HYBRID']

# 'Creating CSV files for making charts'
# print('Creando archivos .CSV')
# counter = 0
# for res in resultados:
#     create_csv(np.array(res), counter)
#     counter += 1

# convergencias = [ionosphere_convergence_BMB, ionosphere_convergence_ES, ionosphere_convergence_ILS, ionosphere_convergence_HYBRID]
# # parkinson_convergence_BMB, parkinson_convergence_ES, parkinson_convergence_ILS, parkinson_convergence_HYBRID,
# # heart_spectf_convergence_BMB, heart_spectf_convergence_ES, heart_spectf_convergence_ILS, heart_spectf_convergence_HYBRID]

# nombres = ['ionosphere_convergence_BMB', 'ionosphere_convergence_ES', 'ionosphere_convergence_ILS', 'ionosphere_convergence_HYBRID']

# # for i in range(len(convergencias)):
# #     dataset = pd.DataFrame({'Agr': convergencias[i], 'Algoritmo':nombres[i].split(sep='_')[2]})
# #     dataset.to_csv('Archivos_CSV/' + nombres[i])

# for i in range(len(convergencias)):
#     for j in range(5):
#         dataset = pd.DataFrame({'Agr': convergencias[i][j], 'Algoritmo':nombres[i].split(sep='_')[1], 'Particion': j})
#         dataset.to_csv('Archivos_CSV/' + nombres[i] + "_" + str(j))


import sys
# 좌표가 주어지고
# 주어진 좌표 중 현재 좌표보다 작은 좌표의 개수가 압축 좌표가 된다.

N = int(sys.stdin.readline())
data = list(map(int,sys.stdin.readline().split()))
# set을 이용해서 중복 데이터를 없앤다.
set_data = list(set(data))
set_data.sort()
result = {}
# 숫자의 인덱스 값을 딕셔너리에 같이 저장한다.
for i in range(len(set_data)):
    result[set_data[i]] = i
# 입력 숫자에 맞는 딕셔너리 값을 출력한다.
for i in data:
    print(result[i],end=' ')


from pyglet.sprite import Sprite
from create_window import scale_game, scale_menu
import resources, random, pyglet

score = None
player_health = []

def load(width, height, batch=None, front=None, back=None):
	global score, player_health
	player = Sprite(img=resources.player_image, x=width*1/3, y=height/2, batch=batch, group=front)
	player.velocity_y = 0
	player.velocity_x = 0
	player.rotation = 0
	creeps = loadcreeps(10, batch, front)
	grid = Sprite(img=resources.grid, x=-1000, y=width/2, batch=batch, group=back)
	grid.velocity_x = 0
	grid.velocity_y = 0
	score = pyglet.text.Label(text='0', font_name='Comic Sans',
		 font_size=50, x=20, y=20, batch=batch, group=front)
	if player_health == []:
		player_health = load_health(width, height, batch, front, back)
	return player, creeps, grid

def loadcreeps(num, batch=None, group=None):
	global creeps
	creeps = []
	for n in range(num):
		while True:
			x = random.randint(1000, 3000)
			y = random.randint(400, 500)
			creep = Sprite(img=resources.creep_image, x=x, y=y, batch=batch, group=group)
			creep.velocity_x = random.randint(-5, 5)
			creep.velocity_y = random.randint(-5, 5)
			creeps.append(creep)
			break
	return creeps

def load_health(width, height, batch=None, front=None, back=None):
	global player_health
	poop = 0
	health =Sprite(img=resources.health_bar, x=width, y=height)
	player_health.append(health)
	for j in range(3):
		poop += width/10
		health = Sprite(img=resources.health_bar, x=width*30/50 + poop, y=height*45/50, batch=batch, group=front)
		player_health.append(health)
	scale_menu(player_health, width)
	return player_health


import os
import errno
from flair.data_fetcher import NLPTaskDataFetcher
from flair.embeddings import WordEmbeddings, FlairEmbeddings, DocumentLSTMEmbeddings
from flair.models import TextClassifier
from flair.trainers import ModelTrainer
from pathlib import Path

DATA_DIRECTORY = './data'

TEN_PERCENT = 'ten_percent'
TEN_LINES = 'ten_lines'
ONE_LINE = 'one_line'

TARGET = TEN_PERCENT

def main():
    test_file = TARGET + '_tes.csv'
    dev_file = TARGET + '_val.csv'
    train_file = TARGET + '_tra.csv'

    corpus = NLPTaskDataFetcher.load_classification_corpus(Path(DATA_DIRECTORY), test_file=test_file, dev_file=dev_file,
                                                           train_file=train_file)
    word_embeddings = [WordEmbeddings('pl'), FlairEmbeddings('polish-forward'),
                       FlairEmbeddings('polish-backward')]
    document_embeddings = DocumentLSTMEmbeddings(word_embeddings, hidden_size=512, reproject_words=True,
                                                 reproject_words_dimension=256)
    classifier = TextClassifier(document_embeddings, label_dictionary=corpus.make_label_dictionary(), multi_label=False)
    trainer = ModelTrainer(classifier, corpus)
    trainer.train('./', max_epochs=10)

if __name__ == '__main__':
    main()


import time, os
import unittest
import HTMLTestRunner

now = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time()))
HtmlFile = "result\\" + now + "HTMLtemplate.html"

cases = []
for file_name in os.listdir(os.getcwd()+r"\testcase"):
    suite1 = unittest.TestLoader().loadTestsFromName('testcase'+'.'+file_name.split('.')[0])
    cases.append(suite1)
suite = unittest.TestSuite(cases)

with open(HtmlFile, "wb") as fp:
    runner = HTMLTestRunner.HTMLTestRunner(stream=fp,
                                           title=u"百度测试报告",
                                           description=u"用例测试情况"
                                           )
    runner.run(suite)
    exit(0)


from math import sqrt

def d(n):
    sum = 1
    t = sqrt(n)
    # only proper divisors; start from 2.
    for i in range(2, int(t)+1):
        if n % i == 0:
            sum += i + n / i
    # don't count the square root twice!
    if t == int(t):
        sum -= t
    return sum

limit = 20162
sum = 0
# it's a set, after all. sets are faster than lists for our needs.
abn = set()
for n in range(1, limit):
    if d(n) > n:
        abn.add(n)
    # if the difference of the number we're examining and every number in the set
    # is in the set, then the number is the sum of two abundant numbers.
    # otherwise, we must add it to our sum in question.
    if not any( (n-a in abn) for a in abn ):
        sum += n
print(sum)


import operator
from functools import reduce
from hero_guides.ability_build.ability_filtering import ability_filter
from hero_guides.ability_build.talent_levels import most_used_talents
from hero_guides.item_builds.filter_items import filter_items

from hero_guides.item_builds.starting_items import starting_items_filter
from helper_funcs.database.collection import all_items

def clean_strings(tup):
    spli = tup[0].split('__')
    return (spli, tup[1])

def update_build(hero: str, role: str, data: list):
    ret = {}
    combined_roles = ['Support', 'Roaming']
    filtered_data = [match for match in data if match['role'] ==
                     role or match['role'] in combined_roles and role in combined_roles]

    # filtered_data = list(data)

    starting_items = clean_strings(
        starting_items_filter(filtered_data, all_items, role))
    starting_items = [{f'item_{i}': item}
                      for i, item in enumerate(starting_items[0])]
    starting_items = reduce(operator.ior, starting_items, {})
    item_build = filter_items(filtered_data, all_items, starting_items)
    talents = most_used_talents(filtered_data, hero)
    talent_build = [{str((i+2) * 5): talent[0]} if int(talent[1]['level']) < (i+2) * 5 else {str(int((talent[1]['level']))): talent[0]}
                    for i, talent in enumerate(talents)]
    seen_levels = []
    for i, d in enumerate(talent_build):
        k = list(d.keys())[0]
        if k in seen_levels:
            new_key = str(int(k) + 1)
            d = {new_key: d[k]}
            talent_build[i] = d
        seen_levels.append(k)

    ability_build = ability_filter(filtered_data, talent_build)
    # ability_build = [{str(i+1): ability}
    #                  for i, ability in enumerate(ability_build[0])]
    talent_tooltips = [
        {talent[0]:f"Pick rate: {talent[1]['perc']}%"} for talent in talents]
    talent_tooltips = reduce(operator.ior, talent_tooltips, {})
    ability_build = ability_build
    ability_build = reduce(operator.ior, ability_build, {})
    ability_build = {'ability_build': ability_build,
                     'abilityTooltips': talent_tooltips}
    # pprint.pprint(item_build)
    return {'starting_items': starting_items, 'items': item_build,
            'abilities': ability_build}


'''
문제 조건
- 바로 앞번호 학생, 바로 뒷번호 학생에게만 체육복 빌려줄 수 있음
- 체육복을 적절히 빌려, 최대한 많은 학생이 체육 수업을 들어야 함

- n: 전체 학생수 (2<=n<=30)
- lost 배열: 도난단한 학생들 번호 (1<=len(lost)<=n)
- reserve: 여벌 체육복 있는 학생들 번호 (1<=len(reserve)<=n)

* 여벌 체육복 가져온 학생이 체육복을 도난 당할 수도 있다
   -> lost, reserve의 번호 중복 가능

solution 함수 작성
- 체육 수업 들을 수 있는 학생 최댓값 return

문제 해결 아이디어
1) 정렬
2) lost와 reserve 중복되는 것 먼저 제거
3) lost에 남은 학생 번호 -> reserve에서 빌려줄 수 있다면 제거

고려할점
- 최댓값을 구해야 하기 떄문에 정렬이 필수적이다.

'''

def solution():
  # 학생 번호 배열
  list = [i for i in range(N)]

  # reserve 값에 대한 0, 1값 (이미 빌려준 경우라면 1로 변경)
  flag = [0 for _ in range(N)]

  cnt = 0

  for n in list:
    # lost 배열에 포함되어 있는 경우라면
    if n+1 in lost:
      # reserve 배열에서 빌려줄 옆 학생이 있는지 확인
      # 앞번호 학생에게 받기
      if n in list and n in reserve and n not in lost:
        if flag[n]==0:
          flag[n] = 1
          cnt +=1
      # 다음 번호 학생에게 받기
      elif n+2 in list and n+2 in reserve and n+2 not in lost:
        if flag[n+2]==0:
          flag[n+2] = 1
          cnt+=1
    # lost와 reserve에 모두 포함된 학생 고려
    else:
      cnt+=1
  return cnt

N = int(input())
lost = list(map(int, input().split()))
reserve = list(map(int, input().split()))
print(solution())


import sys
import submodels_module as modelbank
import numpy as np
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
from scipy.stats import ttest_ind_from_stats as ttest
import load_format_data

def main():
    '''
    train a model if we only had sorted into 2 gates instead of 4
    '''

    a=int(sys.argv[1])
    if a<4:
        b=0
    elif a<8:
        a=a-4
        b=1
    elif a<12:
        a=a-8
        b=2
    else:
        print('incorrect toggle number')

    arch_list=['ridge','svm','forest','fnn']
    stringency_list= ['high','medium','low']

    mdl=modelbank.twogate_assay_to_yield_model([1,8,10],stringency_list[b],arch_list[a],1)
    mdl.cross_validate_model()
    mdl.limit_test_set([1,8,10])
    mdl.test_model()

    mdl=modelbank.seqandtwogateassay_to_yield_model([1,8,10],stringency_list[b],arch_list[a],1)
    mdl.cross_validate_model()
    mdl.limit_test_set([1,8,10])
    mdl.test_model()

# if __name__ == '__main__':
#     main()

arch_list=['ridge','svm','forest','fnn']
stringency_list= ['high','medium','low','4-gate']

loss_per_mdl,std_per_mdl=[],[]
for i in range (2):
    loss_per_str,std_per_str=[],[]
    for stringency in stringency_list:
        cv_loss,test_loss,test_std=np.inf,np.inf,0
        for arch in arch_list:
            if i==0:
                if stringency=='4-gate':
                    mdl=modelbank.assay_to_yield_model([1,8,10],arch,1)
                else:
                    mdl=modelbank.twogate_assay_to_yield_model([1,8,10],stringency,arch,1)
            else:
                if stringency=='4-gate':
                    mdl=modelbank.seqandassay_to_yield_model([1,8,10],arch,1)
                else:
                    mdl=modelbank.seqandtwogateassay_to_yield_model([1,8,10],stringency,arch,1)
            if mdl.model_stats['cv_avg_loss'] < cv_loss:
                cv_loss=mdl.model_stats['cv_avg_loss']
                test_loss=mdl.model_stats['test_avg_loss']
                test_std=mdl.model_stats['test_std_loss']
        loss_per_str.append(test_loss)
        std_per_str.append(test_std)
    loss_per_mdl.append(loss_per_str)
    std_per_mdl.append(std_per_str)

seq_model=modelbank.seq_to_yield_model('forest',1)
seq_loss=seq_model.model_stats['test_avg_loss']
seq_std=seq_model.model_stats['test_std_loss']
x=[-0.3,2.3]
seq_plus=[seq_loss+seq_std]*2
seq_min=[seq_loss-seq_std]*2

control_model=modelbank.control_to_yield_model('ridge',1)
control_loss=control_model.model_stats['test_avg_loss']
control_model.limit_test_set([1,8,10])
exploded_df,_,_=load_format_data.explode_yield(control_model.testing_df)
exp_var=np.average(np.square(np.array(exploded_df['y_std'])))

fig,ax=plt.subplots(1,1,figsize=[2,2],dpi=300)

xloc=[1.2,0.6,0,2]
ax.axhline(seq_loss,-0.5,4.5,color='green',linestyle='--',label='Sequence Model')
ax.axhline(control_loss,-0.5,2.5,color='red',linestyle='--',label='Control')
ax.axhline(exp_var,-0.5,2.5,color='purple',linestyle='--',label='Experimental')
ax.bar(np.subtract(xloc,0.075),loss_per_mdl[0],yerr=std_per_mdl[0],label='Assay',width=0.15,color='blue')
ax.bar(np.add(xloc,0.075),loss_per_mdl[1],yerr=std_per_mdl[1],label='Seq and Assay',width=0.15,color='orange')
ax.fill_between(x,seq_plus,seq_min,alpha=0.2,color='green')
ax.set_xticks(xloc)
ticklabels=['High','Medium','Low','4-Gate']
ax.set_xlabel('Sort Stringency',fontsize=6)
ax.set_xticklabels(ticklabels)

# ax.legend(fontsize=6)
ax.tick_params(axis='both', which='major', labelsize=6)
ax.set_ylabel('$Test^2$ Loss',fontsize=6)
ax.set_ylim([0.35,0.8])
ax.set_xlim([-0.3,2.3])

fig.tight_layout()
fig.savefig('./two_gate.png')
plt.close()


import numpy as np
import cv2
import imutils
from imutils import paths

cv2.namedWindow("Output",cv2.WINDOW_NORMAL)

print("[INFO] loading images...")
imagePaths = sorted(list(paths.list_images("Tests/C")))
images = []
# loop over the image paths, load each one, and add them to our
# images to stitch list
for imagePath in imagePaths:
	image = cv2.imread(imagePath)
	images.append(image)

print("[INFO] stitching images...")
stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()
(status, stitched) = stitcher.stitch(images)

if status == 0:
	# write the output stitched image to disk
	cv2.imwrite("Result/opencv_stitcher_result_C.jpg", stitched)
	# display the output stitched image to our screen
	cv2.imshow("Output", stitched)
	cv2.waitKey(0)
# otherwise the stitching failed, likely due to not enough keypoints)
# being detected
else:
	print("[INFO] image stitching failed ({})".format(status))


import random

logo = """
.d88b                          88888 8           w     8b  8                 8
8P www 8   8 .d88b d88b d88b     8   8d8b. .d88 w8ww   8Ybm8 8   8 8d8b.d8b. 88b. .d88b 8d8b
8b  d8 8b d8 8.dP' `Yb. `Yb.     8   8P Y8 8  8  8     8  "8 8b d8 8P Y8P Y8 8  8 8.dP' 8P
`Y88P' `Y8P8 `Y88P Y88P Y88P     8   8   8 `Y88  Y8P   8   8 `Y8P8 8   8   8 88P' `Y88P 8

 """

possible_numbers = []

for num in range (1, 101):
    possible_numbers.append(num)

def play():
    print(logo)
    end_of_game = False
    random_number = random.choice(possible_numbers)

    difficulty = input('I\'m thinking of a number between 1 and 100.\n\nTo choose a difficulty type either "easy" or "hard".\n').lower()

    if difficulty == 'easy':
        lives = 10
        print(f'You have {lives} attempts remaining to guess the number.\n')
    elif difficulty == 'hard':
        lives = 5
        print(f'You have {lives} attempts remaining to guess the number.\n')

    while not end_of_game:

        guess = int(input('Make a guess: \n'))

        if guess == random_number:
            print(f'You got it! The answer was {random_number}\n')
            end_of_game = True
        elif lives == 0:
            print('You\'ve run out of guesses. You lose!\n')
            end_of_game = True
        elif guess < random_number:
            lives -= 1
            print(f'Too low!\n\nYou have {lives} attempts remaining to guess the number.\n')
            if lives == 0:
                print(f'The number was {random_number}\n')
                end_of_game = True
        elif guess > random_number:
            lives -= 1
            print(f'Too high!\n\nYou have {lives} attempts remaining to guess the number.\n')
            if lives == 0:
                print(f'The number was {random_number}\n')
                end_of_game = True

    replay = input('Would you like to play a guessing game? Type "y" to play, type "n" otherwise.\n')
    if replay == 'y':
        play()
play()