#================================================#
# Program: Association Rule Mining using Apriori #
# Author: Md Mahbub Alam                         #
# Email: emahbub.cse@gmail.com                   #
#================================================#

columns = ['Outlook', 'Temperature', 'Humidity', 'Windy', 'PlayTennis']
columnValues = [['sunny', 'overcast', 'rain'],
		['hot', 'mild', 'cool'],
		['high', 'normal'],
		['TRUE', 'FALSE'],
		['P', 'N']]

#Read data from file and creates a 2D list of datasets
def ReadFromFile(fileName):
	try:
		in_file_ptr = open(fileName, 'r')
	except:
		print('\nThere is no file named \'' + fileName + '\', Please check the file path.\n')
	else:
		firstLine = in_file_ptr.readline().strip().split(',')
		dataLines = list()
		for line in in_file_ptr:
			dataLines.append(line.strip().split(','))
		in_file_ptr.close()
		return firstLine, dataLines
		#return dataLines

#Returns total number of tuples in a dataset
def ReturnNumberOfTuples(dataLines):
	count = 0
	for line in dataLines:
		count += 1
	return count

#Eliminate infrequent itemset by Minimum Support
def FilterWithMinSup(itemSet, minSup, numOfTuples):
	filterItems = list()
	for key, value in itemSet.items():
		if(round(float(value)/numOfTuples, 2) >= minSup):
			continue
		else:
			filterItems.append(key)
	for item in filterItems:
		del itemSet[item]
	return itemSet

#Generate first frequent itemset (frequent 1-itemset)
def GenerateFirstFreqItemset(dataLines, minSup, numOfTuples):
	itemSet = dict()
	for row in dataLines:
		for col in row:
			itemSet[str([col])] = itemSet.get(str([col]), 0) + 1
	itemSet = FilterWithMinSup(itemSet, minSup, numOfTuples)
	return itemSet

#Generate length-(k+1) candidate itemsets from length-k frequent itemsets
def Join(itemSetK, k):
	candidateSetK = list()
	for i in range(len(itemSetK)):
		for j in range(i+1, len(itemSetK)):
			iSet = list(itemSetK[i])[:k-2]
			jSet = list(itemSetK[j])[:k-2]
			if(iSet == jSet): #if first k-2 items are same
				candidateSetK.append(list(set(itemSetK[i]).union(itemSetK[j])))
	return candidateSetK

#return all subsets of a given set
def SubsetsAll(itemSet):
	if(itemSet == []):
		return [[]]
	subSet = SubsetsAll(itemSet[1:])
	return subSet + [[itemSet[0]] + item for item in subSet]

#return subsets of length-k for a given set
def SubsetsK(candSet, start, length, tempList):
	if(length == 0):
		return [tempList]
	else:
		subsetList = list()
		for i in range(start, len(candSet)):
			subsetList.extend(SubsetsK(candSet, i + 1, length - 1, tempList + [candSet[i]]))
		return subsetList

#Eliminate infrequent itemset by second apriori property
#the subsets of a frequent itemset must also be frequent
def Prune(candidateSetK, itemSetK, k):
	filterList = list()
	for candSet in candidateSetK:
		subsetList = SubsetsK(candSet, 0, k - 1, []) #create subset of length-k for a CandidateSet
		#check whether 'itemSetK' contains all the elements of a subset of length-K of a 'candidateSet'
		result =  all(item in itemSetK for item in subsetList)
		if(result):
			continue
		else:
			filterList.append(candSet)
	for item in filterList:
		candidateSetK.remove(item)

#Generate candidateSet of length-k+1 using join and prune operation
def GenerateCandidateSet(itemSetK, k):
	candidateSetK = Join(itemSetK, k) #create length-(k+1) candidate itemsets
	Prune(candidateSetK, itemSetK, k) #eliminate infrequent candidateSet
	return candidateSetK

#scan the dataset to eliminate infrequent itemset with minimum support
def FindFreqItemset(dataSets, itemSetK, minSup, numOfTuples):
	freqItemSetK = dict()
	for dataset in dataSets:
		for item in itemSetK:
			if(set(item).issubset(dataset)): #check whether a itemSet is subset of any sets in datasets
				freqItemSetK[str(item)] = freqItemSetK.get(str(item), 0) + 1
	freqItemSetK = FilterWithMinSup(freqItemSetK, minSup, numOfTuples)
	return freqItemSetK

#return k-th itemSet from frequentItemSet for next iteration
def ReturnCurrentItemSetK(freqItemsetK, itemSetK):
	itemSetK.clear()
	for key in freqItemsetK:
		itemSetK.append(eval(key))

#Apriori algorithm to generate frequent itemset
def Apriori(inputData, minSup, numOfTuples):
	#scan dataset once to get frequent 1-itemset
	freqItemsets = GenerateFirstFreqItemset(inputData, minSup, numOfTuples)

	itemSetK = list()
	ReturnCurrentItemSetK(freqItemsets, itemSetK) #frequent 1-itemset for subsequent iteration

	k = 1
	while(len(itemSetK) > 0):
		candidateSetK = GenerateCandidateSet(itemSetK, k + 1) #Generate length-(k+1) candidate itemsets from length-k frequent itemsets
		freqItemsetK = FindFreqItemset(inputData, candidateSetK, minSup, numOfTuples) #Test the candidates against dataset to find frequent (k+1)-itemsets
		ReturnCurrentItemSetK(freqItemsetK, itemSetK)
		freqItemsets.update(freqItemsetK) #update frequent itemsets
		k = k + 1
	return freqItemsets

#return column attribute of dataset for a value
def ReturnColumn(item):
	position = 0
	for colValue in columnValues:
		if item in colValue:
			return columns[position]
		else:
			position += 1

#return association rule as a string
def ReturnString(A, B):
	tempStr = '{'
	for item in A:
		tempStr += ReturnColumn(item) + '=' + item + ', '
	tempStr = tempStr[:-2]
	tempStr += '} => {'

	for item in B:
		tempStr += ReturnColumn(item) + '=' + item + ', '
	tempStr = tempStr[:-2]
	tempStr += '}'
	return tempStr

#Generate rules from frequent itemsets
def GenerateRules(freqItemsets, minConf, rules, numOfTuples):
	count = 0
	for key_AB, Sup_AB in freqItemsets.items(): #key==AB
		if(len(eval(key_AB)) > 1):
			subSets = SubsetsAll(eval(key_AB)) #retrieve all subsets of a set
			subSets = list(filter(None, subSets)) #remove empty set
			for A in subSets: #itemSet==A
				B = list(set(eval(key_AB)).difference(A)) #itemSet==B
				if(len(B) > 0):
					conf = Sup_AB/freqItemsets[str(A)] #conf = support(AB)/support(A)
					if(conf >= minConf):
						count += 1
						ruleStr = ReturnString(A, B) #return association rule as a string
						ruleStr = 'Rule#' + str(count) + ': ' + ruleStr
						ruleStr += '\n (Support=' + str(round(float(Sup_AB)/numOfTuples, 2)) + ', Confidence=' + str(round(conf, 2)) + ')'
						rules.append(ruleStr)

#Print generated rules
def PrintRules(rules, minSup, minConf):
	print('\nUser Input:')
	print(' Support: ' + str(minSup) + '\n Confidence: ' + str(minConf))
	print('\nRules:')
	for rule in rules: #writing association rules into a file 'Rules.txt'
		print(' ' + rule + '\n')

#Method for generating rules from a given dataset using Apriori
def RuleMining():
	print('\n')
	while(True):
		try:
			minSup = float(input('Enter the minimum support (fraction value): '))
			minConf = float(input('Enter the minimum confidence (fraction value): '))
		except:
			print('\nSupports only fraction value (float number) for minimum support and confidence!\n')
		else:
			if(minSup <= 0):
				continue

			if(minConf <= 0):
				continue

			#read data from file
			firstLine, dataLines = ReadFromFile('Play_Tennis_Data_Set.csv') #'Play_Tennis_Data_Set.csv'
			break

	numOfTuples = ReturnNumberOfTuples(dataLines)

	#Calling Apriori function to generate frequent itemsets
	freqItemsets = Apriori(dataLines, minSup, numOfTuples)

	#Method to generate rules from frequent itemsets
	rules = list()
	GenerateRules(freqItemsets, minConf, rules, numOfTuples)

	#write rules into a file named 'Rules.txt'
	PrintRules(rules, minSup, minConf)

	print('Thank you!.\n')

#main function
if __name__ == "__main__":
	RuleMining()


#!/usr/bin/python

import sys
import subprocess

#some colors
WARNING = '\033[93m'
MESSAGE_COLOR = '\033[96m'
OK = '\033[92m'
FAIL = '\033[91m'

diff_branch = sys.argv[1]
diff = subprocess.run(['git', 'diff', f'HEAD..{diff_branch}', '--numstat'], stdout=subprocess.PIPE)
diff = diff.stdout.decode('utf8')

diff_results = diff.splitlines()
processed_lines = []
changed_lines = 0;
for line in diff_results:
    processed_lines.append(line.strip().split())

for changed in processed_lines:
    changed_lines += int(changed[1])

print (MESSAGE_COLOR,'Total changed lines: ', changed_lines)

if changed_lines <= 200:
   print(OK, 'Your commits are S size')
elif changed_lines < 400:
   print(WARNING, 'Your commits are M size, do not exceed 400 lines')

if changed_lines > 400:
   print(FAIL, 'Your commits are L size, you are over the 400 lines change limit!')


from primaires.format.fonctions import supprimer_accents

# Aptitudes de matelots
NOMS_APTITUDES = {
        "calfeutrage": "charpenterie",
        "escrimeur": "escrimeur",
}

CLES_APTITUDES = {}
for cle, nom in NOMS_APTITUDES.items():
    CLES_APTITUDES[supprimer_accents(nom).lower()] = cle

# Niveaux
NIVEAU_MEDIOCRE = 0
NIVEAU_FAIBLE = 1
NIVEAU_MOYEN = 2
NIVEAU_BON = 3
NIVEAU_TRES_BON = 4
NIVEAU_EXCELLENT = 5

# Noms des niveaux
NOMS_NIVEAUX = {
        NIVEAU_MEDIOCRE: "médiocre",
        NIVEAU_FAIBLE: "peu expérimenté",
        NIVEAU_MOYEN: "assez expérimenté",
        NIVEAU_BON: "plutôt expérimenté",
        NIVEAU_TRES_BON: "très expérimenté",
        NIVEAU_EXCELLENT: "excellent",
}

VALEURS_NIVEAUX = {}
for nom, niveau in NOMS_NIVEAUX.items():
    VALEURS_NIVEAUX[supprimer_accents(niveau).lower()] = nom

# Talents
TALENTS = {
        "calfeutrage": ["calfeutrage"],
        "escrimeur": ["maniement_epee", "parade"],
}

CONNAISSANCES = {
        NIVEAU_MEDIOCRE: 10,
        NIVEAU_FAIBLE: 17,
        NIVEAU_MOYEN: 30,
        NIVEAU_BON: 50,
        NIVEAU_TRES_BON: 70,
        NIVEAU_EXCELLENT: 95,
}


#!/bin/env python3.9

import argparse
from os.path import dirname, join

from matplotlib import pyplot as plt
from matplotlib import use as use_backend
from pandas import DataFrame, read_pickle
from pyperclip import copy
from tqdm import tqdm

from shared import METHODS
from shared import DFLine, Metric, Status, iterate_matlab_folder, read_matlab

DATA_PATH = join(dirname(dirname(__file__)), 'data')
ANGLES = [20, 30, 60]

def extract_mse_dataframe():
    lines = []

    pbar = tqdm(iterate_matlab_folder(DATA_PATH))
    for record in pbar:
        pbar.set_description(f'Extracting MSE from "{record.filename}"')
        downsampled = record.downsampled(5)
        for line in downsampled.mse_lines():
            lines.append(line.df_row)

    df = DataFrame(
        lines,
        columns=DFLine.columns(Metric.MSE)
    )

    df.to_pickle(join(DATA_PATH, 'mse.pkl.xz'), compression='infer')

def extract_biomarkers_dataframes():
    peak_velocity_lines = []
    duration_lines = []
    latency_lines = []

    pbar = tqdm(iterate_matlab_folder(DATA_PATH))
    for record in pbar:
        pbar.set_description(f'Extracting biomarkers from "{record.filename}"')
        downsampled = record.downsampled(5)
        for line in downsampled.peak_velocity_lines():
            peak_velocity_lines.append(line.df_row)

        for line in downsampled.time_lines():
            if line.metric == Metric.Latency:
                latency_lines.append(line.df_row)
            elif line.metric == Metric.Duration:
                duration_lines.append(line.df_row)

    peak_velocity_df = DataFrame(
        peak_velocity_lines,
        columns=DFLine.columns(Metric.PeakVelocity)
    )

    peak_velocity_df.to_pickle(join(DATA_PATH, 'peak_velocities.pkl.xz'), compression='infer')

    latency_df = DataFrame(
        latency_lines,
        columns=DFLine.columns(Metric.Latency)
    )

    latency_df.to_pickle(join(DATA_PATH, 'latencies.pkl.xz'), compression='infer')

    durations_df = DataFrame(
        duration_lines,
        columns=DFLine.columns(Metric.Duration)
    )

    durations_df.to_pickle(join(DATA_PATH, 'durations.pkl.xz'), compression='infer')

def describe_data():
    saccades = []

    data = {
        status: {
            angle: 0
            for angle in ANGLES
        }
        for status in Status
    }

    pbar = tqdm(iterate_matlab_folder(DATA_PATH))
    for record in pbar:
        pbar.set_description(f'Processing {record.filename}')
        data[record.status][record.angle] += 1
        saccades.append(record.saccades_count)

    params = []
    total = 0
    for status in Status:
        status_total = 0
        for angle in ANGLES:
            current = data[status][angle]
            params.append(current)
            status_total += current
        params.append(status_total)
        total += status_total

    for angle in ANGLES:
        angle_total = 0
        for status in Status:
            angle_total += data[status][angle]
        params.append(angle_total)

    params.append(total)

    table = '''
\\begin{table}[h]
    \\centering
    \\begin{tabular}{rccccr}
        \\toprule
        \\textbf{Class} & $\\mathbf{20^\\circ}$ & $\\mathbf{30^\\circ}$ & $\\mathbf{60^\\circ}$ &
        \\textbf{Total}\\\\
        \\midrule
        \\textit{Healthy} & %d & %d & %d & %d\\\\
        \\textit{SCA2-Sick} & %d & %d & %d & %d\\\\
        \\midrule
        \\textit{Total} & %d & %d & %d & %d\\\\
        \\bottomrule
    \\end{tabular}
    \\caption{Records distribution\\label{tbl:records}}
\\end{table}
    ''' % tuple(params)

    copy(table)

    print(table)
    print()
    print(f'Saccades Count: {sum(saccades)}')

def exact_saccades_stats():
    saccades = []
    pbar = tqdm(iterate_matlab_folder(DATA_PATH))
    for record in pbar:
        pbar.set_description(f'Processing {record.filename}')

        downsampled = record.downsampled(5)

        for onset, offset in downsampled.saccades(downsampled.V0):
            saccades.append([
                downsampled.status.value,
                downsampled.angle,
                downsampled.noise,
                (offset - onset) * downsampled.h,
                max(abs(downsampled.V0[onset:offset]))
            ])

    saccades_df = DataFrame(
        saccades,
        columns=['Status', 'Angle', 'Noise', 'Duration', 'PeakVelocity']
    )

    saccades_df.to_pickle(join(DATA_PATH, 'exact_saccades.pkl.xz'), compression='infer')

    print('Job completed')

def figure_3cd_vs_5cd():
    use_backend('Qt5Agg')

    records = list(read_matlab('../data/RegScSimul20_1000_allNoisesDC_0.1_Enfermo.mat'))

    rec = records[0].downsampled(5)

    CD3 = rec.velocities('cd3')
    SNR5 = rec.velocities('snr5')

    plt.rcParams['figure.figsize'] = (8, 6)

    plt.subplot(3, 1, 1)
    plt.plot(rec.X, rec.Y)
    plt.title('Movement signal')
    plt.xlabel('Seconds (s)')
    plt.ylabel('Angle ($\circ$)')

    plt.subplot(3, 1, 2)
    plt.plot(rec.X, CD3)
    plt.title('Differentiated with 3 points central difference')
    plt.xlabel('Time (s)')
    plt.ylabel('Velocity ($\circ/s$)')

    plt.subplot(3, 1, 3)
    plt.plot(rec.X, SNR5)
    plt.title('Differentiated with 5 points central difference')
    plt.xlabel('Time (s)')
    plt.ylabel('Velocity ($\circ/s$)')

    plt.tight_layout()
    plt.savefig('../article/figures/3cd_vs_5cd.eps', format='eps')

    plt.show()

def figure_cd_vs_sl():
    use_backend('Qt5Agg')

    records = list(read_matlab('../data/RegScSimul20_1000_allNoisesDC_0.5_Sano.mat'))

    rec = records[0].downsampled(5)

    FROM_SAMPLE = 300
    TO_SAMPLE = 500
    X = rec.X[FROM_SAMPLE:TO_SAMPLE]
    V0 = rec.V0[FROM_SAMPLE:TO_SAMPLE]
    CD3 = rec.velocities('cd3')[FROM_SAMPLE:TO_SAMPLE]
    SL7 = rec.velocities('sl7')[FROM_SAMPLE:TO_SAMPLE]

    plt.rcParams['figure.figsize'] = (8, 6)

    plt.subplot(2, 1, 1)
    plt.plot(X, CD3, label='CD3 output')
    plt.plot(X, V0, label='Synthetic velocity')
    plt.title('Central Difference by 3 points')
    plt.xlabel('Time (s)')
    plt.ylabel('Velocity ($\circ/s$)')
    plt.ylim([-50, 350])
    plt.legend()

    plt.subplot(2, 1, 2)
    plt.plot(X, SL7, label='SL7 output')
    plt.plot(X, V0, label='Synthetic velocity')
    plt.title('Super Lanczos by 5 points')
    plt.xlabel('Time (s)')
    plt.ylabel('Velocity ($\circ/s$)')
    plt.ylim([-50, 350])
    plt.legend()

    plt.tight_layout()
    plt.savefig('../article/figures/cd_vs_sl.eps', format='eps')

    plt.show()

def detected_saccades_analysis():
    df_lines = []

    stats = {
        method: {
            'unidentified': 0,
            'overidentified': 0,
        }
        for method in METHODS.keys()
        if method not in {'cd3', 'cd5', 'cd7', 'cd9'}
    }

    pbar = tqdm(iterate_matlab_folder(DATA_PATH))
    for record in pbar:
        pbar.set_description(f'Processing {record.filename}')
        downsampled = record.downsampled(5)

        for line in downsampled.detected_saccades_lines():
            df_lines.append(line.df_row)

            if line.value < 0:
                stats[line.method]['unidentified'] += int(line.value)
            elif line.value > 0:
                stats[line.method]['overidentified'] += int(line.value)

    df = DataFrame(
        df_lines,
        columns=DFLine.columns(Metric.DetectedSaccades)
    )

    filename = 'detected_saccades.pkl.xz'
    df.to_pickle(
        join(DATA_PATH, filename),
        compression='infer'
    )

    print(f'Filename: "{filename}" generated')

    records = list(read_matlab('../data/RegScSimul20_1000_allNoisesDC_0.5_Enfermo.mat'))
    rec = records[0].downsampled(5)

    labels = []
    unidentified = []
    overidentified = []
    for method, m_stats in sorted(
        stats.items(),
        key=lambda x: abs(x[1]['unidentified']) + x[1]['overidentified']
    ):
        labels.append(method)
        unidentified.append(m_stats['unidentified'])
        overidentified.append(m_stats['overidentified'])

    plt.bar(labels, unidentified, label='Unidentified saccades')
    plt.bar(labels, overidentified, label='Overidentified saccades')
    plt.xlabel('Method')
    plt.ylabel('Amount of saccades')
    plt.legend()
    plt.title('Missidentified saccades')
    plt.tight_layout()

    plt.savefig('../article/figures/identified_saccades_errors.eps', format='eps')

    plt.show()

def biomarkers_boxplot():
    METHODS = ['l5', 'l7', 'l9', 'l11', 'l13', 'sl7', 'sl9', 'sl11', 'snr5', 'snr7', 'snr9', 'snr11']

    peak_velocities_df = read_pickle('../data/peak_velocities.pkl.xz')
    latencies_df = read_pickle('../data/latencies.pkl.xz')
    duration_df = read_pickle('../data/durations.pkl.xz')

    plt.rcParams['figure.figsize'] = (6, 10)

    peak_velocities, latencies, durations = [], [], []
    for method in METHODS:
        peak_velocities.append(peak_velocities_df[peak_velocities_df.Method == method]['PeakVelocity'].values)
        latencies.append(latencies_df[latencies_df.Method == method]['Latency'].values)
        durations.append(duration_df[duration_df.Method == method]['Duration'].values)

    plt.subplot(3, 1, 1)
    bp = plt.boxplot(peak_velocities, labels=METHODS, notch=True)
    plt.title('Peak Velocity')
    plt.ylabel('Error')
    plt.setp(bp['boxes'][7], color='blue')
    plt.setp(bp['fliers'][7], markeredgecolor='blue')

    plt.subplot(3, 1, 2)
    bp = plt.boxplot(latencies, labels=METHODS, notch=True)
    plt.title('Latency')
    plt.ylabel('Error')
    plt.setp(bp['boxes'][7], color='blue')
    plt.setp(bp['fliers'][7], markeredgecolor='blue')
    plt.setp(bp['boxes'][10], color='blue')
    plt.setp(bp['fliers'][10], markeredgecolor='blue')
    plt.setp(bp['boxes'][11], color='blue')
    plt.setp(bp['fliers'][11], markeredgecolor='blue')

    plt.subplot(3, 1, 3)
    bp = plt.boxplot(durations, labels=METHODS, notch=True)
    plt.title('Duration')
    plt.xlabel('Method')
    plt.ylabel('Error')
    plt.setp(bp['boxes'][2], color='blue')
    plt.setp(bp['fliers'][2], markeredgecolor='blue')
    plt.setp(bp['boxes'][3], color='blue')
    plt.setp(bp['fliers'][3], markeredgecolor='blue')

    plt.tight_layout()
    plt.savefig('../article/figures/biomarkers_boxplot.eps', format='eps')

    plt.show()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        prog='DiffExp',
        description='Differentiation Methods Selection Experiment'
    )
    parser.add_argument(
        '-mse --extract-mse-df',
        action='store_true',
        dest='extract_mse_dataframe',
        help='Extract MSE DataFrame'
    )

    parser.add_argument(
        '-bmk --extract-biomarkers-dataframes',
        action='store_true',
        dest='extract_biomarkers_dataframes',
        help='Generate all data frames'
    )
    parser.add_argument(
        '-dd --describe-data',
        action='store_true',
        dest='describe_data',
        help='Show data distribution stats'
    )
    parser.add_argument(
        '-ess --exact-saccades-stats',
        action='store_true',
        dest='exact_saccades_stats',
        help='Generate DataFrame with saccades reference stats'
    )

    parser.add_argument(
        '-f3v5cd --figure-3cd-vs-5cd',
        action='store_true',
        dest='figure_3cd_vs_5cd',
        help='Generate a figure showing the effects of central difference differentiation'
    )

    parser.add_argument(
        '-fcvs --figure-cd-vs-sl',
        action='store_true',
        dest='figure_cd_vs_sl',
        help='Generate a figure showing central difference vs super lanczos'
    )

    parser.add_argument(
        '-dsa --detected-saccades-analysis',
        action='store_true',
        dest='detected_saccades_analysis',
        help='Analyze detected saccades and make a bar plot'
    )

    parser.add_argument(
        '-bbp --biomarkers-box-plot',
        action='store_true',
        dest='biomarkers_boxplot',
        help='Show biomarkers calculation errors boxplot'
    )

    args = parser.parse_args()

    option_count = 0

    if args.extract_mse_dataframe:
        extract_mse_dataframe()
        option_count += 1

    if args.extract_biomarkers_dataframes:
        extract_biomarkers_dataframes()
        option_count += 1

    if args.describe_data:
        describe_data()
        option_count += 1

    if args.exact_saccades_stats:
        exact_saccades_stats()
        option_count += 1

    if args.figure_3cd_vs_5cd:
        figure_3cd_vs_5cd()
        option_count += 1

    if args.figure_cd_vs_sl:
        figure_cd_vs_sl()
        option_count += 1

    if args.detected_saccades_analysis:
        detected_saccades_analysis()
        option_count += 1

    if args.biomarkers_boxplot:
        biomarkers_boxplot()
        option_count += 1

    if option_count == 0:
        parser.print_help()


import yaml
from colorama import init, Fore
import secrets

def InitProjectMoldy():
    init(autoreset=True)
    packagename = input("What is the name of the Moldy package? ")
    authorpackage = input("What is the author of the Moldy package? ")
    versionpackage = input("What is the version of the Moldy package? ")
    hashofpackage = secrets.token_hex(nbytes=16)
    templateText = [
        {
            "package": [
                f"name: {packagename}",
                f"author: {authorpackage}",
                f"version: {versionpackage}",
                f"hash: {hashofpackage}",
            ]
        }
    ]
    try:
        with open("MoldySpecs.yaml", "w") as f:
            yaml.dump(templateText, f)

        print(Fore.CYAN + "Created the MoldySpecs.yaml file")
    except Exception as err:
        print(Fore.RED + "Error: " + err)


"""A board is a list of list of str. For example, the board
    ANTT
    XSOB
is represented as the list
    [['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']]

A word list is a list of str. For example, the list of words
    ANT
    BOX
    SOB
    TO
is represented as the list
    ['ANT', 'BOX', 'SOB', 'TO']
"""

def is_valid_word(wordlist, word):
    """ (list of str, str) -> bool

    Return True if and only if word is an element of wordlist.

    >>> is_valid_word(['ANT', 'BOX', 'SOB', 'TO'], 'TO')
    True
    >>> is_valid_word(['ANT', 'BOX', 'SOB', 'TO'], 'LONG')
    False
    >>> is_valid_word(['ANT', 'BOX', 'SOB', 'TO'], '')
    False
    """
    return word in wordlist

def make_str_from_row(board, row_index):
    """ (list of list of str, int) -> str

    Return the characters from the row of the board with index row_index
    as a single string.

    >>> make_str_from_row([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 0)
    'ANTT'
    >>> make_str_from_row([[]], 0)
    ''
    """

    row = ''
    for i in range(len(board[row_index])):
        row = row + board[row_index][i]

    return row

def make_str_from_column(board, column_index):
    """ (list of list of str, int) -> str

    Return the characters from the column of the board with index column_index
    as a single string.

    >>> make_str_from_column([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 1)
    'NS'
    >>> make_str_from_column([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 3)
    'TB'
    """

    column = ''
    for i in range(len(board)):
        column = column + board[i][column_index]

    return column

def board_contains_word_in_row(board, word):
    """ (list of list of str, str) -> bool

    Return True if and only if one or more of the rows of the board contains
    word.

    Precondition: board has at least one row and one column, and word is a
    valid word.

    >>> board_contains_word_in_row([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'SOB')
    True
    """

    for row_index in range(len(board)):
        if word in make_str_from_row(board, row_index):
            return True

    return False

def board_contains_word_in_column(board, word):
    """ (list of list of str, str) -> bool

    Return True if and only if one or more of the columns of the board
    contains word.

    Precondition: board has at least one row and one column, and word is a
    valid word.

    >>> board_contains_word_in_column([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'NO')
    False
    >>> board_contains_word_in_column([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'TO')
    True
    """

    for column_index in range(len(board[0])):
        if word in make_str_from_column(board, column_index):
            return True

    return False

def board_contains_word(board, word):
    """ (list of list of str, str) -> bool

    Return True if and only if word appears in board.

    Precondition: board has at least one row and one column.

    >>> board_contains_word([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'ANT')
    True
    >>> board_contains_word([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'TO')
    True
    >>> board_contains_word([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], 'FROM')
    False
    >>> board_contains_word([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], '')
    False
    """

    # check whether word is not empty, because I miss the precondition word is a valid word
    if word == '':
        return False

    return board_contains_word_in_row(board, word) or board_contains_word_in_column(board, word)

def word_score(word):
    """ (str) -> int

    Return the point value the word earns.

    Word length: < 3: 0 points
                 3-6: 1 point per character for all characters in word
                 7-9: 2 points per character for all characters in word
                 10+: 3 points per character for all characters in word

    >>> word_score('DRUDGERY')
    16
    >>> word_score('TO')
    0
    >>> word_score('FLUKE')
    5
    >>> word_score('FORCEFULLY')
    30
    """
    word_length = len(word)

    if word_length < 3:
        points = 0
    elif word_length <= 6:
        points = word_length
    elif word_length <= 9:
        points = word_length * 2
    else:
        points = word_length * 3

    return points

def update_score(player_info, word):
    """ ([str, int] list, str) -> NoneType

    player_info is a list with the player's name and score. Update player_info
    by adding the point value word earns to the player's score.

    >>> update_score(['Jonathan', 4], 'ANT')
    """
    player_info[1] = player_info[1] + word_score(word)

def num_words_on_board(board, words):
    """ (list of list of str, list of str) -> int

    Return how many words appear on board.

    >>> num_words_on_board([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], ['ANT', 'BOX', 'SOB', 'TO'])
    3
    >>> num_words_on_board([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], [''])
    0
    >>> num_words_on_board([['A', 'N', 'T', 'T'], ['X', 'S', 'O', 'B']], ['BOS'])
    0
    """
    num_on_board = 0

    for word in words:
        if board_contains_word(board, word):
            num_on_board += 1

    return num_on_board

def read_words(words_file):
    """ (file open for reading) -> list of str

    Return a list of all words (with newlines removed) from open file
    words_file.

    Precondition: Each line of the file contains a word in uppercase characters
    from the standard English alphabet.
    """

    words = []
    for line in words_file:
        words.append(line.strip())

    return words

def read_board(board_file):
    """ (file open for reading) -> list of list of str

    Return a board read from open file board_file. The board file will contain
    one row of the board per line. Newlines are not included in the board.
    """
    board = []
    for line in board_file:
        row_list = []
        # print(line)
        word = line.strip()
        for char in word:
            row_list.append(char)
        board.append(row_list)

    return board


import re
import json

# 1
with open('phonebook.txt', 'x+', encoding='utf-8') as phone1:
    try:
        phone_book = json.load(phone1)
    except Exception:
        phone_book = {}

while True:
    commands = input('Write command:\n')
    if commands == 'stats':
        print(f'Amount of records is {len(phone_book)}')
    elif commands == 'list':
        print(*phone_book.keys(), sep='\n')
    elif commands in ['delete', 'show']:
        name = input('Write name:\n')
        if commands == 'delete' and name in phone_book.keys():
            del phone_book[name]
            with open('phonebook.txt', 'w') as ph:
                json.dump(phone_book, ph)
                print(f'Record with name "{name}" was successfully deleted')
        elif commands == 'show' and name in phone_book.keys():
            print(f'Here you could see the info for "{name}": {phone_book[name]}')
        else:
            print(f'There is no such name as {name} in phone book. Firstly, you need to add it!')
    elif commands == 'add':
        new_name, phone = input('Provide, please, name and phone:\n').split()
        if new_name in phone_book.keys():
            print(f'Record with {new_name} already exists. Please remove it and add a new one after that')
        else:
            if re.match(r'\A(\+380|380|0)[0-9]{9}\b', phone):
                with open('phonebook.txt', 'w') as ph:
                    phone_book[new_name] = phone
                    json.dump(phone_book, ph)
                    print(f'Contact "{new_name}" was created in the phone book!')
            else:
                print('This phone number is not valid')
    elif commands == 'end':
        print('Thanks for your records. Buy!')
        break
    else:
        print(f'There is no such command as "{commands}". Please, try again')

# 2
file1 = input('Enter file name\n')
with open(file1, 'r', encoding='utf-8') as file2:
    info1 = file2.readlines()
    for i in info1:
        print(re.sub(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', '*@*', i), end='')

# 3
file3 = input('Enter file name\n')
with open(file3, 'r', encoding='utf-8') as file4:
    info2 = file4.readlines()
    for i in info2:
        print(re.sub(r'([a-zA-z])([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]+)([a-zA-z])',
                     r'\1****@****\3', i), end='')


import os
import os.path as osp
import numpy as np
import sys
import torch
import torch.nn as nn
import torch.backends.cudnn as cudnn
from utils import pose_utils
from utils.loss import GANLoss, PixelWiseBCELoss, PixelSoftmaxLoss, VGGLoss, NNLoss, NewL1Loss, TVLoss
from abc import ABC, abstractmethod
import datetime
from torch.optim import lr_scheduler
import time

class BaseModel(ABC):
    def name(self):
        return 'BaseModel'

    def __init__(self, opt):
        super(BaseModel, self).__init__()
        self.opt = opt
        cudnn.enabled = True
        cudnn.benchmark = True
        # define loss
        self.criterionGAN = GANLoss(opt.gan_mode).cuda()
        self.criterionL1 = torch.nn.L1Loss().cuda()
        self.criterion_newL1 = NewL1Loss()
        self.criterion_smooth_L1 = torch.nn.SmoothL1Loss()
        self.criterion_vgg = VGGLoss("vgg_model/vgg19-dcbb9e9d.pth").cuda()
        self.weight = np.array([0.03] * 2 + [0.08] * 1 + [0.03] * 2 + [0.08] * 3 + [0.03] * 5 + [0.08] * 5 + [0.05] * 2)
        self.weight = torch.Tensor(self.weight).cuda()
        self.criterionBCE_re = PixelSoftmaxLoss(self.weight).cuda()
        self.criterion_tv = TVLoss()
        # log dir
        if opt.joint_all:
            self.save_dir = os.path.join('net_model', 'joint_checkpoint', opt.suffix)
        else:
            self.save_dir = os.path.join('net_model', opt.train_mode + '_checkpoint', opt.suffix)
        self.date_suffix = self.dt()
        self.log_dir = os.path.join(self.save_dir, 'logs')

        self.log_name = os.path.join(self.log_dir, 'train_log_%s_%s.log'%(opt.suffix, self.date_suffix))
        self.vis_path = os.path.join(self.save_dir, 'imgs')

        if not os.path.exists(self.vis_path):
            os.makedirs(self.vis_path)
        if not os.path.exists(self.log_dir):
            os.makedirs(self.log_dir)

        with open(os.path.join(self.log_name), 'a') as log_file:
            now = time.strftime("%c")
            log_file.write('================ Training Loss (%s) ================\n' % now)

    def dt(self):
        return datetime.datetime.now().strftime("%m-%d-%H")

    def update_learning_rate(self, opt, optimizer, epoch):
        base_lr = opt.lr
        lr = base_lr
        if epoch > 30:
            lr = base_lr * (1 - base_lr/opt.decay_iters)
        if isinstance(optimizer, list):
            for _ in optimizer:
                for param_group in _.param_groups:
                    param_group['lr'] = lr
        else:
            for param_group in optimizer.param_groups:
                param_group['lr'] = lr

        # TO DO
        # if epoch <= 4:
        #     lr = base_lr
        # elif epoch > 24:
        #     lr = 2e-4 * (1 - (epoch-24) / 10)
        # else:
        #     lr = self.get_learning_rate(optimizer)
        #     if lr <= 2e-4:
        #         lr = 2e-4
        #     else:
        #         lr = base_lr - (base_lr - 2e-4) * (epoch - 4) / 15

        # for scheduler in self.get_scheduler(optimizer, opt):
        #     scheduler.step()

    def get_learning_rate(self, optimizer):
        lr = []
        if not isinstance(optimizer, list):
            for param_group in optimizer.param_groups:
                lr += [param_group['lr']]
        else:
            for _ in optimizer:
                for param_group in _.param_groups:
                    lr += [param_group['lr']]
        return lr[0]

    def set_requires_grad(self, nets, requires_grad=True):
        if not isinstance(nets, list):
            nets = [nets]
        for net in nets:
            if net is not None:
                for param in net.parameters():
                    param.requires_grad = requires_grad

    def adjust_fade_in_alpha(self, epoch):
        alpha = list(np.arange(0.6, 1.2, 0.2))
        if epoch < 6:
            fade_in_alpha = alpha[epoch // 2]
        else:
            fade_in_alpha = 1

        return int(fade_in_alpha)

    def load_network(self, network, save_path, ifprint=False):
        if ifprint:
            print(network)
        try:
            network.load_state_dict(torch.load(save_path))
        except:
            pretrained_dict = torch.load(save_path)
            model_dict = network.state_dict()
            try:
                pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
                network.load_state_dict(pretrained_dict)
            except:
                print('Pretrained network %s has fewer layers; The following are not initialized:')
                for k, v in pretrained_dict.items():
                    if v.size() == model_dict[k].size():
                        model_dict[k] = v
                        print(k)
                if sys.version_info >= (3,0):
                    not_initialized = set()
                else:
                    from sets import Set
                    not_initialized = Set()

                for k, v in model_dict.items():
                    if k not in pretrained_dict or v.size() != pretrained_dict[k].size():
                        not_initialized.add(k.split('.')[0])

                print(sorted(not_initialized))
                network.load_state_dict(model_dict)

    def print_loss(self, opt):
        pass

    def get_scheduler(self, optimizer, opt):

        if opt.lr_policy == 'linear':
            def lambda_rule(epoch):
                lr_l = 1.0 - max(0, epoch + opt.epoch_count - opt.niter) / float(opt.niter_decay + 1)
                return lr_l
            scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda_rule)
        elif opt.lr_policy == 'step':
            scheduler = lr_scheduler.StepLR(optimizer, step_size=opt.lr_decay_iters, gamma=0.1)
        elif opt.lr_policy == 'plateau':
            scheduler = lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.2, threshold=0.01, patience=5)
        elif opt.lr_policy == 'cosine':
            scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=opt.niter, eta_min=0)
        else:
            return NotImplementedError('learning rate policy [%s] is not implemented', opt.lr_policy)
        return scheduler

        # errors: same format as |errors| of plotCurrentErrors


import numpy as np
from .base import Base

class iSLSBase(Base):
    def __init__(self, x_dim, u_dim, N):
        super().__init__(x_dim, u_dim ,N)
        self._forward_model = None
        self._cost_function = None

        nb_max_iterations_line_search = 50
        self.alphas = 10.**np.linspace(0., -5., nb_max_iterations_line_search)

        self._cost = None
        self._cur_decrease_cost = 1e5
        self.x_nom = None
        self.u_nom = None

        self.x_nom_log = []
        self.u_nom_log = []

        self._K = None
        self._k = None

        self.cost_log = []

    #################################### AT OPTIMALITY, RUN THESE ################################

    def get_trajectory_sls(self, x0, K, k, noise_scale=0):
        batch_size = x0.shape[0] if x0.ndim == 2 else 1
        u_log = np.zeros((batch_size, self.N, self.u_dim))
        x_log = np.zeros((batch_size, self.N+1, self.x_dim))
        x_log[:, 0] = x0
        x_vec = np.zeros((batch_size, self.N * self.x_dim))
        for i in range(self.N):
            x_vec[:, i * self.x_dim:(i + 1) * self.x_dim] = x_log[:, i] - self.x_nom[i]
            u_log[:, i] = (x_vec @ K.T + k)[:, i * self.u_dim:(i + 1) * self.u_dim] + self.u_nom[i]
            w = np.random.normal(loc=0, scale=noise_scale, size=x0.shape)
            x_log[:, i+1] = self.forward_model(x_log[:, i], u_log[:, i]) + w
        if x0.ndim == 2:
            return x_log[0, :-1], u_log[0]
        else:
            return x_log[:, :-1], u_log

    def get_trajectory_batch(self, x0, us, noise_scale=0):
        batch_size = x0.shape[0] if x0.ndim == 2 else 1
        u_log = np.zeros((batch_size, self.N, self.u_dim))
        x_log = np.zeros((batch_size, self.N+1, self.x_dim))
        x_log[:, 0] = x0
        for i in range(self.N):
            u_log[:, i] = us[i]
            w = np.random.normal(loc=0, scale=noise_scale, size=x0.shape)
            x_log[:, i + 1] = self.forward_model(x_log[:, i], u_log[:, i]) + w

        if x0.ndim == 1:
            return x_log[0, :-1], u_log[0]
        else:
            return x_log[:, :-1], u_log

    def get_trajectory_dp(self, x0, K, k, noise_scale=0):
        batch_size = x0.shape[0] if x0.ndim == 2 else 1
        u_log = np.zeros((batch_size, self.N, self.u_dim))
        x_log = np.zeros((batch_size, self.N+1, self.x_dim))
        x_log[:, 0] = x0
        for i in range(self.N):
            u_log[:, i] = x_log[:, i].dot(K[i].T) + k[i]
            w = np.random.normal(loc=0, scale=noise_scale, size=x0.shape)
            x_log[:, i+1] = self.forward_model(x_log[:, i], u_log[:, i]) + w
        if x0.ndim == 2:
            return x_log[0, :-1], u_log[0]
        else:
            return x_log[:, :-1], u_log

    ############################## Setter and Getters ################################
    @property
    def nominal_values(self):
        return self._x_nom, self._u_nom

    @nominal_values.setter
    def nominal_values(self, value):
        self.x_nom = value[0]
        self.u_nom = value[1]
        self.cost = self.cost_function(self.x_nom, self.u_nom)
        self.cost_log += [self.cost]
        # self.x_nom_log.append(value[0])
        # self.u_nom_log.append(value[1])

    @property
    def K(self):
        return self._K

    @property
    def k(self):
        return self._k

    @property
    def cost(self):
        return self._cost

    @cost.setter
    def cost(self, value):
        self._cost = value

    @property
    def forward_model(self):
        return self._forward_model

    @forward_model.setter
    def forward_model(self, function):
        self._forward_model = function

    @property
    def cost_function(self):
        if self._cost_function is None:
            self._cost_function = self.compute_cost
        return self._cost_function

    @cost_function.setter
    def cost_function(self, function):
        """

        Parameters
        ----------
        function :

        Returns
        -------

        """
        self._cost_function = function

    @property
    def AB(self):
        return [self.A, self.B]

    @AB.setter
    def AB(self, value):
        """
        Sets or updates the values of A, B, C and D matrices. We define $C = (I-ZA_d)^{-1}$ and $D = CZB_d$

        Parameters
        ----------
        value : a list of A and B [A,B]
                A is a 3D tensor of [N, x_dim, x_dim]
                B is a 3D tensor of [N, x_dim, u_dim]
        Returns
        -------
        None
        """
        self.A, self.B = value[0], value[1]
        for i in range(self.N - 1, 0, -1):
            self.D[i * self.x_dim:, (i - 1) * self.u_dim:i * self.u_dim] = \
                self.C[i * self.x_dim:, i * self.x_dim:(i + 1) * self.x_dim] @ self.B[i-1]

            self.C[i * self.x_dim:, (i - 1) * self.x_dim:i * self.x_dim] = \
                self.C[i * self.x_dim:, i * self.x_dim:(i + 1) * self.x_dim] @ self.A[i-1]

    def reset(self):
        self.PHI_U = np.zeros((self.N * self.u_dim, self.N * self.x_dim))
        self.PHI_X = None
        self.du = None
        self.dx = None

        self._cur_cost = None
        self._x_nom = None
        self._u_nom = None
        self.x_nom_log = []
        self.u_nom_log = []

        self._K = None
        self._k = None

        self.cost_log = []

        # self.cost_function


# Heat - food conflict
from turtle import pos
import numpy as np
import matplotlib.pyplot as plt
import simulator4c as sm
from models import *
from fold2m import *

h = 0.005
model = sm.Model(h)
# Parameters
# The values are choosen so that the agent is in deficit
model.a1 = 2.0
model.a2 = 2.0
model.b1 = 5.0
model.b2 = 5.0
model.sigma = 10.0
model.epsilon = 0.005

world = sm.World(h)
experiment = sm.Experiment( model, world, h )

Npos = 50
positions = np.linspace(0.8, 2.0, Npos)
lifespans = np.zeros_like(positions)
T = 300000
Ypos = np.zeros((Npos, T))

doExp = False

if doExp:

    for i in range(len(positions)):

        experiment.world.food = -positions[i]
        experiment.world.water = positions[i]
        x0 = [1.0, 0.0, -1.0]

        t, X, pos = experiment.run( x0, T )

        Xm = X[2,:]
        life = np.where(np.abs(Xm) > 0.1 )
        print("i = %d"%i)
        lifespans[i] = life[0][-1]
        Ypos[i, :] = pos

    np.save("lifespans.npy", lifespans)
    np.save("Ypos.npy", Ypos)
else:
    lifespans = np.load("lifespans.npy")
    Ypos = np.load("Ypos.npy")
    print(Ypos.shape)
fig = plt.figure()
plt.plot(2*positions, lifespans/float(T), linewidth = 2.5)
plt.xlabel("Separation")
plt.ylabel("Lifespan")

fig = plt.figure()
H = np.zeros((Npos, 60))

for i in range(Npos):
    counts, bins, patches = plt.hist(Ypos[i, :], 60, density=True)
    H[i,:] = counts
plt.imshow(H)
plt.show()


import csv
import os
from pathlib import Path
import time

###### This is an edit of the program CAIFinder.py #######

# The purpose of this file is to go through a file containing gene segments
# which are under investigation, to count the number of codons in each segment,
# and to then print out the relative adaptedness numbers corresponding with
# each codon in that virus species

# Here we open the file where our gene segments are stored for analysis and
# label the UID, Species, Gene name and Sequence so that we can call on them as variables
# later in the script. The gene sequence that is needed is the section of overlapping gene
# from each gene pair, trimmed so that it's in the reading frame of the gene
# it's associated with

#GeneRelativeAdaptedness = []

GenesFile = 'OverlappingVirusGenes.txt'
RelativeAdaptednessFile = 'VirusCodonBias.txt'
AncestralOutputFile = Path('./Ancestral.txt')
NovelOutputFile = Path('./Novel.txt')

if AncestralOutputFile.is_file():
    os.remove('%s'%AncestralOutputFile)
if NovelOutputFile.is_file():
    os.remove('%s'%NovelOutputFile)
time.sleep(0.5)

#########################################################################################################
#########################################################################################################
#########################################################################################################

with open('%s' %GenesFile, 'r') as f:
    reader = csv.reader(f, delimiter = '\t')
    for row in reader:
        UID = row[0]
        PairUID = row[1]
        Species = row[2]
        GeneName = row[3]
        GeneDesignation = row[4]
        Sequence = row[5]

        # Dictionaries are created where we can call on the data which pertain to the codons
        # under analysis. Each dictionary is of the same form and contains a number which
        # is used as a reference as the first entry in every sublist. This number can
        # be used later to navigate between dictionaries to group data pertaining to a particular
        # codon.

        CodonIndex = [[0,'TTT','TTC'],[1,'TTA','TTG','CTT','CTC','CTA','CTG'],[2,'ATT','ATC','ATA'],[3,'ATG'],[4,'GTT','GTC','GTA','GTG'],[5,'TCT','TCC','TCA','TCG'],[6,'CCT','CCC','CCA','CCG'],[7,'ACT','ACC','ACA','ACG'],[8,'GCT','GCC','GCA','GCG'],[9,'TAT','TAC'],[10,'TAA','TAG','TGA'],[11,'CAT','CAC'],[12,'CAA','CAG'],[13,'AAT','AAC'],[14,'AAA','AAG'],[15,'GAT','GAC'],[16,'GAA','GAG'],[17,'TGT','TGC'],[18,'TGG'],[19,'CGT','CGC','CGA','CGG','AGA','AGG'],[20,'AGT','AGC'],[21,'GGT','GGC','GGA','GGG']]

        CodonCount = [[0,0,0],[1,0,0,0,0,0,0],[2,0,0,0],[3,0],[4,0,0,0,0],[5,0,0,0,0],[6,0,0,0,0],[7,0,0,0,0],[8,0,0,0,0],[9,0,0],[10,0,0,0],[11,0,0],[12,0,0],[13,0,0],[14,0,0],[15,0,0],[16,0,0],[17,0,0],[18,0],[19,0,0,0,0,0,0],[20,0,0],[21,0,0,0,0]]

        RelativeAdaptedness =[[0,0,0],[1,0,0,0,0,0,0],[2,0,0,0],[3,0],[4,0,0,0,0],[5,0,0,0,0],[6,0,0,0,0],[7,0,0,0,0],[8,0,0,0,0],[9,0,0],[10,0,0,0],[11,0,0],[12,0,0],[13,0,0],[14,0,0],[15,0,0],[16,0,0],[17,0,0],[18,0],[19,0,0,0,0,0,0],[20,0,0],[21,0,0,0,0]]

        Index = ['Phe','Leu','Ile','Met','Val','Ser','Pro','Thr','Ala','Tyr','Stop','His','Gln','Asn','Lys','Asp','Glu','Cys','Trp','Arg','Ser','Gly']

        # The goal of the program is to now go through the sequences which need analyzing
        # and to count the number of codons of each type. First a counting variable is
        # defined "TotalCodonCount",
        TotalCodonCount = 0
        Sequence1Length = int(len(Sequence))
        Sequence1CodonNumber = int(Sequence1Length)

        # A for loop is created which goes through the nucleotide sequence under investigation
        # in groups of 3. The codon is cross-referenced with the dictionary above and 1 is added
        # to the value in the dictionary CodonCount in the same location. In this manner, each
        # type of codon is counted.
        for n in range(0,Sequence1CodonNumber,3):
            TotalCodonCount += 1
            codon = Sequence[n:n+3]
            for entry in CodonIndex:
                if codon in entry:
                    if codon == 'ATG':
                        pass
                    else:
                        if codon == 'TGG':
                            pass
                        else:
                            external_index = CodonIndex.index(entry)
                            internal_index = entry.index(codon)
                            CodonCount[external_index][internal_index]=CodonCount[external_index][internal_index]+1

        # Now the program opens the file which contains all the relative adaptedness
        # data points which were generated from the online database numbers. The loop goes through
        # and finds the relative adaptedness values which pertain to the virus species in question
        # and labels all of the values with the codon which they correspond to.

        with open('%s' %RelativeAdaptednessFile, 'r') as f:
            reader = csv.reader(f, delimiter = '\t')
            for row in reader:
                UID = row[0]
                VirusName = row[1]
                Designation = row[2]
                if VirusName != Species:
                    pass
                else:
                    if Designation != 'RelativeAdapted':
                        pass
                    else:
                        UUU = float(row[3])
                        UUC = float(row[4])
                        UUA = float(row[5])
                        UUG = float(row[6])
                        UCU = float(row[7])
                        UCC = float(row[8])
                        UCA = float(row[9])
                        UCG = float(row[10])
                        UAU = float(row[11])
                        UAC = float(row[12])
                        UAA = float(row[13])
                        UAG = float(row[14])
                        UGU = float(row[15])
                        UGC = float(row[16])
                        UGA = float(row[17])
                        UGG = float(row[18])
                        CUU = float(row[19])
                        CUC = float(row[20])
                        CUA = float(row[21])
                        CUG = float(row[22])
                        CCU = float(row[23])
                        CCC = float(row[24])
                        CCA = float(row[25])
                        CCG = float(row[26])
                        CAU = float(row[27])
                        CAC = float(row[28])
                        CAA = float(row[29])
                        CAG = float(row[30])
                        CGU = float(row[31])
                        CGC = float(row[32])
                        CGA = float(row[33])
                        CGG = float(row[34])
                        AUU = float(row[35])
                        AUC = float(row[36])
                        AUA = float(row[37])
                        AUG = float(row[38])
                        ACU = float(row[39])
                        ACC = float(row[40])
                        ACA = float(row[41])
                        ACG = float(row[42])
                        AAU = float(row[43])
                        AAC = float(row[44])
                        AAA = float(row[45])
                        AAG = float(row[46])
                        AGU = float(row[47])
                        AGC = float(row[48])
                        AGA = float(row[49])
                        AGG = float(row[50])
                        GUU = float(row[51])
                        GUC = float(row[52])
                        GUA = float(row[53])
                        GUG = float(row[54])
                        GCU = float(row[55])
                        GCC = float(row[56])
                        GCA = float(row[57])
                        GCG = float(row[58])
                        GAU = float(row[59])
                        GAC = float(row[60])
                        GAA = float(row[61])
                        GAG = float(row[62])
                        GGU = float(row[63])
                        GGC = float(row[64])
                        GGA = float(row[65])
                        GGG = float(row[66])

                        # Once all the of the relative adaptedness values are found and
                        # labeled, they are placed into a dictionary in the same form as
                        # the dictionaries above.
                        RelativeAdaptedness = [[0,UUU,UUC],[1,UUA,UUG,CUU,CUC,CUA,CUG],[2,AUU,AUC,AUA],[3,AUG],[4,GUU,GUC,GUA,GUG],[5,UCU,UCC,UCA,UCG],[6,CCU,CCC,CCA,CCG],[7,ACU,ACC,ACA,ACG],[8,GCU,GCC,GCA,GCG],[9,UAU,UAC],[10,UAA,UAG,UGA],[11,CAU,CAC],[12,CAA,CAG],[13,AAU,AAC],[14,AAA,AAG],[15,GAU,GAC],[16,GAA,GAG],[17,UGU,UGC],[18,UGG],[19,CGU,CGC,CGA,CGG,AGA,AGG],[20,AGU,AGC],[21,GGU,GGC,GGA,GGG]]

                        RelativeAdaptednessOverall = []
                        GeneRelativeAdaptedness = []

                        numberCount = 0
                        for entry in RelativeAdaptedness:
                            CountIndex = entry[0]
                            entry = entry[1:]
                            for item in entry:
                                numberOfCodons = CodonCount[CountIndex][entry.index(item)+1]
                                if item == 0.0:
                                    item = 0.5
                                if numberOfCodons == 0:
                                    pass
                                else:
                                    for integer in range(numberOfCodons):
                                        GeneRelativeAdaptedness.append(item)

                        output_preliminary = [UID,PairUID,Species,GeneName]
                        GeneRelativeAdaptedness = [str(x) for x in GeneRelativeAdaptedness]
                        output = output_preliminary + GeneRelativeAdaptedness

                        if GeneDesignation == 'Novel':
                            NovelFileOutput = open('%s'%NovelOutputFile, 'a')
                            NovelFileOutput.write('\t'.join(output[0:]) + '\n')
                            NovelFileOutput.close()
                        elif GeneDesignation == 'Ancestral':
                            AncestralFileOutput = open('%s'%AncestralOutputFile, 'a')
                            AncestralFileOutput.write('\t'.join(output[0:]) + '\n')
                            AncestralFileOutput.close()


class Solution:
    def fractionToDecimal(self, numerator: int, denominator: int) -> str:
        sign = '-' if numerator * denominator < 0 else ''
        numerator, denominator = abs(numerator), abs(denominator)
        integer, mod = divmod(numerator, denominator)
        integer = str(integer)

        fracdict = {}
        fraction = ''
        i = 0
        while mod > 0:
            if mod in fracdict:
                fraction = fraction[:fracdict[mod]] + '(' + fraction[fracdict[mod]:] + ')'
                break
            else:
                fracdict[mod] = i
                div, mod = divmod(mod*10, denominator)
                fraction += str(div)
                i += 1

        return sign + integer + ('.' if fraction else '') + fraction


#!/usr/bin/env python3

from gzip import open
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score

from sklearn.feature_extraction.text import CountVectorizer

def spam_detection(random_state=0, fraction=1.0):
    #following lines are for reading data
    list_ham = None
    list_spam = None
    ham_file = 'src/ham.txt.gz'
    spam_file = 'src/spam.txt.gz'
    with open(ham_file) as ham_data:
        list_ham = ham_data.readlines()
        num_lines = int(fraction * len(list_ham))
        list_ham = list_ham[:num_lines]
    with open(spam_file) as spam_data:
        list_spam = spam_data.readlines()
        num_lines = int(fraction * len(list_spam))
        list_spam = list_spam[:num_lines]
    vec = CountVectorizer()

    #the following block of steps are always necessary to form the entire set
    X_rows = list_ham + list_spam
    X = vec.fit_transform(X_rows).toarray()
    # label 1 for spam
    y = np.zeros(len(X_rows))
    y[len(list_ham):] = 1

    #the set formed above is then transformed into training and test sets
    #this is pretty standard, similar to the previous exercises
    X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.75, random_state=random_state)
    model = MultinomialNB()
    model.fit(X_train, y_train)
    y_fitted = model.predict(X_test)
    result = accuracy_score(y_test, y_fitted)
    misclassified = np.sum(y_test != y_fitted)
    return (result, len(X_test), misclassified)

def main():
    accuracy, total, misclassified = spam_detection()
    print("Accuracy score:", accuracy)
    print(f"{misclassified} messages miclassified out of {total}")

if __name__ == "__main__":
    main()


""" Immutable settings. Common for all projects. """

import logging
from os import path as op, walk, listdir

PROJECT_ROOT = op.abspath(op.dirname(op.dirname(op.dirname(__file__))))
PROJECT_NAME = op.basename(PROJECT_ROOT)

ENVIRONMENT_NAME = 'core'

# Databases
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite',
        'USER': '',
        'PASSWORD': '',
        'TEST_CHARSET': 'utf8',
    }
}

# Caches
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'KEY_PREFIX': '_'.join((PROJECT_NAME, ENVIRONMENT_NAME))
    }
}

# Media settigns
MEDIA_ROOT = op.join(PROJECT_ROOT, 'media')
STATIC_ROOT = op.join(PROJECT_ROOT, 'static')
MEDIA_URL = '/media/'
STATIC_URL = '/static/'

# New Relic settings
NEW_RELIC_LICENSE_KEY = 'notasecret'
NEW_RELIC_REPORT_DURATION = 30

STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

# Templates settings
TEMPLATE_DIRS = ()
for directory_name in walk(PROJECT_ROOT).next()[1]:
    directory_path = op.join(PROJECT_ROOT, directory_name)
    if 'templates' in listdir(directory_path):
        TEMPLATE_DIRS += (op.join(directory_path, 'templates'),)

TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
)

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.static',
    'django.core.context_processors.request',
    'django.contrib.auth.context_processors.auth',
    'django.contrib.messages.context_processors.messages',
)

# Applications
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.admin',
    'django.contrib.staticfiles',
)

# Middleware
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

# Base apps settings
MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'

# Localization
USE_I18N = True
USE_L10N = True
USE_TZ = True
MIDDLEWARE_CLASSES += ('django.middleware.locale.LocaleMiddleware',)
TEMPLATE_CONTEXT_PROCESSORS += ('django.core.context_processors.i18n',)

# Debug
INTERNAL_IPS = ('127.0.0.1',)

# Logging
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' # noqa
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        'django': {
            'handlers': ['console'],
            'level': 'INFO',
            'propagate': True,
        },
        'joltem': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'tests': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        }
    }
}

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
    datefmt='%d.%m %H:%M:%S',
)
logging.info("Core settings loaded.")


import math
import itertools

import numpy as np

import matplotlib.pyplot as plt
from matplotlib.patches import Patch, Circle, ConnectionPatch

from sklearn.cluster import KMeans

class SimpleGraphProps:

    def __init__(self, size=80, color="#000000", alpha=0.5):
        self._size = size
        self._color = color
        self._alpha = alpha

    def get_size(self, i):
        return self._size

    def get_color(self, i):
        return self._color

    def get_label(self, i):
        return None

    def get_label_size(self, i):
        return 0

DEFAULT_PROPS = SimpleGraphProps()

def show_maps(maps, props=DEFAULT_PROPS, ncols=4, size=5):

    N = len(maps)

    if hasattr(props, '__iter__'):
        assert len(props) == N, "props must correspond to maps"
    else:
        props = [props] * N

    nrows = N // ncols
    if N % ncols != 0:
        nrows += 1
    if N < ncols:
        ncols = N

    plt.figure(figsize=(size*ncols, size*nrows))
    for i in range(N):
        ax = plt.subplot(nrows, ncols, i+1)
        show_map(ax, maps[i], props[i])

    plt.tight_layout()

def show_map(ax, amap, props):

    y = amap.y
    labels = amap.labels

    xvals = y[:,0]
    yvals = y[:,1]
    sizes = [props.get_size(l) for l in labels]
    colors = [props.get_color(l) for l in labels]

    # ensure axes are scaled equally and tick marks are suppressed
    ax.axis('equal')
    ax.set_title(amap.name, fontsize=20)
    for axis in [ax.xaxis, ax.yaxis]:
        axis.set_major_formatter(plt.NullFormatter())

    # create all scatterplot points
    ax.scatter(xvals, yvals, color=colors, s=sizes, marker='o', alpha=0.5)

    # add labels as annotations
    for i, l in enumerate(labels):
        text = props.get_label(l)
        if text:
            ax.annotate(text, xy=(xvals[i], yvals[i]),
                horizontalalignment='center',
                verticalalignment='center',
                size=props.get_label_size(l),
            )

#     # legend
#     legend_patches = []
#     # patches for machine types
#     for (stype, color) in colormap.items():
#         patch = ax.scatter([], [], color=color, marker="o", s=getsize(medw), alpha=0.5, label=stype)
#         legend_patches.append(patch)
#     # size scale
#     for factor in [2,3,4,5]:
#         w = 10**factor
#         size=getsize(w)
#         patch = ax.scatter([], [], color="#707070", marker="o", s=size, alpha=0.5, label="{:,.0f} connections".format(w))
#         legend_patches.append(patch)

    #ax.legend(handles=legend_patches, labelspacing=5, handlelength=5, handletextpad=2., borderpad=3, ncol=2, loc=3)


# 1)FOR LOOP
nums_str = input().split(", ")

even_indices = []
numbers = []
for num_str in nums_str:
    number = int(num_str)
    numbers.append(number)

for index, number in enumerate(numbers):
    if number % 2 == 0:
        even_indices.append(index)

print(even_indices)

# 2)MAP
numbers = map(int, input().split(", "))
print([index for index, number in enumerate(numbers) if number % 2 == 0])


import config
import discord
import data
import embeds

def parse_message(message: discord.Message):
    if len(message.content) == 0 and len(message.embeds) > 0:
        text = message.embeds[0].footer.text
        if isinstance(text, str):
            values = dict(part.split('=') for part in filter(lambda key: len(key) > 0, text.split('&')))
            values['lang'] = values.get('lang', 'kr')
            return values
    return dict()

class IgniteButtonView(discord.ui.Button):
    def __init__(self, parent):
        super().__init__(custom_id='ignite', emoji=config.reaction_ignite)
        self.parent = parent

    async def callback(self, interaction: discord.Interaction):
        ignited = not self.parent.is_ignited
        msg = parse_message(interaction.message)
        idx, lang = msg.get('idx'), msg.get('lang')
        if idx and lang:
            embed = embeds.char_embed(data.get(idx, ignited, lang=lang), lang=lang)
            await interaction.response.edit_message(embed=embed)
            self.parent.is_ignited = ignited
        else:
            await interaction.response.defer()

class LanguageButtonView(discord.ui.Button):
    def __init__(self, parent, lang: str):
        super().__init__(custom_id='language_%s' % lang, emoji=config.reaction_lang[lang])
        self.parent = parent
        self.lang = lang

    async def callback(self, interaction: discord.Interaction):
        lang = self.lang
        msg = parse_message(interaction.message)
        idx, current_lang = msg.get('idx'), msg.get('lang')
        if idx and current_lang and lang != current_lang:
            embed = embeds.char_embed(data.get(idx, ignited=False, lang=lang), lang=lang)
            await interaction.response.edit_message(embed=embed)
            self.parent.is_ignited = False
        else:
            await interaction.response.defer()

class CharView(discord.ui.View):
    def __init__(self, char: dict, lang: str):
        super().__init__(timeout=None)
        self.is_ignited = False
        self.char = char
        self.lang = lang

        idx = char['idx']
        if len(char['skills_ignited']) > 0:
            self.add_item(IgniteButtonView(self))

        has_lang = [l for l in config.langs if data.has(idx, l)]
        if len(has_lang) > 1:
            for l in has_lang:
                self.add_item(LanguageButtonView(self, lang=l))

class PaginationView(discord.ui.View):
    def __init__(self):
        super().__init__(timeout=None)

    @discord.ui.button(emoji=config.reaction_prev)
    async def prev(self, interaction: discord.Interaction, button: discord.ui.Button):
        await self.run(interaction, -1)

    @discord.ui.button(emoji=config.reaction_next)
    async def next(self, interaction: discord.Interaction, button: discord.ui.Button):
        await self.run(interaction, +1)

    async def run(self, interaction: discord.Interaction, change: int):
        msg = parse_message(interaction.message)
        tag, query, page = msg.get('tag'), msg.get('query', ''), int(msg.get('page', 1)) + change
        lang = msg.get('lang')

        embed = None
        if tag == 'list':
            found = data.search(query, lang=lang)
            embed = embeds.list_embed(query, found, page, lang=lang)
        elif tag == 'buffs':
            found = data.buffs(query, lang=lang)
            embed = embeds.buffs_embed(query, found, page, lang=lang)

        if embed:
            await interaction.response.edit_message(embed=embed)
        else:
            await interaction.response.defer()


# OPENCORE - ADD
from shared.regular import regular_log, regular_input
from shared.settings import settings
from werkzeug.exceptions import Forbidden
from shared.database.connection.connection import Connection
from shared.permissions.project_permissions import Project_permissions
from shared.database.project import Project
from cryptography.fernet import Fernet
from shared.shared_logger import get_shared_logger

logger = get_shared_logger()

connection_spec_list = [

    {'name': {
        'default': 'My Connection',
        'kind': str,
        'required': False
    }
    },
    {'project_string_id': {
        'kind': str,
        'required': False
    }
    },
    {'permission_scope': {
        'default': 'project',
        'kind': str,
        'required': False,
        'valid_values_list': ['project', 'org', 'Project', 'Org']
    }
    },
    {"archived": {
        'default': False,
        'kind': bool,
        'required': False
    }
    },
    {"aws_v4_signature": {
        'default': False,
        'kind': bool,
        'required': False
    }
    },
    {"private_id": {
        'default': None,
        'kind': str,
        'required': False
    }
    },
    {"aws_region": {
        'default': None,
        'kind': str,
        'required': False
    }
    },
    {"private_host": {
        'default': None,
        'kind': str,
        'required': False
    }
    },
    {"private_secret": {
        'default': None,
        'kind': str,
        'required': False
    }
    },
    {"disabled_ssl_verify": {
        'default': None,
        'kind': bool,
        'required': False
    }
    },
    # WIP... We assume for new we want to update it, otherwise
    # assume we don't. May be cases where we do wish to do so
    # because of encryption though we don't know on the front
    {"do_update_private_secret": {
        'default': False,
        'kind': bool,
        'required': False
    }
    },

    {"account_email": {
        'default': None,
        'kind': str,
        'required': False
    }
    },

    {"project_id_external": {
        'default': None,
        'kind': str,
        'required': False
    }
    },

    {"integration_name": {
        'default': None,
        'kind': str,
        'required': True
    }
    },
    {"url_signer_service": {
        'default': None,
        'kind': str,
        'required': False
    }
    }

    # See update_connection () for where metadata get loaded
]

class Connection_Operations():
    """
    """

    def __init__(
        self,
        session,
        connection_id: int = None,
        metadata: dict = None,
        member = None,
        project_string_id = None
    ):

        self.session = session
        self.connection_id = connection_id

        # This will get converted into
        # metadata after validating spec.
        self.metadata_untrusted = metadata
        self.member = member

        # These are assumed to be set from other functions
        # ie through a validation process...???
        self.org = None
        self.project = None
        self.fernet = None

        self.log = regular_log.default()

        if self.metadata_untrusted:
            self.metadata = self.validate_connection_spec(
                metadata_untrusted = self.metadata_untrusted)
            if len(self.log["error"].keys()) >= 1:
                return

        self.project_string_id = project_string_id

    def init_cryptography(self):
        """
        """

        self.fernet = Fernet(settings.FERNET_KEY)

        if self.fernet is None:
            raise Exception('Fernet not defined.')

    def get_existing_connection(self, connection_id):
        """
        No permissions checking
        Literal get database object
        """
        self.connection = Connection.get_by_id(
            session = self.session,
            id = connection_id)

        return self.connection

    def validate_existing_connection_id_permissions(self):
        """
        For external validation

        We use what we know about the connection (ie the project it's related to)
        and what we know about the user making the request to validate the permissions.

        Because if we use what the user supplies the user could
        supply any project they have permissions to (even if it's unrelated to to the connection)

        The assumption is we operate on the project from the connection
        May still need some more thought here.

        There's some tension / confusion here between how we should validate
        permissions for an existing one...

        concrete for existing
        """
        if self.connection is None:
            raise Forbidden("Not Found")

        self.validate_connection_permissions_scope(
            permission_scope = self.connection.permission_scope,
            project_string_id = self.connection.project.project_string_id,
        )

    def validate_connection_permissions_scope(self,
                                              permission_scope: str,
                                              project_string_id: str = None
                                              ):
        """
        abstract

        For internal use generally.
        """

        permission_scope = permission_scope.lower()

        self.permission_scope = permission_scope

        if permission_scope == "project":
            project_role_list = ["admin", "Editor", "Viewer", "allow_if_project_is_public"]

            Project_permissions.by_project_core(
                project_string_id = project_string_id,
                Roles = project_role_list)

            self.project = Project.get(self.session, project_string_id)
            return

        # Should not be possible to reach here if permission_scope string is validated.
        raise Forbidden("permission_scope is invalid")

    def save(self):

        self.connection = self.get_from_id_or_new_connection(
            connection_id = self.connection_id,
            project = self.project
        )

        if len(self.log["error"].keys()) >= 1:
            return

        self.update_connection(metadata = self.metadata)

        if len(self.log["error"].keys()) >= 1:
            return

        self.session.add(self.connection)

        if not self.connection.id:
            self.session.flush()  # Get ID, relevant if new object

    def get_from_id_or_new_connection(
        self,
        connection_id: int,
        project = None
    ) -> Connection:
        """
        Pattern where creating a "new"
        one really just does the ID and the rest if part of update process?

        """

        if connection_id:
            connection = Connection.get_by_id(
                session = self.session,
                id = connection_id)

            if connection is None:
                self.log['error']['connection'] = "Invalid connection ID"
                return

            return connection

        else:
            return Connection.new(
                member = self.member,
                project = project)

    def self_test(self):

        self.init_cryptography()

        message = "attack at dawn"
        encrypted_message = self.encrypt_secret(message)

        if message == encrypted_message:
            raise Exception("Encryption failed")

        clear_text = self.decrypt_secret(encrypted_message)
        if message != clear_text:
            raise Exception("Decryption failed")

        logger.info("init_cryptography() self test success")

    def encrypt_secret(self, secret) -> str:
        """
        https://pypi.org/project/cryptography/
        it works in bytes
        but we assume secret will be a string

        """
        if not secret:
            raise Exception("Must supply secret")

        if not self.fernet:
            self.init_cryptography()
        if not self.fernet:
            return False

        return self.fernet.encrypt(secret.encode())

    def decrypt_secret(self, secret) -> str:
        """
        For use when a connection is being used to
        process some other part of the system

        Library returns bytes, we want string
            Note difference that we are decoding return value
            Except when encrypting...

        Exception handling
            One example is: secret key is not a match for encrypted data
            Context that we would rather catch these with dedicated cases
            as they come up. Since it's likely to be an ongoing thing that
            it's possible for keys to get rotated / mixed up.
            Still needs more work.
        """
        if not self.fernet:
            self.init_cryptography()
        if not self.fernet:
            return False

        try:
            open_secret = self.fernet.decrypt(secret)
            string_open_secret = open_secret.decode()
            new_line_fixed_string_open_secret = string_open_secret.replace('\\n', '\n')

            return new_line_fixed_string_open_secret

        except Exception as exception:
            print('[decrypt_secret]', exception)
            return False

    def get_secret(self) -> str:
        """
        Concrete getter for default secret
        """

        if not self.connection:
            return False

        return self.decrypt_secret(self.connection.private_secret_encrypted)

    def validate_connection_spec(
        self,
        metadata_untrusted: dict):
        """
        This is strictly validating the
        raw data is there it's not checking permissions

        """

        self.log, metadata = regular_input.input_check_many(
            spec_list = connection_spec_list,
            log = self.log,
            untrusted_input = metadata_untrusted)

        if len(self.log["error"].keys()) >= 1:
            return

        return metadata

    def update_secret_connection(
        self,
        metadata: dict):
        """
        careful, we don't store this on front end by default
        so only update if user expressly updates
        """

        private_secret = metadata.get('private_secret')
        if not private_secret:
            return

        self.connection.private_secret_encrypted = self.encrypt_secret(private_secret)

    def update_connection(
        self,
        metadata: dict):
        """
        Assumes data has been validated...

        Assumes all 'connections' are unique concrete instances

        """

        ## CAREFUL need to add into API spec too
        self.connection.name = metadata.get('name')
        self.connection.permission_scope = metadata.get('permission_scope')
        if self.connection.permission_scope:
            self.connection.permission_scope.lower()
        self.connection.archived = metadata.get('archived')
        self.connection.integration_name = metadata.get('integration_name')
        self.connection.private_host = metadata.get('private_host')
        self.connection.disabled_ssl_verify = bool(metadata.get('disabled_ssl_verify', False))
        self.connection.aws_v4_signature = bool(metadata.get('aws_v4_signature', False))
        self.connection.aws_region = metadata.get('aws_region', 'us-west-1')
        self.connection.private_id = metadata.get('private_id')
        self.connection.account_email = metadata.get('account_email')
        self.connection.project_id_external = metadata.get('project_id_external')
        self.connection.url_signer_service = metadata.get('url_signer_service')

        self.connection.member_updated = self.member

        self.update_secret_connection(metadata = metadata)

    def connection_list(
        self):
        """
        Assumes validated scope / permission

        Seems to make sense to use self here since
        we are only running this if validated right?
        """

        connections_list = Connection.list(
            session = self.session,
            permission_scope = self.permission_scope,
            project = self.project,
            return_kind = "objects"
        )
        return connections_list


# 1이 될 때까지 : 정당성 분석

# 주어진 N에 대하여 최대한 많이 나누기를 수행한다.
# N의 값을 줄일 때 2이상의 수로 나누는 작업이 1을 빼는 작업보다 수를 훨씬 많이 줄일 수 있다.
# N = 25, K = 3

# N, K공백을 기준으로 구분하여 입력 받기
n, k = map(int, input().split())

result = 0

while True:
    # N이 K로 나누어 떨어지는 수가 될 때까지만 1씩 빼기
    target = (n // k) * k
    result += (n - target)
    n = target
    # N이 K보다 작을 때 (더 이상 나눌 수 없을 때) 반복문 탈출
    if n < k:
        break
    # K로 나누기
    result += 1
    n //= k

# 마지막으로 남은 수에 대하여 1씩 빼기
result += (n - 1)
print(result)
# 6


height = int(input('введите высоту в символах :'))
width = height * 4

count = 1

for i in range(height):
    gap = int((width - count) / 2)
    line = (" " * gap) + ("*" * count)
    count += 4
    print(line)

for i in range(height):
    count = 1 if i == height - 1 else 3
    gap = int((width - count) / 2)

    if count == 1:
        line = (" " * (i * 2 + 1)) + "*"
    else:
        line = (" " * (i * 2)) + "*" + (" " * gap) + "*" + (" " * gap) + "*"

    width -= 4
    print(line)


# 검색 알고리즘, 알고리즘 복잡도

'''
Description

참고: sorted(), list.sort()

t = [4, 3, 8, 6, 7, 13, 10, 14, 9]
print(t)
t2 = sorted(t)
print(t2)
print(t)

[4, 3, 8, 6, 7, 13, 10, 14, 9]
[3, 4, 6, 7, 8, 9, 10, 13, 14]
[4, 3, 8, 6, 7, 13, 10, 14, 9]

t.sort() # list의 sort() 함수는 반환값이 없음
print(t)

[3, 4, 6, 7, 8, 9, 10, 13, 14]
'''

'''
검색 알고리즘

Sequential Search (순차 검색): 앞에서부터 하나씩 원하는 값이 리스트의 어디에(인덱스) 저장되어 있는지 찾는 알고리즘
Binary Search (이진 검색): 리스트가 정렬되어 있을 때, 찾는 범위는 반씩 줄이면서 원하는 값이 리스트의 어디에(인덱스) 저장되어 있는지 찾는 알고리즘
'''

'''
실행시간 측정 방법

python에서 제공하는 timeit 모듈에서 제공하는 timeit() 함수를 이용하여, 특정 코드의 실행시간을 측정할 수 있다.

timeit.timeit() 함수는 아래와 같이 정의되어 있다.

timeit.timeit(stmt='pass', setup='pass', timer=, number=1000000, globals=None)
매개변수
stmt: 실행시간을 측정하기 위한 코드
setup: stmt를 실행하기 전에 한 번만 실행하는 코드
timer: 시간을 측정하는 timer의 종류를 명시
number: 반복실행할 회수
globals: 글로벌변수/함수 등을 전달하기 위하여 사용

반환값
stmt로 전달된 명령문을 number번 실행해서 그 평균 실행시간을 반환 (초 단위)

주의 정렬 알고리즘의 경우에는, 입력데이터에 따라 실행속도가 매우 다르게 되는 경우가 많다. 예를 들어, 모든 데이터들이 이미 정렬되어 있는 경우에 실행이 바로 끝나는 알고리즘이 존재한다. 혹은 데이터가 역순으로 정렬되어 있을 때, 평균실행속도보다 실행시간이 훨씬 오래 걸리는 알고리즘도 존재한다.

따라서 정렬알고리즘을 테스트하기 위해서는 리스트에 난수를 발생시킨 후 (혹은 원하는 데이터를 저장한 후), timeit() 함수의 매개변수 number에 1를 전달하여, 한 번만 실행하도록 한다.

같은 데이터 크기 n에 대하여 여러 번 실행해서 그 평균을 구하고 싶은 경우에는, 매번 리스트에 원하는 데이터(난수 혹은 원하는 데이터값)을 넣고 timeit() 함수를 호출하여야 한다.
'''

'''
연습 1. sequential search & binary search

1) 동작의 이해
sequential_search(), binary_search() 함수의 verbose 매개변수에 True를 넘겨주어 실행하면서, 검색 알고리즘의 동작을 이해해볼 것.
인자로 전달하는 리스트의 크기, 저장된 값들을 바꾸면서 프로그램이 어떠한 단계로 실행되는지, 즉 알고리즘이 어떻게 작동하는지 이해해볼 것.
질문: 코드를 그대로 수행하면 우리가 찾고자 하는 값(5)가 리스트의 원소로 존재함에도 불구하고, binary_search()는 None을 반환한다. 이 이유는 무엇인가?

2) 테스트 케이스 작성
알고리즘이 제대로 작동하는 것을 확인하기 위해서 테스트 케이스를 잘 만들 필요가 있다. (참고: 채점 코드로 이와 유사한 방법어로 만들고 있습니다.)
검색의 경우에는 다음과 같이 테스트를 할 수 있을 것입니다.
우선 함수에 전달될 수 있는 가장 간단한 경우들에 대해서 테스트를 합니다. 즉 빈 리스트부터, 원소가 1개, 2개, ... 등의 간단한 경우를 테스트 합니다. 그리고 찾고자 하는 값이 리스트에 존재하는 경우, 그렇지 않은 경우 등에 대해서 나눠서 테스트를 할 필요가 있습니다.
또한 리스트의 원소의 순서에 따라 알고리즘이 작동하지 않을 수 있으니, 동일한 원소들이 포함되어도 그 리스트의 순서를 바꾼 입력을 주어보는 것도 필요하구요.
그리고 어느 정도 이상 규모가 큰 입력에 대해서도 제대로 작동을 하는지 확인을 할 필요도 있습니다. 아래의 예시에서는 n=100인 경우에 테스트를 한 경우입니다.

print(sequential_search([], 1))
print(sequential_search([1], 1))
print(sequential_search([2], 1))
print(sequential_search([1, 2], 1))
print(sequential_search([2, 1], 1))
print(sequential_search([1, 2], 2))
print(sequential_search([2, 1], 2))
print(sequential_search([1, 2], 3))
print(sequential_search([2, 1], 3))

n = 100
t = list(range(n))
random.shuffle(t)
print('t =', t)
for i in range(n):
    index = sequential_search(t, i)
    if index == None:
        # since the list contains 0..(n-1), None shouldn't be returned
        print(f'There is a problem when looking for {i} in t')

To do
이진 검색에 대해서도 위와 유사한 테스트 케이스를 만들어 볼 것. 테스트 케이스가 달라야 할텐데, 그 이유는 무엇일까?
이진 검색에서 일부러 오류를 만들어보고 (예: first = mid + 1 부분을 first = mid로 수정), 이 경우에 어떤 테스트 케이스에서 문제가 생기는지 확인해 볼 것
참고: 필요하면 함수를 부를 때 verbose에 True를 전달하면 도움이 된다

3) n에 따른 실행시간 측정
timeit_search() 함수를 호출하는 부분을 수정하여, 아래 표를 채워보고, 다음 질문에 답해볼 것.
표만을 보고, 알고리즘 복잡도를 추정할 수 있나?
참고: timeit_search()는 수정하지 않고, 그대로 사용해도 됨.
'''

#Code
import random
import timeit

def sequential_search(sequence, item, verbose=False):
    if verbose:
        print(f'sequential_search() invoked,',
              f'item={item}, sequence={sequence}')
    for index in range(len(sequence)):
        if verbose:
            print(f'index={index}, sequence[index]={sequence[index]}')
        if sequence[index] == item:
            return index
    return None

def binary_search(sequence, item, verbose=False):
    if verbose:
        print(f'binary_search() invoked,',
              f'item={item}, sequence={sequence}')
    first = 0
    last = len(sequence) - 1  # last is INCLUSIVE

    while first <= last:
        mid = (first + last) // 2
        if verbose:
            print(f'first={first}, mid={mid}, last={last},',
                  f'sequence[mid]={sequence[mid]}')
        if sequence[mid] == item:
            return mid
        if item < sequence[mid]:
            last = mid - 1
        else:
            first = mid + 1
    return None

def timeit_search(func, n, repetition=None):
    """Return the execution time of func() for repetition times,
       for the problem size of n
    """
    if repetition == None:
        repetition = n

    t = list(range(n))
    duration = timeit.timeit('func(t, random.randrange(n))',
                             setup='import random',
                             globals=locals(),
                             number=repetition)
    return duration

if __name__ == '__main__':
    # 1)
    n = 10
    item = 5

    t = list(range(n))
    random.shuffle(t)  # make a random list
    print(f'Searching {item} in {t}...')
    print('sequential:',  sequential_search(t, item, True))
    print('binary :',  binary_search(t, item, True))

    # 2)
    print(sequential_search([], 1))
    print(sequential_search([1], 1))
    print(sequential_search([2], 1))
    print(sequential_search([1, 2], 1))
    print(sequential_search([2, 1], 1))
    print(sequential_search([1, 2], 2))
    print(sequential_search([2, 1], 2))
    print(sequential_search([1, 2], 3))
    print(sequential_search([2, 1], 3))

    n = 100
    t = list(range(n))
    random.shuffle(t)
    print('t =', t)
    for i in range(n):
        index = sequential_search(t, i)
        if index == None:
            # since the list contains 0..(n-1), None shouldn't be returned
            print(f'There is a problem when looking for {i} in t')
        else:
            print(f'The index of the value {i}: {index}')

    # 3)
    problem_sizes = [1, 10, 20, 50, 100]
    rep = 100
    print('Sequential search...')
    for n in problem_sizes:
        print(f'{n:5d}:', timeit_search(sequential_search, n, rep))

    print('Binary search...')
    for n in problem_sizes:
        print(f'{n:5d}:', timeit_search(binary_search, n, rep))

Week15_Search Algorithm & Sorting Algorithm/W15ExampleProblems/W15P74_SearchAlgorithm&AlgorithmComplexity/W15P74_SearchAlgorithm&AlgorithmComplexity.py


import pytest
from data_structures_and_algorithms_python.data_structures.graphs.graph import *

# 1 Node can be successfully added to the graph

def test_add_node_successfully():
    graph = Graph()
    graph.add_node('A')
    expected = 1
    actual = graph.size()
    assert actual == expected

# 2 An edge can be successfully added to the graph

def test_add_edge_successfully():
    graph = Graph()
    v1 = graph.add_node('A')
    v2 = graph.add_node('B')
    graph.add_edge(v1, v2)
    assert graph._adjacency_list[v1] == [(v2, 0)]

def test_get_all_nodes_and_check_the_size():
    graph = Graph()
    v1 = graph.add_node('A')
    v2 = graph.add_node('B')
    v3 = graph.add_node('C')
    v4 = graph.add_node('D')
    v5 = graph.add_node('E')
    assert graph.size() == 5

def test_get_neighbor_and_with_weights():
    graph = Graph()
    v1 = graph.add_node('A')
    v2 = graph.add_node('B')
    v3 = graph.add_node('C')
    graph.add_edge(v1, v2, 1)
    graph.add_edge(v1, v3, 2)
    assert graph.neighbors(v1) == [('B', 1), ('C', 2)]

# 7A graph with only one node and edge can be properly returned

def test_graph_with_one_node_and_edge():
    graph = Graph()
    v1 = graph.add_node('A')
    with pytest.raises(KeyError):
        graph.add_edge(v1, None)

# 8 An empty graph properly returns null

def test_empty_graph():
    graph = Graph()
    assert graph.print_graph() == None
    print('pass')


#47ms 34.95% (estimate)

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        rts = [root]
        lfts = []
        res = []
        while rts:
            curNode = rts.pop()
            if curNode:
                while curNode:
                    lfts.append(curNode)
                    curNode = curNode.left
                while lfts:
                    curLft = lfts.pop()
                    res.append(curLft.val)
                    if curLft.right:
                        rts.append(curLft.right)
                        break
        return res


from pop import Pop
from params import Params

class Trader(Pop):
    def __init__(self,prov,size):
        Pop.__init__(self,prov,'TRD',size)
        self.bought_inputs = {k:0 for k in Params.goods}
        self.av_provs = self.prov.neighbors
#         self.best_deal_list = None
        self.best_deal = None
#         self.past_deal = {}
#         self.past_past_deal = {}
        self.deal_subdiv = 5

    def produce(self,verbose):
        # do everything in the same day (maybe add the opportunity to add a delay, but for now, only daily, well weekly)
        # maybe add the multiple goods functionality, but for now, all or nothing of one good

        # find all deals
        if verbose:
            print('')
            print(self.prov.name)
        deal_list = []
        q_limit = Params.trader_limit * self.size
        lmk = self.prov.market
        for n in self.av_provs:
            target_prov = self.prov.world.provs[n]
            tmk = target_prov.market
            for k in Params.goods:
                av_good = lmk.get_stock(k)
                q_av = min(q_limit,av_good*0.5)
                for i in range(self.deal_subdiv):
                    subdiv_mod = (i+1)/self.deal_subdiv
                    q_deal = q_av*subdiv_mod

                    local_cost = lmk.buy_cost(k,q_deal)
                    target_cost = tmk.sell_cost(k,q_deal)

                    possible_profit = target_cost - local_cost
                    info_dict = {
                        'n':n,
                        'k':k,
                        'AV:':round(av_good,2),
                        'LP:':round(local_cost/q_deal,2),
                        'TP:':round(target_cost/q_deal,2),
                        'SALE':q_deal,
                        'PROFIT':possible_profit,
                        'PM':possible_profit/q_deal,
                        'SM':subdiv_mod
                    }
                    #display(info_dict)
                    if possible_profit > 0:
                        deal_list.append(info_dict)

        # get best deals
        if len(deal_list) == 0:
            if verbose:
                print('NO GOOD DEAL')
            return
        else:
            if verbose:
                print('DEAL LIST')
                display(deal_list)

        best_deal = max(deal_list,key=lambda x:x['PROFIT'])

        if verbose:
            print('SELECTED DEAL')
            display(best_deal)

        # trade the best deals
        # get loan if needed
        cost = lmk.buy_cost(best_deal['k'],best_deal['SALE'])
        loan = 0
        if cost>self.funds:
            loan = (cost - self.funds)
            if verbose:
                print(f'LOAN OF {loan} NEEDED. COST {cost} FUNDS {self.funds}')
            self.funds += loan
            self.loaned_funds += loan

        # buy local
        bought, real_cost = lmk.buy_good(best_deal['k'],best_deal['SALE'],self.funds,self)

        # sell target
        tmk = self.prov.world.provs[best_deal['n']].market
        sold, real_rev = tmk.sell_good(best_deal['k'],bought,self)

        # pay back the loan imediately
        if loan>0:
            self.pay_loans(loan)

        if verbose:
            print(f'BOUGHT {bought} FOR {real_cost}')
            print(f'SOLD {sold} FOR {real_rev}')
            print(f'FUNDS {self.funds} LOANS {self.loaned_funds}')

#     def find_deals(self,verbose):
#         if verbose:
#             print('')
#             print(self.prov.name)
#         deal_list = []
#         q_limit = Params.trader_limit * self.size
#         for n in self.av_provs:
#             target_prov = self.prov.world.provs[n]
#             lmk = self.prov.market
#             tmk = target_prov.market
#             for k in Params.goods:
#                 # deal info
#                 local_price = lmk.buy_price(k)
#                 target_price = tmk.sell_price(k)
#                 target_demand = tmk.prev_demand[k]
#                 target_supply = tmk.prev_supply[k]
#                 # im missing a way to only consider supply not from me, best way is to check my past deal, if there is any past supplies to that, then subtract it
#                 if (n,k) in self.past_past_deal:
#                     own_supply = self.past_past_deal[(n,k)]
#                     target_supply -= own_supply
#                     if verbose:
#                         print(f'SUBTRACTING {own_supply} {k} {n}')

#                 assert target_supply >= 0, 'TARGET SUPPLY NEGATIVE'

#                 av_good = lmk.prev_supply[k]
#                 max_goods = min(av_good,q_limit,tmk.prev_demand[k])
#                 if max_goods <= 0:
#                     continue
#                 for i in range(5):
#                     q_deal = max_goods*(i+1)/5
#                     expected_price = min(target_demand/(target_supply+q_deal+0.000001),1)*target_price
#                     possible_profit = q_deal*(expected_price-local_price)
#                     info_dict = {
#                         'n':n,
#                         'k':k,
#                         'AV:':round(av_good,2),
#                         'TS:':round(target_supply,2),
#                         'TD:':round(target_demand,2),
#                         'LP:':round(local_price,2),
#                         'TP:':round(target_price,2),
#                         'EP:':round(expected_price,2),
#                         'SALE':q_deal,
#                         'PROFIT':possible_profit,
#                         'PM':possible_profit/q_deal
#                     }
#                     #display(info_dict)
#                     if possible_profit > 0:
#                         deal_list.append(info_dict)

#         if len(deal_list) == 0:
#             if verbose:
#                 print('NO GOOD DEAL')
#             return
#         else:
#             if verbose:
#                 print('DEAL LIST')
#                 display(deal_list)

#         # from all the deals in deal_list it has to pick the best ones to trade
#         # first of all it
#         best_deal_list = []
#         # while there is still space to trade and deals left to evaluate
#         while (q_limit > 0) and (len(deal_list) > 0):
#             # picks the best deal in terms of price margin
#             best_deal_prov_kind = max(deal_list,key=lambda x:x['PM'])
#             # out of that deal, it picks the one with THAT resource and THAT province that maximizes profit
#             used_good = best_deal_prov_kind['k']
#             target_prov = best_deal_prov_kind['n']

#             prov_kind_deal_list = [deal for deal in deal_list if ((deal['k'] == used_good) and (deal['n'] == target_prov))]
#             best_deal = max(prov_kind_deal_list,key=lambda x:x['PROFIT'])

#             deal_list = [deal for deal in deal_list if ((deal['k'] != used_good) or (deal['n'] != target_prov))]
#             q_limit -= best_deal['SALE']

#             best_deal_list.append(best_deal)

#         if len(best_deal_list) > 0:
#             if verbose:
#                 print('BEST DEAL:')
#                 display(best_deal_list)
#             self.best_deal_list = best_deal_list
#         else:
#             if verbose:
#                 print('NO GOOD DEAL')