# -*- coding:utf-8 -*-
# Author : Hu Chen
# MailTo : hchen052@gmail.com
# QQ     :
# Blog   :
# Github : https://github.com/hchen052/JX3KeJuAnswerSearcher
# Create : 2015-08-13
# Version: 1.0
#
# Part of project jx3kejusearch
# Provide search API
#
# 剑网3科举考试答案查询器
# 目前题目数量为1588条

import re
import sys
import os
from pypinyin import lazy_pinyin
import codecs
import HuPySQLite

# 数据库的绝对路径
DB_FILE_PATH = ''
# 数据库名称
DB_FILE_NAME = 'JX3KeJuTiKu.db'
# 表名称
DB_TABLE_NAME = 'jx3keju'
# 科举答案导入文件(txt格式)
# q: _________，众妙之门。  a: 玄之又玄
KEJU_TXT = 'JX3KeJuDaAn_All.txt'

# 重新编码字符.
#
# 将字符串strw从utf-8编码转换成ENCODE_TYPE编码.
def recode(strw):
    import platform
    sysstr = platform.system()
    if sysstr.lower() == 'windows':
        ENCODE_TYPE = sys.getfilesystemencoding()
        return strw.decode('utf-8').encode(ENCODE_TYPE)
    else:
        return strw

def SearchQuestionByPinyin(pinyin):
    """
    方法：  通过拼音的方式来搜索题目，并打印答案。
    参数：  pinyin  :  题目的首字母
    返回：  data  ：  所有符合规则的题目及答案
    """
    global DB_FILE_PATH
    global DB_FILE_NAME
    global DB_TABLE_NAME
    if DB_FILE_PATH == '':
        DB_FILE_PATH = os.getcwd()
    db_file = os.path.join(DB_FILE_PATH, DB_FILE_NAME)
    cx = HuPySQLite.get_conn(db_file)
    cu = cx.cursor()
    sql = '''select question, answer from %s where que_pinyin glob "*%s*"'''%(DB_TABLE_NAME, pinyin)
    cu.execute(sql)
    data = cu.fetchall()
    cu.close()
    cx.close()
    return data

def SearchMain(pinyin):
    rtstr = ''
    pinyin = str(pinyin)
    data = SearchQuestionByPinyin(pinyin.lower())
    if len(data) == 0:
        rtstr += u'%>_<%没找到你的题目，请重试！\n'
    else:
        i = 0
        for value in data:
            q = value[0]
            a = value[1]
            i += 1
            rtstr += u'%2d. %s\n' %(i, q)
            rtstr += u'    答案：%s\n' %a
    return rtstr

if __name__ == '__main__':
    SearchMain()


import os
import re

LOG = "/home/vicente/pacman.log"
CACHE_DIR = "/var/cache/pacman/pkg"

def check_cache(pkg, version):
    pkg_name = f"{pkg}-{version}"
    for file in os.listdir(CACHE_DIR):
        if file[-4:] == ".sig":
            continue
        if file[0:len(pkg_name)] == pkg_name:
            return file
    return None

def main():
    with open(LOG) as f:
        lines = f.readlines()

    n = 0
    errors = []
    version_pattern = re.compile("\[ALPM\] upgraded ([0-9a-z-\+]+) \(([0-9a-z-\.:\+]+) -> ([0-9a-z-\.]+)")
    upgrade_pattern = re.compile("\[ALPM\] upgraded")
    for line in lines:
        match = upgrade_pattern.search(line)
        if match:
            match = version_pattern.search(line)
            if match:
                pkg, old_ver, ver = match.groups()
                pkg_file = check_cache(pkg, old_ver)
                if pkg_file:
                    n += 1
                    cmd = f"pacman -U --noconfirm {CACHE_DIR}/{pkg_file}"
                    print(cmd)
                    os.system(cmd)
                else:
                    error = f"Unable to downgrade pkg {pkg} to version {old_ver}"
                    print(error)
                    errors.append(error)
            else:
                error = "Unable to parse \"{}\"".format(line[:-1])
                print(error)
                errors.append(error)

    print(f"\nFinished: {n} packages downgraded")
    if errors:
        print(f"{len(errors)} packages couldn't be downgraded:")
    for error in errors:
        print(error)

if __name__ == "__main__":
    main()


#sourceFilesNames = ['sfile1','sfile2','sfile3']
#destinationFilesNames = ['dfile1','dfile2','dfile3']
#for x in range(len(sourceFilesNames)):
#    print(sourceFilesNames[x] + " - " + destinationFilesNames[x])

source = [2, 3, 4]
dest = [2, 3, 4]
dest2 = [3, 4, 6]
for s_offset in range(len(source)):
    for d_offset in range(len(dest)):
        for dest2_a in range(len(dest2)):
            print(source[s_offset] + dest[d_offset]+ dest2[dest2_a])
'''
print(source[0] + dest[0])
print(source[0] + dest[1])
print(source[0] + dest[2])

print(source[1] + dest[0])
print(source[1] + dest[1])
print(source[1] + dest[2])

print(source[2] + dest[0])
print(source[2] + dest[1])
print(source[2] + dest[2])

'''
'''
for i in range(10):
    if i==0:
        print('*', end='')
    else:
        for j in range(i*2):
            print('*', end='')
    print('\n', end='')
'''
'''
for i in range(10):
    if (i+1) % 2 != 0: # allow only even number
        for j in range(10):
            print('{:2} x {:2} : {:3}'.format(i+1, j+1, ((i+1)*(j+1))))
        userInput = input('next')
        if userInput!='n':
            break
'''
# for s_offset in range(len(source)):
#     # for d_offset in range(len(dest)):
#         print(source[s_offset])


import logging
import aiogram
from aiogram.dispatcher.filters import Text
from aiogram.utils import exceptions
from database import db
from aiogram import types
from utils import FindFile
from create_bot import bot
import math

def mess_about_file(fileData):
    filename = fileData['filename']
    course = fileData['course']
    subject = fileData['subject']
    msg = f"""Имя файла: *{filename}*
Курс: *{course}*
Предмет: *{subject}*"""
    return msg

async def ask_subject(callback: aiogram.types.CallbackQuery,
                      state: aiogram.dispatcher.FSMContext):
    """
    Спрашиваем предмет, по которому вывести предметы

    :param callback: объект aiogram.types.CallbackQuery
    :param state: aiogram.dispatcher.FSMContext
    :return: None
    """
    chat_id = callback.message.chat.id
    message_id = callback.message.message_id
    state_data = await state.get_data()

    user = db.get_user_by_id(chat_id)
    if user is None or len(user) == 0:
        logging.error(f"Пользователь не найден в функции ask_subject в showFiles, chat_id={chat_id}")
        return
    user = user[0]

    course = user['course']
    direction = user['direction']
    subjects = db.get_subjects(course, direction)
    if subjects is None:
        logging.error(f"Предметы не найдены в функции ask_subject в showFiles, chat_id={chat_id}")
        return

    max_page = math.ceil(len(subjects) / 8)
    if "page_sub" not in state_data:
        await state.update_data(page_sub=1)
        page = 1
    else:
        page = int(state_data['page_sub'])
        if page <= 0:
            page = 1
            await state.update_data(page_sub=page)
            return
        if page > max_page:
            page = max_page
            await state.update_data(page_sub=page)
            return

    msg = "Какой предмет?"
    buttons = []
    for sub in subjects[8 * (page-1): 8 * page]:
        buttons.append([types.InlineKeyboardButton(text=f"{sub['name']}", callback_data=f"{sub['sub_id']}")])

    buttons.append([
        types.InlineKeyboardButton(text="◀", callback_data="page_left_sub"),
        types.InlineKeyboardButton(text=f"{page} / {max_page}", callback_data="page_none"),
        types.InlineKeyboardButton(text="▶", callback_data="page_right_sub"),
    ])
    buttons.append([types.InlineKeyboardButton(text="Главное меню", callback_data="main_menu")])
    keyboard = types.InlineKeyboardMarkup(inline_keyboard=buttons)
    await bot.edit_message_text(chat_id=chat_id, reply_markup=keyboard, text=msg, message_id=message_id)
    await state.set_state(FindFile.askSubject)

async def show_files_list(callback: aiogram.types.CallbackQuery,
                          state: aiogram.dispatcher.FSMContext):
    """
    Показываем список файлов

    :param callback: объект aiogram.types.CallbackQuery
    :param state: aiogram.dispatcher.FSMContext
    :return: None
    """
    await state.update_data(subject=int(callback.data))
    state_data = await state.get_data()

    chat_id = callback.message.chat.id
    message_id = callback.message.message_id

    user = db.get_user_by_id(chat_id)
    if user is None or len(user) == 0:
        logging.error(f"Пользователь не найден в функции show_files_list в showFiles, chat_id={chat_id}")
        return
    user = user[0]

    course = user['course']
    direction = user['direction']
    if 'subject' not in state_data:
        subject = int(callback.data)
    else:
        subject = state_data['subject']
    filesList = db.get_files_by_faculty(0, course, subject, direction)
    if filesList is None:
        buttons = [
            [types.InlineKeyboardButton(text="Вернуться назад", callback_data="ask_subject")]
        ]
        keyboard = types.InlineKeyboardMarkup(inline_keyboard=buttons)
        await bot.edit_message_text(
            chat_id=chat_id,
            reply_markup=keyboard,
            text="Файлов не найдено(",
            message_id=message_id)
        await state.set_state(FindFile.showFile)
        return

    max_page = math.ceil(len(filesList) / 8)
    if "page" not in state_data:
        await state.update_data(page=1)
        page = 1
    else:
        page = int(state_data['page'])
        if page <= 0:
            page = 1
            await state.update_data(page=page)
            return
        if page > max_page:
            page = max_page
            await state.update_data(page=page)
            return

    msg = "Какой файл вы хотите посмотреть?"
    buttons = []
    for file in filesList[8 * (page-1): 8 * page]:
        if file['admin_check'] or user['is_admin']:
            buttons.append([types.InlineKeyboardButton(text=f"{file['filename']}", callback_data=f"{file['file_id']}")])

    buttons.append([
        types.InlineKeyboardButton(text="◀", callback_data="page_left"),
        types.InlineKeyboardButton(text=f"{page} / {max_page}", callback_data="page_none"),
        types.InlineKeyboardButton(text="▶", callback_data="page_right"),
    ])
    buttons.append([types.InlineKeyboardButton(text="Вернуться назад", callback_data="ask_subject")])
    keyboard = types.InlineKeyboardMarkup(inline_keyboard=buttons)
    try:
        await bot.edit_message_text(chat_id=chat_id, reply_markup=keyboard, text=msg, message_id=message_id)
        await state.set_state(FindFile.showFile)
        await state.update_data(subject=subject)
    except aiogram.utils.exceptions.MessageNotModified:
        await callback.answer()

async def page(callback: aiogram.types.CallbackQuery,
               state: aiogram.dispatcher.FSMContext):
    """
    Изменение пагинации

    :param callback: объект aiogram.types.CallbackQuery
    :param state: aiogram.dispatcher.FSMContext
    :return: пересылает на функцию show_files_list
    """
    callback_data = callback.data
    state_data = await state.get_data()
    if callback_data == "page_left":
        callback.data = state_data['subject']
        await state.update_data(page=state_data['page'] - 1)
    elif callback_data == "page_left_sub":
        await state.update_data(page_sub=state_data['page_sub'] - 1)
    elif callback_data == "page_right":
        callback.data = state_data['subject']
        await state.update_data(page=state_data['page'] + 1)
    elif callback_data == "page_right_sub":
        await state.update_data(page_sub=state_data['page_sub'] + 1)
    await callback.answer()
    if callback_data == "page_none":
        return
    if "sub" in callback_data:
        await ask_subject(callback, state)
        return
    await show_files_list(callback, state)

async def show_file_info(callback: aiogram.types.CallbackQuery,
                         state: aiogram.dispatcher.FSMContext):
    """
    Показываем информацию о конкретном файле

    :param callback: объект aiogram.types.CallbackQuery
    :param state: aiogram.dispatcher.FSMContext
    :return: None
    """
    chat_id = callback.message.chat.id
    message_id = callback.message.message_id
    file_id = int(callback.data)

    user = db.get_user_by_id(chat_id)
    if user is None or len(user) == 0:
        logging.error(f"Пользователь не найден в функции show_file_info в showFiles, chat_id={chat_id}")
        return
    user = user[0]

    file = db.get_files_by_file_id(file_id)
    if file is None or len(file) == 0:
        logging.error(f"Файл не найден в функции show_file_info в showFiles, chat_id={chat_id}")
        return
    file = file[0]

    msg = mess_about_file(file)
    buttons = [
        [types.InlineKeyboardButton(text="Скачать", callback_data="download")],
        [types.InlineKeyboardButton(text="Вернуться назад", callback_data="show_files_list")]
    ]
    if user['is_admin']:
        buttons.append([types.InlineKeyboardButton(text="Удалить", callback_data="delete")])
    if user['is_admin']:
        if file['admin_check']:
            buttons.append([types.InlineKeyboardButton(text="Заблокировать", callback_data="ban")])
        else:
            buttons.append([types.InlineKeyboardButton(text="Одобрить", callback_data="un_bun")])
    keyboard = types.InlineKeyboardMarkup(inline_keyboard=buttons)
    await bot.edit_message_text(chat_id=chat_id, reply_markup=keyboard, text=msg, message_id=message_id, parse_mode=types.ParseMode.MARKDOWN)
    await state.set_state(FindFile.currentFile)
    await state.update_data(file_id=file['file_id'])

def register_handle_showFiles(dp: aiogram.Dispatcher):
    dp.register_callback_query_handler(ask_subject, state=FindFile.startFindFile)
    dp.register_callback_query_handler(ask_subject, Text(equals="ask_subject"), state=FindFile.showFile)

    dp.register_callback_query_handler(page, Text(startswith="page"), state=FindFile.askSubject)
    dp.register_callback_query_handler(show_files_list, state=FindFile.askSubject)
    dp.register_callback_query_handler(show_files_list, Text(equals="show_files_list"), state=FindFile.currentFile)
    dp.register_callback_query_handler(page, Text(startswith="page"), state=FindFile.showFile)

    dp.register_callback_query_handler(show_file_info, state=FindFile.showFile)


#!/usr/bin/env python

#(c) Hasiba Asma
#December 2022

#This script can be used to find hits per locus and size of locus
#input directory should be the directory which contain all the output of bedtools closest command (make sure there is nothing else in there)

#this function takes in ortholog dict file and species name and returns the dictionary compOrthoDict[speciesName][]
def orthologsList(orthoFile,speciesName):
	compOrthoDict ={}
	with open(orthoFile) as orf:
		for line in orf:
			geneIDList=[]
			geneID=''
			line=line.strip('\n')
			cols=line.split('\t')
			orthologID=cols[0]
			if cols[1].find(',')!=-1:
				geneIDList=cols[1].split(',')
				if speciesName not in compOrthoDict:
					compOrthoDict[speciesName] = {}
				if orthologID not in compOrthoDict[speciesName]:
					compOrthoDict[speciesName][orthologID] = geneIDList
			#if there is one gene associated with ortholog
			else:
				geneID=cols[1]
				if speciesName not in compOrthoDict:
					compOrthoDict[speciesName] = {}
				if orthologID not in compOrthoDict[speciesName]:
					compOrthoDict[speciesName][orthologID]=geneID
	return(compOrthoDict)

def dictionaryLocus(spex,locusName,scrmCoord):
	#diction={}
	#if locus not in dictionary add it now
	if spex not in diction:
		diction[spex]={}
	if locusName not in diction[spex]:
		#print('flankedgenes not in dictionary yet')
		diction[spex][locusName]=scrmCoord

	#and if it is already there add it in
	else:
		if scrmCoord not in diction[spex][locusName]:
			#print('flanking genes are ',flankedGenes,' butcoord ',coord,' not in dict ',diction[flankedGenes])
			diction[spex][locusName]=diction[spex][locusName]+','+scrmCoord
								#print('added now? ',diction[flankedGenes] )
	return(diction)
# e.g.,
#./checkSameLocus_ForSimulation.py shuffled_files/

import os
import sys
import argparse
import pprint
import re
import csv
import glob

diction={}
def main():
	speciesList=[]
	countOfSpecies={}

	#file=sys.argv[1]
	#takes directory instead
	directory_in_str=sys.argv[1]
	fbgnidFile=sys.argv[2]
	#ortho file
#	OrthodmelOFile=sys.argv[2]
#	OrthoaaegOFile=sys.argv[3]
#	OrthoagamOFile=sys.argv[4]

	a=os.getcwd()
	subdirectory=a+'/'+directory_in_str.strip('/')
	#print(subdirectory)

	#dmelCompleteOrtholog= orthologsList(OrthoDmelOFile,'Dmel')
	#looping over all the files in the subdirectory
	#pprint.pprint(dmelCompleteOrtholog)
	for root, dirs, files in os.walk(subdirectory):
		for filename in files:
			#print(os.path.join(root, filename))
			#print(filename)

			#diction={} #this dictionary would save all locus such that leftFlankedGene-RightFlankedGene would be the key, and value would be all the hits in the locus
			sizeOfLocusDict={} #this dictionary will save size of locus as their values, and locus itself would be the keys
			intronDict={} #for each locus this dictionay would save if the hit is within intron
			locusList=[] #saving all possible/unique locus as a list

			#speciesName=filename.split('_')[2].rstrip('.bed')

			string_split = filename.split(".")
			last_part = string_split[-2]
			#last_part_split = last_part.split("_")
			speciesName=last_part

			#print(speciesName)
			if speciesName not in speciesList:
				speciesList.append(speciesName)
			#glob.glob('Ortho'+speciesName+'OFile')
			#dictFile='Ortho'+speciesName+'OFile'
			#print(dictFile)
			completeOrtholog= orthologsList(speciesName+'_ortholog_dictfile.txt',speciesName)
			#read bed file and create output file with HitsAndSizePerLocus_ beginning

	#reading all files one by one
			with open(os.path.join(root, filename),'r') as infile:
				for line in infile:
					#print(line)
					cols=line.split('\t')
					schr=cols[0]
					sstart=cols[1]
					send=cols[2]
					leftF=cols[14]
					rightF=cols[19]

					if (leftF!= '.') and (rightF!='.'):
						#print(leftF)
						#print(dmelCompleteOrtholog['Dmel'].items())
						for keyO,valO in completeOrtholog[speciesName].items():
							#print(leftF,keyO)
							if leftF == keyO:
								#print(leftF,keyO)
								#print('present')
								#print(dmelCompleteOrtholog[speciesName][leftF])
								leftF=completeOrtholog[speciesName][leftF]
								break

						for keyO,valO in completeOrtholog[speciesName].items():
							#print(leftF,keyO)
							if rightF==keyO:
								#print('present')
								#print(dmelCompleteOrtholog[speciesName][leftF])
								rightF=completeOrtholog[speciesName][rightF]
								break
						#print('none found')
						#try 2:
						#trying to see if there is a fly ortholog then replace the name with that

# 			 			for keyO,valO in completeOrtholog[speciesName].items():
# 							#print(leftF,keyO)
# 							if leftF in keyO:
# 								#print('present')
# 								#print(dmelCompleteOrtholog[speciesName][leftF])
# 								leftF=completeOrtholog[speciesName][leftF]
# 								break
#
# 						for keyO,valO in completeOrtholog[speciesName].items():
# 							#print(leftF,keyO)
# 							if rightF in keyO:
# 								#print('present')
# 								#print(dmelCompleteOrtholog[speciesName][leftF])
# 								rightF=completeOrtholog[speciesName][rightF]
# 								break

						#if leftF in dmelCompleteOrtholog:
						#	print('yes')
						#	print(OrthoDmelOFile[leftF])
						#else:

						sizeOfSCRM=int(send)-int(sstart)
						#sizeOfLocus=sizeOfSCRM+abs(int(cols[15]))+abs(int(cols[20]))
						sizeOfLocus= (int(cols[17]))-(int(cols[13]))

						#exception case where SCRM is overlapping two genes, locus size would be end of right gene - start of left gene
						if (int(sstart) < int(cols[13])) and (int(sstart) < int(cols[17])) and (int(send) > int(cols[13])) and (int(send) > int(cols[17])):
							sizeOfLocus=(int(cols[18]))-(int(cols[12]))

						coord=schr+':'+sstart+'-'+send
						#left and right flanked gene names- saving them together and calling this locus as 'flankedGenes'
						#print(leftF,rightF)
						flankedGenes=str(leftF)+'-'+str(rightF)
						#creating locuslist
						if flankedGenes not in locusList:
							locusList.append(flankedGenes)
							#locusList.append(flankedGenes+':'+str(abs(sizeOfLocus)))
							#creating dictionary to save size of locus, flanked gene as a key
							if flankedGenes not in sizeOfLocusDict:
								sizeOfLocusDict[flankedGenes]=str(abs(sizeOfLocus))

							#adding intron information
							if leftF==rightF:
								intronDict[flankedGenes]='intronic'
							else:
								intronDict[flankedGenes]='not-intronic'

						#add this to a function.. create dictionary for each species i guess??
						diction=dictionaryLocus(speciesName,flankedGenes,coord)

			#pprint.pprint(diction)
			#exit(0)
			#print(locusList)
			#if there is need to create a file for  size and hits per locus thing
			# with open('HitsAndSizePerLocus_'+filename,'w') as outfile:
# 				for item in diction[speciesName].keys():
# 					#print(item)
# 					scrms=diction[speciesName][item].split(',')
# 					#print(scrms)
# 					#print(item,' ',str(len(scrms)),' ',sizeOfLocusDict[item])
# 					outfile.write(item+'\t'+str(len(scrms))+'\t'+sizeOfLocusDict[item]+'\t'+intronDict[item]+'\t'+filename+'\n')
#
	#go through all the dmel genes one by one and scanning all species locus directory, if present add + 1 to count dictionary
	with open(fbgnidFile, 'r') as fb:#, open('finalOutput_orthoPara_test.txt', 'a') as out:
		for line in fb:
			if line.startswith('#') or line == '\n':
				continue

			else:

				geneFBsymb = line.strip('\n')
				geneID = geneFBsymb
				#print('geneid',geneID)
				if geneID not in countOfSpecies:
					countOfSpecies[geneID]=0
				for species in speciesList:
					#print(species)
					for locus in diction[species]:
						out=0
						#print('locus',locus)
						genes=locus.split('-')
						for gene in genes:
							#print('gene',gene)
							#print('geneid',geneID)
							if geneID==gene:
								#print(geneID,gene)
								#print('break')
								countOfSpecies[geneID]+=1
								out=1
								break
						if out==1:
							break

		#pprint.pprint(countOfSpecies)

		#
		#geneListGreaterThan1=[word for word, occurrences in countOfSpecies.items() if occurrences >= 1]
		geneListGreaterThan5=[word for word, occurrences in countOfSpecies.items() if occurrences >= 5]
		geneListGreaterThan10=[word for word, occurrences in countOfSpecies.items() if occurrences >= 10]
		geneListGreaterThan11=[word for word, occurrences in countOfSpecies.items() if occurrences >= 11]
		geneListGreaterThan12=[word for word, occurrences in countOfSpecies.items() if occurrences >= 12]
		geneListGreaterThan13=[word for word, occurrences in countOfSpecies.items() if occurrences >= 13]
		geneListGreaterThan14=[word for word, occurrences in countOfSpecies.items() if occurrences >= 14]
		geneListGreaterThan15=[word for word, occurrences in countOfSpecies.items() if occurrences >= 15]
		geneListGreaterThan16=[word for word, occurrences in countOfSpecies.items() if occurrences >= 16]
		#print(geneListGreaterThan16)
		print(len(geneListGreaterThan5),len(geneListGreaterThan10),len(geneListGreaterThan11),len(geneListGreaterThan12),len(geneListGreaterThan13),len(geneListGreaterThan14),len(geneListGreaterThan15),len(geneListGreaterThan16))
		#['who', 'joey']
				# for k, v in diction.items():
# 					print('v',v)
# 					for x in v.items():
#
# 						print('x',x)
# 						print('xkey',x.keys())

main()


# This code takes the data from the text file and adds it to the csv file.
import re
import csv

number_of_questions = 16
number_of_options = 5

number_of_studs = 10
w, h = number_of_questions*number_of_options + 2, number_of_studs;

Matrix = [["0" for x in range(w)] for y in range(h)]

def initr():
    with open("/Users/pavan/Desktop/Research/Masters_Project/SRC/assessments/assess1_LP.txt",'r') as f:
        mylist = f.read().splitlines()
    return mylist

def scrape(lines):
    ID = []
    r = 1
    for line in lines:
        my_list = line.split("&")
        for obj in my_list:
            keyval = obj.split("=")
            if keyval[0] == "ID":
                c = 0
            elif keyval[0] == "time":
                c = 1
            else:
                c = int(keyval[0]) + 1

            if keyval[1] == "on":
                val = "1"
            else:
                val = keyval[1]

            Matrix[r][c] = val
            Matrix[0][0] = "ID"
            Matrix[0][1] = "Time"
        r = r + 1
    return Matrix,r-1

# WIPES PREVIOUS ENTRIES INTO CSV. SAVE INSTANCE!!
def save_to_csv(db,r):
    with open("/Users/pavan/Desktop/Research/Masters_Project/SRC/assessments/assess1_LP.csv", "wb") as f:
        writer = csv.writer(f)
        writer.writerows(db[0:r+1][:])

if __name__ == '__main__':
    lines = initr()
    db,r = scrape(lines)
    save_to_csv(db,r)


import re

# the following are the regular expressions patterns
# .       - Any Character Except New Line
# \d      - Digit (0-9)
# \D      - Not a Digit (0-9)
# \w      - Word Character (a-z, A-Z, 0-9, _)
# \W      - Not a Word Character
# \s      - Whitespace (space, tab, newline)
# \S      - Not Whitespace (space, tab, newline)

# the following are anchors for patterns
# \b      - Word Boundary (Whitespace (space, tab, newline) before the pattern)
# \B      - Not a Word Boundary (NO Whitespace (space, tab, newline) before the pattern)
# ^       - Beginning of a String (only recognizes matches the are at the very beginning of the string)
# $       - End of a String (only recognizes matches the are at the very end of the string)

# []      - Matches Characters in brackets (only find matches that are in the character set) (character sets don't need to be escaped and are not in any order)
# [^ ]    - Matches Characters NOT in brackets
# |       - Either Or
# ( )     - Group (this allows us to use different patterns in the same locations with using | between our different patterns)

# Quantifiers: (used after the pattern)
# *       - 0 or More
# +       - 1 or More
# ?       - 0 or One
# {3}     - Exact Number
# {3,4}   - Range of Numbers (Minimum, Maximum)

# #### Sample Regexs ####

# [a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+

text_to_search = """
abcdefghijklmnopqurtuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
1234567890

Ha HaHa

MetaCharacters (Need to be escaped):
. ^ $ * + ? { } [ ] \ | ( )

coreyms.com

321-555-4321
123.555.1234
123*555*1234
800-555-1234
900-555-1234

Mr. Schafer
Mr Smith
Ms Davis
Mrs. Robinson
Mr. T

pat
mat
cat
bat
"""
sentence = "Start a sentence and then bring it to an end"

pattern = re.compile(r"\d{3}.\d{3}.\d{4}")
matches = pattern.finditer(text_to_search)

# for match in matches:
#     print(match)

pattern = re.compile(r"Mr\.?\s[A-Z]\w*")
matches = pattern.finditer(text_to_search)

# for match in matches:
#     print(match)

# using groups is the best way to match different patterns in one location
pattern = re.compile(r"(Mr|Ms|Mrs)\.?\s[A-Z]\w*")
matches = pattern.finditer(text_to_search)

for match in matches:
    print(match)


from django.shortcuts import render
from sinapi.models import Material as sinapi_Material
from .models import Material,Material_Historico_Precos
from classifier.NCM import NCM
from classifier.Request import RequestSEFAZ
from classifier.KNN import KNN
from django.db import IntegrityError
from AquiSeFaz.views import retriveAPIs
import pandas as pd

# Create your views here.

def ecoal():
    try:
        print("Atualizando Economiza Alagoas")
        base = NCM(None)
        base.data = pd.DataFrame(list(sinapi_Material.objects.all().values('cod', 'description')))
        base.generalizeString(column='description')
        knn = KNN('classifier/train_NCM.csv', 6)

        #codSinapi, ncm, description, price
        for row in base.data.iterrows():
            termo = row[1]['description']
            r = RequestSEFAZ()
            ecoData = r.request(term=termo)

            for dictionary in ecoData.json():
                if (knn.classifier(int(dictionary['codNcm'])) == "MATERIAIS DE CONSTRUCAO"):
                    try:
                        newMaterial,created = Material.objects.get_or_create(
                            codSinapi=row[1]['cod'],
                            codGtin=dictionary['codGetin'],
                            ncm=dictionary['codNcm'],
                            description=dictionary['dscProduto']
                        )
                    except IntegrityError: continue
                    except:
                        return False

                    try:
                        newMaterialPreco = Material_Historico_Precos(
                            idMaterial=newMaterial,
                            price=dictionary['valUnitarioUltimaVenda']
                        )

                        newMaterialPreco.save()
                    except IntegrityError: continue
                    except:
                        return False
        return True
    except:
        return False


# -*- coding: UTF-8 -*-

import warnings
warnings.filterwarnings("ignore")
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from data_picture_util import plot_confusin_pictures ,read_pkl_data,read_ups_data
import numpy as np
from sklearn.metrics import accuracy_score

def main(X_train, y_train,X_test, y_test ,savename):

    cart = DecisionTreeClassifier()
    models = []
    model_log = LogisticRegression()
    models.append(('log',model_log))
    print("model1 created....")
    model_cart = DecisionTreeClassifier()
    models.append(('cart',model_cart))
    print("model2 created....")
    model_svc = SVC()
    models.append(('svm',model_svc))
    print("model3 created....")
    ensemble_model = VotingClassifier(estimators=models)
    ensemble_model.fit(X_train, y_train)
    accuracy=ensemble_model.score(X_train, y_train)
    print("model_traiing_accuracy %f"%accuracy)
    print("prediction....")
    predictions=ensemble_model.predict(X_test)
    print(predictions)
    predictions_accuracy=accuracy_score(y_test, predictions)
    print("model_testing_accuracy %f"%predictions_accuracy)
    plot_confusin_pictures(y_test,predictions,save_name='voting_confusion_matrix_%s.png'%savename)
if __name__ == '__main__':
    # # ********************************************************
    # _train, y_train, X_test, y_test = read_pkl_data()
    # main(X_train, y_train,X_test, y_test ,"data1")

    # # # ********************************************************
    X_train, y_train, _, _ = read_pkl_data()
    X_test, y_test ,_ ,_= read_ups_data()
    main(X_train, y_train ,X_test, y_test ,"data2")
    # ##################################################################################


# %%
def bio(chars, tag):
    tag = tag.upper()
    if tag == 'O':
        tags = [tag] * len(chars)
    else:
        tags = ['B-'+tag] + ['I-'+tag] * (len(chars) - 1)
    return list(zip(chars, tags))

def bioes(chars, tag):
    tag = tag.upper()
    if tag == 'O':
        tags = [tag] * len(chars)
    elif len(chars) == 1:
        tags = ['S-'+tag]
    else:
        tags = ['B-'+tag] + ['I-'+tag] * (len(chars) - 2) + ['E-'+tag]
    return list(zip(chars, tags))
# %%
def process(file, target, mode = "bio"):
    if mode == "bio":
        labeling = bio
    elif mode == "bioes":
        labeling = bioes
    else:
        raise NotImplementedError
    with open(file, encoding="utf-8")as f:
        lines = f.readlines()
    new_lines = []
    for line in lines:
        new_line = []
        line = line.strip()
        words = line.split(" ")
        for word in words:
            chars, tag = word.split("/")
            new_line += labeling(chars, tag)
        new_lines.append(new_line)
    with open(target, "w", encoding="utf-8")as fw:
        fw.writelines("\n\n".join(["\n".join([" ".join(pair) for pair in line]) for line in new_lines]))

# %%
if __name__ == "__main__":
    process("./data/raw/train1.txt", "./data/processed/train1_bio.txt", "bio")
    process("./data/raw/train1.txt", "./data/processed/train1_bioes.txt", "bioes")
    process("./data/raw/testright1.txt", "./data/processed/testright_bio.txt", "bio")
    process("./data/raw/testright1.txt", "./data/processed/testright_bioes.txt", "bioes")

# %%


# 167. Two Sum II - Input Array Is Sorted

# Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number. Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length.
# Return the indices of the two numbers, index1 and index2, added by one as an integer array [index1, index2] of length 2.
# The tests are generated such that there is exactly one solution. You may not use the same element twice.
# Your solution must use only constant extra space.

# Example 1:
# Input: numbers = [2,7,11,15], target = 9
# Output: [1,2]
# Explanation: The sum of 2 and 7 is 9. Therefore, index1 = 1, index2 = 2. We return [1, 2].

# Example 2:
# Input: numbers = [2,3,4], target = 6
# Output: [1,3]
# Explanation: The sum of 2 and 4 is 6. Therefore index1 = 1, index2 = 3. We return [1, 3].

# Example 3:
# Input: numbers = [-1,0], target = -1
# Output: [1,2]
# Explanation: The sum of -1 and 0 is -1. Therefore index1 = 1, index2 = 2. We return [1, 2].

from typing import List

class Solution:

    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        slow = 0
        fast = slow + 1
        while slow < len(numbers):
            while fast < len(numbers):
                if numbers[slow] + numbers[fast] == target:
                    return [slow + 1, fast + 1]
                fast = fast + 1

            slow = slow + 1
            fast = slow + 1
        return [-1, -1]

    def twoSum1(self, numbers: List[int], target: int) -> List[int]:
        low = 0
        high = len(numbers) - 1
        while low < high:
            total = numbers[low] + numbers[high]
            if total == target:
                return [low + 1, high + 1]
            elif total < target:
                low += 1
            else:
                high -= 1

        return [-1, -1]

# test
solution = Solution()
res = solution.twoSum([2, 7, 11, 15], 9)
res1 = solution.twoSum1([2, 7, 11, 15], 9)
print(res)
print(res1)

Data Structure & Algorithm/Algorithm/Two Point/en/Left & Right/167. Two Sum II - Input Array Is Sorted/167. Two Sum II - Input Array Is Sorted.py


import torch.nn as nn
import torch
import math
from torch import functional as F
from torch._six import container_abcs
from itertools import repeat

class Conv2d(torch.autograd.Function):
    @staticmethod
    def forward(self, x, weight, weight_fluidity):
        '''
            The forward computation for a convolution function

            Arguments:
            X -- output activations of the previous layer, numpy array of shape (n_H_prev, n_W_prev) assuming input channels = 1
            W -- Weights, numpy array of size (f, f) assuming number of filters = 1

            Returns:
            H -- conv output, numpy array of size (n_H, n_W)
            cache -- cache of values needed for conv_backward() function
            '''
        # https://becominghuman.ai/back-propagation-in-convolutional-neural-networks-intuition-and-code-714ef1c38199

        # Retrieving dimensions from X's shape
        (_, n_H_prev, n_W_prev, _) = x.shape

        # Retrieving dimensions from W's shape
        (_, f, f, _) = weight.shape

        # Compute the output dimensions assuming no padding and stride = 1
        n_H = n_H_prev - f + 1
        n_W = n_W_prev - f + 1

        # Initialize the output H with zeros
        H = torch.zeros((n_H, n_W))

        # Looping over vertical(h) and horizontal(w) axis of output volume
        for h in range(n_H):
            for w in range(n_W):
                x_slice = x[h:h + f, w:w + f]
                H[h, w] = torch.sum(x_slice * weight)

        # Saving information in 'cache' for backprop
        self.save_for_backward(x, weight, weight_fluidity)

        return H

    @staticmethod
    def backward(self, dy):
        # https://towardsdatascience.com/backpropagation-in-a-convolutional-layer-24c8d64d8509
        '''
            The backward computation for a convolution function

            Arguments:
            dH -- gradient of the cost with respect to output of the conv layer (H), numpy array of shape (n_H, n_W) assuming channels = 1
            cache -- cache of values needed for the conv_backward(), output of conv_forward()

            Returns:
            dX -- gradient of the cost with respect to input of the conv layer (X), numpy array of shape (n_H_prev, n_W_prev) assuming channels = 1
            dW -- gradient of the cost with respect to the weights of the conv layer (W), numpy array of shape (f,f) assuming single filter
            '''

        # Retrieving information from the "cache"
        (X, W, ws) = self.saved_tensors

        # Retrieving dimensions from X's shape
        (n_H_prev, n_W_prev) = X.shape

        # Retrieving dimensions from W's shape
        (f, f) = W.shape

        # Retrieving dimensions from dH's shape
        (n_H, n_W) = dy.shape

        # Initializing dX, dW with the correct shapes
        dX = torch.zeros(X.shape)
        dW = torch.zeros(W.shape)

        # Looping over vertical(h) and horizontal(w) axis of the output
        for h in range(n_H):
            for w in range(n_W):
                dX[h:h + f, w:w + f] += W * dy(h, w)
                dW += X[h:h + f, w:w + f] * dy(h, w)

        return dX, dW

x = torch.tensor([[[[3.], [4.]], [[5.], [6.]]]], requires_grad=True)
w = torch.tensor([[[[1.], [2.]], [[1.], [2.]]]], requires_grad=True)
wf = torch.tensor([[[[.5], [.1]], [[1], [.2]]]], requires_grad=True)
m = Conv2d.apply(x, w, wf)
print(m)
m.backward()
print(x.grad.data)
print(w.grad.data)
print(wf.grad.data)

'''
class _ConvNd(nn.Module):
    __constants__ = [
        "stride",
        "padding",
        "dilation",
        "groups",
        "bias",
        "padding_mode",
        "output_padding",
        "in_channels",
        "out_channels",
        "kernel_size",
    ]

    def __init__(
            self,
            in_channels,
            out_channels,
            kernel_size,
            stride,
            padding,
            dilation,
            transposed,
            output_padding,
            groups,
            bias,
            padding_mode,
            weight_solidifying_rate=.001,
            sparse_activation_percentage=.02
    ):
        super(_ConvNd, self).__init__()
        if in_channels % groups != 0:
            raise ValueError("in_channels must be divisible by groups")
        if out_channels % groups != 0:
            raise ValueError("out_channels must be divisible by groups")
        self.in_channels = in_channels
        self.out_channels = out_channels
        self.kernel_size = kernel_size
        self.stride = stride
        self.padding = padding
        self.dilation = dilation
        self.transposed = transposed
        self.output_padding = output_padding
        self.groups = groups
        self.padding_mode = padding_mode
        self.weight_solidifying_rate = weight_solidifying_rate
        self.sparse_activation_percentage = sparse_activation_percentage
        if transposed:
            tensor_init = in_channels, out_channels // groups, *kernel_size
        else:
            tensor_init = out_channels, in_channels // groups, *kernel_size
        self.weight = nn.Parameter(
            torch.Tensor(*tensor_init)
        )
        self.weight_importance = nn.parameter(
            torch.Tensor(*tensor_init)
        )
        if bias:
            self.bias = nn.Parameter(torch.Tensor(out_channels))
        else:
            self.register_parameter("bias", None)
        self.reset_parameters()

    def reset_parameters(self):
        nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5))
        nn.init.zeros_(self.weight_importance)
        if self.bias is not None:
            fan_in, _ = nn.init._calculate_fan_in_and_fan_out(self.weight)
            bound = 1 / math.sqrt(fan_in)
            nn.init.uniform_(self.bias, -bound, bound)

    def extra_repr(self):
        s = (
            "{in_channels}, {out_channels}, kernel_size={kernel_size}"
            ", stride={stride}"
        )
        if self.padding != (0,) * len(self.padding):
            s += ", padding={padding}"
        if self.dilation != (1,) * len(self.dilation):
            s += ", dilation={dilation}"
        if self.output_padding != (0,) * len(self.output_padding):
            s += ", output_padding={output_padding}"
        if self.groups != 1:
            s += ", groups={groups}"
        if self.bias is None:
            s += ", bias=False"
        return s.format(**self.__dict__)

    def __setstate__(self, state):
        super(_ConvNd, self).__setstate__(state)
        if not hasattr(self, "padding_mode"):
            self.padding_mode = "zeros"

def _ntuple(n):
    def parse(x):
        if isinstance(x, container_abcs.Iterable):
            return x
        return tuple(repeat(x, n))

    return parse

_single = _ntuple(1)
_pair = _ntuple(2)
_triple = _ntuple(3)
_quadruple = _ntuple(4)

class Conv2d(_ConvNd):
    r"""Applies a 2D convolution over an input signal composed of several input
    planes.

    In the simplest case, the output value of the layer with input size
    :math:`(N, C_{\text{in}}, H, W)` and output :math:`(N, C_{\text{out}}, H_{\text{out}}, W_{\text{out}})`
    can be precisely described as:

    .. math::
        \text{out}(N_i, C_{\text{out}_j}) = \text{bias}(C_{\text{out}_j}) +
        \sum_{k = 0}^{C_{\text{in}} - 1} \text{weight}(C_{\text{out}_j}, k) \star \text{input}(N_i, k)

    where :math:`\star` is the valid 2D `cross-correlation`_ operator,
    :math:`N` is a batch size, :math:`C` denotes a number of channels,
    :math:`H` is a height of input planes in pixels, and :math:`W` is
    width in pixels.

    * :attr:`stride` controls the stride for the cross-correlation, a single
      number or a tuple.

    * :attr:`padding` controls the amount of implicit zero-paddings on both
      sides for :attr:`padding` number of points for each dimension.

    * :attr:`dilation` controls the spacing between the kernel points; also
      known as the à trous algorithm. It is harder to describe, but this `link`_
      has a nice visualization of what :attr:`dilation` does.

    * :attr:`groups` controls the connections between inputs and outputs.
      :attr:`in_channels` and :attr:`out_channels` must both be divisible by
      :attr:`groups`. For example,

        * At groups=1, all inputs are convolved to all outputs.
        * At groups=2, the operation becomes equivalent to having two conv
          layers side by side, each seeing half the input channels,
          and producing half the output channels, and both subsequently
          concatenated.
        * At groups= :attr:`in_channels`, each input channel is convolved with
          its own set of filters, of size:
          :math:`\left\lfloor\frac{out\_channels}{in\_channels}\right\rfloor`.

    The parameters :attr:`kernel_size`, :attr:`stride`, :attr:`padding`, :attr:`dilation` can either be:

        - a single ``int`` -- in which case the same value is used for the height and width dimension
        - a ``tuple`` of two ints -- in which case, the first `int` is used for the height dimension,
          and the second `int` for the width dimension

    .. note::

         Depending of the size of your kernel, several (of the last)
         columns of the input might be lost, because it is a valid `cross-correlation`_,
         and not a full `cross-correlation`_.
         It is up to the user to add proper padding.

    .. note::

        When `groups == in_channels` and `out_channels == K * in_channels`,
        where `K` is a positive integer, this operation is also termed in
        literature as depthwise convolution.

        In other words, for an input of size :math:`(N, C_{in}, H_{in}, W_{in})`,
        a depthwise convolution with a depthwise multiplier `K`, can be constructed by arguments
        :math:`(in\_channels=C_{in}, out\_channels=C_{in} \times K, ..., groups=C_{in})`.

    .. include:: cudnn_deterministic.rst

    Args:
        in_channels (int): Number of channels in the input image
        out_channels (int): Number of channels produced by the convolution
        kernel_size (int or tuple): Size of the convolving kernel
        stride (int or tuple, optional): Stride of the convolution. Default: 1
        padding (int or tuple, optional): Zero-padding added to both sides of the input. Default: 0
        padding_mode (string, optional). Accepted values `zeros` and `circular` Default: `zeros`
        dilation (int or tuple, optional): Spacing between kernel elements. Default: 1
        groups (int, optional): Number of blocked connections from input channels to output channels. Default: 1
        bias (bool, optional): If ``True``, adds a learnable bias to the output. Default: ``True``

    Shape:
        - Input: :math:`(N, C_{in}, H_{in}, W_{in})`
        - Output: :math:`(N, C_{out}, H_{out}, W_{out})` where

          .. math::
              H_{out} = \left\lfloor\frac{H_{in}  + 2 \times \text{padding}[0] - \text{dilation}[0]
                        \times (\text{kernel\_size}[0] - 1) - 1}{\text{stride}[0]} + 1\right\rfloor

          .. math::
              W_{out} = \left\lfloor\frac{W_{in}  + 2 \times \text{padding}[1] - \text{dilation}[1]
                        \times (\text{kernel\_size}[1] - 1) - 1}{\text{stride}[1]} + 1\right\rfloor

    Attributes:
        weight (Tensor): the learnable weights of the module of shape
                         :math:`(\text{out\_channels}, \frac{\text{in\_channels}}{\text{groups}},`
                         :math:`\text{kernel\_size[0]}, \text{kernel\_size[1]})`.
                         The values of these weights are sampled from
                         :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` where
                         :math:`k = \frac{1}{C_\text{in} * \prod_{i=0}^{1}\text{kernel\_size}[i]}`
        bias (Tensor):   the learnable bias of the module of shape (out_channels). If :attr:`bias` is ``True``,
                         then the values of these weights are
                         sampled from :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` where
                         :math:`k = \frac{1}{C_\text{in} * \prod_{i=0}^{1}\text{kernel\_size}[i]}`

    Examples::

        >>> # With square kernels and equal stride
        >>> m = nn.Conv2d(16, 33, 3, stride=2)
        >>> # non-square kernels and unequal stride and with padding
        >>> m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2))
        >>> # non-square kernels and unequal stride and with padding and dilation
        >>> m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1))
        >>> input = torch.randn(20, 16, 50, 100)
        >>> output = m(input)

    .. _cross-correlation:
        https://en.wikipedia.org/wiki/Cross-correlation

    .. _link:
        https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md
    """

    def __init__(self, in_channels, out_channels, kernel_size, stride=1,
                 padding=0, dilation=1, groups=1,
                 bias=True, padding_mode='zeros'):
        kernel_size = _pair(kernel_size)
        stride = _pair(stride)
        padding = _pair(padding)
        dilation = _pair(dilation)
        super(Conv2d, self).__init__(
            in_channels, out_channels, kernel_size, stride, padding, dilation,
            False, _pair(0), groups, bias, padding_mode)

    def conv2d_forward(self, input, weight):
        if self.padding_mode == 'circular':
            expanded_padding = ((self.padding[1] + 1) // 2, self.padding[1] // 2,
                                (self.padding[0] + 1) // 2, self.padding[0] // 2)
            return F.conv2d(F.pad(input, expanded_padding, mode='circular'),
                            weight, self.bias, self.stride,
                            _pair(0), self.dilation, self.groups)
        return F.conv2d(input, weight, self.bias, self.stride,
                        self.padding, self.dilation, self.groups)

    def forward(self, input):
        return self.conv2d_forward(input, self.weight)
'''


import pygame
import random
from icon import Icon

# Class for all the methods required when playing the slot machine
class SlotMachine:
    MAIN_MSG = "Fel's Slot Machine"
    YOU_WIN = "You just won $"
    YOU_WIN_JACKPOT = "Jackpot won $"
    YOU_LOST = "You just lost $"
    YOU_BET = "You bet $"
    NO_CASH_LEFT = "Cannot bet to that amount. Cash not enough."
    CANNOT_SPIN = "Cannot spin. Cash not enough."
    STARTING_BET = 10
    JACKPOT_INCREASE_RATE = .15

    # Function that gets the starting jackpot price and the starting cash amount as the parameters.
    def __init__(self, starting_jackpot, starting_cash):
        # To set all sounds
        pygame.mixer.init()
        self.bet_snd = pygame.mixer.Sound("sounds/bet_snd.wav")
        self.bet_no_cash_snd = pygame.mixer.Sound("sounds/bet_no_cash_snd.wav")
        self.spin_snd = pygame.mixer.Sound("sounds/spin_snd.ogg")
        self.spinning_snd = pygame.mixer.Sound("sounds/spinning_snd.ogg")
        self.reset_snd = pygame.mixer.Sound("sounds/reset_snd.ogg")

        # Setting the starting values
        self.starting_jackpot = starting_jackpot
        self.starting_cash = starting_cash

        # Setting the icons/images that would be in the reels
        self.icons = []
        self.__create_icons()

        # To call the method used to set the initial values
        self.set_resettable_values()

    # Function to set values of slot machine which are resettable
    def set_resettable_values(self):
        self.current_message = SlotMachine.MAIN_MSG
        self.current_jackpot = self.starting_jackpot
        self.current_cash = self.starting_cash
        self.results = 3*["Seven"]
        self.bet = SlotMachine.STARTING_BET

    # Function to create and set icons in an array
    def __create_icons(self):
    # The bonus win rate is for when no sad face appeared on the reel
        self.icons.append(Icon("Sad Face", 0, 0, "sadface.png", bonus_win_rate = 1))
        self.icons.append(Icon("Bell", 10, 1, "bell.png"))
        self.icons.append(Icon("Cherry", 20, 2, "cherry.png"))
        self.icons.append(Icon("Melon", 30, 2, "melon.png"))
        self.icons.append(Icon("Orange", 100, 2, "orange.png"))
        self.icons.append(Icon("Grape", 200, 2, "grape.png"))
        self.icons.append(Icon("Diamond", 300, 5, "diamond.png"))
        self.icons.append(Icon("Seven", 1000, 10, "seven.png", bonus_win_rate = 5))

    # Function to set a bet
    def set_bet(self, bet):
        # When valid, users are allow to bet.
        if self.current_cash - bet >= 0:
            self.bet = bet
            self.current_message = SlotMachine.YOU_BET + str(self.bet)
            self.bet_snd.play()
        # Otherwise, it'll tell users that they're out of cash.
        else:
            self.current_message = SlotMachine.NO_CASH_LEFT
            self.bet_no_cash_snd.play()

    # Functions to get attributes
    def get_bet(self):
        return self.bet

    def get_current_cash(self):
        return self.current_cash

    def get_current_jackpot(self):
        return self.current_jackpot

    def get_current_message(self):
        return self.current_message

    # Function to spin the reels. Spinning is only allowed when there is enough money to do so.
    def spin(self):
        if self.current_cash - self.bet >= 0:
            self.spin_snd.play()
            # pay the bet and increase the jackpot
            self.__pay()
            self.__increase_jackpot()

            # For each reel,
            for spin in range(3):
                # Save the wildcard number as spinned_result
                spinned_result = random.randint(0, 100)

                if spinned_result in range(0, 40):     # 40% Chance
                    self.results[spin] = self.icons[0].name
                elif spinned_result in range(40, 56):  # 16% Chance
                    self.results[spin] = self.icons[1].name
                elif spinned_result in range(56, 70):  # 14% Chance
                    self.results[spin] = self.icons[2].name
                elif spinned_result in range(70, 82):  # 12% Chance
                    self.results[spin] = self.icons[3].name
                elif spinned_result in range(82, 89):  # 7% Chance
                    self.results[spin] = self.icons[4].name
                elif spinned_result in range(89, 95):  # 6% Chance
                    self.results[spin] = self.icons[5].name
                elif spinned_result in range(95, 99):  # 4% Chance
                    self.results[spin] = self.icons[6].name
                elif spinned_result in range(99, 100):  # 1% Chance
                    self.results[spin] = self.icons[7].name

            # To check the result of the calculation rewards.
            self.__check_results()
        else:
            # Show the reason why the slot machine cannot be spinned
            self.current_message = SlotMachine.CANNOT_SPIN

    # Function to reduce cash by the bet amount everytime the user spin the slot machine.
    def __pay(self):
        self.current_cash -= self.bet

    # Function to increase the jackpot prize to be winned
    def __increase_jackpot(self):
        self.current_jackpot += (int(self.bet * SlotMachine.JACKPOT_INCREASE_RATE))

    # Function to check how much the player won or lost
    def __check_results(self):
        winnings = 0
        jackpot_won = 0
        # Go through each icon and check how many of the said icon is present. Base on that, check how much the player have won.
        for icon in self.icons:
            # Check how many of this icon is on the reel. Then multiply the win rate to the bet and add it to winnings.
            if self.results.count(icon.name) == 3:
                winnings += self.bet * icon.win_rate_full
                # Play jackpot when 3 of a kind and not sadface is the result
                if winnings > 0:
                    jackpot_won = self.jackpot_win()
            if self.results.count(icon.name) == 2:
                winnings += self.bet * icon.win_rate_two
        # If there is 1 Seven, it is considered a win
        if self.results.count(self.icons[7].name) == 1:
            winnings += self.bet * self.icons[7].bonus_win_rate
        # If there is no sad face, it is considered a bet return win
        if self.results.count(self.icons[0].name) == 0:
            winnings += self.bet * self.icons[0].bonus_win_rate

        # Set the appropriate message for:
        # If the user won the jackpot
        if jackpot_won > 0:
            self.current_message = SlotMachine.YOU_WIN_JACKPOT + str(jackpot_won) + " With Cash $" + str(winnings)
        # Or if the user won something
        elif winnings > 0:
            self.current_cash += winnings
            self.current_message = SlotMachine.YOU_WIN + str(winnings)
        # Or if the user lost
        elif winnings <= 0:
            self.current_message = SlotMachine.YOU_LOST + str(self.bet)
        else:
            self.current_message = "Somethings wrong"

    # Function to return the value of the user's jackpot winnings
    def jackpot_win(self):
        # Set the wildcard jackpot number
        JACKPOT_WILDCARD = 7
        # Generate a random number from 1 to 100
        jackpot_try = random.randint(1, 100)
        winnings = 0

        # Compare the wildcard to the random number
        if jackpot_try == JACKPOT_WILDCARD:
            # If they match, then the user wins
            self.current_cash += self.current_jackpot
            # Set the current jackpot as the winnings.
            winnings = self.current_jackpot
            # Reset the jackpot
            self.current_jackpot = self.starting_jackpot
        return winnings

    # Function to reset the slot machine when started
    def reset(self):
        self.set_resettable_values()


import sys
import os
import re
import json
# import yaml
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element
from xml.dom import minidom
from configparser import ConfigParser, SectionProxy
from datetime import datetime, timedelta
from pytz import timezone
from Configuration import Configuration

# Set of allowed config file types.
ALLOWED_CONFIG_FILE_TYPES = {'cfg', 'conf', 'config', 'ini', 'json', 'xml', 'yaml', 'yml'}
# Set of allowed `true` string values.
ALLOWED_TRUE_STRINGS = {'true', 't', 'yes', 'y'}
# Set of allowed `false` string values.
ALLOWED_FALSE_STRINGS = {'false', 'f', 'no', 'n'}
# Set of allowed export file types.
ALLOWED_EXPORT_FILE_TYPES = {'json', 'xml', 'yaml', 'yml'}

# Regex for seeing if a string contains `Start` or `End`
START_END_REGEX = r'(Starts|Ends):'
# Regex for seeing if a string contains `All Day`
ALL_DAY_REGEX = r'All\sDay'
# Regex for retrieving the date from a string
DATE_REGEX = r'(0?\d|1[0-2])/(0?\d|[12]\d|3[01])/([12]\d{3})'
# Regex for retrieving the time from a string
TIME_REGEX = r'(0?[0-9]|1[0-2]):([0-5][0-9])(:[0-5][0-9])?\s?[AP]\.?M\.?'
# Regex for retrieving the contact name from a contact info string
CONTACT_NAME_REGEX = r'^[a-zA-Z ,-]+$'
# Regex for retrieving the phone number from a contact info string
PHONE_NUMBER_REGEX = r'\(?\d{3}\)?(\s|-)?\d{3}(\s|-)?\d{4}'
# Regex for retrieving the email from a contact info string
EMAIL_REGEX = r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9.-]+'

class InvalidExportFileTypeError(Exception):
    """An exception that indicates that the export file path has an invalid file type."""
    pass

class InvalidConfigFileTypeError(Exception):
    """An exception that indicates a config file had an invalid file type."""
    pass

class InvalidConfigFileValueError(Exception):
    """An exception that indicates a config file contained invalid values."""
    pass

class InvalidArgumentsError(Exception):
    """An exception that indicates that the command line arguments for the program's execution are invalid."""
    pass

class OverwriteExistingFileError(Exception):
    """An exception that indicates a file already exists and the program cannot overwrite it."""
    pass

def eval_config_file_boolean(text_value):
    """Convert a config file text value into a boolean.

    Parameters
    ----------
    text_value : str
        The text value to be converted into a boolean

    Returns
    -------
    bool
        True -- if the text value is one of the accepted `true` strings;
        False -- if the text value is one of the accepted `false` strings

    Raises
    ------
    InvalidConfigFileValueError
        If the text value does is not any of the accepted `true` or `false` strings.
    """

    # Return True if the text value is one of the accepted `true` strings
    if text_value.strip().lower() in ALLOWED_TRUE_STRINGS:
        return True
    # Return False if the text value is one of the accepted `false` strings
    elif text_value.strip().lower() in ALLOWED_FALSE_STRINGS:
        return False
    # Else, raise an InvalidConfigFileValueError exception
    else:
        raise InvalidConfigFileValueError('`{}` is not a valid value for the config file'.format(text_value))

def validate_start_end_pages(start_page, end_page):
    """Validate the start and end pages of the configuration settings.

    Parameters
    ----------
    start_page : int
        page where the web scraper will begin extracting information
    end_page : int
        page where the web scraper will stop extracting information

    Raises
    ------
    InvalidConfigFileValueError
        if the start and/or end pages are invalid
    """

    # If the start page is negative
    if start_page < 0:
        raise InvalidConfigFileValueError('Start page must be a non-negative number. The number given was `{}`'
                                          .format(start_page+1))
    # If the end page is negative
    if end_page < 0:
        raise InvalidConfigFileValueError('End page must be greater than or equal to 1. The number given was `{}`'
                                          .format(end_page))
    # If the end page comes before the start page
    if end_page < start_page:
        raise InvalidConfigFileValueError('End page must be at or after start page, not before.')

def check_file_extension_exists(file_name):
    """Check to see if the file name has a file extension.

    Parameters
    ----------
    file_name : str
        name of the file to check

    Raises
    ------
    InvalidConfigFileValueError
        if there is no file extension
    """

    if len(file_name.rsplit('.', 1)) < 2:
        raise InvalidConfigFileValueError('No file extension listed in export path `{}`'.format(file_name))

def get_nested_elem(parser, func_list, key_list, file_ext, cast):
    """Retrieve the value of a nested element from within a config file.

    Parameters
    ----------
    parser : ConfigParser (.ini, .config, .cfg), dict (.json, .yaml, .yml), or Element (.xml)
        The object that will store the structure of elements
    func_list : list
        A list of functions that will be called on the structure of elements to get the nested element
    key_list : list
        A list of str that is the `path` within the config file to retrieve the nested element
    file_ext : str
        File extension for the config file
    cast : function
        The data type that the element's text value will be converted into

    Returns
    -------
    type(cast)
        Depending on the function of cast, the text value of the nested element can be converted into any data type
    """

    elem = parser
    # Have element be set to the result of calling `func` on elem to get the value of the key `key`
    for func, key in zip(func_list, key_list):
        elem = func(elem, key)
    # If the file extension is `.xml`, convert the element to its text value.
    if file_ext == 'xml':
        elem = elem.text
    # Cast the text value into the desired data type and return it
    return cast(elem)

def parse_config_file(parser, func_list, file_ext):
    """Parse the configuration file to retrieve all of the configuration settings.

    Parameters
    ----------
    parser : ConfigParser (.ini, .config, .cfg), dict (.json, .yaml, .yml), or Element (.xml)
        The object that will store the structure of elements
    func_list : list
        A list of functions that will be called on the structure of elements to get the nested element
    file_ext : str
        File extension for the config file

    Returns
    -------
    Configuration
        an instance of Configuration that stores all of the configuration settings for the program's execution

    Raises
    ------
    InvalidExportFileTypeError
        if the export file is an invalid file type
    """

    # Retrieve all of the configuration settings from the config file
    chromedriver_path = os.path.abspath(get_nested_elem(parser, func_list, ['chromedriver', 'path'], file_ext, str))
    headless = get_nested_elem(parser, func_list, ['chromedriver', 'headless'], file_ext, eval_config_file_boolean)
    deep_scrape = get_nested_elem(parser, func_list, ['settings', 'deep_scrape'], file_ext, eval_config_file_boolean)
    start_page = get_nested_elem(parser, func_list, ['settings', 'start_page'], file_ext, int) - 1
    end_page = get_nested_elem(parser, func_list, ['settings', 'end_page'], file_ext, int)
    all_pages = get_nested_elem(parser, func_list, ['settings', 'all_pages'], file_ext, eval_config_file_boolean)
    export = get_nested_elem(parser, func_list, ['settings', 'export'], file_ext, eval_config_file_boolean)
    overwrite = get_nested_elem(parser, func_list, ['settings', 'overwrite'], file_ext, eval_config_file_boolean)
    export_path = get_nested_elem(parser, func_list, ['settings', 'export_path'], file_ext, str)
    export_extension = export_path.rsplit('.', 1)[-1].lower()
    print_evts = get_nested_elem(parser, func_list, ['settings', 'print'], file_ext, eval_config_file_boolean)

    # Validate start and end pages
    validate_start_end_pages(start_page, end_page)

    # If the configuration setting for exporting data is enabled and
    # the export file path has no file extension, raise an InvalidConfigFileValueError
    if export:
        check_file_extension_exists(export_path)

    # If the export file path extension is not an allowed export
    # file type, raise an InvalidConfigFileValueError
    if export and export_extension not in ALLOWED_EXPORT_FILE_TYPES:
        raise InvalidExportFileTypeError('One of the following file extensions must be provided: {}'
                                         .format(', '.join(ALLOWED_EXPORT_FILE_TYPES)))

    # Create a new instance of Configuration and return it
    return Configuration(chromedriver_path, headless, deep_scrape, start_page, end_page,
                         all_pages, export, overwrite, export_path, export_extension, print_evts)

def read_config_file(config_file_path):
    """Read the configuration file and extract the configuration settings for the program's execution.

    Parameters
    ----------
    config_file_path : str
        The file path to where the configuration file is located

    Returns
    -------
    Configuration
        an instance of Configuration that stores all of the configuration settings for the program's execution

    Raises
    ------
    InvalidConfigFileValueError
        if any values within the configuration file are invalid
    InvalidConfigFileTypeError
        if the configuration file is a file type that the program cannot read from
    """

    # If the configuration file path has no file extension, raise an InvalidConfigFileValueError
    if len(config_file_path.rsplit('.')) < 2:
        raise InvalidConfigFileValueError('No file extension listed in config file path `{}`'.format(config_file_path))

    # If the configuration file extension is not any of the allowed
    # configuration file types, raise an InvalidConfigFileTypeError
    file_extension = config_file_path.rsplit('.')[-1].lower()
    if file_extension not in ALLOWED_CONFIG_FILE_TYPES:
        raise InvalidConfigFileTypeError("`.{}` is not a valid config file extension. Allowed file types are: {}"
                                         .format(file_extension,
                                                 ', '.join(map(lambda s: '`.' + s + '`', ALLOWED_CONFIG_FILE_TYPES))))

    try:
        # Read a config file of file type: .cfg, .conf, .config, .ini
        if file_extension in {'cfg', 'conf', 'config', 'ini'}:
            ini_parser = ConfigParser()
            ini_parser.read(config_file_path)
            return parse_config_file(ini_parser, [ConfigParser.__getitem__, SectionProxy.__getitem__], file_extension)

        # Read a config file of file type .json
        if file_extension == 'json':
            with open(config_file_path) as f:
                json_parser = json.load(f)
                return parse_config_file(json_parser, [dict.__getitem__] * 2, file_extension)

        # Read a config file of file type: .yaml, .yml
        if file_extension in {'yaml', 'yml'}:
            with open(config_file_path) as f:
                yaml_parser = yaml.load(f)
                return parse_config_file(yaml_parser, [dict.__getitem__] * 2, file_extension)

        # Read a config file of file type .xml
        if file_extension == 'xml':
            tree = ET.parse(config_file_path)
            root = tree.getroot()
            return parse_config_file(root, [Element.find] * 2, file_extension)

    # Handle exception where the file cannot be found
    except FileNotFoundError as e:
        print(str(e))
        sys.exit(1)

    # Handle exception where a key within the configuration file cannot be found
    except KeyError as e:
        print('Missing Key: {}'.format(e))
        sys.exit(1)

def extract_start_end_pages(pages):
    """Return the proper order of start/end pages

    Parameters
    ----------
    pages : list
        A list of page numbers

    Returns
    -------
    tuple (int, int)
        A tuple of page numbers

    Raises
    ------
    InvalidArgumentsError
        if the user entered more than 2 page numbers
    """

    # If the no page numbers were entered, have the start page be 0 and end page be 1
    if len(pages) == 0:
        return 0, 1

    # If one page number was entered, have the start page be 0 and end page be the entered page
    elif len(pages) == 1:
        return 0, pages[0]

    # If two page numbers were entered, have the start page be pages[0]-1 and have the end page be pages[1]
    elif len(pages) == 2:
        return pages[0] - 1, pages[1]

    # If more than two page numbers were entered, raise an InvalidArgumentsError
    else:
        raise InvalidArgumentsError('Too many page arguments. Only 0-2 are needed.')

def read_args(args):
    """Read command line arguments and extract the configuration settings for the program's execution.

    Parameters
    ----------
    args : list
        Command line arguments

    Returns
    -------
    Configuration
        an instance of Configuration that stores all of the configuration settings for the program's execution

    Raises
    ------
    InvalidArgumentsError
        if any of the command line arguments are invalid
    InvalidExportFileTypeError
        if the export file is an invalid file type
    """

    # Extract ChromeDriver path, headless, deep scrape
    chromedriver_path = os.path.abspath(args[args.index('--path')+1])
    headless = '--head' not in args
    deep_scrape = '--deep' in args

    # Extract the numbers of the pages that will be scraped
    pages = list(map(int, filter(lambda arg: arg.isnumeric(), args)))
    start_page, end_page = extract_start_end_pages(pages)

    # Validate the start and end pages
    validate_start_end_pages(start_page, end_page)

    # Extract all pages and export configuration settings
    all_pages = '--all' in args
    export = '--export' in args

    # If the `--export` flag is the last command line argument, raise an InvalidArgumentError
    if '--export' == args[-1]:
        raise InvalidArgumentsError('`--export` cannot be the final argument.')

    # Extract export path, export file extension, overwrite, print_events
    export_path = args[args.index('--export')+1] if export else None
    export_extension = export_path.rsplit('.', 1)[-1].lower() if export_path else None
    overwrite = '--overwrite' in args
    print_evts = '--print' in args

    # If the configuration setting for exporting data is enabled and
    # the export file path has no file extension, raise an InvalidConfigFileValueError
    if export:
        check_file_extension_exists(export_path)

    # If the export file path extension is not an allowed export
    # file type, raise an InvalidConfigFileValueError
    if export and export_extension not in ALLOWED_EXPORT_FILE_TYPES:
        raise InvalidExportFileTypeError('One of the following file extensions must be provided: {}'
                                         .format(', '.join(ALLOWED_EXPORT_FILE_TYPES)))

    # Create a new instance of Configuration and return it
    return Configuration(chromedriver_path, headless, deep_scrape, start_page, end_page,
                         all_pages, export, overwrite, export_path, export_extension, print_evts)

def extract_date_time(raw_date_time, tz):
    """Extract the date & time from a raw string.

    Parameters
    ----------
    raw_date_time : str
        The raw string containing information about an event's date & time
    tz : str
        The timezone of the event

    Returns
    -------
    tuple (str, str)
        A tuple with the event start datetime and event end datetime, both formatted as: MM/DD/YYYY HH:MM AM/PM UTC-OFFSET
    """

    start_date, end_date, start_time, end_time = None, None, None, None

    # If an event is `All Day`, set the start time to be 12:00 AM and end time to be 11:59 PM
    if re.search(ALL_DAY_REGEX, raw_date_time):
        start_time = datetime.strptime('12:00 AM', '%I:%M %p')
        end_time = datetime.strptime('11:59 PM', '%I:%M %p')

    # Extract the start and end dates of an event
    pattern = re.compile(DATE_REGEX)
    for match in re.finditer(pattern, raw_date_time):
        date = match.group()

        # If the event has distinct start and end dates, extract them
        if re.search(START_END_REGEX, raw_date_time):
            if start_date:
                end_date = datetime.strptime(date, '%m/%d/%Y')
            else:
                start_date = datetime.strptime(date, '%m/%d/%Y')
        # Else, set the start and end dates to the same date
        else:
            start_date = datetime.strptime(date, '%m/%d/%Y')
            end_date = datetime.strptime(date, '%m/%d/%Y')

    # Extract the start and end times of an event
    pattern = re.compile(TIME_REGEX)
    for match in re.finditer(pattern, raw_date_time):
        time = match.group()
        if start_time:
            end_time = datetime.strptime(time, '%I:%M %p')
        else:
            start_time = datetime.strptime(time, '%I:%M %p')

    # If end_date is None, set it to start_date
    if not end_date:
        end_date = start_date

    # If end_time is None, set it to two hours after start_time
    if not end_time:
        end_time = start_time + timedelta(hours=2)

    # Combine the start/end dates & start/end times into datetime objects
    start = datetime.combine(start_date.date(), start_time.time())
    end = datetime.combine(end_date.date(), end_time.time())

    # Add timezones to the datetime objects
    start_w_timezone = timezone(tz).localize(start)
    end_w_timezone = timezone(tz).localize(end)

    # Return the event start datetime and event end datetime, both formatted as: MM/DD/YYYY HH:MM AM/PM UTC-OFFSET
    return start_w_timezone.strftime('%m/%d/%Y %I:%M %p %Z%z'), end_w_timezone.strftime('%m/%d/%Y %I:%M %p %Z%z')

def extract_contact_info(raw_contact):
    """Extract the contact information from a raw string of contact info.

    Parameters
    ----------
    raw_contact : str
        The raw string containing information about the contact info for an event.

    Returns
    -------
    dict
        A dictionary containing contact information (name, phone number, email)
    """

    parsed_data = {}

    # Extract the name of the contact
    contact_names = re.findall(CONTACT_NAME_REGEX, raw_contact, flags=re.MULTILINE)
    if contact_names:
        parsed_data['name'] = '\n'.join(contact_names)

    # Extract the email of the contact
    pattern = re.compile(EMAIL_REGEX)
    for match in re.finditer(pattern, raw_contact):
        email = match.group()
        parsed_data['email'] = email

    # Extract the phone number of the contact
    pattern = re.compile(PHONE_NUMBER_REGEX)
    for match in re.finditer(pattern, raw_contact):
        phone_number = match.group()
        parsed_data['phone_number'] = phone_number

    # Return the extracted contact info dictionary
    return parsed_data

def format_attribute(attr):
    """Format the attribute/key of an object/dict for printing (my_attr -> My Attr)

    Parameters
    ----------
    attr : str
        The string to be formatted.

    Returns
    -------
    str
        The formatted string.
    """
    return ' '.join(map(lambda x: x.capitalize(), re.split(r' |_', attr)))

def print_event(evt):
    """Print out an event to the command line.

    Parameters
    ----------
    evt : Event
        The event to be printed out.
    """

    # Retrieve the __str__ representation of the event.
    print_str = str(evt)

    # Retrieve the values of the event's location, contact info, and description and add them to the print_str
    for attr in ['location', 'contact', 'description']:

        # If the event has this attribute, add to the print string
        if evt.__dict__[attr]:

            # If the attribute is contact info, add the contact info's keys and values to the print string
            if attr == 'contact':
                print_str += 'Contact:\n'
                for label, value in evt.__dict__[attr].items():
                    print_str += '  {:<{fill}} {}\n'.format(format_attribute(label) + ':', value,
                                                            fill=max(map(len, evt.contact.keys())) + 1)
                else:
                    print_str += '\n'
            # Else, add the attribute and its value to the print string
            else:
                print_str += '{}:\n{}\n\n'.format(format_attribute(attr), evt.__dict__[attr])

    # If the event has additional info, add its keys and values to the print string
    if evt.__dict__['additional_info']:
        print_str += 'Additional Info:\n'
        for label, value in evt.additional_info.items():
            print_str += '  {:<{fill}} {}\n'.format(label+':', value, fill=max(map(len, evt.additional_info.keys()))+1)

    # Print the print string
    print(print_str.strip())

def print_events(events):
    """Print out a list of events to the command line.

    Parameters
    ----------
    events : list
        List of events to be printed out
    """

    # Loop through all events in the event list and print them out
    for evt in events:
        try:
            print_event(evt)
            print('-' * 120)
        # Handle exceptions that deal with issues with printing Unicode characters
        except UnicodeEncodeError:
            pass

def export_json(events, export_file_path):
    """Export a list of events to a JSON file.

    Parameters
    ----------
    events : list
        A list of events to be exported to a JSON file.
    export_file_path : str
        The destination file path of the JSON file to be written/overwritten.
    """
    with open(export_file_path, 'w') as f:
        json.dump({'events': events}, f, indent=4)

def convert_dict_to_xml(parent, dictionary):
    """Convert a dictionary to a set of nested XML elements.

    Parameters
    ----------
    parent : Element
        The XML element that this XML element will be nested in.
    dictionary : dict
        The dictionary that will be converted to a set of nested XML elements.
    """

    # Loop through all key-value pairs in this dictionary
    for key, value in dictionary.items():
        # If this key has no value associated with it, continue to the next key
        if not value:
            continue
        # Create a new XML element with this key and nest it within the parent element
        element = ET.SubElement(parent, key)
        # If the value is a dictionary, recursively call this method
        # and have the converted dictionary be nested within element
        if isinstance(value, dict):
            convert_dict_to_xml(element, value)
        # Otherwise, set value to be this element's text value
        else:
            element.text = value

def export_xml(events, export_file_path):
    """Export a list of events to an XML file.

    Parameters
    ----------
    events : list
        A list of events to be exported to an XML file.
    export_file_path : str
        The destination file path of the XML file to be written/overwritten.
    """

    # Have an <events> element be the root element
    root = ET.Element('events')

    # Loop through all events in the event list, convert them into XML elements, and nest them within the root element
    for evt in events:
        # Create an XML element called <event>
        evt_element = ET.SubElement(root, 'event')
        # Convert the event and its information within <event>
        convert_dict_to_xml(evt_element, evt)

    # `Prettify` the XML text, with each level deep being indented
    xml_str = minidom.parseString(ET.tostring(root)).toprettyxml(indent='  ')
    with open(export_file_path, 'w') as xml_file:
        xml_file.write(xml_str)

def export_yaml(events, export_file_path):
    """Export a list of events to a YAML file.

    Parameters
    ----------
    events : list
        A list of events to be exported to a YAML file.
    export_file_path : str
        The destination file path of the YAML file to be written/overwritten.
    """

    with open(export_file_path, 'w') as yaml_file:
        yaml.dump({'events': events}, yaml_file, default_flow_style=False)

def export_events(events, config):
    """Export a list of events to a file.

    Parameters
    ----------
    events : list
        A list of events to be exported.
    config : Configuration
        Configuration settings for exporting events.

    Raises
    ------
    OverwriteExistingFileError
        If the file to export to already exists and configuration settings disabled overwriting.
    """

    # If the program is not allowed to overwrite an existing file, raise an OverwriteExistingFileError
    if not config.overwrite and os.path.isfile(config.export_path):
        raise OverwriteExistingFileError('`{}` already exists.'.format(config.export_path))

    # If the directories along the export file path does not exist, create them
    os.makedirs(os.path.dirname(config.export_path), exist_ok=True)

    # If the export file extension is .json, export events to a JSON file
    if config.export_extension == 'json':
        export_json([evt.__dict__ for evt in events], config.export_path)

    # If the export file extension is .xml, export events to an XML file
    elif config.export_extension == 'xml':
        export_xml([evt.__dict__ for evt in events], config.export_path)

    # If the export file extension is .yaml/.yml, export events to a YAML file
    elif config.export_extension in {'yaml', 'yml'}:
        export_yaml([evt.__dict__ for evt in events], config.export_path)


import pygame
import PIL.Image as Image
import PIL.ImageDraw as ImageDraw

image = Image.new("RGB", (640, 480))

draw = ImageDraw.Draw(image)

# points = ((1,1), (2,1), (2,2), (1,2), (0.5,1.5))
points = ((100, 100), (200, 100), (200, 200), (100, 200), (50, 150))
draw.polygon((points), fill=200)

def pilImageToSurface(pilImage):
    return pygame.image.fromstring(
        pilImage.tobytes(), pilImage.size, pilImage.mode).convert()

pygame.init()
window = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()

pygameSurface = pilImageToSurface(image)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.fill(0)
    window.blit(pygameSurface, pygameSurface.get_rect(center = (320, 240)))
    pygame.display.flip()


from django.http.response import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.model_selection import train_test_split
import pandas as pd
from mushroomCLSF.datasets.mushrooms import load_mushrooms
import numpy as np
from mushroomCLSF.views.util import extract_data

def get_decision_path(model, input_sample):
    node_indicator = model.decision_path(input_sample)
    leaf_id = model.apply(input_sample)
    feature = model.tree_.feature
    threshold = model.tree_.threshold
    feature_names = input_sample.columns.to_list()
    sample_id = 0
    # obtain ids of the nodes `sample_id` goes through, i.e., row `sample_id`
    node_index = node_indicator.indices[
                    node_indicator.indptr[sample_id]: node_indicator.indptr[sample_id + 1]
                 ]

    path = []
    for i, node_id in enumerate(node_index):
        # continue to the next node if it is a leaf node
        if leaf_id[sample_id] == node_id:
            continue

        # check if value of the split feature for sample 0 is below threshold
        if input_sample.values[sample_id, feature[node_id]] <= threshold[node_id]:
            threshold_sign = "<="
        else:
            threshold_sign = ">"

        response_threshold = str(threshold[node_id])
        response_no = int(i)
        response_node_id = int(node_id)
        response_feature = str(feature_names[feature[node_id]])
        response_value = str(input_sample.values[sample_id, feature[node_id]])
        response_inequality_sign = str(threshold_sign)

        path.append({
            'no': response_no,
            'node_id': response_node_id,
            'feature': response_feature,
            'value': response_value,
            'inequality_sign': response_inequality_sign,
            'threshold': response_threshold,
        })
    return path

def classify(data):
    """ CLASSIFICATION CODE HERE """
    data = {key: [value] for (key, value) in data.items()}
    input_features = list(data.keys())
    df, encode, decode = load_mushrooms(features=input_features, encode=True)
    input_df = pd.DataFrame.from_dict(data)
    for column in input_df:
        input_df[column] = encode(input_df, column)
    x_train, x_test, y_train, y_test = train_test_split(df[input_features], df['class'], random_state=42, test_size=0.2)
    model = DecisionTreeClassifier(criterion='entropy')
    model.fit(x_train, y_train)
    output = model.predict(input_df)
    result = decode(output, column='class')[0]
    explanation = get_decision_path(model, input_df)
    return result, explanation

@csrf_exempt
def decision_tree_classify(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        converted = extract_data(data)
        result, explanation = classify(converted)
        return JsonResponse(
            data={
                "status": 200,
                "result": result,
                "explanation": explanation
            }
        )

if __name__ == '__main__':
    sample_request_data = {
        'cap-shape': 'x',
        'cap-surface': 's',
        'cap-color': 'n',
        # 'bruises': 't',
        # 'odor': 'p',
        'stalk-shape': 'e',
        'stalk-root': 'e',
        'spore-print-color': 'k',
        'habitat': 'u',
        'population': 's',
        'ring-type': 'p',
    }
    expected_label = 'p'
    res_label, explain_text = classify(sample_request_data)
    print(f'Expected result: {expected_label}')
    print(f'Result: {res_label}\nReason: {explain_text}')


# Criar uma lista e usando for preencher com os 3000 primeiros valores pares.

lista = []

for i in range(3000):
    lista.append(i*2)
print(lista)

# Criar uma lista e usando while preencher com os 3000 primeiros valores pares.

lista = []
i = 0

while i < 3000:
    lista.append(i*2)
    i += 1
print(lista)


from plotly.offline import plot
import plotly.graph_objs as go
import networkx as nx

G = nx.Graph()
G.add_edges_from([(1, 2), (1, 3), (2, 4), (2, 5)])

G.add_nodes_from([1], pos=[0.0, 0.0])
G.add_nodes_from([2], pos=[0.1, 0.2])
G.add_nodes_from([3], pos=[0.1, -0.2])
G.add_nodes_from([4], pos=[0.2, 0.4])
G.add_nodes_from([5], pos=[0.2, -0.2])

pos = nx.get_node_attributes(G, 'pos')
print(pos)
print(G.node)
dmin = 1
ncenter = 0
for n in pos:
    x, y = pos[n]
    d = (x-0.5)**2+(y-0.5)**2
    if d < dmin:
        ncenter = n
        dmin = d

p = nx.single_source_shortest_path_length(G, ncenter)

# Create Edges

edge_trace = go.Scatter(x=[], y=[], line=dict(width=5.5, color='#888', shape='spline', smoothing=1.3), hoverinfo='none', mode='lines')

for edge in G.edges():
    x0, y0 = G.node[edge[0]]['pos']
    x1, y1 = G.node[edge[1]]['pos']
    edge_trace['x'] += tuple([x0, x1, None])
    edge_trace['y'] += tuple([y0, y1, None])

node_trace = go.Scatter(
    x=[],
    y=[],
    text=[],
    mode='markers',
    hoverinfo='text',
    marker=dict(
        showscale=False,
        # colorscale options
        #'Greys' | 'YlGnBu' | 'Greens' | 'YlOrRd' | 'Bluered' | 'RdBu' |
        #'Reds' | 'Blues' | 'Picnic' | 'Rainbow' | 'Portland' | 'Jet' |
        #'Hot' | 'Blackbody' | 'Earth' | 'Electric' | 'Viridis' |
        colorscale='Earth',
        reversescale=False,
        color=[],
        size=10,
        colorbar=dict(
            thickness=15,
            title='Node Connections',
            xanchor='left',
            titleside='right'
        ),
        line=dict(width=2)))

for node in G.nodes():
    x, y = G.node[node]['pos']
    node_trace['x'] += tuple([x])
    node_trace['y'] += tuple([y])

# Color Node Points

for node, adjacencies in enumerate(G.adjacency()):
    node_trace['marker']['color']+=tuple([len(adjacencies[1])])
    node_info = '# of connections: '+str(len(adjacencies[1]))
    node_trace['text']+=tuple([node_info])

# Create Network Graph

fig = go.Figure(data=[edge_trace, node_trace],
             layout=go.Layout(
                title='<br>Network graph made with Python',
                titlefont=dict(size=16),
                showlegend=False,
                hovermode='closest',
                margin=dict(b=20, l=5, r=5, t=40),
                annotations=[dict(
                    text='',
                    showarrow=False,
                    xref="paper", yref="paper",
                    x=0.005, y=-0.002)],
                xaxis=dict(showgrid=True, zeroline=True, showticklabels=True),
                yaxis=dict(showgrid=True, zeroline=True, showticklabels=True)))

plot(fig, filename='networkx.html', auto_open=False)

'''
Эта штука нужна что бы располагать вершины в графе относительно своих братьев

neighbour = [2]
for edge in Edges.objects.all():
    G.add_edges_from([(edge.parent, edge.child)])  # добавляем грань в граф
    neighbour.append(edge.parent.edges_set.count() + 1)  # добавляем для каждой вершины кол-во её братьев
    # print(edge.child, ' - ', edge.parent.edges_set.count() + 1)
# print(neighbour)

count = 0
y = 0
for node in Nodes.objects.order_by('depth'):
    x = node.depth
    divider = 10000/neighbour[count]
    if neighbour[count] != neighbour[count-1] or count == 0:
        y = divider
        G.add_nodes_from([node], pos=[x, y])
    else:
        y += divider
        G.add_nodes_from([node], pos=[x, y])
    # neighbours = node.edges_set.count()  # кол-ви детей у вершины
    count += 1
'''


result = []

def is_safe(board, row, col, n):
    for i in range(col):
        if board[row][i]:
            return False

    i = row
    j = col
    while i >= 0 and j >= 0:
        if board[i][j]:
            return False
        i -= 1
        j -= 1

    i = row
    j = col
    while j >= 0 and i < n:
        if board[i][j]:
            return False
        i = i + 1
        j = j - 1
    return True

def get_n_q_sol(board, col, n):
    if col == n:
        v = []
        for row in board:
            for j in range(len(row)):
                if row[j] == 1:
                    v.append(j + 1)
        result.append(v)
        return True

    res = False

    for i in range(n):
        if is_safe(board, i, col, n):
            board[i][col] = 1
            res = get_n_q_sol(board, col + 1, n) or res
            board[i][col] = 0
    return res

def print_boards(n):
    print("Total Possible Solutions for Board Size ", n, "*", n, " is :", len(result))
    print('Solutions Are as Follow : ')
    for board in range(len(result)):
        for i in range(n):
            for j in range(n):
                if j == result[board][i] - 1:
                    print('1', end=" ")
                else:
                    print('0', end=" ")
            print()
        print()

n = int(input("Enter Board Size : "))
board = [[0 for i in range(n)] for j in range(n)]
get_n_q_sol(board, 0, n)
print_boards(n)


#BOJ 15688번

import sys
input = sys.stdin.readline

n = int ( input() )
datas = [0] * 2000001

for _ in range ( n ) :
    datas[int(input())+1000000 ] += 1

for index , value in enumerate ( datas ) :
    if value == 0 :
        continue
    for _ in range( value ) :
        print( index-1000000 )


# initialize_totsumqt

# menu_excel load
import pandas as pd

filepath = './menu_excel.xlsx'
menu_excel = pd.read_excel(filepath)

# menu class
class Menu:
    def __init__(self, idx):
        # instance attribute 정의
        self.name = menu_excel['메뉴명'][idx]
        self.cost = menu_excel['가격'][idx]
        self.qt = 0
        self.tot = 0

    # 수량 변경/취소
    def menu_qt(self, num):
        # 음수 처리
        if self.qt + num < 0:
            self.qt = 0
        # 수량 취소
        elif num == 0:
            self.qt = 0
        else:
            self.qt += num

        total.tot_qt(self.qt)

        return self.qt

    # 메뉴 금액 계산
    def menu_tot(self):
        self.tot = self.qt * self.cost

        total.tot_sum(self.tot)

        return self.tot

# menu class instance 정의
americano = Menu(0)
latte = Menu(1)
iceamericano = Menu(2)
icelatte = Menu(3)

#전체 수량, 총액 class
class Total:
    def __init__(self):
        self.qt = 0
        self.sum = 0

    def tot_qt(self, qt):
        self.qt += qt

        return self.qt

    def tot_sum(self, tot):
        self.sum += tot

        return self.sum

total = Total()