# **************************************************************************
# *
# * Authors:     Yaiza Rancel (cyrancel@cnb.csic.es) [1]
# *              Pablo Conesa (pconse@cnb.csic.es) [1]
# *              J.M. De la Rosa Trevin (delarosatrevin@scilifelab.se) [2]
# *
# * [1] Unidad de  Bioinformatica of Centro Nacional de Biotecnologia , CSIC
# * [2] SciLifeLab, Stockholm University
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307  USA
# *
# *  All comments concerning this program package may be sent to the
# *  e-mail address 'scipion@cnb.csic.es'
# *
# **************************************************************************
import os
import importlib
import pkgutil
import inspect
import pkg_resources
from email import message_from_string
from collections import OrderedDict
from abc import ABCMeta, abstractmethod

import pyworkflow.utils as pwutils
from pyworkflow.install import Environment

class Domain:
    """
    Class to represent the application domain.
    It will allow to specify new objects, protocols, viewers and wizards
    through the registration of new plugins.
    """

    # The following classes should be defined in subclasses of Domain
    _name = None
    _protocolClass = None
    _objectClass = None
    _viewerClass = None
    _wizardClass = None
    _baseClasses = {}  # Update this with the base classes of the Domain

    # Dictionaries to store different type of objects
    _plugins = {}
    _protocols = {}
    _objects = {}
    _viewers = {}
    _wizards = {}

    @classmethod
    def __getSubmodule(cls, name, subname):
        try:
            return importlib.import_module('%s.%s' % (name, subname))
        except Exception as e:
            msg = str(e)
            # FIXME: The following is a quick and dirty way to filter
            # when the submodule is not present
            if msg != 'No module named %s' % subname:
                pwutils.pluginNotFound("%s.%s" % (name, subname), msg)
            return None

    @classmethod
    def registerPlugin(cls, name):
        """ Register a new plugin. This function should only be called
        when creating a class with __metaclass__=PluginMeta that will
        trigger this.
        """
        m = importlib.import_module(name)
        cls._plugins[name] = m  # Register the name to as a plugin
        # TODO: Load subclasses (protocols, viewers, wizards)

        # Define variables
        m.Plugin._defineVariables()

        # Load bibtex
        m._bibtex = {}
        bib = cls.__getSubmodule(name, 'bibtex')
        if bib is not None:
            try:
                m._bibtex = pwutils.parseBibTex(bib.__doc__)
            except Exception:
                pass

        return m

    @classmethod
    def __isPlugin(cls, m):
        """ Return True if the module is a Scipion plugin. """
        return m.__name__ in cls._plugins

    @classmethod
    def getPlugins(cls):
        """ Return existing plugins for this Domain. """
        loaded = getattr(cls, '_pluginsLoaded', False)
        if not loaded:  # Load plugin only once
            for p, name, isModule in pkgutil.iter_modules():
                if isModule:
                    try:
                        importlib.import_module(name)
                        # NOTE: After importing the modules they will
                        # automatically being register if they has
                        # called Domain.registerPlugin(__name__)
                    except Exception:
                        pass
            cls._pluginsLoaded = True
        return dict(cls._plugins)

    @classmethod
    def getPlugin(cls, name):
        """ Load a given plugin name. """
        m = importlib.import_module(name)

        if not cls.__isPlugin(m):
            raise Exception("Invalid plugin '%s'. "
                            "Class Plugin with __metaclass__=PluginMeta "
                            "not found" % name)
        return m

    @classmethod
    def refreshPlugin(cls, name):
        """ Refresh a given plugin name. """
        import types

        plugin = cls.getPlugin(name)
        if plugin is not None:
            fn = plugin.__file__
            fn_dir = os.path.dirname(fn) + os.sep
            module_visit = {plugin}
            module_visit_path = {fn}
            del fn

            def get_recursive_molules(module):
                """
                Get all plugin modules recursively
                """
                for module_child in vars(module).values():
                    if isinstance(module_child, types.ModuleType):
                        fn_child = getattr(module_child, "__file__", None)
                        if (fn_child is not None) and fn_child.startswith(
                                fn_dir):
                            if fn_child not in module_visit_path:
                                module_visit.add(module_child)
                                module_visit_path.add(fn_child)
                                get_recursive_molules(module_child)

            get_recursive_molules(plugin)
            # reload all plugin modules

            while module_visit:
                for module in module_visit:
                    try:
                        reload(module)
                        module_visit.remove(module)
                        break
                    except Exception as ex:
                        pass

    @classmethod
    def __getSubclasses(cls, submoduleName, BaseClass,
                        updateBaseClasses=False):
        """ Load all detected subclasses of a given BaseClass.
        Params:
            updateBaseClasses: if True, it will try to load classes from the
                Domain submodule that was not imported as globals()
        """
        subclasses = getattr(cls, '_%s' % submoduleName)

        if not subclasses:  # Only discover subclasses once
            if updateBaseClasses:
                sub = cls.__getSubmodule(cls.getName(), submoduleName)
                if sub is not None:
                    for name in cls.getModuleClasses(sub):
                        attr = getattr(sub, name)
                        if inspect.isclass(attr) and issubclass(attr, BaseClass):
                            cls._baseClasses[name] = attr

            for pluginName, plugin in cls.getPlugins().iteritems():
                sub = cls.__getSubmodule(pluginName, submoduleName)
                if sub is not None:
                    for name in cls.getModuleClasses(sub):
                        attr = getattr(sub, name)
                        if inspect.isclass(attr) and issubclass(attr, BaseClass):

                            # Check if the class already exists (to prevent
                            # naming collisions)
                            if name in subclasses:
                                # Get already added class plugin
                                pluginCollision = subclasses[name]._package.__name__
                                print("ERROR: Name collision (%s) detected "
                                      "while discovering %s.%s.\n"
                                      " It conflicts with %s" %
                                      (name, pluginName, submoduleName,
                                       pluginCollision))
                            else:
                                # Set this special property used by Scipion
                                attr._package = plugin
                                subclasses[name] = attr
            subclasses.update(
                pwutils.getSubclasses(BaseClass, cls._baseClasses))

        return subclasses

    @classmethod
    def getModuleClasses(cls, module):

        # Dir was used before but dir returns all imported elements
        # included those imported to be BaseClasses.
        # return dir(module)

        # Get the module name
        moduleName = module.__name__

        # Get any module class
        for name, declaredClass in inspect.getmembers(module, inspect.isclass):
            if moduleName in declaredClass.__module__:
                yield name

    @classmethod
    def getProtocols(cls):
        """ Return all Protocol subclasses from all plugins for this domain.
        """
        return cls.__getSubclasses('protocols', cls._protocolClass)

    @classmethod
    def getObjects(cls):
        """ Return all EMObject subclasses from all plugins for this domain.
        """
        return cls.__getSubclasses('objects', cls._objectClass)

    @classmethod
    def getViewers(cls):
        """ Return all Viewer subclasses from all plugins for this domain.
        """
        return cls.__getSubclasses('viewers', cls._viewerClass,
                                   updateBaseClasses=True)

    @classmethod
    def getWizards(cls):
        """ Return all Wizard subclasses from all plugins for this domain.
        """
        return cls.__getSubclasses('wizards', cls._wizardClass)

    @classmethod
    def getName(cls):
        return cls._name

class Plugin:
    __metaclass__ = ABCMeta

    _vars = {}
    _homeVar = ''  # Change in subclasses to define the "home" variable
    _pathVars = []
    _supportedVersions = []

    @classmethod
    def _defineVar(cls, varName, defaultValue):
        """ Internal method to define variables from the environment. """
        cls._vars[varName] = os.environ.get(varName, defaultValue)

    @classmethod
    def _defineEmVar(cls, varName, defaultValue):
        """ Shortcut method to define variables by prepending EM_ROOT
        to the default value.
        """
        cls._defineVar(varName,
                       os.path.join(Environment.getEm(defaultValue)))

    @classmethod
    @abstractmethod
    def getEnviron(cls):
        """ Setup the environment variables needed to launch programs. """
        pass

    @classmethod
    @abstractmethod
    def _defineVariables(cls):
        """ Method to define variables and their default values.
        It will use the method _defineVar that will take a variable value
        from the environment or from an optional default value.

        This method is not supposed to be called from client code,
        except from the Domain class when registering a Plugin.
        """
        pass

    @classmethod
    @abstractmethod
    def defineBinaries(cls, env):
        """ Define required binaries in the given Environment. """
        pass

    @classmethod
    def getVar(cls, varName, defaultValue=None):
        """ Return the value of a given variable. """
        return cls._vars.get(varName, defaultValue)

    @classmethod
    def getVars(cls):
        """ Return the value of a given variable. """
        return cls._vars

    @classmethod
    def getHome(cls, *paths):
        """ Return a path from the "home" of the package
         if the _homeVar is defined in the plugin. """
        home = cls.getVar(cls._homeVar)
        return os.path.join(home, *paths) if home else ''

    @classmethod
    def getSupportedVersions(cls):
        """ Return the list of supported binary versions. """
        return cls._supportedVersions

    @classmethod
    def getActiveVersion(cls, home=None, versions=None):
        """ Return the version of the binaries that are currently active.
        In the current implementation it will be inferred from the *_HOME
        variable, so it should contain the version number in it. """
        # FIXME: (JMRT) Use the basename might aleviate the issue with matching
        # the binaries version, but we might consider to find a better solution
        home = os.path.basename(home or cls.getHome())
        versions = versions or cls.getSupportedVersions()

        for v in versions:
            if v in home:
                return v

        return ''

    @classmethod
    def validateInstallation(cls):
        """
        Check if the binaries are properly installed and if not, return
        a list with the error messages.

        The default implementation will check if the _pathVars exists.
        """
        missing = ["%s: %s" % (var, cls.getVar(var))
                   for var in cls._pathVars if not os.path.exists(cls.getVar(var))]

        return (["Missing variables:"] + missing) if missing else []

class PluginInfo:
    """
    Information related to a given plugin when it is installed via PIP
    """
    def __init__(self, name):
        try:
            dist = pkg_resources.get_distribution(name)
            lines = [l for l in dist._get_metadata(dist.PKG_INFO)]
            tuples = message_from_string('\n'.join(lines))

        except Exception:
            print("Plugin %s seems is not a pip module yet. "
                  "No metadata found" % name)
            tuples = message_from_string('Author: plugin in development mode?')

        self._name = name
        self._metadata = OrderedDict()

        for v in tuples.items():
            if v[0] == 'Keywords':
                break
            self._metadata[v[0]] = v[1]

    def getAuthor(self):
        return self._metadata.get('Author', "")

    def getAuthorEmail(self):
        return self._metadata.get('Author-email', '')

    def getHomePage(self):
        return self._metadata.get('Home-page', '')

    def getKeywords(self):
        return self._metadata.get('Keywords', '')


def export_posts(urls, titles, source, destination):

	writer = True
	stack = False
	wanted = False
	count = 0

	with open(source) as post_backup:
		with open(destination, "w+") as for_importer:

			for line in post_backup.readlines():

				if writer == True:
					for_importer.write(line)

				if line.startswith("	<item>"):
					stack = True
					stack_content = ""
					writer = False
				elif line.startswith("	</item>"):
					stack = False
					if wanted == True:
						for_importer.write(stack_content)
						for_importer.write(line)
						wanted = False

				if stack == True:
					stack_content += line
					if (line.startswith("		<title>") and ("-").join(line.strip("\n")[9:-8].lower().replace(":", "").replace("'", "").replace("’", "").replace("-|", "").replace(".", "").replace("!", "").replace("-&", "").replace("?","").replace(",","").replace("“", "").replace("”", "").split(" ")) in titles) or (line.startswith("		<link>") and line.strip()[6:-7] in urls):
						count += 1
						wanted = True

	return count


##
## EPITECH PROJECT, 2020
## PSU_zappy_2019
## File description:
## parse
##

key = ["-p", "-n", "-h"]
matching_key = ["port", "name", "host"]

infos = {
    "host": "localhost",
    "name": "",
    "port": ""
}

def print_help(bin_name, code):
    print("USAGE: " + bin_name + " -p port -n name")
    print("\tport\t\tis the port number")
    print("\tname\t\tis the name of the team")
    print("\tmachine\t\tis the name of the machine; localhost by default")
    exit(code)

def parse(param):

    if (len(param) == 2 and param[1] == "-h") : print_help(param[0], 0)
    if (len(param) == 2 and param[1] == "-help") : print_help(param[0], 0)
    if (len(param) < 5) : print_help(param[0], 84)
    i = 1
    while (i < len(param)):
        check = 0
        while (check < len(key)):
            if (key[check].find(param[i]) != - 1):
                infos[matching_key[check]] = param[i + 1]
            check += 1
        i += 1
    if (infos["name"] == "" or infos["port"] == "") : return None
    return (infos)


class Solution:
    def longestIdealString(self, s: str, k: int) -> int:
        n = len(s)
        dp = [0] * 26
        for i in range(0, n):
            index = ord(s[i]) - ord('a')
            left = max(0, index - k)
            right = min(25, index + k)
            dp[index] = max([dp[j] for j in range(left, right + 1)]) + 1
        return max(dp)


# 10815. 숫자 카드

import sys

n = int(input())
card = list(map(int, sys.stdin.readline().split()))
m = int(input())
check = list(map(int, sys.stdin.readline().split()))

card.sort()

def binary_search(array, target, start, end):
    while start <= end:
        mid = (start + end) // 2

        if array[mid] == target:
            return mid
        elif array[mid] > target:
            end = mid - 1
        else:
            start = mid + 1
    return None

for i in range(m):
    if binary_search(card, check[i], 0, n - 1) is not None:
        print(1, end=' ')
    else:
        print(0, end=' ')


runFig = plt.figure()
pwrPlt = runFig.add_axes([.1,1.0, 1.8, .4])
pwrPlt.grid(color='gray', linestyle='-', linewidth=.2)

timePlt = runFig.add_axes([.1,.1,1.8,.9])
timePlt.grid(color='gray', linestyle='-', linewidth=.2)

pwrPlt.plot(drun.TIME_ELAPSED, drun["probe.heater.power"], label="probe.pwr")
pwrPlt.plot(drun.TIME_ELAPSED, drun["device.heater.power"], label="device.pwr")
pwrPlt.set_ylabel("PWR [%]")
pwrPlt.legend(loc='upper left')

timePlt.plot(drun.TIME_ELAPSED, drun.T_Probe, label="probe")
timePlt.plot(drun.TIME_ELAPSED, drun.T_Sample, label="sample")
timePlt.plot(drun.TIME_ELAPSED, drun.T03, label="device")
timePlt.set_xlabel("Czas [h]")
timePlt.set_ylabel("Temperatury [°C]")
timePlt.legend(loc='upper left')

spids = timePlt.twinx()
spids.spines['right'].set_color('red')
spids.plot(meas.TIME_ELAPSED, meas.dT, 'r|')
spids.set_ylabel("dT")

mapPrev = plt.figure()
mapScatterA = mapPrev.add_axes([.1,.1,.8,.8])
mapScatterA.scatter(meas.X, meas.Y, c=meas.Alpha)
mapScatterA.axis('equal')
mapScatterA.set_title('Mapa pogl¹dowa - Alpha')
mapScatterA.set_xlabel('x [mm]')
mapScatterA.set_ylabel('y [mm]')

mapScatterR = mapPrev.add_axes([1.1,.1,.8,.8])
mapScatterR.scatter(meas.X, meas.Y, c=meas.Resistance)
mapScatterR.axis('equal')
mapScatterR.set_title('Mapa pogl¹dowa - Rezystancja')
mapScatterR.set_xlabel('x [mm]')
mapScatterR.set_ylabel('y [mm]')


import pytest
from pygwidget.mixins import TrigonometryMixin

class TestTrigonometryMixin(object):
    mixin = TrigonometryMixin()

    @pytest.mark.parametrize('start_degree, stop_degree, expected', [
        (0, 90, 90),
        (0, 180, 180),
        (150, 180, 30),
        (330, 90, 120),
        (330, 150, 180),
        (300, 150, 210),
        (315, 225, 270),
        (330, 30, 60),
        (330, 330, 0),
        (330, 315, 345),
        (330, 360, 30),
        (330, 0, 30),
    ])
    def test_degree_distance(self, start_degree, stop_degree, expected):
        result = self.mixin.anti_clockwise_degree_distance(
            start_degree, stop_degree)
        assert expected == result

    @pytest.mark.parametrize(
        'start_degree, stop_degree, scales, scale, expected', [
            (0,  180, [0, 1, 2], 1, 90),
            (0, 180, range(0, 100, 10), 45, 90),
            (330, 180, range(0, 100, 10), 90, 330),
            (45, 135, [0, 1, 2], 1, 90),
            (330, 210, range(0, 9), 1, 180),
            (325, 215, range(0, 210, 20), 100, 90)
        ])
    def test_find_scale_degree(self, start_degree, stop_degree, scales, scale,
                               expected):
        result = self.mixin.find_scale_degree(
            start_degree, stop_degree, scales, scale)
        assert expected == result

    @pytest.mark.parametrize('degree, expected', [
        (90, 0),
        (0, -90),
        (180, 90),
        (45, -45),
        (135, 45),
        (225, 135),
        (270, -180),
        (315, -135),
        (-45, -135),
        (330, -120),
        (-30, -120)
    ])
    def test_find_rotation_angle(self, degree, expected):
        assert self.mixin.find_rotation_angle(degree) == expected


from MainClasss import *

SPEED = 1

class WithSomeone(Person):
    def __init__(self, name, image, coord, way_to_image, way_name, level, aim, camera, armor=None, type='bmp'):
        bonus = (level - 1) * level * 2
        self.camera = camera
        super().__init__(image, coord, 100 + bonus, 100 + bonus, 100, 100, name, way_to_image, way_name, armor, type)
        self.f_x_1 = self.f_x_2 = self.f_y_1 = self.f_y_2 = False
        self.count_x = 0
        self.count_y = 0
        self.aim = aim
        self.add_type('NPS')
        self.inventory = Inventory((1, 1))
        self.in_hand_index = 0
        self.point = [0, 0]
        self.new_point = False
        self.weapon = None
        self.tick = 0
        self.name = name
        self.distance = 0
        if self.name != 'Zombie':
            self.distance = 90
            self.add_type('enemy')
        self.y_v = self.x_v = 0
        self.frame_die = 0
        self.f_n_y = False
        self.die_frames = []
        for i in range(1, len(os.listdir(path=f'sprite/{way_to_image}/die/{way_name}/')) + 1):
            self.die_frames.append(Image(f'sprite/{way_to_image}/die/{way_name}/{way_name}_die_{i}.{type}'))
        self.die_tick = 0
        self.f_n_x = False
        self.add_type('NPS')
        self.die_f = False
        self.rect = Rect((self.coord[0] + 0, self.coord[1] + 25, 20, 5))
        self.c_die = False

    def get_in_hand(self):
        return self.inventory.get_items(self.in_hand_index, 0)[0]

    def set_weapon(self, weapon):
        self.weapon = weapon
        self.inventory.add_item(weapon)

    def shoot(self, aims):
        if self.weapon is not None and len(aims) > 0:
            shoot_aim = aims[0]
            distance_aim = get_gipotinuza(shoot_aim.get_coord(), self.coord)
            for aim in aims:
                distance = get_gipotinuza(self.coord, aim.get_coord())
                if distance < distance_aim:
                    shoot_aim = aim
                    distance_aim = distance
            if distance_aim <= 750:
                x, y = shoot_aim.get_coord()
                x_coord = x + (distance_aim // 7 * shoot_aim.x_vel) + 5
                y_coord = y + (distance_aim // 7 * shoot_aim.y_vel) + 10
                self.weapon.shoot(True, self, 'sprite/bullets/standard_bullet.bmp', [x_coord, y_coord])

    def update(self, bots, objects, main_group, camera):
        someone = self.aim
        self.x_vel = 0
        self.y_vel = 0
        platforms = main_group.get_object(self.camera.get_rect())
        for object in objects:
            if object.is_type('Build'):
                platforms.append(object)
        # platforms = main_group.get_object(self.rect) + objects
        # platforms.remove(self.aim)
        if not self.die_f:
            self.x_vel, self.y_vel = 0, 0
            if get_gipotinuza((self.rect.x, self.rect.y), (someone.rect.x, someone.rect.y)) > self.distance and\
                    not self.f_x_1 and not self.f_x_2 and not self.f_y_1 and not self.f_y_2:
                if self.get_coord()[0] > someone.get_coord()[0] + self.distance:
                    self.x_vel = -SPEED
                elif self.get_coord()[0] < someone.get_coord()[0] - self.distance:
                    self.x_vel = SPEED
                if self.get_coord()[1] > someone.get_coord()[1] + self.distance:
                    self.y_vel = -SPEED
                elif self.get_coord()[1] < someone.get_coord()[1] - self.distance:
                    self.y_vel = SPEED
            if self.name == 'Zombie':
                if self.rect.colliderect(someone.rect):
                    someone.damage(0.1)
            self.check_move_1(platforms)
            self.draw()
            return
        else:
            self.die_animation()

    def get_coord(self):
        return self.rect.x, self.rect.y - 25

    def get_rect(self):
        return Rect(self.rect.x, self.rect.y - 25, 20, 30)

    def mov_to_point(self, platforms, someone):
        self.x_vel = 0
        self.y_vel = 0
        if not self.die_f:
            if not self.f_x_1 and not self.f_x_2 and not self.f_y_1 and not self.f_y_2:
                if self.get_coord()[0] > self.point[0]:
                    self.x_vel = -SPEED
                elif self.get_coord()[0] < self.point[0]:
                    self.x_vel = SPEED
                if self.get_coord()[1] > self.point[1]:
                    self.y_vel = -SPEED
                elif self.get_coord()[1] < self.point[1]:
                    self.y_vel = SPEED
            self.check_move_1(platforms)
            self.coord = self.rect.x, self.rect.y
            if get_gipotinuza(self.coord, someone.coord) <= 120 and self.f_x_1 and self.f_x_2 and self.f_y_1 and \
                    self.f_y_2:
                self.point = self.coord
            self.draw()
            return
        else:
            self.die_animation()

    def die_animation(self):
        self.tick += 1
        if self.tick >= 7:
            self.tick = 0
            if self.frame_die >= len(self.die_frames) - 1:
                self.image = self.die_frames[self.frame_die].get_image()
            else:
                self.frame_die += 1
                self.image = self.die_frames[self.frame_die].get_image()
        self.die_tick += 1

    def check_move_1(self, platforms):
        self.rect.x += self.x_vel
        x = self.rect.x
        self.collide(self.x_vel, 0, platforms)
        x2 = self.rect.x
        self.rect.y += self.y_vel
        y = self.rect.y
        self.collide(0, self.y_vel, platforms)
        y2 = self.rect.y
        x_vel, y_vel = 0, 0
        if x > x2:
            self.f_x_1 = True
        elif x < x2:
            self.f_x_2 = True
        if y > y2:
            self.f_y_1 = True
        elif y < y2:
            self.f_y_2 = True
        if self.f_x_1 or self.f_x_2:
            if self.count_x >= 90:
                self.f_x_1 = self.f_x_2 = False
                self.count_x = 0
                self.f_n_x = False
            else:
                self.count_x += 1
        if self.f_y_1 or self.f_y_2:
            if self.count_y >= 90:
                self.f_y_1 = self.f_y_2 = False
                self.count_y = 0
                self.f_n_y = False
            else:
                self.count_y += 1
        if self.f_x_1 or self.f_x_2:
            if self.f_y_1:
                y_vel = SPEED
            elif self.f_y_2:
                y_vel = -SPEED
            else:
                if self.get_coord()[1] > self.point[1] and not self.f_n_x:
                    y_vel = -SPEED
                elif self.get_coord()[1] < self.point[1]:
                    self.f_n_x = True
                    y_vel = SPEED
                else:
                    self.f_n_x = True
                    y_vel = SPEED
        elif self.f_y_1 or self.f_y_2:
            if self.f_x_1:
                x_vel = SPEED
            elif self.f_x_2:
                x_vel = -SPEED
            else:
                if self.get_coord()[0] > self.point[0] and not self.f_n_y:
                    x_vel = -SPEED
                elif self.get_coord()[0] < self.point[0]:
                    self.f_n_y = True
                    x_vel = SPEED
                else:
                    self.f_n_y = True
                    x_vel = SPEED
        if x_vel != 0 or y_vel != 0:
            self.rect.x += x_vel
            x = self.rect.x
            self.collide(x_vel, 0, platforms)
            x2 = self.rect.x
            self.rect.y += y_vel
            y = self.rect.y
            self.collide(0, y_vel, platforms)
            y2 = self.rect.y
            if x_vel != 0:
                self.x_vel = x_vel
            if y_vel != 0:
                self.y_vel = y_vel
            if x > x2:
                self.f_x_1 = True
            elif x < x2:
                self.f_x_2 = True
            if y > y2:
                self.f_y_1 = True
            elif y < y2:
                self.f_y_2 = True

    def check_move_2(self, platforms):
        self.f_x_1 = self.f_x_2 = self.f_y_1 = self.f_y_2 = False
        x_vel = y_vel = 0
        move = False
        print(self.x_vel, self.y_vel, '___1___')
        self.rect.x += self.x_vel
        x = self.rect.x
        self.collide(self.x_vel, 0, platforms)
        x2 = self.rect.x
        self.rect.y += self.y_vel
        y = self.rect.y
        self.collide(0, self.y_vel, platforms)
        y2 = self.rect.y
        print(x, x2, y, y2)
        if x > x2:
            self.f_x_1 = True
        elif x < x2:
            self.f_x_2 = True
        if y > y2:
            self.f_y_1 = True
        if y < y2:
            self.f_y_2 = True
        if not self.f_x_1 and not self.f_x_2:
            self.rect.x -= self.x_vel
        if not self.f_y_1 and not self.f_y_2:
            self.rect.y -= self.y_vel
        print(self.x_v, self.y_v)
        print(self.f_x_1, self.f_x_2, self.f_y_1, self.f_y_2, '___2___')
        if self.f_x_1 or self.f_x_2:
            move = True
            if self.f_y_1 or self.f_y_2:
                if self.f_y_1:
                    print(1, '___3___')
                    y_vel = -SPEED
                elif self.f_y_2:
                    print(2, '___3___')
                    y_vel = SPEED
            elif self.y_v == 0:
                if self.y_vel == 0:
                    print(3, '___3___')
                    y_vel = random.choice([SPEED, -SPEED])
                    self.y_v = y_vel
                else:
                    print(4, '___3___')
                    y_vel = self.y_vel
                    self.y_v = self.y_vel
            elif self.y_v != 0:
                print(11, '___3___')
                y_vel = self.y_v
        else:
            if self.x_v == 0:
                x_vel = self.x_vel
                if self.f_y_1 or self.f_y_2:
                    self.x_v = self.x_vel
            else:
                x_vel = self.x_v
            print(5, '___3___')
        if self.f_y_1 or self.f_y_2:
            if not move:
                if self.f_x_1 or self.f_x_2:
                    if self.f_x_1 and x_vel == 0:
                        print(6, '___3___')
                        x_vel = -SPEED
                    elif self.f_x_2 and x_vel == 0:
                        print(7, '___3___')
                        x_vel = SPEED
                elif self.x_v == 0:
                    if self.x_vel == 0 and x_vel == 0:
                        print(8, '___3___')
                        x_vel = random.choice([SPEED, -SPEED])
                        self.x_v = x_vel
                    else:
                        if x_vel == 0:
                            print(9, '___3___')
                            x_vel = self.x_vel
                            self.x_v = self.x_vel
                elif self.x_v != 0:
                    print(12, '___3___')
                    x_vel = self.x_v
        else:
            if self.y_v == 0:
                print(1)
                y_vel = self.y_vel
                if self.f_x_1 or self.f_x_2:
                    self.y_v = self.y_vel
            else:
                y_vel = self.y_v
                print(2)
            print(10, '___3___')
        if self.x_vel != 0 and not self.f_x_1 and not self.f_x_2 and not self.f_y_1 and not self.f_y_2:
            self.y_v = self.x_v = 0
        self.x_vel = x_vel
        self.y_vel = y_vel
        print(self.x_vel, self.y_vel, '___4___')
        self.rect.x += self.x_vel
        self.collide(self.x_vel, 0, platforms)
        self.rect.y += self.y_vel
        self.collide(0, self.y_vel, platforms)

    def draw_heal_point(self, camera, screen, image):
        if self.heal_point != 0:
            rect = camera.object_coord(self.rect)
            screen.blit(image.get_image(), [rect[0] - 11, rect[1] - 19])
            pygame.draw.polygon(screen, (255, 0, 0), ((rect[0] - 10, rect[1] - 11),
                                                      (rect[0] - 10, rect[1] - 18),
                                                      (rect[0] - 10 + 57 * (self.heal_point / self.max_heal_point), rect[1] - 18),
                                                      (rect[0] - 10 + 57 * (self.heal_point / self.max_heal_point), rect[1] - 11)))

class GroupHelper:
    def __init__(self):
        pass

    def summon(self, group, object_list, quantity):
        name, image, coord, way_to_image, way_name, level, aim, camera, armor, type, range_c = object_list
        for _ in range(quantity):
            group.add_bot(WithSomeone(name, image, [coord[0] + random.choice(range(-range_c, range_c)),
                                      coord[1] + random.choice(range(-range_c, range_c))], way_to_image, way_name,
                                      level, aim, camera, armor, type))


#TITLE: 병사 배치하기 (https://www.acmicpc.net/problem/18353)
#LEVEL: S2
#TAG: dp, lis
#DATE: 20221007
#AUTHOR: squareyun

n=int(input())
a=list(map(int,input().split()))
dp=[1]*n
for i in range(1, n):
    for j in range(i):
        if a[j] > a[i]:
            dp[i] = max(dp[i], dp[j] + 1)
print(n-max(dp))


def solution(name):
    answer = 0
    # 커서 방향 결정
    joystick = [True] * len(name)

    for i in range(len(name)):
        if name[i] == 'A':
            joystick[i] = False

    cursor = 0

    while any(joystick):
        # 앞에 False가 많은지 뒤에 False가 많은지
        go, back = 0, 0

        temp = cursor + 1
        while True: # 순방향
            if temp == -1:
                temp = len(name)-1
            if temp == len(name):
                temp = 0

            if joystick[temp] == False:
                go += 1
                temp += 1
            else:
                break

        temp = cursor - 1
        while True:  # 역방향
            if temp == -1:
                temp = len(name) - 1
            if temp == len(name):
                temp = 0

            if joystick[temp] == False:
                back += 1
                temp -= 1
            else:
                break

        if go <= back: # 순방향
            joystick[cursor] = False
            answer += 1
            answer += ascii(name[cursor])
            cursor += 1
            if cursor == len(name):
                cursor = 0

        else: # 역방향
            joystick[cursor] = False
            answer += 1

            answer += ascii(name[cursor])

            cursor -= 1
            if cursor == -1:
                cursor = len(name)-1

    return answer - 1

def ascii(character):
    if character <= 'M':
        return ord(character) - ord('A')
    else:
        return ord('Z') - ord(character) + 1

print(solution("BABAAAAB"))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) oVoIndia | oVo-HxBots | RachelSaini

import asyncio, os, requests, time
from requests import post
from multiupload import anjana
from telethon.sync import events, Button
from multiupload.fsub import *
from multiupload.utils import downloader, humanbytes
from config import Config

@anjana.on(events.NewMessage(pattern='^/fileio'))
async def fileio(event):
	user_id = event.sender_id
	if event.is_private and not await check_participant(user_id, f'@{Config.CHNAME}', event):
		return
	if event.reply_to_msg_id:
		pass
	else:
		return await event.edit("Please Reply to File")

	async with anjana.action(event.chat_id, 'typing'):
		await asyncio.sleep(2)
	msg = await event.reply("**Processing...**")
	amjana = await event.get_reply_message()

	## FILEIO LIMITATION CHECKING
	if amjana.file.size > 1048576:
		return await event.edit("Oof.. File size too Large. FileIO Limitation is 100MB")

	## LOGGING TO A CHANNEL
	xx = await event.get_chat()
	reqmsg = f'''Req User: [{xx.first_name}](tg://user?id={xx.id})
FileName: {amjana.file.name}
FileSize: {humanbytes(amjana.file.size)}
#FILEIO'''
	await anjana.send_message(Config.LOG_CHANNEL, reqmsg)

	result = await downloader(
		f"downloads/{amjana.file.name}",
		amjana.media.document,
		msg,
		time.time(),
		f"**🏷 Downloading...**\n➲ **File Name:** {amjana.file.name}",
	)

	async with anjana.action(event.chat_id, 'document'):
		await msg.edit("Now Uploading to FileIO")
		url = f"https://file.io/"
		r = post(url, files={'file': open(f'{result.name}','rb')})
	await anjana.action(event.chat_id, 'cancel')

	hmm = f'''File Uploaded successfully !!
Server: FileIO

**~ File name:** __{amjana.file.name}__
**~ File size:** __{humanbytes(amjana.file.size)}__
NOTE: Once the download is complete, The file will be deleted from our servers.'''
	await msg.edit(hmm, buttons=(
		[Button.url('📦 Download', r.json()['link'])],
		[Button.url('Support Chat 💭', 't.me/hxsupport')]
		))

	os.remove(result.name)


"""
Miscellaneous utilities to read and work with the json files and such.
Stuff multiple functions use.
"""
import sys
import os
import errno
import time
import codecs, json
import logging
import tables

import numpy as np
import torch
from transformers import AutoModel

# Use mpl on remote.
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from . import predict_utils as pu
from .retrieval_models import content_profile_models

def load_aspire_config(expanded_model_name):
    """
    Given the name of a model to load, load it and return its
    json config.
    :param expanded_model_name: string of the form <dataset>/<model_name>/<run_name> which is part
        of the path to a trained model.
    """
    trained_model_path = os.path.join(os.environ['CUR_PROJ_DIR'], 'model_runs', expanded_model_name)
    with codecs.open(os.path.join(trained_model_path, 'run_info.json'), 'r', 'utf-8') as fp:
        run_info = json.load(fp)
        all_hparams = run_info['all_hparams']
    return all_hparams

def load_aspire_model(expanded_model_name):
    """
    Given the name of a model to load, load it and return its
    base bert encoder.
    :param expanded_model_name: string of the form <dataset>/<model_name>/<run_name> which is part
        of the path to a trained model.
    """
    if 'gypsum' in os.environ['CUR_PROJ_DIR']:  # This is running on unity (in interactive mode)
        trained_model_path = os.path.join('/gypsum/work1/mccallum/smysore/2021-ai2-scisim', 'model_runs', expanded_model_name)
    else:  # This is running on gypsum.
        trained_model_path = os.path.join(os.environ['CUR_PROJ_DIR'], 'model_runs', expanded_model_name)
    model_name = expanded_model_name.split('/')[1]
    with codecs.open(os.path.join(trained_model_path, 'run_info.json'), 'r', 'utf-8') as fp:
        run_info = json.load(fp)
        all_hparams = run_info['all_hparams']
        # Init model:
    if model_name in {'myspecter', 'cospecter'}:
        model = disent_models.MySPECTER(model_hparams=all_hparams)
    elif model_name in {'miswordbienc'}:
        model = disent_models.WordSentAlignBiEnc(model_hparams=all_hparams)
    elif model_name in {'sbalisentbienc'}:
        model = disent_models.WordSentAbsSupAlignBiEnc(model_hparams=all_hparams)
    model_fname = os.path.join(trained_model_path, 'model_{:s}.pt'.format('cur_best'))
    if torch.cuda.is_available():
        model.load_state_dict(torch.load(model_fname))
    else:
        model.load_state_dict(torch.load(model_fname, map_location=torch.device('cpu')))
    print(f'Loaded model: {trained_model_path}')
    return model.bert_encoder

def load_kpenc_model(expanded_model_name):
    """
    Given the name of a model to load, load it and return its
    base bert encoder.
    :param expanded_model_name: string of the form <dataset>/<model_name>/<run_name> which is part
        of the path to a trained model.
    """
    trained_model_path = os.path.join(os.environ['CUR_PROJ_DIR'], 'model_runs', expanded_model_name)
    with codecs.open(os.path.join(trained_model_path, 'run_info.json'), 'r', 'utf-8') as fp:
        run_info = json.load(fp)
        all_hparams = run_info['all_hparams']

    kp_encoder = AutoModel.from_pretrained(all_hparams['kp-base-pt-layer'])
    model_fname = os.path.join(trained_model_path, 'kp_encoder_{:s}.pt'.format('cur_best'))
    if torch.cuda.is_available():
        kp_encoder.load_state_dict(torch.load(model_fname))
    else:
        kp_encoder.load_state_dict(torch.load(model_fname, map_location=torch.device('cpu')))
    return kp_encoder

def print_sorted_dict(d, out_file):
    for k in sorted(d, key=d.get, reverse=True):
        try:
            out_file.write("{}, {}\n".format(k, d[k]))
        except UnicodeError:
            pass

def create_dir(dir_name):
    """
    Create the directory whose name is passed.
    :param dir_name: String saying the name of directory to create.
    :return: None.
    """
    # Create output directory if it doesnt exist.
    try:
        os.makedirs(dir_name)
        print('Created: {}.'.format(dir_name))
    except OSError as ose:
        # For the case of *file* by name of out_dir existing
        if (not os.path.isdir(dir_name)) and (ose.errno == errno.EEXIST):
            sys.stderr.write('IO ERROR: Could not create output directory\n')
            sys.exit(1)
        # If its something else you don't know; report it and exit.
        if ose.errno != errno.EEXIST:
            sys.stderr.write('OS ERROR: {:d}: {:s}: {:s}\n'.format(ose.errno,
                                                                   ose.strerror,
                                                                   dir_name))
            sys.exit(1)

def read_json(json_file):
    """
    Read per line JSON and yield.
    :param json_file: File-like with a next() method.
    :return: yield one json object.
    """
    for json_line in json_file:
        # Try to manually skip bad chars.
        # https://stackoverflow.com/a/9295597/3262406
        try:
            f_dict = json.loads(json_line.replace('\r\n', '\\r\\n'),
                                encoding='utf-8')
            yield f_dict
        # Skip case which crazy escape characters.
        except ValueError:
            raise

def plot_train_hist(y_vals, checked_iters, fig_path, ylabel, suffix=None):
    """
    Plot y_vals against the number of iterations.
    :param y_vals: list; values along the y-axis.
    :param checked_iters: list; len(y_vals)==len(checked_iters); the iterations
        the values in y_vals correspond to.
    :param fig_path: string; the directory to write the plots to.
    :param ylabel: string; the label for the y-axis.
    :param suffix: string; string to add to the figure filename.
    :return: None.
    """
    # If there is nothing to plot just return.
    if len(checked_iters) <= 3:
        return
    x_vals = np.array(checked_iters)
    y_vals = np.vstack(y_vals)
    plt.plot(x_vals, y_vals, '-', linewidth=2)
    plt.xlabel('Training iteration')
    plt.ylabel(ylabel)
    plt.title('Evaluated every: {:d} iterations'.format(
        checked_iters[1]-checked_iters[0]))
    plt.tight_layout()
    ylabel = '_'.join(ylabel.lower().split())
    if suffix:
        fig_file = os.path.join(fig_path, '{:s}_history-{:s}.eps'.format(ylabel, suffix))
    else:
        fig_file = os.path.join(fig_path, '{:s}_history.eps'.format(ylabel))
    plt.savefig(fig_file)
    if suffix:
        plt.savefig(os.path.join(fig_path, '{:s}_history-{:s}.png'.format(ylabel, suffix)))
    else:
        plt.savefig(os.path.join(fig_path, '{:s}_history.png'.format(ylabel)))
    plt.clf()
    logging.info('Wrote: {:s}'.format(fig_file))


import pygame

"""
The dragonfly sprite
Attributes:
    Attributes:
    window_size: the window size as a tuple
    size: size of the image
    x,y: the position of the dragonfly
    vx: the horizontal speed of the dragonfly
    vy: the vertical speed of the dragonfly
"""

# Derive your class from the Sprite super class

class Dragonfly(pygame.sprite.Sprite):
    def __init__(self, x, y, vx, vy):
        """
        :param x,y: the position of the dragonfly
        :param vx: the speed of the dragonfly
        :return: void
        """
        super().__init__();
        self.image = pygame.image.load("dragonfly.png").convert_alpha()
        self.size = self.image.get_size()

        # Required for collision detection
        # HINT: You will need this for the lab
        self.rect = self.image.get_rect()

        self.rect.x = x
        self.rect.y = y
        if x == 700:
            self.vx = -vx
            self.image = pygame.transform.rotate(self.image, 90)
        elif x == 0:
            self.vx = vx
            self.image = pygame.transform.rotate(self.image, -90)
        self.vy = vy

    def draw(self, screen):
        screen.blit(self.image, (self.rect.x, self.rect.y))

    def update(self):
        t_collide = self.rect.y + self.vy < 175
        b_collide = self.rect.y + self.image.get_height() + self.vy > 525

        # Check collision on top and bottom sides of screen
        if t_collide or b_collide:
            self.vy *= -1

        self.rect.x += self.vx
        self.rect.y += self.vy

        if self.rect.x > 750 or self.rect.x < -50:
            self.kill()

    def check_collide(self, group):
        collided = pygame.sprite.spritecollide(self, group, False)
        if len(collided) > 1:
            self.vx *= -1
            self.vy *= -1


import os
import webbrowser
from dash import Dash, html, Input, Output, callback_context

app = Dash(__name__)

app.layout = html.Div([
    html.Button('Button 1', id='btn-nclicks-1', n_clicks=0),
    html.Button('Button 2', id='btn-nclicks-2', n_clicks=0),
    html.Button('Button 3', id='btn-nclicks-3', n_clicks=0),
    html.Div(id='container-button-timestamp')
])

@app.callback(
    Output('container-button-timestamp', 'children'),
    Input('btn-nclicks-1', 'n_clicks'),
    Input('btn-nclicks-2', 'n_clicks'),
    Input('btn-nclicks-3', 'n_clicks')
)
def displayClick(btn1, btn2, btn3):
    changed_id = [p['prop_id'] for p in callback_context.triggered][0]
    if 'btn-nclicks-1' in changed_id:
        msg = 'Button 1 was most recently clicked'
    elif 'btn-nclicks-2' in changed_id:
        msg = 'Button 2 was most recently clicked'
    elif 'btn-nclicks-3' in changed_id:
        msg = 'Button 3 was most recently clicked'
    else:
        msg = 'None of the buttons have been clicked yet'
    return html.Div(msg)

# Run app
PORT = 1100
def main():

    # The reloader has not yet run - open the browser
    if not os.environ.get("WERKZEUG_RUN_MAIN"):
        webbrowser.open_new("http://localhost:{}".format(PORT))

    # Otherwise, continue as normal
    app.run(host="127.0.0.1", port=PORT)

if __name__=='__main__':
    main()

Example Implementations/PyArduino V2/More Examples/SimpleButton.py


from unittest.mock import patch
from django.test import TestCase

from corehq.apps.data_dictionary.models import (
    CaseProperty,
    CasePropertyGroup,
    CaseType,
)
from corehq.apps.reports.standard.cases.case_data import (
    _get_case_property_tables,
)

@patch('corehq.apps.reports.standard.cases.case_data.domain_has_privilege', lambda _, __: True)
class TestCaseData(TestCase):

    def setUp(self) -> None:
        self.domain = "test-dd-domain"
        self.case_type = "case-test"
        self.timezone = "Asia/Kolkata"

    def tearDown(self) -> None:
        CaseProperty.objects.all().delete()
        CasePropertyGroup.objects.all().delete()
        CaseType.objects.all().delete()

    def test_no_data_dictionary(self):
        dynamic_data = {"prop1": None, "prop2": None}
        result = _get_case_property_tables(self.domain, self.case_type, dynamic_data, self.timezone)
        self._assert_grouping_order_tables(result, [{"name": None, "properties": ["prop1", "prop2"]}])

    def test_dd_ordering_when_single_group(self):
        """
        Tests that when a data dictionary contains only one user defined group,
        properties within the group is retained.
        """
        # Create group1 properties
        self._create_case_property("prop1", "group1")
        self._create_case_property("prop2", "group1")
        result = _get_case_property_tables(self.domain, self.case_type, {}, self.timezone)
        self._assert_grouping_order_tables(result, [{"name": "group1", "properties": ["prop1", "prop2"]}])

    def test_dd_ordering_when_multiple_groups(self):
        """
        Tests that when a data dictionary contains multiple user defined groups,
        ordering of groups and properties within the group is retained.
        """
        # Create group1 properties
        self._create_case_property("prop1", "group1")
        self._create_case_property("prop2", "group1")
        self._create_case_property("prop3", "group2")
        self._create_case_property("prop4", "group2")
        result = _get_case_property_tables(self.domain, self.case_type, {}, self.timezone)
        self._assert_grouping_order_tables(result, [{"name": "group1", "properties": ["prop1", "prop2"]},
                                                    {"name": "group2", "properties": ["prop3", "prop4"]}])

    def test_dd_ordering_when_multiple_groups_and_unrecognized_group(self):
        """
        Tests that when a data dictionary contains multiple user defined groups and a unrecognized group,
        ordering of groups and properties within the group is retained. Ordering is not retained in
        unrecognized group.
        """
        # Create group1 properties
        self._create_case_property("prop1", "group1")
        self._create_case_property("prop2", "group1")
        self._create_case_property("prop3", "group2")
        self._create_case_property("prop4", "group2")

        # Dynamic data with additional property not present in any of the groups
        dynamic_data = {"prop1": None, "prop2": None, "prop3": None, "prop4": None, "prop5": None, "prop6": None}

        result = _get_case_property_tables(self.domain, self.case_type, dynamic_data, self.timezone)
        self._assert_grouping_order_tables(result, [{"name": "group1", "properties": ["prop1", "prop2"]},
                                                    {"name": "group2", "properties": ["prop3", "prop4"]},
                                                    {"name": "Unrecognized", "properties": ["prop5", "prop6"]}
                                                    ])

    def _assert_grouping_order_tables(self, result, expected_result):
        """
        Sample result
        [{'name': 'group1', 'rows': [[{'expr': 'prop1', 'name': 'prop1', 'description': '', 'value': '---',
        'has_history': True}, {'expr': 'prop2', 'name': 'prop2', 'description': '', 'value': '---',
        'has_history': True}]]}, {'name': 'group2', 'rows': [[{'expr': 'prop3', 'name': 'prop3',
        'description': '', 'value': '---', 'has_history': True}, {'expr': 'prop4', 'name': 'prop4',
        'description': '', 'value': '---', 'has_history': True}]]}]
        """
        for group_data, expected_group_data in zip(result, expected_result):
            group_name_actual = group_data.get("name")
            group_name_expected = expected_group_data.get("name")
            self.assertEqual(group_name_expected, group_name_actual)
            rows_actual = group_data.get("rows")[0]
            props_actual = [prop.get("name") for prop in rows_actual]
            if not group_name_actual or group_name_actual == "Unrecognized":
                # Ordering of properties in unrecognized group is not user defined
                self.assertEqual(set(expected_group_data.get("properties")), set(props_actual))
            else:
                self.assertEqual(expected_group_data.get("properties"), props_actual)

    def _create_case_property(self, prop_name, group=None):
        case_type_obj = CaseType.get_or_create(self.domain, self.case_type)
        group_obj = None
        if group:
            group_obj, _ = CasePropertyGroup.objects.get_or_create(name=group, case_type=case_type_obj)
        CaseProperty.objects.get_or_create(case_type=case_type_obj, name=prop_name, group=group_obj)


from datetime import timedelta
from operator import eq

from pyphonetics.distance_metrics import levenshtein_distance
from couchdbkit.ext.django.schema import (
    DecimalProperty,
    ListProperty,
    StringProperty,
)
from dateutil.parser import parse as parse_date

from dimagi.ext.couchdbkit import DocumentSchema

def le_days_diff(max_days, date1, date2):
    """
    Returns True if date1 is less than or equal to max_days away from
    date2, otherwise returns False

    >>> from datetime import date
    >>> le_days_diff(364, '2018-01-01', '2017-01-20')
    True
    >>> le_days_diff(364, date(2017, 1, 20), date(2018, 1, 1))
    True
    >>> le_days_diff(364, '2018-01-01', '2020-01-20')
    False

    """
    if isinstance(date1, str):
        date1 = parse_date(date1)
    if isinstance(date2, str):
        date2 = parse_date(date2)
    return abs(date1 - date2) <= timedelta(max_days)

def le_levenshtein_percent(percent, string1, string2):
    """
    Returns True if Levenshtein distance between string1 and string2,
    divided by max length, is less than or equal to the given percent.

    :param percent: Percent expressed as a decimal between 0 and 1
    :param string1: First string to compare
    :param string2: Second string to compare
    :return: True or False

    >>> le_levenshtein_percent(0.2, 'Riyaz', 'Riaz')
    True
    >>> le_levenshtein_percent(0.2, 'Riyaz', 'Riazz')
    False

    """
    if not 0 <= percent < 1:
        raise ValueError('percent must be greater that or equal to 0 and less than 1')
    dist = levenshtein_distance(string1, string2)
    max_len = max(len(string1), len(string2))
    return dist / max_len <= percent

MATCH_TYPE_EXACT = 'exact'
MATCH_TYPE_LEVENSHTEIN = 'levenshtein'  # Useful for words translated across alphabets
MATCH_TYPE_DAYS_DIFF = 'days_diff'  # Useful for estimated dates of birth
MATCH_FUNCTIONS = {
    MATCH_TYPE_EXACT: eq,
    MATCH_TYPE_LEVENSHTEIN: le_levenshtein_percent,
    MATCH_TYPE_DAYS_DIFF: le_days_diff,
}
MATCH_TYPES = tuple(MATCH_FUNCTIONS)
MATCH_TYPE_DEFAULT = MATCH_TYPE_EXACT

class PropertyWeight(DocumentSchema):
    case_property = StringProperty()
    weight = DecimalProperty()
    match_type = StringProperty(required=False, choices=MATCH_TYPES, default=MATCH_TYPE_DEFAULT)
    match_params = ListProperty(required=False)


import time
from tawhiri.wind import Dataset

d = Dataset()
d.open_dataset("/home/adam/Projects/tawhiri/datasets", 2014, 2, 3, 6)
h = d.get_pressure_heights(10.0, 52.2, 0.2)

n_repeats = 100000
t0 = time.time()
for _ in range(n_repeats):
    d.get_wind(10.0, 12345.0, 52.2, 0.2, pressure_heights=h)
t1 = time.time()

print("Average {:.6f}s".format((t1 - t0) / n_repeats))


from django import forms
from . import models

class Rsvp_Form(forms.ModelForm):

    class Meta:
        model = models.rsvp
        fields = [
            'full_name',
            'email',
            'please_check_if_you_are_able_to_attend',
            'number_attending',
            'message_for_the_happy_couple'
        ]


import numpy as np
import pickle
import glob
import os
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(palette="colorblind")
# sns.set()

class MetaLogger:
    """
    Logs the way we like. Maybe should go in the plotting folder because they go together.
    """
    def __init__(self, logging_directory) -> None:
        super().__init__()
        self._logging_directory = logging_directory
        os.makedirs(logging_directory, exist_ok=True)
        self._logging_values = {}
        self._filenames = {}

    def add_field(self, field_name, filename):
        assert isinstance(field_name, str)
        assert field_name != ""
        for char in [" ", "/", "\\"]:
            assert char not in field_name

        folder_name = os.path.join(self._logging_directory, field_name)
        os.makedirs(folder_name, exist_ok=True)
        print(f"Successfully created the directory {folder_name}")

        full_path = os.path.join(folder_name, filename)
        self._filenames[field_name] = full_path

        assert field_name not in self._logging_values

        self._logging_values[field_name] = []

    def append_datapoint(self, field_name, datapoint, write=False):
        self._logging_values[field_name].append(datapoint)
        if write:
            self.write_field(field_name)

    def write_field(self, field_name):
        full_path = self._filenames[field_name]
        values = self._logging_values[field_name]
        with open(full_path, "wb+") as f:
            pickle.dump(values, f)

    def write_all_fields(self):
        for field_name in self._filenames.keys():
            self.write_field(field_name)

def get_scores(log_dir, subdir="scores", only_longest=False, min_length=-1, cumulative=False):
    longest = 0
    print(log_dir)
    overall_scores = []
    glob_pattern = log_dir + "/" + subdir + "/" + "*.pkl"
    for score_file in glob.glob(glob_pattern):
        with open(score_file, "rb") as f:
            scores = pickle.load(f)
        if only_longest:
            if len(scores) > longest:
                overall_scores = [scores]
                longest = len(scores)
        else:
            if len(scores) >= min_length:  # -1 always passes!
                overall_scores.append(scores)

    if len(overall_scores) == 0:
        raise Exception("No scores in " + log_dir)

    min_length = min(len(s) for s in overall_scores)

    overall_scores = [s[:min_length] for s in overall_scores]

    score_array = np.array(overall_scores)
    # print(score_array.shape)
    if cumulative:
        score_array = np.cumsum(score_array, axis=1)
    return score_array

def get_plot_params(array):
    median = np.median(array, axis=0)
    means = np.mean(array, axis=0)
    std = np.std(array, axis=0)
    N = array.shape[0]
    top = means + (std / np.sqrt(N))
    bot = means - (std / np.sqrt(N))
    return median, means, top, bot

def moving_average(a, n=25):
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n

def smoothen_data(scores, n=10):
    print(scores.shape)
    smoothened_cols = scores.shape[1] - n + 1
    smoothened_data = np.zeros((scores.shape[0], smoothened_cols))
    for i in range(scores.shape[0]):
        smoothened_data[i, :] = moving_average(scores[i, :], n=n)
    return smoothened_data

def generate_plot(score_array, label, smoothen=False,color=None, linewidth=8):
    if smoothen:
        print('bingbingbing')
        smooth_amount = 15 if isinstance(smoothen, bool) else smoothen
        print(smooth_amount)
        score_array = smoothen_data(score_array, n=smooth_amount)
    median, mean, top, bottom = get_plot_params(score_array)
    # plt.plot(mean, linewidth=2, label=label, alpha=0.9)
    # plt.fill_between(range(len(top)), top, bottom, alpha=0.2)
    if color is not None:
        plt.plot(mean, linewidth=linewidth, label=label, alpha=0.9, c=color)
        plt.fill_between(range(len(top)), top, bottom, alpha=0.35, color=color)
    else:
        plt.plot(mean, linewidth=linewidth, label=label, alpha=0.9)
        plt.fill_between(range(len(top)), top, bottom, alpha=0.35)


#!iaskdata/bin/python
# -*- coding: utf8 -*-

from datetime import datetime, timedelta
from config import BASEDIR
from app import app, db
from app.models import BaseUser, Customer, Expert, Topic, Category, TopicRequest, Comment
from app.model_utils import *

def build_topic_1():
    test_topic_1 = Topic(
	topic_id = 1,
        body = 'Our company needs a real-time recommendation system, who can help us?',
        title = u'推荐系统求助',
        created_time = datetime.utcnow(),
        rate = 100.0,
        expert_id = 101
    )
    return test_topic_1

def build_topic_2():
    test_topic_2 = Topic(
	topic_id = 2,
        body = 'A VR company is seeking computer vision experts',
        title = u'VR & AR',
        created_time = datetime.utcnow(),
        rate = 150.0,
        expert_id = 101
    )
    return test_topic_2

def build_customer_1():
    return Customer(
        user_id = 1,
        email = 'larry@iaskdata.com',
        last_seen = datetime.utcnow(),
        name = 'larry',
        company = 'google',
        title = 'CEO',
        about_me = 'i love my job',
        avatar_thumbnail_url = 'thumbnail',
        avatar_url = 'image',
        phone_number = '13880089000'
    )

def build_customer_2():
    return Customer(
        user_id = 2,
        email = 'zuck@iaskdata.com',
        last_seen = datetime.utcnow(),
        name = 'zuck',
        company = 'facebook',
        title = 'CEO',
        about_me = 'i love my job',
        avatar_thumbnail_url = 'thumbnail',
        avatar_url = 'image',
        phone_number = '13880089001'
    )

def build_customer_3():
    return Customer(
        user_id = 3,
        email = 'jack@iaskdata.com',
        last_seen = datetime.utcnow(),
        name = 'jack',
        company = 'Twitter',
        title = 'CEO',
        about_me = 'i love my job',
        phone_number = '13880089002'
    )

def build_expert_1():
    return Expert(
        user_id = 101,
        email = 'andrewng@iaskdata.com',
        last_seen = datetime.utcnow(),
        name = 'Andrew NG',
        company = 'Coursera',
        title = 'Founder',
        about_me = 'I am just GOOOOD',
        degree = 'Ph.D.',
        university = 'Stanford University',
        major = 'Computer Science',
        rating = 4.9,
        bio = 'I graduated from the best university and I created the best company in the field',
        credits = 5
    )

def build_category_1():
    category_id = build_category_id(1, 2)
    return Category(category_id = category_id)

def build_category_2():
    category_id = build_category_id(1, 3)
    return Category(category_id = category_id)

def build_comment_1():
    return Comment(
        comment_id = 1,
    	content = 'this guy is really good at his major',
        request_id = 1,
        rating = 4.6
    )

def build_comment_2():
    return Comment(
        comment_id = 2,
    	content = 'bravo, this expert really knows his field',
        request_id = 2,
        rating = 4.8
    )

def build_topic_request_1():
    return TopicRequest(
        request_id = 1,
        customer_id = 1,
        topic_id = 1,
        request_stage = 0,
    	topic_requested_time = datetime.utcnow(),
    	topic_accepted_time = datetime.utcnow(),
        topic_paid_time = datetime.utcnow(),
        topic_scheduled_time = datetime.utcnow(),
        topic_served_time = datetime.utcnow(),
        topic_rated_time = datetime.utcnow()
    )

def build_topic_request_2():
    return TopicRequest(
        request_id = 2,
        customer_id = 2,
        topic_id = 1,
        request_stage = 0,
    	topic_requested_time = datetime.utcnow(),
    	topic_accepted_time = datetime.utcnow(),
        topic_paid_time = datetime.utcnow(),
        topic_scheduled_time = datetime.utcnow(),
        topic_served_time = datetime.utcnow(),
        topic_rated_time = datetime.utcnow()
    )


# encoding: utf-8
"""The main interface for working with the ISLE dictionary."""

import copy
import os
from typing import List, Optional, Tuple, Iterable, Union, Dict, Generator
from typing_extensions import Literal

from pysle.utilities import constants
from pysle.utilities import errors
from pysle.utilities import utils
from pysle.utilities import phonetic_constants
from pysle.utilities import isle_io
from pysle.utilities import search
from pysle import phonetics

def sequenceMatch(matchChar: str, searchStr: str) -> bool:
    """Does marchChar appear in searchStr?"""
    return matchChar in searchStr

class Isle:
    """The interface for working with ISLEdict.txt

    Pysle comes with ISLEdict.txt installed but you may specify
    a custom dictionary to search with instead.  Please see README.md
    for more information about obtaining an original copy.
    """

    def __init__(self, islePath: Optional[str] = None):
        """The constructor for isle

        Creating an instance of Isle() will load Isle into memory
        which can take time.

        Args:
            islePath: the path to an islex dictionary.  If None, the
                original islex will be used.
        """
        if not islePath:
            islePath = constants.DEFAULT_ISLE_DICT_PATH
        elif not os.path.exists(islePath):
            raise errors.IsleDictDoesNotExistError()

        self.rawData = self._load(islePath)
        self.data: Dict[str, List[phonetics.Entry]] = {}

    def _load(self, islePath) -> Dict[str, List[str]]:
        print("Text")
        return isle_io.readIsleDict(islePath)

    def _lazyLoad(self, word: str) -> List[phonetics.Entry]:
        """Fetches entries for a word; if not parsed yet, parses the original text"""

        entries = self.data.get(word)
        if not entries:
            lazyLoadedEntries: List[phonetics.Entry] = []

            lines = self.rawData.get(word)
            if lines is None:
                raise errors.WordNotInIsleError(word)

            for rawIsleLine in lines:
                entryAsHash = isle_io.parseIslePronunciation(word, rawIsleLine)
                entry = phonetics.Entry(
                    entryAsHash["word"],
                    entryAsHash["syllabificationList"],
                    entryAsHash["posList"],
                )
                lazyLoadedEntries.append(entry)

            self.data[word] = lazyLoadedEntries
            return lazyLoadedEntries
        else:
            return entries

    def getEntries(self) -> Iterable[phonetics.Entry]:
        """Iterates through the isle dictionary

        Yields:
            individual entries in alphabetical order
        """
        for word in self.rawData.keys():
            for entry in self._lazyLoad(word):
                yield entry

    def lookup(self, word: str) -> List[phonetics.Entry]:
        """
        Lookup a word and receive a list of syllables and stressInfo

        Output example for the word 'another' which has two pronunciations
        [
            [Syllabification(syllables=[['ə'], ['n', 'ʌ'], ['ð', 'ɚ']], stressedSyllables=[1], stressedPhones=[1])],
            [Syllabification(syllables=[['ə'], ['n', 'ʌ'], ['ð', 'ə', 'ɹ']], stressedSyllables=[1], stressedPhones=[1])]
        ]

        Args:
            word: the word to lookup

        Returns:
            A list of entries; each entry is unique for a word, pronunciation pair

        Raises:
            WordNotInIsleError: The word was not in the Isle dictionary
        """
        word = word.lower().strip()

        return self._lazyLoad(word)

    def getLength(self, word: str, maxFlag: bool) -> Tuple[float, float]:
        """
        Get the number of syllables and phones in this word

        Args:
            word: the word to lookup
            maxFlag: if True, use the longest pronunciation of all matching entries.
                If False, use the average length

        Returns:
            a tuple containing the number of syllables and number of phones
        """
        phoneCount = 0.0
        syllableCount = 0.0

        syllableCountList = []
        phoneCountList = []

        entries = self.lookup(word)
        for entry in entries:
            syllableList = []
            phoneList = []
            for syllabification in entry.syllabificationList:
                syllableList.extend(syllabification.syllables)
                phoneList.extend(syllabification.desyllabify().phonemes)

            syllableCountList.append(len(syllableList))
            phoneCountList.append(len(phoneList))

        # The average number of phones for all possible pronunciations
        #    of this word
        if maxFlag is True:
            syllableCount += max(syllableCountList)
            phoneCount += max(phoneCountList)
        else:
            syllableCount += sum(syllableCountList) / float(len(syllableCountList))
            phoneCount += sum(phoneCountList) / float(len(phoneCountList))

        return syllableCount, phoneCount

    def contains(self, word: str) -> bool:
        """Check if a word exists in the isle dictionary"""
        try:
            self.lookup(word)
        except errors.WordNotInIsleError:
            return False
        else:
            return True

    def findBestSyllabification(
        self, word: str, phoneList: Union[phonetics.PhonemeList, List[str]]
    ) -> phonetics.Syllabification:
        """
        Find the best syllabification for a word

        First find the closest pronunciation to a given pronunciation. Then take
        the syllabification for that pronunciation and map it onto the
        input pronunciation.

        Args:
            word: the word to lookup
            phoneList: the phonemes to syllabify

        Returns:
            a syllabified version of the input phoneList

        Raises:
            WordNotInIsleError: The word was not in the Isle dictionary
        """
        phoneList = phonetics._toPhonemeList(phoneList)

        try:
            entries = self.lookup(word)
        except errors.WordNotInIsleError:
            # Many words are in the dictionary but not inflected forms
            # like the possesive (eg bob's)
            # If the word could not be found, try dropping the 's
            # and try searching again.
            if len(word) < 2:
                raise

            head = word[:-2]
            tail = word[-2:]
            if tail != "'s":
                raise

            entries = self.lookup(head)

            # Add the 's' sound to each word
            # TODO: don't mutate to avoid deepcopy() call
            modifiedIsleWordList = []
            for entry in entries:
                entry = copy.deepcopy(entry)
                tailSyllabification = entry.syllabificationList[-1]
                finalSyllable = tailSyllabification.syllables[-1]
                lastSound = finalSyllable.phonemes[-1]

                if lastSound in phonetic_constants.alveolars:
                    finalSyllable.phonemes.append("ɪ")
                if lastSound in phonetic_constants.unvoiced:
                    finalSyllable.phonemes.append("s")
                else:
                    finalSyllable.phonemes.append("z")

                modifiedIsleWordList.append(entry)
            entries = modifiedIsleWordList

        return phoneList.findBestSyllabification(entries)

    def findClosestPronunciation(
        self, word: str, phoneList: Union[phonetics.PhonemeList, List[str]]
    ) -> phonetics.Entry:
        """
        Find the closest dictionary pronunciation to a provided pronunciation
        """
        phoneList = phonetics._toPhonemeList(phoneList)
        candidateEntries = self.lookup(word)

        return phoneList.findClosestEntry(candidateEntries)

    def transcribe(
        self,
        sentenceTxt: str,
        preference: Optional[Literal["longest", "shortest"]] = None,
    ) -> str:
        """
        Can be used to generate a hypothetical pronunciation for a sequence of words

        Args:
            sentenceTxt: a sequence of words separated by space e.g. 'Hello world'
            preference: if 'shortest', or 'longest', the appropriate option will be
                picked (based on phone length); otherwise, the first option will
                be picked

        Returns:
            a sequence of IPA characters, separated by space for each word
            e.g. 'hɛloʊ wɜrld'
        """

        if preference:
            utils.validateOption("preference", preference, constants.LengthOptions)

        transcribedWordsList: List[phonetics.PhonemeList] = []
        wordList = sentenceTxt.split(" ")
        for word in wordList:
            entries = self.lookup(word)

            phoneListsOrderedByEntry = [
                syllabification.desyllabify()
                for entry in entries
                for syllabification in entry.syllabificationList
            ]
            numPhones = [len(phoneList) for phoneList in phoneListsOrderedByEntry]

            i = 0
            if preference == constants.LengthOptions.SHORTEST:
                i = numPhones.index(min(numPhones))
            elif preference == constants.LengthOptions.LONGEST:
                i = numPhones.index(max(numPhones))

            transcribedWordsList.append(phoneListsOrderedByEntry[i])

        def cleanPron(pron):
            for val in ["ˈ", "ˌ", " "]:
                pron = pron.replace(val, "")
            return pron

        words: List[str] = [
            " ".join(phoneList.phonemes) for phoneList in transcribedWordsList
        ]
        words = [cleanPron(phones) for phones in words]

        return " ".join(words)

    def search(
        self,
        searchString: str,
        numSyllables: Optional[int] = None,
        wordInitial: Literal["ok", "only", "no"] = "ok",
        wordFinal: Literal["ok", "only", "no"] = "ok",
        spanSyllable: Literal["ok", "only", "no"] = "ok",
        stressedSyllable: Literal["ok", "only", "no"] = "ok",
        multiword: Literal["ok", "only", "no"] = "ok",
        pos: Optional[str] = None,
        exactMatch: bool = False,
        randomize: bool = False,
    ) -> Generator[Dict[str, str], None, None]:
        """Search for isledict entries based on pronunciation

        wordInitial, wordFinal, spanSyllable, stressedSyllable, and multiword
        can take three different values: 'ok', 'only', or 'no'. For example,
        if spanSyllable is 1) 'ok' then searches will include matches that
        span or do not span syllables.  if 2) 'only', then matches that do
        span syllables are included but matches within syllables are not
        included. if 3) 'no' then matches that span syllables are not
        included but matches within are.

        Special search characters:
        'D' - any dental; 'F' - any fricative; 'S' - any stop
        'V' - any vowel; 'N' - any nasal; 'R' - any rhotic
        '#' - word boundary
        'B' - syllable boundary
        '.' - anything

        For example, 'DV.' would search for the three character:
        'dental, vowel, anything'

        For advanced queries:
        Regular expression syntax applies, so if you wanted to search for any
        word ending with a vowel or rhotic, matchStr = '(?:VR)#', '[VR]#', etc.

        Args:
            searchString: the text to search for
            numSyllables: return results with the given number of syllables
            wordInitial: return matches that occur in word-initial position
            wordFinal: return matches that occur in word-final position
            spanSyllable: return matches that span across syllables
            stressedSyllable: return matches that are in stressed position
            multiword: return matches that are composed of multiple words
            pos: a tag in the Penn Part of Speech tagset
                see isletool.phonetics.posList for the full list of possible tags
            exactMatch: match only the exact pronunciation (ignoring stress,
                 syllable markers, etc)
            randomize: randomize the search order (useful if you are only looking for
                a few results)

        Returns:
            a generator for iterating through results

        """

        # Prep the data for searching
        wordInfoList = []
        for word, lines in self.rawData.items():
            for line in lines:
                posStart = line.find("(")
                posEnd = line.find(")", posStart)
                wordStart = line.find("#", posEnd)

                posList = line[posStart + 1 : posEnd]
                wordInfoList.append(
                    {
                        "word": word,
                        "posList": posList,
                        "pronunciation": line[wordStart:],
                    }
                )

        for matchedWordInfo in search.search(
            wordInfoList,
            searchString,
            numSyllables,
            wordInitial,
            wordFinal,
            spanSyllable,
            stressedSyllable,
            multiword,
            pos,
            exactMatch,
            randomize,
        ):
            yield matchedWordInfo

def autopair(isle: Isle, words: List[str]) -> Tuple[List[List[str]], List[int]]:
    """
    Joins adjacent words, if their combination is in the

    It returns complete wordLists with the matching words replaced.
    Each match yields one sentence.

    e.g. (assuming 'red_ball' and 'ball_chaser' are both in isle)
    ```python
    x = ['red', 'ball', 'chaser']
    print(autopair(isle, x))
    >> [['red_ball', 'chaser'], ['red', 'ball_chaser']], [0, 1]
    ```

    Args:
        isle: an instance of Isle
        words: a list of words

    Returns:
        a list of potential matching sentences and a corresponding list of indicies,
        where each index is the starting word where the match was found
    """

    # TODO: Is this method unnecessarily complex?  Maybe we can just return a list
    #       of all adjacent pairs that are in isle?
    # TODO: Can be '-' or '_'
    newWordList = [
        ("%s_%s" % (words[i], words[i + 1]), i) for i in range(0, len(words) - 1)
    ]

    sentenceList = []
    indexList = []
    for word, i in newWordList:
        if word in isle.rawData:
            sentenceList.append(
                words[:i]
                + [
                    word,
                ]
                + words[i + 2 :]
            )
            indexList.append(i)

    return sentenceList, indexList

def findOODWords(isle: Isle, wordList: List[str]) -> List[str]:
    """
    Returns all of the unique out-of-dictionary words found in a list
    """
    oodList = []
    for word in wordList:
        if not isle.contains(word):
            oodList.append(word)

    oodList = list(set(oodList))
    oodList.sort()

    return oodList


#! /usr/bin/env python3

import sys
sys.path.insert(0, 'aima')

import copy
import math
import search

class ASARProblem(search.Problem):
    """Airline Scheduling and Routing Problem"""

    def __init__(self):
        """ """

    def load(self, fh):
        """Receives an opened file, loads the information and initializes
        the problem."""
        # split the file into lines
        lines = fh.read().splitlines()

        # removes blank lines
        file = list(filter(None, lines))
        a, p, l, c = ({} for i in range(4))

        # Separates the file information according to the first letter in each line
        for string in file:
            if string[0] == "A":  # Airport information
                ax = string[2:].split()
                a.update({ax[0]: tuple(ax[1:])})

            elif string[0] == "P":  # Planes class
                px = string[2:].split()
                p.update({px[0]: px[1]})

            elif string[0] == "L":  # Legs information
                lx = string[2:].split()
                l.update({tuple(lx[0:2]): tuple(lx[2:])})

            elif string[0] == "C":  # Planes rotation time information
                cx = string[2:].split()
                c.update({cx[0]: cx[1]})
        # Saves the problem information in problem attributes
        self.a = a
        self.p = p
        self.l = l
        self.c = c
        self.nodes = 1

        planes_list = []  # initially we don't have a plane and airport defined. The algorithm takes care of that
        for key in p:
            planes_list.append(key)
        planes = dict(zip(planes_list, [None] * len(planes_list)))
        legs = list(l.keys())

        self.initial = StateDict(legs, planes, 0, self.nodes) # initial state of the problem

        return self

    def actions(self, state):
        """Return the actions that can be executed in the given
        state. The result would typically be a list, but if there are
        many actions, consider yielding them one at a time in an
        iterator, rather than building them all at once."""
        # actions is a list with [airplane, departure location, arrival location]
        actions = []
        #sate.planes keeps the information for each plane, i.e. in which airport each plane is and the time it leaves that airport
        for (airplane, info) in state.planes.items():
            # if the plane does not have yet a first leg / first airport defined all legs that comply with time constraint are ellectable
            if info == None:
                for leg in state.legs:
                    fligh_duration = self.l[leg][0]
                    arrival = state.time_sum(self.a[leg[0]][0],
                                             fligh_duration)  # check if the arrival time is after the closing time of the airport
                    if arrival <= self.a[leg[1]][1] and arrival >= self.a[leg[1]][
                        0]:  # arrival of aircraft > closing time arrival > opening time
                        actions.append([airplane, leg[0], leg[1]])
            else:
                flag = 0
                # check if it's possible to finish the all legs in the starting airport. if not, no actions are ellectable
                for leg in state.legs:
                    if state.schedule[airplane][1] == leg[1]:
                        flag = 1
               # ellect legs that comply with time constraints and where the departure airport matches with our current state airport
                if flag == 1:
                    for leg in state.legs:
                        if leg[0] == info[
                            1]:  # Check if the leg departure airport is equal to the state airport departure for that aricraft
                            if info[0] <= self.a[info[1]][1] and info[0] >= self.a[info[1]][
                                0]:  # departure is before closing time of the airport
                                fligh_duration = self.l[leg][0]
                                arrival = state.time_sum(info[0],
                                                         fligh_duration)  # check if the arrival time is after the closing time of the airport
                                if arrival <= self.a[leg[1]][1] and arrival >= self.a[leg[1]][
                                    0]:  # arrival of aircraft > closing time
                                    actions.append([airplane, leg[0], leg[1]])
        return actions

    def result(self, state, action):
        """Return the state that results from executing the given
        action in the given state. The action must be one of
        self.actions(state)."""

        new_state = copy.deepcopy(state) # copies the current state info. new_state is the next generated state

        if len(new_state.legs) > 0:
            airplane_code = action[0] # name of the plane used in the current action

            airplane_type = self.p[airplane_code]  # class of the airplane. ex: a320
            protation_time = self.c[airplane_type] # rotation time for that type of plane

            # if the starting airport is not defined yet, we say the departure will happen when the airport opens and define the departure airport according to the leg
            if new_state.planes[action[0]] == None:
                departure = self.a[action[1]][0]
                new_state.planes[action[0]] = [None] * 2
                new_state.planes[action[0]][0] = departure
                new_state.planes[action[0]][1] = action[1]
            else:
                departure = new_state.planes[airplane_code][0]

            flight_duration = self.l[tuple(action[1:])][0]

            arrival = state.time_sum(departure, flight_duration)

            new_state.planes[airplane_code] = ["", ""]
            new_state.planes[airplane_code][0] = new_state.time_sum(arrival,
                                                                    protation_time)  # new time of departure, airplane is added to dictionary

            new_state.planes[airplane_code][1] = action[2]  # new departure airport

            new_state.legs.remove(tuple(action[1:]))  # remove leg already used from list of legs

            leg = tuple(action[1:3])

            index_cost = self.l[leg].index(airplane_type) + 1
            link_cost = self.l[leg][index_cost] # profit to do that specific leg

            new_state.profit = new_state.profit + int(link_cost) # update of total profit

            if airplane_code in new_state.schedule:  # check if it is the first flight
                new_state.schedule[airplane_code].append(departure)
                new_state.schedule[airplane_code].append(action[1])
                new_state.schedule[airplane_code].append(action[2])

            else:
                new_state.schedule.update({airplane_code: [departure, action[1], action[2]]})

        self.nodes = self.nodes + 1
        new_state.code = self.nodes
        return new_state

    def goal_test(self, state):
        # estado inicial igual ao estado final e lista de legs vazia
        """Return True if the state is a goal. The default method compares the
        state to self.goal or checks for state in self.goal if it is a
        list, as specified in the constructor. Override this method if
        checking against a single self.goal is not enough."""
        # if we don't have more legs to do and the end airport corresponds to the star airport the state is a goal
        if not state.legs:

            for (airplane, info) in state.planes.items():
                if info != None:
                    if info[1] != state.schedule[airplane][1]:
                        return False
            return True
        else:
            return False

    def path_cost(self, c, state1, action, state2):
        """Return the cost of a solution path that arrives at state2 from
        state1 via action, assuming cost c to get up to state1."""

        leg = tuple(action[1:3])
        airplane_type = self.p[action[0]]

        index_cost = self.l[leg].index(airplane_type) + 1
        link_cost = self.l[leg][index_cost]

        #cost is given by the accumulation of the inverse of the profit
        cost = c + (1 / float(link_cost))
        return cost

    def heuristic(self, n):
        """ """
        state = n.state
        if self.goal_test(state):  # goal state --> heuristic = 0
            return 0
        est_cost = 0

        if not state.legs:
            return 0

        # sum the max profit of each leg for all legs. That sum give us the heuristic
        for leg in state.legs:
            plane_profit = self.l[leg][1:]
            profit = plane_profit[1::2]
            value = 0
            for x in profit:
                if int(x) > value:
                    value = int(x)
            est_cost = est_cost + value
        h = int(est_cost)
        return h

    def save(self, fh, state):
        """Writes the solution of the problem, if exists."""
        if state != None:  # Verifies if the problem is feasible
            for airplane in state.schedule:
                fh.write("S " + airplane + " ")
                sp = str(state.schedule[airplane])
                sp = sp.replace(',', '').replace('[', '').replace(']', '').replace('\'', '')
                fh.write(sp + "\n")

            fh.write("P " + str(state.profit))
        else:
            fh.write("Infeasible")  # Case where the problem is infeasible.
        return

class StateDict(dict):
    """State Class - Definition of a State"""

    def __init__(self, legs, planes, profit, code):
        """State initialization."""
        self.legs = legs  # Available legs
        self.profit = 0  # State profit
        self.planes = planes  # Planes location and current time
        self.schedule = {}  # State schedule
        self.code = code  # State code

    def print_state(self):
        """Prints state attributes."""
        print("PLANES INFO " + str(self.planes))
        print("LEGS LEFT " + str(self.legs))
        print("PLANES SCHEDULES " + str(self.schedule))
        print("PROFIT " + str(self.profit))
        print("CODE " + str(self.code))
        return

    def __hash__(self):
        return hash(self.code)

    def __lt__(self, other):
        t1 = self.schedule, self.legs, self.profit, self.planes
        t2 = other.schedule, other.legs, other.profit, other.planes
        return self.code < other.code

    def __eq__(self, other):
        return self.schedule == other.schedule and self.legs == other.legs and self.profit == other.profit and self.planes == other.planes

    def time_sum(self, time1, time2):
        """Time calculator using string data."""
        h = int(time1[0:2]) + int(time2[0:2])
        m = int(time1[2:4]) + int(time2[2:4])

        if m >= 60:
            m = m - 60
            h = h + 1
        if h < 10:
            time = "0" + str(h)
        else:
            time = str(h)
        if m < 10:
            time = time + "0" + str(m)
        else:
            time = time + str(m)

        return time

##################################### MAIN ###################################

if len(sys.argv)>1:
    with open(sys.argv[1]) as fh:
        pb = ASARProblem()
        pb.load(fh)
        fh.close()

    #    print(pb.a)
    #    print(pb.p)
    #    print(pb.l)
    #    print(pb.c)
# #
#     print("##################")
#     #initial state for testing
#     state = pb.initial
#     print("---STATE---")
#     state.print_state()
#     print()
# #
# #
#     actions = pb.actions(state)
#     print("---ACTIONS---")
#     print(actions)
#     print()
# #
#     print("---ACTION---")
#     action = actions[0]
#     print(action)
#     print()
# #
#     print("---NEW STATE----")
#     new_state = pb.result(state,action)
#     new_state.print_state()
# #
# #
# #######
#     print()
#     print("--- TESTE 2 ---")
#     actions = pb.actions(new_state)
#     print(actions)
#     action = actions[0]
#     print(action)
#     new_state = pb.result(state,action)
#     new_state.print_state()
# #
# ######
# ########
#     print()
#     cost = pb.path_cost(0, pb.initial, action, new_state)
#     print("---PATH COST---- " + str(cost))
# #
# #########
#     print("---GOAL TEST--- " + str(pb.goal_test(new_state)))

    test = search.astar_search(pb,pb.heuristic)

#### TESTES
    with open("OUTPUT_TESTE.txt","w+") as fh:
        if test == None:
            pb.save(fh,test)
        else:
            pb.save(fh,test.state)

else:
    print("Usage: %s <filename>"%(sys.argv[0]))


import tensorflow as tf
import numpy as np

from snek.Snake import Snek, LEFT

hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))

s: Snek = Snek(20, 20, 5, LEFT)

a = s.snake_coordinates()
a.append((s.food_x, s.food_y))
a.append((s.width, s.height))

tensor = tf.convert_to_tensor(a, tf.int32)

print(tensor)

sess = tf.Session()
out_z = sess.run(tensor)

print(out_z)


import numpy as np
from scipy.special import logsumexp
from scipy.special import expit as logistic_sigmoid

from matplotlib import pyplot as plt

from LRGradientDescent import LogisticRegressionGradientDescent

import sklearn.preprocessing
import sklearn.pipeline
from sklearn.base import BaseEstimator, TransformerMixin

class LRGDWithFeatureTransform(LogisticRegressionGradientDescent):
    ''' Logistic Regression classifier using special feature transform preprocessing!

    Implements the standard sklearn binary classifier API:
    * fit : train the model and set internal trainable attributes
    * predict : produce hard binary predictions
    * predict_proba : produce probabilistic predictions for both labels (0 and 1)

    Inherits all methods from LogisticRegressionGradientDescent, including:
    * constructor
    * gradient descent training of weights via fit
    * utility methods like initialize_w

    '''

    def fit_feature_pipeline(self, x_NF, y_N=None):
        ''' Train the feature-processing pipeline that happens before the LR classifier

        Args
        ----
        x_NF : 2D array, size N x F (n_examples x n_features)
            Each row is a feature vector
        y_N : 1D array, size N (n_examples)
            Each entry is a binary label

        Returns
        -------
        Nothing. Internal attribute 'feature_transform_pipeline' updated.
        '''
        # TODO edit this pipeline!
        # Add whatever additional preprocessing would be useful!
        self.feature_transform_pipeline = sklearn.pipeline.Pipeline(
            [('feature_transform', sklearn.pipeline.FeatureUnion(transformer_list=[
                    ('original_x', sklearn.preprocessing.PolynomialFeatures(degree=1, include_bias=False)),
                    ('squared_x', SquaredFeatureExtractor()),
                    ('avg_x', AverageValueFeatureExtractor()),
                    ]),
            )])
        self.feature_transform_pipeline.fit(x_NF, y_N)

    def predict_proba(self, x_NF):
        ''' Produce soft probabilistic predictions for provided input features

        Args
        ----
        x_NF : 2D array, size N x F (n_examples x n_features_excluding_bias)
            Input features (one row per example).

        Returns
        -------
        yproba_N2 : 2D array, size N x 2
            First column gives probability of zero label (negative)
            Second column gives probability of one label (positive)
            Each entry is a non-negative probability value within (0.0, 1.0)
            Each row sums to one
        '''
        # Transform each original F-dim feature vector to a new H-dim vector!
        feat_NH = self.feature_transform_pipeline.transform(x_NF)
        # Now call your original predict_proba code defined in parent class
        # but passing in the transformed feats!
        return super(LRGDWithFeatureTransform, self).predict_proba(feat_NH)

    ### Method for training

    def fit(self, x_NF, y_N):
        ''' Fit logistic regression model to provided training data

        Will minimize the loss function defined by calc_loss

        Returns
        -------
        Nothing. Only internal instance attributes updated.

        Post Condition
        --------------
        Internal attributes are updated:
        * w_G contains the optimal weights
        * trace_loss contains loss at every step of gradient descent
        * trace_L1_norm_of_grad contains L1 norm of grad after every step
        '''
        # Train the feature processing pipeline
        self.fit_feature_pipeline(x_NF, y_N)
        # Transform each original F-dim feature vector to a new H-dim vector!
        feat_NH = self.feature_transform_pipeline.transform(x_NF)
        ## Now call your original gradient descent code,
        # as defined in the parent class LogisticRegressionGradientDescent,
        # but use the transformed features as input to LR classifier
        return super(LRGDWithFeatureTransform, self).fit(feat_NH, y_N)

class SquaredFeatureExtractor(BaseEstimator, TransformerMixin):
    """ Extracts feature equal to square of each original feature
    """

    def __init__(self):
        pass

    def transform(self, x, y=None):
        """ Average all feature values into a new feature column

        Args
        ----
        x : 2D array, size F

        Returns
        -------
        feat : 2D array, size N x F
            One feature extracted for each example
        """
        return np.square(x)

    def fit(self, x, y=None):
        """ Nothing happens when fitting
        """
        return self

class AverageValueFeatureExtractor(BaseEstimator, TransformerMixin):
    """ Extracts feature equal to the *sum* of all pixels in image
    """

    def __init__(self):
        pass

    def transform(self, x, y=None):
        """ Average all feature values into a new feature column

        Returns
        -------
        feat : 2D array, size N x 1
            One feature extracted for each example
        """
        return np.sum(x, axis=1)[:,np.newaxis]

    def fit(self, x, y=None):
        """ Nothing happens when fitting
        """
        return self

if __name__ == '__main__':
    ## Toy problem
    #
    # Generate negative-label points in a tight cluster centered at zero
    # General positive-label points in a wide ring centered at zero
    #
    # Logistic regression on original features should struggle
    # But using our *squared* features, we should get better performance

    C = 50 # num examples per class
    N = 2 * C # num examples total
    random_state = np.random.RandomState(0)
    x_pos_C2 = 0.5 * random_state.randn(C, 2)
    x_neg_M2 = 5.0 * random_state.randn(100 * C, 2)
    radius_M = np.sqrt(np.sum(np.square(x_neg_M2), axis=1))
    fits_ring_M = np.logical_and(radius_M >= 1.8, radius_M <= 2.5)
    x_neg_C2 = x_neg_M2[fits_ring_M][:C]

    x_N2 = np.vstack([x_neg_C2, x_pos_C2])
    y_N = np.hstack([np.zeros(C), 1.0 * np.ones(C)])

    plt.plot(x_N2[y_N == 1,0], x_N2[y_N == 1,1], color='b', marker='+', ls='')
    plt.plot(x_N2[y_N == 0,0], x_N2[y_N == 0,1], color='r', marker='x', ls='')

    ## Run LR on original features!
    orig_lr = LogisticRegressionGradientDescent(alpha=10.0, step_size=0.1)
    orig_lr.fit(x_N2, y_N)

    ## Run LR on transformed features!
    new_lr = LRGDWithFeatureTransform(alpha=10.0, step_size=0.1)
    new_lr.fit(x_N2, y_N)

    np.set_printoptions(precision=4, suppress=1, linewidth=100)
    for nn in range(3):
        print("Example %d" % nn)
        print("Original feature vector: %s" % x_N2[nn])
        print("     New feature vector: %s" % (
            new_lr.feature_transform_pipeline.transform(x_N2[nn:nn+1])[0]))

    yproba1_orig_N = orig_lr.predict_proba(x_N2)[:,1]
    yproba1_new_N = new_lr.predict_proba(x_N2)[:,1]

    print("Training Error with orig features: %.3f" % (
        np.mean(np.logical_xor(y_N, yproba1_orig_N >= 0.5))))
    print("Training Error with new  features: %.3f" % (
        np.mean(np.logical_xor(y_N, yproba1_new_N >= 0.5))))

    plt.show()