from functools import total_ordering
import json
import os
from typing import final
from googlesearch import search
import cv2
import sys
from random import shuffle
import time
import msvcrt
from time import strptime
from numbers import Number
import cmd
from prettytable import PrettyTable
from datetime import datetime, timedelta
import string
import random
# pip install prettytable
clear = lambda: os.system('cls')
START_STUDYING_TIME: datetime.now() = datetime.now()
'''
This variable (WORK_FROM_DEFINATION) has a questionable name, took me to long do even decide with this one
so I decided ill just name it this and suffer writing an explanation what its responsible for.

If this variable is set to True.
The program will start with the defination of the topic (if available) and show you the notes you
have for it. and from those notes, you type into the console what that topic is. (your notes shouldn't contain
the answer, that defeats the purpose of flashcards, although small hints are okay) If you get it right, you go to the next question.

If this variable is set to False.
The program will show you the topic, and you have to explain to yourself or others what it means, theres no
legit, to type in the answer and check if its right, but youll have to be honest with your self. You can view a
defination (if available) or notes by using the provided commands. This doesn't track points, as theres no way
to do that.
'''
WORK_FROM_DEFINATION: bool = True

PATH_TO_THIS_FOLDER: str = 'C:/Users/jared/Documents/Code/flashcard_generator'

# Delay between getting the answer correc/incorrect and the next flashcard
class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'
number_and_ordered_topics = []
completed_topics = []
sum_of_time: int = 0
def print_commands_list(description, topics, show_topics: bool = False, progress = "", show_words_list: bool = True, show_times: bool = False):
    global completed_topics, number_and_ordered_topics, sum_of_time
    number_and_ordered_topics.clear()
    if description:
        print(
            f'type "next" for next topic\t"d" - description\t"s" - view sources (wiki)\t"notes" - view notes\t"exit" - exit {progress if progress != "" else ""}\n'
        )

    else:
        print(
            f'type "next" for next topic\t"s" - view sources (wiki)\t"notes" - view notes\t"exit" - exit {progress if progress != "" else ""}\n'
        )
    if show_topics:
        topics = sorted(topics)
        completed_topics = sorted(completed_topics)
        # for i, topic in enumerate(topics):
        #     for ctopic in completed_topics:
        #         if topic in ctopic:
        #             topics.pop(i)
        # topics.extend(completed_topics)
        alphabets = list(string.ascii_lowercase)
        alphabet_indexes: dict = {} # this variable name doesnt make sense
        alphabet_indexes.update({'other':[{'index': 0},{'topics':[]}]})
        for alphabet in alphabets:
            alphabet_indexes.update({alphabet:[{'index': 0},{'topics':[]}]})

        for i, topic in enumerate(topics, start=1):
            try:
                first_letter = topic[0].lower()
            except IndexError:
                alphabet_indexes['other'][0]['index'] += 1
                alphabet_indexes['other'][1]['topics'].append(f'{topic}')
                continue
            try:
                alphabet_indexes[first_letter][0]['index'] += 1
                alphabet_indexes[first_letter][1]['topics'].append(f'{topic}')
            except KeyError:
                alphabet_indexes['other'][0]['index'] += 1
                alphabet_indexes['other'][1]['topics'].append(f'{topic}')
        # for topic in topics:
        alphabet_keys = list(alphabet_indexes.keys())
        new_list = []
        overall_count: int = 1
        for key in alphabet_keys:
            # print(t for t in )
            index = alphabet_indexes[key][0]['index']
            if index != 0:
                new_list.append(f'{key.upper()} - {index}')
                for t in alphabet_indexes[key][1]['topics']:
                    new_list.append(f'  {overall_count}) {t}')
                    number_and_ordered_topics.append(t)
                    overall_count += 1
            # new_list.append(t for t in alphabet_indexes[key][1]['topics'])
        # topics = [f'{i}) {topic}' for i, topic in enumerate(topics, start=1)]
        new_list.extend(completed_topics)
        cli = cmd.Cmd()
        cli.columnize(new_list, displaywidth=200)
        print('\n')
'''
    No idea how this function works, I just snatched it from SO, and it worked.
    https://stackoverflow.com/questions/11563615/matching-incorrectly-spelt-words-with-correct-ones-in-python
'''
def compare_words(u1: str, u2: str):
    '''
    Checks to see how similar the words are.
    It returns how many mistakes have been made in spelling.
    I have set the mininum number of mistakes to be 5.

    If the answer is "Theory", and you guessed: "thoery"
    This would still be correct as there is only one mistake.

    If the answer is "Population" and you guessed: "pupolation"
    This would still be correct as there are only 2 mistakes.

    So a maxinum of 6 mistakes, is pretty close to the real deal...
    '''
    try:
        s1 = unicode(u1)
        s2 = unicode(u2)
    except:
        s1 = u1
        s2 = u2
    if len(s1) < len(s2):
        return compare_words(u2, u1)
    if not s1:
        return len(s2)

    previous_row = range(len(s2) + 1)
    for i, c1 in enumerate(s1):
        current_row = [i + 1]
        for j, c2 in enumerate(s2):
            insertions = previous_row[j + 1] + 1 # j+1 instead of j since previous_row and current_row are one character longer
            deletions = current_row[j] + 1       # than s2
            substitutions = previous_row[j] + (c1 != c2)
            current_row.append(min(insertions, deletions, substitutions))
        previous_row = current_row

    return previous_row[-1]

def differnce_in_time(date: str) -> datetime:
    now = datetime.now()
    date = date.replace('  ', ' ')
    split_date = date.split(' ')
    year = int(split_date[-1])
    month_number = strptime(split_date[1], '%b').tm_mon
    day = int(split_date[2])
    hour = int(split_date[3].split(':')[0])
    minute = int(split_date[3].split(':')[1])
    second = int(split_date[3].split(':')[-1])
    new_date = datetime(year, month_number, day, hour, minute, second) #yr, mo, day, hr, min, sec
    return now-new_date

def show_notes(paths_to_notes, topic):
    startCol = int(0)
    for index, path in enumerate(paths_to_notes):
        try:
            img = cv2.imread(path)
        except: continue
        height, width = img.shape[0:2]
        startRow = int(350 if index == 0 else 0)
        endRow = int(height)
        endCol = int(width) # We go to the width of the document because titles could be long.
        croppedImage = img[startRow:endRow, startCol:endCol] # We crop the image accordingly to the values above.

        # Rescale the image so it fits to the screen.
        screen_res = 1380, 920
        scale_width = screen_res[0] / croppedImage.shape[1]
        scale_height = screen_res[1] / croppedImage.shape[0]
        scale = min(scale_width, scale_height)
        window_width = int(croppedImage.shape[1] * scale)
        window_height = int(croppedImage.shape[0] * scale)

        cv2.namedWindow("_" * len(topic), cv2.WINDOW_NORMAL)
        cv2.resizeWindow("_" * len(topic), window_width, window_height)

        cv2.imshow("_" * len(topic), croppedImage)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

def main(json_file, isTimed: bool = False, show_list_of_topics:bool=True, multiple_choices:bool=False):
    global completed_topics, START_STUDYING_TIME, number_and_ordered_topics, sum_of_time
    # with open(json_file) as f:
    #     d = json.load(f)
    d = json_file
    CONSTANT_UNCHANGED_TOPICS = list(d.keys())
    topics = list(d.keys())
    for num, t in enumerate(topics):
        if len(t) > 40 or len(t) <= 3:
            topics.pop(num)
    i: int = 0
    showed_notes = False
    number_of_correct: int = 0
    number_of_completed: int = -1 # Because im to lazy to actually fix this.
    seconds_in_day = 24 * 60 * 60

    # Untill we have went through all topics.
    while True:
        number_of_completed += 1
        START_TOPIC_TIME = datetime.now()
        try:
            topic = topics[i]
            answer = topic.replace(' ', '')
            paths_to_notes = d[topic][1]['paths']
            description = d[topic][0]['dictionary']

            '''
            Instead of choosing random WRONG topics, we can look for topics that are similar to the
            originally selected topic, this makes it harder to guess some topics and adds a level
            of difficultiy.
            '''
            similarity_score = {}
            for t in CONSTANT_UNCHANGED_TOPICS:
                if t != topic:
                    similarity_score.update({t:int(compare_words(topic, t))})

            similarity_score = dict(sorted(similarity_score.items(), key=lambda item: item[1]))
            words_sorted_by_similarity = list(similarity_score.keys())
            options = words_sorted_by_similarity[:5] # Just grabbing the first 5.
            answer_and_possible_answers = []
            for index_of_option, same_index in enumerate(options):
                answer_and_possible_answers.append(same_index)
            answer_and_possible_answers.append(topic)
            shuffle(answer_and_possible_answers)
        except Exception as e:
            print(e)
            clear()
            print_commands_list(
                description=description,
                topics=topics,
                show_topics=True,
                progress=f'\tCorrect: {number_of_correct}/{number_of_completed}\tTopics left: {len(topics)}\tPercentage: {round((number_of_correct/number_of_completed)*100, 1)}%',
            )

            difference = datetime.now()-START_STUDYING_TIME
            minutes, seconds = divmod(difference.days * seconds_in_day + difference.seconds, 60)

            print(f"It took: {minutes} minutes and {seconds} seconds to finish {(len(completed_topics))} topics, with an agerage of {round(sum_of_time/len(completed_topics),2)} seconds per topic! You can review your finals results.")
            break
        # We skip these
        if len(d[topic][1]['paths']) == 0 or topic == 'Useful notes' or topic == "" or topic == " ":
            topics.pop(i)
            continue
        clear()
        if WORK_FROM_DEFINATION:
            try:
                print_commands_list(
                    description=description,
                    topics=topics,
                    show_topics=show_list_of_topics,
                    progress=f'\tCorrect: {number_of_correct}/{number_of_completed}\tTopics left: {len(topics)}\tPercentage: {round((number_of_correct/number_of_completed)*100, 1)}%',
                )
            except ZeroDivisionError:
                print_commands_list(
                    description=description,
                    topics=topics,
                    show_topics=show_list_of_topics,
                    progress=f'\tCorrect: {number_of_correct}/{number_of_completed}\tTopics left: {len(topics)}\tPercentage: 0%',
                )

            if multiple_choices:
                for count, answere_or_not in enumerate(answer_and_possible_answers,start=1):
                    print(f'{count}. {answere_or_not}')
                # {"_" * len(topic)}
            input_call = ''
            console_input = []

            if not showed_notes:
                show_notes(paths_to_notes=paths_to_notes, topic=topics)
                showed_notes = True
            # Get user input
            # while True:
            #     x = msvcrt.getch()
            #     if x == b'\r': # Enter breaks the loop and heads onward with the input.
            #         break
            #     elif x == b'\x08': # Backspace
            #         try:
            #             console_input.pop(-1)
            #         except:
            #             console_input = []
            #     else:
            #         try:
            #             console_input.append(x.decode("utf-8"))
            #         except UnicodeDecodeError:
            #             pass
            #     input_call = ''.join(console_input)
            #     clear()
            #     try:
            #         print_commands_list(
            #             description=description,
            #             topics=topics,
            #             show_topics=show_list_of_topics,
            #             progress=f'\tCorrect: {number_of_correct}/{number_of_completed}\tTopics left: {len(topics)}\tPercentage: {round((number_of_correct/number_of_completed)*100, 1)}%',
            #         )
            #     except ZeroDivisionError:
            #         print_commands_list(
            #             description=description,
            #             topics=topics,
            #             show_topics=show_list_of_topics,
            #             progress=f'\tCorrect: {number_of_correct}/{number_of_completed}\tTopics left: {len(topics)}\tPercentage: 0%',
            #         )

            #     if multiple_choices:
            #         for count, answere_or_not in enumerate(answer_and_possible_answers,start=1):
            #             print(f'{count}. {answere_or_not}')
            #     if len(input_call) > len(topic):
            #         CURSOR: str = bcolors.FAIL + "█" + bcolors.ENDC
            #     elif len(input_call) == len(topic):
            #         CURSOR: str = bcolors.OKGREEN + "█" + bcolors.ENDC
            #     else:
            #         CURSOR: str = bcolors.OKBLUE + "█" + bcolors.ENDC
            #     CURSOR: str = "█"
            #         # {"_" * (len(topic)-len(console_input)-1)}
                # print(f'This topic is? {input_call}{CURSOR}')

            input_call = input("This topic is?\nAnswer: ")

            try:
                if multiple_choices:
                    input_call = answer_and_possible_answers[(int(input_call)-1)]
                input_call = number_and_ordered_topics[(int(input_call)-1)]
            except:
                pass
            input_call = input_call.replace(' ', '')
            if input_call == 'exit':
                break
            elif compare_words(input_call.lower(), answer.lower()) <= (len(answer)/4) and input_call.lower() != 'd' and input_call.lower() != 's'  and input_call.lower() != 'notes' and input_call != '' and input_call != '\n':
                END_TOPIC_TIME = datetime.now()
                elapsed = END_TOPIC_TIME - START_TOPIC_TIME
                minutes, seconds = divmod(elapsed.days * seconds_in_day + elapsed.seconds, 60)
                seconds += minutes*60
                sum_of_time += seconds
                if (isTimed):
                    if elapsed > timedelta(seconds=30):
                        print(f'{bcolors.OKBLUE}That is correct! But you didn\'t complete it within 30 seconds.{bcolors.ENDC}')
                        completed_topics.append(bcolors.OKBLUE + topics[i] + ' - ' + str(seconds) + 's' + bcolors.ENDC)
                    else:
                        print(f'{bcolors.OKGREEN}That is correct!\n\nThe answer was indeed {topic}.{bcolors.ENDC}')
                        completed_topics.append(bcolors.OKGREEN + topics[i] + ' - ' + str(seconds) + 's' + bcolors.ENDC)
                        number_of_correct+=1
                else:
                    print(f'{bcolors.OKGREEN}That is correct!\n\nThe answer was indeed {topic}.{bcolors.ENDC}')
                    completed_topics.append(bcolors.OKGREEN + topics[i] + ' - ' + str(seconds) + 's' + bcolors.ENDC)
                    number_of_correct+=1
                topics.pop(i)
                showed_notes = False
                shuffle(topics)
                input_call = input('Press ENTER to proceed...')
            elif input_call == 'd':
                if description:
                    print(f'The descripion for {"_" * len(topic)} is: "{description[0]}"')
                else:
                    print('No description available.')
                input_call = input('Press ENTER to proceed...')
            elif input_call == 's':
                print('Looking up sources. Please wait.')
                sources = search(f"\"defination\" of \"{topic}\" \"wikipedia\"", num_results=5)
                print(f'Found {len(sources)} sources!')
                for source in sources:
                    print(source)
                input_call = input('Press ENTER to proceed...')
            elif input_call == 'notes':
                show_notes(paths_to_notes=paths_to_notes, topic=topic)
            elif input_call in ['', 'next', 'idk', '\n', '\r']:
                END_TOPIC_TIME = datetime.now()
                elapsed = END_TOPIC_TIME - START_TOPIC_TIME
                minutes, seconds = divmod(elapsed.days * seconds_in_day + elapsed.seconds, 60)
                seconds += minutes*60
                sum_of_time += seconds

                print(f'{bcolors.FAIL}The answer was: {topic}{bcolors.ENDC}')
                completed_topics.append(bcolors.WARNING + topics[i] + ' - ' + str(seconds) + 's' + bcolors.ENDC)
                topics.pop(i)
                showed_notes = False
                shuffle(topics)
                input_call = input('Press ENTER to proceed...')
            else:
                END_TOPIC_TIME = datetime.now()
                elapsed = END_TOPIC_TIME - START_TOPIC_TIME
                minutes, seconds = divmod(elapsed.days * seconds_in_day + elapsed.seconds, 60)
                seconds += minutes*60
                sum_of_time += seconds

                print(f'{bcolors.FAIL}That is incorrect!\nThe correct answer is: {topic}{bcolors.ENDC}')
                completed_topics.append(bcolors.FAIL  + topics[i] + ' - ' + str(seconds) + 's' + bcolors.ENDC)
                topics.pop(i)
                showed_notes = False
                shuffle(topics)
                input_call = input('Press ENTER to proceed...')
        else:
            print_commands_list(description=description, topics=topics)
            print(f'What is {topic}?')
            input_call = input('Command: ')
            if input_call == 'd':
                if description:
                    print(f'The descripion for {topic} is: "{description[0]}"')
                else:
                    print('No description available.')
                input_call = input('Press ENTER to proceed...')
            elif input_call == 's':
                print('Looking up sources. Please wait.')
                sources = search(f"\"defination\" of \"{topic}\" \"wikipedia\"", num_results=5)
                print(f'Found {len(sources)} sources!')
                for source in sources:
                    print(source)

                input_call = input('Press ENTER to proceed...')
            elif input_call == 'notes':
                for path in paths_to_notes:

                    img = cv2.imread(path)

                    # Rescale the image so it fits to the screen.
                    screen_res = 1280, 920
                    scale_width = screen_res[0] / img.shape[1]
                    scale_height = screen_res[1] / img.shape[0]
                    scale = min(scale_width, scale_height)
                    window_width = int(img.shape[1] * scale)
                    window_height = int(img.shape[0] * scale)

                    cv2.namedWindow(topic, cv2.WINDOW_NORMAL)
                    cv2.resizeWindow(topic, window_width, window_height)

                    cv2.imshow(topic, img)
                    cv2.waitKey(0)
                    cv2.destroyAllWindows()
                input_call = input('Press ENTER to proceed...')
            elif input_call in ['next', 'idk', '']:
                END_TOPIC_TIME = datetime.now()
                elapsed = END_TOPIC_TIME - START_TOPIC_TIME
                completed_topics.append(bcolors.OKGREEN + topics[i] + ' - ' + elapsed + bcolors.ENDC)
                topics.pop(i)
                shuffle(topics)
            elif input_call == 'exit':
                break

def start_up():
    global WORK_FROM_DEFINATION, START_STUDYING_TIME
    clear()
    table = PrettyTable()
    json_file_location = PATH_TO_THIS_FOLDER + '/flashcards/JSON_DATA/'
    all_file_names = os.listdir(json_file_location)
    all_file_names = [json_file_location + file for file in all_file_names]
    creation_date = []
    for file in all_file_names:
        (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(file)
        creation_date.append(time.ctime(mtime))
    print('Please select what you want to study by typing its index.')
    table.field_names = ['Index', 'Study topics', 'Last edited', 'Date created']
    for i, cdate in enumerate(creation_date, start=1):
        file_name = all_file_names[i-1].split('/')[-1].replace('.json', '')
        table.add_row([i,file_name,str(differnce_in_time(cdate)) + ' ago', cdate])
    print(table)
    while True:
        index = input('Index: ')
        if index == 'exit':
            sys.exit()
        try:
            index = int(index)
            break
        except ValueError:
            print('That\'s not a number. Try again.')
    selected_json = all_file_names[index-1]
    t = selected_json.split('/')[-1]

    with open(selected_json) as f:
        d = json.load(f)
    '''
    This mess of code is responsible for selecting different modules, if they are available.
    The way it works is complicated and not well documented, but it works, (just bearly)
    and its a really hacky solution.

    The reason it's so complicated, is because I didn't want to change the `generate_flashcards.py` script
    because I would have to recompile it to exe on my system, and change how it compiles the json files.

    I would still have to do some re-compiling and what not to get the desired result, but I chose to do this,
    it like this, because it was the first idea I had in mind, and seemed a good one untill I actually tried
    to implment it.
    '''
    try:
        chapter_sorted_json = {}
        # We get all the modules from the json file.
        '''
        This is hacky, because modules are denoted as just a NUMBER. an empty page, with a title
        as a number. So what were looking for here, is for those titles that are just numbers or floats.
        '''
        for key in d.keys():
            try:
                key = int(key)
            except ValueError:
                try:
                    key = float(key)
                except:
                    continue
            '''
            This if statement might seem pointless, and thats right, it seems pointless.

            But due to the nature of OCR and how wrong it can be sometimes, we have to set this boundry.
            '''
            if key > 20:
                continue
            chapter_sorted_json.update({str(key):{}})
        '''
        We need to set the last key as the first one we found if there are any.
        If there are NO numbers in the json file. the program breaks right here, and
        skips to the exception
        '''
        last_key = list(chapter_sorted_json.keys())[0]

        '''
        What were doing here is were creating a new dictionary, but sorting the topics 'MODULE' wise.

        The way it does that is, if were at module 1, were going to add everything from module 1, until
        we hit the next number, or module, say 2, then we will switch over to using module 2, and addying
        everything to module 2, and so on.

        It's hard to explain but were addying everything to the module from the original dictionary, untill
        we hit the next module number.
        '''
        for i, key in enumerate(d.keys()):
            try:
                key = int(key)
                if key < 20: # Not a pointless if statement
                    last_key = key
            except ValueError:
                try:
                    key = float(key)
                    if key < 20: # Not a pointless if statement
                        last_key = key
                except:
                    pass
            # addying the dictionarys to the module organized dictionary.
            chapter_sorted_json[str(last_key)].update({str(key):[]})
            chapter_sorted_json[str(last_key)][str(key)].append(d[str(key)][0])
            chapter_sorted_json[str(last_key)][str(key)].append(d[str(key)][1])

        # We show the user how many modules there are, and how many topics each one has. and were wating for user input.
        clear()
        table = PrettyTable()
        table.field_names = ['Module Index', 'Module', '# of topics']
        for i, module in enumerate(list(chapter_sorted_json.keys())):
            table.add_row([i+1,module,len(chapter_sorted_json[module])])
        print(table)
        module_select = str(input(f"Studying: {t.replace('.json','')}\nPlease type the modules index you want to study.\nType 'all' for all.\nType '1,2,3' for module's 1 through 3.\n\nInput: "))

        # If we select 'all', we want to generate the list of index for all of those indexes.
        if 'a' in module_select.lower():
            module_select = list(range(1,len(list(chapter_sorted_json.keys()))+1))
            module_select = ','.join(str(x) for x in module_select)
        # If we want to go through modules 2-6, its not fun to type, 2,3,4,5,6. So this option is great
        # It basically generatess the string 2,3,4,5,6 for later processing because thats what its based on
        elif '-' in module_select:
            starting_module = int(module_select.split('-')[0])
            ending_module = int(module_select.split('-')[-1])
            module_select = str(starting_module)
            for i in range((ending_module-1)-starting_module):
                module_select += f",{i+starting_module+1}"
            module_select += ',' + str(ending_module)
        '''
        So what were doing here is were creating a temporary dictionary to ONLY add
        the selected module indexes that were inputed. By default ALL modules are selected.

        If you only want module 2 and 6, we add those to this temporary dictionary and head onward.
        '''
        module_select = module_select.split(',')
        temp_module_select = {}
        for i, module_index in enumerate(module_select):
            for key in list(chapter_sorted_json.keys()):
                try:
                    if list(chapter_sorted_json.keys())[int(module_index)-1] == str(key):
                        temp_module_select.update({key:[]})
                        temp_module_select[key] = chapter_sorted_json[key]
                except IndexError:
                    pass
        # Recompile back to standard simplified format using only the selected modules.
        chapter_sorted_json = temp_module_select
        final_compiled_json = {}

        '''
        This is mess

        I'm not sure if there is a better way to do this, but what were doing is, re-parsing
        the json file back to its orginal form.

        What this means is, we just want ALL the topics, and there information, we dont want
        the module, and what topics it includes.

        Essentially were just taking everything from each module and compiling it into one whole.

        for example. If we have module 1 and 2. Module 1 and 2 have different topics, we just merge
        everything from module 1 and 2, into one whole dictionary with no module index or chapters.

        So its basiclly just like it was in the orignal json format, except with less topics.
        '''
        total_topics: int = 0
        for i, key in enumerate(list(chapter_sorted_json.keys())):
            for topic in chapter_sorted_json[key]:
                total_topics += 1
                final_compiled_json.update({topic:[{'dictionary':[]},{'paths':[]}]})
                try:
                    description = (chapter_sorted_json[key][topic][0]['dictionary'][0])
                except IndexError:
                    description = []
                try:
                    path = chapter_sorted_json[key][topic][1]['paths'][0]
                except IndexError:
                    path = []
                final_compiled_json[topic][0]['dictionary'].append(description)
                final_compiled_json[topic][1]['paths'].append(path)
        studying_modules: list(str) = list(chapter_sorted_json.keys())
        if len(studying_modules) == 1:
            studying_modules = studying_modules[0]
        else:
            studying_modules = ', '.join(studying_modules)
        minutes_to_complete = int(total_topics/(0.0751*60))
        seconds_to_complete = int(((total_topics/(0.0751*60)) - minutes_to_complete)*100)
        yes_or_no = input(f"Studying: {t.replace('.json','')}\nModule(s): {studying_modules}\nTotal topics: {total_topics}\nApproximately will take: {minutes_to_complete} minutes and {seconds_to_complete} seconds to compelte.\nWould you like to work from definitions to find the keyword?\nyes or no?)")
    # This is because sometimes the study material doesnt have modules.
    except IndexError:
        # Set it back to the original json file.
        final_compiled_json = d
        yes_or_no = input(f"Studying: {t.replace('.json','')}\nWould you like to work from definitions to find the keyword?\nyes or no?)")
    if 'y' in yes_or_no.lower():
        WORK_FROM_DEFINATION = True
    elif 'n' in yes_or_no.lower():
        WORK_FROM_DEFINATION = False
        isTimed = False
    elif 'exit' in yes_or_no.lower():
        sys.exit()
    # I have decided that this will be a default setting.
    # if WORK_FROM_DEFINATION:
    #     isTimed = input(f"\nDo you want to be timed?\nyes or no?")
    #     if 'y' in isTimed.lower():
    #         isTimed = True
    #         print('\nYou will have 30 seconds to complete each topic.\n')
    #     elif 'n' in isTimed.lower():
    #         isTimed = False
    #     elif 'exit' in isTimed.lower():
    #         sys.exit()
    show_topics = input(f"\nDo you want to see the list of all the topics?\nyes or no?")
    if 'y' in show_topics.lower():
        show_topics = True
    elif 'n' in show_topics.lower():
        show_topics = False
    elif 'exit' in show_topics.lower():
        sys.exit()
    show_multiple_choices = input(f"\nDo you want to be shown multiple choices?\nyes or no?")
    if 'y' in show_multiple_choices.lower():
        show_multiple_choices = True
    elif 'n' in show_multiple_choices.lower():
        show_multiple_choices = False
    elif 'exit' in show_multiple_choices.lower():
        sys.exit()
    print(f'\n\nLoading {t}')
    START_STUDYING_TIME = datetime.now()
    main(final_compiled_json, True, show_topics, show_multiple_choices)
start_up()


#

# writing from zie's json format into the csr

import json
import logging
import math
from collections import Counter

# helper function for add ef
def add_ef(csr, arg_ef, check_type=False):
    extra_info = arg_ef.get("extra_info", {})
    span_info = extra_info.get("posi")
    if span_info is not None:
        ef_type = arg_ef["type"]
        if check_type and ef_type.split(":")[0] not in ["ldcOnt", "aida"]:
            ef_type = None
        ef_score = arg_ef.get("score")
        if ef_score is not None and ef_score < 0.:
            ef_score = math.exp(ef_score)
        ent = csr.add_entity_mention(
            span_info["head_span"], span_info["span"], span_info["text"], ef_type,
            entity_form=extra_info.get("entity_form"), component=extra_info.get("component"), score=ef_score,
        )
        return ent
    else:
        return None

# read file and add to csr
def add_zie_event(zie_event_file, csr):
    with open(zie_event_file) as fd:
        # read json
        doc = json.load(fd)
        evt_posi_mapping = Counter()
        # --
        # add (certain) efs
        ef_all_dict_mappings = {}  # ef-id -> ef (all)
        ef_dict_mappings = {}  # ef-id -> ef
        ef_csr_mappings = {}  # ef-id -> csr_ef
        for ef in doc["entity_mentions"] + doc["fillers"]:
            ef_all_dict_mappings[ef["id"]] = ef
            if ef["type"].startswith("ldcOnt:") or ef["type"].startswith("aida:"):
                ef_dict_mappings[ef["id"]] = ef  # store for later adding
        # --
        # add events
        evt_csr_mappings = {}  # event-id -> csr_evm
        for evt in doc["event_mentions"]:
            if evt["type"].startswith("rel:"):
                continue  # these will be added later
            if not (evt["type"].startswith("ldcOnt:") or evt["type"].startswith("aida:")):
                logging.info(f"Skipping evt for {evt['type']}({evt['extra_info']['posi']['text']})")
                continue
            extra_info = evt["extra_info"]
            span_info = extra_info["posi"]
            # add one
            csr_evm = csr.add_event_mention(
                span_info["head_span"], span_info["span"], span_info["text"], evt["type"],
                realis=evt["realis"], component=extra_info["component"], score=math.exp(evt["score"]),
                extent_text=span_info.get('extra_text', None), extent_span=span_info.get('extra_span', None)
            )
            # span_key = tuple(span_info["span"])
            # evt_posi_mapping[span_key] += 1
            # if evt_posi_mapping[span_key] > 1:
            #     logging.warning("Same posi-span evt inside zie!!")
            # add args
            if csr_evm is not None:
                evt_csr_mappings[evt["id"]] = csr_evm
            else:
                logging.warning(f"Adding evt failed for {evt['type']}({span_info['text']})")
        # --
        # add args
        for evt in doc["event_mentions"]:
            csr_evm = evt_csr_mappings.get(evt["id"])
            if csr_evm is None:
                continue  # adding failed
            for arg in evt["em_arg"]:
                if not (arg["role"].startswith("ldcOnt:") or arg["role"].startswith("aida:")):
                    logging.info(f"Skipping evt arg for {arg['role']}({arg['extra_info']['posi']['text']})")
                    continue
                # do we want to add things that might not be in ontology?
                # if not arg["role"].startswith("ldcOnt:"):
                #     continue
                arg_extra_info = arg["extra_info"]
                arg_span_info = arg_extra_info["posi"]
                if arg_extra_info.get("is_evt2evt_link", False):
                    # directly use event's adding method to add another event as arg
                    arg_evm = evt_csr_mappings.get(arg["aid"])
                    if arg_evm is not None:
                        arg_onto, slot_type = arg["role"].split(":", 1)
                        arg_id = csr.get_id('arg')
                        csr_arg = csr_evm.add_arg(arg_onto, slot_type, arg_evm, arg_id,
                                                  component=arg_extra_info["component"], score=math.exp(arg["score"]))
                    else:
                        csr_arg = None
                else:
                    # add ent only if used as arg
                    arg_ef = ef_dict_mappings.get(arg["aid"])
                    if arg_ef is not None:
                        if arg["aid"] not in ef_csr_mappings:  # no repeated adding
                            ent = add_ef(csr, arg_ef)
                            if ent is not None:  # set for later use
                                ef_csr_mappings[arg["aid"]] = ent
                    # add arg
                    csr_arg = csr.add_event_arg_by_span(
                        csr_evm, arg_span_info["head_span"], arg_span_info["span"], arg_span_info["text"], arg["role"],
                        component=arg_extra_info["component"], score=math.exp(arg["score"])
                    )
                if csr_arg is None:
                    logging.warning(f"Adding evt arg failed for {arg['role']}({arg_span_info['text']})")
        # --
        # add special rels
        for rel in doc["event_mentions"]:
            if not rel["type"].startswith("rel:"):
                continue
            try:  # to be safe ...
                extra_info = rel["extra_info"]
                span_info = extra_info["posi"]
                rel_type = "ldcOnt:" + rel["type"].split(":")[-1]
                rel_arg_ids, rel_arg_roles = [], []
                for arg in rel["em_arg"]:
                    if not (arg["role"].startswith("rel:") or arg["role"].startswith("aida:")):
                        continue
                    # find the arg
                    arg_extra_info = arg["extra_info"]
                    if arg_extra_info.get("is_evt2evt_link", False):
                        one_arg = evt_csr_mappings.get(arg["aid"])
                    else:
                        arg_ef = ef_all_dict_mappings.get(arg["aid"])
                        one_arg = ef_csr_mappings.get(arg["aid"])
                        if one_arg is None and arg_ef is not None:
                            one_arg = add_ef(csr, arg_ef, check_type=True)
                            if one_arg is not None:
                                ef_csr_mappings[arg["aid"]] = one_arg
                    # skip if not added
                    if one_arg is None:
                        logging.warning(f"Adding rel_arg failed for {arg})")
                        continue
                    # put it
                    arg_role = arg['role'] if arg["role"].startswith("aida:") else f"{rel_type}_{arg['role'].split(':')[-1]}"
                    rel_arg_ids.append(one_arg.id)
                    rel_arg_roles.append(arg_role)
                # finally checking
                if len(rel_arg_ids) >= 2:  # allow extra ones for time
                    # finally adding
                    csr_rel = csr.add_relation(
                        arguments=rel_arg_ids, arg_names=rel_arg_roles,
                        component=extra_info.get("component"), span=span_info["span"],
                        score=math.exp(rel["score"]),
                    )
                    if csr_rel:
                        csr_rel.add_type(rel_type)
                else:
                    logging.warning(f"Adding rel failed (invalid num of args) for {rel})")
            except:
                logging.warning(f"Adding rel failed (some except?) for {rel})")
        # --

# =====
# possible ways to modify "combine_runner.py"
"""
# adding a config option for the dir of zie_event: config.zie_event
# after "if config.conllu_folder:" and before "if config.rich_event:", insert these
# =====
        if config.zie_event:
            if os.path.exists(config.zie_event):
                zie_event_file = find_by_id(config.zie_event, docid)
                if zie_event_file:
                    logging.info("Adding events with zie output: {}".format(zie_event_file))
                    zie_integration_utils.add_zie_event(zie_event_file, csr)
                else:
                    logging.error(f"Cannot find zie output for {docid}")
            else:
                logging.info("No zie event output.")
# =====
"""

# =====
# how to move these to _export?
# msp/ -> msp/; tasks/zie/{common,main,models2,models3,opera,tools} -> tasks/zie/; tasks/zie/csr/* -> tasks/zie/csr/(setup)
# fix previous eval bug
# sed -i 's/ldcOnt:PER:/ldcOnt:PER./g' *
# run combine_runner: at csr dir
# output_base=../hector_out/english/ csr_resources=../csr_resources/ PYTHONPATH=./ python event/mention/combine_runner.py conf/aida/combine.py  --CombineParams.csr_output=../zout_csr_norich/ --CombineParams.rich_event=NOPE
# output_base=../hector_out/english/ csr_resources=../csr_resources/ PYTHONPATH=./ python event/mention/combine_runner.py conf/aida/combine.py  --CombineParams.csr_output=../zout_csr_rich/
# visualization
# python -m event.io.csr2stuff ../zout_csr_norich/ ../zout_visual_norich/ ../csr_resources/LDCOntologyM36.jsonld


class Solution(object):
    def longestWord(self, words):
        """
        :type words: List[str]
        :rtype: str
        """
        wordlength=[len(i) for i in words]
        wordmap={}
        for i in words:
        	wordmap[len(i)]=wordmap.get(len(i),[])+[i]
        lengthset=set(wordlength)
        if 1 not in lengthset:
        	return ""
        select=wordmap[1]
        for i in range(2,max(lengthset)+1):
        	newselect=[]
        	if i not in wordmap.keys():
        		return sorted(select)[0]
        	for j in wordmap[i]:
        		if any([j.find(i)==0 for i in select]):
        			newselect.append(j)
        	if newselect==[]:
        		return sorted(select)[0]
        	else:
        		select=newselect
        return sorted(select)[0]


import os
import html
import time
import asyncio

from amiyabot import QQGuildBotInstance
from amiyabot.builtin.message import MessageStructure

from core.database.group import GroupSetting
from core.database.messages import *
from core.util import TimeRecorder, AttrDict
from core import send_to_console_channel, Message, Chain, AmiyaBotPluginInstance, bot as main_bot

from .helper import WeiboUser

curr_dir = os.path.dirname(__file__)

class WeiboPluginInstance(AmiyaBotPluginInstance):
    ...

bot = WeiboPluginInstance(
    name='明日方舟微博推送',
    version='2.8',
    plugin_id='amiyabot-weibo',
    plugin_type='official',
    description='在明日方舟相关官微更新时自动推送到群',
    document=f'{curr_dir}/README.md',
    instruction=f'{curr_dir}/README_USE.md',
    global_config_schema=f'{curr_dir}/config_schema.json',
    global_config_default=f'{curr_dir}/config_default.yaml',
)

@table
class WeiboRecord(MessageBaseModel):
    user_id: int = IntegerField()
    blog_id: str = CharField()
    record_time: int = IntegerField()

async def send_by_index(index: int, weibo: WeiboUser, data: MessageStructure):
    result = await weibo.get_weibo_content(index - 1)

    if not result:
        return Chain(data).text('博士...暂时无法获取微博呢...请稍后再试吧~')
    else:
        chain = (
            Chain(data)
            .text(result.user_name + '\n')
            .text(html.unescape(result.html_text) + '\n')
            .image(result.pics_list)
        )

        if not isinstance(data.instance, QQGuildBotInstance):
            chain.text(f'\n\n{result.detail_url}')

        return chain

def get_index_from_text(text: str, array: list):
    r = re.search(r'(\d+)', text)
    if r:
        index = abs(int(r.group(1))) - 1
        if index >= len(array):
            index = len(array) - 1

        return index

@bot.on_message(group_id='weibo', keywords=['开启微博推送'])
async def _(data: Message):
    if not data.is_admin:
        return Chain(data).text('抱歉，微博推送只能由管理员设置')

    channel: GroupSetting = GroupSetting.get_or_none(group_id=data.channel_id, bot_id=data.instance.appid)
    if channel:
        GroupSetting.update(send_weibo=1).where(
            GroupSetting.group_id == data.channel_id,
            GroupSetting.bot_id == data.instance.appid,
        ).execute()
    else:
        if GroupSetting.get_or_none(group_id=data.channel_id):
            GroupSetting.update(bot_id=data.instance.appid, send_weibo=1).where(
                GroupSetting.group_id == data.channel_id
            ).execute()
        else:
            GroupSetting.create(group_id=data.channel_id, bot_id=data.instance.appid, send_weibo=1)

    return Chain(data).text('已在本群开启微博推送')

@bot.on_message(group_id='weibo', keywords=['关闭微博推送'])
async def _(data: Message):
    if not data.is_admin:
        return Chain(data).text('抱歉，微博推送只能由管理员设置')

    GroupSetting.update(send_weibo=0).where(
        GroupSetting.group_id == data.channel_id, GroupSetting.bot_id == data.instance.appid
    ).execute()

    return Chain(data).text('已在本群关闭微博推送')

@bot.on_message(group_id='weibo', keywords=['微博'])
async def _(data: Message):
    listens: list = bot.get_config('listen')
    setting = AttrDict(bot.get_config('setting'))

    if len(listens) == 1:
        weibo = WeiboUser(listens[0]['uid'], setting)
    else:
        md = '回复序号选择已关注的微博：\n\n|序号|微博ID|备注|\n|----|----|----|\n'
        for index, item in enumerate(listens):
            md += '|{index}|{uid}|{name}|\n'.format(index=index + 1, **item)

        wait = await data.wait(Chain(data).markdown(md))
        if not wait:
            return None

        index = get_index_from_text(wait.text_digits, listens)
        if index is None:
            return None

        weibo = WeiboUser(listens[index]['uid'], setting)

    message = data.text_digits
    index = 0

    r = re.search(r'(\d+)', message)
    if r:
        index = abs(int(r.group(1)))

    if '最新' in message:
        index = 1

    if index:
        return await send_by_index(index, weibo, data)
    else:
        blog_list = await weibo.get_blog_list()
        user_name = await weibo.get_user_name()

        if not blog_list:
            return Chain(data).text('博士...暂时无法获取微博列表呢...请稍后再试吧~')

        md = f'博士，这是【{user_name}】的微博列表，回复【序号】来获取详情吧\n\n|序号|日期|内容|\n|----|----|----|\n'
        for item in blog_list:
            md += '|{index}|{date}|{content}|\n'.format(**item)

        reply = Chain(data).markdown(md)

        wait = await data.wait(reply)
        if wait:
            r = re.search(r'(\d+)', wait.text_digits)
            if r:
                index = abs(int(r.group(1)))
                return await send_by_index(index, weibo, wait)

@bot.timed_task(each=30)
async def _(_):
    listens: list = bot.get_config('listen')
    for listen in listens:
        user = listen['uid']
        weibo = WeiboUser(user, AttrDict(bot.get_config('setting')))
        new_id = await weibo.get_weibo_id(0)
        if not new_id:
            continue

        record = WeiboRecord.get_or_none(blog_id=new_id)
        if record:
            continue

        WeiboRecord.create(user_id=user, blog_id=new_id, record_time=int(time.time()))

        target: List[GroupSetting] = GroupSetting.select().where(GroupSetting.send_weibo == 1)

        if not target:
            continue

        time_rec = TimeRecorder()
        async_send_tasks = []

        result = await weibo.get_weibo_content(0)

        if not result:
            await send_to_console_channel(Chain().text(f'微博获取失败\nUSER: {user}\nID: {new_id}'))
            return

        send = True
        for regex in bot.get_config("block"):
            if re.match(regex, html.unescape(result.html_text)):
                await send_to_console_channel(Chain().text(f'微博正文触发正则屏蔽，跳过推送\nUSER: {user}\nID: {new_id}'))
                send = False
                break
            if re.search(regex, html.unescape(result.html_text)):
                await send_to_console_channel(Chain().text(f'微博正文触发搜索屏蔽，跳过推送\nUSER: {user}\nID: {new_id}'))
                send = False
                break

        if not send:
            continue

        await send_to_console_channel(
            Chain().text(f'开始推送微博\nUSER: {result.user_name}\nID: {new_id}\n目标数: {len(target)}')
        )

        for item in target:
            data = Chain()

            instance = main_bot[item.bot_id]

            if not instance:
                continue

            data.text(f'来自 {result.user_name} 的最新微博\n\n{html.unescape(result.html_text)}')

            if isinstance(instance.instance, QQGuildBotInstance):
                if not instance.private:
                    for url in result.pics_urls:
                        data.image(url=url)
                else:
                    data.image(result.pics_list)
            else:
                data.image(result.pics_list).text(f'\n\n{result.detail_url}')

            if bot.get_config('sendAsync'):
                async_send_tasks.append(instance.send_message(data, channel_id=item.group_id))
            else:
                await instance.send_message(data, channel_id=item.group_id)
                await asyncio.sleep(bot.get_config('sendInterval'))

        if async_send_tasks:
            await asyncio.wait(async_send_tasks)

        await send_to_console_channel(Chain().text(f'微博推送结束:\n{new_id}\n耗时{time_rec.total()}'))


from alibabacloud.client import AlibabaCloudClient
from alibabacloud.request import APIRequest
from alibabacloud.utils.parameter_validation import verify_params

class BssClient(AlibabaCloudClient):

    def __init__(self, client_config, credentials_provider=None, retry_policy=None,
                 endpoint_resolver=None):
        AlibabaCloudClient.__init__(self, client_config,
                                    credentials_provider=credentials_provider,
                                    retry_policy=retry_policy,
                                    endpoint_resolver=endpoint_resolver)
        self.product_code = 'Bss'
        self.api_version = '2014-07-14'
        self.location_service_code = 'bss'
        self.location_endpoint_type = 'openAPI'

    def open_callback(self, param_str=None):
        api_request = APIRequest('OpenCallback', 'GET', 'http', 'RPC', 'query')
        api_request._params = {"paramStr": param_str}
        return self._handle_request(api_request).result

    def query_for_css_order(self, param_str=None):
        api_request = APIRequest('QueryForCssOrder', 'GET', 'http', 'RPC', 'query')
        api_request._params = {"paramStr": param_str}
        return self._handle_request(api_request).result

    def create_order(self, param_str=None):
        api_request = APIRequest('CreateOrder', 'GET', 'http', 'RPC', 'query')
        api_request._params = {"paramStr": param_str}
        return self._handle_request(api_request).result

    def vno_pay_call_back_notify(self, param_str=None):
        api_request = APIRequest('VnoPayCallBackNotify', 'GET', 'http', 'RPC', 'query')
        api_request._params = {"paramStr": param_str}
        return self._handle_request(api_request).result

    def vno_batch_refund_order(self, param_str=None):
        api_request = APIRequest('VnoBatchRefundOrder', 'GET', 'http', 'RPC', 'query')
        api_request._params = {"paramStr": param_str}
        return self._handle_request(api_request).result

    def subscription_create_order_api(self, product_code=None, owner_id=None):
        api_request = APIRequest('SubscriptionCreateOrderApi', 'GET', 'http', 'RPC', 'query')
        api_request._params = {"productCode": product_code, "ownerId": owner_id}
        return self._handle_request(api_request).result

    def set_resource_business_status(
            self,
            business_status=None,
            resource_owner_id=None,
            resource_id=None,
            resource_owner_account=None,
            owner_account=None,
            owner_id=None,
            resource_type=None):
        api_request = APIRequest('SetResourceBusinessStatus', 'GET', 'http', 'RPC', 'query')
        api_request._params = {
            "BusinessStatus": business_status,
            "ResourceOwnerId": resource_owner_id,
            "ResourceId": resource_id,
            "ResourceOwnerAccount": resource_owner_account,
            "OwnerAccount": owner_account,
            "OwnerId": owner_id,
            "ResourceType": resource_type}
        return self._handle_request(api_request).result

    def describe_coupon_list(
            self,
            start_delivery_time=None,
            page_size=None,
            end_delivery_time=None,
            page_num=None,
            status=None):
        api_request = APIRequest('DescribeCouponList', 'GET', 'https', 'RPC', 'query')
        api_request._params = {
            "StartDeliveryTime": start_delivery_time,
            "PageSize": page_size,
            "EndDeliveryTime": end_delivery_time,
            "PageNum": page_num,
            "Status": status}
        return self._handle_request(api_request).result

    def describe_coupon_detail(self, coupon_number=None):
        api_request = APIRequest('DescribeCouponDetail', 'GET', 'https', 'RPC', 'query')
        api_request._params = {"CouponNumber": coupon_number}
        return self._handle_request(api_request).result

    def describe_cash_detail(self,):
        api_request = APIRequest('DescribeCashDetail', 'GET', 'https', 'RPC', '')

        return self._handle_request(api_request).result


"""Code is based on
https://github.com/rwightman/pytorch-image-models/blob/master/timm/data/mixup.py
"""
import numpy as np
import torch

def to_one_hot(x, num_classes, on_value=1., off_value=0.):
    if len(x.size()) > 1 and x.size(-1) == num_classes:
        # already one-hot form
        return x
    x = x.long().view(-1, 1)
    return torch.full((x.size()[0], num_classes), off_value, device=x.device
                      ).scatter_(dim=1, index=x, value=on_value)

def squeeze_one_hot(x):
    return x.topk(1)[1].long()

def smooth_target(target, smoothing=0.1, num_classes=1000):
    target *= (1. - smoothing)
    target += (smoothing / num_classes)
    return target

def mix_target(target_a, target_b, num_classes, lam=1., smoothing=0.0):
    y1 = smooth_target(target_a, smoothing, num_classes)
    y2 = smooth_target(target_b, smoothing, num_classes)
    return lam * y1 + (1. - lam) * y2

def rand_bbox(size, lam):
    W = size[2]
    H = size[3]
    cut_rat = np.sqrt(1. - lam)
    cut_w = np.int(W * cut_rat)
    cut_h = np.int(H * cut_rat)

    # uniform
    cx = np.random.randint(W)
    cy = np.random.randint(H)

    bbx1 = np.clip(cx - cut_w // 2, 0, W)
    bby1 = np.clip(cy - cut_h // 2, 0, H)
    bbx2 = np.clip(cx + cut_w // 2, 0, W)
    bby2 = np.clip(cy + cut_h // 2, 0, H)

    lam = 1 - ((bbx2 - bbx1) * (bby2 - bby1) / (size[2] * size[3]))

    return bbx1, bby1, bbx2, bby2, lam

def cutmix_batch(image, target, mix_args):
    if not mix_args.disable and np.random.rand(1) < mix_args.prob:
        lam = np.random.beta(mix_args.beta, mix_args.beta)
    else:
        target = smooth_target(
            target=target,
            smoothing=mix_args.smoothing,
            num_classes=mix_args.num_classes)
        return image, target

    rand_index = torch.randperm(image.size()[0], device=image.device)
    target_a = target
    target_b = target[rand_index]
    bbx1, bby1, bbx2, bby2, lam = rand_bbox(image.size(), lam)
    image[:, :, bbx1:bbx2, bby1:bby2] = image[rand_index, :, bbx1:bbx2,
                                              bby1:bby2]

    target = mix_target(target_a=target_a,
                        target_b=target_b,
                        num_classes=mix_args.num_classes,
                        lam=lam,
                        smoothing=mix_args.smoothing)
    return image, target


#!/bin/python3

import math
import os
import random
import re
import sys

first_multiple_input = input().rstrip().split()

n = int(first_multiple_input[0])

m = int(first_multiple_input[1])

matrix = []

for _ in range(n):
    matrix_item = input()
    matrix.append(matrix_item)

decoded_list = list(zip(*matrix))

decoded_string = ""
for item in decoded_list:
    decoded_string = decoded_string + "".join(item)

print(re.sub(r'\b[^a-zA-Z0-9]+\b',r" ", decoded_string))


import os
from gimpfu import *
from gimpenums import *

def pluginFunction(img, drw):
    #set filepaths
    appdir = os.path.expanduser('~')+"/_blenderextpaint_autorefresh"
    UV_FILEPATH = appdir+"/uv.png"

    try:
        uv_layer = pdb.gimp_file_load_layer(img, UV_FILEPATH)
        pdb.gimp_image_insert_layer(img, uv_layer, None, 0)
        pdb.gimp_item_set_name(uv_layer, "ignore uv")
        pdb.gimp_layer_scale(uv_layer, img.width, img.height, False)
        pdb.gimp_image_set_active_layer(img, drw)
        #re-render
        pdb.gimp_image_resize(img, img.width, img.height, 0, 0)
    except: pass

register(
  "gimp_blenderextpaint_uv_import",
  "Import UVs",
  "Import UVs",
  "See Blender script for developers",
  "See Blender script for developers",
  "",
  "<Image>/Filters/Blender-GIMP Autorefresh/UV Import",
  "*",
  [],
  [],
  pluginFunction
)
main()


import logging
import os
import shutil

class PyTestLogger:

    session_log_dir_name = "Pytest_logs"
    workspace = "C:\\dev"
    log_source_dir = "pytest_project"
    log_destination_root_path = "C:\\dev\\Log"
    log_level_name_list = ["debug", "info", "warning", "error", "critical"]

    def __init__(self, log_file_name, log_level_list):
        """ Initialize self.  See help(type(self)) for accurate signature. """

        self.logger = logging.getLogger(log_file_name)
        self.logger.setLevel(logging.DEBUG)
        self.log_file_name = log_file_name
        self.formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s: %(message)s')
        self.log_level_list = log_level_list
        self.in_progress_flag = False

        if self.log_level_list.count(logging.DEBUG):
            self.file_handler_debug = logging.FileHandler(self.log_file_name + "_" +
                                                          PyTestLogger.log_level_name_list[0] + ".log", mode="w")
            self.file_handler_debug.setLevel(logging.DEBUG)

        if self.log_level_list.count(logging.INFO):
            self.file_handler_info = logging.FileHandler(self.log_file_name + "_" +
                                                         PyTestLogger.log_level_name_list[1] + ".log", mode="w")
            self.file_handler_info.setLevel(logging.INFO)

        if self.log_level_list.count(logging.WARNING):
            self.file_handler_warning = logging.FileHandler(self.log_file_name + "_" +
                                                            PyTestLogger.log_level_name_list[2] + ".log", mode="w")
            self.file_handler_warning.setLevel(logging.WARNING)

        if self.log_level_list.count(logging.ERROR):
            self.file_handler_error = logging.FileHandler(self.log_file_name + "_" +
                                                          PyTestLogger.log_level_name_list[3] + ".log", mode="w")
            self.file_handler_error.setLevel(logging.ERROR)

        if self.log_level_list.count(logging.CRITICAL):
            self.file_handler_critical = logging.FileHandler(self.log_file_name + "_" +
                                                             PyTestLogger.log_level_name_list[4] + ".log", mode="w")
            self.file_handler_critical.setLevel(logging.CRITICAL)

        self.update_formatter()

    @classmethod
    def set_session_log_dir_name(cls, dir_name):  # real signature unknown
        cls.session_log_dir_name = dir_name

    def set_formatter(self, formatter):
        if not self.in_progress_flag:
            self.formatter = logging.Formatter(formatter)
            self.update_formatter()
        else:
            raise Exception("Failed to set formatter! Logging is in progress! Please call this function before "
                            "start_logger() or after stop_logger()!")

    def update_formatter(self):
        if self.log_level_list.count(logging.DEBUG):
            self.file_handler_debug.setFormatter(self.formatter)
        if self.log_level_list.count(logging.INFO):
            self.file_handler_info.setFormatter(self.formatter)
        if self.log_level_list.count(logging.WARNING):
            self.file_handler_warning.setFormatter(self.formatter)
        if self.log_level_list.count(logging.ERROR):
            self.file_handler_error.setFormatter(self.formatter)
        if self.log_level_list.count(logging.CRITICAL):
            self.file_handler_critical.setFormatter(self.formatter)

    def start_logger(self):
        self.in_progress_flag = True
        if self.log_level_list.count(logging.DEBUG):
            self.logger.addHandler(self.file_handler_debug)
        if self.log_level_list.count(logging.INFO):
            self.logger.addHandler(self.file_handler_info)
        if self.log_level_list.count(logging.WARNING):
            self.logger.addHandler(self.file_handler_warning)
        if self.log_level_list.count(logging.ERROR):
            self.logger.addHandler(self.file_handler_error)
        if self.log_level_list.count(logging.CRITICAL):
            self.logger.addHandler(self.file_handler_critical)

    def stop_logger(self):

        if self.log_level_list.count(logging.DEBUG):
            self.file_handler_debug.close()
            self.logger.removeHandler(self.file_handler_debug)
        if self.log_level_list.count(logging.INFO):
            self.file_handler_info.close()
            self.logger.removeHandler(self.file_handler_info)
        if self.log_level_list.count(logging.WARNING):
            self.file_handler_warning.close()
            self.logger.removeHandler(self.file_handler_warning)
        if self.log_level_list.count(logging.ERROR):
            self.file_handler_error.close()
            self.logger.removeHandler(self.file_handler_error)
        if self.log_level_list.count(logging.CRITICAL):
            self.file_handler_critical.close()
            self.logger.removeHandler(self.file_handler_critical)

        self.in_progress_flag = False

    def save_log_files(self, test_name, file_name):

        test_suite_dir = file_name
        session_dir = PyTestLogger.session_log_dir_name

        log_source_path = os.path.join(PyTestLogger.workspace, PyTestLogger.log_source_dir)
        log_save_path = os.path.join(PyTestLogger.log_destination_root_path, session_dir, test_suite_dir, test_name)

        log_files_list = list()

        for root, dirs, files in os.walk(log_source_path):
            for file in files:
                for log_level_name in self.log_level_name_list:
                    if ((self.log_file_name + "_" + log_level_name + ".log") == file) or ("witef.log" == file):
                        log_files_list.append(os.path.join(root, file))

        if not os.path.exists(log_save_path):
            os.makedirs(log_save_path)

        for path in log_files_list:
            print(path)
            shutil.copy(path, log_save_path)


import codecs
import sys
import os

from lib import NaiveBayesClassifier

def deserialize(filename):
    source = codecs.open(filename, 'r', 'utf-8')
    data = source.readlines()
    source.close()

    return data

def run(args):
    source = args[1]
    os.chdir(source)

    labels = os.listdir('.')
    data = {label: deserialize(label) for label in labels}

    nb = NaiveBayesClassifier()
    nb.train_from_data(data)

    code = """
#!/usr/bin/env python
def normalize_space(s):
    \"\"\"Return s stripped of leading/trailing whitespace
    and with internal runs of whitespace replaced by a single SPACE\"\"\"
    # This should be a str method :-(
    return ' '.join(s.split())

    replacement = [normalize_space(i) for i in hello]}return
    """

    results = []
    for language in labels:
        results.append((language, nb.probability(code, language)))

    results = results[0:10]

    sorted_results = sorted(results, key = lambda tup: -tup[1])
    print(sorted_results)

if __name__ == '__main__':
    run(sys.argv)


#!../venv/bin/python3
import configparser
import sys

import pymongo
from dateutil import parser
from pymongo import MongoClient

def add_actuators(db: MongoClient, config: configparser.ConfigParser) -> None:
    """
    Adds actuators specified in configuration file

    :param db: the MongoClient
    :param config: the configuration parser
    :return: None
    """

    actuators = list()

    # fans
    num_fans = int(config["fans"]["number_small_fans"])

    actuators.extend([{
        "name": "fan" + str(i + 1).zfill(2),
        "type": "fan",
        "state": False
    } for i in range(num_fans)])

    additional_fans = config["fans"]["additional_fans"].split(",")

    actuators.extend([{
        "name": fan,
        "type": "fan",
        "state": False
    } for fan in additional_fans])

    # heater
    num_heaters = int(config["heaters"]["number_heaters"])

    actuators.extend([{
        "name": "heater" + str(i + 1).zfill(2),
        "type": "heater",
        "state": False
    } for i in range(num_heaters)])

    # water
    num_solenoids = int(config["solenoids"]["number_solenoids"])

    actuators.extend([{
        "name": "solenoid" + str(i + 1).zfill(2),
        "type": "water",
        "state": False
    } for i in range(num_solenoids)])

    # lights
    num_lights = int(config["lights"]["number_lights"])

    actuators.extend([{
        "name": "lights" + str(i + 1).zfill(2),
        "type": "lights",
        "state": False
    } for i in range(num_lights)])

    db.actuators.insert_many(actuators)

def add_default_settings(db: MongoClient, config: configparser.ConfigParser) -> None:
    """
    Adds the settings from the configuration file
    :param db: the MongoClient
    :param config: the configuration parser
    :return: None
    """
    lights_start_time = parser.parse(config["settings"]["lights_start_time"])
    lights_end_time = parser.parse(config["settings"]["lights_end_time"])

    default_settings = {
        "is_manual_mode": bool(config["settings"]["manual_mode"]),
        "temperature": {
            "min": int(config["settings"]["min_temperature"]),
            "max": int(config["settings"]["max_temperature"])
        },
        "soil_moisture": {
            "min": int(config["settings"]["min_soil_moisture"]),
            "max": int(config["settings"]["max_soil_moisture"])
        },
        "lights": {
            "start_time": lights_start_time.hour * 3600 + lights_start_time.minute * 60,  # seconds since midnight
            "end_time": lights_end_time.hour * 3600 + lights_end_time.minute * 60
        },
        "watering_times": [],
        "error_flush_times": [],
        "email_addresses": []
    }

    db.settings.insert_one(default_settings)

def create_indexes(db: MongoClient) -> None:
    """
    Creates indexes on the database
    :param db: the MongoClient
    :return: None
    """
    # need this index to make sure all the names are unique
    db.actuators.create_index([("name", pymongo.TEXT)], name="name_index", default_language="english", unique=True)

    # need these indexes because these collections could be large and we always query on name/sensor.type and timestamp
    db.actuators_state_log.create_index([("name", pymongo.ASCENDING), ("timestamp", pymongo.DESCENDING)],
                                        name="name_timestamp_index",
                                        default_language="english")
    db.data_readings.create_index([("sensor.type", pymongo.ASCENDING), ("timestamp", pymongo.DESCENDING)],
                                  name="type_timestamp_index",
                                  default_language="english")
    db.greenhouse_server_state.create_index([("timestamp", pymongo.DESCENDING)], name="timestamp_index")

def reinitialize_db(config: configparser.ConfigParser, tables: list = None) -> None:
    """
    Initializes the greenhouse database with data or reinitializes it
    :param config: the configuration parser
    :param tables: a list of tables to fill (actuators, settings, etc)
    :return: None
    """

    mongo_uri = config["mongo"]["mongo_uri"]

    if mongo_uri:
        client = MongoClient(mongo_uri)
    else:
        client = MongoClient()

    db = client.greenhouse

    if "actuators" in tables:
        db.actuators.drop()
        add_actuators(db, config)

    if "actuators_state_log" in tables:
        db.actuators_state_log.drop()
        state_log_size = 100 * 1000000
        db.create_collection("actuators_state_log", capped=True, size=state_log_size)

    if "settings" in tables:
        db.settings.drop()
        add_default_settings(db, config)

    if "data_readings" in tables:
        db.data_readings.drop()
        data_readings_size = 350 * 1000000
        db.create_collection("data_readings", capped=True, size=data_readings_size)

    if "greenhouse_server_state" in tables:
        db.greenhouse_server_state.drop()
        pings_size = 5 * 1000000
        db.create_collection("greenhouse_server_state", capped=True, size=pings_size)

    create_indexes(db)

if __name__ == "__main__":

    if len(sys.argv) != 3:
        print("Usage: " + sys.argv[0] + " [configfile] [tables (comma separated)]")
        exit(1)

    config = configparser.ConfigParser()
    config.read(sys.argv[1])
    tables_str = sys.argv[2]

    tables = tables_str.split(",")

    reinitialize_db(config, tables)


def compare1(word, guess):
    assert len(guess) == 5
    assert len(word) == 5

    code = [0] * 5
    used = [False] * 5

    for i in range(5):
        if guess[i] == word[i]:
            code[i] = 2
            used[i] = True

    for i in range(5):
        if code[i] == 2:
            continue
        for j in range(5):
            if guess[i] == word[j] and not used[j]:
                code[i] = 1
                used[j] = True
                break

    value = 0
    for v in code:
        value = value * 3 + v

    return value

def compare2(word, guess):
    assert len(word) == 5
    assert len(guess) == 5

    code = [0] * 5
    used = [False] * 5
    for i in range(5):
        if word[i] == guess[i]:
            code[i] = 2
            used[i] = True

    for i in range(5):
        if code[i] != 0:
            continue
        for j in range(5):
            if code[j] == 2:
                continue
            if guess[i] == word[j] and not used[j]:
                code[i] = 1
                used[j] = True
                break

    value = 0
    for i in code:
        value = value * 3 + i

    return value

from dataSource import DataSource
from game import toBase3

dataSource = DataSource()

while True:

    word = dataSource.getRandomWord()
    guess = dataSource.getRandomWord()
    if compare1(word, guess) != compare2(word, guess):
        print (f"{word} {guess} {toBase3(compare1(word, guess))}, {toBase3(compare2(word, guess))}")
        break


import cv2
import numpy as np
import csv

import sys, os
from tqdm import *

from os import listdir
from os.path import isfile, join

import argparse
import logging

import cPickle as pickle

AGES = ['child', 'young', 'adult', 'elder']
GENDERS = ['male', 'female']

IMG_DIM = (224, 224)

class Dataset():
    def load_labeled_data(self, raw_data_path):
        X = []
        T = []
        for g_i in range(len(GENDERS)):
            for a_i in range(len(AGES)):
                age = AGES[a_i]
                gender = GENDERS[g_i]
                label = g_i
                label = np.array([label], dtype=np.int32)[np.newaxis, :]

                path =  join(raw_data_path, age, gender)
                onlyfiles = [f for f in listdir(path) if isfile(join(path, f))]
                onlyfiles.sort(key=lambda f: int(filter(str.isdigit, f)))

                for i in tqdm(range(len(onlyfiles))):
                    img = (cv2.imread(path + '/' + onlyfiles[i]))
                    img = cv2.resize(img, IMG_DIM)
                    X.append(img[np.newaxis, :])
                    T.append(label)
        X = np.asarray(np.concatenate(X))
        T = np.asarray(np.concatenate(T))
        return X, T

    def load_unlabeled_data(self, raw_data_path):
        X = []
        F = []
        for g_i in range(len(GENDERS)):
            for a_i in range(len(AGES)):
                age = AGES[a_i]
                gender = GENDERS[g_i]
                label = g_i
                label = np.array([label], dtype=np.int32)[np.newaxis, :]

                path =  join(raw_data_path, age, gender)
                onlyfiles = [f for f in listdir(path) if isfile(join(path, f))]
                onlyfiles.sort(key=lambda f: int(filter(str.isdigit, f)))

                for i in tqdm(range(len(onlyfiles))):
                    img = cv2.cvtColor(cv2.imread(join(path, onlyfiles[i]), cv2.COLOR_RGB2GRAY))
                    img = cv2.resize(img, IMG_DIM)
                    X.append(img[np.newaxis, :])
                    F.append(onlyfiles[i])
        X = np.asarray(np.concatenate(X))
        return X, F

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--type', help='load labeled/unlabeled data',
            choices=['label', 'unlabel'], type=str, default='label')
    parser.add_argument('--input', help='input', type=str, default='data')
    parser.add_argument('--output', help='output', type=str, default='data')

    args = parser.parse_args()
    dataset = Dataset()

    if args.type == 'label':
        X, T = dataset.load_labeled_data(args.input)
        np.save(join(args.output, 'X'), X)
        np.save(join(args.output, 'T'), T)
    elif args.type == 'unlabel':
        X, F = dataset.load_unlabeled_data(args.input)
        np.save(join(args.output, 'X'), X)
        pickle.dump(F, open(join(args.input, 'X.index'), "wb"), True)


#Tower of Hanoi visualization -guided by Dr. P. N. Singh
import turtle
peg_height = 290
def draw_line(x,y,heading,length,pensize,color):
    turtle.up()
    turtle.goto(x,y)
    turtle.seth(heading)
    turtle.down()
    turtle.color(color)
    turtle.pensize(pensize)
    turtle.fd(length)

def draw_scene():
    turtle.bgcolor('light blue')
    draw_line(-600,-170,0,1200,10,'brown')
    for i in range(-250,251,250):
        draw_line(i,-163,90,peg_height,5,'black')

from turtle import *

class Disc(Turtle):
    def __init__(self, n):
        Turtle.__init__(self, shape="square", visible=False)
        self.pu()
        self.shapesize(1.5, n*1.5, 2) # rectangle for disc shape
        self.fillcolor(n/6., 0, 1-n/6.)
        self.st()

class Tower(list):
    "Hanoi tower, a subclass of built-in type list"
    def __init__(self, x):
        "create an empty tower. x is x-position of peg"
        self.x = x
    def push(self, d):
        d.setx(self.x)
        d.sety(-150+34*len(self))
        self.append(d)
    def pop(self):
        d = list.pop(self)
        d.sety(150)
        return d

def hanoi(n, from_, with_, to_):
    if n > 0:
        hanoi(n-1, from_, to_, with_)
        to_.push(from_.pop())
        hanoi(n-1, with_, from_, to_)

def play():
    onkey(None,"space")
    clear()
    draw_scene()
    try:
        hanoi(disks, t1, t2, t3)
        write("Done",align="center", font=("Arial", 18, "bold"))
    except Terminator:
        pass  # turtledemo user pressed STOP

def parastoh():
    global t1, t2, t3
    ht(); penup(); goto(0, -225)   # writer turtle
    t1 = Tower(-250)
    t2 = Tower(0)
    t3 = Tower(250)
    for i in range(disks,0,-1):
        t1.push(Disc(i))
    write("Spacebar to solve the TOH puzzle",align="center", font=("Arial", 16, "bold"))
    onkey(play, "space")
    listen()

disks=4 # 1 to 6
parastoh()


import argparse

def get_arguments():
    parser = argparse.ArgumentParser(description=("MIDI music generator is a script for generating "
                                                  "simple MIDI music with different opions"))
    parser.add_argument('--narcossity', '-n', type=int, choices=range(1, 5), dest='narcossity_level', default=1,
                        help="Change the level of narcossity.")
    parser.add_argument('-p', "--path", type=str, dest="fileName", default="myMidi.mid",
                        help=("Sets the path of the generated midi file. Note, that the name "
                              "should end witch .mid. If only a name is given the file is created in"
                              "working directory"))
    parser.add_argument('-k', '--key', type=int, dest='key', default=7,
                        help="Set the base key for whole midi file. The KEY should be"
                             "between 0 and 12.")
    parser.add_argument('-b', '--beats', type=int, dest='beats_per_bar', default=16,
                        help="Set the number of beats per bar. BEATS_PER_BAR should be between 4 and 64")
    parser.add_argument('-B', '--bars', type=int, dest='number_of_bars', default=16,
                        help="Set the number of bars = length of the music")
    parser.add_argument('-j', '--jazz', dest='genre', action='store_const', const=1,
                        help='Sets genre type to jazz. Setting flag -j is similar to setting: '
                             '-n 2 -b 20')
    parser.add_argument('-s', '--samba', dest='genre', action='store_const', const=2,
                        help='Sets genre type to samba. Setting flag -s is similar to setting: '
                             '-n 4 -b 16')

    arguments = parser.parse_args()

    if arguments.key not in range(0, 12) or arguments.beats_per_bar not in range(4, 65):
        print("Bad arguments, type -h or --help to see help message")
        exit(1)

    if arguments.genre == 1:
        arguments.narcossity_level = 2
        arguments.beats_per_bar = 20
    elif arguments.genre == 2:
        arguments.narcossity_level = 4
        arguments.beats_per_bar = 16

    return arguments


import sys
row, col = map(int, sys.stdin.readline().split())
rowcol = [row, col]
map = ''
for i in range(row):
    map += sys.stdin.readline().rstrip()

maxSize = min(rowcol) + 1
maxSize //= 2

size = maxSize

while size > 1:
    num1 = (size * 2) + (col - (2 * size - 1))
    num2 = num1 - 2

    loop1 = row - (2*size - 1)+1
    loop2 = col - (2*size - 1)+1

    for j in range(loop1):
        for k in range(loop2):
            chk = True
            idx1 = size - 1 + j*col + k
            idx2 = idx1
            idx3 = idx1+(col*(2*(size)-2))
            idx4 = idx3
            if chk:
                for m in range(size):
                    if map[idx1] == '0' or map[idx2] == '0' or map[idx3] == '0' or map[idx4] == '0':
                        chk = False
                        break
                    idx1 += num1
                    idx2 += num2
                    idx3 -= num1
                    idx4 -= num2
            if chk:
                break
        if chk:
            break
    if chk:
        break
    size -= 1
if size == 1:
    if '1' not in map:
        size = 0

print(size)

백준/Platinum/1028. 다이아몬드 광산/다이아몬드 광산.py


"""
This document for benchmark functions is provided by supervisor
"""

import os, json

path_info = os.path.join(os.path.dirname(os.path.abspath(__file__)),"functions_info.json")

class Reference(object):
	def __init__(self, raw_data):
		data=raw_data.strip()
		if data[0]!="@" or data[-1]!="}":
			raise ValueError("Problems in formatting the following reference: "+raw_data)
		self.paper_type, json_raw = data[1:].split("{")
		self.data = json.load("{"+json_raw)
	def __str_(self):
		return '@'+self.paper_type+str(self.data)

class FunctionsInfo(object):
	def __init__(self):
		self.load()

	def load(self):
		f=open(path_info)
		self.config = json.load(f)
		f.close()

	def save(self):
		f=open(path_info,'w')
		f.write(json.dumps(self.config,indent=2))
		f.close()

	def _parameters2str(self,parameters):
		return ','.join([p+'='+str(v) for p,v in parameters])

	def add_function(self, function_name, parameters=[]):
		if function_name not in self.config:
			if len(parameters)==0:
				self.config[function_name]={'minima':{},'suggested bounds':{}}
			else:
				pn=self._parameters2str(parameters)
				self.config[function_name]={pn:{'minima':{},'suggested bounds':{}}}

	def add_optimum(self, function_name, value, position, parameters=[], isMaximum=False, dimensions_invariant=False):
		name=function_name.upper()
		self.add_function(name, parameters)
		if isMaximum:
			optimum_type="maxima"
		else:
			optimum_type="minima"
		if len(parameters)==0:
			vals=self.config[name][optimum_type]
		else:
			pn=self._parameters2str(parameters)
			if pn not in self.config[name]:
				self.config[name][pn]={'minima':{},'suggested bounds':{} }
			vals=self.config[name][pn][optimum_type]
		if dimensions_invariant:
			dim='*'
		else:
			dim=str(len(position))
		if dim not in vals:
			vals[dim]=[]
		vals[dim]+=[position]

	# auxiliary function
	def _get_solutions(self,function_name,n_dimensions,optimum_type,parameters=[]):
		name=function_name.upper()
		ret=[]
		if optimum_type not in self.config[name]:
			return []
		if len(parameters)==0:
			vals=self.config[name][optimum_type]
		else:
			pn=self._parameters2str(parameters)
			if pn not in self.config[name]:
				return []
			vals=self.config[name][pn][optimum_type]
		if '*' in vals:
			ret+=[[vals['*'][0][0]]*n_dimensions] # this is just a workaround to make the call consistent
		if str(n_dimensions) in vals:
			ret+=vals[str(n_dimensions)]
		return ret

	# returns all the known minima
	def get_minima(self,function_name,n_dimensions,parameters=[]):
		return self._get_solutions(function_name,n_dimensions,"minima",parameters)

	# returns all the known maxima
	def get_maxima(self,function_name,n_dimensions,parameters=[]):
		return self._get_solutions(function_name,n_dimensions,"maxima",parameters)

	def suggested_bounds(self, function_name, lower_bound, upper_bound, parameters=[]):
		name=function_name.upper()
		self.add_function(name, parameters)
		if len(parameters)==0:
			vals=self.config[name]["suggested bounds"]
		else:
			pn=self._parameters2str(parameters)
			if pn not in self.config[name]:
				self.config[name][pn]={'minima':{},'suggested bounds':{} }
			vals=self.config[name][pn]["suggested bounds"]
		vals["lower"] = lower_bound
		vals["upper"] = upper_bound

	def get_suggested_bounds(self, function_name, parameters=[]):
		name=function_name.upper()
		if len(parameters)==0:
			vals=self.config[name]["suggested bounds"]
		else:
			pn=self._parameters2str(parameters)
			vals=self.config[name][pn]["suggested bounds"]
		return (vals["lower"], vals["upper"])

	def get_reference(self, function_name):
		name=function_name.upper()
		if name not in self.config or "reference" not in self.config[name]:
			return None
		return Reference(self.config[name]["reference"])


# -*- coding: utf-8 -*-
"""
In this exercise you will create a program that reads a pressure from the user in kilopascals. Once the pressure has been read your program should report the equivalent
pressure in pounds per square inch, millimeters of mercury and atmospheres. Use
your research skills to determine the conversion factors between these units.

"""

import math
p = float(input("Please enter the pressure in kilopascals:"))

pounds_per_square_inch = p/6.895
millimeters_of_mercury = p * 7.501
millimeters_of_atmospheres = p / 101.325

print("Equivalent pressure in pounds per square inch: {}".format(pounds_per_square_inch))
print("Equivalent pressure in millimeters of mercury: {}".format(millimeters_of_mercury))
print("Equivalent pressure in millimeters of atmospheres.: {}".format(millimeters_of_atmospheres))


from collections import deque

FILENAME = "input.txt"
LOOK_BACK = 3

def filter_empty(item: str) -> bool:
    return len(item) == 0

if __name__ == "__main__":

    previous = None
    increase = 0
    window = deque()

    with open(FILENAME, "r") as fid:
        while True:
            text = fid.readline().strip()
            try:
                # empty string at last position
                line = int(text)
            except ValueError:
                break
            window.append(line)
            if len(window) > LOOK_BACK:
                previous = window.popleft()
            try:
                if line > previous:
                    increase += 1
            except TypeError:
                pass

    print("Total count", increase)


# Created 28/10/2021
# Runs regression and optimisation examples for choice of prior mean function, acquisition function and kernel

from Regressors import *
from AcquisitionFuncs import *
from Algorithms import *
import matplotlib.pyplot as plt
import time
from numpy.random import normal

# defining objective
def objective(x, noise=0.05):
    noise = normal(loc=0, scale=noise)
    return np.ndarray.flatten((x ** 2 * np.sin(5 * np.pi * x) ** 6.0) + noise)

acq_types = ['PI', 'EI', 'UCB', 'PI-EI']
kernels = ['RBF', 'Periodic']
prior_mean_funcs = ['None', 'linear', 'quadratic']

# acq_types = ['PI']
# kernels = ['RBF']
# prior_mean_funcs = ['quadratic']

for acq_type in acq_types:
    for kernel_type in kernels:
        for prior_mean_func in prior_mean_funcs:

            if prior_mean_func == 'None':

                if kernel_type == 'RBF':
                    model = GaussianProcessReg(sigma=0.1, lengthscale=0.05, obs_noise_stdev=0.01)

                elif kernel_type == 'Periodic':
                    model = GaussianProcessReg(kernel_type='Periodic', sigma=0.1, lengthscale=0.05, obs_noise_stdev=0.01, period=2)

            elif prior_mean_func == 'linear':

                def linear(x, a, b):
                    return np.ndarray.flatten(a * x + b)

                if kernel_type=='RBF':
                    model = GaussianProcessReg(sigma=0.1, lengthscale=0.05, obs_noise_stdev=0.01, prior_mean=linear,
                                               prior_mean_kwargs={'a': 0.5, 'b': 0})

                elif kernel_type=='Periodic':
                    model = GaussianProcessReg(kernel_type='Periodic', sigma=0.1, lengthscale=0.05, obs_noise_stdev=0.01, period=2,
                                               prior_mean=linear, prior_mean_kwargs={'a': 0.5, 'b': 0})

            elif prior_mean_func == 'quadratic':

                def quadratic(x, a, b, c):
                    return np.ndarray.flatten(a * x ** 2 + b * x + c)

                if kernel_type == 'RBF':
                    model = GaussianProcessReg(sigma=0.1, lengthscale=0.05, obs_noise_stdev=0.01, prior_mean=quadratic,
                                               prior_mean_kwargs={'a': 0.5, 'b': 0, 'c': 0})

                elif kernel_type == 'Periodic':
                    model = GaussianProcessReg(kernel_type='Periodic', sigma=0.1, lengthscale=0.05, obs_noise_stdev=0.01, period=2,
                                               prior_mean=quadratic, prior_mean_kwargs={'a': 0.5, 'b': 0, 'c': 0})

            if acq_type == 'PI':
                acq_func = acq_func_builder('PI', margin=0.01)

            elif acq_type == 'EI':
                acq_func = acq_func_builder('EI', margin=0.01)

            elif acq_type == 'UCB':
                acq_func = acq_func_builder('UCB', std_weight=1)

            elif acq_type == 'PI-EI':
                pi = acq_func_builder('PI', margin=0.01)
                ei = acq_func_builder('EI', margin=0.01)
                acq_func = 0.1 * pi + 0.5 * ei

            num_iters = 6
            domain_dim = 1
            # initialising
            X0 = np.asarray(0.47).reshape((1, domain_dim))
            y0 = objective(X0)
            model.fit(X0, y0, compute_cov=True)

            X, y, surrogate_data = opt_routine(acq_func, model, num_iters, X0, y0, objective, return_surrogates=True)

            surrogate_means = surrogate_data['means']
            surrogate_stds = surrogate_data['stds']
            test_points = np.asarray(np.arange(0, 1, 1 / 1000)).reshape((1000, domain_dim))
            y_vals_no_noise = objective(test_points, noise=0.)

            f, axarr = plt.subplots(2, 3, sharex=True, sharey=True, figsize=(12, 8))
            for i in range(num_iters):
                #plt.clf()
                axarr[i//3, i%3].scatter(np.ndarray.flatten(X)[:i+1], y[:i+1])
                axarr[i//3, i%3].plot(np.ndarray.flatten(test_points), surrogate_means[i])
                axarr[i//3, i%3].plot(np.ndarray.flatten(test_points), y_vals_no_noise)
                axarr[i//3, i%3].fill_between(np.ndarray.flatten(test_points), surrogate_means[i] - surrogate_stds[i],
                                 surrogate_means[i] + surrogate_stds[i], alpha=0.4)
                axarr[i//3, i%3].set_title("t=" + str(i))

            plt.tight_layout()
            plt.savefig("/Users/jlw31/Desktop/Some results/" + acq_type + "/" + kernel_type + "/" +
                        prior_mean_func + "/Results.png")


#Printing *,Anything on the screen by taking number

def Display(value):
    for i in range(0,value,1):
        print("Marevllous")

def main():
    no=0

    print("Enter the size")
    no=int(input())

    Display(no)

if __name__=="__main__":
    main()


import logging

from klio.metrics import dispatcher

class MetricsRegistry(object):
    """Main client to create and emit metrics.

    Args:
        relay_clients (list(klio.metrics.base.AbstractRelayClient)):
            configured relay clients.
    """

    def __init__(self, relay_clients, transform_name):
        self._relays = relay_clients
        self._transform_name = transform_name
        self._registry = {}

    def counter(self, name, value=0, **kwargs):
        """Get or create a counter.

        Creates a new counter if one is not found with a key of
        ``"counter_{name}_{transform}"`` of the given  ``transform``.

        New counters will be stored in memory for simple caching.

        Args:
            name (str): name of counter
            value (int): starting value of counter; defaults to 0
            kwargs (dict): keyword arguments passed to each configured
                relay clients' counter object.
        Returns:
            dispatcher.CounterDispatcher: instance of a counter dispatcher
        """
        transform_name = kwargs.pop("transform", self._transform_name)
        key = "counter_{}_{}".format(name, transform_name)
        if key in self._registry:
            return self._registry[key]

        counter = dispatcher.CounterDispatcher(
            relay_clients=self._relays,
            name=name,
            value=value,
            transform=transform_name,
            **kwargs
        )
        self._registry[key] = counter
        return counter

    def gauge(self, name, value=0, **kwargs):
        """Get or create a gauge.

        Creates a new gauge if one is not found with a key of
        "gauge_{name}_{transform}".

        New gauges will be stored in memory for simple caching.

        Args:
            name (str): name of gauge
            value (int): starting value of gauge; defaults to 0
            kwargs (dict): keyword arguments passed to each configured
                relay clients' gauge object.
        Returns:
            dispatcher.GaugeDispatcher: instance of a gauge dispatcher
        """
        transform_name = kwargs.pop("transform", self._transform_name)
        key = "gauge_{}_{}".format(name, transform_name)
        if key in self._registry:
            return self._registry[key]

        gauge = dispatcher.GaugeDispatcher(
            relay_clients=self._relays,
            name=name,
            value=value,
            transform=transform_name,
            **kwargs
        )
        self._registry[key] = gauge
        return gauge

    def timer(self, name, value=0, timer_unit="ns", **kwargs):
        """Get or create a timer.

        Creates a new timer if one is not found with a key of
        "timer_{name}_{transform}".

        New timers will be stored in memory for simple caching.

        Args:
            name (str): name of timer
            value (int): starting value of timer; defaults to 0
            timer_unit (str): desired unit of time; defaults to ns
            kwargs (dict): keyword arguments passed to each configured
                relay clients' timer object.
        Returns:
            dispatcher.TimerDispatcher: instance of a timer dispatcher
        """
        transform_name = kwargs.pop("transform", self._transform_name)
        key = "timer_{}_{}".format(name, transform_name)
        if key in self._registry:
            return self._registry[key]

        timer = dispatcher.TimerDispatcher(
            relay_clients=self._relays,
            name=name,
            value=value,
            transform=transform_name,
            timer_unit=timer_unit,
            **kwargs
        )
        self._registry[key] = timer
        return timer

    def marshal(self, metric):
        """Create a dictionary-representation of a given metric.

        Used when metric objects need to be pickled.

        Args:
            metric (dispatcher.BaseMetricDispatcher): metric instance to
                marshal.

        Returns:
            dict: the metric's data in dictionary form
        """
        data = {
            "type": metric.METRIC_TYPE,
            "name": metric.name,
            "value": metric.value,
        }
        data.update(metric.kwargs)
        return data

    def unmarshal(self, metric_data):
        """Create a metric instance based off of a dictionary.

        If "type" is not specified or is not one of "counter", "gauge",
        or "timer", it defaults to a gauge-type metric.

        Used when metrics objects need to be unpickled.

        Args:
            metric_data (dict): dictionary-representation of a given
                metric.

        Returns:
            dispatcher.BaseMetricDispatcher: a dispatcher relevant to
            metric type.
        """
        metric_type = metric_data.pop("type", None)
        name = metric_data.pop("name", None)
        value = metric_data.pop("value", None)
        kwargs = metric_data

        metric_method = {
            "counter": self.counter,
            "gauge": self.gauge,
            "timer": self.timer,
        }.get(metric_type)

        if not metric_method:
            msg = "Metric type '{}' not supported. Defaulting to gauge.".format(
                metric_type
            )
            logging.getLogger("klio.metrics").warning(msg)
            metric_method = self.gauge

        return metric_method(name=name, value=value, **kwargs)


import copy
import itertools

from enum import Enum
import tensorflow as tf
import numpy as np

class HandGesture(Enum):
    NONE = "NONE"     # ❌

    FORWARD = "FORWARD"  # ✋
    STOP = "STOP"     # ✊
    UP = "UP"       # 👆
    LAND = "LAND"     # 👌
    DOWN = "DOWN"     # 👇
    BACK = "BACK"     # 👊
    LEFT = "LEFT"     # 👈 thumb
    RIGHT = "RIGHT"    # 👉 thumb

    def enum_all():
        return list(HandGesture)

class KeyPointClassifier(object):
    def __init__(
        self,
        model_path='modules/command_recognition/model/keypoint_classifier.tflite',
    ):
        self.interpreter = tf.lite.Interpreter(
            model_path=model_path,
            num_threads=1
        )
        self.interpreter.allocate_tensors()

        self.input = self.interpreter.get_input_details()
        self.output = self.interpreter.get_output_details()

    def classify(self, landmarks):
        landmarks = np.array([self._pre_process_landmark(landmarks)], dtype=np.float32)

        input_details_tensor_index = self.input[0]['index']
        self.interpreter.set_tensor(
            input_details_tensor_index,
            landmarks,
        )
        self.interpreter.invoke()

        output_index = self.output[0]['index']

        results = np.squeeze(self.interpreter.get_tensor(output_index))
        best_res = np.argmax(results)

        if results[best_res] <= 0.7 or \
            ((results[best_res] - sorted(results)[:-1]) < 0.5).any():
            return HandGesture.NONE
        else:
            return HandGesture.enum_all()[best_res + 1]

    def _pre_process_landmark(self, landmarks):
        temp_landmarks = copy.deepcopy(landmarks)

        # Convert to relative coordinates
        base_x, base_y = 0, 0
        for index, landmark_point in enumerate(temp_landmarks):
            if index == 0:
                base_x, base_y = landmark_point[0], landmark_point[1]

            temp_landmarks[index][0] = temp_landmarks[index][0] - base_x
            temp_landmarks[index][1] = temp_landmarks[index][1] - base_y
            temp_landmarks[index].pop()

        # Convert to a one-dimensional list
        temp_landmarks = list(itertools.chain.from_iterable(temp_landmarks))

        # Normalization
        max_value = max(list(map(abs, temp_landmarks)))

        temp_landmarks = list(map(lambda n: n / max_value, temp_landmarks))

        return temp_landmarks