# goal
# 실패율이 높은 스테이지부터 내림차순으로 스테이지의 번호가 담겨있는 배열을 return 하도록 solution 함수

# description
# 실패율 - 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수
# 전체 스테이지의 개수 N, 게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages가 매개변수

# condition
# 스테이지의 개수 N은 1 이상 500 이하의 자연수이다.
# stages의 길이는 1 이상 200,000 이하이다.
# stages에는 1 이상 N + 1 이하의 자연수가 담겨있다.
# 각 자연수는 사용자가 현재 도전 중인 스테이지의 번호를 나타낸다.
# 단, N + 1 은 마지막 스테이지(N 번째 스테이지) 까지 클리어 한 사용자를 나타낸다.
# 만약 실패율이 같은 스테이지가 있다면 작은 번호의 스테이지가 먼저 오도록 하면 된다.
# 스테이지에 도달한 유저가 없는 경우 해당 스테이지의 실패율은 0 으로 정의한다.

import collections

def solution(N, stages):
    total = len(stages)
    dic = {}
    # counter 함수 통해서 각 숫자별 개수 구하기
    stages_counter = collections.Counter(stages)

    # 1부터 N+1까지 돌려서 dic에 key(숫자) value(실패율)로 넣기 total에서 이전 숫자만큼 분모 빼면서 넣기
    # 끝까지 통과한 애들은 필요 없어서 N+1.
    for i in range(1, N+1):
        dic[i] = 0 if stages_counter[i] == 0 else stages_counter[i]/total
        total -= stages_counter[i]

    return [k for k, v in sorted(dic.items(), reverse=True, key=lambda x: x[1])]


import time

import PySimpleGUI as sg

from classes.logger import Logger
from classes.microscope_mover import MicroscopeMover, mover
from classes.scanner import Scanner
from classes.solis import Automatization
from gui.helpers import disable_element, enable_element, get_load_path, str_to_int
from gui.scanner_gui import AutomatizationGUI

PADDING = 4

logger = Logger(__name__).get_logger()

paused = False
stopped = False
current_point_nr = 1

def construct_number_with_padding(point_number: int, line_number: int):
    digit_count_point = len(str(point_number))
    digit_count_line = len(str(line_number))
    return f"P{'0'*(PADDING - digit_count_point)}{point_number}x{'0'*(PADDING - digit_count_line)}{line_number}"

def start_scanning(scanner: Scanner, mover: MicroscopeMover, solis: Automatization, integr_time: int):
    global paused, stopped, current_point_nr
    logger.info("Started scanning sequence")

    line_number = 0
    point_number = 1
    previous_x = 0
    one_point = True

    if len(scanner.all_scanner_points) >= 2:
        step = scanner.all_scanner_points[1] - scanner.all_scanner_points[0]
        one_point = False
        previous_x = 99999999 if step.x > 0 else -99999999

    for i, point in enumerate(scanner.all_scanner_points):

        while paused:
            time.sleep(0.5)

        if stopped:
            return

        current_point_nr = i + 1
        if not one_point:

            if step.x < 0 and point.x > previous_x:
                line_number += 1
                point_number = 1
            elif step.x > 0 and point.x < previous_x:
                line_number += 1
                point_number = 1

            previous_x = point.x

        point_filename = construct_number_with_padding(point_number, line_number)
        scanner.next_scan()
        mover.set_coordinates(point)

        solis.capture_and_save(filename=point_filename, integr_time=integr_time, first_time=i == 0)
        point_number += 1

    logger.info("Successfully ended scanning sequence")
    stopped, paused = False, False

def main():
    global paused, stopped, current_point_nr

    solis = Automatization("Andor SOLIS for Spectroscopy: *")

    if not solis.success:
        return

    gui = AutomatizationGUI()
    scanner = Scanner()
    window = gui.window

    started = False

    while 1:
        event, values = window.read(timeout=1000)

        if started and current_point_nr > 1 and not paused:
            sg.one_line_progress_meter(
                "Progress bar",
                current_point_nr,
                len(scanner.all_scanner_points),
                orientation="h",
                keep_on_top=True,
                no_button=True,
            )

        if event == sg.WIN_CLOSED:
            break

        if event == "-LOADSCANPOINTS-":

            points_load_path = get_load_path()

            if not points_load_path:
                continue

            if not scanner.load_coordinates(points_load_path):
                continue

            window["-POINTCOUNT-"].update(scanner.all_point_count)
            stopped, paused = False, False

        if event == "-GOFIRSTPOINT-":

            if not scanner.all_scanner_points:
                logger.error("No scanning points loaded")
                continue

            mover.set_coordinates(scanner.all_scanner_points[0])

        if event == "-STARTSCAN-":
            stopped = False
            if not scanner.all_scanner_points:
                logger.error("No scanning points loaded")
                continue

            integration_time = str_to_int(values["-INTEGRATIONTIME-"])

            if integration_time <= 0:
                logger.error("Negative total integration time")
                continue

            started = True

            window.perform_long_operation(lambda: start_scanning(scanner, mover, solis, integration_time), "-ENDSCAN-")
            disable_element(window, "-STARTSCAN-")
            enable_element(window, "-STOP-")
            enable_element(window, "-PAUSE-")

        if event == "-ENDSCAN-":
            started = False
            message = "Scanning stopped by user" if stopped else "Scanning successfully ended"
            color = "red" if stopped else "green"
            sg.one_line_progress_meter_cancel()
            sg.popup_ok(message, keep_on_top=True, background_color=color)
            enable_element(window, "-STARTSCAN-")
            disable_element(window, "-STOP-")
            disable_element(window, "-PAUSE-")

        if event == "-PAUSE-":
            paused = True if not paused else False
            logger.warning("Paused Scanning" if paused else "Continue scanning")
            window["-PAUSE-"].update("Unpause" if paused else "Pause")
            window["-STOP-"].update(disabled=paused)

        if event == "-STOP-":
            stopped = True

if __name__ == "__main__":
    main()


"""
Django command to wait for DB to be available
"""
import time

# Shows error but the psycopg2 is successfully installed on docker
from psycopg2 import OperationalError as Psycopg2Error
from django.db.utils import OperationalError

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    """
    Django command to wait for db
    """

    def handle(self, *args, **options):

        self.stdout.write('Waiting for the Database to start....')
        db_up = False

        while db_up is False:

            try:
                self.check(databases=['default'])
                db_up = True

            except (Psycopg2Error, OperationalError):
                self.stdout.write("DB is unavailable right now. \
                 Waiting for 1 sec to restart the database")
                time.sleep(1)

        self.stdout.write(self.style.SUCCESS('DB is UP '))


from .interpretpicklist import Interpretpicklist
from . import dateutils
from datetime import datetime
from . import xmlutilities
from synthesis.exceptions import DataFormatError#, SoftwareCompatibilityError
from . import logger
#from sys import version
from . import dbobjects
from .writer import Writer
from zope.interface import implementer
from sqlalchemy import or_, and_, between
from .conf import settings
from lxml import etree as ET

def buildWorkhistoryAttributes(element):
    element.attrib['date_added'] = datetime.now().isoformat()
    element.attrib['date_effective'] = datetime.now().isoformat()

@implementer(Writer)
class SvcPointXML5Writer():
    # Writer Interface

    hmis_namespace = "http://www.hmis.info/schema/2_8/HUD_HMIS_2_8.xsd"
    airs_namespace = "http://www.hmis.info/schema/2_8/AIRS_3_0_draft5_mod.xsd"
    nsmap = {"hmis" : hmis_namespace, "airs" : airs_namespace}

    svcpt_version = '5.00'

    def __init__(self, poutDirectory, processingOptions, debugMessages=None):
        #print "%s Class Initialized" % self.__name__

        if settings.DEBUG:
            print("XML File to be dumped to: %s" % poutDirectory)
            self.log = logger.Logger(configFile=settings.LOGGING_INI, loglevel=40)    # JCS 10/3/11

        self.outDirectory = poutDirectory
        self.pickList = Interpretpicklist()
        # SBB20070626 Adding the declaration for outcomes list
        self.options = processingOptions

        # SBB20070628 adding a buffer for errors to be displayed at the end of the process.
        self.errorMsgs = []

        self.db = dbobjects.DB()            # JCS 10/05/11
        self.db.Base.metadata.create_all()

    def write(self):
        self.startTransaction()
        self.processXML()
        self.prettify()
        print('==== Self:', self)
        xmlutilities.writeOutXML(self, xml_declaration=True, encoding="UTF-8")    # JCS, 1 Sep 2012
        #self.commitTransaction()
        return True

    def updateReported(self, currentObject):
        # update the reported field of the currentObject being passed in.  These should all exist.
        try:
            if settings.DEBUG:
                print('Updating reporting for object: %s' % currentObject.__class__)
            currentObject.reported = True
            #currentObject.update()
            self.commitTransaction()
        except:
            print("Exception occurred during update the 'reported' flag")
            pass

    def prettify(self):
        xmlutilities.indent(self.root_element)

    def dumpErrors(self):
        print("Error Reporting")
        print("-" * 80)
        for row in range(len(self.errorMsgs)):
            print("%s %s" % (row, self.errorMsgs[row]))

    def setSysID(self, pSysID):
        self.sysID = pSysID

    def commitTransaction(self):
        self.session.commit()

    def startTransaction(self):
        self.session = self.db.Session()

    def pullConfiguration(self, pExportID):
        # need to use both ExportID and Processing Mode (Test or Prod)
        export = self.session.query(dbobjects.Export).filter(dbobjects.Export.export_id == pExportID).one()
        if settings.DEBUG:
            print("trying to do pullConfiguration")
            #print "export is:", export, "pExportID is", pExportID
            #print "export.export_id is: ", export.export_id
            #print "dbobjects.SystemConfiguration.source_id is ", dbobjects.SystemConfiguration.source_id

        selink = self.session.query(dbobjects.SourceExportLink).filter(dbobjects.SourceExportLink.export_index_id == export.id).one()
        #print '==== Selink.id:', selink.id
        source = self.session.query(dbobjects.Source).filter(dbobjects.Source.id == selink.source_index_id).one()
        #print '==== Source.id:', source.id
        self.configurationRec = self.session.query(dbobjects.SystemConfiguration).filter(and_(dbobjects.SystemConfiguration.source_id == source.source_id, dbobjects.SystemConfiguration.processing_mode == settings.MODE)).one()
        #print '==== sys config.id', self.configurationRec.id

    def processXML(self): # records represents whatever element you're tacking more onto, like entry_exits or clients
        if settings.DEBUG:
            print("processXML: Appending XML to Base Record")
        self.root_element = self.createDoc() #makes root element with XML header attributes
        #print '==== root created'
        clients = self.createClients(self.root_element) # JCS - tag is <clientRecords> Only node under clients is <Client>
        print('==== clientRecords created')

        if self.options.reported == True:
            Persons = self.session.query(dbobjects.Person).filter(dbobjects.Person.reported == True)
        elif self.options.unreported == True:
            Persons = self.session.query(dbobjects.Person).filter(or_(dbobjects.Person.reported == False, dbobjects.Person.reported == None))
        elif self.options.reported == None:
            Persons = self.session.query(dbobjects.Person)
        # Now apply the dates to the result set.
        if self.options.alldates == None:
            Persons = Persons.filter(between(dbobjects.Person.person_id_date_collected, self.options.startDate, self.options.endDate))

        pulledConfigID = 0    # JCS Only pull it if it has changed
        for self.person in Persons:
            #print "person is: ", self.person

            export = self.person.fk_person_to_export    # this is a single record because:
            # person has: export_index_id = Column(Integer, ForeignKey('export.id'))
            # export has: fk_export_to_person = relationship('Person', backref='fk_person_to_export')
            # Therefore there are multiple persons to one export - but only one export to a person

            #print "==== export before pullconfig:", export.id, export  # JCS
            if pulledConfigID != export.id:
                self.pullConfiguration(export.export_id)
                pulledConfigID = export.id

            self.ph = self.person.fk_person_to_person_historical    # JCS This is a list of records
            self.race = self.person.fk_person_to_races
            self.site_service_part = self.person.site_service_participations    # JCS

            #information_releases = self.person.fk_person_to_release_of_information    # JCS a set
            #self.service_event = self.person.fk_person_to_service_event
            # Instead of generating a number (above), use the client number that is already provided in the legacy system
            # or
            # self.iDG.initializeSystemID(self.person.id)
            self.sysID = self.person.id        # JCS beware set self.sysID
            #if settings.DEBUG:
                #print "self.person is:", self.person
            if self.person: # and not self.person.person_legal_first_name_unhashed+self.person.person_legal_last_name_unhashed == None:
                self.client = self.createClient(clients) # JCS - no clients in svc5? yes as clientRecords
                # Sub can be: active, anonymous, firstName, suffix, unnamedClient, alias, middleName, childEntryExit,
                # childReleaseOfInfo, childGoal
                self.customizeClient(self.client)
                self.customizeClientPersonalIdentifiers(self.client, self.person)
                self.assessment_data = self.createAssessmentData(self.client) # JCS New - self?
                self.customizeAssessmentData(self.assessment_data)
                if self.site_service_part:      # JCS 21 Dec 2012
                    self.child_entry_exit = self.createChildEntryExit(self.client)
                    for ssp in self.site_service_part:
                        self.createEntryExit(self.child_entry_exit, ssp)
            # update the reported flag for person (This needs to be applied to all objects that we are getting data from)
            self.updateReported(self.person)

        # Query Mechanism for Site Service Participation (Entry Exits) same as for Person?
# This is only if we want to create an EE summary at the end for all Clients
#        if self.options.reported == True:
#            site_service_part = self.session.query(dbobjects.SiteServiceParticipation).filter(dbobjects.SiteServiceParticipation.reported == True)
#        elif self.options.unreported == True:
#            site_service_part = self.session.query(dbobjects.SiteServiceParticipation).filter(or_(dbobjects.SiteServiceParticipation.reported == False, dbobjects.SiteServiceParticipation.reported == None))
#        elif self.options.reported == None:
#            site_service_part = self.session.query(dbobjects.SiteServiceParticipation)
#        else:
#            pass
#
#        # setup the date filter also
#        site_service_part = site_service_part.filter(between(dbobjects.SiteServiceParticipation.site_service_participation_idid_num_date_collected, self.options.startDate, self.options.endDate))
#
#        entry_exits = self.createEntryExits(self.root_element)
#        for EE in site_service_part:
#            # SBB20100405 do this to pull the configuration record
#            person = EE.fk_participation_to_person
#            export = person.fk_person_to_export
#            self.pullConfiguration(export.export_id)
#            self.updateReported(EE)        # Reporting Update
#            self.sysID = EE.id            # JCS beware set self.sysID
#            self.createEntryExit(entry_exits, EE)

        # End of ProcessXML()

    def createDoc(self):

        # From hl7
        #self.mymap = { None  : "urn:hl7-org:v3",
        #          "voc" : "urn:hl7-org:v3/voc",
        #          "xsi" : "http://www.w3.org/2001/XMLSchema-instance"}
        #root_element = ET.Element("ClinicalDocument", nsmap=self.mymap)
        #root_element.attrib["{"+self.mymap["xsi"]+"}schemaLocation"] = "urn:hl7-org:v3 infrastructure/cda/CDA.xsd"
        # From hl7 end

        #sp5_instance looks like this
        # <records xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        #       xsi:noNamespaceSchemaLocation="file:/home/eric/workspace/servicepoint_schema/sp5/sp5.xsd"
        #       odb_identifier="qwo7Wsoi"
        #       import_identifier="v7:1bl.e">

        self.mymap = {"xsi" : "http://www.w3.org/2001/XMLSchema-instance"}  # Yes lxml

        #root_element = ET.Element("records")       # Non-lxml
        root_element = ET.Element("records", nsmap=self.mymap)  # Yes lxml

        #root_element.attrib["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"    # Non-lxml

        #root_element.attrib["xsi:noNamespaceSchemaLocation"] = "sp5.xsd"     # Non-lxml
        root_element.attrib["{"+self.mymap["xsi"]+"}noNamespaceSchemaLocation"] = "sp5.xsd"  # Yes lxml

        # Added by JCS 1 Sep 2012
        root_element.attrib["odb_identifier"] = "qwo7Wsoi"      # Yes lxml
        root_element.attrib["import_identifier"] = "v7:1bl.e"   # Yes lxml

        #root_element.attrib["schema_revision"] = "300_108"    # JCS Not in Schema
        #root_element.text = "\n"
        return root_element

    def createClients(self, root_element):
        clients = ET.SubElement(root_element, "clientRecords")
        return clients

    def createClient(self, clients):
        client = ET.SubElement(clients, "Client")    #  Cap 'C' in svc5
        return client

    def createChildEntryExit(self,client):
        child_entry_exit = ET.SubElement(client, "childEntryExit") # JCS new - sub-client
        return child_entry_exit

    def createEntryExits(self,root_element):
        entry_exits = ET.SubElement(root_element, "entryExitRecords") # JCS - not in SVP5?
        return entry_exits

    def customizeClient(self, client):

        #print "==== Customize Client:", self.configurationRec.odbid, self.person.person_id_id_num
        client.attrib["record_id"] = "CL-" + str(self.person.id)
        #client.attrib["external_id"] = self.person.person_id_id_num    # JCS -this item is optional
        client.attrib["system_id"] = self.person.person_id_id_num        # JCS just a guess ????
        client.attrib["date_added"] = dateutils.fixDate(datetime.now())
        client.attrib["date_updated"] = dateutils.fixDate(datetime.now())

        # SBB20070702 check if self.intakes has none, this is a daily census that is alone
    def customizeClientPersonalIdentifiers(self,client,recordset):    # params are: self.client, self.person

        if recordset.person_legal_first_name_unhashed != "" and recordset.person_legal_first_name_unhashed != None:
            first_name = ET.SubElement(client, "firstName")
            first_name.text = recordset.person_legal_first_name_unhashed

        if recordset.person_legal_last_name_unhashed != "" and recordset.person_legal_last_name_unhashed != None:
            last_name = ET.SubElement(client, "lastName")
            last_name.text = recordset.person_legal_last_name_unhashed

        #we don't have the following elements for daily_census only clients, but SvcPt requires them:
        # I simulated this w/my datasets.  Column names are as in the program
        if recordset.person_legal_middle_name_unhashed != "" and recordset.person_legal_middle_name_unhashed != None:
            mi_initial = ET.SubElement(client, "mi_initial")
            mi_initial.text = self.fixMiddleInitial(recordset.person_legal_middle_name_unhashed)

        # SBB20070831 incoming SSN's are 123456789 and need to be 123-45-6789
        fixedSSN = self.fixSSN(recordset.person_social_security_number_unhashed) # JCS  .person_SSN_unhashed)

        if fixedSSN != "" and fixedSSN != None:        #ECJ20071111 Omit SSN if it's blank
            soc_sec_no = ET.SubElement(client, "socSecNoDashed")
            soc_sec_no.text = fixedSSN
            ssn_data_quality = ET.SubElement(client, "ssnDataQualityValue")
            ssn_data_quality.text = "full ssn reported (hud)"

    def createEntryExit(self, entry_exits, EE):    # Outer Node, one EntryExit(ssp)

        entry_exit = ET.SubElement(entry_exits, "EntryExit")

        entry_exit.attrib["record_id"] = "EE-"+str(EE.id)
        # ssp-idid-num looks like it ought to be unique, but isn't in sample input data, so append client id????
        entry_exit.attrib["system_id"] = EE.site_service_participation_idid_num+"-"+EE.person.person_id_id_num
        # person.site_service_participations = relationship("SiteServiceParticipation", backref="person")
        entry_exit.attrib["date_added"] = dateutils.fixDate(datetime.now())
        entry_exit.attrib["date_updated"] = dateutils.fixDate(datetime.now())

        self.customizeEntryExit(entry_exit, EE)
        return entry_exit

    def customizeEntryExit(self, entry_exit, EE):
        # Schema expects one of ( active, typeEntryExit, client, exitDate, reasonLeavingValue, reasonLeavingOther,
        #    destinationValue, destinationOther, notes, group )
        # There is no type in our input XML, nor a field in ssp. Schema needs {'basic', 'basic center program entry/exit',
        #   'hprp', 'hud', 'path', 'quick call', 'standard', 'transitional living program entry/exit'}
        type1 = ET.SubElement(entry_exit, "typeEntryExit")    # JCS  this is a fudge to pass validation
        type1.text = "basic"    # "hud-40118"

        provider_id = ET.SubElement(entry_exit, "provider")
        provider_id.text = '%s' % self.configurationRec.providerid

        if EE.participation_dates_start_date != "" and EE.participation_dates_start_date != None:
            entry_date = ET.SubElement(entry_exit, "entryDate")
            entry_date.text = dateutils.fixDate(EE.participation_dates_start_date)

            if EE.participation_dates_end_date != "" and EE.participation_dates_end_date != None:
                exit_date = ET.SubElement(entry_exit, "exitDate")
                exit_date.text = dateutils.fixDate(EE.participation_dates_end_date)
        return

    def createAssessmentData(self, client):        # dynamic content type
        assessment_data = ET.SubElement(client, "assessmentData")
        return assessment_data

    def customizeAssessmentData(self, assessment_data):

        if self.person.person_gender_unhashed != "" and self.person.person_gender_unhashed != None:
            persGender = ET.SubElement(assessment_data, "svpprofgender" ) #"gender")
            persGender.attrib["date_added"] = dateutils.fixDate(self.person.person_gender_unhashed_date_collected)
            persGender.attrib["date_effective"] = dateutils.fixDate(self.person.person_gender_unhashed_date_effective)
            persGender.text = str(self.person.person_gender_unhashed)

        # dob (Date of Birth)    lots of:SVPPROFDOB    a few:DATEOFBIRTH
        if self.person.person_date_of_birth_unhashed != "" and self.person.person_date_of_birth_unhashed != None:
            dob = ET.SubElement(assessment_data, "svpprofdob")
            dob.attrib["date_added"] = dateutils.fixDate(self.person.person_date_of_birth_unhashed_date_collected)
            dob.attrib["date_effective"] = dateutils.fixDate(datetime.now())    # No date effect. in Person
            dob.text = dateutils.fixDate(self.person.person_date_of_birth_unhashed)

        # Ethnicity           lots of:SVPPROFETH    a few:Ethnicity     uses:ETHNICITYPickOption
        if self.person.person_ethnicity_unhashed != "" and self.person.person_ethnicity_unhashed != None:
            # Our Interpretpicklist basically has 2 options. The schema has 23
            ethText = self.pickList.getValue("EthnicityPick",str(self.person.person_ethnicity_unhashed))
            eth = ET.SubElement(assessment_data, "svpprofeth")
            eth.attrib["date_added"] = dateutils.fixDate(self.person.person_ethnicity_unhashed_date_collected)
            eth.attrib["date_effective"] = dateutils.fixDate(datetime.now())    # No date effect. in Person
            eth.text = ethText  # str(self.person.person_ethnicity_unhashed)

        # Race    more than one?? JCS
        for race in self.race:
            # JCS schema has 'RACEPickOption' - using existing RacePick for now
            raceText = self.pickList.getValue("RacePick",str(race.race_unhashed))
            # print '==== race:', race.race_unhashed, raceText
            if raceText != None:
                raceNode = ET.SubElement(assessment_data, "svpprofrace")    # JCS "primaryrace" or "svpprofrace"?
                raceNode.attrib["date_added"] = dateutils.fixDate(race.race_date_collected)
                raceNode.attrib["date_effective"] = dateutils.fixDate(race.race_date_effective)
                raceNode.text = raceText

        for ph in self.ph:
            #print '==== ph person id:', ph.person_index_id #, ph.__dict__
            # JCS - Fails if none - seen in going from tbc to here - but don't know if that ever happens
            hs = self.session.query(dbobjects.HousingStatus).filter(dbobjects.HousingStatus.person_historical_index_id == ph.id).one()
            hsText = self.pickList.getValue("HOUSINGSTATUSPickOption",hs.housing_status)
            #print '==== hs:', hsText
            if hsText != None:
                housingStatus = ET.SubElement(assessment_data, "svp_hud_housingstatus")    # JCS
                housingStatus.attrib["date_added"] = dateutils.fixDate(hs.housing_status_date_collected)
                housingStatus.attrib["date_effective"] = dateutils.fixDate(hs.housing_status_date_effective)
                housingStatus.text = hsText

            foster = self.session.query(dbobjects.FosterChildEver).filter(dbobjects.FosterChildEver.person_historical_index_id == ph.id).one()
            fosterText = self.pickList.getValue("ENHANCEDYESNOPickOption",str(foster.foster_child_ever))
            if fosterText != None:
                fosterEver = ET.SubElement(assessment_data, "x20wereyoueverafoster")    # JCS
                fosterEver.attrib["date_added"] = dateutils.fixDate(foster.foster_child_ever_date_collected)
                fosterEver.attrib["date_effective"] = dateutils.fixDate(foster.foster_child_ever_date_effective)
                fosterEver.text = fosterText

        # length of stay at prior residence
        losapr = self.session.query(dbobjects.LengthOfStayAtPriorResidence).filter(dbobjects.LengthOfStayAtPriorResidence.person_historical_index_id == ph.id).one()
        losaprText = self.pickList.getValue("LENGTHOFTHESTAYPickOption",losapr.length_of_stay_at_prior_residence)
        #print '==== losapr:', losaprText
        if losaprText != None:
            lengthOfStay = ET.SubElement(assessment_data, "hud_lengthofstay")    # JCS
            lengthOfStay.attrib["date_added"] = dateutils.fixDate(losapr.length_of_stay_at_prior_residence_date_collected)
            lengthOfStay.attrib["date_effective"] = dateutils.fixDate(losapr.length_of_stay_at_prior_residence_date_effective)
            lengthOfStay.text = losaprText

        # "Prior Residence" becomes "typeoflivingsituation"
        tols = self.session.query(dbobjects.PriorResidence).filter(dbobjects.PriorResidence.person_historical_index_id == ph.id).one()
        tolsText = self.pickList.getValue("LIVINGSITTYPESPickOption",tols.prior_residence_code)
        #print '==== (prior) tols:', tolsText
        if tolsText != None:
            priorLiving = ET.SubElement(assessment_data, "typeoflivingsituation")    # JCS
            priorLiving.attrib["date_added"] = dateutils.fixDate(tols.prior_residence_code_date_collected)
            priorLiving.attrib["date_effective"] = dateutils.fixDate(tols.prior_residence_code_date_effective)
            priorLiving.text = tolsText
        # There's also a  prior_residence_id_id_num populated with a 13 digit number as string  JCS

        # Physical Disability - Boolean
        pdyn = self.session.query(dbobjects.PhysicalDisability).filter(dbobjects.PhysicalDisability.person_historical_index_id == ph.id).one()
        pdynText = pdyn.has_physical_disability
        #print '==== pdyn:', pdynText
        if pdynText != None:
            physDisabYN = ET.SubElement(assessment_data, "svpphysicaldisabilit")    # JCS
            physDisabYN.attrib["date_added"] = dateutils.fixDate(pdyn.has_physical_disability_date_collected)
            # This is required, but input is usually blank - something plugs in now()
            physDisabYN.attrib["date_effective"] = dateutils.fixDate(pdyn.has_physical_disability_date_effective)
            physDisabYN.text = pdynText
        # There is also a complex type "disabilities_1"

        # Veteran Status - Uses "ENHANCEDYESNOPickOption" which is a union, and allows anything
        vvs = self.session.query(dbobjects.VeteranVeteranStatus).filter(dbobjects.VeteranVeteranStatus.person_historical_index_id == ph.id).one()
        vvsText = vvs.veteran_status
        #print '==== vvs:', vvsText
        if vvsText != None:
            vetStat = ET.SubElement(assessment_data, "veteran")    # JCS
            vetStat.attrib["date_added"] = dateutils.fixDate(vvs.veteran_status_date_collected)
            vetStat.attrib["date_effective"] = dateutils.fixDate(vvs.veteran_status_date_effective)
            vetStat.text = vvsText

#    def customizeDisabilities_1(self, disabilities_1, ph):
#        #if self.intakes['DisabilityDiscription'] != "":
#        noteondisability = ET.SubElement(disabilities_1,'noteondisability')
#        noteondisability.attrib["date_added"] = dateutils.fixDate(datetime.now())
#        noteondisability.attrib["date_effective"] = dateutils.fixDate(ph.physical_disability_date_collected)
#        noteondisability.text = ph.physical_disability

    def current_picture(self, node):
        ''' Internal function.  Debugging aid for the export module.'''
        if settings.DEBUG:
            print("Current XML Picture is")
            print("======================\n" * 2)
            ET.dump(node)
            print("======================\n" * 2)

    def calcHourlyWage(self, monthlyWage):
        if monthlyWage != "":
            if monthlyWage.strip().isdigit():
                if float(monthlyWage) > 5000.00:
                    hourlyWage = float(monthlyWage) / 160.00#IGNORE:@UnusedVariable
            else:
                hourlyWage = float(monthlyWage)#IGNORE:@UnusedVariable
        else:
            hourlyWage = 0.00
        return str(round(hourlyWage,2))

    def fixMiddleInitial(self, middle_initial):
        fixed_middle_initial = middle_initial[0].upper().lstrip()
        return fixed_middle_initial

    def fixSSN(self, incomingSSN):
        originalSSN = incomingSSN
        if incomingSSN == "" or incomingSSN == None:
            return incomingSSN

        dashCount = incomingSSN.count('-')
        if dashCount > 0:
            if dashCount == 2:
            # already has the dashes, return the string
                if settings.DEBUG:
                    self.debugMessages.log("incoming SSN is correctly formatted: %s\n" % (incomingSSN))

                return incomingSSN
            else:       # incoming SSN has 1 dash but not 2.  This is an error
            # fix this data
                incomingSSN = incomingSSN.replace( '-', '')
                if len(incomingSSN) < 9:
                    # reformat the string and return
                    theError = (1020, 'Data format error discovered in trying to cleanup incoming SSN: %s, original SSN: %s' % (incomingSSN, originalSSN))
                    if settings.DEBUG:
                        self.debugMessages.log(">>>> Incoming SSN is INcorrectly formatted.  Original SSN from input file is: %s and Attempted cleaned up SSN is: %s\n" % (originalSSN, incomingSSN))
                    raise DataFormatError(theError)

        # If we are here, we can simply reformat the string into dashes
        if settings.DEBUG:
            pass    # JCS
        #   self.debugMessages.log("incoming SSN is INcorrectly formatted: %s.  Reformatting to: %s\n" % (incomingSSN, '%s-%s-%s' % (incomingSSN[0:3], incomingSSN[3:5], incomingSSN[5:10])))
        return '%s-%s-%s' % (incomingSSN[0:3], incomingSSN[3:5], incomingSSN[5:10])

#if __name__ == "__main__":
#   vld = SVCPOINTXMLWriter(".")
#   vld.write()


import numpy as np
import cv2
import matplotlib.pyplot as plt

def getScoreImg():
    nums = cv2.imread("numbers.png")
    ret, nums = cv2.threshold(nums,127,255,cv2.THRESH_BINARY_INV)
    nums = cv2.cvtColor(nums, cv2.COLOR_BGR2GRAY)
    top = np.zeros((1,530))
    nums = np.concatenate((top,top,top,top, nums, top,top,top,top,top), axis=0)
    nums = cv2.resize(nums, (530*40//109, 40))
    ret, nums = cv2.threshold(nums,127,255,cv2.THRESH_BINARY_INV)

    zero = nums[:, 2:20]
    one = nums[:, 21:38]
    two = nums[:, 39: 57]
    three = nums[:, 58: 77]
    four = nums[:, 76:97]
    five = nums[:, 96:115]
    six = nums[:, 115:134]
    seven = nums[:, 134:153]
    eight = nums[:, 152:172]
    nine = nums[:, 171:191]
    cv2.imwrite("0.png", zero)
    cv2.imwrite("1.png", one)
    cv2.imwrite("2.png", two)
    cv2.imwrite("3.png", three)
    cv2.imwrite("4.png", four)
    cv2.imwrite("5.png", five)
    cv2.imwrite("6.png", six)
    cv2.imwrite("7.png", seven)
    cv2.imwrite("8.png", eight)
    cv2.imwrite("9.png", nine)

    plt.imshow(one, cmap='gray')
    plt.show()

def getTimeImg():
    nums = cv2.imread("time.png")
    ret, nums = cv2.threshold(nums,127,255,cv2.THRESH_BINARY_INV)
    nums = cv2.cvtColor(nums, cv2.COLOR_BGR2GRAY)
    print(nums.shape)
    # top = np.zeros((1,530))
    # nums = np.concatenate((top,top,top,top,top,top,top,top, nums,top,top,top,top,top,top,top,top,top), axis=0)
    nums = cv2.resize(nums, (480*40//172, 40))
    ret, nums = cv2.threshold(nums,127,255,cv2.THRESH_BINARY_INV)

    zero = nums[:, 0:12]
    one = nums[:, 12:21]
    two = nums[:, 22: 33]
    three = nums[:, 33: 44]
    four = nums[:, 43:56]
    five = nums[:, 55:66]
    six = nums[:, 66:78]
    seven = nums[:, 77:88]
    eight = nums[:, 88:100]
    nine = nums[:,99:110]
    cv2.imwrite("time_0.png", zero)
    cv2.imwrite("time_1.png", one)
    cv2.imwrite("time_2.png", two)
    cv2.imwrite("time_3.png", three)
    cv2.imwrite("time_4.png", four)
    cv2.imwrite("time_5.png", five)
    cv2.imwrite("time_6.png", six)
    cv2.imwrite("time_7.png", seven)
    cv2.imwrite("time_8.png", eight)
    cv2.imwrite("time_9.png", nine)

    plt.imshow(nine, cmap='gray')
    plt.show()

if __name__ == "__main__":
    getScoreImg()
    # getTimeImg()


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

# # COEN 140 Final Project - Music Genre Classifer

# In[241]:

import os
import json
import numpy as np
import scipy
import pandas as pd
import librosa as lb
import warnings

from sklearn.model_selection import train_test_split
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis
from sklearn.linear_model import LogisticRegression
from sklearn.cluster import KMeans

# ## Import functions

# In[3]:

def import_features(n=None):
    return pd.read_csv('fma_metadata/features.csv', header=[0,1,2], index_col=0, nrows=n)

def import_tracks(n=None, col=':'):
    return pd.read_csv('fma_metadata/tracks.csv', header=[0,1], index_col=0, nrows=n)

def import_genres(n=None):
    return pd.read_csv('fma_metadata/genres.csv', header=0, index_col=0, nrows=n)

# ## Feature extraction function

# In[3]:

def get_song_features(name):
    # Get the file path to an included audio example
    file = os.path.join(os.getcwd(), "test_songs", name)

    # Load into waveform 'y', sampling rate 'sr'
    y, sr = lb.load(file)
    print('> \'{}\' successfully loaded'.format(name))

    ## Extract all features
    df = {}

    df["chroma_stft"] = lb.feature.chroma_stft(y=y, sr=sr)
    df["chroma_cqt"] = lb.feature.chroma_cqt(y=y, sr=sr)
    df["chroma_cens"] = lb.feature.chroma_cens(y=y, sr=sr)

    df["tonnetz"] = lb.feature.tonnetz(y=y, sr=sr)
    df["mfcc"] = lb.feature.mfcc(y=y, sr=sr)

    df["spectral_centroid"] = lb.feature.spectral_centroid(y=y, sr=sr)
    df["spectral_bandwidth"] = lb.feature.spectral_bandwidth(y=y, sr=sr)
    df["spectral_contrast"] = lb.feature.spectral_contrast(y=y, sr=sr)
    df["spectral_rolloff"] = lb.feature.spectral_rolloff(y=y, sr=sr)

    df["rmse"] = lb.feature.rms(y=y)
    df["zcr"] = lb.feature.zero_crossing_rate(y=y)

    print('> Successfully extracted into dict')
    return df

# In[4]:

## format new song features

# fetch new song features as dict
feat = get_song_features("one_summers_day.mp3")

# fetch empty array with correct format, then append empty row
df = import_features(0).append(pd.Series(dtype=float), ignore_index=True)

# apply stats to new song features
stats = ['kurtosis','max','mean','median','min','skew','std']
funcs = [scipy.stats.kurtosis, np.amax, np.mean, np.median, np.amin, scipy.stats.skew, np.std]

for ft in df.columns.unique(0):
    for st, fn in zip(stats, funcs):
        df.loc[:,(ft,st)] = fn(feat[ft], axis=1)

print('> Successfully applied statistics')

# ## Classifier Helper Functions

# In[4]:

def format_test_valid(X, y, drop_unique=False):
    # parse genres into array
    y = y.apply(lambda g: json.loads(g))

    # select/remove empty genres
    eg = y.index[y.map(lambda g: len(g)==0)]
    X = X.drop(eg)
    y = y.drop(eg)

    # split into train/validate groups
    Xt, Xv, yt, yv = train_test_split(X, y, test_size=0.2, random_state=1)

    # remove genres with only 1 entry
    if drop_unique:
        ug = yt.drop_duplicates(False).index
        Xt = Xt.drop(ug)
        yt = yt.drop(ug)

    return Xt, Xv, yt, yv

def format_track_data(data, cols=None):
    # select specified columns
    data = data.loc[:,('track',cols)]
    data.columns = cols

    # parse genres into array
    data = data.applymap(lambda t: json.loads(t))

    return data

def score(a, b):
    assert len(a) == len(b), 'Arrays are not the same size'

    c = 0
    for v1, v2 in zip(a,b):
        if isinstance(v2, (int, np.integer)):
            if (v1==v2):
                c=c+1
        else:
            if v1 in v2:
                c=c+1
    return c/len(a)

def print_scores(ts, vs, name='New'):
    print('> {} Scores:'.format(name))
    print('Training score: {:.3f}\nValidation score: {:.3f}\n'.format(ts, vs))

# ## Classifier Implementations
# ### LDA Function

# In[264]:

def m1_LDA(X, y, score_method='default', verbose=False):
    #split data
    Xt, Xv, yt, yv = train_test_split(X, y, test_size=0.2)
    yt1 = yt.apply(lambda g: g[0])

    # fitting
    lda = LinearDiscriminantAnalysis()
    lda.fit(Xt, yt1)

    # predictions
    pt = lda.predict(Xt)
    terr = score(pt,yt)

    pv = lda.predict(Xv)
    verr = score(pv,yv)

    if verbose:
        print_scores(terr, verr, 'LDA')

    return verr

# ### QDA Function

# In[227]:

def m2_QDA(X, y, score_method='default', verbose=False):
    #split data
    Xt, Xv, yt, yv = train_test_split(X, y, test_size=0.2)
    yt1 = yt.apply(lambda g: g[0])

    # drop unique tracks
    ug = yt1.drop_duplicates(False).index
    Xt = Xt.drop(ug)
    yt = yt.drop(ug)
    yt1 = yt1.drop(ug)

    # fitting
    qda = QuadraticDiscriminantAnalysis(tol=10**-10)
    qda.fit(Xt, yt1)

    # predictions
    pt = qda.predict(Xt)
    terr = score(pt,yt)

    pv = qda.predict(Xv)
    verr = score(pv,yv)

    if verbose:
        print_scores(terr, verr, 'QDA')

    return verr

# ### KMC Function

# In[198]:

def m3_KMC(X, y, init_method='k-means++', verbose=False):
    #split data
    Xt, Xv, yt, yv = train_test_split(X, y, test_size=0.2)
    yt1 = yt.apply(lambda g: g[0])

    # kmeans
    centroids = yt1.drop_duplicates()
    if init_method == 'centroids':
        init_method = Xt.loc[centroids.index]
    kmc = KMeans(n_clusters=len(centroids), init=init_method, n_init=10)
    kmc.fit(Xt)

    # predictions
    pt = pd.Series(kmc.predict(Xt), index=Xt.index)
    for ci in pt.unique():
        same_gen = pt[pt==ci].index.values
        #print('{} entries in cluster {}'.format(len(same_gen), ci))
        all_gen = np.concatenate(yt[same_gen].values)
        mode_gen, cont_gen = scipy.stats.mode(all_gen)
        pt.loc[same_gen] = mode_gen[0]
    terr = score(pt,yt)

    pv = pd.Series(kmc.predict(Xv), index=Xv.index)
    for ci in pv.unique():
        same_gen = pv[pv==ci].index.values
        mode_gen, cont_gen = scipy.stats.mode(np.concatenate(yv[same_gen].values))
        pv.loc[same_gen] = mode_gen[0]
    verr = score(pv,yv)

    if verbose:
        print_scores(terr, verr, 'KMeans')

    return verr

# ## Testing
# ### Initial Testing

# In[256]:

# Import data
n = None # None = 106,574
X = import_features(n)
y = import_tracks(n)
g = import_genres(n)

# format genres properly
cols = ['genres','genres_all']
y = y.loc[:,('track',cols)]
y.columns = cols
y = y.applymap(lambda t: json.loads(t))

# Remove entries with empty genres
eg = y.index[y['genres'].map(lambda t: len(t)==0)]
X = X.drop(eg)
y = y.drop(eg)

# Add another column holding parent genres
y['top_level'] = y['genres'].apply(lambda t: [g.loc[t[0]]['top_level']])
print('> Data imported successfully')

# In[ ]:

lda = m1_LDA(X, y['genres'], verbose=True)
lda = m1_LDA(X, y['genres_all'], verbose=True)
lda = m1_LDA(X, y['top_level'], verbose=True)

# In[ ]:

warnings.filterwarnings('default')
qda = m2_QDA(X, y['genres'], verbose=True)
qda = m2_QDA(X, y['genres_all'], verbose=True)
qda = m2_QDA(X, y['top_level'], verbose=True)

# In[ ]:

for km in ['k-means++', 'random', 'centroids']:
    print('> Testing method: ', km)
    m3_KMC(X, y['genres'], km, verbose=True)
    m3_KMC(X, y['genres_all'], km, verbose=True)
    m3_KMC(X, y['top_level'], km, verbose=True)

# ### Per Feature/Statistic Testing

# In[ ]:

yc = 'top_level'
cols = ['lda','qda','kmc-km++','kmc-rand','kmc-cent']
warnings.filterwarnings('ignore')

## test each feature
res_feat = pd.DataFrame(columns=cols)
for ft in X.columns.unique(level=0):
    print('> Testing feature: ', ft)
    res_feat.loc[ft, 'lda'] = m1_LDA(X.loc[:,pd.IndexSlice[ft, :, :]], y[yc])
    res_feat.loc[ft, 'qda'] = m2_QDA(X.loc[:,pd.IndexSlice[ft, :, :]], y[yc])
    res_feat.loc[ft, 'kmc-km++'] = m3_KMC(X.loc[:,pd.IndexSlice[ft, :, :]], y[yc], 'k-means++')
    res_feat.loc[ft, 'kmc-rand'] = m3_KMC(X.loc[:,pd.IndexSlice[ft, :, :]], y[yc], 'random')
    res_feat.loc[ft, 'kmc-cent'] = m3_KMC(X.loc[:,pd.IndexSlice[ft, :, :]], y[yc], 'centroids')

## test each statistic
res_stat = pd.DataFrame(columns=cols)
for st in X.columns.unique(level=1):
    print('> Testing statistic: ', st)
    res_stat.loc[st, 'lda'] = m1_LDA(X.loc[:,pd.IndexSlice[:, st, :]], y[yc])
    res_stat.loc[st, 'qda'] = m2_QDA(X.loc[:,pd.IndexSlice[:, st, :]], y[yc])
    res_stat.loc[st, 'kmc-km++'] = m3_KMC(X.loc[:,pd.IndexSlice[:, st, :]], y[yc], 'k-means++')
    res_stat.loc[st, 'kmc-rand'] = m3_KMC(X.loc[:,pd.IndexSlice[:, st, :]], y[yc], 'random')
    res_stat.loc[st, 'kmc-cent'] = m3_KMC(X.loc[:,pd.IndexSlice[:, st, :]], y[yc], 'centroids')

## print results
print('Results by feature:\n', res_feat)
print('Results by statistic:\n', res_stat)

## export results
res_feat.to_csv('res_feat_{}.csv'.format(yc))
res_stat.to_csv('res_stat_{}.csv'.format(yc))

# ### Final Testing

# In[296]:

m1_LDA(X.loc[:,pd.IndexSlice[:, :, :]], y['top_level'], verbose=True)
m1_LDA(X.loc[:,pd.IndexSlice[['chroma_cens','mfcc','spectral_contrast'], :, :]], y['top_level'], verbose=True)

qft = ['mfcc', 'spectral_bandwidth', 'spectral_centroid', 'spectral_contrast', 'spectral_rolloff', 'zcr']
m2_QDA(X.loc[:,pd.IndexSlice[:, ['std'], :]], y['top_level'], verbose=True)
m2_QDA(X.loc[:,pd.IndexSlice[qft, ['std'], :]], y['top_level'], verbose=True)
m2_QDA(X.loc[:,pd.IndexSlice[qft, ['mean','median','std'], :]], y['top_level'], verbose=True)

kft = ['mfcc', 'spectral_bandwidth', 'spectral_centroid', 'spectral_contrast', 'spectral_rolloff']
m3_KMC(X.loc[:,pd.IndexSlice[['mfcc'], ['skew'], :]], y['genres_all'], verbose=True)
m3_KMC(X.loc[:,pd.IndexSlice[['mfcc'], ['mean', 'median', 'skew'], :]], y['genres_all'], verbose=True)
m3_KMC(X.loc[:,pd.IndexSlice[['mfcc'], :, :]], y['genres_all'], verbose=True)

m3_KMC(X.loc[:,pd.IndexSlice[kft, ['skew'], :]], y['genres_all'], 'random', verbose=True)
m3_KMC(X.loc[:,pd.IndexSlice[kft, ['mean', 'median', 'skew'], :]], y['genres_all'], 'random', verbose=True)
m3_KMC(X.loc[:,pd.IndexSlice[kft, :, :]], y['genres_all'], 'random', verbose=True)

print('> Testing complete')


import pyautogui as pag
from collections import namedtuple,Counter
import random

"""
https://asyncfor.com/posts/doc-pyautogui.html
screenWidth, screenHeight = pyautogui.size()
currentMouseX, currentMouseY = pyautogui.position()
pyautogui.moveTo(100, 150)
pyautogui.click()
#  鼠标向下移动10像素
pyautogui.moveRel(None, 10)
pyautogui.doubleClick()
#  用缓动/渐变函数让鼠标2秒后移动到(500,500)位置
#  use tweening/easing function to move mouse over 2 seconds.
pyautogui.moveTo(1800, 500, duration=2, tween=pyautogui.easeInOutQuad)
#  在每次输入之间暂停0.25秒
pyautogui.typewrite('Hello world!', interval=0.25)
pyautogui.press('esc')
pyautogui.keyDown('shift')
pyautogui.press(['left', 'left', 'left', 'left', 'left', 'left'])
pyautogui.keyUp('shift')
pyautogui.hotkey('ctrl', 'c')
"""

#("mouse","click",(10,100)) ,("mouse","move",(10,100)),("key","press","a")
#status 默认为 None
CMD = namedtuple("CMD",["device","action","code","status"],defaults=[None])

#status_device_action_map
sda_map = {"bc":["mouse","click"],
               "kd":["keyboard","keyDown"],
                "None":["mouse","move"]}
#status:target name
pag.FAILSAFE = False
PC_bind = {
    "mouse":{"move":pag.moveTo,"click":pag.click},
    "keyboard":{}
}

Andriod_bind = {}


from api.repository.organization_repository import OrganizationRepository
from api.services.formatter import FormatterService

class OrganizationService:
    @staticmethod
    def get_all_organization_with_total_amount_paid():
        organizations_with_total_amount_paid = []
        organizations = OrganizationRepository.get_all_organizations()

        for organization in organizations:
            amount_paid = OrganizationRepository.get_total_amount_paid_by_organization(organization)
            organizations_with_total_amount_paid.append({
                "company": organization.name,
                "company_type": organization.company_type,
                "amount_paid": amount_paid,
                "amount_paid_formatted": FormatterService.format_monetary_amount(amount_paid)
            })

        return organizations_with_total_amount_paid


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

from tkinter import *

class KitchenTable():
    def __init__(self, root):
        self.tk=Frame(root)
        self.tk.pack(expand=True,fill="both")
        self.tk.configure(bg="white")
        self.order_ready=False
        self.food_placed=False
        # Set custom colors
        heading_bg = "#FF5733"  # Orange
        button_bg = "#4CAF50"    # Green
        button_fg = "white"
        label_fg = "black"
        heading_label = Label(self.tk, text="Kitchen Table", bg=heading_bg, fg="white", font=("Arial", 24))
        heading_label.grid(row=0, column=0, columnspan=4, pady=(10, 20), sticky="ew")

        self.table_data = [
            ["Table", "Food", "Qty", "Call"],
            [1, "", 0, ""],
            [2, "", 0, ""],
            [3, "", 0, ""]
        ]
        self.create_table()
        update_button = Button(
            self.tk, text="Update Table",
            command=self.update_table,
              bg=button_bg,
                fg=button_fg,
                  relief=FLAT)
        update_button.grid(
            row=len(self.table_data),
              column=0,
                columnspan=4,
                  pady=10,
                    sticky="ew")

    def create_table(self):

        self.widgets = []  # Store widgets to be able to update them later
        for i, row in enumerate(self.table_data):
            widgets_row = []
            for j, cell_value in enumerate(row):
                if j == 3 and i != 0:  # For the 4th column and skip the header row
                    button = Button(
                        self.tk, text=cell_value,
                         command=lambda i=i: self.button_clicked(i),
                          bg="#FF5733", fg="white", relief=RAISED)  # Orange button with raised relief
                    button.grid(row=i + 1, column=j, sticky="ew")
                    widgets_row.append(button)
                else:
                    label = Label(self.tk, text=cell_value, relief=RAISED, width=10, fg="black")  # Raised relief
                    label.grid(row=i + 1, column=j, sticky="ew")
                    widgets_row.append(label)
            self.widgets.append(widgets_row)

        # Add the "Food Placed" button at the bottom
        food_placed_button = Button(self.tk, text="Food Placed", command=self.food_placed_button_clicked,
                                    bg="#FF5733", fg="white", relief=RAISED)
        food_placed_button.grid(row=len(self.table_data) + 1, column=3, sticky="ew")

    def food_placed_button_clicked(self):
        print("Food Placed Button clicked.")
        self.food_placed=True

    def update_table(self,):

        # Update the widgets in the table with the new data
        for i, row in enumerate(self.table_data):
            for j, cell_value in enumerate(row):
                self.widgets[i][j].config(text=cell_value)

    def button_clicked(self, row_index):
        print(f"Button in row {row_index} clicked.")
        button = self.widgets[row_index][3]  # Get the button widget in the clicked row
        button.config(bg="#4CAF50")
        self.order_ready=row_index
        print(self.order_ready)

    def update_image(self):
        self.tk.update()

    def destroy(self):
            self.tk.destroy()


def eval(tokens):
    stack = [None]
    opstack = [None]
    for token in tokens:
        pending = None
        if token == '(':
            stack.append(None)
            opstack.append(None)
        elif token == ')':
            pending = stack.pop()
            opstack.pop()
        elif token == '+':
            opstack[-1] = lambda x, y : x + y
        elif token == '*':
            opstack[-1] = lambda x, y : x * y
        else:
            pending = int(token)

        if pending is not None:
            if stack[-1] is None:
                stack[-1] = pending
            else:
                stack[-1] = opstack[-1](stack[-1], pending)

    return stack[-1]

lines = []
total = 0
for line in open('input.txt'):
    line = line.strip()
    lines.append(line)
    tokens = line.replace('(', ' ( ').replace(')', ' ) ').split()
    total += eval(tokens)

print(total)


from math import sqrt
# ref = set((long, lat, val))
parsed_data = {}

def fn(lat, lon, ref):
	ret = [0.0, 0.0]
	d_tot = 0.0
	for data in ref:
		d_lat, d_lon, _, _ = data
		d_tot += 1.0/getDist(lon, lat, d_lon, d_lat)

	for data in ref:
		d_lat, d_lon, air, ground = data
		dist = getDist(lon, lat, d_lon, d_lat)
		ret[0] += (1.0/dist)/d_tot * air
		ret[1] += (1.0/dist)/d_tot * ground

	return ret

def getDist(h_lon, h_lat, t_lon, t_lat):

	h_lon = float(h_lon)
	h_lat = float(h_lat)
	dx = abs(h_lon - t_lon)
	dy = abs(h_lat - t_lat)
	return sqrt(dx*dx + dy*dy)

def parseLoc():
	with open('./Road_Weather_Clean2 (1).csv', 'r') as f:
		for line in f:
			name, lat, lon, date, air, ground = line.strip().split(',')
			if date not in parsed_data:
				parsed_data[date] = []

			parsed_data[date].append((float(lat), float(lon), float(air), float(ground)))

def parseFire():
	g = open("./output.csv", "w")
	g.write("@relation fire\n@attribute lat numeric\n@attribute lon numeric\n@attribute airtemp numeric\n@attribute groundtemp numeric\n@attribute seconds numeric\n@attribute fire {Y, N}\n@data\n")
	with open('./Seattle_Real_Time_Fire_911_Calls.csv', 'r') as f:
		for line in f:
			parts = line.strip().split(",")
			if len(parts) != 8:
				continue
			_, _, date, lat, lon, _, _, _ = parts
			if len(date.split(" ")) != 4 or not lat or not lon:
				continue
			day, time, pm, _ = date.split(" ")
			hr, _, _ = time.split(':')
			hr = int(hr)
			if (hr == 12 and pm == 'AM'):
				hr = 0
			elif (hr != 12 and pm == 'PM'):
				hr += 12
			date = day + " %.2d" % hr

			if date in parsed_data:
				air, ground = fn(lat, lon, parsed_data[date])
				g.write((lat + ',' + lon + ',%.2f,%.2f,%d,Y\n') % (air, ground, hr))

	g.close()

parseLoc()
parseFire()


"""
Test the rendering mechanism to see if inquirer works
"""
from unittest.mock import Mock, create_autospec, patch

import inquirer
from pytest import fixture

from hacenada import render, session

@fixture
def renderer():
    rr = render.InquirerRender()
    return rr

def test_inquirer_type(renderer):
    """
    Do I look up inquirer question type by hacenada typename?
    """
    assert renderer._inquirer_dispatch("description") is inquirer.text

@fixture
def seshie():
    """
    A mock session
    """
    sesh = create_autospec(session.Session)
    sesh.storage.description = "DESCRIPTION"
    return sesh

def test_render(renderer, steppie, seshie):
    """
    Do I render questions to the screen?
    """
    prompt = Mock(return_value="here we go")
    with patch.object(
        render.InquirerRender, "_inquirer_dispatch", autospec=True, return_value=prompt
    ) as m_prompt:
        ret = renderer.render(steppie, seshie)

    m_prompt.return_value.assert_called_once_with("DESCRIPTION : q1\noh noo\n>>")
    assert ret == {"q1": "here we go"}

def test_render_no_description(renderer, steppie, seshie):
    """
    Do I display the right title when there's no description property set?
    """
    seshie.storage.description = None
    seshie.script.preamble = {"name": "SCRIPT NAME"}
    prompt = Mock(return_value="here we go")
    with patch.object(
        render.InquirerRender, "_inquirer_dispatch", autospec=True, return_value=prompt
    ) as m_prompt:
        renderer.render(steppie, seshie)

    m_prompt.return_value.assert_called_once_with("SCRIPT NAME : q1\noh noo\n>>")


from django import forms
from django.contrib.contenttypes.models import ContentType
from django.db import transaction

from .fields import TaxiField, TaxiSingleField
from .models import TermTaxonomy, TermTaxonomyItem

class TaxiModelMixin(forms.ModelForm):
    """
    Mixin used on model forms where a TaxiField is set.
    The mixin is responsible to create and delete
    TermTaxonomyItems for a given instance based on form data.
    """

    taxi_fields = None

    def __init__(self, *args, **kwargs):
        self.taxi_fields = {}
        for field_name, field in self.__class__.base_fields.items():
            if type(field) in [TaxiField, TaxiSingleField]:
                self.taxi_fields[field_name] = field.taxonomy_slug

        # Set initial
        instance = kwargs.get("instance")
        if instance:
            kwargs["initial"] = kwargs.get("initial", {})
            for field in self.taxi_fields:
                kwargs["initial"].update(
                    {
                        field: list(
                            instance.terms.values_list("term_taxonomy__term", flat=True)
                        )
                    }
                )

        super().__init__(*args, **kwargs)

        # Set choices
        for field in self.taxi_fields:
            self.fields[field].choices = self.get_choices(field).values_list(
                "id", "term__name"
            )

    def get_choices(self, field):
        return TermTaxonomy.objects.filter(taxonomy__slug=self.taxi_fields[field])

    def get_existing_term_taxonomy_ids(self, field, instance):
        return list(
            instance.terms.filter(
                term_taxonomy__taxonomy__slug=self.taxi_fields[field]
            ).values_list("term_taxonomy", flat=True)
        )

    def _save_taxi(self):
        instance = self.instance
        content_type = ContentType.objects.get_for_model(instance)
        with transaction.atomic():
            for field, term_taxonomy in self.taxi_fields.items():
                existing = self.get_existing_term_taxonomy_ids(field, instance)
                choices = self.get_choices(field)
                data = self.cleaned_data[field]
                data = [int(data)] if type(data) == str else [int(i) for i in data]
                for choice in choices:
                    if choice.pk in data and choice.pk in existing:
                        # Do nothing, selected and already exists.
                        pass
                    elif choice.pk in data and choice.pk not in existing:
                        # Create the new choice that does not already exist.
                        TermTaxonomyItem(
                            content_type=content_type,
                            object_id=instance.pk,
                            term_taxonomy=choice,
                        ).save()
                    elif choice.pk not in data and choice.pk in existing:
                        # Remove the unselected choice that already exists.
                        TermTaxonomyItem.objects.filter(
                            term_taxonomy=choice,
                            content_type=content_type,
                            object_id=instance.pk,
                        ).delete()
                    elif choice.pk not in data and choice.pk not in existing:
                        # Final case, choice not selected and do not exist.
                        pass

    def _save_m2m_taxi(self):
        self._save_m2m()
        self._save_taxi()

    def save(self, commit=True):
        instance = super().save(commit=commit)
        if commit:
            self._save_taxi()
        else:
            self.save_m2m = self._save_m2m_taxi  # noqa

        return instance


# -*- coding: utf-8 -*-
"""
Created on Fri Nov  4 14:23:45 2022

@author: Audi Aulia
"""
print ("Menentukan bilangan prima.")

def prima():
    num = int(input("Masukan angka : "))
    for i in range(2, num):
        if num % i == 0:
            return False
    return True

x = prima()
print(x)


carte_chance = {
    0:["Amende pour excès de vitesse", -15],
    1:["La banque vous verse un dividende de € 50",50],
    2:["Vous êtes imposé pour les réparations de voirie a raison de : € 40 par house et € 115 par hotel",""],
    3:["Avancez jusqu'à la case Départ",0],
    4:["Payez les frais de scolarité : € 150",-150],
    5:["Rendez-vous Rue de la Paix",0],
    6:["Rendez-vous à l'Avenue Henri-Martin. Si vous passez par Départ recevez € 200",0],
    7:["Faites des réparations dans toutes vos houses : € 25 et € 100 par hôtel",""],
    8:["Avancez au Bd de la Villette. Si vous passez par Départ recevez € 200",0],
    9:["Allez à la gare de Lyon. Si vous passez par Départ recevez € 200",0],
    10:["Votre immeuble et votre prêt rapportent. Vous devez toucher € 150",150],
    11:["Allez en prison. Ne franchissez pas la case Départ. Ne touchez pas € 200",0],
    12:["Reculez de 3 squares",0],
    13:["Amende pour ivresse : € 20",-20],
    14:["Vous avez gagné le price de mots croisés. Recevez € 100",100],
    15:["Vous êtes libéré de prison .Cette carte peut être conservée jusqu'à ce qu'elle soit utilisée ou vendue.",0]
}

carte_caisse_communaute = {

    0:["C'est votre jour anniversaire chaque joueur doit vous donner € 10",""],
    1:["Payer l'hôpital € 100",-100],
    2:["Vous avez gagné le 2nd price de beauté. Recevez € 10",10],
    3:["Erreur de la banque en votre faveur recevez € 200",200],
    4:["Recevez votre intérêt sur l'emprunt à 7% , € 25",25],
    5:["Payez un amende de € 10 ou bien tirez un carte 'CHANCE'",""],
    6:["Retournez a Belleville",0],
    7:["Recevez votre revenu annuel € 100",100],
    8:["Allez en prison .Avancez tout droit en prison .Ne passez pas par la case départ . Ne recevez pas € 200",0],
    9:["Placez-vous sur la case Départ",0],
    10:["Payez la note du médecin € 50",-50],
    11:["Payez votre police d'assurance s'élevant à € 50",-50],
    12:["Les contributions vous remboursent la somme de € 20",20],
    13:["Vous héritez de € 100",100],
    14:["La vente de votre stock vous rapporte € 50",50],
    15:["Vous êtes libéré de prison .Cette carte peut être conservée jusqu'à ce qu'elle soit utilisée ou vendue.",0]
}

squares = {
    0:"Case Départ",            # 0
    1:"Belleville",             # 1
    2:"Caisse de Communauté",   # 2
    3:"Lecourbe",               # 3
    4:"Impôts",                 # 4
    5:"Gare Montparnasse",      # 5
    6:"Vaugirard",              # 6
    7:"Carte Chance",           # 7
    8:"Courcelles",             # 8
    9:"Républiques",            # 9
    10:"Simple Visite",          # 10
    11:"La Villette",            # 11
    12:"Cie électricité",        # 12
    13:"Neuilly",                # 13
    14:"Paradis",                # 14
    15:"Gare de Lyon",           # 15
    16:"Mozart",                 # 16
    17:"Caisse de Communauté",   # 17
    18:"Saint-Michel",           # 18
    19:"Pigalle",                # 19
    20:"Parc Gratuit",           # 20
    21:"Matignon",               # 21
    22:"Carte Chance",           # 22
    23:"Malesherbes",            # 23
    24:"Henri-Martin",           # 24
    25:"Gare du Nord",           # 25
    26:"Saint-Honoré",           # 26
    27:"La Bourse",              # 27
    28:"Cie des Eaux",           # 28
    29:"La Fayette",             # 29
    30:"Allez en Prison",        # 30
    31:"Breteuil",               # 31
    32:"Foch",                   # 32
    33:"Caisse de Communauté",   # 33
    34:"Capucines",              # 34
    35:"Gare Saint-Lazare",      # 35
    36:"Carte Chance",           # 36
    37:"Champs-élysées",         # 37
    38:"Taxe de Luxe",           # 38
    39:"La Paix",                # 39
    40:"Prison",                 # 40
    41:"Les stations",              # 5 + 15 + 25 + 35 (41)
    42:"Les Cies",               # 12 + 28 (42)
    43:"Brun",                   # 1 + 3 (43)
    44:"Bleu clair",             # 6 + 8 + 9 (44)
    45:"Violet",                 # 11 + 13 + 14 (45)
    46:"Orange",                 # 16 + 18 + 19 (46)
    47:"Rouge",                  # 21 + 23 + 24 (47)
    48:"Jaune",                  # 26 + 27 + 29 (48)
    49:"Vert",                   # 31 + 32 + 34 (49)
    50:"Bleu foncé"              # 37 + 39 (50)
}
companies = {
    12 : {
        "name": "Compagnie de distribution d'électricité",
        "price": 150,
        "mortgage":75,
        "color": 42,
        "owner": ""
    },

    28: {
        "name": "Compagnie de distribution des eaux",
        "price": 150,
        "mortgage":75,
        "color": 42,
        "owner": ""
    }
}

stations = {
    5: {
        "name": "Gare Montparnasse",
        "price": 200,
        "loyer": [25,50,100,200],
        "mortgage":100,
        "color": 41,
        "owner": ""
    },

    15: {
        "name": "Gare de Lyon",
        "price": 200,
        "loyer": [25,50,100,200],
        "mortgage":100,
        "color": 41,
        "owner": ""
    },

    25: {
        "name": "Gare du Nord",
        "price": 200,
        "loyer": [25,50,100,200],
        "mortgage":100,
        "color": 41,
        "owner": ""
    },

    35: {
        "name": "Gare Saint-Lazare",
        "price": 200,
        "loyer": [25,50,100,200],
        "mortgage":100,
        "color": 41,
        "owner": ""
    }
}

lots = {
    1: {
        "name": "Boulevard de Belleville",
        "price": 60,
        "loyer": [2,10,30,90,160,250],
        "mortgage":30,
        "house":50,
        "color": 43,
        "owner": ""
    },

    3: {
        "name": "Rue Lecourbe",
        "price": 60,
        "loyer": [4,20,60,180,320,450],
        "mortgage":30,
        "house":50,
        "color": 43,
        "owner": ""
    },

    6: {
        "name": "Rue Vaugirard",
        "price": 100,
        "loyer": [6,30,90,270,400,550],
        "mortgage":50,
        "house":50,
        "color": 44,
        "owner": ""
    },

    8: {
        "name": "Rue de Courcelles",
        "price": 100,
        "loyer": [6,30,90,270,400,550],
        "mortgage":50,
        "house":50,
        "color": 44,
        "owner": ""
    },

    9: {
        "name": "Avenue de la République",
        "price": 120,
        "loyer": [8,40,100,300,450,600],
        "mortgage":60,
        "house":50,
        "color": 44,
        "owner": ""
    },

    11: {
        "name": "Boulevard de la Villette",
        "price": 140,
        "loyer": [10,50,150,450,625,750],
        "mortgage":70,
        "house":100,
        "color": 45,
        "owner": ""
    },

    13: {
        "name": "Avenue de Neuilly",
        "price": 140,
        "loyer": [10,50,150,450,625,750],
        "mortgage":70,
        "house":100,
        "color": 45,
        "owner": ""
    },

    14: {
        "name": "Rue de Paradis",
        "price": 160,
        "loyer": [12,60,180,500,700,900],
        "mortgage":80,
        "house":100,
        "color": 45,
        "owner": ""
    },

    16: {
        "name": "Avenue Mozart",
        "price": 180,
        "loyer": [14,70,200,550,750,950],
        "mortgage":90,
        "house":100,
        "color": 46,
        "owner": ""
    },

    18: {
        "name": "Boulevard St Michel",
        "price": 180,
        "loyer": [14,70,200,550,750,950],
        "mortgage":90,
        "house":100,
        "color": 46,
        "owner": ""
    },

    19: {
        "name": "Place Pigalle",
        "price": 200,
        "loyer": [16,80,220,600,800,1000],
        "mortgage":100,
        "house":100,
        "color": 46,
        "owner": ""
    },

    21: {
        "name": "Avenue Matignon",
        "price": 220,
        "loyer": [18,90,250,700,875,1050],
        "mortgage":110,
        "house":150,
        "color": 47,
        "owner": ""
    },

    23: {
        "name": "Boulevard Malesherbes",
        "price": 220,
        "loyer": [18,90,250,700,875,1050],
        "mortgage":110,
        "house":150,
        "color": 47,
        "owner": ""
    },

    24: {
        "name": "Avenue Henri Martin",
        "price": 240,
        "loyer": [20,100,300,750,925,1100],
        "mortgage":120,
        "house":150,
        "color": 47,
        "owner": ""
    },

    26: {
        "name": "Faubourg St Honoré",
        "price": 260,
        "loyer": [22,110,330,800,975,1150],
        "mortgage":130,
        "house":150,
        "color": 48,
        "owner": ""
    },

    27: {
        "name": "Place de la Bourse",
        "price": 260,
        "loyer": [22,110,330,800,975,1150],
        "mortgage":130,
        "house":150,
        "color": 48,
        "owner": ""
    },

    29: {
        "name": "Rue de la Fayette",
        "price": 280,
        "loyer": [24,120,360,850,1025,1200],
        "mortgage":140,
        "house":150,
        "color": 48,
        "owner": ""
    },

    31: {
        "name": "Avenue de Breteuil",
        "price": 300,
        "loyer": [26,130,390,900,1100,1275],
        "mortgage":150,
        "house":200,
        "color": 49,
        "owner": ""
    },

    32: {
        "name": "Avenue Foch",
        "price": 300,
        "loyer": [26,130,390,900,1100,1275],
        "mortgage":150,
        "house":200,
        "color": 49,
        "owner": ""
    },

    34: {
        "name": "Boulevard des Capucines",
        "price": 320,
        "loyer": [28,150,450,1000,1200],
        "mortgage":160,
        "house":200,
        "color": 49,
        "owner": ""
    },

    37: {
        "name": "Avenue des Champs-Elisées",
        "price": 350,
        "loyer": [35,175,500,1100,1300,1500],
        "mortgage":175,
        "house":200,
        "color": 50,
        "owner": ""
    },

    39: {
        "name": "Rue de la Paix",
        "price": 400,
        "loyer": [50,200,600,1400,1700,2000],
        "mortgage":200,
        "house":200,
        "color": 50,
        "owner": ""
    }
}

# Une compagnie: 4 fois le montant des dés
# Deux compangnies: 10 fois le montant des dés

# name des différentes squares
# @case = ("Case Départ",            # 0
#          "Belleville",             # 1
#          "Caisse de Communauté",   # 2
#          "Lecourbe",               # 3
#          \"Impôts",                 # 4
#          "Gare Montparnasse",      # 5
#          "Vaugirard",              # 6
#          "Carte Chance",           # 7
#          "Courcelles",             # 8
#          "Républiques",            # 9
#          "Simple Visite",          # 10
#          "La Villette",            # 11
#          "Cie électricité",        # 12
#          "Neuilly",                # 13
#          "Paradis",                # 14
#          "Gare de Lyon",           # 15
#          "Mozart",                 # 16
#          "Caisse de Communauté",   # 17
#          "Saint-Michel",           # 18
#          "Pigalle",                # 19
#          "Parc Gratuit",           # 20
#          "Matignon",               # 21
#          "Carte Chance",           # 22
#          "Malesherbes",            # 23
#          "Henri-Martin",           # 24
#          "Gare du Nord",           # 25
#          "Saint-Honoré",           # 26
#          "La Bourse",              # 27
#          "Cie des Eaux",           # 28
#          "La Fayette",             # 29
#          \"Allez en Prison",        # 30
#          "Breteuil",               # 31
#          "Foch",                   # 32
#          "Caisse de Communauté",   # 33
#          "Capucines",              # 34
#          "Gare Saint-Lazare",      # 35
#          "Carte Chance",           # 36
#          "Champs-élysées",         # 37
#          "Taxe de Luxe",           # 38
#          "La Paix",                # 39
#          "Prison",                 # 40
#          "Les stations",              # 5 + 15 + 25 + 35 (41)
#          "Les Cies",               # 12 + 28 (42)
#          "Brun",                   # 1 + 3 (43)
#          "Bleu clair",             # 6 + 8 + 9 (44)
#          "Violet",                 # 11 + 13 + 14 (45)
#          \"Orange",                 # 16 + 18 + 19 (46)
#          "Rouge",                  # 21 + 23 + 24 (47)
#          "Jaune",                  # 26 + 27 + 29 (48)
#          "Vert",                   # 31 + 32 + 34 (49)
#          "Bleu foncé"              # 37 + 39 (50)
#          );

#          Cartes Chances
# Amende pour excès de vitesse : F 1.500
# La banque vous verse un dividende de F 5.000
# Vous êtes imposé pour les réparations de voirie a raison de : F 4.000 par house et F 11.500 par hotel
# Avancez jusqu'à la case "Départ"
# Payez les frais de scolarité : F 15.000
# Rendez-vous Rue de la Paix (nu = F 5.000 Hôtel = F 200.000)
# Rendez-vous à l'Avenue Henri-Martin (nu = F 2.000 Hôtel = F 110.000). Si vous passez par "Départ" recevez F 20.000
# Faites des réparations dans toutes vos houses : F 2.500 et F 10.000 par hôtel
# Avancez au Bd de la Villette (nu = F 1.000 Hôtel = F 75.000). Si vous passez par "Départ" recevez F 20.000
# Allez à la gare de Lyon (1 gare = F 2.500;4 stations = F 20.000). Si vous passez par "Départ" recevez F 20.000
# Votre immeuble et votre prêt rapportent. Vous devez toucher F 15.000
# Allez en prison. Ne franchissez pas la case "Départ". Ne touchez pas F 20.000
# Reculez de 3 squares
# Amende pour ivresse : F 2.000
# Vous avez gagné le price de mots croisés. Recevez F 10.000
# Vous êtes libéré de prison .Cette carte peut être conservée jusqu'à ce qu'elle soit utilisée ou vendue.

# Cartes Caisses de Communauté

# C'est votre jour anniversaire chaque joueur doit vous donner F 1.000
# Payer l'hôpital F 10.000
# Vous avez gagné le 2nd price de beauté. Recevez F 1.000
# Erreur de la banque en votre faveur recevez F 20.000
# Recevez votre intérêt sur l'emprunt à 7% , F 2.500
# Payez un amende de F 1.000 ou bien tirez un carte "CHANCE"
# Retournez a Belleville(nu = F 200 Hôtel = F 25.000)
# Recevez votre revenu annuel F 10.000
# Allez en prison .Avancez tout droit en prison .Ne passez pas par la case départ . Ne recevez pas F 20.000
# Placez-vous sur la case " Départ"
# Payez la note du médecin F 5.000
# Payez votre police d'assurance s'élevant à F 5.000
# Les contributions vous remboursent la somme de F 2.000
# Vous héritez de F 10.000
# La vente de votre stock vous rapporte F 5.000
# Vous êtes libéré de prison .Cette carte peut être conservée jusqu'à ce qu'elle soit utilisée ou vendue.
# Boulevard de Belleville
# Terrain nu : 2€
# 1 houses : 10€
# 2 houses : 30€
# 3 houses : 90€
# 4 houses : 160€
# hotel : 250€

# Rue Lecourbe
# Terrain nu : 4€
# 1 houses : 20€
# 2 houses : 60€
# 3 houses : 180€
# 4 houses : 320€
# hotel : 450€

# Rue Vaugirard
# Terrain nu : 6€
# 1 houses : 30€
# 2 houses : 90€
# 3 houses : 270€
# 4 houses : 400€
# hotel : 550€

# Avenue de la République
# Terrain nu : 8€
# 1 houses : 40€
# 2 houses : 100€
# 3 houses : 300€
# 4 houses : 450€
# hotel : 600€

# Rue de Courcelles
# Terrain nu : 6€
# 1 houses : 30€
# 2 houses : 90€
# 3 houses : 270€
# 4 houses : 400€
# hotel : 550€

# Avenue de Neuilly
# Terrain nu : 10€
# 1 houses : 50€
# 2 houses : 150€
# 3 houses : 450€
# 4 houses : 625€
# hotel : 750€

# Rue de Paradis
# Terrain nu : 12€
# 1 houses : 60€
# 2 houses : 180€
# 3 houses : 500€
# 4 houses : 700€
# hotel : 900€

# Boulevard de la Villette
# Terrain nu : 10€
# 1 houses : 50€
# 2 houses : 150€
# 3 houses : 450€
# 4 houses : 625€
# hotel : 750€

# Avenue Mozart
# Terrain nu : 14€
# 1 houses : 70€
# 2 houses : 200€
# 3 houses : 550€
# 4 houses : 760€
# hotel : 950€

# Place Pigalle
# Terrain nu : 16€
# 1 houses : 80€
# 2 houses : 220€
# 3 houses : 600€
# 4 houses : 800€
# hotel : 1000€

# Boulevard St Michel
# Terrain nu : 14€
# 1 houses : 70€
# 2 houses : 200€
# 3 houses : 550€
# 4 houses : 750€
# hotel : 950€

# Boulevard Malesherbes
# Terrain nu : 18€
# 1 houses : 90€
# 2 houses : 2500€
# 3 houses : 700€
# 4 houses : 875€
# hotel : 1050€

# Avenue Henri Martin
# Terrain nu : 20€
# 1 houses : 100€
# 2 houses : 300€
# 3 houses : 750€
# 4 houses : 925€
# hotel : 1100€

# Avenue Matignon
# Terrain nu : 18€
# 1 houses : 90€
# 2 houses : 250€
# 3 houses : 700€
# 4 houses : 875€
# hotel : 1050€

# Place de la Bourse
# Terrain nu : 22€
# 1 houses : 110€
# 2 houses : 330€
# 3 houses : 800€
# 4 houses : 975€
# hotel : 1150€

# Faubourg St Honoré
# Terrain nu : 22€
# 1 houses : 110€
# 2 houses : 330€
# 3 houses : 800€
# 4 houses : 975€
# hotel : 1150€

# Rue de la Fayette
# Terrain nu : 24€
# 1 houses : 120€
# 2 houses : 360€
# 3 houses : 850€
# 4 houses : 1025€
# hotel : 1200€

# Avenue Foch
# Terrain nu : 26€
# 1 houses : 130€
# 2 houses : 390€
# 3 houses : 900€
# 4 houses : 1100€
# hotel : 250€

# Avenue de Breteuil
# Terrain nu : 26€
# 1 houses : 130€
# 2 houses : 390€
# 3 houses : 900€
# 4 houses : 1100€
# hotel : 1275€

# Boulevard des Capucines
# Terrain nu : 28€
# 1 houses : 150€
# 2 houses : 450€
# 3 houses : 1000€
# 4 houses : 1200€
# hotel : 1400€

# Avenue des Champs-Elisées
# Terrain nu : 35€
# 1 houses : 175€
# 2 houses : 500€
# 3 houses : 1100€
# 4 houses : 1300€
# hotel : 1500€

# Rue de la Paix
# Terrain nu : 50€
# 1 houses : 200€
# 2 houses : 600€
# 3 houses : 1400€
# 4 houses : 1700€
# hotel : 2000€

# stations
# 1 gare : 25€
# 2 gare : 50€
# 3 gare : 100€
# 4 gare : 200€

# companies distribution des eaux et d'électricité
# Une compagnie: 4 fois le montant des dés
# Deux compangnies: 10 fois le montant des dés


import pygame
import Config
import tile_map
import light_handling

win = pygame.display.set_mode(Config.WINDOW_SIZE)
clock = pygame.time.Clock()
map = tile_map.Tile_map()
light = light_handling.light_handling(map.walls, map.points)

flag = True
while flag:
    clock.tick(Config.FPS)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            flag = False
    mouse_pos = pygame.mouse.get_pos()
    mouse_pressed = pygame.mouse.get_pressed()
    map.update_variables(mouse_pos, mouse_pressed, light)
    light.update_variables(mouse_pos, mouse_pressed)

    win.fill((0,0,0))
    light.draw(win)
    map.draw(win)

    pygame.display.update()


import sys
from collections import deque

n, w, L = map(int, input().split())
weight = deque(map(int, sys.stdin.readline().split()))      # 트럭 무게 리스트 (=> 대기)
bridge = deque()                                            # 다리 위
for i in range(w-1):                                        # w-1만큼 0으로 채우고
    bridge.append(0)
bridge.append(weight[0])                                    # 다리 제일 마지막에 첫번째 트럭 올리기
weight.popleft()                                            # 올렸으니까 popleft, 시간은 1
time = 1

while True:
    bridge.popleft()
    if weight and sum(bridge) + weight[0] <= L:
        # 대기 중인 트럭이 있고 현재 다리 위 트럭들의 무게 합 + 다음 무게 < L이면
        bridge.append(weight.popleft())     # 대기 첫번째를 다리 위로 올리기
    else:
        bridge.append(0)                    # 최대하중 넘어가면 0을 추가해서 다리 위 트럭이 이동만 하도록
    time += 1                               # 한 번 이동할 때마다(popleft - append) 시간 + 1

    if not weight and sum(bridge) == 0:     # 만약 대기 중인 트럭이 없고 다리 위에도 모두 0이면 다 지나간 것
        break

print(time)

###########################
# wait = deque()
# truck_sum = 0
# time = 0

# for i in weight:
#     wait.append((i, w))

# # print(wait)

# while bridge or wait:
#     # if len(bridge) < w and wait:
#     if wait:
#         truck_wgt, bri_time = wait.popleft()
#         if len(bridge) < w and truck_sum + truck_wgt <= L:
#             bridge.append((truck_wgt, bri_time))
#             truck_sum += truck_wgt
#             bri_time -= 1

#     if bri_time == 0:
#         bridge.popleft()
#         truck_sum - truck_wgt

#     time += 1

# print(time)


import serial
import time
import numpy as np
class DummyHead():

    def __init__(self, port):
        """Will work in deg in this class"""
        self.ino = serial.Serial('/dev/cu.usbmodem'+str(port), 115200, timeout=1)
        time.sleep(2)
        self.theta = 0

        #need big range here
        self.max_left = 30
        self.max_right = -30

        #Starting moving left
        self.left = True
        self.right = False

    def look_around(self):
        """Move the dummy hehad so it looks around randomly"""

        # go back and forth
        if self.left:
            self.theta += 1

            if self.theta >= self.max_left:
                self.left = False
                self.right = True

        elif self.right:
            self.theta -= 1

            if self.theta <= self.max_right: #past -90 deg
                self.left = True
                self.right = False

        # self.theta = 20
        self.move(self.theta)

    def get_rotation(self):
        return np.deg2rad(self.theta)

    def close(self):
        self.ino.close()

    def move(self, theta):
        """Moves dummy head to location"""

        q1 = theta
        q2 = 0

        msg = self.formatAngle(q1,q2)
        # print(msg)
        self.ino.write(msg)

    def formatAngle(self, q1,q2):
        q1, q2 = self.calibrate(q1, q2)
        data =  str(q1) + "," + str(q2) + '\n'
        data =  str(q1) + "," + str(q2) + '\n'
        return data.encode()

    def calibrate(self, q1_angle, q2_angle):
        #make this so
        q1_offset = 90 - 30
        q2_offset = 0

        # q1_angle *= -1
        return q1_angle + q1_offset, q2_angle + q2_offset
    def read(self):
        data = self.ino.readline()
        if data:
            data = data.decode('ascii')
            data = data.strip('\n')
            data = data.strip('\r')
            print(data)

# #Example Usage
# head = DummyHead(14141)
# angle = 0
# while True:
#     time.sleep(0.5)
#     head.move(90)
#     # head.move(90)
#     # angle += np.deg2rad(1)#hhead has 1 deg of res
#     head.read()
# head.close()


# -*- coding: utf-8 -*-
"""
Created on Mon Jan 28 20:19:55 2019

@author: mjkiqce3
"""
import numpy as np
import multiprocessing
from multiprocessing import Pool
def computeerr(n,regressor,cc,inputtest):

    for i in range(n): # We can parallelise here
        datause=cc[:,:,i]
        X=datause[:,0:10]
        y=datause[:,-1]
        y=np.reshape(y,(600,1))
        print ('Now in data set :', i)
        n_queries = 10
        for idx in range(n_queries): # We cant parallelise here
            query_idx, query_instance = regressor.query(X)
            regressor.teach(X[query_idx].reshape(1, -1), y[query_idx].reshape(1, -1))
    y_pred_final= regressor.predict(inputtest)
    return y_pred_final,regressor

if __name__ == "__main__":
    number_of_realisations = range(100)
    p = Pool(multiprocessing.cpu_count())
    p.map(computeerr,number_of_realisations)


from django import forms
from .models import *

class StockCreateForm(forms.ModelForm):
	class Meta:
		model=Stock
		fields=['category','item_name','quantity']
	#prevent saving form with blank details
	def clean_category(self):
		category=self.cleaned_data.get('category')
		if not category:
			raise forms.ValidationError('This field is required')

		for instance in Stock.objects.all():
			if instance.category==category:
				raise forms.ValidationError(category+' is already created')
		return category

	def clean_item_name(self):
		item_name=self.cleaned_data.get('item_name')
		if not item_name:
			raise forms.ValidationError('This field is required')
		return item_name

class StockSearchForm(forms.ModelForm):
	export_to_CSV = forms.BooleanField(required=False)
	class Meta:
		model = Stock
		fields = ['category', 'item_name']

class StockUpdateForm(forms.ModelForm):
	class Meta:
		model = Stock
		fields = ['category', 'item_name', 'quantity']

class IssueForm(forms.ModelForm):
	class Meta:
		model = Stock
		fields = ['issue_quantity', 'issue_to']

class ReceiveForm(forms.ModelForm):
	class Meta:
		model = Stock
		fields = ['receive_quantity', 'receive_by']

class ReorderLevelForm(forms.ModelForm):
	class Meta:
		model = Stock
		fields = ['reorder_level']

class StockHistorySearchForm(forms.ModelForm):
	export_to_CSV = forms.BooleanField(required=False)
	start_date = forms.DateTimeField(required=False)
	end_date = forms.DateTimeField(required=False)
	class Meta:
		model = StockHistory
		fields = ['category', 'item_name', 'start_date', 'end_date']

class CategorysForm(forms.ModelForm):
	class Meta:
		model=Category
		fields=['name']

class CustomerDetailsForm(forms.ModelForm):
	class Meta:
		model=CustomerDetails
		fields=['customer_name','national_id','email','phone_number','home_address']
	#preventing null and duplicate entries
	def clean_customer_name(self):
		customer_name=self.cleaned_data.get('customer_name')
		if not customer_name:
			raise forms.ValidationError('Customers name is required')
		return customer_name

	def clean_national_id(self):
		national_id=self.cleaned_data.get('national_id')
		if not national_id:
			raise forms.ValidationError("Customer's National ID is required")
		for instance in CustomerDetails.objects.all():
			if instance.national_id==national_id:
				raise forms.ValidationError('Customer with national ID '+national_id+' already exists')
		return national_id

	def clean_email(self):
		email=self.cleaned_data.get('email')
		if not email:
			raise forms.ValidationError('This field is required')
		for instance in CustomerDetails.objects.all():
			if instance.email==email:
				raise forms.ValidationError('A customer with this email address already exists')
		return email

	def clean_phone_number(self):
		phone_number=self.cleaned_data.get('phone_number')
		if not phone_number:
			raise forms.ValidationError('Customers name is required')

		for instance in CustomerDetails.objects.all():
			if instance.phone_number==phone_number:
				raise forms.ValidationError('A customer with this phone number already exists')
		return phone_number

class CustomerSearchForm(forms.ModelForm):
	export_to_CSV=forms.BooleanField(required=False)
	class Meta:
		model=CustomerDetails
		fields=['customer_name','national_id']

class CustomerUpdateForm(forms.ModelForm):
	class Meta:
		model=CustomerDetails
		fields=['customer_name','national_id','email','phone_number','home_address']


from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.api import urlfetch
from django.utils import simplejson as json

base = 'https://github.com/login/oauth/access_token'
client_id = '?client_id='
redirect_url = '&redirect_uri=https://githubanywhere.appspot.com/callback.html'
client_secret = '&client_secret='

class MainHandler(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write('Hello world!')

class APIv0LoginOauthAccessTokenHandler(webapp.RequestHandler):
  def post(self):
    self.response.headers['Content-Type'] = 'text/plain'
#    self.response.out.write('APIv0UserFollowHandler\n')
    user = GetUserFromPath(self.request.path)
    code = self.request.get('code')
    url = base + client_id + redirect_url + client_secret + '&code=' + code
    result = urlfetch.fetch(url, None, 'POST')
    self.response.out.write(result.content)

class APIv0Handler(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'application/json'
    # self.response.out.write('APIv0Handler\n')
    url = 'https://github.com/api/v2/json' + self.request.path
    access_token = self.request.get('access_token')
    if access_token:
      url += '?access_token=' + access_token
    result = urlfetch.fetch(url, None, 'GET')
    self.response.out.write(result.content)
  def post(self):
    self.response.headers['Content-Type'] = 'application/json'
    # self.response.out.write('APIv0UserFollowHandler\n')
    url = 'https://github.com/api/v2/json' + self.request.path
    access_token = self.request.get('access_token')
    if access_token:
      url += '?access_token=' + access_token
    result = urlfetch.fetch(url, None, 'POST')
    self.response.out.write(result.content)

def GetUserFromPath(path, element = 3):
  return path.split('/')[element]

def main():
  application = webapp.WSGIApplication([
      ('/', MainHandler),
      ('/login/oauth/access_token', APIv0LoginOauthAccessTokenHandler),
      ('/.*', APIv0Handler),
    ],
    debug=True)
  util.run_wsgi_app(application)

if __name__ == '__main__':
  main()


from __future__ import print_function
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sys

dropOutColumn = ['MakeId', 'Url', 'FrontImagePath', 'PhotoCount', 'Price', 'Km', 'ModelName', 'VersionName', 'AdditionalFuel',
                 'VideoCount', 'OfferStartDate', 'OfferEndDate', 'LastUpdatedOn', 'AreaName', 'CityId', 'StateName',
                 'CertifiedLogoUrl', 'NoOfOwners', 'Emi', 'EmiFormatted', 'AbsureWarranty', 'AbsureScore', 'FinanceUrl',
                 'MakeMapping', 'RootMapping', 'ApiFlag', 'MaskingNumber', 'SellerContact', 'HostUrl', 'OriginalImgPath',
                 'CertificationId', 'InspectionText', 'HasWarranty', 'DealerQuickBloxId', 'NearbyCityText', 'NBCityStripId',
                 'DeliveryText', 'DeliveryCity', 'IsNearbyCityListing', 'Responses', 'IsEligibleForFinance', 'ResponsesText',
                 'MfgDate', 'ValuationUrl', 'CertificationScore', 'SellerNote', 'SellerName', 'IsHotDeal', 'MakeName', 'MakeMonth', 'InquiryId',
                 'RootId', 'ModelId', 'VersionId', 'MaskingName', 'SubSegmentID', 'VersionSubSegmentID', 'IsPremium', 'IsPremiumPackage',
                 'FinanceUrlText', 'SortScore','Seller','Fuel','GearBox','BodyStyleId','RootName']

def clean_trainig_data(file_path='raw_data.csv'):

    raw_df = pd.read_csv(file_path)

    # drop useless column
    raw_df.drop(dropOutColumn, axis=1, inplace=True)

    # after drop column
    raw_df.to_csv("useful_data.csv")

    raw_df.drop(['ProfileId'], axis=1, inplace=True)
    print(raw_df.head)
    raw_df = dummy(raw_df)

    # write to CSV
    raw_df.to_csv("refined_data.csv",index=False)
    # return raw_df

def dummy(raw_df):
	# colors
    raw_df['enc_color_silver'] = pd.get_dummies(raw_df.Color).Silver
    raw_df['enc_color_white'] = pd.get_dummies(raw_df.Color).White
    raw_df['enc_color_grey'] = pd.get_dummies(raw_df.Color).Grey
    raw_df['enc_color_gold'] = pd.get_dummies(raw_df.Color).Gold
    raw_df['enc_color_black'] = pd.get_dummies(raw_df.Color).Black
    raw_df['enc_color_blue'] = pd.get_dummies(raw_df.Color).Blue
    def encode_other_color(x):
        return 0 if (x == 'White' or x == 'Silver' or x == 'Grey' or x == 'Gold' or x == 'Black' or x == 'Blue') else 1
    raw_df['enc_color_other'] = raw_df.Color.apply(encode_other_color)

    raw_df.drop(['Color'],axis=1,inplace=True)
    raw_df = pd.get_dummies(raw_df)
    return raw_df

clean_trainig_data();


from __future__ import division
import numpy
import matplotlib.cm as cm
import matplotlib.pyplot as plt
#import imp
import os,sys
import numpy as np
#importlibutil

#from scipy.optimize import minimize
from scipy.optimize import basinhopping

import random
import math

micron=1e-6
sys.path.append("/opt/lumerical/v212/api/python")
import lumapi
#lumapi=imp.load_source("lumapi", "C:\\Program Files\\Lumerical\\v212\\api\\python\\lumapi.py")
base_file = "base_rotator.fsp"

#--- COST FUNCTION ------------------------------------------------------------+

# function we are attempting to optimize (minimize)
def func1(x):
    if os.path.exists(base_file):
        with lumapi.FDTD(filename=base_file, hide='TRUE') as fdtd: #hide='TRUE'
            xmax=x[0]*micron
            ymin_bot=x[1]*micron
            w_bot=x[2]*micron

            ymin_top=-x[3]*micron
            ymax_top=x[3]*micron

            print('xmax:', x[0], ', ymin_bot:', x[1], ', w_bot:', x[2], ', ymin_top:', -x[3])
            fdtd.switchtolayout()

            fdtd.select("Bottom")
            Vbot=fdtd.get("vertices")
            Vbot[0, 0]=xmax
            Vbot[0, 1]=ymin_bot
            Vbot[1, 0]=xmax
            Vbot[1, 1]=ymin_bot+w_bot
            fdtd.set("vertices", Vbot)

            fdtd.select("Top")
            Vtop=fdtd.get("vertices")
            Vtop[0, 0]=xmax
            Vtop[0, 1]=ymin_top
            Vtop[1, 0]=xmax
            Vtop[1, 1]=ymax_top
            fdtd.set("vertices", Vtop)

            fdtd.select("FDTD")
            fdtd.set("x max", xmax-0.5e-6)

            fdtd.select("DFTmonitor_output")
            fdtd.set("x", xmax-0.6e-6)
            fdtd.set("y min", ymin_bot-0.2e-6)
            fdtd.set("y max", ymin_bot+w_bot+0.2e-6)

            fdtd.save()
            fdtd.run()

            bot_monitor=fdtd.getresult("monitor_bottom", "E")
            E_abs=abs(bot_monitor["E"])
            P=E_abs**2

            i1,i2,i3,i4,i5=np.shape(P)

            line_pow=P[i1-5, :, 0, 0, 1] #P[xindex, yindex all, 0, 0, Y polarization]
            p_target=np.max(line_pow)
            print('P_TE:', p_target)
    else:
        print("base file doesn't exist...")
    return -p_target

#--- RUN ----------------------------------------------------------------------+
initial=[50.39, 0.91, 0.65, 0.73]               # initial starting location [x1,x2...]
bounds=[(45, 55), (0.8, 1), (0.55, 0.75), (0.6,0.9)]  # input bounds [(x1_min,x1_max),(x2_min,x2_max)...]
res=basinhopping(func=func1, x0=initial, niter=5, T=1.0, stepsize=0.5, minimizer_kwargs={'method': 'L-BFGS-B', 'bounds': bounds}, take_step=None, accept_test=None, callback=None, interval=50, disp=False, niter_success=3, seed=None, target_accept_rate=0.5, stepwise_factor=0.9)
#minimize(fun=func1, x0=initial, method='L-BFGS-B', bounds=bounds, options={'eps': 1e-01, 'maxiter': 5})
#initial_optimized=[50.39, 0.91, 0.65, 0.73]
#res=func1(initial_optimized) #18.9%
print(res)


import asyncio
import logging
import signal
import session

log = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG)

class MyClientSession(session.ClientSession):

    async def on_connected(self):
        self.update_sock.subscribe('test.topic')
        self.client_state = session.ClientSessionState.SUBSCRIBED

        self.chat_task = asyncio.Task(self.r())
        asyncio.ensure_future(self.chat_task)

    async def on_stopped(self):
        if not self.chat_task.cancelled():
            self.chat_task.cancel()

    async def r(self):
        count = 0
        while True:
            count += 1
            # print('Sending command ...')
            await asyncio.sleep(1)
            try:
                reply = await self.cmd(f'test_cmd {count}')
            except TimeoutError:
                log.warning(f"Timeout waiting for cmd.")
            except:
                log.exception('', exc_info=True)
            # if (count % 1000) == 0:
            print(f'cmd count {count}')

c = MyClientSession()

c.install()
c.start()

async def update(msg):
    if (msg % 100000) == 0:
        print(f'update: {msg}')

c.register('test.topic', update)

l = asyncio.get_event_loop()

# async def main():
#     results = await asyncio.gather(
#         r(), c.run(), return_exceptions=True)
#     for e in results:
#         if isinstance(e, Exception) and not isinstance(e, asyncio.CancelledError):
#             logging.error("Exception thrown during shutdown", exc_info=(type(e), e, e.__traceback__))

def stop(msg):
    log.debug(msg)
    tasks = asyncio.Task.all_tasks()
    for task in tasks:
        task.cancel()

l.add_signal_handler(signal.SIGINT, lambda msg: c.exit(), "Halting on SIGINT")

try:
    l.run_until_complete(c.run())
except asyncio.CancelledError:
    log.debug('CancelledError')
finally:
    l.close()


from setuptools import setup, find_packages

with open('README.rst', encoding='utf-8') as f:
    long_description = f.read()

setup(
    name='mycroft-ekylibre-utils',
    version='0.9',
    packages=find_packages(),
    url='http://github.com/ekylibre',
    author='Ekylibre',
    author_email='rdechazelles@ekylibre.com',
    description='Ekylibre set of tools for MycroftAI skills',
    long_description=long_description,
    long_description_content_type='text/x-rst',
    install_requires=["requests", 'urllib3'],
    include_package_data=True,
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: Apache Software License",
        "Operating System :: OS Independent",
    ],
)


import json
import re

def is_empty_line(line):
    pattern = r'^\s*$'  # 匹配只包含空白字符的行
    return re.match(pattern, line) is not None

def is_digit_line(line):
    pattern = r'^\s*\d+\s*$'  # 匹配只包含空白字符的行
    return re.match(pattern, line) is not None

if __name__ == '__main__':
    items = []
    with open('./openssl_tls_error', 'r') as f:
        lines = f.readlines()
        i = 0
        while i < len(lines):
            line = lines[i]
            if is_empty_line(line):
                i += 1
                continue
            if is_digit_line(line):
                item = {
                    'errno': line.strip(),
                    'title': lines[i + 2].strip(),
                    'description': lines[i + 4].strip(),
                    'icon': 'icons/tls.png'
                }
                i += 5
                items.append(item)
            else:
                i += 1

    with open('../openssl_tls_errno.json', 'w', encoding='utf-8') as out:
        json.dump(items, out, ensure_ascii=False, indent=4)


T = int(input())
lengths = []
strings = []
charCounts = {'_':0}

for i in range(65,91):
	#print(chr(i))
	charCounts[str(chr(i))] = 0

for i in range(T):
	lengths.append(int(input()))
	strings.append(input())

for each in strings:
	unhappy = False
	if('_' in each):
		for i in range(len(each)):
			charCounts[each[i]] += 1
		for key in charCounts:
			if key != '_':
				if(charCounts[key] == 1):
					print("NO")
					unhappy = True
					break
		if(not unhappy):
			print("YES")
		for key in charCounts:
			charCounts[key] = 0
	else:
		for i in range(len(each)):
			if(len(each) == 1):
				unhappy = True
				print("NO")
				break
			elif(i==0):
				if(each[i] != each[i+1]):
					unhappy = True
					print("NO")
					break
			elif(i==len(each)-1):
				if(each[i] != each[i-1]):
					unhappy = True
					print("NO")
					break
			if(not ((each[i-1] == each[i]) or (each[i] == each[i+1]))):
				unhappy = True
				print("NO")
				break
		if(not unhappy):
			print("YES")

#print(charCounts)
#print(lengths)
#print(strings)


from flask import Flask;from flask_ipban import IpBan;from flask_limiter import Limiter;from flask_limiter.util import get_remote_address
from blueprint.main import main
from socket import gethostname
from os import getcwd, path
from yaml import safe_load
import logging, secrets

def loadConfig():
    PATH = (getcwd()+'/config.yaml')
    if path.isfile(PATH):
        with open(PATH,'r+') as config:
            return safe_load(config)
    else:
        print('[err] config.yaml not found!')
        return None
def GenerateRandomToken(length=30):
     return secrets.token_urlsafe(length)

config = loadConfig()
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['HOST_NAME'] = config['HOST_NAME']
app.config['SESSION_COOKIE_DOMAIN'] = False
app.secret_key = GenerateRandomToken()
app.register_blueprint(main)

logging.basicConfig(filename='logs.log',
                    level=logging.DEBUG,
                    format=f'%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s')

ip_ban = IpBan(ban_seconds=(config['IpBan']))
ip_ban.init_app(app)

limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=config['default_limits']
)

if __name__ == '__main__':
    if 'liveconsole' not in gethostname():
        app.run(debug=True)