# -*- coding: utf-8 -*-

import datetime
import logging

from pytz import timezone, UTC, utc
from datetime import datetime, time, timedelta, date
from odoo import api, fields, models
from odoo.exceptions import ValidationError, UserError
from odoo.osv import expression
from odoo.tools.translate import _
from odoo.tools.float_utils import float_round
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from odoo.addons.resource.models.resource import float_to_time, datetime_to_string, string_to_datetime, HOURS_PER_DAY
from odoo.addons.resource.models.resource import Intervals

class HolidaysType(models.Model):
    _inherit = "hr.leave.type"

    unpaid = fields.Boolean('Es se paga?', default=False)
    request_unit = fields.Selection([
        ('day', 'Días'), ('hour', 'Horas')],
        default='day', string='Tomar ausencias en', required=True)
    time_type = fields.Selection([
        ('leave', 'Ausentismo'),
        ('other', 'Other'),
        ('inability', 'Incapacidad'),],
        default='leave', string="Tipo de licencia",
        help="Si esto debe calcularse como vacaciones o como tiempo de trabajo (por ejemplo: formación)")
    allocation_type = fields.Selection([
        ('fixed', 'Arreglado por HR'),
        ('fixed_allocation', 'Solucionado por solicitud de asignación de recursos humanos'),
        ('no', 'Sin asignación')],
        default='fixed', string='Modo',
        help='\tCorregido por HR: asignado por HR y no se puede omitir; los usuarios pueden solicitar hojas;'
             '\tSolucionado por solicitud de asignación de recursos humanos +: asignado por recursos humanos y los usuarios pueden solicitar permisos y asignaciones;'
             '\tSin asignación: sin asignación por defecto, los usuarios pueden solicitar permisos libremente;')
    code = fields.Char('Code', required=True)
    color_name = fields.Selection([
        ('red', 'Red'),
        ('blue', 'Blue'),
        ('lightgreen', 'Light Green'),
        ('lightblue', 'Light Blue'),
        ('lightyellow', 'Light Yellow'),
        ('magenta', 'Magenta'),
        ('lightcyan', 'Light Cyan'),
        ('black', 'Black'),
        ('lightpink', 'Light Pink'),
        ('brown', 'Brown'),
        ('violet', 'Violet'),
        ('lightcoral', 'Light Coral'),
        ('lightsalmon', 'Light Salmon'),
        ('lavender', 'Lavender'),
        ('wheat', 'Wheat'),
        ('ivory', 'Ivory'),
        ('orange', 'Orange'),
        ('golden', 'Golden'),
        ('fuchsia', 'Fuchsia'),
        ], string='Color in Report', required=True, default='red',
        help='This color will be used in the leaves summary located in Reporting > Leaves by Department.')

    _sql_constraints = [('code_unique', 'unique(Code)', "the code must be unique")]

    @api.multi
    def name_get(self):
        res = []
        for record in self:
            name = record.name
            code = record.code
            if code:
                name = "[%(code)s] %(name)s" % {
                    'code': code,
                    'name': name,
                }
            res.append((record.id, name))
        return res

    @api.model
    def name_search(self, name, args=None, operator='like', limit=100, name_get_uid=None):
        args = args or []
        domain = []
        if name:
            domain = [('code', operator, name)]
        code = self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid)
        return self.browse(code).name_get()

class HolidaysRequest(models.Model):
    _inherit = "hr.leave"

    date_to = fields.Datetime(
        'End Date', readonly=True, copy=False, required=False,
        default=fields.Datetime.now,
        states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange')
    group_id = fields.Many2one('hr.group', "Group", readonly=True, related= 'employee_id.group_id', store=True)
    time_type = fields.Selection("Selection", related= 'holiday_status_id.time_type')
    # Translate fields
    request_unit_half = fields.Boolean('Half Day')
    type_inhability_id = fields.Many2one('hr.leave.inhability', "Type inhability")
    inhability_classification_id = fields.Many2one('hr.leave.classification', "Classification")
    inhability_category_id = fields.Many2one('hr.leave.category', "Category")
    inhability_subcategory_id = fields.Many2one('hr.leave.subcategory', "Subcategory")
    folio = fields.Char('Folio')

    @api.multi
    @api.onchange('type_inhability_id')
    def onchange_type_inhability_id(self):
        self.inhability_classification_id = False
        domain = {'inhability_classification_id': [('id', 'in', self.type_inhability_id.classification_ids.ids)]}
        return {'domain': domain}

    @api.multi
    @api.onchange('inhability_classification_id')
    def onchange_inhability_classification_id(self):
        self.inhability_category_id = False
        domain = {'inhability_category_id': [('id', 'in', self.inhability_classification_id.category_ids.ids)]}
        return {'domain': domain}

    @api.multi
    @api.onchange('inhability_category_id')
    def onchange_inhability_category_id(self):
        self.inhability_subcategory_id = False
        domain = {'inhability_subcategory_id': [('id', 'in', self.inhability_category_id.subcategory_ids.ids)]}
        return {'domain': domain}

    @api.multi
    def action_approve(self):
        if not self.request_date_to:
            raise UserError(_('You must enter the end date.'))
        if any(holiday.state != 'confirm' for holiday in self):
            raise UserError(_('Leave request must be confirmed ("To Approve") in order to approve it.'))

        current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
        self.filtered(lambda hol: hol.validation_type == 'both').write({'state': 'validate1', 'first_approver_id': current_employee.id})
        self.filtered(lambda hol: not hol.validation_type == 'both').action_validate()
        if not self.env.context.get('leave_fast_create'):
            self.activity_update()
        return True

    def request_parameters(self, employee, request_date_from, number_of_days, request_date_from_period):
        if not number_of_days or number_of_days < 0:
            raise UserError(_('Negative or empty values are not allowed for the number of days.'))
        if not employee:
            raise UserError(_('The employee is required.'))
        employee_id = self.env['hr.employee'].search([('id','=', employee)])
        if not employee_id:
            raise UserError(_('No employees found for the key %s.') % employee)

        dates = {}
        calendar = employee_id.resource_calendar_id or self.env.user.company_id.resource_calendar_id
        request_date_from = datetime.strptime(fields.Date.from_string(request_date_from).strftime(DEFAULT_SERVER_DATE_FORMAT), DEFAULT_SERVER_DATE_FORMAT)
        tz = self.env.user.tz if self.env.user.tz and not self.request_unit_custom else 'UTC'  # custom -> already in UTC

        domain = [('calendar_id', '=', calendar.id or self.env.user.company_id.resource_calendar_id.id)]
        attendances = self.env['resource.calendar.attendance'].search(domain, order='dayofweek, day_period DESC')

        # find first attendance coming after first_day
        attendance_from = next((att for att in attendances if int(att.dayofweek) >= request_date_from.weekday()), attendances[0])
        hour_from = float_to_time(attendance_from.hour_from)

        request_date_from = timezone(tz).localize(datetime.combine(request_date_from.date(), hour_from)).astimezone(UTC).replace(tzinfo=None)
        request_date_to = request_date_from + timedelta(hours=calendar.hours_per_day or HOURS_PER_DAY)

        # find last attendance coming before last_day
        attendance_to = next((att for att in reversed(attendances) if int(att.dayofweek) <= request_date_to.weekday()), attendances[-1])
        hour_to = float_to_time(attendance_to.hour_to)
        request_date_from = timezone(tz).localize(datetime.combine(request_date_from.date(), hour_from)).astimezone(UTC).replace(tzinfo=None)
        # if ist half day
        if number_of_days == 0.5 and request_date_from_period:
            if request_date_from_period == 'am':
                hour_from = float_to_time(attendance_from.hour_from)
                hour_to = float_to_time(attendance_from.hour_to)
            else:
                hour_from = float_to_time(attendance_to.hour_from)
                hour_to = float_to_time(attendance_to.hour_to)

            # ~ half_day = calendar.hours_per_day / 2 or HOURS_PER_DAY / 2
            request_date_from = timezone(tz).localize(datetime.combine(request_date_from.date(), hour_from)).astimezone(UTC).replace(tzinfo=None)
            request_date_to = timezone(tz).localize(datetime.combine(request_date_to.date(), hour_to)).astimezone(UTC).replace(tzinfo=None)
        if number_of_days == 1:
            request_date_to = request_date_from + timedelta(hours=calendar.hours_per_day or HOURS_PER_DAY)
        if number_of_days > 1:
            request_date_to = request_date_from + timedelta(days=number_of_days)

        dates['request_date_from'] = request_date_from.date()
        dates['request_date_to'] = request_date_to.date()
        dates['date_from'] = request_date_from
        dates['date_to'] = request_date_to
        dates['request_date_from_period'] = request_date_from_period
        return dates

    @api.model
    def create(self, values):
        """ Override to avoid automatic logging of creation """
        if self.env.context.get('import_file'):
            request_parameters = self.request_parameters(values.get('employee_id'),values.get('request_date_from'),values.get('number_of_days'),values.get('request_date_from_period'))
            values['request_date_from'] = request_parameters.get('request_date_from')
            values['request_date_to'] = request_parameters.get('request_date_to')
            values['date_from'] = request_parameters.get('date_from')
            values['date_to'] = request_parameters.get('date_to')
            values['request_date_from_period'] = request_parameters.get('request_date_from_period') if request_parameters.get('request_date_from_period') else None
        return super(HolidaysRequest, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(values)

class CalendarLeaves(models.Model):
    _inherit = "resource.calendar.leaves"

    time_type = fields.Selection(selection_add=[('inability', 'Incapacidad')])

# ~ def string_to_datetime(value):
    # ~ """ Convert the given string value to a datetime in UTC. """
    # ~ return utc.localize(fields.Datetime.from_string(value))

# ~ def datetime_to_string(dt):
    # ~ """ Convert the given datetime (converted in UTC) to a string value. """
    # ~ return fields.Datetime.to_string(dt.astimezone(utc))

class ResourceCalendar(models.Model):
    _inherit = "resource.calendar"

    def _leave_intervals(self, start_dt, end_dt, resource=None, domain=None):
        """ Return the leave intervals in the given datetime range.
            The returned intervals are expressed in the calendar's timezone.
        """
        assert start_dt.tzinfo and end_dt.tzinfo
        self.ensure_one()

        # for the computation, express all datetimes in UTC
        resource_ids = [resource.id, False] if resource else [False]
        if domain is None:
            domain = [('time_type', 'in', ['leave','inability'])]
        domain = domain + [
            ('calendar_id', '=', self.id),
            ('resource_id', 'in', resource_ids),
            ('date_from', '<=', datetime_to_string(end_dt)),
            ('date_to', '>=', datetime_to_string(start_dt)),
        ]

        # retrieve leave intervals in (start_dt, end_dt)
        tz = timezone((resource or self).tz)
        start_dt = start_dt.astimezone(tz)
        end_dt = end_dt.astimezone(tz)
        result = []
        for leave in self.env['resource.calendar.leaves'].search(domain):
            dt0 = string_to_datetime(leave.date_from).astimezone(tz)
            dt1 = string_to_datetime(leave.date_to).astimezone(tz)
            result.append((max(start_dt, dt0), min(end_dt, dt1), leave))

        return Intervals(result)


# 996. Number of Squareful Arrays

# 2021/02/11
# Runtime: 1120 ms, faster than 5.05% of Python3 online submissions for Number of Squareful Arrays.
# Memory Usage: 14.4 MB, less than 56.49% of Python3 online submissions for Number of Squareful Arrays.

# 感觉就是全排列问题
# 但是仅仅是勉强过了，难道可以优化？
# 剪枝 - 1、去重；2、相邻两数是平方数

class Solution:
    def numSquarefulPerms(self, A: List[int]) -> int:
        self.ans = 0
        A.sort()
        self.dfs(A, [], [False] * len(A))
        return self.ans

    def dfs(self, A, perm, visited):
        if len(perm) == len(A):
            self.ans += 1
        for i in range(len(A)):
            if visited[i]: continue
            if i > 0 and A[i] == A[i - 1] and not visited[i - 1]: continue   # remove duplication
            if perm and not self.is_square(perm[-1] + A[i]): continue        # remove non-square pair
            visited[i] = True
            perm.append(A[i])
            self.dfs(A, perm, visited)
            visited[i] = False
            perm.pop()

    def is_square(self, x):                                                  # determine whether a number is a square
        i = 0
        while i * i < x:
            i += 1
        return True if i * i == x else False


# -*- coding: utf-8 -*-
"""
Created on Fri Aug 16 13:24:12 2019

@author: USER
"""

# -*- coding: utf-8 -*-
"""
Created on Mon Oct  8 21:07:41 2018

@author: USER
"""
import sys
from PyQt5.QtWidgets import *

try:
    import win32com.client
    import pythoncom
except:
    print("no window conmunication")

from pandas import DataFrame
#from threading import Timer,Thread,Event
import time

from subject import *
from observer import *
from timeManager import *

class XAQueryEventHandlerT2301:
    query_state = 0

    def OnReceiveData(self, code):
        XAQueryEventHandlerT2301.query_state = 1

#class PyOptHogaMon:
class PyOptHogaMon(Observer):
    def __init__(self):
        print("optmon has created")
        self.count = 0
        self.tmanager = timeManager()

    def update(self, 호가시간_, 단축코드_, 매도호가1_, 매수호가1_, 이론가_): #업데이트 메서드가 실행되면 변화된 감정내용을 화면에 출력해줍니다
        self.호가시간=호가시간_
        self.단축코드=단축코드_
        self.매도호가1=매도호가1_
        self.매수호가1=매수호가1_
        self.이론가 = 이론가_

        self.display()

    def register_subject(self, subject):
        self.subject = subject
        self.subject.register_observer(self)

    def display(self):
        #print ('호가시간:', self.호가시간, '단축코드:', self.단축코드 , '매도호가1:', self.매도호가1,'매수호가1:', self.매수호가1, '이론가:', self.이론가)
        pass
#       self.comm_connect()
#   self.get_code_list()

#--------------------------
# t2301  차트
#--------------------------
    def get_opt_chart(self, Option_expiration_mon):

        instXAQueryT2301 = win32com.client.DispatchWithEvents("XA_DataSet.XAQuery", XAQueryEventHandlerT2301)
        instXAQueryT2301.ResFileName = "C:\\eBEST\\xingAPI\\Res\\t2301.res"
        instXAQueryT2301.SetFieldData("t2301InBlock","yyyymm",0,Option_expiration_mon) #"201908" 형테
        instXAQueryT2301.SetFieldData("t2301InBlock","gubun",0,"G")
        instXAQueryT2301.Request(0)

        while XAQueryEventHandlerT2301.query_state == 0:
            pythoncom.PumpWaitingMessages()
        XAQueryEventHandlerT2301.query_state = 0

        histimpv = instXAQueryT2301.GetFieldData("t2301OutBlock", "histimpv",0)            #역사적 변동성
        jandatecnt = instXAQueryT2301.GetFieldData("t2301OutBlock", "jandatecnt",0) # 옵션 잔존일
        cimpv = instXAQueryT2301.GetFieldData("t2301OutBlock", "cimpv",0)           #콜옵션 대표 IV
        pimpv = instXAQueryT2301.GetFieldData("t2301OutBlock", "pimpv",0)           #풋옵션 대표 IV
        gmprice = instXAQueryT2301.GetFieldData("t2301OutBlock", "gmprice",0)       #근월물 현재가
        gmsign = instXAQueryT2301.GetFieldData("t2301OutBlock", "gmsign",0)         #근월물 전일대비 구분
        gmchange = instXAQueryT2301.GetFieldData("t2301OutBlock", "gmchange",0)     #근월물 전일대비
        gmdiff = instXAQueryT2301.GetFieldData("t2301OutBlock", "gmdiff",0)         #근월물 등락율
        gmvolume = instXAQueryT2301.GetFieldData("t2301OutBlock", "gmvolume",0)
        gmshcode = instXAQueryT2301.GetFieldData("t2301OutBlock", "gmshcode",0)

#        print(histimpv, jandatecnt,cimpv,  pimpv )

        count = instXAQueryT2301.GetBlockCount("t2301OutBlock1")

        #ohlcv = {'date':[], 'open':[], 'high':[], 'low':[], 'close':[]}
        ohlcv = { 'actprice':[], 'optcode':[], 'price':[], 'diff':[], 'volume':[],  'iv':[],  'offerho1':[], 'bidho1':[], 'theoryprice':[], 'impv':[], 'gmprice':[]}

        for i in range(count):
            actprice = instXAQueryT2301.GetFieldData("t2301OutBlock1", "actprice",i)
            optcode = instXAQueryT2301.GetFieldData("t2301OutBlock1", "optcode",i)
            price = instXAQueryT2301.GetFieldData("t2301OutBlock1", "price",i)
            sign = instXAQueryT2301.GetFieldData("t2301OutBlock1", "sign",i)
            diff = instXAQueryT2301.GetFieldData("t2301OutBlock1", "diff",i)

            volume = instXAQueryT2301.GetFieldData("t2301OutBlock1", "volume",i)
            iv = instXAQueryT2301.GetFieldData("t2301OutBlock1", "iv",i)
            mgjv = instXAQueryT2301.GetFieldData("t2301OutBlock1", "mgjv",i)
            mgjvupdn = instXAQueryT2301.GetFieldData("t2301OutBlock1", "mgjvupdn",i)
            offerho1 = instXAQueryT2301.GetFieldData("t2301OutBlock1", "offerho1",i)

            bidho1 = instXAQueryT2301.GetFieldData("t2301OutBlock1", "bidho1",i)
            cvolume = instXAQueryT2301.GetFieldData("t2301OutBlock1", "cvolume",i)
            delt = instXAQueryT2301.GetFieldData("t2301OutBlock1", "delt",i)
            gama = instXAQueryT2301.GetFieldData("t2301OutBlock1", "gama",i)
            vega = instXAQueryT2301.GetFieldData("t2301OutBlock1", "vega",i)

            ceta = instXAQueryT2301.GetFieldData("t2301OutBlock1", "ceta",i)
            rhox = instXAQueryT2301.GetFieldData("t2301OutBlock1", "rhox",i)
            theoryprice = instXAQueryT2301.GetFieldData("t2301OutBlock1", "theoryprice",i)
            impv = instXAQueryT2301.GetFieldData("t2301OutBlock1", "impv",i)
            timevl = instXAQueryT2301.GetFieldData("t2301OutBlock1", "timevl",i)

            jvolume = instXAQueryT2301.GetFieldData("t2301OutBlock1", "jvolume",i)
            parpl = instXAQueryT2301.GetFieldData("t2301OutBlock1", "parpl",i)
            jngo = instXAQueryT2301.GetFieldData("t2301OutBlock1", "jngo",i)
            offerrem1 = instXAQueryT2301.GetFieldData("t2301OutBlock1", "offerrem1",i)
            bidrem1 = instXAQueryT2301.GetFieldData("t2301OutBlock1", "bidrem1",i)

            open = instXAQueryT2301.GetFieldData("t2301OutBlock1", "open",i)
            high = instXAQueryT2301.GetFieldData("t2301OutBlock1", "high",i)
            low = instXAQueryT2301.GetFieldData("t2301OutBlock1", "low",i)
            atmgubun = instXAQueryT2301.GetFieldData("t2301OutBlock1", "atmgubun",i)
            jisuconv = instXAQueryT2301.GetFieldData("t2301OutBlock1", "jisuconv",i)

            value = instXAQueryT2301.GetFieldData("t2301OutBlock1", "value",i)

            ohlcv['actprice'].append(actprice)
            ohlcv['optcode'].append(optcode)
            ohlcv['price'].append(price)
            ohlcv['diff'].append(diff)
            ohlcv['volume'].append(volume)
            ohlcv['iv'].append(iv)
            ohlcv['offerho1'].append(offerho1)
            ohlcv['bidho1'].append(bidho1)
            ohlcv['theoryprice'].append(theoryprice)
            ohlcv['impv'].append(impv)
            ohlcv['gmprice'].append(gmprice)

            print(actprice, optcode, price, sign,  diff, volume, iv, mgjv, mgjvupdn, offerho1, bidho1, cvolume, delt, gama, vega, ceta, rhox, theoryprice)
            self.subject.change_optprice(timevl,optcode,offerho1,bidho1,theoryprice)

        count = instXAQueryT2301.GetBlockCount("t2301OutBlock2")

        #ohlcv = {'date':[], 'open':[], 'high':[], 'low':[], 'close':[]}
        ohlcv2 = {'actprice':[], 'optcode':[], 'price':[], 'diff':[], 'volume':[],  'iv':[],  'offerho1':[], 'bidho1':[], 'theoryprice':[], 'impv':[], 'gmprice':[]}

        for i in range(count):
            actprice2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "actprice",i)
            optcode2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "optcode",i)
            price2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "price",i)
            sign2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "sign",i)
            diff2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "diff",i)

            volume2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "volume",i)
            iv2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "iv",i)
            mgjv2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "mgjv",i)
            mgjvupdn2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "mgjvupdn",i)
            offerho12 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "offerho1",i)

            bidho12 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "bidho1",i)
            cvolume2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "cvolume",i)
            delt2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "delt",i)
            gama2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "gama",i)
            vega2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "vega",i)

            ceta2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "ceta",i)
            rhox2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "rhox",i)
            theoryprice2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "theoryprice",i)
            impv2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "impv",i)
            timevl2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "timevl",i)

            jvolume2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "jvolume",i)
            parpl2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "parpl",i)
            jngo2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "jngo",i)
            offerrem12 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "offerrem1",i)
            bidrem12 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "bidrem1",i)

            open2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "open",i)
            high2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "high",i)
            low2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "low",i)
            atmgubun2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "atmgubun",i)
            jisuconv2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "jisuconv",i)

            value2 = instXAQueryT2301.GetFieldData("t2301OutBlock2", "value",i)

            ohlcv2['actprice'].append(actprice2)
            ohlcv2['optcode'].append(optcode2)
            ohlcv2['price'].append(price2)
            ohlcv2['diff'].append(diff2)
            ohlcv2['volume'].append(volume2)
            ohlcv2['iv'].append(iv2)
            ohlcv2['offerho1'].append(offerho12)
            ohlcv2['bidho1'].append(bidho12)
            ohlcv2['theoryprice'].append(theoryprice2)
            ohlcv2['impv'].append(impv2)
            ohlcv2['gmprice'].append(gmprice)

            print(actprice2,optcode2, price2, sign2,  diff2, volume2, iv2, mgjv2, mgjvupdn2, offerho12, bidho12, cvolume2, delt2, gama2, vega2, ceta2, rhox2, theoryprice2)
            self.subject.change_optprice(timevl2,optcode2,offerho12,bidho12,theoryprice2)

#        self.subject.print_opt()
        return ohlcv, ohlcv2

#--------------------------
# XReal_OC0_  Real data Acquisition
#--------------------------

    def OnReceiveRealData(self, tr_code): # event handler
        """
        이베스트 서버에서 ReceiveRealData 이벤트 받으면 실행되는 event handler
        """
        self.count += 1
        #호가시간 = self.GetFieldData("OutBlock", "hoime")

        호가시간 = self.tmanager.getCurrentDash()
        매도호가1 = self.GetFieldData("OutBlock", "offerho1")
        매수호가1 = self.GetFieldData("OutBlock", "bidho1")
        매도호가2 = self.GetFieldData("OutBlock", "offerho2")
        매수호가2 = self.GetFieldData("OutBlock", "bidho2")
        단축코드 = self.GetFieldData("OutBlock", "optcode")

        # 변경
        self.subject.change_optprice(호가시간,단축코드, 매도호가1,매수호가1,"")
        #print("호가발생", self.count, tr_code, 호가시간, 단축코드, 매도호가1, 매수호가1, 매도호가2, 매수호가2)

    def start(self,  Option_expiration_mon):
        """
        이베스트 서버에 실시간 data 요청함.
        """
        optresult, optresult2 = self.get_opt_chart(Option_expiration_mon)

        self.ResFileName = "C:\\eBEST\\xingAPI\\Res\\OH0.res" # RES 파일 등록
        #self.SetFieldData("InBlock", "optcode", optcode)
        #self.AdviseRealData() # 실시간데이터 요청

        for i in optresult['optcode']:
            self.add_item(i)

        for i in optresult2['optcode']:
            self.add_item(i)

    def add_item(self, optcode):
        # 실시간데이터 요청 종목 추가
        self.SetFieldData("InBlock", "optcode", optcode)
        self.AdviseRealData()

    def remove_item(self, optcode):
        # stockcode 종목만 실시간데이터 요청 취소
        self.UnadviseRealDataWithKey(optcode)

    def end(self):
        self.UnadviseRealData() # 실시간데이터 요청 모두 취소

    @classmethod
    def get_instance(cls):
        xreal = win32com.client.DispatchWithEvents("XA_DataSet.XAReal", cls)
        return xreal

#from thread import Thread
import threading
import time
from kospi200Simulation import *

#class PyOptHogaMon:
class PyOptHogaMonSimul(PyOptHogaMon):
    _instance = None

    def __init__(self):
        if self._instance is not None:
            raise ValueError("An instantiation already exist")
        print("optmon Hoga Simulation has created")
        self.count = 0

        self.simulmonitor = Kospi200Simul(2.6,10)

    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            cls._instance = PyOptHogaMonSimul()
        return cls._instance

    def update(self, 호가시간_, 단축코드_, 매도호가1_, 매수호가1_, 이론가_): #업데이트 메서드가 실행되면 변화된 감정내용을 화면에 출력해줍니다
        self.호가시간=호가시간_
        self.단축코드=단축코드_
        self.매도호가1=매도호가1_
        self.매수호가1=매수호가1_
        self.이론가 = 이론가_

        self.display()

    def register_subject(self, subject):
        self.subject = subject
        self.subject.register_observer(self)

    def display(self):
        #print ('호가시간:', self.호가시간, '단축코드:', self.단축코드 , '매도호가1:', self.매도호가1,'매수호가1:', self.매수호가1, '이론가:', self.이론가)
        pass
#       self.comm_connect()
#   self.get_code_list()

#--------------------------
# t2301  차트
#--------------------------
    def get_opt_chart(self, Option_expiration_mon):

        #가상 호가 시뮬레이션
        pass

#--------------------------
# XReal_OC0_  Real data Acquisition
#--------------------------

    def OnReceiveRealData(self, tr_code): # event handler
        """
        이베스트 서버에서 ReceiveRealData 이벤트 받으면 실행되는 event handler
        """

        self.count += 1
        self.subject.clear_optchart()

        cur_kospi_price = pd.to_numeric(self.simulmonitor.df["현재지수"][self.count])
        k = self.simulmonitor.df["일자"][self.count]
        curr_year = k[0:4]
        curr_month = k[5:7]
        curr_day = k[8:10]
        currday_dash = curr_year+'/'+curr_month+'/'+curr_day
        expire_month = self.simulmonitor.tmanager.getNextYearMonth(pd.to_numeric(curr_year),pd.to_numeric(curr_month))

        print(self.simulmonitor.df["일자"][self.count], "cur_kospi_price",pd.to_numeric(self.simulmonitor.df["현재지수"][self.count]),"expire month",expire_month)

        mintick = int(cur_kospi_price-50.0)
        maxtick = int(cur_kospi_price+50.0)

        forprinting_opt_call_index = []
        forprinting_opt_call_code = []
        forprinting_opt_call_price = []

        forprinting_opt_put_index = []
        forprinting_opt_put_code = []
        forprinting_opt_put_price = []

        index_range = np.arange(mintick, maxtick, 2.5)

        if curr_year in ["2006","2007","2008","2009","2010","2011","2012","2013","2014","2015","2016","2017","2018"]  :
            for i in index_range:
                opt_code = self.simulmonitor.optcodetool.optcode_gen(i,expire_month,'call')

                try:
                    calloptdata = pd.read_csv("./data/K"+opt_code+".csv",sep=",")
                    matchingdayindex = (calloptdata[calloptdata['일자'] == currday_dash])

                    호가시간 = k
                    매도호가1 = matchingdayindex.iloc[0]['시가']
                    매수호가1 = matchingdayindex.iloc[0]['시가']
                    단축코드 = opt_code
                    이론가 = "11"

                    self.subject.change_optprice(호가시간,단축코드, 매도호가1,매수호가1,이론가)

                    forprinting_opt_call_index.append(i)
                    forprinting_opt_call_code.append(opt_code)
                    forprinting_opt_call_price.append(매도호가1)

                except:
                    #print("safe call option has not been solved" )
                    pass

                opt_code = self.simulmonitor.optcodetool.optcode_gen(i,expire_month,'put')
                try:
                    putoptdata = pd.read_csv("./data/K"+opt_code+".csv",sep=",")
                    matchingdayindex = (putoptdata[putoptdata['일자'] == currday_dash])

                    호가시간 = k
                    매도호가1 = matchingdayindex.iloc[0]['시가']
                    매수호가1 = matchingdayindex.iloc[0]['시가']
                    단축코드 = opt_code
                    이론가 = "11"

                    self.subject.change_optprice(호가시간,단축코드, 매도호가1,매수호가1,이론가)

                    forprinting_opt_put_index.append(i)
                    forprinting_opt_put_code.append(opt_code)
                    forprinting_opt_put_price.append(매도호가1)

                except:
                    #print("safe call option has not been solved" )
                    pass

        # 변경

       #

        print(forprinting_opt_call_price)
        print(forprinting_opt_put_price)
        #dd = self.subject.get_optChart()
        #print(dd['bidho'])
        #만기에 지우기 장기 옵션 없음

        threading.Timer(0.1,self.OnReceiveRealData, args = ("dd",)).start()
        return True

    def start(self,  Option_expiration_mon):
        """
        이베스트 서버에 실시간 data 요청함.
        """

        #while(1):
        self.OnReceiveRealData("DD")
        #t1 = Thread(target = self.OnReceiveRealData, args = ("dd",))

        #t1.start()

    def add_item(self, optcode):
        # 실시간데이터 요청 종목 추가
        pass

    def remove_item(self, optcode):
        # stockcode 종목만 실시간데이터 요청 취소
        pass

    def end(self):
        pass

try:
    from bestConnect import *
except:
    print("no window communication")
#unit test code
if __name__ == "__main__":

    secinfo = secInfo()                        #계좌 정보 holder
    best = BestAccess()                        #Login class 생성
    accounts_list = best.comm_connect(secinfo) #Login

    optdata =  OptData() #ㅐ
    optmon  = PyOptHogaMon.get_instance()
        #opthogamon observer 등록
    optmon.register_subject(optdata)
    optmon.start("202002")

    while 1:
        pythoncom.PumpWaitingMessages()


# -*- encoding=utf-8 -*-
"""
main window
create: 2020/02/03 18:00
author: zhenchao
"""
import json
import copy
from utils import *
from PyQt5.QtCore import Qt, QDate
from PyQt5.QtWidgets import QWidget, QPushButton, QLabel, QHBoxLayout, QVBoxLayout, QFrame, QSplitter, \
    QLineEdit, QComboBox, QTextEdit, QMessageBox, QDateTimeEdit, QDialog

class MainWindow(QWidget):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.__type = []
        self.__username_entry = None
        self.__password_entry = None
        self.__text_edit_label = None
        self.__method_combobox = None
        self.__num_edit = None
        self.__combobox = None
        self.__thread = None
        self.__new_type_edit = None
        self.__new_num_add = None
        self.__start_calendar_widget = None
        self.__end_calendar_widget = None
        self.__conf = Config()
        self.__cache_list = []
        self.__last_typo = ''
        self.__last_num = 0
        self.__last_method = ''
        self.__total_text_edit = None
        self.get_conf_list()
        self.init_ui()

    def get_conf_list(self):
        _typos_str = self.__conf.get('List', 'typo')
        if _typos_str == '':
            self.__type.extend(['--新增--'])
            return
        _typos_list = _typos_str.split(':')
        self.__type.extend(_typos_list)

    def set_conf_list(self):
        self.__conf.set('List', typo=':'.join(self.__type))

    def init_ui(self):
        self.resize(800, 600)
        self.setWindowTitle(title)

        # top left widget
        v_box = QVBoxLayout(self)
        top_left = QFrame(self)
        time_label = QLabel()
        self.__thread = Thread(time_label)
        self.__thread.start()
        ok_btn = QPushButton('确定')
        cancel_btn = QPushButton('消除')
        ok_btn.clicked.connect(lambda: self.btn_cb('ok'))
        cancel_btn.clicked.connect(lambda: self.btn_cb('cancel'))
        type_label = QLabel('材料')
        num_label = QLabel('数量')
        method_label = QLabel('类型')
        self.__method_combobox = QComboBox(self)
        self.__method_combobox.addItems(['进货', '出货'])
        self.__num_edit = QLineEdit()
        self.__combobox = QComboBox(self)
        self.__combobox.addItems(self.__type)
        self.__combobox.setCurrentIndex(0)
        self.__combobox.activated.connect(self.show_dialog)
        # self.__combobox.highlighted.connect(self.show_dialog)

        top_left_v_box = QVBoxLayout()
        # time
        top_left_v_box.addWidget(time_label)

        # method
        h_box = QHBoxLayout(self)
        h_box.addWidget(method_label)
        h_box.addWidget(self.__method_combobox)
        h_box.addStretch(1)
        top_left_v_box.addLayout(h_box)

        # type
        h_box = QHBoxLayout(self)
        h_box.addWidget(type_label)
        h_box.addWidget(self.__combobox)
        h_box.addStretch(1)
        top_left_v_box.addLayout(h_box)

        # num
        h_box = QHBoxLayout(self)
        h_box.addWidget(num_label)
        h_box.addWidget(self.__num_edit)
        h_box.addStretch(1)
        top_left_v_box.addLayout(h_box)
        top_left_v_box.addStretch(1)

        # btn
        h_box = QHBoxLayout(self)
        h_box.addStretch(1)
        h_box.addWidget(cancel_btn)
        h_box.addWidget(ok_btn)

        v_box.addLayout(top_left_v_box)
        v_box.addLayout(h_box)
        top_left.setFrameShape(QFrame.StyledPanel)
        top_left.setLayout(v_box)

        # top middle widget
        top_mid_v_box = QVBoxLayout(self)
        top_mid = QFrame(self)
        self.__total_text_edit = QTextEdit(self)
        self.__total_text_edit.setFontPointSize(15)
        self.update_total_data()
        top_mid_v_box.addWidget(self.__total_text_edit)

        top_mid.setFrameShape(QFrame.StyledPanel)
        top_mid.setLayout(top_mid_v_box)

        # top right widget
        top_right = QFrame(self)
        _label = QLabel('月度统计')
        search_btn = QPushButton('开始统计')
        search_btn.clicked.connect(lambda: self.btn_cb('search'))
        self.__start_calendar_widget = QDateTimeEdit(QDate.currentDate(), self)
        self.__start_calendar_widget.setCalendarPopup(True)
        self.__start_calendar_widget.setDisplayFormat("yyyy-MM-dd")
        self.__end_calendar_widget = QDateTimeEdit(QDate.currentDate(), self)
        self.__end_calendar_widget.setCalendarPopup(True)
        self.__end_calendar_widget.setDisplayFormat("yyyy-MM-dd")
        start_date_label = QLabel('起始日期')
        end_date_label = QLabel('结束日期')

        v_box = QVBoxLayout(self)
        v_box.addWidget(_label)

        h_box = QHBoxLayout(self)
        h_box.addWidget(start_date_label)
        h_box.addWidget(self.__start_calendar_widget)
        h_box.addStretch(1)
        v_box.addLayout(h_box)

        h_box = QHBoxLayout(self)
        h_box.addWidget(end_date_label)
        h_box.addWidget(self.__end_calendar_widget)
        h_box.addStretch(1)
        v_box.addLayout(h_box)
        v_box.addStretch(1)

        h_box = QHBoxLayout(self)
        h_box.addStretch(1)
        h_box.addWidget(search_btn)
        v_box.addLayout(h_box)

        top_right.setFrameShape(QFrame.StyledPanel)
        top_right.setLayout(v_box)

        # bottom widget
        v_box = QVBoxLayout(self)
        self.__text_edit_label = QTextEdit(self)
        self.__text_edit_label.setFontPointSize(15)
        v_box.addWidget(self.__text_edit_label)
        bottom = QFrame(self)
        bottom.setFrameShape(QFrame.StyledPanel)
        bottom.setLayout(v_box)

        h_splitter = QSplitter(Qt.Horizontal)
        h_splitter.addWidget(top_left)
        h_splitter.addWidget(top_mid)
        h_splitter.addWidget(top_right)

        v_splitter = QSplitter(Qt.Vertical)
        v_splitter.addWidget(h_splitter)
        v_splitter.addWidget(bottom)

        h_box = QHBoxLayout(self)
        h_box.addWidget(v_splitter)
        self.setLayout(h_box)
        # self.setGeometry(300, 300, 300, 200)

    def update_total_data(self):
        json_data = self.load_json_file(total=True)
        _type_list = []
        for typo in json_data['IN'].keys():
            _type_list.append(f'{typo}:{json_data["IN"][typo]}')

        self.__total_text_edit.setText('当前仓库物料清单:\n'+'\n'.join(_type_list))
        cursor = self.__total_text_edit.textCursor()
        pos = len(self.__total_text_edit.toPlainText())
        cursor.setPosition(pos-1)
        self.__total_text_edit.setTextCursor(cursor)

    def init_total_data(self):
        pass

    def run(self):
        self.show()

    def load_json_file(self, total=False):
        now = datetime.datetime.now().strftime("%Y-%m-%d")
        datebase_dir = os.path.join(pathlib.Path('.').absolute(), 'datebase')
        if not os.path.exists(datebase_dir):
            os.mkdir(datebase_dir)
        if total:
            json_file = os.path.join(datebase_dir, 'total')
        else:
            json_file = os.path.join(datebase_dir, now)
        if not os.path.exists(json_file):
            with open(json_file, 'w+', encoding='gbk'):
                return copy.deepcopy(config_json)
        with open(json_file, 'r', encoding='gbk') as fp:
            try:
                return json.load(fp)
            except json.decoder.JSONDecodeError as e:
                logger.debug(f'load {json_file} Error:{e}')
                return copy.deepcopy(config_json)

    def dump_json_file(self, json_data, total=False):
        now = datetime.datetime.now().strftime("%Y-%m-%d")
        datebase_dir = os.path.join(pathlib.Path('.').absolute(), 'datebase')
        if total:
            json_file = os.path.join(datebase_dir, "total")
        else:
            json_file = os.path.join(datebase_dir, now)
        with open(json_file, 'w+', encoding='gbk') as fp:
            json.dump(json_data, fp)

    def fill_data(self, method, typo, num, json_data):
        if method == "进货":
            method = 'IN'
        elif method == "出货":
            method = "OUT"
        else:
            return
        try:
            old_num = int(json_data[method][typo])
        except KeyError:
            old_num = 0
        except ValueError:
            old_num = 0

        # current day
        new_num = old_num + int(num)
        json_data[method][typo] = str(new_num)

        # total
        total_json_data = self.load_json_file(total=True)
        try:
            old_num = int(total_json_data['IN'][typo])
        except KeyError:
            old_num = 0
        except ValueError:
            old_num = 0
        if method == 'OUT':
            new_num = old_num - int(num)
            if new_num < 0:
                self.__cache_list.pop()
                # self.__cache_list[len(self.__cache_list)-1] = f'【出货失败,库存不足】:{typo}:{num}'
                self.__text_edit_label.setPlainText('\n'.join(self.__cache_list))
                self.show_warning_dialog(f'{typo}出货失败:库存不足')
                return
        else:
            new_num = old_num + int(num)
        total_json_data['IN'][typo] = str(new_num)
        self.dump_json_file(total_json_data, total=True)
        self.dump_json_file(json_data)
        self.update_total_data()

    def deal_with_json_data(self, res, js_data):
        for key in js_data.keys():
            for typo in js_data[key]:
                if typo in res[key]:
                    res[key][typo] = str(int(js_data[key][typo]) + int(res[key][typo]))
                else:
                    res[key][typo] = js_data[key][typo]

    def search(self, start, end):
        dates = get_date_range(start, end)
        res = copy.deepcopy(config_json)
        datebase_dir = os.path.join(pathlib.Path('.').absolute(), 'datebase')
        for date in dates:
            try:
                with open(os.path.join(datebase_dir, date)) as fp:
                    js_data = json.load(fp)
                    self.deal_with_json_data(res, js_data)
            except FileNotFoundError:
                logger.debug(f'file {date} not fond')
            except json.decoder.JSONDecodeError as e:
                logger.debug(f'JSONDecodeError {e}')

        self.show_search_result(res)

    def show_search_result(self, res):
        for typo in res['IN']:
            _in = res['IN'][typo]
            try:
                _out = res['OUT'][typo]
            except KeyError:
                _out = '0'
            _template = f'{typo}：进货量{_in} 出货量{_out}'
            self.__cache_list.append(_template)

        self.__text_edit_label.setText('\n'.join(self.__cache_list))

    def _check_num(self, num):
        try:
            num = int(num)
        except ValueError:
            self.show_warning_dialog("数量必须是数字")
            return False
        return True

    def btn_cb(self, text):
        json_data = self.load_json_file()
        if text == "ok":
            typo = self.__combobox.currentText()
            method = self.__method_combobox.currentText()
            num = self.__num_edit.text()
            if not self._check_num(num):
                return
            self.__last_typo = typo
            self.__last_method = method
            self.__last_num = int(num)
            self.__cache_list.append(f'【{method}】:{typo}:{num}')
            self.__text_edit_label.setPlainText('\n'.join(self.__cache_list))
            self.fill_data(method, typo, num, json_data)
            self.__num_edit.clear()
        elif text == "cancel":
            if self.__last_num == '0':
                return
            self.__cache_list.append(f'【消除】:{self.__last_typo}:{self.__last_num}')
            self.__text_edit_label.setText('\n'.join(self.__cache_list))
            self.fill_data(self.__last_method, self.__last_typo, str(0-int(self.__last_num)), json_data)

            self.__last_num = '0'
            self.__last_typo = self.__last_method = ''

        elif text == "add":
            new_type = self.__new_type_edit.text()
            # num = self.__new_num_add.text()
            # if not self._check_num(num):
            #     return
            if new_type in self.__type:
                self.show_warning_dialog(f'物料{new_type}已存在!')
                return
            self.__type.insert(-1, new_type)
            self.__type = list({}.fromkeys(self.__type).keys())
            self.set_conf_list()
            self.__combobox.clear()
            self.__combobox.addItems(self.__type)
            self.__combobox.setCurrentText(new_type)
            # self.__last_num = int(num)
            self.__cache_list.append(f'【新增】:{new_type}')
            self.__text_edit_label.setText('\n'.join(self.__cache_list))
            self.__new_type_edit.clear()
            # self.fill_data('进货', new_type, num, json_data)
        elif text == "search":
            start_date = self.__start_calendar_widget.dateTime().toString(Qt.ISODate).split('T')[0]
            end_date = self.__end_calendar_widget.dateTime().toString(Qt.ISODate).split('T')[0]

            # self.__text_edit_label.clear()
            self.__cache_list.append(f'======{start_date}至{end_date}材料统计情况======')
            self.search(start_date, end_date)

        cursor = self.__text_edit_label.textCursor()
        pos = len(self.__text_edit_label.toPlainText())
        cursor.setPosition(pos - 1)
        self.__text_edit_label.setTextCursor(cursor)

    def cancel_thread(self):
        if self.__thread:
            self.__thread.cancel()

    def closeEvent(self, event):
        """
        重写closeEvent方法，实现dialog窗体关闭时执行一些代码
        :param event: close()触发的事件
        :return: None
        """
        reply = QMessageBox.question(self, title, "是否要退出程序？", QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            if self.__thread:
                self.__thread.cancel()
            event.accept()

        else:
            event.ignore()

    def show_warning_dialog(self, text):
        dialog = QDialog(self)
        v_box = QVBoxLayout(self)

        warning_label = QLabel(text)
        v_box.addWidget(warning_label)
        dialog.setLayout(v_box)
        dialog.setWindowModality(Qt.ApplicationModal)
        dialog.exec_()

    def show_dialog(self):
        if self.__combobox.currentText() != "--新增--":
            return
        dialog = QDialog(self)
        v_box = QVBoxLayout(self)

        add_label = QLabel('新增材料:')
        name_label = QLabel('材料名称')
        ok_btn = QPushButton('新增')
        ok_btn.clicked.connect(lambda: self.btn_cb('add'))

        self.__new_type_edit = QLineEdit()
        h_box = QHBoxLayout(self)
        h_box.addWidget(add_label)
        h_box.addStretch(1)
        v_box.addLayout(h_box)

        h_box = QHBoxLayout(self)
        h_box.addWidget(name_label)
        h_box.addWidget(self.__new_type_edit)
        h_box.addStretch(1)
        v_box.addLayout(h_box)
        v_box.addStretch(1)

        h_box = QHBoxLayout(self)
        h_box.addStretch(1)
        h_box.addWidget(ok_btn)
        v_box.addLayout(h_box)

        dialog.setLayout(v_box)
        dialog.setWindowModality(Qt.ApplicationModal)
        dialog.exec_()


# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
#
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is
# regenerated.
# --------------------------------------------------------------------------

from msrest.serialization import Model

class NodeDeactivationInfo(Model):
    """Information about the node deactivation. This information is valid for a
    node that is undergoing deactivation or has already been deactivated.

    :param node_deactivation_intent: The intent or the reason for deactivating
     the node. Following are the possible values for it. Possible values
     include: 'Invalid', 'Pause', 'Restart', 'RemoveData', 'RemoveNode'
    :type node_deactivation_intent: str or
     ~azure.servicefabric.models.NodeDeactivationIntent
    :param node_deactivation_status: The status of node deactivation
     operation. Following are the possible values. Possible values include:
     'None', 'SafetyCheckInProgress', 'SafetyCheckComplete', 'Completed'
    :type node_deactivation_status: str or
     ~azure.servicefabric.models.NodeDeactivationStatus
    :param node_deactivation_task: List of tasks representing the deactivation
     operation on the node.
    :type node_deactivation_task:
     list[~azure.servicefabric.models.NodeDeactivationTask]
    :param pending_safety_checks: List of pending safety checks
    :type pending_safety_checks:
     list[~azure.servicefabric.models.SafetyCheckWrapper]
    """

    _attribute_map = {
        'node_deactivation_intent': {'key': 'NodeDeactivationIntent', 'type': 'str'},
        'node_deactivation_status': {'key': 'NodeDeactivationStatus', 'type': 'str'},
        'node_deactivation_task': {'key': 'NodeDeactivationTask', 'type': '[NodeDeactivationTask]'},
        'pending_safety_checks': {'key': 'PendingSafetyChecks', 'type': '[SafetyCheckWrapper]'},
    }

    def __init__(self, node_deactivation_intent=None, node_deactivation_status=None, node_deactivation_task=None, pending_safety_checks=None):
        super(NodeDeactivationInfo, self).__init__()
        self.node_deactivation_intent = node_deactivation_intent
        self.node_deactivation_status = node_deactivation_status
        self.node_deactivation_task = node_deactivation_task
        self.pending_safety_checks = pending_safety_checks


#!/usr/bin/env python3
from migen import *

class Wb_Mem(Module):
    def __init__(self, width, depth):

        #inputs:
        self.RESET_i = RESET_i = Signal() #active for returing back to the retset state
        self.ADR_i = ADR_i = Signal(16)
        self.DAT_i = DAT_i = Signal(16)
        self.WE_i = WE_i = Signal() #write enable
        self.STB_i = STB_i = Signal() #active to indicate bus transaction request
        self.CYC_i = CYC_i  = Signal() #wishbone transaction, true on (or before) the first i_wb_stb clock, stays true until the last o_wb_ack

        #outputs
        self.STALL_o = STALL_o = Signal() # false when the transaction happens
        self.ACK_o = ACK_o = Signal() #active for indicating the end of the transaction
        self.DAT_o = DAT_o = Signal(16)

        #imported_modules
        fsm = FSM(reset_state="RESET")
        self.submodules += fsm

        storage = Memory(width, depth)
        self.specials += storage

        ###

        #internal signals
        write_port = storage.get_port(write_capable = True)
        read_port = storage.get_port(has_re=True)

        ###

        self.comb += [
            write_port.adr.eq(ADR_i),
            read_port.adr.eq(ADR_i),
            write_port.dat_w.eq(DAT_i),
            DAT_o.eq(write_port.dat_r)
        ]

        fsm.act("INACTIVE",
            STALL_o.eq(1),
            NextValue(ACK_o,0),
            If((STB_i == 1) ,
                NextState("READING")),
            If((STB_i == 1) & (WE_i == 1),
                NextState("WRITING"))
        )

        fsm.act("READING",
            NextValue(STALL_o,0),
            NextValue(read_port.re,1),

            If((RESET_i == 1),
                NextState("RESET")
            ),

            If((CYC_i == 0),
                NextValue(read_port.re,0),
                NextValue(ACK_o,1),
                NextState("INACTIVE"),
            )
        )

        fsm.act("WRITING",
            STALL_o.eq(0),
            NextValue(write_port.we,1),

            If((RESET_i == 1),
                NextState("RESET")
            ),

            If((CYC_i == 0),
                NextValue(write_port.we,0),
                NextValue(ACK_o,1),
                NextState("INACTIVE")
            )

        )

        fsm.act("RESET",
                NextState("INACTIVE")
        )

def tick():
    global t
    t=t+1
    yield

def simulation_story(dut):

    global t
    t = 0
    # if it needs it, here is some empty startup time
    for i in range(5):
        yield from tick()

    # see if storage can handle more than 50 locations
    for i in range (50):
        yield dut.ADR_i.eq(i+20)
        yield dut.DAT_i.eq(i)
        yield dut.CYC_i.eq(1)
        yield dut.WE_i.eq(1)
        yield dut.STB_i.eq(1)
        yield
        yield dut.WE_i.eq(0)
        yield dut.STB_i.eq(0)
        yield
        yield

        yield from tick()

        yield dut.CYC_i.eq(0)
        yield from tick()

        print("stored number is ",(yield dut.DAT_i))
        print("in adress ",(yield dut.ADR_i))
        yield from tick()

    #wriring the first value
    yield dut.ADR_i.eq(100)
    yield dut.DAT_i.eq(0x1000)
    yield dut.CYC_i.eq(1)
    yield dut.WE_i.eq(1)
    yield dut.STB_i.eq(1)
    yield
    yield dut.WE_i.eq(0)
    yield dut.STB_i.eq(0)
    yield
    yield

    yield from tick()
    yield dut.CYC_i.eq(0)

    print("stored number is ",(yield dut.DAT_i))
    print("in adress ",(yield dut.ADR_i))

    #reading the first value
    yield from tick()
    yield dut.CYC_i.eq(1)
    yield dut.ADR_i.eq(100)

    yield dut.STB_i.eq(1)

    yield
    yield dut.STB_i.eq(0)
    yield from tick()
    yield from tick()
    yield from tick()
    yield dut.CYC_i.eq(0)

    yield from tick()

    print("Red number is ",(yield dut.DAT_o))
    print("of adress: ",(yield dut.ADR_i))
    assert( 0x1000 == (yield dut.DAT_o))

    #wriring the second value
    yield dut.ADR_i.eq(200)
    yield dut.DAT_i.eq(0x2000)
    yield dut.CYC_i.eq(1)
    yield dut.WE_i.eq(1)
    yield dut.STB_i.eq(1)
    yield
    yield dut.WE_i.eq(0)
    yield dut.STB_i.eq(0)
    yield
    yield

    yield from tick()
    yield dut.CYC_i.eq(0)
    print("stored number is ",(yield dut.DAT_i))
    print("in adress ",(yield dut.ADR_i))

    #reading the second value
    yield from tick()
    yield dut.CYC_i.eq(1)
    yield dut.ADR_i.eq(200)

    yield dut.STB_i.eq(1)

    yield
    yield dut.STB_i.eq(0)
    yield from tick()
    yield from tick()
    yield from tick()
    yield dut.CYC_i.eq(0)

    yield from tick()

    print("Red number is ",(yield dut.DAT_o))
    print("of adress: ",(yield dut.ADR_i))
    assert( 0x2000 == (yield dut.DAT_o))

    #wriring the third value
    yield dut.ADR_i.eq(300)
    yield dut.DAT_i.eq(0x3000)
    yield dut.CYC_i.eq(1)
    yield dut.WE_i.eq(1)
    yield dut.STB_i.eq(1)
    yield
    yield dut.WE_i.eq(0)
    yield dut.STB_i.eq(0)
    yield
    yield

    yield from tick()
    yield dut.CYC_i.eq(0)
    print("stored number is ",(yield dut.DAT_i))
    print("in adress ",(yield dut.ADR_i))

    #reading the third value
    yield from tick()
    yield dut.CYC_i.eq(1)
    yield dut.ADR_i.eq(300)

    yield dut.STB_i.eq(1)

    yield
    yield dut.STB_i.eq(0)
    yield from tick()
    yield from tick()
    yield from tick()
    yield dut.CYC_i.eq(0)

    yield from tick()

    print("Red number is ",(yield dut.DAT_o))
    print("of adress: ",(yield dut.ADR_i))
    assert( 0x3000 == (yield dut.DAT_o))

    #wriring the fourth value
    yield dut.ADR_i.eq(400)
    yield dut.DAT_i.eq(0x4000)
    yield dut.CYC_i.eq(1)
    yield dut.WE_i.eq(1)
    yield dut.STB_i.eq(1)
    yield
    yield dut.WE_i.eq(0)
    yield dut.STB_i.eq(0)
    yield
    yield

    yield from tick()
    yield dut.CYC_i.eq(0)
    print("stored number is ",(yield dut.DAT_i))
    print("in adress ",(yield dut.ADR_i))

    #reading the third value
    yield from tick()
    yield dut.CYC_i.eq(1)
    yield dut.ADR_i.eq(400)

    yield dut.STB_i.eq(1)
    yield
    yield dut.STB_i.eq(0)
    yield from tick()
    yield from tick()
    yield from tick()
    yield dut.CYC_i.eq(0)

    yield from tick()

    print("Red number is ",(yield dut.DAT_o))
    print("of adress: ",(yield dut.ADR_i))
    assert( 0x4000 == (yield dut.DAT_o))

if __name__ == "__main__":
    dut = Wb_Mem(16, 16)
    run_simulation(dut, simulation_story(dut), vcd_name="test_memory_wb.vcd")


from django.shortcuts import render
from django.http import HttpResponse
from django.template import RequestContext, loader
import blog.settings
import FIFA

# Create your views here.
def index(request):
    team1 = FIFA.get_teams()
    team2 = FIFA.get_teams()
    #response = "{0}
vs.
{1}".format(team1, team2)
    #return HttpResponse(response)
    template = loader.get_template('FIFA/index.html')
    context = RequestContext(request, {
        'team1': team1,
        'team2': team2
    })
    return HttpResponse(template.render(context))

def about(request):
    response = "This site selects three random teams from all 5 and 4.5 star club teams in FIFA. " \
               "I got sick of only being able to random in a single country's league so I decided to roll my own solution. " \
               "Here's how it's intended to be used: Each player/team gets a pool of three random teams to pick from. That's all there is to it! " \
               "Here are the possible teams:

 {0}".format(FIFA.teams)
    return HttpResponse(response)


import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import time

from utils import project_list, cols

def create_project_list():
    df = pd.read_csv('../data/travistorrent_8_2_2017.csv')
    project_list = df['gh_project_name'].unique()

    col_names = ['project_name', 'failure_rate', 'number_of_builds']
    projects_df = pd.DataFrame(columns=col_names)

    for prj in project_list:
        df1 = df[df['gh_project_name'] == prj]
        df1 = df1[df1['tr_status'] != 'canceled']
        df1 = df1.drop_duplicates(subset=['tr_build_id'])

        failure_rate = float(
            '{0:.2f}'.format(
                df1[df1['tr_status'] != 'passed']['tr_build_id'].count() / df1['tr_build_id'].count() * 100))

        number_of_builds = df1['tr_build_id'].count()

        row = [prj, failure_rate, number_of_builds]
        print(row)
        projects_df.loc[len(projects_df)] = row

    projects_df.to_csv('../data/projects.csv')

def extract_project(prj):
    df = pd.read_csv('../data/travistorrent_8_2_2017.csv')
    df1 = df[df['gh_project_name'] == prj]
    df1 = df1.drop_duplicates(subset=['tr_build_id'])
    df1.to_csv('../data/{}.csv'.format(prj.replace('/', '--')))

def run_extract():
    extract_project('opal/opal')
    extract_project('rspec/rspec-core')
    extract_project('FenixEdu/fenixedu-academic')

def get_pr_ratio():
    for prj in project_list:
        df = pd.read_csv('../data/{}.csv'.format(prj), usecols=['gh_is_pr'])
        print(prj, '{0:.2f}%'.format(df[df['gh_is_pr'] == True]['gh_is_pr'].count() / df['gh_is_pr'].count() * 100))

def get_projects_stats():
    for prj in project_list:
        df = pd.read_csv('../data/{}.csv'.format(prj['name']), usecols=cols)
        print(prj['name'],
              '{0:.2f}%'.format(df[df['tr_status'] == 'canceled']['tr_status'].count() * 100 / df['tr_status'].count()))

def get_projects_years():
    for prj in project_list:
        df = pd.read_csv('../data/{}.csv'.format(prj['name']), usecols=['gh_build_started_at'])
        print(prj['name'])
        print(df['gh_build_started_at'].min())
        print(df['gh_build_started_at'].max())
        print()

def plot_build_date_histogram():
    for prj in project_list:
        df = pd.read_csv('../data/{}.csv'.format(prj['name']), usecols=['gh_build_started_at'])
        df['gh_build_started_at'] = pd.to_datetime(df['gh_build_started_at'])
        df['gh_build_started_at'] = df['gh_build_started_at'].dt.date

        # print(len(set(df['gh_build_started_at'])))
        # print(df['gh_build_started_at'].min())
        # print(df['gh_build_started_at'].max())

        fig, ax = plt.subplots(1, 1)
        ax.hist(df['gh_build_started_at'], bins=len(df['gh_build_started_at']), histtype='bar')

        locator = mdates.AutoDateLocator()
        ax.xaxis.set_major_locator(locator)
        # ax.xaxis.set_major_formatter(mdates.DateFormatter("'%y"))
        ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator))

        plt.xlabel('Date')
        plt.ylabel('Build frequency')
        plt.title('{} Build Date Histogram'.format(prj['name']))
        plt.show()

def plot_build_duration_histogram():
    for prj in project_list:
        # print(prj['name'], 'Build Duration')
        df = pd.read_csv('../data/{}.csv'.format(prj['name']), usecols=['tr_duration', 'tr_status'])

        df = df[df['tr_status'] != 'canceled']

        # print('Min: ', int(df['tr_duration'].min() / 60), 'm')
        # print('Max: ', int(df['tr_duration'].max() / 60), 'm')
        # print('Mean: ', int(df['tr_duration'].mean() / 60), 'm')
        # print('Median: ', int(df['tr_duration'].median() / 60), 'm')
        # print('STD: ', int(df['tr_duration'].std() / 60), 'm')

        # print('Max: ', int(df['tr_duration'].max()), 's')
        # print('Mean: ', int(df['tr_duration'].mean()), 's')
        # print('Median: ', int(df['tr_duration'].median()), 's')
        # print('STD: ', int(df['tr_duration'].std()), 's')

        print(time.strftime('%H:%M:%S', time.gmtime(int(df['tr_duration'].mean()))))

        # print()

        # fig, ax = plt.subplots(1, 1)
        # ax.hist(df['tr_duration'], bins=len(df['tr_duration']), histtype='bar')
        #
        # locator = mdates.AutoDateLocator()
        # ax.xaxis.set_major_locator(locator)
        # # ax.xaxis.set_major_formatter(mdates.DateFormatter("'%y"))
        # ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(locator))
        #
        # plt.xlabel('Date')
        # plt.ylabel('Build frequency')
        # plt.title('{} Build Date Histogram'.format(project))
        # plt.show()

        # break

def get_projects_num_of_builds():
    for prj in project_list:
        df = pd.read_csv('../data/{}.csv'.format(prj['name']), usecols=['tr_status', 'tr_build_id'])
        df = df[df['tr_status'] != 'canceled']
        # print(prj['name'])
        print(df['tr_build_id'].count())
        # print()

def get_projects_num_of_failures():
    for prj in project_list:
        df = pd.read_csv('../data/{}.csv'.format(prj['name']), usecols=['tr_status', 'tr_build_id'])
        df = df[df['tr_status'] != 'canceled']
        df = df[df['tr_status'] != 'passed']
        # print(prj['name'])
        print(df['tr_build_id'].count())
        # print()

def get_failure_distribution_avg():
    d = dict()

    lav = list()

    for prj in project_list:
        df = pd.read_csv('../data/{}.csv'.format(prj['name']), usecols=['tr_status', 'tr_build_id'])
        df = df[df['tr_status'] != 'canceled']

        av = [prj['name']]

        i = 0
        for item in list(df['tr_status']):
            if item != 'passed':
                av.append(i)
                i = 0
            else:
                i += 1

        lav.append(av)
        # d[prj['name']] = ','.join(str(item) for item in av)

        # print(statistics.mean(av))
        # print(df['tr_build_id'].count())
        # break

    # for item in lav:
    #     print(item)

    s = ''

    for i in range(20000):
        l = ''
        c = True
        for item in lav:
            if len(item) > i:
                c = False
                l += str(item[i])

            l += ','

        if c:
            break

        l = l[:-1] + '\n'
        s += l

    with open('num_of_builds_until_failure.csv', 'w') as f:
        f.write(s)

    # print(s)

    # p = pd.DataFrame(d.items(), columns=['Project', 'Num of builds until failre'])
    # p.to_csv('num_of_builds_until_failure.csv')

    # def tgrp(df):
    #     df = df.drop('Project', axis=1)
    #     return df.reset_index(drop=True).T
    #
    # df2 = p.groupby('Project').apply(tgrp).unstack()

    # df2 = p.set_index(['Project', 'Num of builds until failre']).unstack()
    # print(df2)

    # print(p)

def get_last_failure_distance():
    lav = list()

    for prj in project_list:
        df = pd.read_csv('../data/{}.csv'.format(prj['name']), usecols=['tr_status', 'tr_build_id'])
        df = df[df['tr_status'] != 'canceled']

        av = [prj['name']]

        result = []
        d = 0

        for item in df['tr_status']:
            result.append(d)

            if item != 'passed':
                d = 0
            else:
                d += 1

        av.extend(result)

        # lav.


from functions import *
from computer import *

b = [[" ", " ", " "], #Board
     [" ", " ", " "],
     [" ", " ", " "]]
tokens = ["X", "O"]
message = ""

clearScreen()
print("Command Line Tic-Tac-Toe \n"
      "to make your move give two numbers, \n"
      "Column then Row, seperated with a space \n"
      "ex: 0 2"
     )
input()
clearScreen()

print("1 Player or 2 Player or 0 Player")
try:
    playerNum = int(input(">"))
except ValueError:
    clearScreen()
    print("Please give a number 0-2")
    playerNUm = int(input(">"))

clearScreen()

def makeMove(board, token):
    if playerNum == 2:
        player = input(token + " move > ")

    if playerNum == 1:
        if token == tokens[1]:
            player = computer(b)

        if token == tokens[0]:
            player = input(token + " move > ")

    if playerNum == 0:
        player = computer(b)

    try:
        row, col = [int(x) for x in player.split(" ")]
    except:
        return [False, "Redoing turn, incorrect format."]

    if b[col][row] != " ":
        return [False, "Redoing turn, space already taken."]

    b[col][row] = token
    return [True, ""]

while True:
    i = 0
    while i <= 1:
        print(message)
        printBoard(b)
        flag, message = makeMove(b, tokens[i])
        if flag == False:
            pass
        else:
            i += 1

        if winner(b, tokens)[0]: break
        clearScreen()

    else: continue

    clearScreen()
    break

printBoard(b)
print(winner(b, tokens)[1])


import torch
import torch.nn as nn
import torchvision
from torch.utils.data import DataLoader
import numpy as np
import argparse
import time

import pdb

from lib.episode_generator import MiniImagenet
from lib.episode_generator import CIFAR10
from lib.episode_generator import Chexpert
from lib.episode_generator import ImagenetTrain, ImagenetVal

#from lib.simplenet import SimpleNet
#from lib.resnet12 import ResNet12
#from lib.wideresnet import WideResNet
from lib.vggnet import VGGNet

from lib.utils import get_available_gpu_ids
from lib.utils import xent
from lib.utils import mixup
from lib.utils import xent

# ========= HYPERPARAMS ===========
def parse_args():
    parser = argparse.ArgumentParser(description='imgnet size')
    parser.add_argument('--project', dest='project', default='pytorchnets')
    parser.add_argument('--datatype', dest='datatype', default='imagenet')
    parser.add_argument('--max_epoch', dest='max_epoch', default=20, type=int)
    parser.add_argument('--lr_decay', dest='lr_decay', default=0.2, type=float)
    parser.add_argument('--lr_decay_list', dest='lr_decay_list', default='60,120,160')
    parser.add_argument('--lr_init', dest='lr_init', default=1e-2, type=float)
    parser.add_argument('--num_workers', dest='num_workers', default=32, type=int)
    parser.add_argument('--num_gpus', dest='num_gpus', default=1, type=int)
    parser.add_argument('--per_gpu_batch', dest='per_gpu_batch', default=16, type=int)
    parser.add_argument('--aug_mixup', dest='aug_mixup', default=1, type=int)
    parser.add_argument('--arch', dest='arch', default='vgg')
    parser.add_argument('--wd', dest='weight_decay', default=5e-4, type=float)
    parser.add_argument('--pr', dest='pretrain', default=0, type=int)

    args = parser.parse_args()
    return args
# ========= HYPERPARAMS ===========

if __name__=='__main__':
    args = parse_args()
    print ('='*30, 'ARGS', '='*30)
    args.batch_size = args.per_gpu_batch * args.num_gpus
    #args.devices = get_available_gpu_ids()[:args.num_gpus]
    args.devices = [0,1,4,6][:args.num_gpus]
    args.lr_decay_list = [int(r) for r in args.lr_decay_list.split(',')]
    args.save_str = 'net.{}_data.{}_task.{}_mixup.{}_batchsize.{}'\
            .format(args.arch, args.datatype, 'clf',
                    args.aug_mixup, args.batch_size)
    torch.cuda.set_device(args.devices[0])
    for arg in sorted(vars(args)):
        print ('%15s: %s'%(arg, getattr(args, arg)))
    print ('='*63)

    if args.datatype=='miniImagenet':
        data_dir = 'data/miniImagenet/train'
        train_dataset = MiniImagenet(data_dir, transform=True, split='train')
        test_dataset = MiniImagenet(data_dir, split='test')
    elif args.datatype=='cifar10':
        data_dir = 'data/cifar-10-batches-py'
        train_dataset = CIFAR10(data_dir, transform=True, phase='train')
        test_dataset = CIFAR10(data_dir, transform=False, phase='test')
    elif args.datatype=='chexpert':
        data_dir = 'data/CheXpert-v1.0-small'
        train_dataset = Chexpert(data_dir, transform=True, phase='train')
        test_dataset = Chexpert(data_dir, transform=False, phase='valid')
    elif args.datatype=='imagenet':
        data_dir = 'data/Imagenet'
        train_dataset = ImagenetTrain(data_dir)
        test_dataset = ImagenetVal(data_dir)

    train_dataloader = DataLoader(train_dataset, batch_size=args.batch_size,
            shuffle=True, num_workers=args.num_workers, drop_last=True)
    test_dataloader = DataLoader(test_dataset, batch_size=args.batch_size,
            shuffle=False, num_workers=args.num_workers)

    if args.arch=='simple':
        train_net = SimpleNet(fc=train_dataset.n_classes)
    elif args.arch=='res12':
        train_net = ResNet12(fc=train_dataset.n_classes)
    elif args.arch=='wdres':
        train_net = WideResNet(fc=train_dataset.n_classes)
    elif args.arch=='vgg':
        train_net = VGGNet(fc=train_dataset.n_classes, imgsize=train_dataset.hw)
    train_net = nn.DataParallel(train_net, args.devices).cuda()

    loss_fn = nn.CrossEntropyLoss()
    optimizer = torch.optim.SGD(train_net.parameters(), lr=args.lr_init,
            momentum=0.9, weight_decay=args.weight_decay)
    lr_scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer,
            args.lr_decay_list, gamma=args.lr_decay)

    # restoring
    if args.pretrain:
        train_net.load_state_dict(torch.load('models/{}'.format(args.save_str)))
    #train_net.load_only_possibles(torch.load('models/{}'.format(cfg)))
    #tramport Queuein_net.load_state_dict(torch.load('models/{}'.format(cfg)), strict=False)

    for epoch in range(args.max_epoch):
        accs, losses = [], []
        t0 = time.time()
        t2 = time.time()
        btime, mtime = 0, 0

        train_net.train()
        for i, batch in enumerate(train_dataloader):

            t1 = time.time()
            btime += t1 - t2

            x, y = batch
            if args.aug_mixup:
                lam = np.random.beta(1, 1)
                if epoch >= args.max_epoch - 20:
                    lam = 1

                x, y = mixup(x, y, lam, train_dataset.n_classes)
                x, y = x.cuda(non_blocking=True), y.long().cuda(non_blocking=True)
                pred = train_net.forward(x)
                loss = xent(pred, y)
                acc = (pred.max(1)[1] == y.max(1)[1]).float().mean()
            else:
                x, y = x.cuda(), y.cuda().long()
                if len(y.shape) != 1:
                    y = y.max(1)[1]

#                pdb.set_trace()

                pred = train_net.forward(x)
                loss = loss_fn(pred, y)
                acc = (pred.max(1)[1] == y).float().mean()

            accs.append(acc)
            losses.append(loss)

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            t2 = time.time()
            mtime += t2 - t1

            print (btime, mtime)
            #pdb.set_trace()

            if (i % 100 == 0) and (i != 0):
                max_iter = len(train_dataset) // args.batch_size
                print ('{} / {} ({:.3f}) \%, expected epoch time - {:.3f}'\
                        .format(i, max_iter,
                            i/max_iter, (time.time() - t0) / i * max_iter))

        lr_scheduler.step()
        taccs = []
        train_net.eval()
        for i, batch in enumerate(test_dataloader):
            x, y = batch
            #x, y = x.to(device, dtype=dtype), y.to(device).long()
            x, y = x.cuda(non_blocking=True), y.long().cuda(non_blocking=True)
            train_net.eval()
            pred = train_net.forward(x)
            if len(y.shape) == 1:
                y = y.max(1)[1]
            tacc = (pred.max(1)[1] == y).float().mean()
            taccs.append(tacc)

        taccs = torch.stack(taccs)
        accs = torch.stack(accs)
        losses = torch.stack(losses)

        print ('===Epoch {} / {} ====='.format(epoch, args.max_epoch))
        print ('Trainin acc : {:.3f}  |  '
                'loss : {:.3f}  |  '
                'Test Acc: {:.3f} |'
                'Lr: {:.3f} * 1e-3 |'
                'in {:.3f} sec'\
                .format(torch.mean(accs)*100.,
                    torch.mean(losses),
                    torch.mean(taccs)*100.,
                    optimizer.param_groups[0]['lr'] * 1e+3,
                    time.time()-t0))
        print ('profiling - batch time: {:.3f} / model time: {:.3f}  || proportion - {:.3f}'\
                .format(btime, mtime, btime/mtime*100.))

        if (epoch % 10 == 0 and epoch != 0) or epoch == args.max_epoch-1:
            loc = 'models/{}'.format(args.save_str)
            torch.save(train_net.state_dict(), loc)
            print ('saved in {}'.format(loc))

    #


from datetime import datetime
import logging as log
from galaxy.http import HttpClient
import dateutil.parser

from galaxy.api.errors import (
    AuthenticationRequired, AccessDenied, UnknownError
)

from consts import CLUB_APPID, CHROME_USERAGENT

class BackendClient(HttpClient):
    def __init__(self, plugin):
        self._plugin = plugin
        self._auth_lost_callback = None
        self.token = None
        self.session_id = None
        self.refresh_token = None
        self.refresh_time = None
        self.user_id = None
        self.__refresh_in_progress = False
        super().__init__()
        self._session.headers = {
            'Authorization': None,
            'Ubi-AppId': CLUB_APPID,
            "User-Agent": CHROME_USERAGENT,
            'Ubi-SessionId': None
        }

    def set_auth_lost_callback(self, callback):
        self._auth_lost_callback = callback

    def is_authenticated(self):
        return self.token is not None

    async def _do_request(self, method, *args, **kwargs):
        if not kwargs or 'headers' not in kwargs:
            log.info("No headers in kwargs, using session headers")
            kwargs['headers'] = self._session.headers
        if 'add_to_headers' in kwargs:
            for header in kwargs['add_to_headers']:
                kwargs['headers'][header] = kwargs['add_to_headers'][header]
            kwargs.pop('add_to_headers')

        r = await super().request(method, *args, **kwargs)
        j = await r.json()  # all ubi endpoints return jsons
        log.info(f"Response status: {r}")
        return j

    async def _do_request_safe(self, method, *args, **kwargs):

        async def _refresh_and_request():
            await self._refresh_ticket()
            return await self._do_request(method, *args, **kwargs)

        if self.__refresh_in_progress:
            log.info(f'Refreshing already in progress. Calling url without refresh')
            return await self._do_request(method, *args, **kwargs)

        self.__refresh_in_progress = True
        result = {}
        try:
            if not self.refresh_token:
                result = await _refresh_and_request()
            else:
                log.debug(f'rememberMeTicket expiration time: {str(self.refresh_time)}')
                refresh_needed = self.refresh_time is None or datetime.now() > datetime.fromtimestamp(int(self.refresh_time))
                if refresh_needed:
                    await self._refresh_remember_me()
                    result = await _refresh_and_request()
                else:
                    try:
                        result = await _refresh_and_request()
                    except (AccessDenied, AuthenticationRequired):
                        # fallback for another reason than expired time or wrong calculation due to changing time zones
                        log.debug('Fallback refresh')
                        await self._refresh_remember_me()
                        result = await _refresh_and_request()
        except (AccessDenied, AuthenticationRequired) as e:
            log.debug(f"Unable to refresh authentication calling auth lost: {repr(e)}")
            if self._auth_lost_callback:
                self._auth_lost_callback()
            raise
        except Exception as e:
            log.debug("Refresh workflow has failed:" + repr(e))
            raise
        else:
            self._plugin.store_credentials(self.get_credentials())
        finally:
            self.__refresh_in_progress = False

        return result

    async def _do_options_request(self):
        await self._do_request('options', "https://public-ubiservices.ubi.com/v3/profiles/sessions", headers={
            "Origin": "https://connect.ubisoft.com",
            "Referer": "https://connect.ubisoft.com/login?appId=314d4fef-e568-454a-ae06-43e3bece12a6",
            "User-Agent": CHROME_USERAGENT,
        })

    async def _refresh_remember_me(self):
        log.debug('Refreshing rememberMeTicket')
        await self._do_options_request()
        j = await self._do_request(
            'post',
            f'https://public-ubiservices.ubi.com/v3/profiles/sessions',
            headers={
                'Accept': '*/*',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'en-US;en;q=0.5',
                'Authorization': f"rm_v1 t={self.refresh_token}",
                'Content-Type': 'application/json',
                'Ubi-AppId': CLUB_APPID,
                'User-Agent': CHROME_USERAGENT,
                'Host': 'public-ubiservices.ubi.com',
                'Origin': 'https://connect.ubisoft.com',
                'Referer': 'https://connect.ubisoft.com',
            },
            json={"rememberMe": True}
        )
        self._handle_authorization_response(j)

    async def _refresh_ticket(self):
        log.debug('Refreshing ticket')
        await self._do_options_request()
        j = await self._do_request(
            'put',
            f'https://public-ubiservices.ubi.com/v3/profiles/sessions',
            headers={
                'Accept': '*/*',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'en-US;en;q=0.5',
                'Authorization': f"Ubi_v1 t={self.token}",
                'Content-Type': 'application/json',
                'Ubi-AppId': CLUB_APPID,
                'User-Agent': CHROME_USERAGENT,
                'Host': 'public-ubiservices.ubi.com',
                'Origin': 'https://connect.ubisoft.com',
                'Referer': 'https://connect.ubisoft.com',
            })
        self._handle_authorization_response(j)

    def _handle_authorization_response(self, j):
        refresh_time = datetime.now() + (dateutil.parser.parse(j['expiration']) - dateutil.parser.parse(j['serverTime']))
        j['refreshTime'] = round(refresh_time.timestamp())
        self.restore_credentials(j)

    def restore_credentials(self, data):
        self.token = data['ticket']
        self.session_id = data['sessionId']
        self.user_id = data['userId']
        self.refresh_time = data.get('refreshTime', '0')
        if data.get('rememberMeTicket'):
            self.refresh_token = data['rememberMeTicket']

        self._session.headers = {
            'Ubi-AppId': CLUB_APPID,
            "Authorization": f"Ubi_v1 t={self.token}",
            "Ubi-SessionId": self.session_id
        }
        self._plugin.store_credentials(self.get_credentials())

    def get_credentials(self):
        return {
            "ticket": self.token,
            "sessionId": self.session_id,
            "rememberMeTicket": self.refresh_token,
            "userId": self.user_id,
            "refreshTime": self.refresh_time
        }

    async def authorise_with_stored_credentials(self, credentials):
        self.restore_credentials(credentials)
        user_data = await self.get_user_data()
        await self.post_sessions()
        return user_data

    async def authorise_with_cookies(self, cookies):
        user_data = {}
        tasty_cookies = ['user_id', 'user_name', 'ticket', 'rememberMeTicket', 'sessionId']
        for cookie in cookies:
            if cookie['name'] in tasty_cookies:
                user_data[cookie['name']] = cookie['value']
        user_data['userId'] = user_data.pop('user_id')
        user_data['username'] = user_data.pop('user_name')

        self.restore_credentials(user_data)
        await self.post_sessions()
        return user_data

    async def get_user_data(self):
        return await self._do_request_safe('get', f"https://public-ubiservices.ubi.com/v3/users/{self.user_id}")

    async def get_friends(self):
        r = await self._do_request_safe('get', f'https://api-ubiservices.ubi.com/v2/profiles/me/friends')
        return r

    async def get_club_titles(self):
        return await self._do_request_safe('get', "https://public-ubiservices.ubi.com/v1/profiles/me/club/aggregation/website/games/owned")

    async def get_game_stats(self, space_id):
        url = f"https://public-ubiservices.ubi.com/v1/profiles/{self.user_id}/statscard?spaceId={space_id}"
        headers = {}
        headers['Ubi-RequestedPlatformType'] = "uplay"
        headers['Ubi-LocaleCode'] = "en-GB"

        try:
            j = await self._do_request('get', url, add_to_headers=headers)
        except UnknownError:  # no stats available for this user
            return {}
        return j

    async def get_applications(self, spaces):
        space_string = ','.join(space['spaceId'] for space in spaces)
        j = await self._do_request_safe('get', f"https://api-ubiservices.ubi.com/v2/applications?spaceIds={space_string}")
        return j

    async def get_challenges(self, space_id):
        j = await self._do_request_safe('get', f"https://public-ubiservices.ubi.com/v1/profiles/{self.user_id}/club/actions?limit=100&locale=en-US&spaceId={space_id}")
        return j

    async def get_configuration(self):
        r = await self._do_request_safe('get', f'https://uplaywebcenter.ubi.com/v1/configuration')
        return r.json()

    async def post_sessions(self):
        headers = {}
        headers['Content-Type'] = 'application/json'
        j = await self._do_request_safe('post', f"https://public-ubiservices.ubi.com/v2/profiles/sessions", add_to_headers=headers)
        return j


# type: ignore
from models.plaid_account import PlaidAccount
from tests.mocks.plaid_response import accounts_response
from tests.factories import PlaidAccountFactory, PlaidItemFactory

class TestPlaidAccount:
    def test_get_plaid_account(self) -> None:
        plaid_account = PlaidAccountFactory.create()
        res = PlaidAccount.get_plaid_account(plaid_account.account_id)
        assert res == plaid_account

    def test_create_plaid_accounts(self) -> None:
        plaid_item = PlaidItemFactory.create()
        plaid_accounts = PlaidAccount.create_plaid_accounts(
            plaid_item=plaid_item, accounts=accounts_response["accounts"]
        )
        assert len(plaid_accounts) == 3

        account = accounts_response["accounts"][0]
        plaid_account = next(
            pa for pa in plaid_accounts if account["account_id"] == pa.account_id
        )
        assert plaid_account
        assert plaid_account.item_id == plaid_item.id
        assert plaid_account.mask == account["mask"]
        assert plaid_account.plaid_subtype == account["subtype"]
        assert plaid_account.plaid_type == account["type"]
        assert plaid_account.official_name == account["official_name"]
        assert plaid_account.name == account["name"]
        assert plaid_account.current_balance == account["balances"]["current"]


from pprint import pprint

class Node:
    def __init__(self, item):
        self.mItem = item
        self.mNext = None

class Queue:

    def __init__(self):
        self.mFront = None
        self.mBack = None

    def empty(self):
        return self.mFront is None and self.mBack is None

    def enqueue(self, item):
        new_node = Node(item)
        if self.empty():
            self.mFront = new_node
        else:
            self.mBack.mNext = new_node

        self.mBack = new_node

    def dequeue(self):
        if self.empty():
            raise Exception("Queue: 'dequeue' applied to empty container")

        current_front = self.mFront
        item = current_front.mItem
        self.mFront = self.mFront.mNext
        del current_front

        if self.mFront is None:
            self.mBack = None
        return item

di = [0, -1, 0, 1]
dj = [-1, 0, 1, 0]

def CanGo(i, j, n):
    if i<0 or i>=n or j<0 or j>=n:
        return False
    return True

def wave(maze, waveMatrix, start, count):
    n = len(maze)
    #pprint(maze)
    #pprint(waveMatrix)
    q = Queue()
    q.enqueue((start[0],start[1]))
    waveMatrix[start[0]][start[1]] = 1
    while not q.empty():
        current = q.dequeue()
        i, j = current[0], current[1]
        for k in range(len(dj)):
            i1, j1 = i + di[k], j + dj[k]
            if CanGo(i1, j1, n) and waveMatrix[i1][j1] == -1 and maze[i1][j1] == '.':
                q.enqueue((i1, j1))
                waveMatrix[i1][j1] = 1
            elif not CanGo(i1, j1, n) or maze[i1][j1] == '#':
                #print(i1,j1)
                count[0] += 1
    #pprint(waveMatrix)
    return  count

start = 0
end = 0

n = int(input())
mtr = []
for i in range(n):
    mtr.append(list(input()))

count = [0]
waveMatrix = [[-1]*n for i in range(n)]
wave(mtr, waveMatrix, (0,0), count)
#pprint(waveMatrix)
if waveMatrix[n-1][n-1] == -1:
    wave(mtr, waveMatrix,(n-1,n-1), count)
#pprint(waveMatrix)

print((count[0]-4)*9)


import pygame
from pygame.sprite import Sprite
from pygame.locals import *

class Recurso:
    def __init__(self,nombre):
        self.nombre=nombre
        self.libre=True

    def __str__(self):
        return(self.nombre)

    def utilizar(self):
        if self.libre:
            print("usando el",self.nombre)
            self.libre=False
        else:
            print("el",self.nombre,"esta ocupado")

    def liberar(self):
        if not self.libre:
            print("el",self.nombre,"fue liberado")
            self.libre=True
        else:
            print("el",self.nombre,"no estaba siendo usado")

class Horno(Recurso, Sprite):
    def __init__(self, cont_size, nombre="Horno"):
        Recurso.__init__(self,nombre)
        Sprite.__init__(self)
        self.cont_size = cont_size
        self.image = pygame.image.load("imagenes/horno.png")
        self.rect = self.image.get_rect()
        self.rect.move_ip(cont_size[0] - 430, cont_size[1] - 430)

class Cuchillos(Recurso, Sprite):
    def __init__(self, cont_size, nombre="Cuchillos"):
        Recurso.__init__(self,nombre)
        Sprite.__init__(self)
        self.cont_size = cont_size
        self.image = pygame.image.load("imagenes/cuchillos.png")
        self.rect = self.image.get_rect()
        self.rect.move_ip(cont_size[0] - 420, cont_size[1] - 685)

class Licuadora(Recurso, Sprite):
    def __init__(self, cont_size, nombre="Licuadora"):
        Recurso.__init__(self,nombre)
        Sprite.__init__(self)
        self.cont_size = cont_size
        self.image = pygame.image.load("imagenes/licuadora.png")
        self.rect = self.image.get_rect()
        self.rect.move_ip(cont_size[0] - 390, cont_size[1] - 575)

Chef Race - Colas Multiples Retroalimentadas/recursos.py


#!/usr/bin/env python

__author__ = "Gabriel Bassett"
"""
 AUTHOR: {0}
 DATE: <DATE>
 DEPENDENCIES: <a list of modules requiring installation>
 Copyright <YEAR> {0}

 LICENSE:
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.

 DESCRIPTION:
 <ENTER DESCRIPTION>

""".format(__author__)
# PRE-USER SETUP
pass

########### NOT USER EDITABLE ABOVE THIS POINT #################

# USER VARIABLES
PLUGIN_CONFIG_FILE = "generic.yapsy-plugin"
NAME = "generic"

########### NOT USER EDITABLE BELOW THIS POINT #################

## IMPORTS
from yapsy.IPlugin import IPlugin
import logging
import networkx as nx
from datetime import datetime # timedelta imported above
import dateutil  # to parse variable time strings
import uuid
import ConfigParser
import inspect
try:
    import tldextract
    module_import_success = True
except:
    module_import_success = False
    logging.error("Module import failed.  Please install the following module: tldextract.")
    raise

## SETUP
loc = inspect.getfile(inspect.currentframe())
ind = loc.rfind("/")
loc = loc[:ind+1]
config = ConfigParser.SafeConfigParser()
config.readfp(open(loc + PLUGIN_CONFIG_FILE))

if config.has_section('Core'):
    if 'name' in config.options('Core'):
        NAME = config.get('Core', 'name')
if config.has_section('Log'):
    if 'level' in config.options('Log'):
        LOGLEVEL = config.get('Log', 'level')
    if 'file' in config.options('Log'):
        LOGFILE = config.get('Log', 'file')

## EXECUTION
class PluginOne(IPlugin):
    inputs = None

    def __init__(self):
        pass

    def configure(self):
        """

        :return: return list of [configure success (bool), name, description, list of acceptable inputs, resource cost (1-10, 1=low), speed (1-10, 1=fast)]
        """
        config_options = config.options("Configuration")

        if 'cost' in config_options:
            cost = config.get('Configuration', 'cost')
        else:
            cost = 9999
        if 'speed' in config_options:
            speed = config.get('Configuration', 'speed')
        else:
            speed = 9999

        if config.has_section('Documentation') and 'description' in config.options('Documentation'):
            description = config.get('Documentation', 'description')
        else:
            logging.error("'Description not in config file.")
            return [None, False, NAME, None, cost, speed]

        if 'type' in config_options:
            plugin_type = config.get('Configuration', 'type')
        else:
            logging.error("'Type' not specified in config file.")
            return [None, False, NAME, description, None, cost, speed]

        if 'inputs' in config_options:
            self.inputs = config.get('Configuration', 'Inputs')
            self.inputs = [l.strip().lower() for l in self.inputs.split(",")]
        else:
            logging.error("No input types specified in config file.")
            return [plugin_type, False, NAME, description, None, cost, speed]

        return [plugin_type, True, NAME, description, self.inputs, cost, speed]

    def run(self, enrichment_dict, start_time="", confidence=1):
        """ dict, str -> networkx multiDiGraph

        :param enrichment_dict: a dictionary of the form {'key': <key of atomic to describe>, 'value':<value of atomic to describe>, 'describing_key':<key of describing atomic>, 'describing_value':<value of describing atomic>}
        :param start_time: string in ISO 8601 combined date and time format (e.g. 2014-11-01T10:34Z) or datetime object.
        :param include_subdomain: Boolean value.  Default False.  If true, subdomain will be returned in enrichment graph
        :return: a networkx graph representing the sections of the domain
        """
        described_key = enrichment_dict['key']
        described_value = enrichment_dict['value']
        describing_key = enrichment_dict['describing_key']
        describing_value = enrichment_dict['describing_value']

        g = nx.MultiDiGraph()

        if type(start_time) is str:
            try:
                time = dateutil.parser.parse(start_time).strftime("%Y-%m-%dT%H:%M:%SZ")
            except:
                time = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
        elif type(start_time) is datetime:
            time = start_time.strftime("%Y-%m-%dT%H:%M:%SZ")
        else:
            time = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")

        # Get or create target node
        described_uri = "class=attribute&key={0}&value={1}".format(described_key, described_value)
        g.add_node(described_uri, {
            'class': 'attribute',
            'key': described_key,
            "value": described_value,
            "start_time": time,
            "uri": described_uri
        })

        # Get or create classification node
        describing_uri = "class=attribute&key={0}&value={1}".format(describing_key, describing_value)
        g.add_node(describing_uri , {
            'class': 'attribute',
            'key': describing_key,
            "value": describing_value,
            "start_time": time,
            "uri": describing_uri
        })

        # Link target to classification
        edge_attr = {
            "relationship": "describedBy",
            "start_time": time,
            "origin": "generic",
            "confidence": confidence
        }
        source_hash = uuid.uuid3(uuid.NAMESPACE_URL, described_uri)
        dest_hash = uuid.uuid3(uuid.NAMESPACE_URL, describing_uri )
        edge_uri = "source={0}&destionation={1}".format(str(source_hash), str(dest_hash))
        rel_chain = "relationship"
        while rel_chain in edge_attr:
            edge_uri = edge_uri + "&{0}={1}".format(rel_chain,edge_attr[rel_chain])
            rel_chain = edge_attr[rel_chain]
        if "origin" in edge_attr:
            edge_uri += "&{0}={1}".format("origin", edge_attr["origin"])
        edge_attr["uri"] = edge_uri
        g.add_edge(described_uri, describing_uri , edge_uri, edge_attr)

        return g


"""
126. Word Ladder II

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

Only one letter can be changed at a time
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:

Return an empty list if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
You may assume beginWord and endWord are non-empty and are not the same.

Example 1:

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

Output:
[
  ["hit","hot","dot","dog","cog"],
  ["hit","hot","lot","log","cog"]
]

Example 2:

Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

Output: []

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

"""

class WordLadderII:

    def doit_bfs_bidirect(self, beginWord, endWord, wordList):
        import collections
        import string

        if endWord not in wordList:
            return []

        def construct_paths(source, dest, tree):
            if source == dest:
                return [[source]]
            return [[source] + path for succ in tree[source] for path in construct_paths(succ, dest, tree)]

        def add_path(tree, word, neigh, is_forw):
            if is_forw:
                tree[word] += neigh,
            else:
                tree[neigh] += word,

        def bfs_level(this_lev, oth_lev, tree, is_forw, words_set):
            if not this_lev:
                return False

            if len(this_lev) > len(oth_lev):
                return bfs_level(oth_lev, this_lev, tree, not is_forw, words_set)

            for word in (this_lev | oth_lev):
                words_set.discard(word)

            next_lev, done = set(), False
            while this_lev:
                word = this_lev.pop()
                for c in string.ascii_lowercase:
                    for index in range(len(word)):
                        neigh = word[:index] + c + word[index + 1:]
                        if neigh in oth_lev:
                            done = True
                            add_path(tree, word, neigh, is_forw)
                        if not done and neigh in words_set:
                            next_lev.add(neigh)
                            add_path(tree, word, neigh, is_forw)

            return done or bfs_level(next_lev, oth_lev, tree, is_forw, words_set)

        tree, path, paths = collections.defaultdict(list), [beginWord], []
        bfs_level(set([beginWord]), set([endWord]), tree, True, set(wordList))

        return construct_paths(beginWord, endWord, tree)

    def doit_bfs(self, beginWord, endWord, wordList):
        from collections import defaultdict
        tree, words, n = defaultdict(set), set(wordList), len(beginWord)
        if endWord not in wordList:
            return []

        found, bq, eq, nq, rev = False, {beginWord}, {endWord}, set(), False
        while bq and not found:
            words -= set(bq)
            for x in bq:
                for i in range(n):
                    first, second = x[:i], x[i + 1:]
                    for c in 'qwertyuiopasdfghjklzxcvbnm':
                        y = first + c + second
                        if y in words:
                            if y in eq:
                                found = True
                            else:
                                nq.add(y)
                            tree[y].add(x) if rev else tree[x].add(y)
            bq, nq = nq, set()
            if len(bq) > len(eq):
                bq, eq, rev = eq, bq, not rev

        def bt(x):
            return [[x]] if x == endWord else [[x] + rest for y in tree[x] for rest in bt(y)]

        return bt(beginWord)

    def doit_bfs_bidirect(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: List[List[str]]
        """
        from collections import defaultdict

        beginset, endset, tree = set([beginWord]), set([endWord]), defaultdict(set)
        wl = set(wordList)

        if endWord not in wl:
            return []

        found, reverse = False, False
        while beginset and not found:

            wl -= beginset
            nextset = set()

            for w in beginset:

                for i in range(len(w)):
                    for c in 'abcdefghijklmnopqrstuvwxyz':
                        nw = w[:i] + c + w[i + 1:]
                        if nw in wl:
                            if nw in endset:
                                found = True
                            else:
                                nextset.add(nw)

                            if reverse:
                                tree[nw].add(w)
                            else:
                                tree[w].add(nw)

            beginset = nextset
            if len(beginset) > len(endset):
                beginset, endset = endset, beginset
                reverse = not reverse

        def build(x):
            if x == endWord:
                return [[x]]
            else:
                res = []
                for c in tree[x]:
                    for r in build(c):
                        res.append([x] + r)
                return res

        return build(beginWord)

if __name__ == '__main__':

    WordLadderII().doit_bfs_1("hit", "cog", ["hot","dot","dog","lot","log","cog"])