# -*- coding: utf-8 -*-
# =============================================================================
# Modules
# =============================================================================
import copy
from psychopy import visual
from .utils import *
from .saccadedb import SaccadeDB

# =============================================================================
# Class: Configuration
# =============================================================================
class Configuration(object):
    def __init__(self, db=None, name=u""):
        self.__in_db = False
        self.__database = None
        # -------------------
        self.__name = u"Unnamed"
        self.__tracker = u"eyegaze"
        self.__monitor = u"default"
        self.__screen = 0
        self.__path = format_path(get_main_path()+u"/events/")
        # -------------------
        if self.set_database(db=db) and name != u"":
            self.load(name=name)

    # =================================
    @staticmethod
    def get_list(db):
        if isinstance(db, SaccadeDB):
            sql = u"""
            select con_name
            from configuration
            order by con_name asc;
            """
            item_list = db.pull_query(query=sql)
            if item_list is not None:
                return [item for item in item_list]
        return []

    # =================================
    def set_database(self, db):
        if isinstance(db, SaccadeDB):
            self.__database = db
            return True
        return False

    def get_database(self):
        return self.__database

    def in_database(self):
        return self.__in_db

    # -----------------------
    def set_name(self, name):
        name = format_text(text=name, lmin=3, lmax=50, var_name=u"name")
        if self.__database:
            sql = u"select * from configuration where con_name='{0}';".format(name)
            mas_res = self.__database.pull_query(query=sql)
            if mas_res is None:
                self.__name = name
                return True
        return False

    def get_name(self):
        return self.__name

    # -----------------------
    def set_screen(self, screen):
        screen_num = len(get_available_screens())
        self.__screen = format_int(value=screen, vmin=0, vmax=screen_num, var_name=u"screen")
        return True

    def get_screen(self):
        try:
            return get_available_screens()[self.__screen]
        except IndexError:
            return get_available_screens()[0]

    # -----------------------
    def set_monitor(self, monitor):
        monitor = format_text(text=monitor, var_name=u"monitor")
        if monitor in get_available_monitors():
            self.__monitor = monitor
            return True
        return False

    def get_monitor(self):
        return self.__monitor

    # -----------------------
    def set_tracker(self, tracker):
        tracker = format_text(text=tracker, var_name=u"tracker")
        if tracker in get_available_trackers():
            self.__tracker = tracker
            return True
        return False

    def get_tracker_name(self):
        return self.__tracker

    def get_tracker_conf_path(self):
        if self.__tracker in get_available_trackers():
            base_path = format_path(get_module_path()+u"/api/resources/eyetrackers/")
            return base_path+self.__tracker+u"_config.yaml"
        return u""

    # -----------------------
    def set_events_path(self, path):
        import os
        path = format_path(path)
        if not os.path.isdir(path):
            os.mkdir(path)
        if os.path.isdir(path):
            self.__path = path
            return True
        return False

    def get_events_path(self):
        return self.__path

    # =================================
    def load(self, name):
        name = format_text(text=name, lmin=3, lmax=50, var_name=u"name")
        if self.__database:
            sql = u"""
            select
            con_screen, con_monitor, con_tracker, con_path
            from configuration
            where con_name='{0}';
            """.format(name)
            con_res = self.__database.pull_query(query=sql)
            if con_res is not None:
                self.__in_db = True
                self.__name = name
                self.__screen = int(con_res[0, 0])
                self.__monitor = unicode(con_res[0, 1])
                self.__tracker = unicode(con_res[0, 2])
                self.__path = unicode(con_res[0, 3])
                return True
        return False

    def save(self):
        if self.__database:
            sql = u"""
            insert or replace into configuration
            (con_name, con_screen, con_tracker, con_monitor, con_path)
            values ('{0}', '{1}', '{2}', '{3}', '{4}')
            """.format(self.__name, self.__screen, self.__tracker, self.__monitor, self.__path)
            operation_ok = self.__database.push_query(query=sql)
            self.__in_db = operation_ok
            return operation_ok
        return False

    def copy(self, name):
        new_con = copy.deepcopy(self)
        new_con.set_database(db=self.__database)
        new_con.__in_db = False
        name_check = new_con.set_name(name=name)
        return new_con if name_check else None

    def remove(self):
        if self.__in_db:
            sql = u"delete from configuration where con_name='{0}';".format(self.__name)
            operation_ok = self.__database.push_query(query=sql)
            self.__in_db = not operation_ok
            return operation_ok
        return False

    # =================================
    def get_iohub(self):
        import yaml
        # -------------------
        if self.__in_db:
            configuration = {
                u"monitor_devices": [
                    {u"Display": {
                        u"name":                            u"display",
                        u"reporting_unit_type":             u"pix",
                        u"device_number":                   self.__screen,
                        u"psychopy_monitor_name":           self.__monitor,
                        u"override_using_psycho_settings":  True,
                    }},
                    {u"Keyboard": {
                        u"name":        u"keyboard",
                        u"enable":      True,
                        u"save_events": True,
                    }},
                    {u"Experiment": {
                        u"name":        u"experimentRuntime",
                        u"enable":      True,
                        u"save_events": True,
                    }}
                ],
                u"data_store": {
                    u"enable":      True,
                }
            }
            tracker_path = self.get_tracker_conf_path()
            tracker = yaml.load(open(tracker_path, u"r"))[u"monitor_devices"][0]
            configuration[u"monitor_devices"].append(tracker)
            return configuration
        return None

    def get_configuration(self):
        if self.__in_db:
            configuration = {
                u"name":            self.__name,
                u"screen":          self.__screen,
                u"tracker":         self.__tracker,
                u"monitor":         self.__monitor,
                u"experiment_path": self.__path,
            }
            return configuration
        return None

# =============================================================================
# Class type: ItemList
# =============================================================================
class ItemList(object):
    # =================================
    def __init__(self, item_class):
        self._class = item_class
        self._item_dat = []

    # =================================
    def item_add(self, item):
        if isinstance(item, self._class) and self.check_item_name(item.get_name()) == -1:
            self._item_dat.append(item)
            return True
        return False

    def item_copy(self, item_id, new_name):
        if 0 <= item_id < self.get_items_length():
            new_name = format_text(text=new_name, var_name=u"copy name")
            if new_name is not None and self.check_item_name(new_name) == -1:
                new_item = self._item_dat[item_id].copy()
                new_item.set_name(name=new_name)
                return self.item_add(item=new_item)
        return False

    def item_remove(self, item_id):
        if 0 <= item_id < self.get_items_length():
            self._item_dat.pop(item_id)
            return True
        return False

    def item_replace(self, item_id, new_item):
        if 0 <= item_id < self.get_items_length():
            item_popped = self._item_dat.pop(item_id)
            if isinstance(new_item, self._class) and self.check_item_name(new_item.get_name()) == -1:
                self._item_dat.insert(item_id, new_item)
                return True
            self._item_dat.insert(item_id, item_popped)
            return False

    def item_swap(self, item1_id, item2_id):
        data_len = self.get_items_length()
        if 0 <= item1_id < data_len and 0 <= item2_id < data_len:
            temp = self._item_dat[item1_id]
            self._item_dat[item1_id] = self._item_dat[item2_id]
            self._item_dat[item2_id] = temp
            return True
        return False

    def get_items(self):
        return self._item_dat

    def get_item(self, item_id):
        if 0 <= item_id < self.get_items_length():
            return self._item_dat[item_id]
        return None

    def check_item_name(self, item_name):
        try:
            return self.get_items_str().index(item_name)
        except ValueError:
            return -1

    def get_items_str(self):
        return [item.get_name() for item in self._item_dat]

    def get_items_length(self):
        return len(self._item_dat)

# =============================================================================
# Class type: ItemListSequence
# =============================================================================
class ItemListSequence(ItemList):
    # =================================
    def __init__(self, item_class):
        super(ItemListSequence, self).__init__(item_class=item_class)
        self._item_seq = []

    # =================================
    def item_remove(self, item_id):
        if 0 <= item_id < self.get_items_length():
            item = self._item_dat[item_id]
            self._item_seq = [seq for seq in self._item_seq if seq[0] is not item]
            self._item_dat.pop(item_id)
            return True
        return False

    def item_replace(self, item_id, new_item):
        if 0 <= item_id < self.get_items_length():
            item_popped = self._item_dat.pop(item_id)
            if isinstance(new_item, self._class) and self.check_item_name(new_item.get_name()) == -1:
                self._item_dat.insert(item_id, new_item)
                self._item_seq = [[new_item, seq[1]] if seq[0] == item_popped else seq for seq in self._item_seq]
                return True
            self._item_dat.insert(item_id, item_popped)
            return False

    # =================================
    def sequence_add(self, item_id, quantity):
        quantity = format_int(quantity)
        if 0 <= item_id < self.get_items_length() and quantity is not None:
            self._item_seq.append([self._item_dat[item_id], quantity])
            return True
        return False

    def sequence_edit(self, index, item_id, quantity):
        quantity = format_int(quantity)
        if 0 <= index < self.get_sequence_length() and 0 <= item_id < self.get_items_length() and quantity is not None:
            self._item_seq[index] = [self._item_dat[item_id], quantity]
            return True
        return False

    def sequence_remove(self, index):
        if 0 <= index < self.get_sequence_length():
            self._item_seq.pop(index)
            return True
        return False

    def sequence_swap(self, index1, index2):
        itm_num = self.get_sequence_length()
        if 0 <= index1 < itm_num and 0 <= index2 < itm_num:
            temp = self._item_seq[index1]
            self._item_seq[index1] = self._item_seq[index2]
            self._item_seq[index2] = temp
            return True
        return False

    def get_sequence(self):
        return self._item_seq

    def get_sequence_item(self, index):
        seq_len = self.get_sequence_length()
        if 0 <= index < seq_len:
            return self._item_seq[index]
        return None

    def get_sequence_str(self):
        return [[item[0].get_name(), item[1]] for item in self._item_seq]

    def get_sequence_length(self):
        return len(self._item_seq)

# =============================================================================
# Class: Component
# =============================================================================
class Component(object):
    # =================================
    def __init__(self):
        self.__name = u"Unnamed"
        self.__units = u"deg"
        self.__pos = (0.0, 0.0)
        self.__rot = 0.0
        self.__size = 1.0
        self.__shape = u"square"
        self.__color = u"white"
        self.__image = None

    def __deepcopy__(self, memo):
        com_copy = Component()
        com_copy.set_name(name=self.__name)
        com_copy.set_units(units=self.__units)
        com_copy.set_position(posx=self.__pos[0], posy=self.__pos[1])
        com_copy.set_rotation(rot=self.__rot)
        com_copy.set_size(size=self.__size)
        com_copy.set_shape(shape=self.__shape)
        com_copy.set_color(color=self.__color)
        com_copy.set_image(image=self.__image)
        return com_copy

    # =================================
    @staticmethod
    def get_list(db, exp, tes, fra):
        if isinstance(db, SaccadeDB):
            sql = u"""
            select com_index, com_name, com_shape
            from component
            where exp_code='{0}' and tes_index='{1}' and fra_index='{2}'
            order by com_index asc;
            """.format(exp, tes, fra)
            item_list = db.pull_query(query=sql)
            if item_list is not None:
                return [[int(item[0]), item[1], item[2]] for item in item_list]
        return []

    # =================================
    def set_name(self, name):
        self.__name = format_text(text=name, lmin=3, lmax=50, var_name=u"name")
        return True

    def get_name(self):
        return self.__name

    # -----------------------
    def set_units(self, units):
        units = format_text(text=units, lmin=2, lmax=20, var_name=u"units")
        if units in get_available_units():
            self.__units = units
            return True
        return False

    def get_units(self):
        return self.__units

    # -----------------------
    def set_position(self, posx, posy):
        posx = format_float(value=posx, vmin=-9999.0, vmax=9999.0, var_name=u"position (x)")
        posy = format_float(value=posy, vmin=-9999.0, vmax=9999.0, var_name=u"position (y)")
        self.__pos = (posx, posy)
        return True

    def get_position(self):
        return self.__pos

    # -----------------------
    def set_rotation(self, rot):
        rot = format_float(value=rot, vmin=-360.0, vmax=360.0, var_name=u"rotation")
        self.__rot = rot
        return True

    def get_rotation(self):
        return self.__rot

    # -----------------------
    def set_size(self, size):
        size = format_float(value=size, vmin=0.0, vmax=9999.0, var_name=u"size")
        self.__size = size
        return True

    def get_size(self):
        return self.__size

    # -----------------------
    def set_image(self, image):
        from os import path
        from PIL import Image
        if image is None:
            return False
        if isinstance(image, Image.Image):
            self.__image = image
            self.__shape = u"image"
            return True
        elif image != u"" and path.isfile(path=image):
            self.__image = Image.open(image)
            self.__shape = u"image"
            return True
        return False

    def remove_image(self):
        self.__image = None

    def get_image(self):
        return self.__image

    # -----------------------
    def set_shape(self, shape):
        shape = format_text(text=shape, lmin=5, lmax=20, var_name=u"shape")
        if shape in get_available_shapes():
            self.__shape = shape
            return True
        return False

    def get_shape(self):
        return self.__shape

    # -----------------------
    def set_color(self, color):
        from psychopy import colors
        color = format_text(text=color, lmin=3, lmax=20, var_name=u"shape color")
        if colors.isValidColor(color):
            self.__color = color
            return True
        return False

    def get_color(self):
        return self.__color

    # =================================
    def __decode_image(self, enc_img):
        from PIL import Image
        from io import BytesIO
        coded = format_text(text=enc_img, var_name=u"encoded image")
        if coded == u"":
            self.__image = None
        else:
            img_buff = BytesIO()
            img_buff.write(coded.decode(u"base64"))
            self.__shape = u"image"
            self.__image = Image.open(img_buff)

    def __encode_image(self):
        from io import BytesIO
        if self.__image is None:
            return u""
        img_buff = BytesIO()
        self.__image.save(img_buff, u"PNG")
        return img_buff.getvalue().encode(u"base64")

    # =================================
    def load(self, db, exp, tes, fra, com):
        sql = u"""
        select
        com_name, com_units, com_pos_x, com_pos_y, com_rotation, com_size, com_image, com_shape, com_color
        from component
        where exp_code='{0}' and tes_index='{1}' and fra_index='{2}' and com_index='{3}';
        """.format(exp, tes, fra, com)
        com_res = db.pull_query(query=sql)
        if com_res is not None:
            self.__name = unicode(com_res[0, 0])
            self.__units = unicode(com_res[0, 1])
            self.__pos = (float(com_res[0, 2]),
                          float(com_res[0, 3]))
            self.__rot = float(com_res[0, 4])
            self.__size = float(com_res[0, 5])
            self.__shape = unicode(com_res[0, 7])
            self.__color = unicode(com_res[0, 8])
            self.__decode_image(enc_img=unicode(com_res[0, 6]))
            return True
        return False

    def save(self, db, exp, tes, fra, com):
        sql = u"""
        insert into component
        (exp_code, tes_index, fra_index, com_index,
        com_name, com_units, com_pos_x, com_pos_y, com_rotation, com_size,
        com_image, com_shape, com_color)
        values ('{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}', '{11}', '{12}');
        """.format(
            exp, tes, fra, com,
            self.__name, self.__units, self.__pos[0], self.__pos[1], self.__rot, self.__size,
            self.__encode_image(), self.__shape, self.__color
        )
        operation_ok = db.push_query(query=sql)
        return operation_ok

    def copy(self):
        return copy.deepcopy(self)

    # =================================
    def get_execution(self, win):
        from switch import Switch
        if not isinstance(win, visual.Window):
            return None
        with Switch(self.__shape) as case:
            if case(u"image"):
                return visual.ImageStim(win=win, name=self.__name, image=self.__image,
                                        pos=self.__pos, ori=self.__rot, units=self.__units)
            elif case(u"arrow"):
                return visual.ShapeStim(win=win, name=self.__name, lineColor=self.__color, fillColor=self.__color,
                                        size=self.__size, pos=self.__pos, ori=self.__rot, units=self.__units,
                                        vertices=((1.0, 0.0), (0.6667, 0.1667), (0.6667, 0.0667), (0.0, 0.0667),
                                                  (0.0, -0.0667), (0.6667, -0.0667), (0.6667, -0.1667)))
            else:
                return visual.GratingStim(win=win, name=self.__name, color=self.__color, sf=0,
                                          mask=None if self.__shape == u"square" else self.__shape,
                                          size=self.__size, pos=self.__pos, ori=self.__rot, units=self.__units)

    def get_configuration(self):
        component = {
            u"name":        self.__name,
            u"units":       self.__units,
            u"position":    self.__pos,
            u"rotation":    self.__rot,
            u"size":        self.__size,
            u"image":       self.__encode_image(),
            u"shape":       self.__shape,
            u"color":       self.__color
        }
        return component

# =============================================================================
# Class: Frame (child of ItemList)
# =============================================================================
class Frame(ItemList):
    # =================================
    def __init__(self):
        super(Frame, self).__init__(item_class=Component)
        # -------------------
        self.__name = u"Unnamed"
        self.__color = u"black"
        self.__is_task = False
        self.__keys_allowed = u""
        self.__keys_correct = u""
        self.__time = 0.0

    # =================================
    @staticmethod
    def get_list(db, exp, tes):
        if isinstance(db, SaccadeDB):
            sql = u"""
            select fra_index, fra_name
            from frame
            where exp_code='{0}' and tes_index='{1}'
            order by fra_index asc;
            """.format(exp, tes)
            item_list = db.pull_query(query=sql)
            if item_list is not None:
                return [[int(item[0]), item[1]] for item in item_list]
        return []

    # =================================
    def set_name(self, name):
        self.__name = format_text(text=name, lmin=3, lmax=50, var_name=u"name")
        return True

    def get_name(self):
        return self.__name

    # -----------------------
    def set_color(self, color):
        from psychopy import colors
        color = format_text(text=color, lmin=3, lmax=20, var_name=u"background")
        if colors.isValidColor(color):
            self.__color = color
            return True
        return False

    def get_color(self):
        return self.__color

    # -----------------------
    def set_as_task(self, state):
        self.__is_task = format_bool(state=state, var_name=u"task selection")
        if self.__is_task:
            self.__time = 0.0
            return True
        self.__keys_allowed = u""
        self.__keys_correct = u""
        return False

    def is_task(self):
        return self.__is_task

    # -----------------------
    def set_time(self, value):
        if not self.__is_task:
            self.__time = format_float(value=value, vmin=0.0, vmax=9999.0, var_name=u"time")
            return True
        return False

    def get_time(self):
        return self.__time

    # -----------------------
    def set_keys_allowed(self, keys):
        if self.__is_task:
            keys = format_text(text=keys, var_name=u"allowed keys").replace(unicode(u" "), unicode(u""))
            self.__keys_allowed = keys
            return True
        return False

    def get_keys_allowed(self):
        return self.__keys_allowed

    # -----------------------
    def set_keys_correct(self, keys):
        if self.__is_task and self.__keys_allowed != u"":
            keys = format_text(text=keys, var_name=u"selected keys").replace(unicode(u" "), unicode(u""))
            allowed = self.__keys_allowed.split(u",")
            selected = keys.split(u",")
            key_match = [key for key in selected if key in allowed]
            if len(key_match) == len(selected):
                self.__keys_correct = keys
                return True
        return False

    def get_keys_correct(self):
        return self.__keys_correct

    # =================================
    def load(self, db, exp, tes, fra):
        sql = u"""
        select
        fra_name, fra_color, fra_is_task, fra_time, fra_keys_allowed, fra_keys_correct
        from frame
        where exp_code='{0}' and tes_index='{1}' and fra_index='{2}';
        """.format(exp, tes, fra)
        fra_res = db.pull_query(query=sql)
        if fra_res is not None:
            self.__name = unicode(fra_res[0, 0])
            self.__color = unicode(fra_res[0, 1])
            self.__is_task = bool(int(fra_res[0, 2]))
            self.__time = float(fra_res[0, 3])
            self.__keys_allowed = unicode(fra_res[0, 4])
            self.__keys_correct = unicode(fra_res[0, 5])
            self.__load_components(db=db, exp=exp, tes=tes, fra=fra)
            return True
        return False

    def save(self, db, exp, tes, fra):
        sql = u"""
        insert into frame
        (exp_code, tes_index, fra_index,
        fra_name, fra_color, fra_is_task, fra_time, fra_keys_allowed, fra_keys_correct)
        values ('{0}', '{1}', '{2}', '{3}', '{4}', '{5:x}', '{6}', '{7}', '{8}');
        """.format(
            exp, tes, fra,
            self.__name, self.__color, self.__is_task, self.__time, self.__keys_allowed, self.__keys_correct
        )
        operation_ok = db.push_query(query=sql)
        if operation_ok:
            self.__save_components(db=db, exp=exp, tes=tes, fra=fra)
        return operation_ok

    def copy(self):
        return copy.deepcopy(self)

    # =================================
    def __load_components(self, db, exp, tes, fra):
        component_list = Component.get_list(db=db, exp=exp, tes=tes, fra=fra)
        if component_list is not None:
            for component in component_list:
                new_component = Component()
                new_component.load(db=db, exp=exp, tes=int(tes), fra=int(fra), com=int(component[0]))
                self.item_add(item=new_component)

    def __save_components(self, db, exp, tes, fra):
        for component in self._item_dat:
            index = self._item_dat.index(component)
            component.save(db=db, exp=exp, tes=tes, fra=fra, com=index)

    # =================================
    def get_execution(self, win):
        if not isinstance(win, visual.Window):
            return None
        frame = {
            u"name":                self.__name,
            u"is_task":             self.__is_task,
            u"time":                self.__time,
            u"allowed_keys":        self.__keys_allowed.replace(u"space", u" ").split(u","),
            u"correct_keys":        self.__keys_correct.replace(u"space", u" ").split(u","),
            u"correct_keys_str":    self.__keys_correct,
            u"background":          visual.Rect(win=win, width=win.size[0], height=win.size[1], units=u"pix",
                                                lineColor=self.__color, fillColor=self.__color),
            u"components":          [item.get_execution(win=win) for item in self._item_dat]
        }
        return frame

    def get_configuration(self):
        frame = {
            u"name":            self.__name,
            u"is_task":         self.__is_task,
            u"time":            self.__time,
            u"allowed_keys":    self.__keys_allowed,
            u"correct_keys":    self.__keys_correct,
            u"background":      self.__color,
            u"components":      [item.get_configuration() for item in self._item_dat]
        }
        return frame

# =============================================================================
# Class: Test (child of ItemList)
# =============================================================================
class Test(ItemList):
    # =================================
    def __init__(self):
        super(Test, self).__init__(item_class=Frame)
        self.__name = u"Unnamed"
        self.__description = u""

    # =================================
    @staticmethod
    def get_list(db, exp):
        if isinstance(db, SaccadeDB):
            sql = u"""
            select tes_index, tes_name
            from test
            where exp_code='{0}'
            order by tes_index asc;
            """.format(exp)
            item_list = db.pull_query(query=sql)
            if item_list is not None:
                return [[int(item[0]), item[1]] for item in item_list]
        return []

    # =================================
    def set_name(self, name):
        self.__name = format_text(text=name, lmin=3, lmax=50, var_name=u"name")
        return True

    def get_name(self):
        return self.__name

    def set_description(self, text):
        self.__description = format_text(text=text, var_name=u"description")
        return True

    def get_description(self):
        return self.__description

    # =================================
    def load(self, db, exp, tes):
        sql = u"""
        select
        tes_name, tes_description
        from test
        where exp_code='{0}' and tes_index='{1}';
        """.format(exp, tes)
        tes_res = db.pull_query(query=sql)
        if tes_res is not None:
            self.__name = unicode(tes_res[0, 0])
            self.__description = unicode(tes_res[0, 1])
            self.__load_frames(db=db, exp=exp, tes=tes)
            return True
        return False

    def save(self, db, exp, tes):
        sql = u"""
        insert into test
        (exp_code, tes_index, tes_name, tes_description)
        values ('{0}', '{1}', '{2}', '{3}');
        """.format(
            exp, tes,
            self.__name, self.__description
        )
        operation_ok = db.push_query(query=sql)
        if operation_ok:
            self.__save_frames(db=db, exp=exp, tes=tes)
        return operation_ok

    def copy(self):
        return copy.deepcopy(self)

    # =================================
    def __load_frames(self, db, exp, tes):
        frame_list = Frame.get_list(db=db, exp=exp, tes=tes)
        if frame_list is not None:
            for frame in frame_list:
                new_frame = Frame()
                new_frame.load(db=db, exp=exp, tes=int(tes), fra=int(frame[0]))
                self.item_add(item=new_frame)

    def __save_frames(self, db, exp, tes):
        for frame in self._item_dat:
            index = self._item_dat.index(frame)
            frame.save(db=db, exp=exp, tes=tes, fra=index)

    # =================================
    def get_execution(self, win):
        if not isinstance(win, visual.Window):
            return None
        test = {
            u"name":        self.__name,
            u"frames":      [item.get_execution(win=win) for item in self._item_dat]
        }
        return test

    def get_configuration(self):
        test = {
            u"name":        self.__name,
            u"description": self.__description,
            u"frames":      [item.get_configuration() for item in self._item_dat],
        }
        return test

# =============================================================================
# Class: Experiment (child of ItemList)
# =============================================================================
class Experiment(ItemListSequence):
    # =================================
    def __init__(self, db=None, code=u""):
        super(Experiment, self).__init__(item_class=Test)
        self.__in_db = False
        self.__database = None
        # -------------------
        self.__date_created = u""
        self.__date_updated = u""
        # -------------------
        self.__code = u""
        self.__name = u"Unnamed"
        self.__version = u"1.0"
        self.__description = u""
        self.__instructions = u""
        self.__comments = u""
        # -------------------
        self.__dia_is_active = True
        self.__dia_ask_age = True
        self.__dia_ask_gender = True
        self.__dia_ask_glasses = True
        self.__dia_ask_eye_color = True
        self.__con_need_space = False
        self.__con_is_random = False
        self.__con_is_rest = False
        self.__con_rest_time = 0.0
        self.__con_rest_period = 0
        self.__test_sequence = None
        # -------------------
        if self.set_database(db=db) and code != u"":
            self.load(code=code)

    # =================================
    @staticmethod
    def get_list(db):
        if isinstance(db, SaccadeDB):
            sql = u"""
            select exp_code, exp_name, exp_version, exp_date_creation, exp_date_update
            from experiment
            order by exp_name asc, exp_version asc;
            """
            item_list = db.pull_query(query=sql)
            if item_list is not None:
                return [[item[0], [item[1], item[2]], [item[3], item[4]]] for item in item_list]
        return []

    # =================================
    def set_database(self, db):
        if isinstance(db, SaccadeDB):
            self.__database = db
            return True
        return False

    def get_database(self):
        return self.__database

    def in_database(self):
        return self.__in_db

    # -----------------------
    def set_code(self, code):
        code = format_text(text=code, lmin=3, lmax=10, var_name=u"code")
        if self.__database:
            sql = u"select * from experiment where exp_code='{0}';".format(code)
            operation_ok = self.__database.pull_query(query=sql)
            if operation_ok is None:
                self.__code = code
                return True
        return False

    def get_code(self):
        return self.__code

    # -----------------------
    def set_info(self, name, version):
        name = format_text(text=name, lmin=3, lmax=50, var_name=u"name")
        version = format_text(text=version, lmin=3, lmax=10, var_name=u"version")
        if self.__database:
            sql = u"select * from experiment where exp_name='{0}' and exp_version='{1}';".format(name, version)
            operation_ok = self.__database.pull_query(query=sql)
            if operation_ok is None:
                self.__name = name
                self.__version = version
                return True
        return False

    def get_name(self):
        return self.__name

    def get_version(self):
        return self.__version

    # -----------------------
    def set_descripton(self, text):
        self.__description = format_text(text=text, var_name=u"description")
        return True

    def get_description(self):
        return self.__description

    # -----------------------
    def set_comments(self, text):
        self.__comments = format_text(text=text, lmax=50, var_name=u"comments")
        return True

    def get_comments(self):
        return self.__comments

    # -----------------------
    def set_instructions(self, text):
        self.__instructions = format_text(text=text, var_name=u"instructions")
        return True

    def get_instructions(self):
        return self.__instructions

    # -----------------------
    def set_dialog(self, status, askage=False, askgender=False, askglasses=False, askeyecolor=False):
        self.__dia_is_active = format_bool(state=status, var_name=u"dialog state")
        self.__dia_ask_age = format_bool(state=askage, var_name=u"ask age state")
        self.__dia_ask_gender = format_bool(state=askgender, var_name=u"ask gender state")
        self.__dia_ask_glasses = format_bool(state=askglasses, var_name=u"ask glasses state")
        self.__dia_ask_eye_color = format_bool(state=askeyecolor, var_name=u"ask eye color state")
        return True

    def is_dialog_active(self):
        return self.__dia_is_active

    def is_ask_age(self):
        return self.__dia_ask_age

    def is_ask_gender(self):
        return self.__dia_ask_gender

    def is_ask_glasses(self):
        return self.__dia_ask_glasses

    def is_ask_eye_color(self):
        return self.__dia_ask_eye_color

    # -----------------------
    def set_space_start(self, status):
        self.__con_need_space = format_bool(state=status, var_name=u"use space status")
        return True

    def is_space_start(self):
        return self.__con_need_space

    # -----------------------
    def set_random(self, status):
        self.__con_is_random = format_bool(state=status, var_name=u"use random sequence status")
        return True

    def is_random(self):
        return self.__con_is_random

    # -----------------------
    def set_rest_conf(self, status, period=1, time=1.0):
        self.__con_is_rest = format_bool(state=status, var_name=u"include rest status")
        self.__con_rest_period = format_int(value=period, vmin=1, vmax=9999, var_name=u"rest period")
        self.__con_rest_time = format_float(value=time, vmin=1.0, vmax=9999.0, var_name=u"rest_time")
        return True

    def is_rest(self):
        return self.__con_is_rest

    def get_rest_period(self):
        return self.__con_rest_period

    def get_rest_time(self):
        return self.__con_rest_time

    # =================================
    def load(self, code):
        code = format_text(text=code, lmin=3, lmax=10, var_name=u"code")
        if self.__database:
            sql = u"""
            select
            exp.exp_name, exp.exp_version, exp.exp_description, exp.exp_instructions, exp.exp_comments,
            exp.exp_date_creation, exp.exp_date_update,
            dia.dia_is_active, dia.dia_ask_age, dia.dia_ask_gender, dia.dia_ask_glasses, dia.dia_ask_eye_color,
            con.con_need_space, con.con_is_random, con.con_is_rest, con.con_rest_period, con.con_rest_time
            from experiment as exp
            inner join exp_dia as dia on exp.exp_code=dia.exp_code
            inner join exp_con as con on exp.exp_code=con.exp_code
            where exp.exp_code='{0}';
            """.format(code)
            exp_res = self.__database.pull_query(query=sql)
            if exp_res is not None:
                self.__in_db = True
                self.__code = code
                self.__name = unicode(exp_res[0, 0])
                self.__version = unicode(exp_res[0, 1])
                self.__description = unicode(exp_res[0, 2])
                self.__instructions = unicode(exp_res[0, 3])
                self.__comments = unicode(exp_res[0, 4])
                self.__date_created = get_time(exp_res[0, 5])
                self.__date_updated = get_time(exp_res[0, 6])
                self.__dia_is_active = bool(int(exp_res[0, 7]))
                self.__dia_ask_age = bool(int(exp_res[0, 8]))
                self.__dia_ask_gender = bool(int(exp_res[0, 9]))
                self.__dia_ask_glasses = bool(int(exp_res[0, 10]))
                self.__dia_ask_eye_color = bool(int(exp_res[0, 11]))
                self.__con_need_space = bool(int(exp_res[0, 12]))
                self.__con_is_random = bool(int(exp_res[0, 13]))
                self.__con_is_rest = bool(int(exp_res[0, 14]))
                self.__con_rest_period = int(exp_res[0, 15])
                self.__con_rest_time = float(exp_res[0, 16])
                self.__load_tests()
                return True
        return False

    def save(self):
        if self.__database is not None and self.__code != u"" and self.__name != u"":
            if self.__in_db:
                sql = u"""
                update experiment set
                exp_name='{1}', exp_version='{2}', exp_description='{3}', exp_instructions='{4}', exp_comments='{5}'
                where exp_code='{0}';
                update exp_dia set
                dia_is_active='{6:x}', dia_ask_age='{7:x}', dia_ask_gender='{8:x}', dia_ask_glasses='{9:x}',
                dia_ask_eye_color='{10:x}'
                where exp_code='{0}';
                update exp_con set
                con_need_space='{11:x}', con_is_random='{12:x}', con_is_rest='{13:x}', con_rest_period='{14}',
                con_rest_time='{15}'
                where exp_code='{0}';
                """.format(
                    self.__code, self.__name, self.__version, self.__description, self.__instructions, self.__comments,
                    self.__dia_is_active, self.__dia_ask_age, self.__dia_ask_gender, self.__dia_ask_glasses,
                    self.__dia_ask_eye_color, self.__con_need_space, self.__con_is_random, self.__con_is_rest,
                    self.__con_rest_period, self.__con_rest_time
                )
            else:
                sql = u"""
                insert into experiment
                (exp_code, exp_name, exp_version, exp_description, exp_comments, exp_instructions)
                values ('{0}', '{1}', '{2}', '{3}', '{4}', '{5}');
                insert into exp_dia
                (exp_code, dia_is_active, dia_ask_age, dia_ask_gender, dia_ask_glasses, dia_ask_eye_color)
                values ('{0}', '{6:x}', '{7:x}', '{8:x}', '{9:x}', '{10:x}');
                insert into exp_con
                (exp_code, con_need_space, con_is_random, con_is_rest, con_rest_period, con_rest_time)
                values ('{0}', '{11:x}', '{12:x}', '{13:x}', '{14}', '{15}');
                """.format(
                    self.__code, self.__name, self.__version, self.__description, self.__comments, self.__instructions,
                    self.__dia_is_active, self.__dia_ask_age, self.__dia_ask_gender, self.__dia_ask_glasses,
                    self.__dia_ask_eye_color, self.__con_need_space, self.__con_is_random, self.__con_is_rest,
                    self.__con_rest_period, self.__con_rest_time
                )
            operation_ok = self.__database.push_query(query=sql)
            self.__in_db = operation_ok
            if operation_ok:
                self.__save_tests()
            return operation_ok
        return False

    def copy(self, code, version):
        new_exp = copy.deepcopy(self)
        new_exp.set_database(db=self.__database)
        new_exp.__in_db = False
        code_check = new_exp.set_code(code=code)
        info_check = new_exp.set_info(name=self.__name, version=version)
        return new_exp if code_check and info_check else None

    def remove(self):
        if self.__in_db:
            sql = u"delete from experiment where exp_code='{0}';".format(self.__code)
            exp_res = self.__database.push_query(query=sql)
            self.__in_db = not exp_res
            return exp_res
        return False

    # =================================
    def __load_tests(self):
        test_list = Test.get_list(db=self.__database, exp=self.__code)
        if not test_list:
            return
        for test in test_list:
            new_test = Test()
            new_test.load(db=self.__database, exp=self.__code, tes=int(test[0]))
            self.item_add(item=new_test)
        sql = u"""
        select tes_index, tes_quantity
        from exp_seq
        where exp_code='{0}'
        order by seq_index asc;
        """.format(self.__code)
        seq_res = self.__database.pull_query(query=sql)
        if seq_res is not None:
            for item in seq_res:
                self.sequence_add(int(item[0]), int(item[1]))

    def __save_tests(self):
        self.__database.push_query(query=u"delete from test where exp_code='{0}';".format(self.__code))
        if not self._item_dat:
            return
        for test in self._item_dat:
            index = self._item_dat.index(test)
            test.save(db=self.__database, exp=self.__code, tes=index)
        seq_index = 0
        sql = u"""
        insert into exp_seq
        (exp_code, tes_index, seq_index, tes_quantity)
        values ('{0}', '{1}', '{2}', '{3}');
        """
        for item in self._item_seq:
            tes_index = self._item_dat.index(item[0])
            self.__database.push_query(query=sql.format(self.__code, tes_index, seq_index, item[1]))
            seq_index += 1

    # =================================
    def get_iohub(self):
        if self.__in_db:
            experiment = {
                u"title":                       self.__name,
                u"code":                        self.__code,
                u"version":                     self.__version,
                u"description":                 self.__description,
                u"display_experiment_dialog":   True,
                u"session_defaults": {
                    u"name":                    u"Session...",
                    u"code":                    0,
                    u"comments":                self.__comments,
                },
                u"display_session_dialog":      True,
                u"session_variable_order":      [u"name", u"code", u"comments"],
                u"ioHub": {
                    u"enable":                  True,
                },
            }
            if self.__dia_is_active:
                experiment[u"session_defaults"][u"user_variables"] = {}
                if self.__dia_ask_age:
                    experiment[u"session_defaults"][u"user_variables"][u"participant_age"] = u"Unknown"
                    experiment[u"session_variable_order"].append(u"participant_age")
                if self.__dia_ask_gender:
                    experiment[u"session_defaults"][u"user_variables"][u"participant_gender"] = [u"Male", u"Female"]
                    experiment[u"session_variable_order"].append(u"participant_gender")
                if self.__dia_ask_glasses:
                    experiment[u"session_defaults"][u"user_variables"][u"glasses"] = [u"Yes", u"No"]
                    experiment[u"session_defaults"][u"user_variables"][u"contacts"] = [u"Yes", u"No"]
                    experiment[u"session_variable_order"].append(u"glasses")
                    experiment[u"session_variable_order"].append(u"contacts")
                if self.__dia_ask_eye_color:
                    experiment[u"session_defaults"][u"user_variables"][u"eye_color"] = u"Unknown"
                    experiment[u"session_variable_order"].append(u"eye_color")
            return experiment
        return None

    def get_execution(self, win):
        import numpy as np
        if not (isinstance(win, visual.Window) and self.__in_db):
            return None
        experiment = {
            u"instructions":    self.__instructions,
            u"space_start":     self.__con_need_space,
            u"rest": {
                u"active":      self.__con_is_rest,
                u"period":      self.__con_rest_period,
                u"time":        self.__con_rest_time,
            },
            u"test_data":       [item.get_execution(win=win) for item in self._item_dat],
            u"test_sequence":   []
        }
        for item in self._item_seq:
            test = item[0]
            quantity = item[1]
            if test.get_items():
                index = self._item_dat.index(test)
                experiment[u"test_sequence"].append(index*np.full(shape=(quantity, 1), fill_value=1, dtype=int))
        experiment[u"test_sequence"] = np.concatenate(experiment[u"test_sequence"])
        if self.__con_is_random:
            np.random.shuffle(experiment[u"test_sequence"])
        return experiment

    def get_configuration(self):
        if self.__in_db:
            experiment = {
                u"title":                   self.__name,
                u"code":                    self.__code,
                u"version":                 self.__version,
                u"description":             self.__description,
                u"instructions":            self.__instructions,
                u"session_configuration": {
                    u"comments":            self.__comments,
                    u"space_start":         self.__con_need_space,
                    u"randomize":           self.__con_is_random,
                    u"rest": {
                        u"active":          self.__con_is_rest,
                        u"period":          self.__con_rest_period,
                        u"time":            self.__con_rest_time,
                    },
                    u"dialog": {
                        u"active":          self.__dia_is_active,
                        u"ask_age":         self.__dia_ask_age,
                        u"ask_gender":      self.__dia_ask_gender,
                        u"ask_glasses":     self.__dia_ask_glasses,
                        u"ask_eye_color":   self.__dia_ask_eye_color,
                    }
                },
                u"tests":                   [item.get_configuration() for item in self._item_dat],
                u"sequence":                [[self._item_dat.index(item[0]), item[1]] for item in self._item_seq]
            }
            return experiment
        return None


import sys
p_h1=0.1
p_h2=0.2
p_h3=0.4
p_h4=0.2
p_h5=0.1
p_C_h1=1
p_L_h1=0
p_C_h2=0.75
p_L_h2=0.25
p_C_h3=0.5
p_L_h3=0.5
p_C_h4=0.25
p_L_h4=0.75
p_C_h5=0
p_L_h5=1
string=sys.argv[1]
P_H1_Q=[p_h1]
P_H2_Q=[p_h2]
P_H3_Q=[p_h3]
P_H4_Q=[p_h4]
P_H5_Q=[p_h5]
P_Q_next_C=[p_C_h1*p_h1+p_C_h2*p_h2+p_C_h3*p_h3+p_C_h4*p_h4+p_C_h5*p_h5]
P_Q_next_L=[p_L_h1*p_h1+p_L_h2*p_h2+p_L_h3*p_h3+p_L_h4*p_h4+p_L_h5*p_h5]
f=open("result.txt","w")
f.write("Observation sequence Q: "+string)
f.write("\n")
f.write("Length of Q: "+str(len(string)))
for i in range(0,len(string)):
	f.write("\n")
	f.write("\n")
	f.write("After Observation "+str(i+1)+" = "+string[i]+":")
	f.write("\n")
	f.write("\n")
	if(string[i]=="C"):
		pth1=p_C_h1*P_H1_Q[i]/P_Q_next_C[i]
		pth2=p_C_h2*P_H2_Q[i]/P_Q_next_C[i]
		pth3=p_C_h3*P_H3_Q[i]/P_Q_next_C[i]
		pth4=p_C_h4*P_H4_Q[i]/P_Q_next_C[i]
		pth5=p_C_h5*P_H5_Q[i]/P_Q_next_C[i]
	else:
		pth1=p_L_h1*P_H1_Q[i]/P_Q_next_L[i]
		pth2=p_L_h2*P_H2_Q[i]/P_Q_next_L[i]
		pth3=p_L_h3*P_H3_Q[i]/P_Q_next_L[i]
		pth4=p_L_h4*P_H4_Q[i]/P_Q_next_L[i]
		pth5=p_L_h5*P_H5_Q[i]/P_Q_next_L[i]
	Pt1c=p_C_h1*pth1+p_C_h2*pth2+p_C_h3*pth3+p_C_h4*pth4+p_C_h5*pth5
	Pt1l=p_L_h1*pth1+p_L_h2*pth2+p_L_h3*pth3+p_L_h4*pth4+p_L_h5*pth5
	f.write("P(h1 | Q) = "+str(pth1))
	f.write("\n")
	f.write("P(h2 | Q) = "+str(pth2))
	f.write("\n")
	f.write("P(h3 | Q) = "+str(pth3))
	f.write("\n")
	f.write("P(h4 | Q) = "+str(pth4))
	f.write("\n")
	f.write("P(h5 | Q) = "+str(pth5))
	f.write("\n")
	f.write("\n")
	f.write("Probability that the next candy we pick will be C, given Q: "+str(Pt1c))
	f.write("\n")
	f.write("Probability that the next candy we pick will be L, given Q: "+str(Pt1l))
	P_H1_Q.append(pth1)
	P_H2_Q.append(pth2)
	P_H3_Q.append(pth3)
	P_H4_Q.append(pth4)
	P_H5_Q.append(pth5)
	P_Q_next_C.append(Pt1c)
	P_Q_next_L.append(Pt1l)
f.write("\n")


def gcd(n, m):
    if m == 0:
        return n
    return gcd(m, n % m)

A = list(map(int, input().split()))

lcm = 1
for i in A:
    lcm = lcm * i // gcd(lcm, i)
print(lcm)


import tensorflow as tf

class Teacher(object):
    #adapted from https://leimao.github.io/blog/Save-Load-Inference-From-TF-Frozen-Graph/
    def __init__(self, model_filepath):

        # The file path of model
        self.model_filepath = model_filepath
        # Initialize the model
        self.load_graph(model_filepath = self.model_filepath)

    def load_graph(self, model_filepath):
        '''
        Lode trained model.
        '''
        print('Loading model...')
        self.graph = tf.Graph()

        with tf.gfile.GFile(model_filepath, 'rb') as f:
            graph_def = tf.GraphDef()
            graph_def.ParseFromString(f.read())

        print('Check out the input placeholders:')
        nodes = [n.name + ' => ' +  n.op for n in graph_def.node if n.op in ('Placeholder')]
        for node in nodes:
            print(node)

        with self.graph.as_default():
            self.VisInput = tf.placeholder(shape=[None, 168, 168, 3], dtype=tf.float32,name="visual_observation_0")
            self.VecInput = tf.placeholder(shape=[None, 8], dtype=tf.float32,name='vector_observation')
            self.action_masks = tf.placeholder(shape=[None, 11], dtype=tf.float32, name="action_masks")
            tf.import_graph_def(graph_def, {'visual_observation_0': self.VisInput,
                                            'vector_observation': self.VecInput,
                                            'action_masks':self.action_masks})
            #self.init = tf.global_variables_initializer()

        self.graph.finalize()

        print('Model loading complete!')

        # Get layer names
        layers = [op.name for op in self.graph.get_operations()]
        for layer in layers:
            print(layer)

        """
        # Check out the weights of the nodes
        weight_nodes = [n for n in graph_def.node if n.op == 'Const']
        for n in weight_nodes:
            print("Name of the node - %s" % n.name)
            # print("Value - " )
            # print(tensor_util.MakeNdarray(n.attr['value'].tensor))
        """

        # In this version, tf.InteractiveSession and tf.Session could be used interchangeably.
        #self.sess = tf.InteractiveSession(graph = self.graph)
        self.sess = tf.Session(graph = self.graph)

        #self.sess.run(self.init)

    def get_teacher_action(self, visIn, vecIn, ActMask):
        #'dense/kernel:0', 'dense_1/kernel:0', 'dense_2/kernel:0', 'dense_3/kernel:0', 'dense_4/kernel:0'

        # Know your output node name
        output_tensor = self.graph.get_tensor_by_name("import/action:0")
        #enc_tensor = self.graph.get_tensor_by_name('import/concat:0')
        #output = self.sess.run([output_tensor, enc_tensor], feed_dict = {self.VisInput: visIn, self.VecInput: vecIn, self.action_masks: ActMask})
        output = self.sess.run(output_tensor, feed_dict = {self.VisInput: visIn, self.VecInput: vecIn, self.action_masks: ActMask})

        return output


from xml.dom.minidom import *
from spider import Spider

class SpiderXmlFactory:
    def __init__(self):
        self._filename = "params.xml"
        self._parameters = "parameters"
        self._page = "page"
        self._domain = "domain"
        self._depth = "depth"

    def create_spider(self):
        spider = Spider()

        xml = parse(self._filename)
        params = xml.getElementsByTagName(self._parameters)
        if params is not None:
            params = params[0]

            pages = params.getElementsByTagName(self._page)
            for page in pages:
                print(page.firstChild.data)
                spider.add_url(page.firstChild.data)

            domains = params.getElementsByTagName(self._domain)
            for domain in domains:
                print(domain.firstChild.data)
                spider.add_domain(domain.firstChild.data)

            depth = params.getElementsByTagName(self._depth)
            if depth is not None:
                depth = depth[0]
                print(depth.firstChild.data)
                spider.set_max_depth(depth.firstChild.data)

        return spider


print(" >> Tempo de trabalho sem acidente <<")
dias = int(input(" Digite o tempo sem acidentes (em dias):"))
dias_copia = dias
anos = dias// 365
dias = dias - (anos*356)
meses = dias // 30
dias = dias - (meses*30)

print(str(dias_copia) + "dias = " + str(anos) + " anos," + str(meses) + "meses e" + str(dias) + "dias")


import pygame

class Animation:

	def __init__(self, settings, file_pattern, file_pattern_frame_token, label, fps, max_size=None, does_loop=True):

		self.settings = settings
		self.file_pattern = file_pattern
		self.file_pattern_frame_token = file_pattern_frame_token
		self.label = label
		self.fps = None
		if max_size is None:
			max_size = settings.board_actor_default_max_size
		elif isinstance(max_size, int):
			max_size = (max_size, max_size)
		self.max_size_x, self.max_size_y = max_size

		self.does_loop = does_loop
		self.animation_finished = False

		self.ms_per_frame = None
		self.set_fps(fps)

		self.rect = None
		self.image = None
		self.images = None
		self.load_images()

		self.__current_animation_frame = 0
		self.time_since_last_frame_change = 0

	def set_fps(self, fps):

		self.fps = fps
		self.ms_per_frame = 1000 / self.fps

	def load_images(self):

		images = []

		#
		print(self.label, ":: Attempting to load from pattern:", self.file_pattern)

		# Load up to 1,000 frames
		for i in range(1, 1000):

			image_file_path = self.file_pattern
			image_file_path = image_file_path.replace(self.file_pattern_frame_token, str(i))

			try:
				image = pygame.image.load(image_file_path)
			except pygame.error:
				print(self.label, ": Loaded", str(len(images)), "frames for image set:", self.file_pattern)
				break

			image = self.resize_image_to_max_size(image)
			images.append(image)

		self.images = images
		self.activate_image(self.images[0])

	def resize_image_to_max_size(self, image):

		# Resize?
		# print(self.label, ":: Attempting to resize to ", self.max_size_x, self.max_size_y)
		if (not self.max_size_x) and (not self.max_size_y):
			return image

		image_rect = image.get_rect()
		ratio_x = self.max_size_x / (image_rect.width + (self.settings.board_actor_padding * 2))
		ratio_y = self.max_size_y / (image_rect.height + (self.settings.board_actor_padding * 2))

		# Resize down or up
		if ratio_x != 1 or ratio_y != 1:

			# Choose the smaller side
			if ratio_x < ratio_y:
				ratio = ratio_x
			else:
				ratio = ratio_y

			if ratio != 1:
				new_width = int(image_rect.width * ratio)
				new_height = int(image_rect.height * ratio)
				image = pygame.transform.smoothscale(image, (new_width, new_height))

		return image

	def animate(self, elapsed_ms):

		to_return = None
		image = None

		self.time_since_last_frame_change += elapsed_ms

		while self.time_since_last_frame_change >= self.ms_per_frame:

			self.time_since_last_frame_change -= self.ms_per_frame

			frame_number = self.adjust_current_animation_frame(1)

			if frame_number >= len(self.images) - 1:
				if self.does_loop:
					self.set_current_animation_frame(0)
				else:
					self.set_current_animation_frame(len(self.images) - 1)
					self.animation_finished = True
			image = self.images[self.get_current_animation_frame()]

		#
		if image:
			to_return = self.activate_image(image)

		return to_return

	def is_finished(self):

		return self.animation_finished

	def activate_image(self, image):

		self.image = image
		self.rect = self.image.get_rect()

		return self.rect

	def get_image(self):

		return self.image

	def get_rect(self):

		return self.rect.copy()

	def get_frame_count(self):

		return len(self.images)

	def adjust_current_animation_frame(self, n):

		return self.set_current_animation_frame(
			self.get_current_animation_frame() + n
		)

	def set_current_animation_frame(self, n):

		if n < 0:
			n = 0
		elif n >= len(self.images):
			n = 0

		self.__current_animation_frame = n

		return n

	def get_current_animation_frame(self):

		return self.__current_animation_frame

	def start_over(self):

		self.animation_finished = False
		self.set_current_animation_frame(0)
		self.activate_image(self.images[self.get_current_animation_frame()])
		self.time_since_last_frame_change = 0

	def update(self, elapsed_ms):

		self.animate(elapsed_ms)


try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

config = {
    'description': 'benchlingapi',
    'author': 'Justin D Vrana',
    'url': 'https://github.com/klavinslab/benchlingapi',
    'download_url': 'https://github.com/klavinslab/benchlingapi.git',
    'author_email': 'justin.vrana@gmail.com',
    'version': '0.9.1',
    'install_requires': ['requests', 'bs4'],
    'packages': ['benchlingapi'],
    'tests_require': ['pytest'],
    'scripts': [],
    'name': 'benchlingapi',
    'license': 'Copyright University of Washington'
}

setup(**config)


"""
This file houses a local db object. This allows us to develop without having an actual database
instance running. This is only for testing purposes

Note that all data storage is in memory, so do not run on this mode for too long.
Also note that this is news application specific, and hence contains articles and sources
"""
import logging

from tinydb import TinyDB, Query
from ..dbobject import DBObject
from ...utils.general import copy_dict_shallow

logger = logging.getLogger(__name__)

class LocalDatabase(object):
    """
    Based on tinydb. This database is meant to be used when developing locally.
    Currently only supports articles and sources

    Generally, the functions starting in underscore require tindb.Query() objects to
    be passed in. Use the other ones when calling transactions from outside.
    """

    def __init__(self, articles=None, sources=None, json_save_file='database.json'):

        self.db = TinyDB(json_save_file)
        self.articles = self.db.table('articles')
        self.sources = self.db.table('sources')

        for article in articles:
            self.articles.insert(copy_dict_shallow(article))

        for source in sources:
            self.sources.insert(copy_dict_shallow(source))

        self.tables = { 'articles', 'sources' }

    def _insert(self, tableName, obj):
        """
        Save the object to the database
        """
        assert tableName in self.tables

        table = getattr(self, tableName)
        table.insert(obj)

    def _get(self, tableName, query):
        assert tableName in self.tables
        table = getattr(self, tableName)
        return table.search(query)

    def _updateAll(self, tableName, query, fields):
        """
        Update all records matching query to contain fields
        """
        assert tableName in self.tables
        table = getattr(self, tableName)
        table.update(fields, query)

    def get(self, tableName, fields=None, query={}):
        """
        Get all records in the given table that match query. Return the fields that are requested.
        fields: list of str
        query: dict { key: value, ... }
        """

        # Build a tinydb.Query()
        MatchingQuery = Query()
        for key, value in query.items():
            MatchingQuery = MatchingQuery & (Query()[key] == value)

        matches = self._get(tableName, MatchingQuery)

        # Filter only the fields that we want
        results = list()
        for match in matches:
            filtered_match = dict()
            for key, value in match.items():
                if fields == None or key in fields:
                    filtered_match[key] = value
            results.append(filtered_match)

        return results

    def updateOrInsertOne(self, tableName, query, fields):
        """
        If there are 0 records that match query, add in the entirety of fields as a new
            record into the db under tableName
        If there is exactly 1 record that matches query, update that record with fields
        If there is more than one record that matches query, error.
        """

        # Query the database with the given query
        MatchingQuery = Query()
        for key, value in query.items():
            MatchingQuery = MatchingQuery & (Query()[key] == value)

        existing_sources = self._get(
            tableName=tableName,
            query=MatchingQuery
        )

        if len(existing_sources) > 1:
            # Something has gone wrong
            logger.exception("db.updateOne failed. Found {0} in {1} that match {2}".format(
                len(existing_sources),
                tableName,
                query
            ))
            raise Exception()
        elif len(existing_sources) == 0:
            # Insert this into the DB
            logger.debug("Found 0 existing records for query {0}. Inserting {1} into db.".format(
                query,
                fields
            ))
            self._insert(
                tableName=tableName,
                obj=fields
            )
        else:
            # Update the one record that exists in the DB
            assert len(existing_sources) == 1 # Sanity check
            logger.debug("Found 1 existing record for query {0}. Updating with {1}".format(
                query,
                fields
            ))
            self._updateAll(
                tableName=tableName,
                query=MatchingQuery,
                fields=fields
            )


id = "aa"
in_A = 11; in_B = "aa"
if id == in_A:
	print("Hello. A")
elif id == in_B:
	print("Hello. B")
else:
	print("WHO???")

"""
id=11
in_A=11;in_B="aa"
if id==in_A
	puts("Hello! A")
elseif id==in_B
	puts("Hello! B")
else
	puts("WHO???")
end
"""


#!usr/bin/env python3
from collections import defaultdict
from collections import deque
from heapq import heappush, heappop
import sys
import math
import bisect
import random
def LI(): return list(map(int, sys.stdin.readline().split()))
def I(): return int(sys.stdin.readline())
def LS():return list(map(list, sys.stdin.readline().split()))
def S(): return list(sys.stdin.readline())[:-1]
def IR(n):
    l = [None for i in range(n)]
    for i in range(n):l[i] = I()
    return l
def LIR(n):
    l = [None for i in range(n)]
    for i in range(n):l[i] = LI()
    return l
def SR(n):
    l = [None for i in range(n)]
    for i in range(n):l[i] = S()
    return l
def LSR(n):
    l = [None for i in range(n)]
    for i in range(n):l[i] = SR()
    return l
mod = 1000000007

#A
"""
s = input()
print(s+"pp")
"""

#B
"""

n = I()
a = LI()
ans = 0
f = [0,0,1,0,1,2,3,0,1,0]
for i in a:
    ans += f[i]
print(ans)
"""

#C
"""
xs,ys,xg,yg,t,v = LI()
n = I()
l = t*v
ans = "NO"
for i in range(n):
    x,y = LI()
    d = ((x-xs)**2+(y-ys)**2)**(1/2)+((x-xg)**2+(y-yg)**2)**(1/2)
    if d <= l:
        ans = "YES"
print(ans)
"""

#D
def bfs(s,g,n):
    bfs_map = [-1 for i in range(n)]
    bfs_map[s] = 0
    q = deque()
    q.append(s)
    fin = False
    while q:
        x = q.popleft()
        for y in range(n):
            if c[x][y] > 0 and bfs_map[y] < 0:
                bfs_map[y] = bfs_map[x]+1
                if y == g:
                    fin = True
                    break
                q.append(y)
        if fin:
            break

    if bfs_map[g] == -1:
        return [None,0]
    path = [None for i in range(bfs_map[g]+1)]
    m = float("inf")
    path[bfs_map[g]] = g
    y = g
    for i in range(bfs_map[g])[::-1]:
        for x in range(n+1):
            if c[x][y] > 0 and bfs_map[x] == bfs_map[y]-1:
                path[i] = x
                if c[x][y] < m:
                    m = c[x][y]
                y = x
                break
    return [path,m]

def ford_fulkerson(s,g,c,n):
    while 1:
        p,m = bfs(s,g,n)
        if not m:break
        for i in range(len(p)-1):
            c[p[i]][p[i+1]] -= m
            c[p[i+1]][p[i]] += m

    return sum(c[g])

n,g,e = LI()
p = LI()
c = [[0 for i in range(n+1)] for j in range(n+1)]
for i in p:
    c[i][n] = 1
for i in range(e):
    a,b = LI()
    c[a][b] = 1
    c[b][a] = 1
print(ford_fulkerson(0,n,c,n+1))

#E

#F

#G

#H

#I

#J

#K

#L

#M

#N

#O

#P

#Q

#R

#S

#T


import discord
from discord.ext import commands

bot = commands.Bot(command_prefix='€', description="Este es el bot de fuentes")

@bot.command()
async def guillermina(ctx):
    await ctx.send('donde esta alfredito?')

@bot.command()
async def programeitor(ctx):
    ctx.send('guille deja de programar coñooooo')

@bot.event
async def on_ready():
    print('Esto funciona')

bot.run('820248417615740939')


#-*- coding: utf-8 -*-
from __future__ import print_function
import os
import rsa
import json
import time
import binascii
import requests

class KsherPay(object):
    __nonce_str = (''.join(map(lambda x: (hex(x)[2:]), os.urandom(17))))[:32]
    __time_stamp = time.strftime('%Y%m%d%H%M%S%SS')
    __DOMAIN = 'https://api.mch.ksher.net/KsherPay'
    __GATEWAY_DOMAIN = 'https://gateway.ksher.com/api'
    def __init__(self, appid='', privatekey='', pubkey='', version='3.0.0'):
        self.appid = appid # ksher appid
        self.privatekey = privatekey # 私钥
        self.pubkey = pubkey # ksher公钥
        self.version = version # SDK版本

    def __new__(cls, *args, **kwargs):
        if not hasattr(KsherPay, "_instance"):
            KsherPay.__instance = object.__new__(cls)
        return KsherPay.__instance

    def __ksher_sign(self, kwargs):
        """
        签名
        :param kwargs:
        :return:
        """
        print("__ksher_sign:",kwargs)
        alist = sorted(["%s=%s" % (key, str(value)) for key, value in kwargs.items()])
        predata = "".join(alist).encode('utf8')
        print("predata:",predata)
        keydata = ''
        with open(self.privatekey) as f:
            keydata = f.read()
        privkeystr = rsa.PrivateKey.load_pkcs1(keydata, 'PEM')
        signature = rsa.sign(predata, privkeystr, 'MD5')
        signature = binascii.hexlify(signature)
        return signature

    def __verify_ksher_sign(self, signature, kwargs):
        """
        验签
        :param signature:
        :param kwargs:
        :return:
        """
        predata = "".join(sorted(["%s=%s" % (key, kwargs[key]) for key in kwargs.keys()])).encode('utf-8')
        pubkey = ''

        try:
            with open(self.pubkey) as f:
                pubkey = rsa.PublicKey.load_pkcs1(f.read())
            ecodesign = binascii.unhexlify(signature)
            if rsa.verify(predata, ecodesign, pubkey):
                print('验签通过......')
                return True
        except Exception as e:
            # if e.message == 'Verification failed':
            print('验签失败......')
            return False

    def _request(self, url, data, m=""):
        sign = self.__ksher_sign(data)
        data.update({'sign': sign.decode()})
        print('请求{}接口的请求数据:\n {}'.format(url, json.dumps(data, sort_keys=True, indent=4)))
        if m == "POST":
            r = requests.post(url, data, timeout=60)
        else:
            r = requests.get(url, params=data, timeout=60)
        response = r.text
        if r.status_code == 200:
            response = r.json()
            if response.get('code') == 0:
                signature = response.get('sign', '')
                verified = self.__verify_ksher_sign(signature, response.get('data'))
                verified = True
                if not verified:
                    response = {
                        "code": 0,
                        "data": {
                            "err_code": "VERIFY_KSHER_SIGN_FAIL",
                            "err_msg": "verify signature failed",
                            "result": "FAIL"
                        },
                        "msg": "ok",
                        "sign": "",
                        "status_code": "",
                        "status_msg": "",
                        "time_stamp": self.__time_stamp,
                        "version": self.version
                    }
                    return response
        print('请求{}接口的响应数据:\n {}'.format(url, json.dumps(response, sort_keys=True, indent=4)))
        return response

    def quick_pay(self, **kwargs):
        """
        B扫C支付
        :param kwargs:
        Mandatory params:
                mch_order_no
                total_fee
                fee_type
                auth_code
                channel
            Optional Params
                operator_id
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/quick_pay'.format(self.__DOMAIN), data=kwargs)
        return response

    def jsapi_pay(self, **kwargs):
        """
        C扫B支付
        :param kwargs:
        Mandatory params:
                mch_order_no
                total_fee
                fee_type
                channel
        Optional Params:
                redirect_url
                notify_url
                paypage_title
                operator_id
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/jsapi_pay'.format(self.__DOMAIN), data=kwargs)
        return response

    def native_pay(self, **kwargs):
        """
        动态码支付
        :param kwargs:
        Mandatory params:
                mch_order_no
                total_fee
                fee_type
                channel
        Optional Params:
                redirect_url
                notify_url
                paypage_title
                product
                attach
                operator_id
                device_id
                img_type
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/native_pay'.format(self.__DOMAIN), data=kwargs)
        return response

    def minipro_pay(self, **kwargs):
        """
        小程序支付
        :param kwargs:
        Mandatory params:
                mch_order_no
                total_fee
                fee_type
                channel
                sub_openid
                channel_sub_appid

        Optional Params:
                redirect_url
                notify_url
                paypage_title
                product
                operator_id
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/mini_program_pay'.format(self.__DOMAIN), data=kwargs)
        return response

    def app_pay(self, **kwargs):
        """
        app支付
        :param kwargs:
        Mandatory params:
                mch_order_no
                total_fee
                fee_type
                channel
                sub_openid
                channel_sub_appid

        Optional Params:
                redirect_url
                notify_url
                paypage_title
                product
                attach
                operator_id
                refer_url 仅当channel为alipay时需要
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/app_pay'.format(self.__DOMAIN), data=kwargs)
        return response

    def wap_pay(self, **kwargs):
        """
        H5支付，仅支持channel=alipay
        :param kwargs:
        Mandatory params:
                mch_order_no
                total_fee
                fee_type
                channel

        Optional Params:
                redirect_url
                notify_url
                paypage_title
                product
                attach
                operator_id
                device_id
                refer_url
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/wap_pay'.format(self.__DOMAIN), data=kwargs)
        return response

    def web_pay(self, **kwargs):
        """
        PC网站支付，仅支持channel=alipay
        :param kwargs:
        Mandatory params:
                mch_order_no
                total_fee
                fee_type
                channel

        Optional Params:
                redirect_url
                notify_url
                paypage_title
                product
                attach
                operator_id
                device_id
                refer_url
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/web_pay'.format(self.__DOMAIN), data=kwargs)
        return response

    def order_query(self, **kwargs):
        """
        订单查询
        :param kwargs:
        Mandatory params:
                mch_order_no、ksher_order_no、channel_order_no三选一
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/order_query'.format(self.__DOMAIN), data=kwargs, m="GET")
        return response

    def order_close(self, **kwargs):
        """
        订单关闭
        :param kwargs:
        Mandatory params:
                mch_order_no、ksher_order_no、channel_order_no三选一
        Optional Params:
                operator_id
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/order_close'.format(self.__DOMAIN), data=kwargs)
        return response

    def order_reverse(self, **kwargs):
        """
        订单撤销
        :param kwargs:
        Mandatory params:
                mch_order_no、ksher_order_no、channel_order_no三选一
        Optional Params:
                operator_id
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/order_reverse'.format(self.__DOMAIN), data=kwargs)
        return response

    def order_refund(self, **kwargs):
        """
        订单退款
        :param kwargs:
        Mandatory params:
                total_fee
                fee_type
                refund_fee
                mch_refund_no
                mch_order_no、ksher_order_no、channel_order_no三选一
        Optional Params:
                operator_id
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/order_refund'.format(self.__DOMAIN), data=kwargs)
        return response

    def refund_query(self, **kwargs):
        """
        退款查询
        :param kwargs:
        Mandatory params:
                mch_refund_no、ksher_refund_no、channel_refund_no三选一
                mch_order_no、ksher_order_no、channel_order_no三选一
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/refund_query'.format(self.__DOMAIN), data=kwargs, m="GET")
        return response

    def rate_query(self, **kwargs):
        """
        汇率查询
        :param kwargs:
        Mandatory params:
                channel
                fee_type
                date
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        response = self._request(url='{}/rate_query'.format(self.__DOMAIN), data=kwargs,m="GET")
        return response

    def gateway_order_query(self, **kwargs):
        """
        聚合支付商户查询订单支付状态
        :param kwargs:
        Mandatory params:
                mch_order_no
        :return:
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        print('kwargs: ', kwargs)
        print('===================')
        response = self._request(url='{}/gateway_order_query'.format(self.__GATEWAY_DOMAIN), data=kwargs, m="GET")
        return response

    def gateway_pay(self, **kwargs):
        """
        Gateway Pay API params
        聚合支付商户通过API提交数据
        :param kwargs:
        mandatory parmas:

                mch_order_no: 商户订单号 str
                total_fee: 金额(分) int
                fee_type: 货币种类 st
                channel_list: 支付通道 str
                mch_code: 商户订单code str
                mch_redirect_url: 商户通知url str
                mch_redirect_url_fail: 失败回调网址 str
                product_name: 商品描述 str
                refer_url: 商家refer str
                device: 设备名称(PC or H5) str

        Optional params:

                color: 横幅颜色 str
                background: 横幅背景图片 str
                payment_color: 支付按钮颜色 str
                ksher_explain: 最下方文案 str
                hide_explain: 是否显示最下方文案(1显示 0不显示) int
                expire_time: 订单过期时间(min) int
                hide_exp_time: 是否显示过期时间(1显示 0不显示) int
                logo: 横幅logo str
                lang: 语言(en,cn,th) str
                shop_name: logo旁文案 str
                attach: 商户附加信息 str
        :return:
        {'pay_content': 'https://gateway.ksher.com/mindex?order_uuid=订单uuid'}
        """
        kwargs.update({'appid': self.appid, 'nonce_str': self.__nonce_str, 'time_stamp': self.__time_stamp})
        print("kwargs: ", kwargs)
        print("===============")
        response = self._request(url='{}/gateway_pay'.format(self.__GATEWAY_DOMAIN), data=kwargs)
        return response


import requests
from lxml import html

sess = requests.Session()
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
}

url = "https://stackoverflow.com/"
r = sess.get(url, headers=headers)
tree = html.fromstring(r.text)

links = tree.xpath('//div[@class="summary"]/h3/a/@href')