import os
import json
from Script.Core import cache_control, value_handle, game_type
from Script.Config import game_config, normal_config
from Script.UI.Moudle import draw

cache: game_type.Cache = cache_control.cache
""" 游戏缓存数据 """
scene_path_edge_path = os.path.join("data", "ScenePath")
""" 寻路路径配置文件路径 """
scene_path_edge = {}
""" 寻路路径 """
width: int = normal_config.config_normal.text_width
""" 窗体宽度 """

def get_map_draw_for_map_path(map_path_str: str) -> str:
    """
    从地图路径获取地图绘制数据
    Keyword arguments:
    map_path -- 地图路径
    """
    map_data = get_map_data_for_map_path(map_path_str)
    return map_data.map_draw

def get_scene_id_in_map_for_scene_path_on_map_path(scene_path: list, map_path: list) -> list:
    """
    获取场景在地图上的相对位置
    Keyword arguments:
    scene_path -- 场景路径
    map_path -- 地图路径
    """
    return scene_path[len(map_path)]

def get_map_for_path(scene_path: list) -> list:
    """
    查找场景所在地图路径
    Keyword arguments:
    scene_path -- 场景路径
    """
    map_path = scene_path[:-1]
    map_path_str = get_map_system_path_str_for_list(map_path)
    if map_path_str in cache.map_data:
        return map_path
    return get_map_for_path(map_path)

def get_map_data_for_map_path(map_path_str: str) -> game_type.Map:
    """
    从地图路径获取地图数据
    Keyword arguments:
    map_path -- 地图路径
    Return arguments:
    game_type.Map -- 地图数据
    """
    return cache.map_data[map_path_str]

def get_scene_list_for_map(map_path_str: str) -> list:
    """
    获取地图下所有场景
    Keyword arguments:
    map_path -- 地图路径
    """
    map_data = get_map_data_for_map_path(map_path_str)
    scene_list = list(map_data.path_edge.keys())
    return scene_list

def get_scene_name_list_for_map_path(map_path_str: str):
    """
    获取地图下所有场景的名字
    Keyword arguments:
    map_path -- 地图路径
    """
    scene_list = get_scene_list_for_map(map_path_str)
    scene_name_data = {}
    for scene in scene_list:
        load_scene_data = get_scene_data_for_map(map_path_str, scene)
        scene_name = load_scene_data.scene_name
        scene_name_data[scene] = scene_name
    return scene_name_data

def character_move_scene(old_scene_path: list, new_scene_path: list, character_id: int):
    """
    将角色移动至新场景
    Keyword arguments:
    old_scene_path -- 旧场景路径
    new_scene_path -- 新场景路径
    character_id -- 角色id
    """
    old_scene_path_str = get_map_system_path_str_for_list(old_scene_path)
    new_scene_path_str = get_map_system_path_str_for_list(new_scene_path)
    character_data = cache.character_data[character_id]
    # 从旧场景移除角色
    if character_id in cache.scene_data[old_scene_path_str].character_list:
        cache.scene_data[old_scene_path_str].character_list.remove(character_id)
    # 在新场景添加角色
    if character_id not in cache.scene_data[new_scene_path_str].character_list:
        character_data.position = new_scene_path
        cache.scene_data[new_scene_path_str].character_list.add(character_id)
    # 刷新移动起止位置
    character_data.behavior.move_src = old_scene_path
    character_data.behavior.move_target = new_scene_path
    # 清零最终目的地
    if new_scene_path == character_data.behavior.move_final_target:
        character_data.behavior.move_final_target = []
        # print(f"debug {character_data.name} 清零最终目的地")

def get_map_system_path_str_for_list(now_list: list) -> str:
    """
    将地图路径列表数据转换为字符串
    Keyword arguments:
    now_list -- 地图路径列表数据
    """
    # print(f"debug now_list = {now_list}")
    return os.sep.join(now_list)

def get_path_finding(map_path_str: str, now_node: str, target_node: str) -> (str, game_type.TargetPath):
    """
    查询寻路路径
    Keyword arguments:
    map_path -- 地图路径
    now_node -- 当前节点相对位置
    target_node -- 目标节点相对位置
    Return arguments:
    str:end -- 寻路路径终点
    game_type.TargetPath -- 寻路路径
    """
    if now_node == target_node:
        return "End", game_type.TargetPath()
    else:
        return (
            "",
            cache.map_data[map_path_str].sorted_path[now_node][target_node],
        )

def get_scene_to_scene_map_list(now_scene_path: list, target_scene_path: list) -> (str, list):
    """
    获取场景到场景之间需要经过的地图列表
    如果两个场景属于同一地图并在同一层级，则返回common
    Keyword arguments:
    now_scene_path -- 当前场景路径
    target_scene_path -- 目标场景路径
    Return arguments:
    str:common -- 两个场景在同一层级
    list -- 场景层级路径列表
    """
    scene_affiliation = judge_scene_affiliation(now_scene_path, target_scene_path)
    if scene_affiliation == "common":
        return "common", []
    elif scene_affiliation == "subordinate":
        return (
            "",
            get_map_hierarchy_list_for_scene_path(now_scene_path, target_scene_path),
        )
    elif scene_affiliation == "nobelonged":
        common_map = get_common_map_for_scene_path(now_scene_path, target_scene_path)
        now_scene_to_common_map = get_map_hierarchy_list_for_scene_path(now_scene_path, common_map)
        target_scene_to_common_map = get_map_hierarchy_list_for_scene_path(target_scene_path, common_map)
        common_map_to_target_scene = value_handle.reverse_array_list(target_scene_to_common_map)
        return "", now_scene_to_common_map + common_map_to_target_scene[1:]

def get_common_map_for_scene_path(scene_a_path: list, scene_b_path: list) -> list:
    """
    查找场景共同所属地图
    Keyword arguments:
    scene_aPath -- 场景A路径
    scene_bpath -- 场景B路径
    """
    hierarchy = []
    if scene_a_path[:-1] == [] or scene_b_path[:-1] == []:
        return hierarchy
    else:
        for i in range(0, len(scene_a_path)):
            try:
                if scene_a_path[i] == scene_b_path[i]:
                    hierarchy.append(scene_a_path[i])
                else:
                    break
            except IndexError:
                break
        return get_map_path_for_true(hierarchy)

def get_map_hierarchy_list_for_scene_path(now_scene_path: list, target_scene_path: list) -> list:
    """
    查找当前场景到目标场景之间的层级列表(仅当当前场景属于目标场景的子场景时可用)
    Keyword arguments:
    now_scene_path -- 当前场景路径
    target_scene_path -- 目标场景路径
    Return arguments:
    hierarchy_list -- 当前场景路径到目标场景路径之间的层级列表
    """
    hierarchy_list = []
    now_path = None
    while True:
        if now_path is None:
            now_path = now_scene_path[:-1]
        if now_path != target_scene_path:
            hierarchy_list.append(now_path)
            now_path = now_path[:-1]
        else:
            break
    return hierarchy_list

def get_map_path_for_true(map_path: list) -> list:
    """
    判断地图路径是否是有效的地图路径，若不是，则查找上层路径，直到找到有效地图路径并返回
    Keyword arguments:
    map_path -- 当前地图路径
    """
    map_path_str = get_map_system_path_str_for_list(map_path)
    if map_path_str in cache.map_data:
        return map_path
    else:
        new_map_path = map_path[:-1]
        return get_map_path_for_true(new_map_path)

def judge_scene_is_affiliation(now_scene_path: list, target_scene_path: list) -> str:
    """
    获取场景所属关系
    当前场景属于目标场景的子场景 -> 返回'subordinate'
    目标场景属于当前场景的子场景 -> 返回'superior'
    other -> 返回'common'
    Keyword arguments:
    now_scene_path -- 当前场景路径
    target_scene_path -- 目标场景路径
    """
    if judge_scene_affiliation(now_scene_path, target_scene_path) == "subordinate":
        return "subordinate"
    elif judge_scene_affiliation(target_scene_path, now_scene_path) == "subordinate":
        return "superior"
    return "common"

def judge_scene_affiliation(now_scene_path: list, target_scene_path: list) -> str:
    """
    判断场景有无所属关系
    当前场景属于目标场景的子场景 -> 返回'subordinate'
    当前场景与目标场景的第一个上级场景相同 -> 返回'common'
    other -> 返回'nobelonged'
    Keyword arguments:
    now_scene_path -- 当前场景路径
    target_scene_path -- 目标场景路径
    """
    judge = 1
    for i in range(len(now_scene_path)):
        if len(target_scene_path) - 1 >= i:
            if now_scene_path[i] != target_scene_path[i]:
                judge = 0
                break
        if i > len(target_scene_path) - 1:
            break
        if target_scene_path[i] != now_scene_path[i]:
            judge = 0
            break
    if judge:
        return "subordinate"
    now_father = now_scene_path[:-1]
    target_father = target_scene_path[:-1]
    if now_father == target_father:
        return "common"
    return "nobelonged"

def get_relation_map_list_for_scene_path(scene_path: list) -> list:
    """
    获取场景所在所有直接地图(当前场景id为0，所在地图在上层地图相对位置也为0，视为直接地图)位置
    Keyword arguments:
    scene_path -- 当前场景路径
    """
    now_path = scene_path
    now_map_path = scene_path[:-1]
    now_pathId = now_path[-1]
    map_list = []
    if now_map_path != [] and now_map_path[:-1] != []:
        map_list.append(now_map_path)
        if now_pathId == "0":
            return map_list + get_relation_map_list_for_scene_path(now_map_path)
        else:
            return map_list
    else:
        map_list.append(now_map_path)
        return map_list

def get_scene_data_for_map(map_path_str: str, map_scene_id: str) -> game_type.Scene:
    """
    载入地图下对应场景数据
    Keyword arguments:
    map_path -- 地图路径
    map_scene_id -- 场景相对位置
    Return arguments:
    game_type.Scene -- 场景数据
    """
    if map_path_str == "":
        scene_path_str = map_scene_id
    else:
        scene_path_str = map_path_str + os.sep + str(map_scene_id)
    scene_path = get_map_system_path_for_str(scene_path_str)
    scene_path = get_scene_path_for_true(scene_path)
    scene_path_str = get_map_system_path_str_for_list(scene_path)
    return cache.scene_data[scene_path_str]

def get_scene_path_for_map_scene_id(map_path: list, map_scene_id: str) -> list:
    """
    从场景在地图中的相对位置获取场景路径
    Keyword arguments:
    map_path -- 地图路径
    map_scene_id -- 场景在地图中的相对位置
    """
    new_scene_path = map_path.copy()
    new_scene_path.append(map_scene_id)
    new_scene_path = get_scene_path_for_true(new_scene_path)
    return new_scene_path

def get_map_system_path_for_str(path_str: str) -> list:
    """
    将地图系统路径文本转换为地图系统路径
    """
    return path_str.split(os.sep)

def get_map_scene_id_for_scene_path(map_path: list, scene_path: list) -> str:
    """
    从场景路径查找场景在地图中的相对位置
    Keyword arguments:
    map_path -- 地图路径
    scene_path -- 场景路径
    """
    return scene_path[len(map_path)]

def get_scene_path_for_true(scene_path: list) -> list:
    """
    获取场景的有效路径(当前路径下若不存在场景数据，则获取当前路径下相对位置为0的路径)
    Keyword arguments:
    scene_path -- 场景路径
    """
    scene_path_str = get_map_system_path_str_for_list(scene_path)
    # print(f"debug scene_path_str = {scene_path_str} ")
    # print(f"debug cache.scene_data = {cache.scene_data} ")
    if scene_path_str in cache.scene_data:
        return scene_path
    else:
        scene_path.append("0")
        return get_scene_path_for_true(scene_path)

def get_map_door_data_for_scene_path(scene_path: list) -> dict:
    """
    从场景路径获取当前地图到其他地图的门数据
    Keyword arguments:
    scene_path -- 场景路径
    """
    map_path = get_map_for_path(scene_path)
    map_path_str = get_map_system_path_str_for_list(map_path)
    return get_map_door_data(map_path_str)

def get_map_door_data(map_path_str: str) -> dict:
    """
    获取地图下通往其他地图的门数据
    Keyword arguments:
    map_path -- 地图路径
    """
    map_data = cache.map_data[map_path_str]
    if "MapDoor" in map_data:
        return map_data["MapDoor"]
    else:
        return {}

def get_scene_character_name_list(scene_path_str: str, remove_own_character=False) -> list:
    """
    获取场景上所有角色的姓名列表
    Keyword arguments:
    scene_path -- 场景路径
    remove_own_character -- 从姓名列表中移除主角 (default False)
    """
    scene_character_data = cache.scene_data[scene_path_str].character_list
    now_scene_character_list = list(scene_character_data)
    name_list = []
    if remove_own_character:
        now_scene_character_list.remove(0)
    for character_id in now_scene_character_list:
        character_name = cache.character_data[character_id].name
        name_list.append(character_name)
    return name_list

def get_character_id_by_character_name(character_name: str, scene_path_str: str) -> str:
    """
    获取场景上角色姓名对应的角色id
    Keyword arguments:
    character_name -- 角色姓名
    scene_path -- 场景路径
    """
    character_nameList = get_scene_character_name_list(scene_path_str)
    character_nameIndex = character_nameList.index(character_name)
    character_idList = get_scene_character_id_list(scene_path_str)
    return character_idList[character_nameIndex]

def get_scene_character_id_list(scene_path_str: str) -> list:
    """
    获取场景上所有角色的id列表
    Keyword arguments:
    scene_path -- 场景路径
    """
    return list(cache.scene_data[scene_path_str].character_list)

def sort_scene_character_id(scene_path_str: str):
    """
    对场景上的角色按好感度进行排序
    Keyword arguments:
    scene_path -- 场景路径
    """
    now_scene_character_intimate_data = {}
    for character in cache.scene_data[scene_path_str].character_list:
        now_scene_character_intimate_data[character] = cache.character_data[character].intimate
    new_scene_character_intimate_data = sorted(
        now_scene_character_intimate_data.items(),
        key=lambda x: (x[1], -int(x[0])),
        reverse=True,
    )
    new_scene_character_intimate_data = value_handle.two_bit_array_to_dict(
        new_scene_character_intimate_data
    )
    cache.scene_data[scene_path_str].character_list = set(new_scene_character_intimate_data)

def init_scene_edge_path_data():
    """初始化全部地图寻路数据"""
    global scene_path_edge
    scene_path_edge = {}
    for now_position_str in cache.scene_data:
        scene_path_edge[now_position_str] = {}
        # 忽略大地图
        if "泰拉" in now_position_str:
            continue
        for target_scene_str in cache.scene_data:
            if target_scene_str == now_position_str:
                continue
            # 忽略大地图
            if "泰拉" in target_scene_str:
                continue
            now_position = get_map_system_path_for_str(now_position_str)
            target_scene = get_map_system_path_for_str(target_scene_str)
            scene_hierarchy = judge_scene_affiliation(now_position, target_scene)
            if scene_hierarchy == "common":
                map_path = get_common_map_for_scene_path(now_position, target_scene)
                now_map_scene_id = get_map_scene_id_for_scene_path(map_path, now_position)
                target_map_scene_id = get_map_scene_id_for_scene_path(map_path, target_scene)
                _, _, now_move_target, now_move_time = identical_map_move(
                    now_position, map_path, now_map_scene_id, target_map_scene_id
                )
            else:
                _, _, now_move_target, now_move_time = difference_map_move(now_position, target_scene)
            scene_path_edge[now_position_str][target_scene_str] = [now_move_target, now_move_time]
    with open(scene_path_edge_path, "w") as path_edge_file:
        json.dump(scene_path_edge, path_edge_file)

def difference_map_move(now_position: list, target_scene: list) -> (str, list, list, int):
    """
    角色跨地图层级移动
    Keyword arguments:
    target_scene -- 寻路目标场景(在地图系统下的绝对坐标)
    Return arguments:
    str:null -- 未找到路径
    str:end -- 当前位置已是路径终点
    list -- 路径
    list -- 本次移动到的位置
    int -- 本次移动花费的时间
    """
    is_affiliation = judge_scene_affiliation(now_position, target_scene)
    now_true_position = get_scene_path_for_true(now_position)
    now_true_map = get_map_for_path(now_true_position)
    if is_affiliation == "subordinate":
        now_true_affiliation = judge_scene_is_affiliation(now_true_position, target_scene)
        if now_true_affiliation == "subordinate":
            now_map_scene_id = get_map_scene_id_for_scene_path(now_true_map, now_true_position)
            return identical_map_move(now_position, now_true_map, now_map_scene_id, "0")
        now_map = get_map_for_path(target_scene)
        now_map_scene_id = get_map_scene_id_for_scene_path(now_map, now_position)
        return identical_map_move(now_position, now_map, now_map_scene_id, "0")
    relation_map_list = get_relation_map_list_for_scene_path(now_true_position)
    now_scene_real_map = relation_map_list[-1]
    now_map_scene_id = get_map_scene_id_for_scene_path(now_scene_real_map, now_true_position)
    common_map = get_common_map_for_scene_path(now_true_position, target_scene)
    if now_scene_real_map != common_map:
        if now_map_scene_id == "0":
            now_true_position = now_scene_real_map.copy()
            relation_map_list = get_relation_map_list_for_scene_path(now_true_position)
            now_scene_real_map = relation_map_list[-1]
    target_map_scene_id = get_map_scene_id_for_scene_path(common_map, target_scene)
    if now_scene_real_map == common_map:
        now_map_scene_id = get_map_scene_id_for_scene_path(common_map, now_true_position)
    else:
        now_map_scene_id = get_map_scene_id_for_scene_path(now_scene_real_map, now_true_position)
        target_map_scene_id = "0"
        common_map = now_scene_real_map
    return identical_map_move(now_position, common_map, now_map_scene_id, target_map_scene_id)

def identical_map_move(
    now_position: list,
    now_map: list,
    now_map_scene_id: str,
    target_map_scene_id: str,
) -> (str, list, list, int):
    """
    角色在相同地图层级内移动
    Keyword arguments:
    now_position -- 当前场景位置
    now_map -- 当前地图路径
    now_map_scene_id -- 当前角色所在场景(当前地图层级下的相对坐标)
    target_map_scene_id -- 寻路目标场景(当前地图层级下的相对坐标)
    Return arguments:
    str:null -- 未找到路径
    str:end -- 当前位置已是路径终点
    list -- 路径
    list -- 本次移动到的位置
    int -- 本次移动花费的时间
    """
    now_map_str = get_map_system_path_str_for_list(now_map)
    move_end, move_path = get_path_finding(now_map_str, now_map_scene_id, target_map_scene_id)
    now_target_position = []
    now_need_time = 0
    if move_path != []:
        now_target_scene_id = move_path.path[0]
        now_need_time = move_path.time[0]
        now_target_position = get_scene_path_for_map_scene_id(now_map, now_target_scene_id)
    return move_end, move_path, now_target_position, now_need_time

def judge_scene_accessible(target_scene_str : str, character_id : int) -> int :
    """
    判断目标地点是否可以进入
    Keyword arguments:
    target_scene_str -- 目标场景位置（例：A\B\C）
    Return arguments:
    str -- open:可以进入,wait_open:未解锁,door_lock:门上锁,private:私密场所
    """

    # print(f"debug target_scene_str = {target_scene_str}")
    now_scene_data = cache.scene_data[target_scene_str]
    character_data = cache.character_data[character_id]
    pl_character_data = cache.character_data[0]
    # print(f"debug now_scene_data.name = {now_scene_data.scene_name}")

    # 遍历设施开放清单，如果名称和地图名称一样的话，则进行判断
    for open_cid in game_config.config_facility_open:
        # print(f"debug game_config.config_facility_open[open_cid].name = {game_config.config_facility_open[open_cid].name}")
        if game_config.config_facility_open[open_cid].name == now_scene_data.scene_name:

            # 如果该设施已开放，则正常通过
            if cache.rhodes_island.facility_open[open_cid]:
                return "open"
            # 是玩家的话输出提示信息
            elif character_id == 0:
                # 获取设施的解锁条件数据
                facility_effect_cid = game_config.config_facility_open[open_cid].zone_cid
                facility_npc_cid = game_config.config_facility_open[open_cid].NPC_id

                # 如果是需要设施等级解锁的话
                info_text = ""
                if facility_effect_cid:
                    zone_data = game_config.config_facility_effect[facility_effect_cid]
                    zone_name,zone_lv = zone_data.name,str(zone_data.level)
                    info_text += f"\n  ●目标移动房间——{now_scene_data.scene_name}，当前尚未解锁，解锁需要将{zone_name}升到{zone_lv}级\n"
                # 也可能需要NPC才能解锁
                if facility_npc_cid:
                    for character_id in cache.character_data:
                        character_data = cache.character_data[character_id]
                        if character_data.adv == facility_npc_cid:
                            info_text += f"\n  ●目标移动房间——{now_scene_data.scene_name}，当前尚未解锁，解锁需要获得干员{character_data.name}\n"
                            break

                line = draw.LineDraw("-", width)
                line.draw()
                info_draw = draw.WaitDraw()
                info_draw.text = info_text
                info_draw.width = width
                info_draw.draw()

            return "wait_open"

    # 锁门判断
    if now_scene_data.close_flag == 1:
        # 即使关门，也可以进去自己的宿舍
        if character_data.dormitory == target_scene_str:
            pass
        # 助理可以进锁门了的玩家房间
        elif character_id and character_id == pl_character_data.assistant_character_id:
            pass
        else:
            # 如果是玩家的话输出提示信息
            if character_id == 0:
                line = draw.LineDraw("-", width)
                line.draw()
                info_draw = draw.WaitDraw()
                info_draw.text = f"\n  ●目标移动房间——{now_scene_data.scene_name}，当前门是锁着的，需要钥匙或其他方法进入\n"
                info_draw.width = width
                info_draw.draw()
            return "door_lock"

    # 私密场所判断，仅限干员
    if character_id:
        # 博士房间
        if "Dr_room" in now_scene_data.scene_tag:
            # 助理可以进
            if character_id == pl_character_data.assistant_character_id:
                pass
            else:
                return "private"
        # 男厕所
        elif "Toilet_Male" in now_scene_data.scene_tag:
            return "private"
        # 非自己的宿舍
        elif "Dormitory" in now_scene_data.scene_tag and character_data.dormitory != target_scene_str:
            return "private"

    return "open"

def judge_scene_name_open(full_scene_str : str) -> int :
    """
    通过地点名判断目标地点是否可以进入
    Keyword arguments:
    full_scene_str -- 目标场景位置（例：A\B\C）
    Return arguments:
    int -- 是否可以进入
    """
    from Script.Config import game_config
    now_scene_data = cache.scene_data[full_scene_str]

    # print(f"debug scene_name = {now_scene_data.scene_name}")
    # 遍历设施开放清单，如果名称和地图名称一样的话，则进行判断
    for open_cid in game_config.config_facility_open:
        # print(f"debug game_config.config_facility_open[open_cid].name = {game_config.config_facility_open[open_cid].name}")
        if game_config.config_facility_open[open_cid].name == now_scene_data.scene_name:
            if cache.rhodes_island.facility_open[open_cid]:
                return 1
            else:
                return 0

    # 关了门的房间进不去
    if now_scene_data.close_flag == 1:
        return 0

    return 1


a = input("1. Sayı: ")
b = input("2. Sayi: ")

a , b = int(a) , int(b)

bolen_a = list()
bolen_b = list()
ortak = list()

for i in range(1,a+1):
    if a % i == 0:
        bolen_a.append(i)

for i in range(1,b+1):
    if b % i == 0:
        bolen_b.append(i)

for i in bolen_a:
    for y in bolen_b:
        if i == y:
            ortak.append(y)

print(bolen_a)
print(bolen_b)
print(ortak)
print(ortak[len(ortak)-1])


import random
import math
import pygame as py

class Gamestate:
    def __init__(self, rows: int):
        self.size = rows
        self.tiles = [0] * rows ** 2

        self.addTile()
        self.addTile()

    def shiftTiles(self, direction: int):
        copy = self.tiles

        if direction in (py.K_UP, py.K_DOWN):
            self.transposeTiles()

        if direction in (py.K_RIGHT, py.K_DOWN):
            self.mirrorTiles()

        rows = [self.tiles[row_start:row_start + self.size] for row_start in range(0, self.size ** 2, self.size)]

        for row_num in range(self.size):
            row = rows[row_num]
            for tile in range(1, self.size):
                degree = row[tile]
                if degree == 0: continue

                for destination in range(tile, -1, -1):
                    if destination == 0:
                        row[destination] = degree
                        row[tile] = 0
                        break

                    if row[destination - 1] == 0:
                        continue

                    if row[destination - 1] == degree:
                        row[destination - 1] += 1
                        row[tile] = 0
                        break

                    row[tile] = 0
                    row[destination] = degree
                    break

            self.tiles[row_num * self.size:(row_num + 1) * self.size] = row

        if direction in (py.K_RIGHT, py.K_DOWN):
            self.mirrorTiles()

        if direction in (py.K_UP, py.K_DOWN):
            self.transposeTiles()

        if not self.tiles != copy:
            self.addTile()

    def addTile(self):
        if self.tiles.count(0) == 0: return

        tile = math.floor(random.random() * self.size ** 2)
        while self.tiles[tile] != 0:
            tile = math.floor(random.random() * self.size ** 2)

        degree = min(math.floor(-math.log10(random.random())), 4) + 1

        self.tiles[tile] = degree

    def transposeTiles(self):
        transposed = [0] * self.size ** 2

        for tile in range(self.size ** 2):
            row = tile // self.size
            col = tile % self.size

            transposed[tile] = self.tiles[self.size * col + row]

        self.tiles = transposed

    def mirrorTiles(self):
        mirrored = []

        for row_number in range(self.size):
            row = self.tiles[row_number * self.size: (row_number + 1) * self.size]
            mirrored_row = row[::-1]  # Reverse the row to mirror it
            mirrored.extend(mirrored_row)

        self.tiles = mirrored

    def gameOver(self) -> bool:
        if self.tiles.count(0) > 0: return False

        rows = [self.tiles[row_start:row_start + self.size] for row_start in range(0, self.size ** 2, self.size)]
        self.transposeTiles()
        cols = [self.tiles[col_start:col_start + self.size] for col_start in range(0, self.size ** 2, self.size)]
        self.transposeTiles()

        for row in range(self.size):
            for tile in range(self.size - 1):
                if rows[row][tile] == rows[row][tile + 1]: return False
                if cols[row][tile] == cols[row][tile + 1]: return False

        return True


"""empty message

Revision ID: b441e488714d
Revises: 4868780239ae
Create Date: 2019-12-08 14:12:50.600366

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'b441e488714d'
down_revision = '4868780239ae'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.alter_column('Artist', 'seeking_venue', server_default=False)
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.alter_column('Artist', 'seeking_venue', server_default=None)
    # ### end Alembic commands ###


class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:

        Mark=[False]*(len(s)+1)
        Mark[len(s)]=True

        for i in range(len(s)-1,-1,-1):
            for word in wordDict:
                if (len(word)+i)<=len(s) and s[i:i+len(word)] == word and Mark[i+len(word)]:
                    Mark[i]=True
                    break

        return Mark[0]


__author__ = 'Sam Kasbawala'
__credits__ = 'Sam Kasbawala'

import unittest

class TreeNode():
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None
        self.parent = None

def next_node(node):
    """Returns the next node in the in-order sequence given the current node"""

    # If the node is None, then there is no next node
    if node is None:
        return None

    # In-order traversal goes: left -> current -> right
    # If at current, then the next node is the left most of the right tree
    if node.right is not None:
        current_node = node.right
        while current_node.left is not None:
            current_node = current_node.left
        return current_node

    # If there is no right sub-tree, and we are on the left side of the parent
    # node, the next node is the parent node. If we are on the right side of
    # the parent node, we need to traverse up until we find a node that hasn't
    # been traversed. We know a node hasn't been traversed if we move from
    # it's left child to the parent
    child = node
    parent = node.parent

    while (parent is not None and parent.right is child):
        child = child.parent
        parent = parent.parent
    return parent

class TestNextNode(unittest.TestCase):
    def test_next_node(self):
        tree_1 = TreeNode(2)
        tree_1.left = TreeNode(1)
        tree_1.left.parent = tree_1
        tree_1.right = TreeNode(3)
        tree_1.right.parent = tree_1

        self.assertTrue(next_node(tree_1), tree_1.right)
        self.assertTrue(next_node(tree_1.left), tree_1)
        self.assertIsNone(next_node(tree_1.right))

        a = TreeNode('a')
        b = TreeNode('b')
        c = TreeNode('c')
        d = TreeNode('d')
        e = TreeNode('e')
        f = TreeNode('f')
        g = TreeNode('g')

        d.left = b
        b.parent = d
        d.right = f
        f.parent = d

        b.left = a
        a.parent = b
        b.right = c
        c.parent = b

        f.left = e
        e.parent = f
        f.right = g
        g.parent = f

        self.assertTrue(next_node(d), e)
        self.assertTrue(next_node(a), b)
        self.assertTrue(next_node(e), f)
        self.assertTrue(next_node(f), g)
        self.assertIsNone(next_node(g))

        self.assertIsNone(next_node(None))

if __name__ == '__main__':
    unittest.main()


#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'Liwink'

import socket
import time

class HTTPServer:
    """A non-blocking, single-threaded HTTP server.

    A server is defined by by a request callback that takes on HTTPRequest
    instance as an argument and writes a valid HTTP response with
    request.write().

    """

    def __init__(self, request_callback, no_keep_alive=False, io_loop=None,
                 xheaders=False, ssl_options=None):
        self.request_callback = request_callback
        self.no_keep_alive = no_keep_alive
        self.io_loop = io_loop
        self.xheaders = xheaders
        self.ssl_options = ssl_options
        self._socket = None
        self._started = False

    def listen(self, port, address=""):
        self.bind(port, address)
        self.start(1)

    def bind(self, port, address=""):
        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
        self._socket.setsocketopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._socket.bind((port, address))
        self._socket.listen(1)

    def start(self, num_processes=1):
        self._started = True
        if num_processes == 1:
            if not self.io_loop:
                self.io_loop = ioloop.IOLoop.instance()
            self.io_loop.add_handler(self._socket.fileno(),
                                     self._handle_events,
                                     ioloop.IOLoop.READ)

    def _handle_events(self):
        while True:
            connection, address = self._socket.accept()
            stream = iostream.IOStream(connection, io_loop=self.io_loop)
            # not explicitly, just create a object
            # ( create -> 'read_until' -> callback
            HTTPConnection(stream, address, self.request_callback,
                           self.no_keep_alive, self.xheaders)

class HTTPConnection:
    """Handles a connection to an HTTP client, executing HTTP requests.

    We parse HTTP headers and bodies, and execute the request callback
    until the HTTP connection is closed.

    """

    def __init__(self, stream, address, request_callback, no_keep_alive=False,
                 xheaders=False):
        self.stream = stream
        self.address = address
        self.request_callback = request_callback
        self.no_keep_alive = no_keep_alive
        self.xheaders = xheaders
        self._request = None
        self._request_finished = False
        # TODO: \r\n\r\n ?
        self.stream.read_until("\r\n\r\n", self._on_headers)

    def _on_headers(self, data):
        eol = data.find("\r\n")
        start_line = data[:eol]
        method, uri, version = start_line.splite(" ")
        headers = httputil.HTTPHeaders.parse(data[eol:])
        self._request = HTTPRequest(
            connection=self, method=method, uri=uri, version=version,
            headers=headers, remote_ip=self.address[0]
        )
        content_length = headers.get("Content-Length")
        # following not good, should be one method
        if content_length:
            self.stream.read_bytes(int(content_length), self._on_request_body)
        self.request_callback(self._request)

class HTTPRequest:
    def __init__(self, method, uri, version="HTTP/1.0", headers=None,
                 body=None, remote_ip=None, protocol=None, host=None,
                 files=None, connection=None):
        self.method = method
        self.uri = uri
        self.version = version
        self.headers = headers
        self.body = body or ""
        self.host = host or self.headers.get("Host") or "127.0.0.1"
        self.files = files or {}
        self.connection = connection
        self._start_time = time.time()
        self._finish_time = None


get_ipython().system(u'pip install --upgrade --no-deps https://cntk.ai/PythonWheel/CPU-Only/cntk-2.4-cp35-cp35m-linux_x86_64.whl')

import cntk as C
print ("Using Microsoft Cognitive Toolkit version {}".format(C.__version__))

import numpy as np
print ("Using numpy version {}".format(np.__version__))

# In[2]:

import matplotlib.pyplot as plt
get_ipython().magic(u'matplotlib inline')
import time
import sys
import os
import cv2
from IPython.display import Image, display #, SVG
from cntk.learners import learning_rate_schedule, UnitType
from cntk.initializer import he_normal
from cntk.layers import AveragePooling, BatchNormalization, Convolution, Dense
from cntk.ops import element_times, relu, sigmoid
from cntk import load_model, placeholder, Constant
from tqdm import *          # tqdm allows us to pretty-print our loops later on...
import helper # some functions to plot images
import coco   # local class to read the COCO images and labels
import gc # Python garbage collector

# Paths relative to current python file.
abs_path  = os.path.dirname(os.path.abspath('.'))
data_path = os.path.join(abs_path, "../../data/M4")
zip_path = os.path.join(abs_path, "../data-zip")
output_path = os.path.join(abs_path, "lab1/output")

# Now, let's setup and call our function to setup the large dataset that is  needed for this lab.
#
# Why are we doing this? We need this step because Azure Notebooks has two storage areas: a persistent but slow area, and a transient but fast area. To ensure that this lab is able to execute as fast as possible on Azure Notebooks, we unzip our data set into this transient area once per session.  If it has already been unzipped then we'll automatically detect this and skip the step, so it is safe to run this next code block at any time.
#
# Depending on how you are executing the lab, this step can take a minute or two.  The output you should expect to see from the following code block will look something like:
#
#     Start unzipping data files in /home/nbuser/library/Module4/../data-zip to /home/nbuser/library/Module4/../../data/M4
#     zip file count:1
#     Destination folder /home/nbuser/library/Module4/../../data/M4 doesn't exist, creating it
#     Start unzipping files to /home/nbuser/library/Module4/../../data/M4
#        unzipping CocoMS.zip ...
#     Complete: Files have been unzipped to /home/nbuser/library/Module4/../../data/M4

# In[3]:

import sys
import os
import zipfile
import fnmatch

def hydrate(zip_path, dest_path):
    print("Start unzipping data files in {0} to {1}".format(zip_path,dest_path))
    if (os.path.exists(zip_path) == False):
        print("The source folder {0} doesn't exist, so quitting".format(zip_path))
        quit()

    zipfile_count = len(fnmatch.filter(os.listdir(zip_path), '*.zip'))
    if (zipfile_count == 0):
        print("No zip (.zip) files in {0}, so quitting ".format(zip_path))

    print("zip file count:%s" % zipfile_count)

    if (os.path.exists(dest_path) == False):
        print("Destination folder {0} doesn't exist, creating it".format(dest_path))
        os.makedirs(dest_path)

        # Extract all zip files from zip_path to dest_path
        print("Start unzipping files to {0}".format(dest_path))
        for item in os.listdir(zip_path): # loop through items in dir
            if item.endswith(".zip"): # check for ".zip" extension
                print("   unzipping {0} ...".format(item))
                file_name = os.path.join(zip_path,item) # get full path of files
                zip_ref = zipfile.ZipFile(file_name) # create zipfile object
                zip_ref.extractall(dest_path) # extract file to dir
                zip_ref.close() # close file
    else:
        print("data folder already populated")

    print("Complete: Files have been unzipped to {0}".format(dest_path))

hydrate(zip_path, data_path)

# In the next code block, we check to see whether the Microsoft Cognitive Toolkit can use a GPU for its work. We are going to use the best available device (GPU, if available, else CPU).

# In[4]:

try:
    isUsingGPU # if this is our first time running, this will cause an exception as undefined
except NameError:
    try:
        isUsingGPU = C.device.try_set_default_device(C.device.gpu(0))
    except ValueError:
        isUsingGPU = False
        C.device.try_set_default_device(C.device.cpu())

print ("The Cognitive Toolkit is using the {} for processing.".format("GPU" if isUsingGPU else "CPU"))

# Next, we're going to implement functions to split our data into minibatches. We discussed in Module 3, Lab 2 how minibatches offer a number of advantages over single batch for training.
#
# To split our data into minibatches, we will use Python's array slice notation.
#
# By way of a quick explanation of this, the notation works as follows:
#
#     array[start:end] # items start through end-1
#     array[start:]    # items start through the rest of the array
#     array[:end]      # items from the beginning through end-1
#     array[:]         # a copy of the whole array
#
# So, we'll slice our training data (images in `data_x`, pixel-labels in `data_y`) into `minibatch_size` chunks, where `i` is the chunk number.
#
# **Add your code here to replace the commented section in the cell below** -- your code needs to take `data_x` and slice it into `sx` and `data_y` and slice it into `sy`.  As a hint, for each slice, you'll want to take elements from `i * minibatch_size` (inclusive) to `(i + 1) * minibatch_size` (exclusive), using the Python array slice notation explained above.

# In[7]:

def slice_minibatch(data_x, data_y, i, minibatch_size):
    sx = []
    sy = []
    # Use the Python array slice notation the divide up the dataset into minibatches
    #
    # *** YOUR CODE HERE ***
    # Set sx to the slice of data_x from element (i * minibatch_size) to (((i + 1) * minibatch_size)-1)
    # Set sy to the slice of data_y from element (i * minibatch_size) to (((i + 1) * minibatch_size)-1)
    # Hint: You'll find answers at the bottom of this lab.
    # *** YOUR CODE HERE ***
    sx = data_x[(i * minibatch_size):((i + 1) * minibatch_size)]
    sy = data_y[(i * minibatch_size):((i + 1) * minibatch_size)]
    return sx, sy

# Our next function will measure and record the test error per mini-batch, appending it to an errors array. We will use this to calculate the mean error across all mini-batches.
#
# **Again, you will need to fill in some code in the cell below**. Use the Python numpy `mean()` method on the `errors` array to calculate the average error across the minibatch and store the value in the variable named `result`.

# In[8]:

def measure_error(data_x_files, data_y_files, x, y, trainer, minibatch_size):
    errors = []
    for i in range(0, int(len(data_x_files) / minibatch_size)):
        data_sx_files, data_sy_files = slice_minibatch(data_x_files, data_y_files, i, minibatch_size)
        data_sx, data_sy = source.files_to_data(data_sx_files, data_sy_files)
        errors.append(trainer.test_minibatch({x: data_sx, y: data_sy}))

    result = 0
    #
    # *** YOUR CODE HERE ***
    # Use np.mean to set result to the average of the errors across each minibatch.
    # Hint: You'll find answers at the bottom of this lab.
    # *** YOUR CODE HERE ***
    result = np.mean(errors)
    return result

# ## Augmenting our ResNet model from Classification to Semantic Segmentation
#
# Now, we need to add additional Fully-Convolutional layers to our ResNet classification model to allow it to perform Semantic Segmentation.
#
# First, let's create the functions for our usual ResNet building blocks, as per Module 3 Lab 2:

# In[9]:

# Built on top of the ResNet model in CNTK repository
# https://github.com/Microsoft/CNTK/blob/master/Examples/Image/Classification/ResNet/Python/resnet_models.py

#
# ResNet building blocks
#
def conv_bn(input, filter_size, num_filters, strides=(1,1), init=C.he_normal()):
    c = Convolution(filter_size, num_filters, activation=None, init=init, pad=True, strides=strides, bias=False)(input)
    r = BatchNormalization(map_rank=1, normalization_time_constant=4096, use_cntk_engine=False)(c)
    return r

def conv_bn_relu(input, filter_size, num_filters, strides=(1,1), init=C.he_normal()):
    r = conv_bn(input, filter_size, num_filters, strides, init)
    return relu(r)

def resnet_basic(input, num_filters):
    c1 = conv_bn_relu(input, (3,3), num_filters)
    c2 = conv_bn(c1, (3,3), num_filters)
    p  = c2 + input
    return relu(p)

def resnet_basic_inc(input, num_filters, strides=(2,2)):
    c1 = conv_bn_relu(input, (3,3), num_filters, strides)
    c2 = conv_bn(c1, (3,3), num_filters)
    s  = conv_bn(input, (1,1), num_filters, strides)
    p  = c2 + s
    return relu(p)

def resnet_basic_stack(input, num_stack_layers, num_filters):
    assert (num_stack_layers >= 0)
    l = input
    for _ in range(num_stack_layers):
        l = resnet_basic(l, num_filters)
    return l

# Now, we need to add some functions to help us augment our ResNet model with fully-convolutional layers.
#
# This is where the magic happens, where we convert ResNet for object classification to ResNet for semantic segmentation.
#
# In 2015 (https://arxiv.org/pdf/1411.4038.pdf) and 2016 (https://arxiv.org/pdf/1605.06211.pdf), Long, Shelhamer, and Darrell presented a new method for object boundaries detection using Fully Convolutional Networks (FCN). They discovered that fully convolutional networks, trained end-to-end, pixels-to-pixels, exceeded the state-of-the-art in semantic segmentation.
#
# The main difference from a regular convolutional network is that the final fully-connected classifier is removed and replaced by a combination of all the convolutional features maps extracted from ResNet skipped connections. This allows:
#
#  * combining of features from different stages which vary in accuracy of semantic information;
#  * upsampling of learned low resolution semantic features maps through learnable one-by-one (1x1) convolutions and 2D upsampling.
#
#
# The following diagram shows the evolution of our model, from the basic ResNet20 classifier in Module 3, Lab 2, (on the left-hand side) to our fully convolutional network architecture for semantic segmentation in this lab (on the right-hand side):
# ![ResNet20 Fully Convolutional Semantic Segmentation Network Architecture](images/resnet20_fcn_semantic_segmentation_network_architecture.svg "ResNet20 Fully Convolutional Semantic Segmentation Network Architecture")
#
# In the right-hand side of the diagram above, the extra convolutional layers coming from the FCN model are actually deconvolutional layers - that is, they are deconvolving back to prediction masks, which are then reshaped and fused by the upsampling layers.
#
# The function `create_model()` in the following code block shows how this is implemented using the Microsoft Cognitive Toolkit. We take connections from `r1`, `r2_2` and `r3_2` with the feature maps we are interested in to finally combine them in the 'merged' layer after upsampling. A convolution with a sigmoid function classifies the output depending on the number of object classes - in our case, just for airplanes.
#
# The function `OneByOneConvAndUpSample()`  performs a 1x1 convolution over the input and and upsamples the output using basic Cognitive Toolkit primitives for operating with tensors.
#
# We also need a dice coefficient function, which is a statistic function commonly used to compare the similarity between two samples. This is what we will use to compare our predicted semantic segmentation labelling against the ground truth for our training and test images.

# In[10]:

def UpSampling2D(x):
    xr = C.reshape(x, (x.shape[0], x.shape[1], 1, x.shape[2], 1))
    xx = C.splice(xr, xr, axis=-1) # axis=-1 refers to the last axis
    xy = C.splice(xx, xx, axis=-3) # axis=-3 refers to the middle axis
    r = C.reshape(xy, (x.shape[0], x.shape[1] * 2, x.shape[2] * 2))

    return r

def UpSampling2DPower(x, k_power):
    for i in range(k_power):
        x = UpSampling2D(x)

    return x

def OneByOneConvAndUpSample(x, k_power, num_channels):
    x = Convolution((1, 1), num_channels, init=he_normal(), activation=relu, pad=True)(x)
    x = UpSampling2DPower(x, k_power)

    return x

def dice_coefficient(x, y):
    # average of per-channel dice coefficient
    # global dice coefificnet doesn't work as class with larger region dominates the metrics
    # https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient
    intersection = C.reduce_sum(x * y, axis=(1,2))

    return C.reduce_mean(2.0 * intersection / (C.reduce_sum(x, axis=(1,2)) + C.reduce_sum(y, axis=(1,2)) + 1.0))

# With these functions, we can create a new model that is a combination of ResNet plus our additional layers of convolution and upsampling.

# In[11]:

#
# Defines the fully convolutional models for image segmentation
#
def create_model(input, num_classes):
    c_map = [16, 32, 64]
    num_stack_layers = 3

    conv = conv_bn_relu(input, (3,3), c_map[0])
    r1 = resnet_basic_stack(conv, num_stack_layers, c_map[0])

    r2_1 = resnet_basic_inc(r1, c_map[1])
    r2_2 = resnet_basic_stack(r2_1, num_stack_layers-1, c_map[1])

    r3_1 = resnet_basic_inc(r2_2, c_map[2])
    r3_2 = resnet_basic_stack(r3_1, num_stack_layers-1, c_map[2])

    # now we'll add our "deconvolutional" layers (1x1 convolution with upsampling)

    up_r1 = OneByOneConvAndUpSample(r1, 0, num_classes)
    up_r2_2 = OneByOneConvAndUpSample(r2_2, 1, num_classes)
    up_r3_2 = OneByOneConvAndUpSample(r3_2, 2, num_classes)

    merged = C.splice(up_r1, up_r3_2, up_r2_2, axis=0)

    resnet_fcn_out = Convolution((1, 1), num_classes, init=he_normal(), activation=sigmoid, pad=True)(merged)

    return resnet_fcn_out

# As before in Module 3 Lab2, we can look at the Cognitive Toolkit generated view of this model, as rendered by GraphViz:
#
# ![ResNet20_Semantic_Segmentation_Model](images/ResNet20_Semantic_Segmentation_Model.svg "ResNet20 Fully Convolutional Semantic Segmentation Network Model")
#

# As this model is generated directly from the Microsoft Cognitive Toolkit, it represents the network that we have actually
# programmed the toolkit to construct.  If you are interested, you can download this model from the images/ subdirectory of this lab, and view it separately, comparing it against our reference diagram above.

# ## Training
#
# We will again create a training function to train our network using mini-batches.
#
# It is worth repeating that training without a GPU is really slow. Our code here checks whether we are going to be running on a GPU or CPU. If we're running on a CPU, we'll deliberately shrink the amount of training to just a single epoch to give you a *flavor* of what happens during training, but that model will perform pretty badly. In the case of running from a CPU and training for a single epoch, we will read in a pre-trained model for inference instead.
#

# In[12]:

def train(train_image_files, train_mask_files, val_image_files, val_mask_files):
    # Create model
    sample_img, sample_mask = source.files_to_data([train_image_files[0]], [val_image_files[0]])
    x = C.input_variable(sample_img[0].shape)
    y = C.input_variable(sample_mask[0].shape)

    z = create_model(x, source.num_classes)
    dice_coef = dice_coefficient(z, y)

    # Prepare model and trainer
    if (isUsingGPU):
        lr_mb = [0.001] * 5 + [0.0001] * 5 + [0.00001]*5 + [0.000001]*5 + [0.0000001]*5
    else:
        # training without a CPU is really slow, so we'll deliberatly shrink the amount of training
        # to just an epoch if we're on a CPU - just to give a flavor of what happens during training
        # and then read in a pre-trained model for inference instead.
        lr_mb = [0.0001] * 1 # deliberately shrink if training on CPU...
    lr = learning_rate_schedule(lr_mb, UnitType.sample)
    momentum = C.learners.momentum_as_time_constant_schedule(0.9)
    trainer = C.Trainer(z, (-dice_coef, -dice_coef), C.learners.adam(z.parameters, lr=lr, momentum=momentum))

    training_errors = []
    test_errors = []

    # Get minibatches of training data and perform model training
    minibatch_size = 8
    num_epochs = len(lr_mb)

    for e in range(0, num_epochs):
        for i in tqdm(range(0, int(len(train_image_files) / minibatch_size)), ascii=True,
                               desc="[i] Processing epoch {}/{}".format(e, num_epochs-1)):
            data_x_files, data_y_files = slice_minibatch(train_image_files, train_mask_files, i, minibatch_size)
            data_x, data_y = source.files_to_data(data_x_files, data_y_files)
            trainer.train_minibatch({x: data_x, y: data_y})
            gc.collect()

        # Measure training error
        training_error = measure_error(data_x_files, data_y_files, x, y, trainer, minibatch_size)
        training_errors.append(training_error)

        # Measure test error
        test_error = measure_error(val_image_files, val_mask_files, x, y, trainer, minibatch_size)
        test_errors.append(test_error)

        print("    epoch #{}: training_error={}, test_error={}".format(e, training_errors[-1], test_errors[-1]))

    return trainer, training_errors, test_errors

# # Initialise the Model
#
# Now, let's put it all to the test, and see our solution in action!  First, we need to configure our data source, which involves parsing to figure out how many training and validation samples we have.

# In[13]:

# Configure the data source

print('[i] Configuring data source...')
try:
    source = coco.CocoMs(os.path.join(data_path, "CocoMS"))
    training_input_image_files, training_target_mask_files = source.get_data(train_data_folder='/Training')
    validation_input_image_files, validation_target_mask_files = source.get_data(train_data_folder='/Validation')
    print('[i] # training samples:   ', len(training_input_image_files))
    print('[i] # validation samples: ', len(validation_input_image_files))
    print('[i] # classes:            ', source.num_classes)
    print('[i] Image size:           ', (224,224))
except (ImportError, AttributeError, RuntimeError) as e:
    print('[!] Unable to load data source:', str(e))

# In the next code block, we'll train our model. We'll need to either train from scratch or load a model that we made earlier...
#
# ## If training on a CPU
#
# If we are training on a CPU (like we will be in Azure Notebooks), we deliberately limit the training to a single epoch for time reasons. This gives an example of what training is like, but the resulting model will be very innaccurate.
#
# Try completing the lab using the pre-trained model, and viewing the results. This was trained on a system with a powerful GPU, and run for a number of epochs.
#
# Then restart the Jupyter Notebook and clear all outputs - run to this point again, but set `make_model` to `True` in the code block below below. Continue running on to the end, and you will quickly see how much worse the results are, and get an intuition for how much better the results get with increasing the number of epochs of training.
#
# You can expect even our very limited training in Azure Notebooks to take 50 minutes or so to complete. By comparison, a GPU could be anywhere from 10x to 100x faster.

# In[14]:

# And now do some training

make_model = False

# Load the saved model if specified
model_file = "cntk-resnet-fcn.dnn"

if (make_model):
    print("[i] Starting training...", flush=True)
    if (not isUsingGPU):
        print("    Have you tried running again with make_model set to False to compare output?", flush=True)

    tic = time.time()
    trainer, training_errors, test_errors = train(training_input_image_files, training_target_mask_files,
                                              validation_input_image_files, validation_target_mask_files)
    print('Training time: {} s.'.format(time.time() - tic))

    print("[i] Training finished...")
    model = trainer.model
    del training_input_image_files
    del training_target_mask_files

else:
    # load model
    if os.path.isfile(model_file):
        print("[i] Skipping training, using pre-trained model...")
        model = C.load_model(model_file)
    else:
        print("[!] model files {} does not exist. This will force training".format(model_file))
        tic = time.time()
        trainer, training_errors, test_errors = train(training_input_image_files, training_target_mask_files,
                                                  validation_input_image_files, validation_target_mask_files)
        print('Training time: {} s.'.format(time.time() - tic))
        print("[i] Training finished...")
        model = trainer.model
        # clean-up no longer needed variables
        del training_input_image_files
        del training_target_mask_files

# ## At last, some Semantic Segmentation predictions!
#
# With our model initialised (either trained or using a downloaded pre-trained model, we can now start making predictions on test images, and try to label them.  We will do this in two steps:
#
#  * First, we will do a forward pass of the input image through our network in order to calculate the actual prediction masks, which contain a class label for each image in the input image;
#  * Second, we will create some graphics, allowing us to quickly visualize how well we did.

# In[15]:

#
# We need to convert our validation filenames to image data for the predictor...
#

print ("[i] Converting file lists to image data...", flush=True)
tic = time.time()
validation_input_images, validation_target_masks =         source.files_to_data(validation_input_image_files, validation_target_mask_files)
print('Converting validation image data time: {} s.'.format(time.time() - tic))
print("[i] Converting file lists finished...")

# In[16]:

#
# First, let's do our semantic segmentation prediction
#

print("[i] Starting prediction...", flush=True)
tic = time.time()

pred = []
for idx in tqdm(range(0, len(validation_input_images)),ascii=True, desc='[i] Predicting...'):
    pred += list(model.eval(validation_input_images[idx]))
print('Prediction time: {} s.'.format(time.time() - tic))
print('[i] {} images predicted.'.format(len(pred)))
print("[i] Prediction finished...")

# If you have run the Python code above, you'll again see how much faster predicting with a network is compared to training the network.
#
# And now some image processing to allow us better understand the results... We are going to blend our input images and predictions together, so we can see where we labeled the pixels correctly and where we did not.
#

# In[17]:

#
# Second, let's do our image processing to create some graphics for ease of visualisation
#
print("[i] Started image processing...", flush=True)

tic = time.time()

input_images_rgb = []

for x in tqdm(validation_input_images, ascii=True, desc='[i] Converting input images (BGR2RGB)...'):
    img = np.moveaxis(x,0,2).astype(np.uint8)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    input_images_rgb.append(img)

target_masks_rgb=[]
for x in tqdm(validation_target_masks, ascii=True, desc='[i] Coloring ground truth images...'):
    target_masks_rgb.append(helper.masks_to_colorimg(x))

pred_rgb=[]
for x in tqdm(pred, ascii=True, desc='[i] Coloring prediction images...'):
    pred_rgb.append(helper.masks_to_colorimg(x))

output_images_rgb = []
for index in tqdm(range(len(input_images_rgb)), ascii=True, desc='[i] Combining input images + predictions...'):
    img = cv2.bitwise_or(input_images_rgb[index], pred_rgb[index])
    output_images_rgb.append(img)

print('Image Processing time: {} s.'.format(time.time() - tic))

print("Image processing finished...")

# If we have trained, we can view the learning curves for our training and our testing. All going well, these will have converged to a reasonable error rate, based on our dice coefficient. Ideally, we want the curves for test and training sets to be as close together as possible. Normally we'll see the curve for the training set is slightly more accurate (lower `dice_coef` value) than the test set.
#
# If you have trained locally on a GPU, they should look something like:
#
# ![sample training curve](images/sample_training_curve.png "Sample Training Curve")
#
# If you have trained on a CPU and only for one epoch, you'll only have one reading for test and training error, so you might get a funny graph like:
#
# ![cpu limited_training curve](images/cpu_limited_training_curve.png "CPU Limited Training Curve")
#
# If you have trained on CPU and see that type of curve, don't worry about it - it makes perfect sense for the limited (but costly in terms of time) amount of training you performed!  Your network has not converged *yet* and it would not be expected perform well. If you had plenty of patience, you could continue to train it for longer and see the curves converging.
#

# In[18]:

if (make_model):
    helper.plot_errors({"training": training_errors, "test": test_errors}, title="Simulation Learning Curve")

    # clean-up some variables we no longer need to reduce our memory footprint...
    # otherwise our Azure Notebook might run out of memory
    del validation_input_images
    del validation_input_image_files
    del validation_target_mask_files
    del validation_target_masks
    del trainer
    del training_errors
    del test_errors
    print("Garbage collection reclaimed {} objects".format(gc.collect()))
    plt.close()

# ## *A picture is worth a thousand words*
#
# And now, some images. We'll plot an original test image, with its associated ground truth mask/label. Alongside these, we'll show our predicted mask, and finally our predicted mask super-imposed on the original image, allowing us to visually see how well our model did. **Note: this plot function takes a while!**

# In[19]:

helper.plot_side_by_side([input_images_rgb, target_masks_rgb, pred_rgb, output_images_rgb])

# If you took the pre-trained model or trained via a GPU, we did well, considering the network learned *from scratch* how to label planes of all sorts, and from all viewpoints and angles. However, we can see that in some cases the network did make mistakes. This is mostly due to our network being small and our training set being very small -- to make this lab run in a reasonable amount of time.
#
# If you trained on a CPU, the very limited training will mean we're just barely detecting the planes and our model has a lot more *learning* to do to be useful.
#
# A larger network would be more expressive (e.g., ResNet-150), and could capture greater detail. If running on a GPU, we could relatively easily switch in a larger/deeper ResNet model and benefit from its greater capabilities.
#
# Additionally, a larger corpus of training examples would allow the network to better learn the objective, and to generalise much more accurately to new examples.
#
# There is something we can do to help tremendously with the limited training set by making use of *Transfer Learning*.  We will see in in the next lab.
#
# For now, let's take a look at some of the more interesting samples.

# In[20]:

plt.imshow(output_images_rgb[89])

# In[21]:

plt.imshow(output_images_rgb[2])

# In[22]:

plt.imshow(output_images_rgb[6])

# In[23]:

plt.imshow(output_images_rgb[7])

# In[24]:

plt.imshow(output_images_rgb[8])

# In[25]:

plt.imshow(output_images_rgb[11])

# # Conclusions
#
# In this lab, we used the Microsoft Cognitive Toolkit to build a ResNet20 model and modified it to perform semantic segmentation.
#
# We used the Coco dataset, which provides labels and masks for a variety of object classes. We focused on a subset containing airplanes.  We either used a pre-trained model or used this subset to train our model using the training data in mini-batches. Then we used this trained model to perform segmentation on some test images and plotted the results.
#
# Despite the fact that our accuracy was limited by the size of the base model (ResNet20, vs its
# larger cousin ResNet150, for example) and the size of the training set (~3K images), we demonstrated
# segmentation results far superior than could be expected of the traditional hand-crafted methods we saw in Module 2.
#
# In the next lab, we'll look at transfer learning -- a way of bringing in extra smarts from another
# model already trained on a much larger but different dataset. These extra smarts can help boost the
# performance of our semantic segmentation considerably.

# **Solution to missing slice_minibatch code**
#
#     sx = data_x[i \* minibatch_size: (i+1) \* minibatch_size]
#     sy = data_y[i \* minibatch_size: (i+1) \* minibatch_size]
#

# **Solution to missing measure_error code**
#
#     result = np.mean(errors)
#
#

courses/Microsoft/DEV290x - Computer Vision and Image Analysis (2018)/Labs/Module4_Lab1_Using_ResNet_with_FC_Layers_to_implement_Semantic_Segmentation.py


# PROBLEM: Right view of binary tree
# https://leetcode.com/problems/binary-tree-right-side-view/

from typing import List

class Node:
    def __init__(self, data=0, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right

def NBT (elements, root, i, n) -> Node:
    if n==0 : return None

    if i<n:
        temp = Node(elements[i])
        root = temp
        root.left = NBT(elements, root.left, 2*i+1, n)
        root.right = NBT(elements, root.right, 2*i+2, n)

    return root

# SOLUTION
def right_view (root: Node) -> List[int]:
    q = []
    result = []

    if root==None : return result

    q.append(root)

    while len(q)!=0:
        size = len(q)

        for i in range(size):
            t = q.pop(0)
            if i==size-1 : result.append(t.data)
            if t.left!=None : q.append(t.left)
            if t.right!=None : q.append(t.right)

    return result

if __name__ == "__main__":
    # INPUT :
    elements = [1,2,3,None,5,None,4]
    root = NBT(elements, Node(elements[0]), 0, len(elements))

    # OUTPUT :
    result = right_view(root)
    print("[", end="")
    for x in result:
        if x==None: continue
        print(x, end=" ")
    print("\b]")


import numpy as np
import pandas as pd
from .loan import Loan

class Mortgage(object):
    """
        Mortgage.
    """

    def __init__(self, years, annual_interest_rate, amount, payment_type=0):
        super(Mortgage, self).__init__()
        self.annual_interest_rate = annual_interest_rate
        self.years = years
        self.amount = amount
        self.payments_per_year = 12
        self.payment_type = payment_type
        loan = Loan(self.years*self.payments_per_year, self.annual_interest_rate/self.payments_per_year, self.amount, 0, self.payment_type)
        self.loans = [loan]

    def amortisation_schedule(self, loan):
        df = pd.DataFrame({'Principal' :[ loan.PPMT(i+1) for i in range(self.payments_per_year*self.years)],
                                     'Interest' :[loan.IPMT(i+1) for i in range(self.payments_per_year*self.years)]})

        df['Instalment'] = df.Principal + df.Interest
        df['Balance'] = self.amount + np.cumsum(df.Principal)
        return(df)

# Credit to - https://www.listendata.com/2019/10/amortisation-schedule-r-python.html


#  This is an example how to parse the sites which are forbidden to access

import requests, csv
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
}

def get_school_names(url):
    with requests.Session() as req:
        req.headers.update(headers)
        r = req.get(url).text

        soup = BeautifulSoup(r, 'lxml')

        useful_infos = soup.find_all(class_="col-xs-12 col-md-4")
        file = open('dvfu_schools.csv', 'w', encoding='utf8', newline='')
        writer = csv.writer(file)
        writer.writerow(["id", "school name"])
        id = 0
        for _ in useful_infos:
            id += 1
            title = _.find(name="h4", class_="title").getText()
            writer.writerow([id, title])

        file.close()

url = 'https://www.dvfu.ru/schools/'
get_school_names(url)


# -*- coding: utf-8 -*-
"""
Created on Thu Jan 16 10:35:04 2014

@author: rd64
"""
import sys
from text_read import Ui_Form
from PyQt4 import QtGui, QtCore

class StartUI(QtGui.QMainWindow):
    def __init__(self,parent=None):
        QtGui.QWidget.__init__(self,parent)
        self.ui=Ui_Form()
        self.ui.setupUi(self)
        QtCore.QObject.connect(self.ui.Button_read, QtCore.SIGNAL("clicked()"),self.file_dailog)

    def file_dialog(self):
        self.ui.text_window.setText("hello world , 你好吗？")

if __name__=="__main__":
    app=QtGui.QApplication(sys.argv)
    myapp=StartUI()
    myapp.show()
    sys.exit(app.exec_())


from os import getenv
import requests
from django.core.mail.backends.base import BaseEmailBackend

DEFAULT_FROM_EMAIL = getenv('DEFAULT_FROM_EMAIL')

SENDGRID_API_KEY = getenv('SENDGRID_API_KEY')

class SendGridEmailBackend(BaseEmailBackend):
    def send_email(self, to_email, email_subject, email_body):
        url = 'https://api.sendgrid.com/v3/mail/send'

        email_body = email_body.replace('\n', '<br />')

        payload = '''
                  {
                      "personalizations": [
                      {
                          "to": [
                              {
                                  "email": "to_email"
                              }
                          ],
                          "subject": "email_subject"
                      }
                    ],
                      "from": {
                          "email": "from_email"
                      },
                      "content": [
                          {
                              "type": "text/html",
                              "value": "email_body"
                          }
                      ]
                  }'''.replace('to_email', to_email)\
                      .replace('email_subject', email_subject)\
                      .replace('from_email', DEFAULT_FROM_EMAIL)\
                      .replace('email_body', email_body)

        headers = {
            'Authorization': f'Bearer {SENDGRID_API_KEY}',
            'Content-Type': 'application/json; charset=utf-8;'
        }

        response = requests.request(
            'POST', url, headers=headers, data=payload.encode('utf-8'))
        if response.status_code != 202:
            raise Exception(
                f'{payload}\n{response.status_code}\n{response.content}')

    def send_messages(self, email_messages):
        for email_message in email_messages:
            self.send_email(
                email_message.to[0], email_message.subject, email_message.body)


#!/usr/bin/env python3

import gzip
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn import metrics

def spam_detection(random_state=0, fraction=1.0):
    model = MultinomialNB()
    cv = CountVectorizer()

    with gzip.open('src/spam.txt.gz', 'rb') as f: # Opening file
        spam = f.readlines()
        length = int(len(spam) * fraction)
        spam = spam[:length]
    with gzip.open('src/ham.txt.gz', 'rb') as f: # Opening file
        ham = f.readlines()
        length = int(len(ham) * fraction)
        ham = ham[:length]

    arr = np.concatenate( (ham, spam) )
    feature = cv.fit_transform(arr).toarray()
    label = np.concatenate( (np.zeros(len(ham)), np.ones(len(spam))) )

    X_train, X_test, y_train, y_test = train_test_split( feature, label, test_size=0.25, random_state=random_state )
    model.fit(X_train, y_train)
    y_fitted = model.predict(X_test)

    n = len(y_test) # Amount of all test cases
    acc = metrics.accuracy_score(y_test, y_fitted)
    return acc, n, n - int(n * acc) # accuracy, all cases, failed cases

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

if __name__ == "__main__":
    main()


from PIL import Image
from torchvision import transforms
import os

mean = (0.485, 0.456, 0.406)
std = (0.229, 0.224, 0.225)
my_transform = transforms.Compose([transforms.Resize((224, 224)),
                                transforms.ToTensor(),
                                transforms.Normalize(mean, std)])
class ReadImage:
    def __init__(self,dir):
        super(ReadImage, self).__init__()
        self.transform = my_transform
        self.img_dir = dir
    def read_img(self,img_name):
        image_url = os.path.join(self.img_dir, img_name)
        image = Image.open(image_url).convert('RGB')
        image = self.transform(image)
        return image


def incluir_digito_control(tarjeta):
    if len(tarjeta) == 16:
        suma = 0
        for i in range(0, 15):
            if tarjeta[i] % 2 == 0:
                suma += tarjeta[i]
            else:
                if tarjeta[i] < 5:
                    suma += 2 * tarjeta[i]
                else:
                    suma += 2 * tarjeta[i] - 9

        tarjeta[15] = 10 - suma % 10
        return tarjeta
    else:
        raise ValueError("La tarjeta debe de tener 16 dígitos.")

print(incluir_digito_control([1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]))


"""
Functions to get image coordinates from WCS
"""
import logging
from pathlib import Path

import numpy as np
from astropy import units as u
from astropy.io import fits
from astropy.units import Quantity
from astropy.wcs import WCS

from mirar.data import Image

logger = logging.getLogger(__name__)

def get_corners_ra_dec_from_header(
    header: fits.Header,
) -> [
    tuple[float, float],
    tuple[float, float],
    tuple[float, float],
    tuple[float, float],
]:
    """
    Function to get corner RA/Dec of the image from the header
    Args:
        header:

    Returns:

    """
    nx, ny = header["NAXIS1"], header["NAXIS2"]
    image_crds = [(0, 0), (nx, 0), (0, ny), (nx, ny)]
    wcs_crds = []
    for image_crd in image_crds:
        ra_deg, dec_deg = WCS(header).all_pix2world([image_crd[0]], [image_crd[1]], 1)
        wcs_crds.append((ra_deg[0], dec_deg[0]))

    return wcs_crds

def get_image_center_wcs_coords(image: Image, origin: int = 0):
    """
    Get RA/Dec of an image
    Args:
        origin: 0 or 1, depending on whether you want it in DS9 coordinates
        image: Image

    Returns:

    """
    header = image.header
    wcs = WCS(header=header)
    nx, ny = header["NAXIS1"], header["NAXIS2"]
    ra_deg, dec_deg = wcs.all_pix2world([nx / 2], [ny / 2], origin)
    return ra_deg[0], dec_deg[0]

def get_xy_from_wcs(
    ra_deg: float | list[float],
    dec_deg: float | list[float],
    header: fits.Header,
    origin: int = 0,
) -> (float, float):
    """
    Get image x-y coordinates of a given ra/dec
    Args:
        ra_deg: RA in decimal degrees
        dec_deg: Dec in decimal degrees
        header: image header, requires WCS keywords
        origin: 0 or 1, depending on whether you want it in DS9 coordinates

    Returns:
        x: x coordinate
        y: y coordinate
    """
    wcs = WCS(header)
    x, y = wcs.all_world2pix(ra_deg, dec_deg, origin)
    return x, y

def write_regions_file(
    regions_path: str | Path,
    x_coords: list[float],
    y_coords: list[float],
    system: str = "image",
    region_radius: float = 5,
    text: list | None = None,
):
    """
    Function to write a regions file
    Args:
        regions_path: str, path to regions file
        x_coords: list, x-coordinates or RA
        y_coords: list, y-coordinates or Dec
        system: str, image or wcs
        region_radius: float, radius of circle
        text: list, text to accompany the regions file

    Returns:

    """
    logger.debug(f"Writing regions path to {regions_path}")
    if text is not None:
        assert len(text) == len(x_coords) == len(y_coords), (
            "Text must be same size as coordinates, found len(text) = "
            f"{len(text)}, len(x_coords) = {len(x_coords)}, len(y_coords) = "
            f"{len(y_coords)}"
        )

    with open(f"{regions_path}", "w", encoding="utf8") as regions_f:
        regions_f.write(f"{system}\n")
        for ind, x in enumerate(x_coords):
            line = f"CIRCLE({x},{y_coords[ind]},{region_radius})"
            if text is not None:
                line += f" # text={text[ind]}"
            regions_f.write(f"{line}\n")

def get_image_dims_from_header(header: fits.Header) -> (Quantity, Quantity):
    """
    Get image dimensions from the header
    Args:
        header:

    Returns:

    """
    nx, ny = header["NAXIS1"], header["NAXIS2"]
    dx, dy = header["CD1_1"], header["CD2_2"]
    img_dims = (dx * nx * u.deg, dy * ny * u.deg)
    return img_dims

def check_coords_within_image(
    ra: float | list[float], dec: float | list[float], header: fits.Header
) -> list[bool]:
    """
    Check that the coordinates are within the image
    Args:
        :param ra: RA in decimal degrees
        :param dec: Dec in decimal degrees
        :param header: Image header with WCS info.
    Returns:
        :return: True if within image, False if not
    """
    if isinstance(ra, float):
        ra = [ra]
    if isinstance(dec, float):
        dec = [dec]
    wcs = WCS(header)
    nx, ny = header["NAXIS1"], header["NAXIS2"]
    x, y = wcs.all_world2pix(ra, dec, 0)
    return np.invert((x < 0) | (x > nx) | (y < 0) | (y > ny))


import torch
import logging

import torchvision.transforms as transforms
import numpy as np

from utils import skeletonize, stroke2img

def load_class(class_name):
    components = class_name.split('.')
    mod = __import__(components[0])
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

class controller(object):

    def __init__(self) -> None:
        pass

class Learner(object):
    """ class that stores learner performance
    """
    def __init__(self) -> None:

        self.__init_parameters()

    def __init_parameters(self,):
        self.score = 0
        self.satisfied = False

    def reset(self):

        self.__init_parameters()

class Executor(object):
    """Class that carries out teaching process

    Args:
        object ([type]): [description]
    """
    def __init__(self, args) -> None:

        logging.info('Initialize Runner')
        self.cuda = args.get('CUDA', False)
        self.feedbaock = args.get('WITH_FEEDBACK', False)
        self.learner = Learner()
        self.controller = controller()

        self.__init_parameters(args)
        self.__init_network()

    def __init_parameters(self,args):

        self.gan_path = args.get('GAN_MODEL_PATH')
        self.dis_path = args.get('DIS_MODEL_PATH')

        self.gan_type = args.get('GAN_MODEL_TYPE')
        self.dis_type = args.get('DIS_MODEL_TYPE')

        self.input_channel = args.get('INPUT_CHANNEL')
        self.output_channel = args.get('OUTPUT_CHANNEL')

        self.font_type = args.get('TTF_FILE')
        self.font_size = args.get('FONT_SIZE', 128)
        assert self.font_type is not None, 'Please provide a font file'

        if args.get('PRE_PROCESS',None):
            assert args.get('PRE_PROCESS').upper() == 'DEFAULT', '{} preprocess is not supported'.format(args.get('PRE_PROCESS'))
            self.pre_process = [ transforms.ToTensor(),
                                 transforms.Normalize((0.5,), (0.5,)) ]
        else:
            self.pre_process = [ transforms.ToTensor()
                                ]

    def __init_network(self,):

        self.gan = load_class(self.gan_type)(self.input_channel, self.output_channel)
        self.dis = load_class(self.dis_type)(self.output_channel)

        if self.cuda:
            self.gan = self.gan.cuda()
            self.dis = self.dis.cuda()

        if self.gan_path is not None:
            self.gan.load_state_dict({k.replace('module.',''):v for k,v in torch.load(self.gan_path).items()})

        if self.dis_path is not None:
            self.dis.load_state_dict({k.replace('module.',''):v for k,v in torch.load(self.dis_path).items()})

    def interact(self, traj, score=None):
        """TO DO: interaction part
        """
        output_img = self.__capture_image()
        self.learner.score = self.get_score(output_img)
        return False

    def get_score(self, image):

        return self.dis(self.pre_process(image))

    def __capture_image(self, ):
        """ Capture image with post process in order for discrinmintor to score
        """
        raise NotImplementedError

    def sample_stroke(self, ):
        """ For future development, decompose one character into several strokes
        """
        pass

    def __reset_learner(self,):
        """ Reset learner model
        """
        self.learner.reset()

    def __quit(self):
        """ Quit all the processes
        """
        pass

    def pipeline(self,):
        """ Full pipeline
        Obtain target stroke -> generate target stroke's trajectory -> Interact with learner -> Get learner output
        """

        while True:

            stroke = input('Please provide a stroke you want to learn: ')

            if stroke is ' ':
                break

            while not self.learner.satisfied:

                stroke_img = stroke2img(self.font_type, stroke,self.font_size)
                stroke_img = np.array(stroke_img)
                traj, traj_img = skeletonize(~stroke_img)

                self.interact(traj)

        logging.info('Quittiing')

        # cv2.imshow('',stroke_img)
        # cv2.waitKey(0)


import random
import sys
import time

wins = 0
losses = 0
ties = 0

while True:  # Main game loop.
    while True:
        print(f"{wins} Wins, {losses} Losses, {ties} Ties")
        player_move = input("Enter your move: (R)ock (P)aper (S)cissors or (Q)uit").upper()
        if player_move == "Q":
            print("Thanks for playing!")
            sys.exit()
        if player_move == "R" or player_move == "P" or player_move == "S":
            break
        else:
            print("Type one of R, P, S, or Q.")

    if player_move == "R":
        print("Rock versus...")
        player_move = "ROCK"
    elif player_move == "P":
        print("Paper versus...")
        player_move = "PAPER"
    elif player_move == "S":
        print("Scissors versus...")
        player_move = "SCISSORS"

    time.sleep(0.5)
    print("1...")
    time.sleep(0.25)
    print("2...")
    time.sleep(0.25)
    print("3...")
    time.sleep(0.25)

    random_number = random.randint(1, 3)
    if random_number == 1:
        computer_move = "ROCK"
    elif random_number == 2:
        computer_move = "PAPER"
    elif random_number == 3:
        computer_move = "SCISSORS"
    print(computer_move)
    time.sleep(0.5)

    if player_move == computer_move:
        print("It's a tie!")
        ties = ties + 1
    elif player_move == "ROCK" and computer_move == "SCISSORS":
        print("You win!")
        wins = wins + 1
    elif player_move == "PAPER" and computer_move == "ROCK":
        print("You win!")
        wins = wins + 1
    elif player_move == "SCISSORS" and computer_move == "PAPER":
        print("You win!")
        wins = wins + 1
    elif player_move == "ROCK" and computer_move == "PAPER":
        print("You lose!")
        losses = losses + 1
    elif player_move == "PAPER" and computer_move == "SCISSORS":
        print("You lose!")
        losses = losses + 1
    elif player_move == "SCISSORS" and computer_move == "ROCK":
        print("You lose!")
        losses = losses + 1


from flask import Flask, render_template
from model.words import Words

# Set up custom delimiters to avoid Vue.js conflict.
class CustomFlask(Flask):
  jinja_options = Flask.jinja_options.copy()
  jinja_options.update(dict(
    block_start_string='(%',
    block_end_string='%)',
    variable_start_string='((',
    variable_end_string='))',
    comment_start_string='(#',
    comment_end_string='#)',
  ))

app = CustomFlask(__name__)

word_gen = Words("model/word_lists/onegin.csv")

@app.route('/')
def play_hat():
    return render_template('index.html', words=word_gen.get_random(500), words_num=word_gen.size())


from django.test import TestCase
from django.urls import reverse
import json

from enterprise.models import *
from enterprise.serializers import *

class BuyerSellerRelationshipModelViewTest(TestCase):
    def setUp(self):
        '''
        Populating test db with Enterprise, Buyer, Entity and Seller with ID 1
        Entering a buyer_seller_relationship_list with buyer id 1 and seller id 1
        '''
        Enterprise.objects.create(enterprise_name="ENT 1")
        self.enterprise1 = Enterprise.objects.get(enterprise_id=1)
        entity_data1 = {
            "enterprise_id": self.enterprise1,
            "entity_type": "IT",
            "entity_name": "Apple",
            "entity_primary_address": "xyz",
            "entity_primary_email": "apple@gmail.com"
        }
        Entity.objects.create(**entity_data1)
        self.entity1 = Entity.objects.get(entity_id=1)
        buyer_data = {
            "buyer_id" : self.entity1
        }
        Buyer.objects.create(**buyer_data)
        self.buyer = Buyer.objects.get(buyer_id=1)
        Enterprise.objects.create(enterprise_name="ENT 2")
        self.enterprise2 = Enterprise.objects.get(enterprise_id=2)
        entity_data2 = {
            "enterprise_id": self.enterprise2,
            "entity_type": "IT1",
            "entity_name": "Apple1",
            "entity_primary_address": "xyz1",
            "entity_primary_email": "apple1@gmail.com"
        }
        Entity.objects.create(**entity_data2)
        self.entity2 = Entity.objects.get(entity_id=2)
        seller_data = {
            "seller_id" : self.entity2
        }
        Seller.objects.create(**seller_data)
        self.seller = Seller.objects.get(seller_id=2)
        data = {
            "buyer_enterprise_id" : self.enterprise1,
            "buyer_entity_id" : self.buyer,
            "seller_entity_id" : self.seller,
            "relationship_type" : "xcvz"
        }
        BuyerSellerRelationship.objects.create(**data)

    def test_get_valid_buyer_seller_relationship(self):
        '''
        Getting buyer_seller_relationship with buyer_id 1
        '''
        response = self.client.get(reverse("enterprise:get_buyer_seller_relationship_list", args=[1]))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data[0]["buyer_enterprise_id"], 1)
        self.assertEqual(response.data[0]["seller_entity_id"], 2)

    def test_get_invalid_buyer_seller_relationship(self):
        '''
        Getting buyer_seller_relationship with buyer_id 2 which does not exist
        '''
        response = self.client.get(reverse("enterprise:get_buyer_seller_relationship_list", args=[2]))
        self.assertEqual(response.status_code, 404)

    def test_post_valid_buyer_seller_relationship(self):
        # Entering new entity and address in entity address with id 2
        Enterprise.objects.create(enterprise_name="ENT 3")
        self.enterprise3 = Enterprise.objects.get(enterprise_id=3)
        entity_data3 = {
            "enterprise_id": self.enterprise3,
            "entity_type": "IT3",
            "entity_name": "Apple3",
            "entity_primary_address": "xyz3",
            "entity_primary_email": "apple3@gmail.com"
        }
        Entity.objects.create(**entity_data3)
        self.entity3 = Entity.objects.get(entity_id=3)
        buyer_data = {
            "buyer_id" : self.entity3
        }
        Buyer.objects.create(**buyer_data)
        self.buyer = Buyer.objects.get(buyer_id=3)
        Enterprise.objects.create(enterprise_name="ENT 4")
        self.enterprise4 = Enterprise.objects.get(enterprise_id=4)
        entity_data4 = {
            "enterprise_id": self.enterprise4,
            "entity_type": "IT4",
            "entity_name": "Apple4",
            "entity_primary_address": "xyz4",
            "entity_primary_email": "apple4@gmail.com"
        }
        Entity.objects.create(**entity_data4)
        self.entity4 = Entity.objects.get(entity_id=4)
        seller_data = {
            "seller_id" : self.entity4
        }
        Seller.objects.create(**seller_data)
        self.seller = Seller.objects.get(seller_id=4)
        data = {
            "relationship_type" : "xcvz"
        }
        # Posting a entity_address with address id 2 and entity id 2
        response = self.client.post(reverse("enterprise:buyer_seller_relationship_list", args=[3,4]),data)
        self.assertEqual(response.status_code, 201)
        self.assertEqual(response.data["buyer_enterprise_id"], 3)
        self.assertEqual(response.data["relationship_type"], "xcvz")

    def test_post_invalid_buyer_seller_relationship(self):
        '''
        Posting a buyer_seller_relationship with seller id 1 and buyer id 1, which already exists
        violating unique_together constraint
        '''
        data = {
            "relationship_type" : "xcvz"
        }
        response = self.client.post(reverse("enterprise:buyer_seller_relationship_list", args=[1,2]),data)
        self.assertEqual(response.status_code, 400)

        '''
        Posting buyer and sellers with nonexisting ids
        '''
        #invalid seller id
        response = self.client.post(reverse("enterprise:buyer_seller_relationship_list", args=[1,4]), data)
        self.assertEqual(response.status_code, 404)
        #invalid buyer id
        response = self.client.post(reverse("enterprise:buyer_seller_relationship_list", args=[3,2]), data)
        self.assertEqual(response.status_code, 404)

    def test_delete_valid_buyer_seller_relationship(self):
        # Deleting buyer_seller_relationship with id 1
        response = self.client.delete(reverse("enterprise:buyer_seller_relationship_list", args=[1,2]))
        self.assertEqual(response.status_code, 200)

    def test_delete_invalid_buyer_seller_relationship(self):
        '''
        Posting buyer and sellers with nonexisting ids
        '''
        #invalid seller id
        response = self.client.delete(reverse("enterprise:buyer_seller_relationship_list", args=[1,4]))
        self.assertEqual(response.status_code, 404)
        #invalid buyer id
        response = self.client.delete(reverse("enterprise:buyer_seller_relationship_list", args=[3,2]))
        self.assertEqual(response.status_code, 404)

        # Deleting buyer_seller_relationship with buyer id 1 seller id 2
        response = self.client.delete(reverse("enterprise:buyer_seller_relationship_list", args=[1,2]))
        self.assertEqual(response.status_code, 200)
        # Again deleting buyer_seller_relationship with buyer id 1 seller id 2
        response = self.client.delete(reverse("enterprise:buyer_seller_relationship_list", args=[1,2]))
        self.assertEqual(response.status_code, 400)


from csv2_common import check_keys, show_table, yaml_full_load

import json
import os
import shutil
import yaml

def delete(gvar):
    """
    Delete settings.
    """

    mandatory = ['-s']
    required = []
    optional = ['-H', '-h', '-v', '-Y']

    if gvar['retrieve_options']:
        return mandatory + required + optional

    # Check for missing arguments or help required.
    check_keys(gvar, mandatory, required, optional, requires_server=False)

    if os.path.isdir('%s/.csv2/%s' % (gvar['home_dir'], gvar['pid_defaults']['server'])):
        # Confirm settings delete.
        if not gvar['user_settings']['yes']:
            print('Are you sure you want to delete the settings for server "%s"? (yes|..)' % gvar['pid_defaults']['server'])
            _reply = input()
            if _reply != 'yes':
                print('%s settings delete "%" cancelled.' % gvar['pid_defaults']['server'] % gvar['command_name'])
                exit(0)

        shutil.rmtree('%s/.csv2/%s' % (gvar['home_dir'], gvar['pid_defaults']['server']))
    else:
        print('Error: Settings for server "%s" do not exist.' % gvar['pid_defaults']['server'])
        exit(1)

def list(gvar):
    """
    List settings.
    """

    mandatory = []
    required = []
    optional = ['-CSV', '-CSEP', '-H', '-h', '-NV', '-ok', '-r', '-s', '-v', '-V', '-VC', '-w']

    if gvar['retrieve_options']:
        return mandatory + required + optional

    # Check for missing arguments or help required.
    check_keys(gvar, mandatory, required, optional, requires_server=False)

    # Retrive all possible option names ordered by 'server' and then alphabetically.
    if os.path.isfile('%s/.csv2/default_server' % gvar['home_dir']):
        fd = open('%s/.csv2/default_server' % gvar['home_dir'])
        default_server = fd.read()
        fd.close
        report_title = 'Defaults (default server = %s)' % default_server
    else:
        report_title = 'Defaults'

    # Retrive all possible option names ordered by 'server' and then alphabetically.
    _keys = ['server,k']
    for _ix in range(len(gvar['command_keys'])):
        key = gvar['command_keys'][_ix][1][2:]
        if key not in _keys and '%s,k' % key not in _keys:
            _keys.append(key)
    _keys = [_keys[0]] + sorted(_keys[1:])

    # Build a queryset of the settings.
    _queryset = []
    for server in os.listdir('%s/.csv2' % gvar['home_dir']):
        if server[0] == '.':
            continue

        server_path = '%s/.csv2//%s' % (gvar['home_dir'], server)
        if os.path.isdir(server_path):
            if 'server' not in gvar['command_args'] or server == gvar['command_args']['server']:
                _fd = open('%s/settings.yaml' % server_path)
                _settings = yaml_full_load(_fd.read())
                _fd.close()

                for key in sorted(_keys):
                    if key not in _settings:
                        if key == 'server':
                            _settings[key] = server

                _queryset.append({'fields': _settings})

    # Display results.
    show_table(gvar, _queryset, _keys, allow_null=False, title=report_title)

def set(gvar):
    """
    Modify settings.
    """

    mandatory = ['-s']
    required = []
    optional = ['*']
    not_optional = ['-br']

    if gvar['retrieve_options']:
        return mandatory + required + optional

    # Check for missing arguments or help required.
    check_keys(gvar, mandatory, required, optional, not_optional=not_optional, requires_server=False)

    # If this is the user's first server, make it the default.
    if len(os.listdir('%s/.csv2' % gvar['home_dir'])) < 1:
        gvar['set_default_server'] = True

    # Make the server directory, if necessary.
    if not os.path.exists('%s/.csv2/%s' % (gvar['home_dir'], gvar['pid_defaults']['server'])):
        os.makedirs('%s/.csv2/%s' % (gvar['home_dir'], gvar['pid_defaults']['server']), mode=0o700)

    # Write the default server file.
    if gvar['set_default_server']:
        _fd = open('%s/.csv2/default_server' % gvar['home_dir'], 'w')
        _fd.write(gvar['pid_defaults']['server'])
        _fd.close()
        os.chmod('%s/.csv2/default_server' % gvar['home_dir'], 0o600)

    # Write the settings file.
    _fd = open('%s/.csv2/%s/settings.yaml' % (gvar['home_dir'], gvar['pid_defaults']['server']), 'w')
    _fd.write(yaml.dump(gvar['user_settings']))
    _fd.close()
    os.chmod('%s/.csv2/%s/settings.yaml' % (gvar['home_dir'], gvar['pid_defaults']['server']), 0o600)