"""
Plugins to track bases and mining locations, based on https://github.com/dsjoerg/ggpyjobs/blob/master/sc2parse/plugins.py
Aaron Bauer
Carleton College
August 2020
"""

import os

from sc2.position import Point2

os.environ["OMP_NUM_THREADS"] = "1"  # keep sklearn from spawning a bunch of threads

import traceback
from sklearn.cluster import AffinityPropagation
import numpy as np
from math import dist
import time
import warnings

warnings.simplefilter('ignore', UserWarning)
import sc2reader
from sc2reader.log_utils import loggable
import logging
from sc2reader.engine.plugins import SelectionTracker, APMTracker
from selection_plugin import ActiveSelection
from typing import NamedTuple, Tuple
from enum import Enum

base_names_tier_one = set(["Hatchery", "Nexus", "CommandCenter"])
base_names = set(["Hatchery", "Lair", "Hive", "Nexus", "CommandCenter", "CommandCenterFlying", "OrbitalCommand",
                  "OrbitalCommandFlying", "PlanetaryFortress"])
flying_buildings = ["Barracks", "Factory", "Starport", "CommandCenter"]
land_cc_abils = ['LandOrbitalCommand', 'LandCommandCenter']
cc_names = ['OrbitalCommand', 'CommandCenter']
BaseType = Enum("BaseType", "MAIN EXPANSION PROXY NONE")

class BaseCluster(NamedTuple):
    label: int
    center: Tuple[int, int]
    base_type: BaseType
    player_id: int

def is_mining_loc(resource_clusters, location):
    """
    Uses affinity propagation (https://scikit-learn.org/stable/modules/clustering.html#affinity-propagation)
    to cluster resource locations into possible base locations, returns True if location within 8.5 of a center
    """
    # 8.5 threshold set empirically based on 5-replay sample
    # TODO verify with bigger sample
    if len(resource_clusters) == 0:
        return False
    return min([dist(location, center) for center in resource_clusters]) < 8.5

def select_center(cs):
    if len(cs) == 1:
        return cs[0]
    for c in cs:
        assert len([dist(c, x) for x in cs if x != c]) > 0, cs
    return min(cs, key=lambda c: np.mean([dist(c, x) for x in cs if x != c]))

def get_current_name(unit, frame):
    name = unit.name
    for f, t in unit.type_history.items():
        if frame >= f:
            name = t.name
    return name

def get_last_known_loc(unitid, frame, lookup):
    for f in range(frame - 1, 0, -1):
        if f in lookup and unitid in lookup[f]:
            return f, lookup[f][unitid]
    raise ValueError(f"no last known location for {unitid}")

# TODO differentiate between mining bases and other bases (usually turrets/bunkers/nydus worm/proxy barrack or pylon)
@loggable
class BaseTracker(object):
    """
    Tracks a player's current bases
    """

    name = "BaseTracker"

    def handleInitGame(self, event, replay):
        self.resource_locs = None
        try:
            replay.load_map()
            self.map_dim = (replay.map.map_info.width + replay.map.map_info.height) / 2
        except:
            self.map_dim = 150  # go with a reasonable if map can't be loaded
        self.under_construction = {}
        self.building_locs = {}
        self.lookup = {}
        self.keyframes = []
        self.mains = []

    def handleUnitBornEvent(self, event, replay):
        if event.unit.is_building:
            # this must be a starting base
            assert event.unit.name in base_names, "born event for non-main building"
            self.building_locs[event.unit.id] = (event.location, event.unit.owner.team_id, 0, True)
            self.lookup[event.frame] = self.building_locs.copy()
            self.keyframes.append(event.frame)
            self.mains.append(event.location)

    def handleUnitInitEvent(self, event, replay):
        # resources should have been created by now, can initialize resoursce locations
        if self.resource_locs is None:
            self.resource_locs = [o.location for o in replay.objects.values() if
                                  o.name and ("Mineral" in o.name or "Vespene" in o.name) and hasattr(o, "location")]
            try:
                self.resource_clusters = AffinityPropagation(preference=-1000, random_state=None).fit(
                    self.resource_locs).cluster_centers_
            except:
                print(self.resource_locs)
                traceback.print_exc()
        if event.unit.is_building:
            assert event.unit.id not in self.under_construction, "init event for already under construction unit"
            self.under_construction[event.unit.id] = (event.location, event.unit.owner.team_id, event.unit.finished_at,
                                                      is_mining_loc(self.resource_clusters,
                                                                    event.location) and event.unit.name in base_names)

    def handleUnitDoneEvent(self, event, replay):
        if event.unit.is_building:
            assert event.unit.id in self.under_construction and event.unit.id not in self.building_locs, "done event dictionary problem"
            self.building_locs[event.unit.id] = self.under_construction[event.unit.id]
            del self.under_construction[event.unit.id]
            self.lookup[event.frame] = self.building_locs.copy()
            self.keyframes.append(event.frame)

    def handleUnitDiedEvent(self, event, replay):
        if event.unit.is_building and "Flying" not in get_current_name(event.unit, event.frame):
            if event.unit.id not in self.building_locs and event.unit.id not in self.under_construction:
                self.logger.info(
                    f"dying {event.unit}, built {event.unit.finished_at} missing from dicts as of {event.frame}, probably due to missed landing: {replay.filename}")
            if event.unit.id in self.under_construction:
                del self.under_construction[event.unit.id]
            elif event.unit.id in self.building_locs:
                del self.building_locs[event.unit.id]
            self.lookup[event.frame] = self.building_locs.copy()
            self.keyframes.append(event.frame)

    def handleTargetPointCommandEvent(self, event, replay):
        if event.ability_name.startswith("Land"):
            selects = event.active_selection
            flying_selects = [obj for obj in selects if sorted(obj.type_history.items())[0][1].name in flying_buildings]
            target_type = event.ability_name[4:]
            targets = [obj for obj in flying_selects if get_current_name(obj, event.frame) == f"{target_type}Flying"]
            if len(targets) == 0:
                self.logger.error(
                    f"Landing {target_type} but none selected. event={event}, selects={selects}, names={[get_current_name(s, event.frame) for s in selects]}")
            else:
                # assume the order is given to the first selected building
                # TODO is this true? probably not, selection is sorted by id
                unit = targets[0]
                if unit.id in self.building_locs:
                    self.logger.info(f"\nflying building {unit} should not be in dict: {replay.filename}, {event}")
                    # go back through events and find the type change where the building lifted off
                    for e in [e for e in replay.events[::-1] if e.frame < event.frame]:
                        if isinstance(e,
                                      sc2reader.events.UnitTypeChangeEvent) and e.unit == unit and e.unit_type_name == f"{target_type}Flying":
                            # remove flying building from intervening frames
                            for frame in range(event.frame - 1, e.frame - 1, -1):
                                if frame in self.lookup and unit.id in self.lookup[frame]:
                                    del self.lookup[frame][unit.id]
                            self.logger.info(f"CORRECTED via type change event {e}\n")
                            break
                # drop the z-coordinate from the event location
                self.building_locs[unit.id] = (event.location[:2], unit.owner.team_id, unit.finished_at,
                                               is_mining_loc(self.resource_locs,
                                                             event.location[:2]) and unit.name in base_names)
                self.lookup[event.frame] = self.building_locs.copy()
                self.keyframes.append(event.frame)

    def handleBasicCommandEvent(self, event, replay):
        if event.ability_name.startswith("Lift"):
            selects = event.active_selection
            flying_selects = [obj for obj in selects if sorted(obj.type_history.items())[0][1].name in flying_buildings]
            target_type = event.ability_name[4:]
            targets = [obj for obj in flying_selects if get_current_name(obj, event.frame - 1) == target_type]
            if len(targets) == 0:
                self.logger.error(
                    f"Lifting {target_type}, but none selected. event={event}, selects={selects}, names={[get_current_name(s, event.frame - 1) for s in selects]}")
            else:
                # assume all selected building of the target type lift off
                # TODO is this true?
                for unit in targets:
                    if unit.id not in self.building_locs:
                        self.logger.info(
                            f"\nlanded building {unit} should be in dict at {event.frame}: {replay.filename}, {event}")
                        for e in replay.events[::-1]:
                            if unit.finished_at is not None and unit.finished_at < e.frame < event.frame and isinstance(
                                    e,
                                    sc2reader.events.UnitTypeChangeEvent) and e.unit == unit and e.unit_type_name == target_type:
                                # most recent landing
                                self.logger.info(
                                    f"found recent landing {e}, last known loc = {get_last_known_loc(unit.id, e.frame, self.lookup)}, built at {self.lookup[unit.finished_at][unit.id]}")
                                frame, loc = get_last_known_loc(unit.id, e.frame, self.lookup)
                                for f in range(frame + 1, event.frame):
                                    if f in self.lookup:
                                        self.lookup[f][unit.id] = loc
                                self.logger.info(f"CORRECTED using position as of {frame}\n")
                                break
                    else:
                        del self.building_locs[unit.id]

                    self.lookup[event.frame] = self.building_locs.copy()
                    self.keyframes.append(event.frame)

    #     def handleUnitTypeChangeEvent(self, event, replay):
    #         # current state is flying or new state is flying
    #         if ("Flying" in get_current_name(event.unit, event.frame - 1)) != ("Flying" in event.unit_type_name):
    #             unit = event.unit
    #             # lifting
    #             if "Flying" in event.unit_type_name:
    #                 print("lifting", unit)
    #                 assert unit.id in self.building_locs, f"landed building {unit} should be in dict: {replay.filename}, {event}"
    #                 del self.building_locs[unit.id]
    #                 self.lookup[event.frame] = self.building_locs.copy()
    #             else:
    #                 print("landing", unit)
    #                 assert unit.id not in self.building_locs, f"flying building {unit} should not be in dict: {replay.filename}, {event}"
    #                 # drop the z-coordinate from the event location
    #                 self.building_locs[unit.id] = (event.location[:2], unit.owner.team_id, unit.finished_at,
    #                                                is_mining_loc(self.resource_locs, event.location[:2]) and unit.name in base_names)
    #                 self.lookup[event.frame] = self.building_locs.copy()

    def handleEndGame(self, event, replay):
        try:
            pdict = {}
            for player in replay.players:
                player.bases = {}
                player.base_cluster = {}
                pdict[player.team_id] = player

            old_frames = {p.pid: 0 for p in replay.players}
            for frame in self.keyframes:
                for player in replay.players:
                    player.bases[frame] = {}
                    player.base_cluster[frame] = {}
                    if frame > 0:
                        for f in range(old_frames[player.pid] + 1, frame):
                            player.bases[f] = player.bases[old_frames[player.pid]]
                            player.base_cluster[f] = player.base_cluster[old_frames[player.pid]]
                        old_frames[player.pid] = frame

                for f, ls in self.lookup.items():
                    if f <= frame:
                        locs, teamids, finishes, prefs = zip(*list(ls.values()))
                        unit_ids = list(ls.keys())
                    else:
                        break
                locs = np.array(locs)
                prefs = np.array(prefs)
                finishes = np.array(finishes)
                self.logger.debug(f"(frame {frame}): locs = {locs.tolist()} prefs = {prefs.tolist()}")

                af = AffinityPropagation(preference=[0 if p else -5000 for p in prefs], random_state=None).fit(locs)
                count = 1
                while -1 in af.labels_ and count < 100:  # indicates clustering did not converge, so we retry until it does (giving up after 100 tries)
                    af = AffinityPropagation(preference=[0 if p else -5000 for p in prefs], random_state=None,
                                             max_iter=5000).fit(locs)
                    count += 1
                if count > 1:
                    self.logger.warning(
                        f"(frame {frame}): Tried {count} times to achieve convergence --- {'FAILED' if count == 100 else 'SUCCEEDED'}")
                cluster_centers_indices = af.cluster_centers_indices_
                centers = af.cluster_centers_.tolist()
                labels = af.labels_
                self.logger.debug(f"(frame {frame}): labels = {labels}")
                n_clusters = len(cluster_centers_indices)

                # mining location? must be separate cluster
                new_centers = []
                for k in range(n_clusters):
                    # mining bases in this cluster
                    mining_locs = [(loc, finish) for loc, finish, pref in
                                   zip(locs[labels == k], finishes[labels == k], prefs[labels == k]) if pref]
                    if len(mining_locs) > 1:
                        # split up clusters with more than one mining base
                        self.logger.debug(f"(frame {frame}): mining_locs = {mining_locs}")
                        original = min(filter(lambda x: x is not None, mining_locs), key=lambda x: x[1])
                        to_split = [x for x in mining_locs if x[0].tolist() != original[0].tolist()]
                        self.logger.debug(f"(frame {frame}): original = {original}, to_split = {to_split}")
                        for i, (loc, finish) in enumerate(to_split):
                            new_label = n_clusters + i
                            self.logger.debug(
                                f"(frame {frame}): changing {labels[(locs == loc).all(axis=1).nonzero()]} to {new_label}")
                            labels[(locs == loc).all(axis=1).nonzero()] = new_label
                            members = [(loc, finish) for loc, finish, pref in
                                       zip(locs[labels == k], finishes[labels == k], prefs[labels == k]) if not pref]
                            for ml, mf in members:
                                if dist(ml, loc) == min(dist(ml, x[0]) for x in
                                                        [original] + to_split[:i] + to_split[i + 1:]) and mf >= finish:
                                    self.logger.debug(
                                        f"(frame {frame}): changing {labels[(locs == ml).all(axis=1).nonzero()]} to {new_label}")
                                    labels[(locs == ml).all(axis=1).nonzero()] = new_label
                        new_centers.append(loc)

                for c in new_centers:
                    cluster_centers_indices = np.append(cluster_centers_indices, (locs == c).all(axis=1).nonzero())
                    n_clusters += 1

                # maximum distance
                new_centers = []
                for loc in locs:
                    if all(dist(loc, c) / self.map_dim > 0.1 for c in
                           centers):  # too far away from any cluster center, should be split
                        if any(dist(loc, select_center(cs)) / self.map_dim <= 0.1 for cs in
                               new_centers):  # close to an already split building, merge
                            _, i = min((dist(loc, select_center(cs)), i) for i, cs in enumerate(new_centers))
                            labels[(locs == loc).all(axis=1).nonzero()] = n_clusters + i
                            new_centers[i].append(tuple(loc))
                        else:  # start a new cluster
                            labels[(locs == loc).all(axis=1).nonzero()] = n_clusters + len(new_centers)
                            new_centers.append([tuple(loc)])

                for cs in new_centers:
                    central = select_center(cs)
                    cluster_centers_indices = np.append(cluster_centers_indices,
                                                        (locs == central).all(axis=1).nonzero())
                    n_clusters += 1
                self.logger.debug(
                    f"(frame {frame}): set(labels) = {set(labels)} center indices = {cluster_centers_indices}")
                base_types = {}
                for loc, label in zip(locs, labels):
                    if any(np.array_equal(loc, m) for m in self.mains):
                        base_types[label] = BaseType.MAIN
                    elif label not in base_types and (is_mining_loc(self.resource_clusters, loc)):
                        base_types[label] = BaseType.EXPANSION
                for unit_id, loc, team_id, label in zip(unit_ids, locs, teamids, labels):
                    pdict[team_id].bases[frame][unit_id] = loc
                    pdict[team_id].base_cluster[frame][unit_id] = BaseCluster(label, Point2(
                        locs[cluster_centers_indices[label]]), base_types.get(label, BaseType.PROXY), team_id)

        except:
            print(locs)
            print(replay.filename)
            traceback.print_exc()

        for player in replay.players:
            if frame < replay.frames:
                for f in range(frame + 1, replay.frames + 1):
                    player.bases[f] = player.bases[frame]
                    player.base_cluster[f] = player.base_cluster[frame]
            assert len(
                player.bases) == replay.frames + 1, f"{len(player.bases)} base entries, {replay.frames} frames {sorted(player.bases.keys())}"

            # TODO save cluster information for detecting scouting of new bases, etc.
            # for k in range(n_clusters):
            #     class_members = labels == k
            #     cluster_center = locs[cluster_centers_indices[k]]
            #     player = replay.player[teamids[cluster_centers_indices[k]]]

if __name__ == "__main__":
    # pro replays over 1000 seconds long
    files = ['replays/spawningtool_52661.SC2Replay',
             'replays/spawningtool_55197.SC2Replay',
             'replays/spawningtool_54185.SC2Replay',
             'replays/spawningtool_56994.SC2Replay',
             'replays/spawningtool_55200.SC2Replay',
             'replays/spawningtool_55942.SC2Replay',
             'replays/spawningtool_52636.SC2Replay',
             'replays/spawningtool_47751.SC2Replay',
             'replays/spawningtool_47709.SC2Replay',
             'replays/spawningtool_52635.SC2Replay',
             'replays/spawningtool_59082.SC2Replay',
             'replays/spawningtool_58796.SC2Replay',
             'replays/spawningtool_52662.SC2Replay',
             'replays/spawningtool_40787.SC2Replay']
    sc2reader.engine.register_plugin(APMTracker())
    sc2reader.engine.register_plugin(SelectionTracker())
    sc2reader.engine.register_plugin(ActiveSelection())
    bt = BaseTracker()
    bt.logger.setLevel(logging.WARN)
    bt.logger.addHandler(logging.StreamHandler())
    sc2reader.engine.register_plugin(bt)

    start = time.perf_counter()
    replays = [sc2reader.load_replay(f) for f in files]
    print(f"loading {len(files)} replays each over 1000 seconds took {time.perf_counter() - start} seconds")

    # fig, ax = plt.subplots()
    # fig.set_tight_layout(True)
    # def update(r, frame):
    #     ax.clear()
    #     colors = " br"
    #     for k in range(len({c.label for c in n_clusters):
    #         class_members = labels == k
    #         cluster_center = locs[cluster_centers_indices[k]]
    #         col = colors[teamids[cluster_centers_indices[k]]]
    #         ax.plot(locs[class_members, 0], locs[class_members, 1], col + '.')
    #         ax.plot(cluster_center[0], cluster_center[1], 'o', markerfacecolor=col,
    #                  markeredgecolor='k', markersize=14)
    #         for loc in locs[class_members]:
    #             ax.plot([cluster_center[0], loc[0]], [cluster_center[1], loc[1]], col)
    #     ax.text(1, 1, f"{frame // 22.4}s          {r.filename}")
    #     return ax


import logging
import os

from aminator.plugins.provisioner.base import BaseProvisionerPlugin
from aminator.util.linux import command, keyval_parse

__all__ = ('YumProvisionerPlugin',)
log = logging.getLogger(__name__)

class YumProvisionerPlugin(BaseProvisionerPlugin):
    """
    YumProvisionerPlugin takes the majority of its behavior from BaseProvisionerPlugin
    See BaseProvisionerPlugin for details
    """
    _name = 'yum'

    def _refresh_repo_metadata(self):
        config = self._config.plugins[self.full_name]
        return yum_clean_metadata(config.get('clean_repos', []))

    def _provision_package(self):
        result = self._refresh_repo_metadata()
        if not result.success:
            log.critical('Repo metadata refresh failed: {0.std_err}'.format(result.result))
            return False
        context = self._config.context
        if context.package.get('local_install', False):
            return yum_localinstall(context.package.arg)
        else:
            return yum_install(context.package.arg)

    def _store_package_metadata(self):
        context = self._config.context
        config = self._config.plugins[self.full_name]
        metadata = rpm_package_metadata(context.package.arg, config.get('pkg_query_format', ''),
                                        context.package.get('local_install', False))
        for x in config.pkg_attributes:
            metadata.setdefault(x, None)
        context.package.attributes = metadata

@command()
def yum_install(package):
    return 'yum --nogpgcheck -y install {0}'.format(package)

@command()
def yum_localinstall(path):
    if not os.path.isfile(path):
        log.critical('Package {0} not found'.format(path))
        return None
    return 'yum --nogpgcheck -y localinstall {0}'.format(path)

@command()
def yum_clean_metadata(repos=None):
    clean='yum clean metadata'
    if repos:
        return '{0} --disablerepo=\* --enablerepo={1}'.format(clean, ','.join(repos))
    return clean

@command()
def rpm_query(package, queryformat, local=False):
    cmd = 'rpm -q --qf'.split()
    cmd.append(queryformat)
    if local:
        cmd.append('-p')
    cmd.append(package)
    return cmd

@keyval_parse()
def rpm_package_metadata(package, queryformat, local=False):
    return rpm_query(package, queryformat, local)


import cv2
from cvzone.HandTrackingModule import HandDetector
import math
import random as rd
import numpy as np
import time

capture = cv2.VideoCapture(0)
capture.set(3, 980)
capture.set(4, 750)

# Stone Paper Scissor
stone = cv2.imread("stone.png")
paper = cv2.imread("paper.png")
scissor = cv2.imread("scissors.png")
objectType =[1,2,3,1,2,1,2,3,1,3,1,2,3,1,2,3]
spsx = 110
spsy = 480

detector = HandDetector(maxHands=1, detectionCon=0.8)

def subX(point1, point2):
    return point1[0] - point2[0]

def subY(point1, point2):
    return point1[1] - point2[1]

def detectStonePaperScissor(img, target):
    a1, a2, a3, a4 = target[8::4]
    b1, b2, b3, b4 = target[5::4]

    hx1, hy1 = target[3][:2]
    hx2, hy2 = target[17][:2]
    d1 = math.hypot(subX(a1, b1), subY(a1, b1))
    d2 = math.hypot(subX(a2, b2), subY(a2, b2))
    d3 = math.hypot(subX(a3, b3), subY(a3, b3))
    d4 = math.hypot(subX(a4, b4), subY(a4, b4))
    h = math.hypot(hx1 - hx2, hy1 - hy2)

    mean = ((d1 + d2 + d3 + d4) / 4) / h

    if 0.20 < mean < 0.623:
        drawStone(img, target)
        return 1
    elif 0.63 < mean < 0.94:
        drawPaper(img, target)
        return 2
    elif mean > 1:
        drawScissor(img, target)
        return 3
    else:
        print(mean)
        return -1

def drawScissor(img, cursor):
    points = [8, 7, 6, 5, 9, 10, 11, 12]
    scissorColor = (170, 224, 130)
    # displayImage(img, scissor, spsx, spsy)
    for p in range(len(points) - 1):
        cv2.line(img, (cursor[points[p]][0], cursor[points[p]][1]),
                 (cursor[points[p + 1]][0], cursor[points[p + 1]][1]), scissorColor, 5)

def drawPaper(img, cursor):
    points = [0, 1, 2, 3, 4, 3, 2, 5, 6, 7, 8, 7, 6, 5, 9, 10, 11, 12, 11, 10, 9, 13, 14, 15, 16, 15, 14, 13, 17, 18,
              19, 20, 19, 18, 17, 0]
    paperColor = (233, 193, 133)
    # displayImage(img, paper, spsx, spsy)
    for p in range(len(points) - 1):
        cv2.line(img, (cursor[points[p]][0], cursor[points[p]][1]),
                 (cursor[points[p + 1]][0], cursor[points[p + 1]][1]),
                 paperColor, 5)

def drawStone(img, cursor):
    points = [4, 3, 2, 5, 6, 7, 8, 7, 6, 5, 9, 10, 11, 12, 11, 10, 9, 13, 14, 15, 16, 15, 14, 13, 17, 18, 19, 20, 19,
              18, 17]
    stoneColor = (0, 128, 255)
    # displayImage(img, stone, spsx, spsy)
    for p in range(len(points) - 1):
        cv2.line(img, (cursor[points[p]][0], cursor[points[p]][1]),
                 (cursor[points[p + 1]][0], cursor[points[p + 1]][1]),
                 stoneColor, 5)

def createRectangleText(text, cx, cy, sizex, sizey, fontSize=1, bold=2):
    cv2.rectangle(img, (cx - sizex, cy - sizey), (cx + sizex-50, cy + sizey), (255, 255, 255), cv2.FILLED)
    cv2.putText(img, f'{text}', (cx -10- sizex // 2, cy + sizey // 3), cv2.FONT_HERSHEY_DUPLEX,
                fontSize, (0, 0, 255), bold)

def displayImage(img, dispalyImg, x, y):
    desired_size = 64
    top,bottom,left,right = [10,10,10,10]

    dispalyImg = cv2.copyMakeBorder(dispalyImg, top, bottom, left, right, cv2.BORDER_CONSTANT,
                       value=(255,255,255))
    img[x:x + desired_size+20, y:y + desired_size+20, :] = dispalyImg[:desired_size+20,:desired_size+20,:]

def resultDisplay(result):
    x = 470
    y = 450
    cv2.rectangle(img, (450, 400), (630, 490), (255, 255, 255), cv2.FILLED)
    if result == "You Won":
        cv2.putText(img, f'{result}', (x,y), cv2.FONT_HERSHEY_DUPLEX,
            1, (0, 255, 0), 2)
    elif result == "You Loss":
        cv2.putText(img, f'{result}',(x,y), cv2.FONT_HERSHEY_DUPLEX,
            1, (0, 0, 255), 2)
    else:
        cv2.putText(img, f'{result}',(x,y), cv2.FONT_HERSHEY_DUPLEX,
            1, (255, 0, 0), 2)

def targetBox(img,colorCode):
    decisionBox = np.ones((200,200,3))*colorCode
    img[70:270,:200] = decisionBox

def startTimer(cx,cy,stop=False):
    cv2.circle(img, (cx, cy),30, (255, 255, 255), cv2.FILLED)
    if stop:
        cv2.putText(img, f'0', (cx-10, cy+10), cv2.FONT_HERSHEY_DUPLEX,
                1, (0, 0, 0), 1)
    else:
        cv2.putText(img, f'{int(totalTime-(time.time()-timeStart))}', (cx-10, cy+10), cv2.FONT_HERSHEY_DUPLEX,
                1, (0, 0, 0), 1)

def computerSPS(img):
    val = rd.choice(objectType)
    if val == 1:
        displayImage(img, stone, spsx, spsy)
        return 1
    elif val == 2:
        displayImage(img, paper, spsx, spsy)
        return 2
    else:
        displayImage(img, scissor, spsx, spsy)
        return 3

def lastPart():
    cv2.rectangle(img, (450, 50), (600, 250), (255, 255, 255), cv2.FILLED)
    if val == 1:
        displayImage(img, stone, spsx, spsy)
    elif val == 2:
        displayImage(img, paper, spsx, spsy)
    elif val == 3:
        displayImage(img, scissor, spsx, spsy)
    startTimer(530, 70, stop=True)
    resultDisplay(whoWin(playVal, val))
    if playVal == 1:
        drawStone(img, playerCood)
    elif playVal == 2:
        drawPaper(img, playerCood)
    else:
        drawScissor(img, playerCood)

def whoWin(userInput,systemInput):
    print(userInput,systemInput)
    if userInput == systemInput:
        print("draw")
        return "Draw"
    if userInput == 1 and systemInput == 2: # stone and paper
        print("System Win")
        return "You Loss"
    else:
        print("Player Win")
        return "You Won"

    if userInput == 2 and systemInput == 3: # paper and scissor
        print("System Win")
        return "You Loss"
    else:
        print("Player Loss")
        return "You Won"

    if userInput == 3 and systemInput == 1: # scissor and stone
        print("System Win")
        return "You Loss"
    else:
        print("Player Loss")
        return "You Won"

timeStart = time.time()
totalTime = 4
colorCode = 255

stop = 0
val = "Not selected"
playVal = -1
playerCood = []
while True:
    success, img = capture.read()
    img = cv2.flip(img, 1)
    hand = detector.findHands(img, draw=False)
    targetBox(img,colorCode)
    if stop == 1:
        lastPart()
    if hand:
        lmList = hand[0]['lmList']
        bx, by, bw, bh = hand[0]["bbox"]
        obj = detectStonePaperScissor(img, lmList)
        objText = {"1": "Stone", "2": "Paper", "3": "Scissor", "-1": "Hand not found"}
        createRectangleText(objText[str(playVal)], 100, 50, 150, 30)
        cv2.rectangle(img, (450, 50), (600, 250), (255, 255, 255), cv2.FILLED)
        if bx<200 and bx+bw < 200 and 70<by<270 and 70<by+bh<270:
            if int(totalTime-(time.time()-timeStart)) < 0:
                lastPart()
                stop = 1

            else:
                val = computerSPS(img)
                playVal = obj
                playerCood = lmList
                colorCode = 100
                startTimer(530, 70)
        else:
            colorCode = 255
            displayImage(img,stone,spsx,spsy)
            startTimer(530, 70)
            timeStart = time.time()

    else:
        createRectangleText("Hand not found", 100, 50, 150, 30, fontSize=0.7, bold=1)

    cv2.imshow("Stone Paper Scissor Detector", img)

    if cv2.waitKey(30) & 0xFF == ord('q'):
        break


from django.conf.urls import url
from . import views

app_name = 'auth'

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^loginVoter/$', views.loginVoter, name='loginVoter'),
    url(r'^validateVoter/$', views.validateVoter, name='validateVoter'),
    url(r'^logout/$', views.logout, name='logout'),
    url(r'^addAdmin/$', views.addAdmin, name='addAdmin'),
    url(r'^loginAdmin/$', views.loginAdmin, name='loginAdmin'),
    url(r'^validateAdmin/$', views.validateAdmin, name='validateAdmin'),
    #url(r'^profile/$', views.profileView, name='profileView'),

]


from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.urls import reverse

from .models import Article, TimePeriod, Photo, Album
from .forms import ArticleForm, TimePeriodForm, PhotoForm, AlbumForm
import datetime

def tape(request):
    articles = Article.objects.all()
    return render(request, 'tape.html', context={'articles': articles})

def view_article(request, pk):
    article = Article.objects.filter(id=pk)
    return render(request, 'view_article.html', context={'article': article})

@login_required
def write_article(request):
    form = ArticleForm
    if request.method == 'POST':
        article = Article()
        article.title = request.POST.get('title')
        article.prev = request.POST.get('prev')
        article.text = request.POST.get('text')
        if request.FILES.get('photo') is not None:
            article.photo = request.FILES.get('photo')
        article.create_preview()
        article.save()
        return redirect('/')
    return render(request, 'add_article.html', context={'form': form})

@login_required
def del_article(request, pk):
    article = Article.objects.filter(id=pk)
    article.delete()
    return redirect('/')

'''
@login_required
def edit_article(request, pk):
    ed_article = Article.objects.filter(id=pk)
    form = ArticleForm(instance=ed_article[0])
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        article = form.save(commit=False)
        art_id = ed_article[0].id
        article.id = art_id
        article.photo = ed_article[0].photo
        ed_article[0].delete
        article.save()
        return redirect('tape')
    return render(request, 'add_article.html', context={'form': form})
'''

@login_required
def view_periods(request):
    form = TimePeriodForm
    if request.method == 'POST':
        form = TimePeriodForm(request.POST)
        if form.is_valid():
            period = form.save(commit=False)
            period.save()
            return redirect('periods_view')
    periods = TimePeriod.objects.all()
    return render(request, 'date_manager.html', context={'periods': periods, 'form': form})

@login_required
def del_period(request, pk):
    period = TimePeriod.objects.filter(id=pk)
    period.delete()
    return redirect('periods_view')

def view_timetable(request):
    periods = TimePeriod.objects.all()
    current_date = datetime.date.today()
    periods_to_show = []
    for period in periods:
        if period.start_date <= current_date <= period.end_date:
            periods_to_show.append(period)
    if 6 <= current_date.month <= 8:
        week = 'Лето'
    else:
        first_sep = datetime.date(current_date.year, 9, 1)
        days = int(str(current_date - first_sep).split()[0])
        week = days // 7
        if week % 2 == 0:
            week = 'четная'
        else:
            week = 'нечётная'
    return render(request, "timetable.html", context={'periods': periods_to_show, 'week': week})

def add_album(request):
    albums = Album.objects.all()
    form = AlbumForm
    if request.method == 'POST':
        form = AlbumForm(request.POST)
        if form.is_valid():
            album = form.save(commit=False)
            album.save()
            return redirect('albums')
    return render(request, "albums.html", context={'albums': albums, 'form': form})

def view_album(request, pk):
    album = Album.objects.filter(id=pk)
    photos = Photo.objects.filter(album__id=album[0].id)
    form = PhotoForm
    if request.method == 'POST':
        form = PhotoForm(request.POST, request.FILES)
        if form.is_valid():
            photo = form.save(commit=False)
            photo.album = album[0]
            photo.save()
    return render(request, "album.html", context={'form': form, 'photos': photos})

@login_required
def del_album(request, pk):
    album = Album.objects.filter(id=pk)
    album.delete()
    return redirect('/albums')


import send, report, config
import pandas as pd

data = report.getjson("open")
df = pd.json_normalize(data)

category = df.loc[pd.isnull(df['request.category.name'])]
assigned = category.loc[category['request.technician.name'] != None]
technician = assigned['request.technician.name'].unique()
technician = technician[~pd.isnull(technician)]
assigned = assigned[['request.id','request.subject','request.requester.name','request.technician.name']]

for assign in assigned['request.id']:
    assigned['request.id'].loc[assigned['request.id'] == assign] = f"""{assign}"""

for tech in technician:
    to_email = assigned.loc[assigned['request.technician.name'] == tech]
    tech_email = tech.replace(" ", "")+f"{config.at}"
    body = to_email.to_html(index=False, escape=False)
    send.email("⚠ Unassigned Ticket Categories", body, tech_email, tech)


import pandas as pd
import os
from sqlalchemy import create_engine, MetaData, Table, select
import warnings
from sqlalchemy import exc as sa_exc

class SqlConnection:
    type_db = 'sqlite'
    directory_db = '\\'.join(os.getcwd().split('\\')[0:-1])
    filename_db = 'db.sqlite3'
    path_db = type_db + ':///' + directory_db + '\\' + filename_db

    def __init__(self, db_table):
        self.engine = create_engine(self.path_db)
        self.connection = self.engine.connect()
        self.metadata = MetaData()
        self.query = None
        self.results = None
        self.rowcount = 0
        self.table = Table(db_table, self.metadata, autoload=True, autoload_with=self.engine)

    def select_query(self, sqlalchemy_query, output='df'):
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", category=sa_exc.SAWarning)
            self.query = sqlalchemy_query
            self.results = self.connection.execute(self.query).fetchall()
            # get rowcount and put to self.rowcount
            if output == 'df':
                return pd.DataFrame.from_records(self.results, columns=self.query.columns.keys())
            if output == 'records':
                return self.results

    def insert_query(self, sqlalchemy_query, insert_values):
        values_list = [x for x in insert_values.T.to_dict().values()]
        self.results = self.connection.execute(sqlalchemy_query, values_list)
        # get rowcount and put to self.rowcount

    def update_query(self, sqlalchemy_query):
        self.results = self.connection.execute(sqlalchemy_query)
        # get rowcount and put to self.rowcount

if __name__ == '__main__':
    s = SqlConnection('stockindex_app_stock')
    q = select([s.table])

    test_records_update = [(1, 'BUI', 'Buhler Industries',   3.69,  0, 0, 9.22500000e+07, 'TSX', 'TSX:BUI', '',
                            3.69,  3.69,  3.69, 3.94, 3.53, 25000000),
                         (2, 'BYD-UN', 'The Boyd Group', 111.1,  7.68, 0, 2.33681536e+09, 'TSX', 'TSX:BYD-UN', '',
                          118.78, 115.97, 121.21, 133, 102.59,  19673475),
                         (3, 'GWO', 'Great West Life Company',  27.87,  2.13, 0, 2.96515036e+10, 'TSX', 'TSX:GWO', '',
                          30,  30.55,  30.59, 33.1,  28.37, 988383452),
                         (4, 'IGM', 'IGM Financial',  22.37, 12.47, 0, 8.39154568e+09, 'TSX', 'TSX:IGM', '',
                          34.84,  34.26,  34.84, 39.95, 31.54, 240859520),
                         (5, 'PBL', 'Pollard Banknote',  19.53,  2.84, 0, 5.73245969e+08, 'TSX', 'TSX:PBL', '',
                          22.37,  22.1,  22.37, 27.75,  19.91,  25625658),
                         (6, 'NFI', 'New Flyer Industries',  34.31,  3.05, 0, 2.32951738e+09, 'TSX', 'TSX:NFI', '',
                          37.36,  38.21,  38.42, 52.48,  32.95,  62353249),
                         (7, 'NWC', 'Northwest Company',  28,  1.3, 0, 1.42685108e+09, 'TSX', 'TSX:NWC', '',
                          29.3 ,  29.29,  29.44, 30.6 ,  27.03,  48697989),
                         (8, 'EIF', 'Exchange Income Corp',  30.23,  0.76, 0, 9.72296840e+08, 'TSX', 'TSX:EIF', '',
                          30.99,  31.3,  31.48, 35.34,  26.87,  31374535),
                         (9, 'AFN', 'Ag Growth International',  50,  3.63, 0, 9.84849521e+08, 'TSX', 'TSX:AFN', '',
                          53.63,  54.44,  54.44, 64.72,  47.84,  18363780)]


import numpy as np
import matplotlib.pyplot as plt
class NoamOpt:
    "Optim wrapper that implements rate."

    def __init__(self, model_size, factor, warmup, initial_lr, optimizer):
        self.optimizer = optimizer
        self._step = 0
        self.warmup = warmup
        self.factor = factor
        self.model_size = model_size
        self._rate = 0
        self.initial_lr = initial_lr

    def step(self):
        "Update parameters and rate"
        self._step += 1
        rate = self.rate()
        for p in self.optimizer.param_groups:
            p['lr'] = rate
        self._rate = rate
        self.optimizer.step()

    def rate(self, step=None):
        "Implement `lrate` above"
        if step is None:
            step = self._step
        return self.initial_lr + self.factor * \
               (self.model_size ** (-0.5) *
                min(step ** (-0.5), step * self.warmup ** (-1.5)))

if __name__ == '__main__':
    opts = [NoamOpt(512, 1, 4000, 0.01, None),
            NoamOpt(512, 1, 8000, 0.01, None),
            NoamOpt(256, 1, 4000, 0.01, None)]
    plt.plot(np.arange(1, 20000), [[opt.rate(i) for opt in opts] for i in range(1, 20000)])
    plt.legend(["512:4000", "512:8000", "256:4000"])
    plt.show()


from configs.hparams import create_hparams
from concurrent.futures import ProcessPoolExecutor
from functools import partial
import librosa
from utils import read_wav_np
import os
hparams = create_hparams()
from scipy.io.wavfile import write
from utils import read_wav_np
import torch
def check_paths(lists, num_workers=16, tqdm=lambda x: x):
    files2d = [[] for i in range(len(lists))]
    futures = [[] for i in range(len(lists))]
    names = ['train', 'valid', 'test']
    for i in range(len(lists)):
        with open(lists[i],  'r', encoding='utf-8-sig') as f:
            files2d[i] = f.readlines()
    executor = ProcessPoolExecutor(max_workers=num_workers)

    for i in range(len(files2d)):
        for line in files2d[i]:
            path = line.split('|')[0]
            futures[i].append(executor.submit(partial(_process_utterance, path)))
        write_metadata([future.result() for future in tqdm(futures[i])], 'filelists', 'problematic_merge_korean_pron_{}.txt'.format(names[i]))

'''
1. Read each file
2. Down sample to 22050Hz
3. Create meta file with the format 'path|phonemes|speaker'
["g",  "n",  "d",  "l",  "m",  "b",  "s",  "-", "j",   "q",
                "k", "t", "p", "h", "x", "w", "f", "c", "z", "A",
                "o", "O", "U", "u", "E", "a", "e", "1", "2", "3",
                "4", "5", "6", "7", "8", "9", "[", "]", "<", ">",
                "G", "N", "D", "L", "M", "B", "0", "K", ";;",";", "sp", "*",
                "$", "?", "!","#"]
'''
# I have not decided whether to separate dierectories for train/eval/test
def _process_utterance(in_path):
    try:
        sr, wav = read_wav_np(in_path)
    except:
        return in_path+'\n'
    return ''

def write_metadata(metadata, out_dir, out_file):
    with open(os.path.join(out_dir, out_file), 'w', encoding='utf-8') as f:
        for m in metadata:
            f.write((m))


from .settings import *
from .nat import *
from .ip_range import *

# No more than 4 interfaces per address family in peer addr.
PEER_ADDR_MAX_INTERFACES = 4

# No more than 2 signal pipes to send signals to nodes.
SIGNAL_PIPE_NO = 2

"""
        can be up to N interfaces
[ IP4 nics
    [
        interface_offset,
        ext ip,
        nic ip,
        port,
        nat_type,
        delta_type,
        delta_val
    ]
    ,... more interfaces for AF family
],[IP6 nics ...],node_id
"""
def make_peer_addr(node_id, interface_list, signal_offsets, port=NODE_PORT, ip=None, nat=None, if_index=None):
    ensure_resolved(interface_list)
    signal_offsets_as_str = [to_b(str((x))) for x in signal_offsets]
    bufs = [
        # Make signal pipe buf.
        b','.join(signal_offsets_as_str)
    ]

    for af in [IP4, IP6]:
        af_bufs = []
        for i, interface in enumerate(interface_list):
            # AF type is not supported.
            if not len(interface.rp[af].routes):
                continue

            r = interface.route(af)
            if r is None:
                continue

            if nat:
                nat_type = nat["type"]
                delta_type = nat["delta"]["type"]
                delta_value = nat["delta"]["value"]
            else:
                nat_type = interface.nat["type"]
                delta_type = interface.nat["delta"]["type"]
                delta_value = interface.nat["delta"]["value"]

            af_bufs.append(b"[%d,%b,%b,%d,%d,%d,%d]" % (
                if_index or i,
                ip or to_b(r.ext()),
                ip or to_b(r.nic()),
                port,
                nat_type,
                delta_type,
                delta_value
            ))

        if len(af_bufs):
            af_bufs = b'|'.join(af_bufs)
        else:
            af_bufs = b''

        # The as_buf may be empty if AF has no routes.
        # Expected and okay.
        bufs.append(af_bufs or b"0")

    bufs.append(node_id)
    return b'-'.join(bufs)

def parse_peer_addr(addr):
    af_parts = addr.split(b'-')
    if len(af_parts) != 4:
        log("p2p addr invalid parts")
        return None

    # Parse signal server offsets.
    p = af_parts.pop(0).split(b",")
    signal = [int(n) for n in p if in_range(int(n), [0, len(MQTT_SERVERS) - 1])]
    if len(signal) > SIGNAL_PIPE_NO:
        log("p2p addr invalid signal no for p2p addr")
        return None

    # Parsed dict.
    schema = [is_no, is_b, is_b, is_no,  is_no, is_no, is_no]
    translate = [to_n, to_b, to_b, to_n, to_n, to_n, to_n]
    out = {
        IP4: [],
        IP6: [],
        "node_id": af_parts[2],
        "signal": signal
    }

    for af_index, af_part in enumerate(af_parts[:2]):
        interface_infos = af_part.split(b'|')
        for info in interface_infos:
            # Strip outer braces.
            if len(info) < 2:
                continue
            inner = info[1:-1]

            # Split into components.
            parts = inner.split(b',')
            if len(parts) != 7:
                log("p2p addr: invalid parts no.")
                continue

            # Test type of field.
            # Convert to its end value if it passes.
            try:
                for j, part in enumerate(parts):
                    if not schema[j](part):
                        raise Exception("Invalid type.")
                    else:
                        parts[j] = translate[j](part)
            except Exception:
                continue

            # Is it a valid IP?
            try:
                IPRange(to_s(parts[1]))
            except Exception:
                log("p2p addr: ip invalid.")
                continue

            # Is it a valid IP?
            try:
                IPRange(to_s(parts[2]))
            except Exception:
                log("p2p addr: ip invalid.")
                continue

            # Is listen port right?
            if not in_range(parts[3], [1, MAX_PORT]):
                log("p2p addr: listen port invalid")
                continue

            # Check NAT type is valid.
            if not in_range(parts[4], [OPEN_INTERNET, BLOCKED_NAT]):
                log("p2p addr: nat type invalid")
                continue

            # Check delta type is valid.
            if not in_range(parts[5], [NA_DELTA, RANDOM_DELTA]):
                log("p2p addr: delta type invalid")
                continue

            # Check delta value is valid.
            if not in_range(parts[6], [0, MAX_PORT]):
                log("p2p addr: Delta value invalid")
                continue

            # Build dictionary of results.
            delta = delta_info(parts[5], parts[6])
            nat = nat_info(parts[4], delta)
            as_dict = {
                "if_index": parts[0],
                "ext": IPRange(to_s(parts[1])),
                "nic": IPRange(to_s(parts[2])),
                "nat": nat,
                "port": parts[3]
            }

            # Save results.
            af = VALID_AFS[af_index]
            out[af].append(as_dict)

    return out

def peer_addr_extract_exts(p2p_addr):
    exts = []
    for af in VALID_AFS:
        for info in p2p_addr[af]:
            exts.append(info["ext"])
            exts.append(info["nic"])

    return exts

def is_p2p_addr_us(addr_bytes, if_list):
    # Parse address bytes to address.
    addr = parse_peer_addr(addr_bytes)

    # Check all address families.
    for af in VALID_AFS:
        # Check all interface details for AF.
        for info in addr[af]:
            # Compare the external address.
            ipr = info["ext"]

            # Set the right interface to check.
            if_index = info["if_index"]
            if if_index + 1 > len(if_list):
                continue

            # Check all routes in the interface.
            interface = if_list[if_index]
            for route in interface.rp[af].routes:
                # Only interested in the external address.
                for ext_ipr in route.ext_ips:
                    # IPs are equal or in same block.
                    if ipr in ext_ipr:
                        return True

    # Nothing found that matches.
    return False

if __name__ == "__main__": # pragma: no cover
    from .interface import Interface
    async def test_p2p_addr():
        x = await Interface("enp3s0").start()
        if_list = [x]
        node_id = b"noasdfosdfo"
        b_addr = make_peer_addr(node_id, if_list)
        print(b_addr)

        addr = parse_peer_addr(b_addr)
        print(addr)

    async_test(test_p2p_addr)


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from django.test import LiveServerTestCase
from main.models import Category
from .base import FunctionalTest

from main.views import NORMAL_DATE_FORMAT, WITHOUT_WEEKDAY_DATE_FORMAT
from datetime import date , timedelta
from unittest import skip
import time

class AlreadyVisitorTest(FunctionalTest):

    def test_add_history_and_can_write_history_of_past(self):
        """ 과거 내역도 저장하기"""

        #edith가 해당 웹사이트 방문
        self.browser.get(self.live_server_url)

        #메뉴에서 거래내역추가를 눌러 거래내역 추가로 이동한다.
        # edith는 오늘의 식사/군것질 거래내역,  키위바나나 , 2000원을 입력한다.
        self.add_new_history( cate="군것질", name = "딸기바나나", price = 2000, day = date.today())
        #이어서 저번주의 세끼, 맘스터치 , 5600원을 입력한다.
        self.add_new_history( cate= "세끼", name="맘스터치", price = 5600, day =date.today() + timedelta(days= -7) )
        # 다시 메인 화면으로 돌아가지고, 현재 사용금액등이 변경되어 있다.   (사용금액 2000원,    사용가능금액 298000)
        # (계속 입력은 아직 추가 x)

        rows_text = self.find_rows_from_table_id("present_box")
        self.assertIn('사용한 돈 2000원', rows_text)
        self.assertIn('남은 돈 268000원', rows_text )

        rows_text =  self.find_rows_from_table_id('detail_box')
        self.assertIn('군것질 30000원 28000원 {}원'.format(30000// (7-self.weekday) - 2000), rows_text)
        self.assertIn('세끼 100000원 100000원 {}원'.format(100000// (7-self.weekday)), rows_text)
        self.assertIn('기타 100000원 100000원 {}원'.format(100000// (7-self.weekday)), rows_text)

    def test_can_go_to_main_by_button(self):
        #에디스는 사이트를 방문해 거래내역추가로 이동한다

        self.browser.get(self.live_server_url)

        self.go_to_page("add_history")

        #에디스는 각 내역을 입력했지만, 취소하고 메인으로 돌아가고 싶다
        self.browser.find_element_by_id("history_category_inputBox").send_keys('군것질')
        self.browser.find_element_by_id("history_name_inputBox").send_keys('딸기바나나')
        self.browser.find_element_by_id("history_price_inputBox").send_keys('1500')

        self.browser.find_element_by_id("go_to_main").click()

        # 메인에는 아무것도 바뀌어있지 않다.
        time.sleep(1)
        rows_text = self.find_rows_from_table_id("present_box")
        self.assertIn('사용한 돈 0원', rows_text)
        self.assertIn('남은 돈 270000원', rows_text )

        rows_text =  self.find_rows_from_table_id('detail_box')
        self.assertIn('군것질 30000원 30000원 {}원'.format(30000// (7-self.weekday)), rows_text)
        self.assertIn('세끼 100000원 100000원 {}원'.format(100000// (7-self.weekday)), rows_text)
        self.assertIn('기타 100000원 100000원 {}원'.format(100000// (7-self.weekday)), rows_text)

class HalbuTest(FunctionalTest):
    def test_add_history_and_halbu_works(self):
        #Edith는 사이트에 접속한다.
        self.browser.get(self.live_server_url)

        #에디스는 하리보, 10000원, 나만의 할부 5주를 입력한다.
        self.add_new_history(cate="군것질",name= "하리보", price = 10000, halbu = 5)
        #5주이므로 2000원어치만 표시되어 있다.
        rows_text = self.find_rows_from_table_id("present_box")
        self.assertIn('사용한 돈 2000원', rows_text)
        self.assertIn('남은 돈 268000원', rows_text )

        rows_text =  self.find_rows_from_table_id('detail_box')
        self.assertIn('군것질 30000원 28000원 {}원'.format(30000 // (7-self.weekday) - 2000), rows_text)
        self.assertIn('세끼 100000원 100000원 {}원'.format(100000// (7-self.weekday)), rows_text)
        self.assertIn('기타 100000원 100000원 {}원'.format(100000// (7-self.weekday)), rows_text)

        #에디스는 저번주에 구입한 맥심 모카골드 12000원 짜리를 12주 할부 처리한다.
        self.add_new_history(cate ="기타", name = "맥심 모카골드", price = 12000, halbu = 12, day = date.today() + timedelta(days= -7))

        #메인메뉴에는 1000원짜리로 기록되어 있다.
        rows_text = self.find_rows_from_table_id("present_box")
        self.assertIn('사용한 돈 3000원', rows_text)
        self.assertIn('남은 돈 267000원', rows_text )

        rows_text =  self.find_rows_from_table_id('detail_box')
        self.assertIn('군것질 30000원 28000원 {}원'.format(30000// (7-self.weekday) - 2000), rows_text)
        self.assertIn('세끼 100000원 100000원 {}원'.format(100000// (7-self.weekday)), rows_text)
        self.assertIn('기타 100000원 99000원 {}원'.format(99000// (7-self.weekday)) , rows_text)


from typing import Any, Dict

import attr
import numpy as np

from nlisim.coordinates import Voxel
from nlisim.diffusion import apply_diffusion
from nlisim.grid import RectangularGrid
from nlisim.module import ModuleModel, ModuleState
from nlisim.modules.molecules import MoleculesState
from nlisim.random import rg
from nlisim.state import State
from nlisim.util import activation_function, turnover_rate

def molecule_grid_factory(self: 'TGFBState') -> np.ndarray:
    return np.zeros(shape=self.global_state.grid.shape, dtype=float)

@attr.s(kw_only=True, repr=False)
class TGFBState(ModuleState):
    grid: np.ndarray = attr.ib(
        default=attr.Factory(molecule_grid_factory, takes_self=True)
    )  # units: atto-mols
    half_life: float  # units: min
    half_life_multiplier: float  # units: proportion
    macrophage_secretion_rate: float  # units: atto-mol * cell^-1 * h^-1
    macrophage_secretion_rate_unit_t: float  # units: atto-mol * cell^-1 * step^-1
    k_d: float  # aM

class TGFB(ModuleModel):
    """TGFB"""

    name = 'tgfb'
    StateClass = TGFBState

    def initialize(self, state: State) -> State:
        tgfb: TGFBState = state.tgfb

        # config file values
        tgfb.half_life = self.config.getfloat('half_life')  # units: min
        tgfb.macrophage_secretion_rate = self.config.getfloat(
            'macrophage_secretion_rate'
        )  # units: atto-mol * cell^-1 * h^-1
        tgfb.k_d = self.config.getfloat('k_d')  # units: aM

        # computed values
        tgfb.half_life_multiplier = 0.5 ** (
            self.time_step / tgfb.half_life
        )  # units in exponent: (min/step) / min -> 1/step
        # time unit conversions
        tgfb.macrophage_secretion_rate_unit_t = tgfb.macrophage_secretion_rate * (
            self.time_step / 60
        )  # units: atto-mol/(cell*h) * (min/step) / (min/hour)

        return state

    def advance(self, state: State, previous_time: float) -> State:
        """Advance the state by a single time step."""
        from nlisim.modules.macrophage import MacrophageCellData, MacrophageState
        from nlisim.modules.phagocyte import PhagocyteStatus

        tgfb: TGFBState = state.tgfb
        molecules: MoleculesState = state.molecules
        macrophage: MacrophageState = state.macrophage
        voxel_volume: float = state.voxel_volume
        grid: RectangularGrid = state.grid

        for macrophage_cell_index in macrophage.cells.alive():
            macrophage_cell: MacrophageCellData = macrophage.cells[macrophage_cell_index]
            macrophage_cell_voxel: Voxel = grid.get_voxel(macrophage_cell['point'])

            if macrophage_cell['status'] == PhagocyteStatus.INACTIVE:
                tgfb.grid[tuple(macrophage_cell_voxel)] += tgfb.macrophage_secretion_rate_unit_t
                if (
                    activation_function(
                        x=tgfb.grid[tuple(macrophage_cell_voxel)],
                        k_d=tgfb.k_d,
                        h=self.time_step / 60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=1,
                    )
                    > rg.uniform()
                ):
                    macrophage_cell['status_iteration'] = 0

            elif macrophage_cell['status'] not in {
                PhagocyteStatus.APOPTOTIC,
                PhagocyteStatus.NECROTIC,
                PhagocyteStatus.DEAD,
            }:
                if (
                    activation_function(
                        x=tgfb.grid[tuple(macrophage_cell_voxel)],
                        k_d=tgfb.k_d,
                        h=self.time_step / 60,  # units: (min/step) / (min/hour)
                        volume=voxel_volume,
                        b=1,
                    )
                    > rg.uniform()
                ):
                    macrophage_cell['status'] = PhagocyteStatus.INACTIVATING
                    macrophage_cell[
                        'status_iteration'
                    ] = 0  # Previously, was no reset of the status iteration

        # Degrade TGFB
        tgfb.grid *= tgfb.half_life_multiplier
        tgfb.grid *= turnover_rate(
            x=np.array(1.0, dtype=np.float64),
            x_system=0.0,
            base_turnover_rate=molecules.turnover_rate,
            rel_cyt_bind_unit_t=molecules.rel_cyt_bind_unit_t,
        )

        # Diffusion of TGFB
        tgfb.grid[:] = apply_diffusion(
            variable=tgfb.grid,
            laplacian=molecules.laplacian,
            diffusivity=molecules.diffusion_constant,
            dt=self.time_step,
        )

        return state

    def summary_stats(self, state: State) -> Dict[str, Any]:
        tgfb: TGFBState = state.tgfb
        voxel_volume = state.voxel_volume

        return {
            'concentration (nM)': float(np.mean(tgfb.grid) / voxel_volume / 1e9),
        }

    def visualization_data(self, state: State):
        tgfb: TGFBState = state.tgfb
        return 'molecule', tgfb.grid


from __future__ import annotations

from pathlib import Path

import pytest

from poetry.core.masonry.utils.package_include import PackageInclude

fixtures_dir = Path(__file__).parent / "fixtures"
with_includes = fixtures_dir / "with_includes"

def test_package_include_with_multiple_dirs() -> None:
    pkg_include = PackageInclude(base=fixtures_dir, include="with_includes")
    assert pkg_include.elements == [
        with_includes / "__init__.py",
        with_includes / "bar",
        with_includes / "bar/baz.py",
        with_includes / "extra_package",
        with_includes / "extra_package/some_dir",
        with_includes / "extra_package/some_dir/foo.py",
        with_includes / "extra_package/some_dir/quux.py",
        with_includes / "not_a_python_pkg",
        with_includes / "not_a_python_pkg/baz.txt",
    ]

def test_package_include_with_simple_dir() -> None:
    pkg_include = PackageInclude(base=with_includes, include="bar")
    assert pkg_include.elements == [with_includes / "bar/baz.py"]

def test_package_include_with_nested_dir() -> None:
    pkg_include = PackageInclude(base=with_includes, include="extra_package/**/*.py")
    assert pkg_include.elements == [
        with_includes / "extra_package/some_dir/foo.py",
        with_includes / "extra_package/some_dir/quux.py",
    ]

def test_package_include_with_no_python_files_in_dir() -> None:
    with pytest.raises(ValueError) as e:
        PackageInclude(base=with_includes, include="not_a_python_pkg")

    assert str(e.value) == "not_a_python_pkg is not a package."

def test_package_include_with_non_existent_directory() -> None:
    with pytest.raises(ValueError) as e:
        PackageInclude(base=with_includes, include="not_a_dir")

    err_str = str(with_includes / "not_a_dir") + " does not contain any element"

    assert str(e.value) == err_str

def test_pep_561_stub_only_package_good_name_suffix() -> None:
    pkg_include = PackageInclude(
        base=fixtures_dir / "pep_561_stub_only", include="good-stubs"
    )
    assert pkg_include.elements == [
        fixtures_dir / "pep_561_stub_only/good-stubs/__init__.pyi",
        fixtures_dir / "pep_561_stub_only/good-stubs/module.pyi",
    ]

def test_pep_561_stub_only_partial_namespace_package_good_name_suffix() -> None:
    pkg_include = PackageInclude(
        base=fixtures_dir / "pep_561_stub_only_partial_namespace", include="good-stubs"
    )
    assert pkg_include.elements == [
        fixtures_dir / "pep_561_stub_only_partial_namespace/good-stubs/module.pyi",
        fixtures_dir / "pep_561_stub_only_partial_namespace/good-stubs/subpkg/",
        fixtures_dir
        / "pep_561_stub_only_partial_namespace/good-stubs/subpkg/__init__.pyi",
        fixtures_dir / "pep_561_stub_only_partial_namespace/good-stubs/subpkg/py.typed",
    ]

def test_pep_561_stub_only_package_bad_name_suffix() -> None:
    with pytest.raises(ValueError) as e:
        PackageInclude(base=fixtures_dir / "pep_561_stub_only", include="bad")

    assert str(e.value) == "bad is not a package."


import click
import numpy as np
import pandas as pd

from tqdm import tqdm
from pathlib import Path
from sentence_transformers import SentenceTransformer

#model = SentenceTransformer('all-mpnet-base-v2')
model = SentenceTransformer('all-MiniLM-L6-v2')
@click.command()
@click.argument('input_path', type=click.Path(exists=True))
@click.argument('output_path', type=click.Path())

def main(input_path, output_path):

    final_db = pd.read_csv(input_path + '/predictionDB.csv',lineterminator='\n')
    nrows = final_db.shape[0]

    if not Path(output_path + '/embeddings').exists():
        Path(output_path + '/embeddings').mkdir()

    if not Path(output_path + '/embeddings2').exists():
        Path(output_path + '/embeddings2').mkdir()

    for index,row in tqdm(final_db.iterrows()):
        frases = row['COMMIT_MESSAGE']
        matrix = model.encode(frases)
        np.save(output_path +'/embeddings/' + row['COMMIT_HASH'] + '.npy',matrix)

        frases = row['CLEAN_CMS']
        matrix = model.encode(frases)
        np.save(output_path +'/embeddings2/' + row['COMMIT_HASH'] + '.npy',matrix)

if __name__ == '__main__':
    main()


from WebPage import WebPage
from selenium.common.exceptions import NoSuchElementException
class ListWordPage(WebPage):
    def fillSearchWordText(self,word: str):
        try:
            self.webTestModule.driver.find_element_by_id('searchWordText').send_keys(word)
        except NoSuchElementException:
            assert False, "search word text field not found!"
    def clickSearchButton(self):
        try:
            self.webTestModule.driver.find_element_by_xpath("//input[@value='Search Word']").click()
        except NoSuchElementException:
            assert False, "search word button not found!"
    def locateWord(self,word:str):
        try:
            self.webTestModule.driver.find_element_by_xpath("//td[contains(text(),'"+word+"')]")
        except NoSuchElementException:
            assert False, word+" word not found!"
    def checkWordNotExist(self,word:str):
        try:
            self.webTestModule.driver.find_element_by_xpath("//td[contains(text(),'"+word+"')]")
        except NoSuchElementException:
            return
        assert False, word+" word found!"
    def deleteWord(self):
        try:
            self.webTestModule.driver.find_element_by_xpath("//input[@value='delete']").click()
        except NoSuchElementException:
            assert False, "delete button not found!"


import cv2
# This is the distance from camera to face object
DECLARED_LEN = 30 # cm
# width of the object face
DECLARED_WID = 14.3 # cm
# Definition of the RGB Colors format
GREEN = (0, 255, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
#Defining the fonts family, size, type
fonts = cv2.FONT_HERSHEY_COMPLEX
# calling the haarcascade_frontalface_default.xml module for face detection.
face_cascade= cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

def focal_length(determined_distance, actual_width, width_in_rf_image):
    focal_length_value = (width_in_rf_image * determined_distance) / actual_width
    return focal_length_value

def distance_finder(focal_length, real_face_width, face_width_in_frame):
    distance = (real_face_width * focal_length) / face_width_in_frame
    return distance

def face_data(image):
  face_width = 0
#   gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    #We use 1.3 for less powerful processors but can increase it according to your processing power of your machine.
  faces =face_cascade.detectMultiScale(image,1.05, 5)
    #getting the rectangular frame
  for (x, y, h, w) in faces:
        cv2.rectangle(image, (x, y), (x + w, y + h), WHITE, 1)
        face_width = w

  return face_width

ref_image = cv2.imread("shivaadla.jpg")
ref_image_face_width = face_data(ref_image)
#Processing our called reference image
focal_length_found = focal_length(DECLARED_LEN, DECLARED_WID, ref_image_face_width)
# print(focal_length_found)
cv2.imshow("ref_image", ref_image)
cap = cv2.VideoCapture(0)
while True:

    _, frame=cap.read()
    # calling face_data function
    face_width_in_frame=face_data(frame)
    # finding the distance by calling function Distance
    if face_width_in_frame != 0:
         Distance=distance_finder(focal_length_found, DECLARED_WID, face_width_in_frame)
        # Writing Text on the displaying screen
         cv2.putText(
            frame, f"Distance = {round(Distance,2)} CM", (50, 50), fonts, 1, (WHITE),2)
    cv2.imshow('frame', frame)
    if cv2.waitKey(1) == ord("q"):
        break
cap.release()
cv2.destroyAllWindows()


import os
from pathlib import Path

import pytest
from unit.applications.proto import ApplicationProto

client = ApplicationProto()

@pytest.fixture(autouse=True)
def setup_method_fixture(temp_dir):
    os.makedirs(f'{temp_dir}/assets/dir')
    os.makedirs(f'{temp_dir}/assets/d$r')
    Path(f'{temp_dir}/assets/index.html').write_text('0123456789')
    Path(f'{temp_dir}/assets/dir/file').write_text('file')
    Path(f'{temp_dir}/assets/d$r/file').write_text('d$r')

    assert 'success' in client.conf(
        {
            "listeners": {"*:7080": {"pass": "routes"}},
            "routes": [{"action": {"share": f'{temp_dir}/assets$uri'}}],
        }
    )

def update_share(share):
    if isinstance(share, list):
        return client.conf(share, 'routes/0/action/share')

    return client.conf(f'"{share}"', 'routes/0/action/share')

def test_static_variables(temp_dir):
    assert client.get(url='/index.html')['status'] == 200
    assert client.get(url='/d$r/file')['status'] == 200

    assert 'success' in update_share('$uri')
    assert client.get(url=f'{temp_dir}/assets/index.html')['status'] == 200

    assert 'success' in update_share(f'{temp_dir}/assets${{uri}}')
    assert client.get(url='/index.html')['status'] == 200

def test_static_variables_array(temp_dir):
    assert 'success' in update_share([f'{temp_dir}/assets$uri', '$uri'])

    assert client.get(url='/dir/file')['status'] == 200
    assert client.get(url=f'{temp_dir}/assets/index.html')['status'] == 200
    assert client.get(url='/blah')['status'] == 404

    assert 'success' in client.conf(
        {
            "share": [f'{temp_dir}/assets$uri', '$uri'],
            "fallback": {"return": 201},
        },
        'routes/0/action',
    )

    assert client.get(url='/dir/file')['status'] == 200
    assert client.get(url=f'{temp_dir}/assets/index.html')['status'] == 200
    assert client.get(url='/dir/blah')['status'] == 201

def test_static_variables_buildin_start(temp_dir):
    assert 'success' in update_share('$uri/assets/index.html')
    assert client.get(url=temp_dir)['status'] == 200

def test_static_variables_buildin_mid(temp_dir):
    assert 'success' in update_share(f'{temp_dir}$uri/index.html')
    assert client.get(url='/assets')['status'] == 200

def test_static_variables_buildin_end():
    assert client.get(url='/index.html')['status'] == 200

def test_static_variables_invalid(temp_dir):
    assert 'error' in update_share(f'{temp_dir}/assets/d$r$uri')
    assert 'error' in update_share(f'{temp_dir}/assets/$$uri')
    assert 'error' in update_share(
        [f'{temp_dir}/assets$uri', f'{temp_dir}/assets/dir', '$$uri']
    )


#!/usr/bin/python3.8
# -*- coding:utf-8 -*-
import shapely
import random
import math
from shapely.ops import split, nearest_points
from multiprocessing import Pool

from .compute_kernel import GetKernel
from .compute_visibility import GetVisibilityPolygon
from ..Test.draw_pictures import *
def SelectMaxPolygon(polygons):
    MaxPolygon = None
    if polygons is None:
        print("polygons is None")
        return None
    elif (type(polygons) == shapely.Polygon):
        MaxPolygon = polygons
    else:
        for p in list(polygons.geoms):
            if (type(p) == shapely.MultiPolygon) or (type(p) == shapely.GeometryCollection):
                p = SelectMaxPolygon(p)
            elif MaxPolygon == None or ((type(p) == shapely.Polygon) and p.area > MaxPolygon.area):
                MaxPolygon = p
    if(MaxPolygon) == None:
        print("SelectMaxPolygon Failed",type(polygons))
    return MaxPolygon

def SelectPointFromPolygon(polygon):
    minx, miny, maxx, maxy = polygon.bounds
    tempPolygon = polygon.buffer(-1)
    while True:
        p = shapely.Point(random.uniform(minx, maxx),
                          random.uniform(miny, maxy))
        if tempPolygon.contains(p):
            return p
def FindVisibleRegion(polygon, watcher, d = 32, useCPP = False):

    visiblePolygon = GetVisibilityPolygon(polygon, watcher)

    dVisibility = watcher.buffer(d)  # d范围视距
    visiblePolygon = visiblePolygon.intersection(dVisibility)  # 有限视距下的可视范围

    visiblePolygon = SelectMaxPolygon(visiblePolygon)
    if(visiblePolygon == None):
        print("failed find visibile polygon")

    return visiblePolygon.simplify(1, preserve_topology=False)

def GetKernelPolygon(visiblePolygon):
    xList, yList = GetKernel(visiblePolygon)
    kernel = list(zip(xList, yList))
    return shapely.Polygon(kernel)

def GetRayLine(watcher, vertex):
    xGap = vertex[0] - watcher[0]
    yGap = vertex[1] - watcher[1]
    rate = (1/(math.hypot(xGap, yGap)))*1e10
    extendPoint1 = (watcher[0] + xGap*rate,watcher[1] + yGap*rate)
    extendPoint2 = (watcher[0] - xGap*rate,watcher[1] - yGap*rate)
    return shapely.LineString([extendPoint1, extendPoint2])

def GetSingleReflexChord(visiblePolygonPointList, reflexPoint, kernel):

    prependicular = None
    kernelPointList = list(kernel.exterior.coords)
    kernelPointList.pop()
    kernelPointList.reverse()
    if (reflexPoint in list(kernelPointList)):  # 如果反射点在kernel上
        numOfKernelPoints = len(kernelPointList)
        reflex_kernel_pos = visiblePolygonPointList.index(reflexPoint)
        reflexKernelLeft = kernelPointList[(reflex_kernel_pos - 1) % numOfKernelPoints]
        reflexKernelRight = kernelPointList[(reflex_kernel_pos + 1) % numOfKernelPoints]
        # 和弦的斜率应为 反射点临边斜率的平均值
        if (abs(reflexPoint[0] - reflexKernelLeft[0]) < 1e-2 or abs(reflexKernelRight[0] - reflexPoint[0]) < 1e-2):
            extendPoint = (reflexPoint[0], reflexPoint[1] + 1)
        else:
            prependicular1 = (reflexKernelRight[1] - reflexPoint[1]) / (reflexKernelRight[0] - reflexPoint[0])
            prependicular2 = (reflexPoint[1] - reflexKernelLeft[1]) / (reflexPoint[0] - reflexKernelLeft[0])

            prependicular = (prependicular1 + prependicular2) / 2
            extendPoint = (reflexPoint[0]+1, reflexPoint[1] + prependicular)
    else:
        point = shapely.Point(reflexPoint)  # 如果反射点不在kernel上
        nearestPoint = (nearest_points(point, kernel))[1]
        # 和弦的斜率应为 点连线的垂线的斜率
        if abs(point.y - nearestPoint.y) < 1e-6:  # 斜率判断
            extendPoint = (reflexPoint[0], reflexPoint[1] + 1)

        else:
            prependicular = (nearestPoint.x - point.x) / (point.y - nearestPoint.y)
            extendPoint = (reflexPoint[0]+1, reflexPoint[1] + prependicular)
    return GetRayLine(reflexPoint, extendPoint)

def GetSplitedPolygon(chord, visiblePolygon, watcher):
    polygon = shapely.Point(1,1)
    tempVisiblePolygon = visiblePolygon
    polygons = list(split(tempVisiblePolygon, chord).geoms)
    for polygon in polygons:
        if type(polygon) == (shapely.Polygon) and polygon.contains(watcher):
            return polygon
    # print(polygons)
    return polygon

def MaximallyCoveringConvexSubset(args):  # MCCS
    unCoveredPolygon = args[0]
    initialPolygon = args[1]
    watcher = args[2]
    d = args[3]
    visiblePolygon = FindVisibleRegion(
        initialPolygon, watcher, d,False)  # d为可视距离

    kernelPolygon, reflexPointList = GetKernel(visiblePolygon, watcher)
    reflexPointList.sort(key=lambda watcher: shapely.distance(
        kernelPolygon, shapely.Point(watcher)))  # 列表排序
    polygon = visiblePolygon
    numOfReflexPoints = len(reflexPointList)

    for i in range(numOfReflexPoints):

        polygonPointList = list(polygon.exterior.coords)
        polygonPointList.pop()
        numOfPolygonPoints = len(polygonPointList)
        reflexPoint1 = reflexPointList[i]
        reflexPoint2 = reflexPointList[(i+1) % numOfReflexPoints]

        if (reflexPoint1 not in polygonPointList):
            continue
        r1Pos = polygonPointList.index(reflexPoint1)
        r1Left = polygonPointList[(r1Pos - 1) % numOfPolygonPoints]
        r1Right = polygonPointList[(r1Pos + 1) % numOfPolygonPoints]

        # extremal chords
        chord = GetRayLine(reflexPoint1, r1Left)
        ePolygon1 = GetSplitedPolygon(chord, polygon, watcher)

        chord = GetRayLine(reflexPoint1, r1Right)
        ePolygon2 = GetSplitedPolygon(chord, polygon, watcher)

        # two reflex chord
        if (len(reflexPointList) > 1):
            chord = GetRayLine(reflexPoint1, reflexPoint2)
            tPolygon = GetSplitedPolygon(chord, polygon, watcher)
        else:
            tPolygon = shapely.Point(1, 1)  # area of point is 0

        # single reflex chord
        chord = GetSingleReflexChord(
            polygonPointList, reflexPoint1, kernelPolygon)
        sPolygon = GetSplitedPolygon(chord, polygon, watcher)
        polygon = max(ePolygon1, ePolygon2, tPolygon, sPolygon, key=lambda inptPolygon: (
            unCoveredPolygon.intersection(inptPolygon)).area)
    return polygon

def PolygonCover(polygon, d, coverage, iterations=32):
    polygonCoverList = []
    unCoverPolygon = shapely.Polygon(polygon)
    pool = Pool(8)
    while ((unCoverPolygon.area / polygon.area) > (1-coverage)):

        point = SelectPointFromPolygon(unCoverPolygon)
        R0 = MaximallyCoveringConvexSubset((unCoverPolygon, polygon, point, d))
        bestR = R0
        #迭代开始
        num = iterations
        pointList = []
        while num > 0:
            pointList.append(SelectPointFromPolygon(R0))
            num -= 1
        RList =(pool.map(MaximallyCoveringConvexSubset,[(unCoverPolygon, polygon, point, d) for point in pointList]))
        RList.append(R0)
        bestR = max(RList,key=lambda R:(R.intersection(unCoverPolygon)).area)
        bestR = bestR.simplify(0.05,False)

        polygonCoverList.append(bestR)
        unCoverPolygon = unCoverPolygon.difference(bestR)
        if(type(unCoverPolygon) == shapely.GeometryCollection):
            polygonList = []
            for geoms in unCoverPolygon.geoms:
                if type(geoms) == shapely.Polygon:
                    polygonList.append(geoms)
            unCoverPolygon = shapely.GeometryCollection(polygonList)

    return polygonCoverList


# 1.데이터 수집
#  - 웹 크롤링(Web Crawling)
#  - OpenAPI(기관에서 제공)
#  - Database & Server
#  - Excel

#  웹 크롤링: 웹 사이트에 존재하는 데이터를 수집하는 방법
#    - 라이브러리: BeautifulSoup4, Requests, Selenium

# 웹사이트: HTML 언어
# 개발자(HTML Code) -> 웹 브라우저(Chrome) -> 랜더링 -> 예쁜 웹 사이트 짜짠!

import requests
from bs4 import BeautifulSoup

# requests: 웹 사이트(url) 전체 코드 복사 Get
# BeautifulSoup4: 전체 코드에서 수집하고 싶은 정보만 Get

url = "https://v.daum.net/v/20231004111930039"  # 데이터를 수집하고 싶은 주소
result = requests.get(url)  # requests는 해당 URL의 모든 소스코드를 가져옴
# print(result.text)

# result.text(전체코드) => Beautifulsoup 읽고 해석 => doc(전체코드)
doc = BeautifulSoup(result.text, "html.parser")

# 전체코드 중 수집하고 싶은 부분만 select

# HTML
#  1.Tag로 구현 ex) ,

,
값

#  2.선택자
#   - ID 선택자(#): 유니크, 1개만 존재
#   - Class 선택자(.): 복수개 선택

# select() => list type[]
# get_text() => Tag정보 제거, 순수 Text만 추출
title = doc.select("h3.tit_view")[0].get_text()
print(f"제목: {title}")  # f-string 기법
# print("제목: {}".format(title))  # format() 기법

# section 태그의 자식인 p태그만 선택!
contents = doc.select("section > p")  # 10개의 P태그 묶음
# print(len(contents))

# 1.P태그에서 text값만 추출 => 10번
# 2.10개 text값을 더하기!
# 3.출력
content = ""  # 본문 더해서 저장할 변수
for i, p in enumerate(contents):  # 10개의 p
    # print(i+1, p.get_text())
    content = content + p.get_text()

print(f"본문: {content}")


import pytest

@pytest.fixture
def create_overdue_books_query(library_ma_tables, get_uid, client):
    checkouts = library_ma_tables["Checkouts"]
    patrons = library_ma_tables["Patrons"]
    items = library_ma_tables["Items"]
    publications = library_ma_tables["Publications"]
    request_data = {
        "name": get_uid(),
        "base_table": checkouts.id,
        "initial_columns": [
            {
                "id": checkouts.get_column_by_name("id").id,
                "alias": "Checkout id"
            }, {
                "id": checkouts.get_column_by_name("Due Date").id,
                "alias": "Due Date"
            }, {
                "id": checkouts.get_column_by_name("Check In Time").id,
                "alias": "Check In Time"
            }, {
                "id": patrons.get_column_by_name("Email").id,
                "alias": "email",
                "display_name": "Patron Email",
                "jp_path": [
                    [
                        checkouts.get_column_by_name("Patron").id,
                        patrons.get_column_by_name("id").id,
                    ]
                ]
            }, {
                "id": publications.get_column_by_name("Title").id,
                "alias": "Book Title",
                "jp_path": [
                    [
                        checkouts.get_column_by_name("Item").id,
                        items.get_column_by_name("id").id,
                    ], [
                        items.get_column_by_name("Publication").id,
                        publications.get_column_by_name("id").id,
                    ]
                ]
            },
        ],
        "transformations": [
            {
                "spec": {
                    "lesser": [
                        {"column_name": ["Due Date"]},
                        {"literal": ["2022-08-10"]}
                    ]
                },
                "type": "filter"
            },
            {
                "spec": {
                    "empty": [{"column_name": ["Check In Time"]}]
                },
                "type": "filter"
            },
            {
                "spec": {
                    "grouping_expressions": [{"input_alias": "email"}],
                    "aggregation_expressions": [
                        {
                            "input_alias": "Book Title",
                            "output_alias": "Title List",
                            "function": "aggregate_to_array"
                        }
                    ]
                },
                "type": "summarize",
                "display_names": {
                    "Title List": "Titles"
                }
            }
        ],

    }
    response = client.post('/api/db/v0/queries/', data=request_data)
    assert response.status_code == 201
    return response

@pytest.fixture
def check_overdue_books_columns(create_overdue_books_query, client):
    query_id = create_overdue_books_query.json()['id']
    expect_response_data = [
        {
            'alias': 'Title List',
            'display_name': 'Titles',
            'type': '_array',
            'type_options': {'item_type': 'text'},
            'display_options': None
        }, {
            'alias': 'email',
            'display_name': 'Patron Email',
            'type': 'mathesar_types.email',
            'type_options': None,
            'display_options': None
        }
    ]
    actual_response_data = client.get(f'/api/db/v0/queries/{query_id}/columns/').json()
    assert sorted(actual_response_data, key=lambda x: x['alias']) == expect_response_data
    return query_id

@pytest.fixture
def run_overdue_books_scenario(check_overdue_books_columns, client):
    query_id = check_overdue_books_columns
    expect_records = [
        {
            'email': 'eduardorojas13@peterson-curry.com',
            'Title List': ['Bar Order Might Per', 'Hand Raise Son Probably Do']
        }, {
            'email': 'heatherwheeler@peterson-delgado.com',
            'Title List': ['Bar Order Might Per', 'I Worker Suffer Likely']
        }, {
            'email': 'jhooper@bowers.com',
            'Title List': ['Military Myself Sport Wrong']
        }, {
            'email': 'kathyb@le.org',
            'Title List': ['Pass Street Year']
        }, {
            'email': 'kwright@odonnell.com',
            'Title List': ['Day Beyond Property', 'On Letter Experience']
        }, {
            'email': 'tevans46@thompson.net',
            'Title List': ['Space Music Rest Crime']
        }, {
            'email': 'y.ho@johnson.info',
            'Title List': ['Mention Add Size City Kid', 'Economic Too Level']
        }
    ]
    actual_records = sorted(
        client.get(f'/api/db/v0/queries/{query_id}/records/').json()['results'],
        key=lambda x: x['email']
    )
    for rec_pair in zip(actual_records, expect_records):
        assert rec_pair[0]['email'] == rec_pair[1]['email']
        assert sorted(rec_pair[0]['Title List']) == sorted(rec_pair[1]['Title List'])

@pytest.fixture
def create_monthly_checkouts_query(run_overdue_books_scenario, get_uid, client):
    _ = run_overdue_books_scenario
    checkouts = {
        t["name"]: t for t in client.get("/api/db/v0/tables/").json()["results"]
    }["Checkouts"]
    columns = {
        c["name"]: c for c in checkouts["columns"]
    }
    request_data = {
        "name": get_uid(),
        "base_table": checkouts["id"],
        "initial_columns": [
            {"id": columns["id"]["id"], "alias": "id"},
            {"id": columns["Checkout Time"]["id"], "alias": "Checkout Time"},
        ],
        "transformations": [
            {
                "spec": {
                    "grouping_expressions": [
                        {
                            "input_alias": "Checkout Time",
                            "output_alias": "Checkout Month",
                            "preproc": "truncate_to_month",
                        }
                    ],
                    "aggregation_expressions": [
                        {
                            "input_alias": "id",
                            "output_alias": "Count",
                            "function": "count",
                        }
                    ]
                },
                "type": "summarize",
                "display_names": {
                    "Checkout Month": "Month",
                    "Count": "Number of Checkouts"
                }
            }
        ]
    }
    response = client.post('/api/db/v0/queries/', data=request_data)
    assert response.status_code == 201
    return response

@pytest.fixture
def check_monthly_checkouts_columns(create_monthly_checkouts_query, client):
    query_id = create_monthly_checkouts_query.json()['id']
    expect_repsonse_data = [
        {
            'alias': 'Checkout Month',
            'display_name': 'Month',
            'type': 'text',
            'type_options': None,
            'display_options': None
        }, {
            'alias': 'Count',
            'display_name': 'Number of Checkouts',
            'type': 'integer',
            'type_options': None,
            'display_options': None
        }
    ]
    actual_response_data = client.get(f'/api/db/v0/queries/{query_id}/columns/').json()
    assert sorted(actual_response_data, key=lambda x: x['alias']) == expect_repsonse_data
    return query_id

def test_monthly_checkouts_scenario(check_monthly_checkouts_columns, client):
    query_id = check_monthly_checkouts_columns
    expect_records = [
        {'Checkout Month': '2022-05', 'Count': 39},
        {'Checkout Month': '2022-06', 'Count': 26},
        {'Checkout Month': '2022-07', 'Count': 29},
        {'Checkout Month': '2022-08', 'Count': 10},
    ]
    actual_records = client.get(f'/api/db/v0/queries/{query_id}/records/').json()['results']
    assert sorted(actual_records, key=lambda x: x['Checkout Month']) == expect_records


from itertools import dropwhile

def parse_input(inp):
    return [int(i) for i in inp[0]]

def mix_cups(cups, cup, repeat):
    for _ in range(repeat):
        pickup = [cups[cup]]
        pickup.append(cups[pickup[-1]])
        pickup.append(cups[pickup[-1]])
        destination = next(dropwhile(lambda x: x in pickup, ((len(cups) - 2 + x) % (len(cups)) + 1 for x in (cup, cup-1,cup-2, cup-3))))
        next_destination = cups[destination]
        cups[cup] = cups[pickup[-1]]
        cups[destination] = pickup[0]
        cups[pickup[-1]] = next_destination
        cup = cups[cup]

def p1(inp):
    cups = {c: inp[i+1] if i < len(inp) - 1 else inp[0] for i, c in enumerate(inp)}
    mix_cups(cups, inp[0], 100)
    def order(cup):
        return str(cup) + order(cups[cup]) if cup != 1 else ''
    return order(cups[1])

def p2(inp):
    cups = {**{c: inp[i+1] if i < len(inp) - 1 else len(inp)+1 for i, c in enumerate(inp)}, **{i: i+1 for i in range(len(inp)+1, 10**6)}, 10**6: inp[0]}
    mix_cups(cups, inp[0], 10**7)
    return cups[1] * cups[cups[1]]

if __name__ == "__main__":
    with open('input.txt', "r") as f:
        inp = parse_input(f.readlines())
        print(f"Part 1: {p1(inp)}")
        print(f"Part 2: {p2(inp)}")


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import datetime
from django.test import TestCase
from django.utils import timezone
from django.urls import reverse

from .models import Question

# Create your tests here.

class QuestionModelTests(TestCase):

    def test_was_published_recently_with_future_question(self):
        """
        was_published_recently() returns False for questions whose pub_date
        is in the future.
        """
        # Будущее время
        time = timezone.now() + datetime.timedelta(days=1)
        # Вопрос из будущего
        future_question = Question(pub_date=time)
        # Должнв получить False
        self.assertIs(future_question.was_published_recently(), False)

    def test_was_published_recently_with_old_question(self):
        """
        was_published_recently() returns False for questions whose pub_date
        is in the old.
        """
        # Прошлое (больше дня) время
        time = timezone.now() - datetime.timedelta(days=1, seconds=1)
        # Вопрос старше 1 дня
        old_question = Question(pub_date=time)
        # Должны вернуть False
        self.assertIs(old_question.was_published_recently(), False)

    def test_was_published_recently_with_recent_question(self):
        """
        was_published_recently() returns False for questions whose pub_date
        is in the recent.
        """
        # Прошлое время (не старше дня назад)
        time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
        # Вопрос не старше 1 дня
        recent_question = Question(pub_date=time)
        # Должны вернуть True
        self.assertIs(recent_question.was_published_recently(), True)

def create_question(question_text, days):
    """
    Create a question with the given `question_text` and published the
    given number of `days` offset to now (negative for questions published
    in the past, positive for questions that have yet to be published).
    """
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)

class QuestionIndexViewTests(TestCase):
    def test_no_questions(self):
        """
        If no questions exist, an appropriate message is displayed.
        """
        response = self.client.get(reverse('polls:index'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'No polls are available.')
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_past_question(self):
        """
        Questions with a pub_date in the past are displayed on the
        index page.
        """
        create_question(question_text='Past question.', days=-30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            ['<Question: Past question.>']
        )


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Category',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
                ('name', models.CharField(max_length=255, verbose_name='Category Name')),
                ('description', models.TextField(null=True)),
            ],
            options={
            },
            bases=(models.Model,),
        ),
        migrations.CreateModel(
            name='PropertyName',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', auto_created=True, serialize=False)),
                ('name', models.CharField(max_length=255, verbose_name='Property Name')),
                ('description', models.TextField(null=True)),
                ('category', models.ForeignKey(to='category.Category')),
            ],
            options={
            },
            bases=(models.Model,),
        ),
    ]


import sys
sys.path.append(r'D:\00_work\ML_LIB')
#sys.path.append(r'E:\01_PProj\ML_LIB')

import Lib_sjw.training as tr
import Lib_sjw.model_interface as mi
import Lib_sjw.model_parmas as mp
import Lib_sjw.evaluator as ev
import Lib_sjw.classification_util as cu

from sklearn.metrics import mean_squared_error , roc_auc_score , precision_score
from sklearn.model_selection import train_test_split
import numpy as np

from collections import OrderedDict

from sklearn.datasets import fetch_california_housing , load_iris , load_breast_cancer

'''
1. 데이터 만들기
2. 모델 제너레이터 만들기
3. 모델 생성 파라미터, 피팅 파라미터 만들기
4. 성능평가 메트릭 정의하기 :  f : y , pred -> value
5. training_fixedTest 실행하기
6. 유틸에 테스트 데이터에 대한 성능평가, 또는 저장 등을 하기
'''

def Test_Classification(xtrain , ytrain , xtest , nfold = 5 , verbose = False):
    # name list
    name_list = ['xgb',
                 'lgb',
                 'cat',
                 'rfc',
                 'svm',
                 'gpc',
                 'lda',
                 'qda']
    # model_list , param_list ,
    model_list = OrderedDict()
    model_list['xgb']  = mi.myXGBClassifier()
    model_list['lgb']  = mi.myLGBMClassifier()
    model_list['cat']  = mi.myCatBoostClassifier()
    model_list['rfc']  = mi.myRandomForestClassifier()

    model_list['svm']  = mi.mySVMClassifier()
    model_list['gpc']  = mi.myGPClassifier()
    model_list['lda']  = mi.myLDAClassifier()
    model_list['qda']  = mi.myQDAClassifier()

    param_list = OrderedDict()
    param_list['xgb'] = mp.param_xgb('classification' , len(np.unique(ytrain)), use_gpu= False)
    param_list['lgb'] = mp.param_lgbm('classification' , len(np.unique(ytrain)), use_gpu= False)
    param_list['cat']  = mp.param_cat('classification' , use_gpu= True , is_unbalance= False )
    param_list['rfc']  = mp.param_rf('classification')
    param_list['svm']  = mp.param_svm('classification')
    param_list['gpc']  = mp.param_gpc('classification')
    param_list['lda']  = mp.param_lda()
    param_list['qda']  = mp.param_qda()

    #fitting parmas
    fitpm_list = OrderedDict()

    for name in name_list:
            fitpm_list[name] = {}
    fitpm_list['lgb'] = {'early_stopping_rounds' : 12 , 'verbose' : -1}
    #fit_cat = {}
    #fit_xgb = {}

    # metric func
    metric_func = cu.aucpr
    #metric_func = partial(cu.auc_multi , [0,1,2,3])

    # Result
    result_list = OrderedDict()

    # Training
    for name in name_list:
        print(name)
        fold_predict , fold_oof , fold_metric , fold_model = tr.training_fixedTest('classification' , model_list[name] , param_list[name] , fitpm_list[name] ,  metric_func , xtrain , ytrain , xtest , nfold  )
        result_list[name] = [fold_predict , fold_oof , fold_metric , fold_model]
    print('Test_Classification Complete')
    return result_list

def Test_Classification_TestFold(X , y , nfold_test , nfold_val , verbose = True):
    # name list
    name_list = ['xgb',
                 'lgb',
                 'cat',
                 'rfc',
                 'svm',
                 'gpc',
                 'lda',
                 'qda']
    # model_list , param_list ,
    model_dict = OrderedDict()
    model_dict['xgb']  = mi.myXGBClassifier()
    model_dict['lgb']  = mi.myLGBMClassifier()
    model_dict['cat']  = mi.myCatBoostClassifier()
    model_dict['rfc']  = mi.myRandomForestClassifier()
    model_dict['svm']  = mi.mySVMClassifier()
    model_dict['gpc']  = mi.myGPClassifier()
    model_dict['lda']  = mi.myLDAClassifier()
    model_dict['qda']  = mi.myQDAClassifier()

    param_list = OrderedDict ( )
    param_list['xgb'] = mp .param_xgb ('classification' , len(np.unique(y)) , use_gpu= False )
    param_list['lgb'] = mp .param_lgbm('classification' , len(np.unique(y)) , use_gpu= False )
    param_list['cat'] = mp .param_cat ('classification' , use_gpu= True , is_unbalance= False )
    param_list['rfc'] = mp .param_rf ('classification' )
    param_list['svm'] = mp .param_svm ('classification' )
    param_list['gpc'] = mp .param_gpc ('classification' )
    param_list['lda'] = mp .param_lda ( )
    param_list['qda'] = mp .param_qda ( )

    #fitting parmas
    fitpm_list = OrderedDict()
    for name in name_list:
            fitpm_list[name] = {}
    fitpm_list['lgb'] = {'early_stopping_rounds' : 12 , 'verbose' : -1}
    #fit_cat = {}
    #fit_xgb = {}

    # metric func
    metric_func = cu.aucpr
    #metric_func = partial(cu.auc_multi , [0,1,2,3])
    # Result
    result_list = OrderedDict()
    auc_score_list = OrderedDict()
    for name in name_list:
        print(name)
        test_fold_index , oof, model_list = tr.training_Testfold('classification' , model_dict[name] , param_list[name] , fitpm_list[name] ,  metric_func , X , y , nfold_test , nfold_val )
        result_list[name] = [test_fold_index , oof, model_list]
        #auc_score_list[name] = roc_auc_score(np.where(y > 0.5 , 1 ,0 ) , np.argmax(oof.mean(axis = 0) , axis = 1))
    print('Test_Classification_TestFold Compelte')
    return result_list

if __name__ == '__main__':
    data = load_iris()
    X = data.data
    y = data.target

    xtrain , xtest , ytrain , ytest = train_test_split(X , y , test_size = 0.2 )

    Test_Classification(xtrain , ytrain , xtest , 2,False)
    Test_Classification_TestFold(X,y,2,2)

    print('done')