from datetime import datetime, timedelta, date
from mylogger import mylogger,nulLogger
from agileTools import gen_periodno, gen_periodno_date,yroffset
from sqliteDB import sqliteDB
import sys
import calendar
import os

empty_rate=-999.99

class OctopusAgileDB:
#filepaths
    database    = None
#sqlite database object
    dbobject    = None
# logging
    log         = None
#chargebands
    chargebands = {
        "default" : {
            "rate"  : empty_rate
        },
        "good" :  {
            "rate"  : 0.00
        },
        "average" :  {
            "rate"  : 12.0
        },
        "high" :  {
            "rate"  : 18.0
        },
        "extreme" :  {
            "rate"  : 25.0
        }
    }

#############################################################################
#  __init__ initialise an agile DB object
##############################################################################
    def __init__(self, theConfig, theLogger=None,):
        # initialise the logfile
        if theLogger == None:
            theLogger = nulLogger()

        self.log = theLogger

        self.log.debug("STARTED OctopusAgileDB __init__")

        self.log.debug("STARTED process_config_file: filepaths")

        # Get the database we are using from the configuration file
        self.database   = theConfig.read_value('filepaths','database_file')

        if self.database == None :
            self.log.error("no database file path registered")
        else:
            self.dbobject = sqliteDB(self.database, theLogger)

        self.log.debug("STARTED process_config_file: chargebands")

        # Look at extreme - if not present use defaults
        rate = theConfig.read_value('chargebands','extreme_rate')
        if rate != None: self.chargebands["extreme"]["rate"] = rate

        # Look at high - if not present use defaults
        rate = theConfig.read_value('chargebands','high_rate')
        if rate != None: self.chargebands["high"]["rate"] = rate

        # Look at average - if not present use defaults
        rate = theConfig.read_value('chargebands','average_rate')
        if rate != None: self.chargebands["average"]["rate"] = rate

        # Look at good - if not present use defaults
        rate = theConfig.read_value('chargebands','good_rate')
        if rate != None: self.chargebands["good"]["rate"] = rate

        self.log.debug("FINISHED OctopusAgileDB __init__")

#############################################################################
#  initialise_agile_db - create a new database  run this once
##############################################################################
    def initialise_agile_db(self):

        self.log.debug("STARTED initialise_agile_db ")
        result = False
        data = False
        month_rollup = False
        day_rollup = False

        if self.dbobject.db_ready() == True:
            if self.dbobject.db_connect() == True:

                # create the agile_data table containing forward costs and back usage
                self.log.debug("creating agile_data table")
                sqlite_query = 'CREATE TABLE agile_data (periodno INTEGER PRIMARY KEY, year INTEGER, month INTEGER, day INTEGER, hour INTEGER, minute INTEGER, cost REAL, usage REAL, CHECK (year >= 2020 AND month <= 12 AND day <= 31 AND hour < 24 AND minute < 60))'
                if self.dbobject.db_query(sqlite_query) == True:
                    data = True
                    self.log.debug("Created agile_data table")

                # create a rollup table with the results by day averaged
                self.log.debug("creating day_rollup table")
                sqlite_query = 'CREATE TABLE agile_rollup_day (dayno INTEGER PRIMARY KEY, year INTEGER, month INTEGER, day INTEGER, cost REAL, usage REAL, unit REAL, CHECK (year >= 2020 AND month <= 12 AND day <= 31))'
                if self.dbobject.db_query(sqlite_query) == True:
                    rollup = True
                    self.log.debug("Created day_rollup table")

                # create a rollup table with the results by month averaged
                self.log.debug("creating month rollup table")
                sqlite_query = 'CREATE TABLE agile_rollup_month (monthno INTEGER PRIMARY KEY, year INTEGER, month INTEGER,  cost REAL, usage REAL, unit REAL, CHECK (year >= 2020 AND month <= 12 ))'
                if self.dbobject.db_query(sqlite_query) == True:
                    rollup = True
                    self.log.debug("Created day_rollup table")

                if data and day_rollup and month_rollup:
                    result = True

                self.dbobject.db_disconnect()
        self.log.debug("FINISHED initialise_agile_db ")
        return result

##############################################################################
#  connect to the database
###############################################################################
    def connect_agile_db(self):
        self.log.debug("STARTED connect_agile_db ")
        result = self.dbobject.db_connect()
        self.log.debug("FINISHED connect_agile_db  ")
        return result

##############################################################################
#  disconnect from the database
###############################################################################
    def disconnect_agile_db(self):
        self.log.debug("STARTED disconnect_agile_db ")
        result = self.dbobject.db_disconnect()
        self.log.debug("FINISHED disconnect_agile_db  ")
        return result

##############################################################################
#  get_db_first_missing_usage - find the first period missing usage data
###############################################################################
    def get_db_first_missing_usage(self):
        result = None
        periodno = -1
        self.log.debug("STARTED get_db_first_missing_usage ")

        if self.dbobject.db_ready() == True:
            if self.dbobject.db_connect() == True:
                # Query the database for the lowest periodno where usgae value is empty_rate
                sqlite_select_query = f"SELECT periodno FROM agile_data WHERE usage = {empty_rate} ORDER BY periodno LIMIT 1"
                if self.dbobject.db_query(sqlite_select_query) == True:

                    # There can be only 1 row - we have a LIMIT1 on the result of the query
                    got_row = False
                    for row in self.dbobject.db_queryresults():
                         got_row = True
                         periodno = row[0]

                    if got_row != True:
                        self.log.debug(f"Database usage data missing from {periodno}")
                    else:
                        self.log.debug("Database usage_data is up to date.")

                self.dbobject.db_disconnect()
            else:
                self.log.error(f"Failed to query agile_data ")

        if periodno != -1:
            result = periodno

        self.log.debug("FINISHED get_db_first_missing_usage ")
        return result

##############################################################################
#   get_db_first_missing_period - find the first period missing
##############################################################################
    def get_db_first_missing_period(self):
        self.log.debug("STARTED get_db_first_missing_period")
        result = None
        periodno = -1
        if self.dbobject.db_ready() == True:

            if self.dbobject.db_connect() == True:

                sqlite_select_query = f"SELECT MAX(periodno) FROM agile_data"
                if self.dbobject.db_query(sqlite_select_query) == True:

                    # There can be only 1 row - the query is returning the max value
                    got_row = False
                    for row in self.dbobject.db_queryresults():
                        got_row = True
                        periodno = row[0]

                else:
                    self.log.error("Failed to update data in sqlite table")

                self.dbobject.db_disconnect()
                self.log.debug("The SQLite connection is closed")
        if periodno != -1:
            result = periodno
        self.log.debug("FINISHED get_db_first_missing_period ")
        return periodno

##############################################################################
#  get_db_period_cost - get the cost for the requsted period
##############################################################################
    def get_db_period_cost(self,dateobj):
        self.log.debug("STARTED get_db_period_cost ")
        result = None
        cost = empty_rate
        if self.dbobject.db_ready() == True:
            periodno = gen_periodno_date(dateobj)
            if self.dbobject.db_connect() == True:

                sqlite_select_query = f"""SELECT cost from agile_data WHERE periodno = {periodno} """
                if self.dbobject.db_query(sqlite_select_query) == True:

                    # There can be only 1 row - we are searching on the primary key
                    for row in self.dbobject.db_queryresults():
                        cost = row[0]

                    self.log.debug(f"cost for periodno {periodno} is {cost} pence")

                else:
                    self.log.error(f"Failed to retrieve database data from table:")

                self.dbobject.db_disconnect()
                self.log.debug("The SQLite connection is closed")
        if cost != empty_rate:
            result = cost
        self.log.debug("FINISHED get_db_period_cost ")
        return result

##############################################################################
#  create_db_period_cost - create a database entry with cost for this period
##############################################################################
    def create_db_period_cost(self,year,month,day,hour,minute,cost,inlist=False):
        self.log.debug("STARTED create_period_cost ")
        result=False
        connected = True

        if self.dbobject.db_ready() == True:

            if inlist == False: connected = self.dbobject.db_connect()
            if connected == True:
                # index is based on half hour periods (per day,month and year)
                periodno = gen_periodno(year,month,day,hour,minute)

                sqlite_insert_query = """INSERT INTO agile_data
                     ('periodno','year','month','day','hour','minute','cost','usage')
                        VALUES (?,?,?,?,?,?,?,?); """
                data_tuple = (periodno,year,month,day,hour,minute,cost,empty_rate)

                if self.dbobject.db_query(sqlite_insert_query,data_tuple) == True:
                    result = True
                    self.log.debug(f"SQLQuery {year:4d}/{month:02d}/{day:02d}/{hour:02d}:{minute:02d} completed ")
                else:
                    self.log.error(f"Failed to insert data into sqlite table:")
                    result = False

            if inlist == False: self.dbobject.db_disconnect()

        self.log.debug("FINISHED create_period_cost ")

        return result

##############################################################################
#  get_db_period_data - call Octopus to get usage/cost for a timestamp (day,month,year)
##############################################################################
    def get_db_period_data(self,year=0,month=0,day=0,inlist=False):
        self.log.debug("STARTED get_db_period_data ")
        result = None
        connected = True
        if self.dbobject.db_ready()== True:
            yearstring=""
            monthstring=""
            daystring=""
            result=[]

            if year != 0:
                yearstring =f" WHERE YEAR='{year}'"
                if month != 0:
                    monthstring =f" and MONTH='{month}'"
                    if day != 0:
                        daystring =f" and DAY='{day}'"

            sqlite_select_query=" SELECT * from agile_data " + yearstring + monthstring + daystring + ";"

            if inlist == False: connected = self.dbobject.db_connect()

            if connected == True:
                if self.dbobject.db_query(sqlite_select_query) == True:
                    for row in self.dbobject.db_queryresults():
                        # row0 = periodno, row1=year, row2=month, row3=day, row4=hour,row5=minute, row6=cost, row7 = usage
                        target_band="default"
                        for band in self.chargebands:
                            if  row[6] > float(self.chargebands[band]["rate"]):
                                target_band = band
                        if row[7] != empty_rate:
                            cost = row[6]*row[7]
                        else:
                            cost = 0
                        output = (f"{row[3]:02d}/{row[2]:02d}/{row[1]:04d} {row[4]:02d}:{row[5]:02d}", row[6], row[7], f"{cost:5.3f}" ,target_band)
                        self.log.debug(output)
                        result+= [output]

                else:
                    self.log.error(f"Failed to retrieve database data from table: ")
                    result = None

                if inlist == False:
                    self.dbobject.db_disconnect()
                    self.log.debug("The SQLite connection is closed")

        self.log.debug("FINISHED get_period_data ")
        return result

##############################################################################
#   update_db_period_usage - update the database cost table with usage info
##############################################################################
    def update_db_period_usage(self,year,month,day,hour,minute,usage,inlist):
        result = False
        connected = True
        periodno = 0
        self.log.debug("STARTED save_period_usage ")

        if self.dbobject.db_ready() == True:

            if inlist == False:
                connected = self.dbobject.db_connect()

            if connected == True:
                # index is based on half hour slots (per day,month and year)
                periodno = gen_periodno(year,month,day,hour,minute)

                sqlite_update_query = """UPDATE agile_data SET usage = ? WHERE periodno = ? """
                data_tuple = (usage,periodno)

                if self.dbobject.db_query(sqlite_update_query,data_tuple) == True:
                    result = True
                    self.log.debug(f"Record {year}/{month}/{day}/{hour}:{minute} updated with usage {usage} in database")

                else:
                    self.log.error("Failed to update data in sqlite table")
                    result = False

            if inlist == False: self.dbobject.db_disconnect()

        self.log.debug("FINISHED save_period_usage ")
        return result

##############################################################################
#  get_db_data_years - get the years we have data for
##############################################################################
    def get_db_data_years(self):
        year_list=[]
        result = None
        self.log.debug("STARTED get_db_data_years ")

        if self.dbobject.db_ready() == True:
            if self.dbobject.db_connect() == True:

                self.log.debug("querying agile_data table")
                # create the agile_data table containing forward costs and back usage
                sql_select_query="SELECT year FROM agile_data GROUP BY year"
                if self.dbobject.db_query(sql_select_query) == True:

                    for row in  self.dbobject.db_queryresults():
                        self.log.debug(f"row={row}")
                        year_list += row

                else:
                    self.log.error(f"Failed SQL data call in get_data_years ")

                self.dbobject.db_disconnect()
                self.log.debug("The SQLite connection is closed")
                result = year_list
        self.log.debug("FINISHED get_db_data_years ")

        return result

##############################################################################
#  get_db_data_months- get the months we have data for
##############################################################################
    def get_db_data_months(self,year):
        month_list=[]
        result = None
        self.log.debug("STARTED get_db_data_months ")
        if self.dbobject.db_ready() == True:
            if self.dbobject.db_connect() == True:

                self.log.debug("creating agile_data table")
                # create the agile_data table containing forward costs and back usage
                sql_select_query=f"SELECT year FROM agile_data WHERE year = {year} GROUP BY month"
                if self.dbobject.db_query(sql_select_query) == True:

                    for row in  self.dbobject.db_queryresults():
                        self.log.debug(f"row={row}")
                        month_list += row

                else:
                    self.log.error("Failed SQL data call in get_data_months")

                self.dbobject.db_disconnect()
                self.log.debug("The SQLite connection is closed")
                result = month_list

        self.log.debug("FINISHED get_db_data_months ")
        return result

##############################################################################
#  get_db_data_days - get the years we have data for
##############################################################################
    def get_db_data_days(self,year,month):
        day_list=[]
        result = None
        self.log.debug("STARTED get_db_data_days ")
        if self.dbobject.db_ready() == True:
            if self.dbobject.db_connect() == True:

                self.log.debug("creating agile_data table")
                # create the agile_data table containing forward costs and back usage
                sql_select_query=f"SELECT day  FROM agile_data WHERE year = {year} AND month = {month} GROUP BY day"
                if self.dbobject.db_query(sql_select_query) == True:

                    for row in  self.dbobject.db_queryresults():
                        self.log.debug(f"row={row}")
                        day_list += row
                else:
                    self.log.error("Failed SQL data call in get_data_days")

                self.dbobject.db_disconnect()
                self.log.debug("The SQLite connection is closed")
                result = day_list

        self.log.debug("FINISHED get_db_data_days ")
        return result

##############################################################################
#  create_db_rollup_period - create a rollup for a period
##############################################################################
    def create_db_rollup_month(self,year,month):
        period_data=[]
        month_use = 0
        month_cost = 0
        month_unit = 0
        result = None
        self.log.debug("STARTED create_db_rollup_month ")
        daysinmonth = calendar.monthrange(year,month)[1]
        cost= [] * daysinmonth
        use= [] * daysinmonth
        unit= [] * daysinmonth
        if self.db_ready() == True:
            if self.dbobject.db_connect() == True:
                # we'vew got more database work to do - set inlist to true to keep connection open
                period_data = self.get_db_period_data(year,month,0,True)

                if period_data != None:
                    for entry in period_data:
                        # got a months worth of entries total up the days
                        day = int(entry[0].split('/')[0])
                        self.log.debug(f"entry data = [{entry}] day=[{day}]")
                        if float(entry[2]) != -999.99:
                            use[day]  += float(entry[2])
                            cost[day] += float(entry[3])
                            unit [day] = cost[day]/use[day]
                            # average out the result for the current month
                            month_use  += float(entry[2])
                            month_cost += float(entry[3])
                            month_unit  = month_cost/ month_use

                    # we have a per day total and a per month total (running in the case the periods are not complete)
                    # put those values into the database

                    #first off insert the month into the month table
                    monthno = 12 * (year - yroffset) + month
                    sql_month_insert_query = "INSERT INTO agile_rollup_month (monthno, year, month, cost , usage , unit) VALUES = (?,?,?,?,?,?)"
                    month_tuple=(monthno, year, month, month_cost , month_use , month_unit)

                    for day in 1..daysinmonth:
                        dayno = day + (month * 31) + ((year - yroffset ) * 366)
                        day_tuple=(dayno, year, month, day, cost[day], use[day], unit[day])
                        sql_day_insert_query = "INSERT INTO agile_rollup_day (dayno, year, month, day, cost, usage, unit) VALUES = (?,?,?,?,?,?.?)"

            # Finished disconnect from the database
            self.dbobject.db_disconnect()
        self.log.debug("FINISHED create_db_rollup_month ")
        return result


import time

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import pandas as pd

service = Service(ChromeDriverManager().install())
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome(service=service, options=chrome_options)
for page_index in range(1, 30):
    driver.implicitly_wait(2)
    table = driver.find_element(By.CLASS_NAME, 'zg_table')
    table_items = table.find_element(By.TAG_NAME, 'tbody').find_elements(By.TAG_NAME, 'tr')
    columns = table_items[0].find_elements(By.TAG_NAME, 'th')
    columns_row = []
    data_rows = []
    for column in columns:
        if column.text == '详情介绍':
            break
        columns_row.append(column.text)
    print("current_page:", page_index)
    for item in table_items:
        item_contents = item.find_elements(By.TAG_NAME, 'td')
        if len(item_contents) == 0:
            continue
        row = []
        for item_content in item_contents:
            if item_content.text == '职位详情':
                break
            row.append(item_content.text)
        data_rows.append(row)
    df = pd.DataFrame(data_rows, columns=columns_row)
    print(df)
    df.to_csv('./data.csv', mode='a', index=False, sep=',', encoding='utf_8_sig')

    next_pages_components = driver.find_element(By.CLASS_NAME, 'zg_page').find_element(By.TAG_NAME, 'p')
    next_pages_hrefs = next_pages_components.find_elements(By.TAG_NAME, 'a')
    for next_pages_href in next_pages_hrefs:
        if next_pages_href.text == '下一页':
            next_pages_href.click()
            break


#Finding how many integers divisble by the Entered number
n = int(input("How many integers do you have? "))
k = int(input("Enter the K value: "))
l,t = list(),list()
for i in range(n):
    l.append(int(input("Enter the Element-{}: ".format(i+1))))
for i in l:
    if i%k == 0:
        t.append(i)
print("The given numbers Divisible by '{}' are :".format(k))
for i in t:
    print(i)

Finding the given numbers Divible by one number.py


class Heap(object):

    def __init__(self):
        self.array = []

    def _percolate_up_iteration(self, index):
        if index <= 0:
            return
        while index > 0:
            parent_index = (index - 1) // 2
            if self.array[index] < self.array[parent_index]:
                self.array[parent_index], self.array[index] = self.array[index], self.array[parent_index]
                index = parent_index
            else:
                break

    def _percolate_up_recursion(self, index):
        if index <= 0:
            return
        parent_index = (index - 1) // 2
        if self.array[index] < self.array[parent_index]:
            self.array[parent_index], self.array[index] = self.array[index], self.array[parent_index]
            self._percolateUpRecursion(self, parent_index)

    def _percolate_down_iteration(self, index):
        if index > len(self.array) // 2 - 1:
            return
        while index <= len(self.array) // 2 - 1:
            index_left_child = index * 2 + 1
            index_right_child = index * 2 + 2
            index_min_child = index_left_child
            if index_right_child < len(self.array) and self.array[index_right_child] < self.array[index_left_child]:
                index_min_child = index_right_child
            if self.array[index] > self.array[index_min_child]:
                self.array[index], self.array[index_min_child] = self.array[index_min_child], self.array[index]
                index = index_min_child
            else:
                break

    def _percolate_down_recursion(self, index):
        if index > len(self.array) // 2 - 1:
            return
        index_left_child = index * 2 + 1
        index_right_child = index * 2 + 2
        index_min_child = index_left_child
        if index_right_child < len(self.array) and self.array[index_right_child] < self.array[index_left_child]:
            index_min_child = index_right_child
        if self.array[index] > self.array[index_min_child]:
            self.array[index], self.array[index_min_child] = self.array[index_min_child], self.array[index]
            self._percolateDownRecursion(self, index_min_child)

    def is_empty(self):
        return len(self.array) == 0

    def get_size(self):
        return len(self.array)

    def get_top(self):
        if len(self.array) > 0:
            return self.array[0]
        else:
            return None

    def pop(self):
        if self.is_empty():
            print('Heap is already empty!')
            return None
        result = self.array[0]
        self.array[0] = self.array[-1]
        self.array.pop()
        if len(self.array) > 0:
            self._percolate_down_iteration(0)
        return result

    def insert(self, number):
        self.array.append(number)
        self._percolate_up_iteration(len(self.array) - 1)

def find_first_k_elements1(array, k):
    if not array or k >= len(array):
        return array
    h = Heap()
    for num in array:
        h.insert(num)
    result = []
    for i in range(k):
        result.append(h.pop())
    return result

def find_first_k_elements2(array, k):
    if not array or k >= len(array):
        return array
    h = Heap()
    for i in range(len(array)):
        if i < k:
            h.insert(-1 * array[i])
        elif h.get_top() < -1 * array[i]:
            h.pop()
            h.insert(-1 * array[i])
    result = []
    while not h.is_empty():
        result.append(-1 * h.pop())
    return result

def find_first_k_elements3(array, k, left_index, right_index):
    if not array or k >= right_index - left_index + 1 or k <= 0:
        return
    left = left_index
    right = right_index - 1
    while left <= right:
        if array[left] <= array[right_index]:
            left += 1
        else:
            array[left], array[right] = array[right], array[left]
            right -= 1
    array[left], array[right_index] = array[right_index], array[left]
    num_smaller = left - left_index
    if k == num_smaller or k == num_smaller + 1:
        return
    elif k < num_smaller:
        find_first_k_elements3(array, k, left_index, left - 1)
    else:
        find_first_k_elements3(array, k - num_smaller - 1, left + 1, right_index)

testHeap = Heap()
testArray = [2, 4, 2, 8, 5, 6, 1, 12, 9]
for element in testArray:
    testHeap.insert(element)
while not testHeap.is_empty():
    print(testHeap.pop(), end=' ')
print()

print(find_first_k_elements1(testArray, 3))
print(find_first_k_elements2(testArray, 3))
find_first_k_elements3(testArray, 7, 0, len(testArray) - 1)
print(testArray[:7])


from torch.utils.data import DataLoader
import numpy as np
import torchdata.datapipes as dp
import os
import pandas as pd
from PIL import Image
from torch.utils.data import Dataset

class MyDataset(Dataset):
    def __init__(self, csv_path, transform=None):

        df = pd.read_csv(csv_path)
        self.transform = transform

        # based on DataFrame columns
        self.font_names = df["fontName"]
        self.averages = df["readabilityScore"]

        self.font2readability = {}

        for i, name in enumerate(df["fontName"]):
            self.font2readability[name] = df["readabilityScore"][i]

    def __getitem__(self, index):

        averages = self.averages[index]
        return {"a" : averages}

    def __len__(self):
        return self.averages.shape[0]

train_dataset = MyDataset(
    csv_path="./data/readability.csv"
    # transform=data_transforms["train"],
)

train_loader = DataLoader(
    dataset=train_dataset,
    batch_size=32,
    shuffle=True,
    drop_last=True,
    # transform=data_transforms["train"],
    num_workers=0,
)

num_epochs = 1
for epoch in range(num_epochs):

    for batch_idx, x in enumerate(train_loader):
        # if batch_idx >= 3:
        #     break
        # print(" Batch index:", batch_idx)
        # print(" | Batch size:", x.shape[0])
        # print(" | x shape:", x.shape)
        # print(" | y shape:", x[""])
        print(x.keys())

print("Labels from current batch:", x)

# def filter_for_data(filename):
#     return "sample_data" in filename and filename.endswith(".csv")

# def row_processer(row):
#     return {"label": np.array(row[0], np.int32), "data": np.array(row[1:], dtype=np.float64)}

# def build_datapipes(root_dir="./data"):
#     datapipe = dp.iter.FileLister(root_dir)
#     datapipe = datapipe.filter(filter_fn=filter_for_data)
#     datapipe = datapipe.open_files(mode='rt')
#     datapipe = datapipe.parse_csv(delimiter=",", skip_lines=1)
#     # Shuffle will happen as long as you do NOT set `shuffle=False` later in the DataLoader
#     datapipe = datapipe.shuffle()
#     datapipe = datapipe.map(row_processer)
#     return datapipe

# if __name__ == '__main__':
#     datapipe = build_datapipes()
#     dl = DataLoader(dataset=datapipe, batch_size=5, num_workers=2)
#     first = next(iter(dl))
#     labels, features = first['label'], first['data']
#     print(f"Labels batch shape: {labels.size()}")
#     print(f"Feature batch shape: {features.size()}")
#     print(f"{labels = }\n{features = }")
#     n_sample = 0
#     for row in iter(dl):
#         n_sample += 1
#     print(f"{n_sample = }")


import socket
import os

class PC():
    def __init__(self, tcp_ip):
        self.tcp_ip = tcp_ip
        self.port = 5182
        self.connection = None
        self.client = None
        self.address = None
        self._is_pc_connected = False

    def is_connected(self):
        return self._is_pc_connected

    def close(self):
        if self.connection != None:
            self.connection.close()
        if self.client != None:
            self.client.close()
        self._is_pc_connected = False

    def connect(self):
        try:
            self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.connection.bind((self.tcp_ip, self.port))
            self.connection.listen(1)
            print("[@] Listening for incoming connections from PC...")
            self.client, self.address = self.connection.accept()
            print("[@] Connected! Connection address: {}".format(self.address))
            self._is_pc_connected = True
        except Exception as e:
            print("[!] Error connecting to PC")
            print(e)

    def write(self, msg):
        try:
            self.client.sendto(msg, self.address)
        except Exception as e:
            print("[!] Error writing message")
            print(e)

    def read(self):
        try:
            return self.client.recv(2048)
        except Exception as e:
            print("[!] Error reading message")
            print(e)


#!/usr/bin/env python3
import requests
import chess

Piece = {'K': "king", 'Q': "queen", 'N': "knight", 'R': "rook", 'B': "bishop"}

Number = {'1': 'one', '2': 'two', '3': 'three',
          '4': 'four', '5': 'five', '6': 'six',
          '7': 'seven', '8': 'eight'}

Wrapped_Spk = {'one': '1', 'two': '2', 'three': '3',
               'four': '4', 'five': '5', 'six': '6',
               'seven': '7', 'eight': '8', "king": 'K',
               "queen": 'Q', "knight": 'N', "rook": 'R',
               "bishop": 'B', "x": 'x', "check": 'x'}

def API_token():
    """
    Return the api token from `secret.key`
    """
    with open("secret.key", "r") as pf:
        token = pf.readline()
    return 'Bearer ' + token

Token = API_token()

def Parse_move(move):
    """
    Function that takes a move and transcribe it to spoken text.
    Args:
    (move): string representing the pgn/fen move
    Return:
    (Parsed): Spoken text format for the pgn move
    """
    Parsed = ""
    for char in move:
        if char == 'O':
            if len(move) == 3:
                Parsed += "short castle"
            else:
                Parsed += "long castle"
            break
        if char == 'x':
            Parsed += 'takes on '
        elif char == '+':
            Parsed += ' check'
        elif char.isupper():
            Parsed += Piece[char] + " "
        elif char.islower():
            Parsed += char + " "
        elif char.isdigit():
            Parsed += Number[char] + " "
        elif char == '#':
            Parsed += " Checkmate"
    Parsed += " \n"
    return " ".join(Parsed.split())

def Spoken_ToFen(Spoken):
    """
    convert Spoken text to fen
    Finish short castling...checkmate
    """
    if Spoken == 'short castle':
        return 'O-O'
    if Spoken == 'long castle':
        return 'O-O-O'
    Spoken = Spoken.replace("takes on", "x")
    Spoken = Spoken.replace("take on", "x")
    To_list = Spoken.split()

    spk = ''
    for elem in To_list:
        if len(elem) == 1:
            spk += elem
        else:
            spk += Wrapped_Spk[elem]
    return spk

def get_fen():
    """
    Function returning the CURRENT fen
    FEN example of return:
      'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
    """
    headers = {'Authorization': Token}
    url = "https://lichess.org/api/account/playing"
    res = requests.get(url, headers=headers)
    if res.status_code != 200:
        print("Check your connection")
    res_json = res.json()

    fen = res_json["nowPlaying"][0]["fen"]
    return fen

def get_legalMoves():
    """
    Function that return the CURRENT possible moves to play.
    Example of return: ['Nh3', 'Nf3', 'Nc3', 'Na3', 'h3', 'g3']
    """
    fen = get_fen()
    board = chess.Board(fen)
    legal_moves = list(board.legal_moves)

    moves_t = str(board.legal_moves)[37:-1]
    moves_t = moves_t.replace(", ", "', '")
    moves_t = moves_t.replace("(", "('")
    moves_t = moves_t.replace(")", "')")
    moves_t = eval(moves_t)
    """
    moves_t: more than one move to play: ('Kf8', 'dxc5', 'g5', 'd5', 'a5')
    moves_t: one move to play: 'Kf8'
    """
    if type(moves_t) is not tuple:  # One single move
        return [moves_t]

    moves = []
    for i in moves_t:
        moves.append(i)
    return moves

def get_pieces():
    """
    Function that returns a dictionary of the CURRENT legal
      moves per piece in spoken version.
    Example of return: {'knight': ['knight h three', 'knight f three'],
      'pawn': ['h three']}
    """
    moves = get_legalMoves()  # (INPUT: list of pgn leal moves)

    dic = {'N': [], 'P': [], 'K': [], 'Q': [], 'B': [], 'R': []}
    for move in moves:
        if move[0].islower():
            dic['P'].append(move)
        else:
            if move[0] == 'O':  # Castling move
                dic['K'].append(move)
            else:
                dic[move[0]].append(move)

    pieces = {'knight': dic['N'], 'pawn': dic['P'],
              'king': dic['K'], 'queen': dic['Q'],
              'bishop': dic['B'], 'rook': dic['R']}

    # do not include pieces with no move to play
    updated = dict((key, value) for key, value in pieces.items()
                   if value != [])

    # get the spoken version of notation
    spk_fen = {}
    for key in updated.keys():
        spk_fen[key] = []
        for fen in updated[key]:
            spk_fen[key].append(Parse_move(fen))
    return spk_fen

def get_grammar():
    """
    Function that return a tuple of:
      1. grammar to pass for the model recognizer.
        - Example: '["knight h six", "knight f six", "knight c six", "[unk]"]'
      2. `to_check`
    """
    legal_moves = get_pieces()  # (INPUT)
    grammar = ''
    to_check = []
    for key, value in legal_moves.items():
        for elem in value:
            to_check.append(elem)
            grammar += '\"{0}\", '.format(elem)
    return '[{0}\"[unk]\"]'.format(grammar), to_check


from collections import (
    Counter,
    defaultdict,
)
from itertools import (
    groupby,
)
import logging
from operator import (
    attrgetter,
)
from typing import (
    Dict,
    Iterable,
    List,
    Mapping,
    MutableMapping,
    MutableSet,
    Optional,
    Sequence,
    Tuple,
    Type,
    Union,
)

from elasticsearch import (
    ConflictError,
    ElasticsearchException,
)
from elasticsearch.helpers import (
    scan,
    streaming_bulk,
)
from more_itertools import (
    one,
)

from azul import (
    CatalogName,
    config,
)
from azul.deployment import (
    aws,
)
from azul.es import (
    ESClientFactory,
)
from azul.indexer import (
    Bundle,
    BundleUUID,
    BundleVersion,
)
from azul.indexer.aggregate import (
    Entities,
)
from azul.indexer.document import (
    Aggregate,
    AggregateCoordinates,
    CataloguedContribution,
    CataloguedEntityReference,
    CataloguedFieldTypes,
    Contribution,
    Document,
    DocumentCoordinates,
    EntityID,
    EntityReference,
    EntityType,
    VersionType,
)
from azul.indexer.document_service import (
    DocumentService,
)
from azul.indexer.transform import (
    Transformer,
)
from azul.types import (
    JSON,
    MutableJSON,
)

log = logging.getLogger(__name__)

Tallies = Mapping[EntityReference, int]

CataloguedTallies = Mapping[CataloguedEntityReference, int]

MutableCataloguedTallies = MutableMapping[CataloguedEntityReference, int]

CollatedEntities = MutableMapping[EntityID, Tuple[BundleUUID, BundleVersion, JSON]]

class IndexService(DocumentService):

    def settings(self, index_name) -> JSON:

        aggregate = config.parse_es_index_name(index_name).aggregate
        num_nodes = aws.es_instance_count
        num_workers = config.contribution_concurrency(retry=False)

        # Put a primary aggregate shard on every node. Linearly scale the number
        # of contribution shards with the number of indexer workers i.e.,
        # writers. There was no notable difference in speed between factors 1
        # and 1/4 but the memory pressure was unsustainably high with factor 1.
        #
        num_shards = num_nodes if aggregate else max(num_nodes, num_workers // 4)

        # Replicate aggregate shards over the entire cluster, every node should
        # store the complete aggregate index to avoid intra-cluster talk when
        # responding to client queries, hopefully accelerating them. Aggregate
        # indices are small so distributing them fully makes sense.
        #
        # No replication for contribution indices because durability does not
        # matter to us as much. If a node goes down, we'll just have to reindex.
        # I have yet to perform a successful replacement of a cluster node.
        # With bigger cluster sizes this may become an issue again but I simply
        # don't sufficiently understand that scenario to be able to prepare for
        # it with confidence.
        #
        num_replicas = (num_nodes - 1) if aggregate else 0
        return {
            'index': {
                'number_of_shards': num_shards,
                'number_of_replicas': num_replicas,
                'refresh_interval': f'{config.es_refresh_interval}s'
            }
        }

    def index_names(self, catalog: CatalogName) -> List[str]:
        return [
            config.es_index_name(catalog=catalog,
                                 entity_type=entity_type,
                                 aggregate=aggregate)
            for entity_type in self.entity_types(catalog)
            for aggregate in (False, True)
        ]

    def index(self, catalog: CatalogName, bundle: Bundle) -> None:
        """
        Index the bundle referenced by the given notification. This is an
        inefficient default implementation. A more efficient implementation
        would transform many bundles, collect their contributions and aggregate
        all affected entities at the end.
        """
        contributions = self.transform(catalog, bundle, delete=False)
        tallies = self.contribute(catalog, contributions)
        self.aggregate(tallies)

    def delete(self, catalog: CatalogName, bundle: Bundle) -> None:
        """
        Synchronous form of delete that is currently only used for testing.

        In production code, there is an SQS queue between the calls to
        `contribute()` and `aggregate()`.
        """
        # FIXME: this only works if the bundle version is not being indexed
        #        concurrently. The fix could be to optimistically lock on the
        #        aggregate version (https://github.com/DataBiosphere/azul/issues/611)
        contributions = self.transform(catalog, bundle, delete=True)
        # FIXME: these are all modified contributions, not new ones. This also
        #        happens when we reindex without deleting the indices first. The
        #        tallies refer to number of updated or added contributions but
        #        we treat them as if they are all new when we estimate the
        #        number of contributions per bundle.
        # https://github.com/DataBiosphere/azul/issues/610
        tallies = self.contribute(catalog, contributions)
        self.aggregate(tallies)

    def transform(self, catalog: CatalogName, bundle: Bundle, delete: bool):
        log.info('Transforming metadata for bundle %s, version %s.', bundle.uuid, bundle.version)
        contributions = []
        for transformer_cls in self.transformers(catalog):
            transformer: Transformer = transformer_cls.create(bundle, deleted=delete)
            contributions.extend(transformer.transform())
        return contributions

    def create_indices(self, catalog: CatalogName):
        es_client = ESClientFactory.get()
        for index_name in self.index_names(catalog):
            es_client.indices.create(index=index_name,
                                     ignore=[400],
                                     body=dict(settings=self.settings(index_name),
                                               mappings=dict(doc=self.metadata_plugin(catalog).mapping())))

    def delete_indices(self, catalog: CatalogName):
        es_client = ESClientFactory.get()
        for index_name in self.index_names(catalog):
            if es_client.indices.exists(index_name):
                es_client.indices.delete(index=index_name)

    def contribute(self, catalog: CatalogName, contributions: List[Contribution]) -> CataloguedTallies:
        """
        Write the given entity contributions to the index and return tallies, a
        dictionary tracking the number of contributions made to each entity.

        Tallies for overwritten documents are not counted. This means a tally
        with a count of 0 may exist. This is ok. See description of aggregate().
        """
        tallies = Counter()
        writer = self._create_writer(catalog)
        while contributions:
            writer.write(contributions)
            retry_contributions = []
            for c in contributions:
                if c.coordinates in writer.retries:
                    retry_contributions.append(c)
                else:
                    entity = CataloguedEntityReference.for_entity(catalog, c.coordinates.entity)
                    # Don't count overwrites, but ensure entry exists
                    was_overwrite = c.version_type is VersionType.none
                    tallies[entity] += 0 if was_overwrite else 1
            contributions = retry_contributions
        writer.raise_on_errors()
        return tallies

    def aggregate(self, tallies: CataloguedTallies):
        """
        Read all contributions to the entities listed in the given tallies from
        the index, aggregate the contributions into one aggregate per entity and
        write the resulting aggregates to the index.

        Normally there is a one-to-one correspondence between number of
        contributions for an entity and the value for a tally, however tallies
        are not counted for updates. This means, in the case of a duplicate
        notification or writing over an already populated index, it's possible
        to receive a tally with a value of 0. We still need to aggregate (if the
        indexed format changed for example). Tallies are a lower bound for the
        number of contributions in the index for a given entity.

        Also note that the input tallies can refer to entities from different
        catalogs.
        """
        # Use catalog specified in each tally
        writer = self._create_writer(catalog=None)
        while True:
            # Read the aggregates
            old_aggregates = self._read_aggregates(tallies)
            total_tallies: MutableCataloguedTallies = Counter(tallies)
            total_tallies.update({
                old_aggregate.coordinates.entity: old_aggregate.num_contributions
                for old_aggregate in old_aggregates.values()
            })
            # Read all contributions from Elasticsearch
            contributions = self._read_contributions(total_tallies)
            actual_tallies = Counter(contribution.coordinates.entity
                                     for contribution in contributions)
            if tallies.keys() != actual_tallies.keys():
                message = 'Could not find all expected contributions.'
                args = (tallies, actual_tallies) if config.debug else ()
                raise EventualConsistencyException(message, *args)
            assert all(tallies[entity] <= actual_tally
                       for entity, actual_tally in actual_tallies.items())
            # Combine the contributions into old_aggregates, one per entity
            new_aggregates = self._aggregate(contributions)
            # Set the expected document version from the old version
            for new_aggregate in new_aggregates:
                old_aggregate = old_aggregates.pop(new_aggregate.coordinates.entity, None)
                new_aggregate.version = None if old_aggregate is None else old_aggregate.version
            # Empty out any unreferenced aggregates (can only happen for deletions)
            for old_aggregate in old_aggregates.values():
                old_aggregate.contents = {}
                new_aggregates.append(old_aggregate)
            # Write aggregates to Elasticsearch
            writer.write(new_aggregates)
            # Retry if necessary
            if not writer.retries:
                break
            tallies: CataloguedTallies = {
                aggregate.coordinates.entity: tallies[aggregate.coordinates.entity]
                for aggregate in new_aggregates
                if aggregate.coordinates in writer.retries
            }
        writer.raise_on_errors()

    def _read_aggregates(self, entities: CataloguedTallies) -> Dict[CataloguedEntityReference, Aggregate]:
        coordinates = [
            AggregateCoordinates(entity=entity)
            for entity in entities
        ]
        request = {
            'docs': [
                {
                    '_type': coordinate.type,
                    '_index': coordinate.index_name,
                    '_id': coordinate.document_id
                }
                for coordinate in coordinates
            ]
        }
        catalogs = {coordinate.entity.catalog for coordinate in coordinates}
        mandatory_source_fields = set()
        for catalog in catalogs:
            aggregate_cls = self.aggregate_class(catalog)
            mandatory_source_fields.update(aggregate_cls.mandatory_source_fields())
        response = ESClientFactory.get().mget(body=request,
                                              _source_includes=list(mandatory_source_fields))

        def aggregates():
            for doc in response['docs']:
                if doc['found']:
                    coordinate = DocumentCoordinates.from_hit(doc)
                    aggregate_cls = self.aggregate_class(coordinate.entity.catalog)
                    aggregate = aggregate_cls.from_index(self.catalogued_field_types(),
                                                         doc,
                                                         coordinates=coordinate)
                    yield aggregate

        return {a.coordinates.entity: a for a in aggregates()}

    def _read_contributions(self, tallies: CataloguedTallies) -> List[CataloguedContribution]:
        es_client = ESClientFactory.get()
        entity_ids_by_index: MutableMapping[str, MutableSet[str]] = defaultdict(set)
        for entity in tallies.keys():
            index = config.es_index_name(catalog=entity.catalog,
                                         entity_type=entity.entity_type,
                                         aggregate=False)
            entity_ids_by_index[index].add(entity.entity_id)
        query = {
            "query": {
                "bool": {
                    "should": [
                        {
                            "bool": {
                                "must": [
                                    {
                                        "term": {
                                            "_index": index
                                        }
                                    },
                                    {
                                        "terms": {
                                            "entity_id.keyword": list(entity_ids)
                                        }
                                    }
                                ]
                            }
                        } for index, entity_ids in entity_ids_by_index.items()
                    ]
                }
            }
        }
        index = sorted(list(entity_ids_by_index.keys()))
        # scan() uses a server-side cursor and is expensive. Only use it if the number of contributions is large
        page_size = 1000  # page size of 100 caused excessive ScanError occurrences
        num_contributions = sum(tallies.values())
        hits = None
        if num_contributions <= page_size:
            log.info('Reading %i expected contribution(s) using search().', num_contributions)
            response = es_client.search(index=index,
                                        body=query,
                                        size=page_size,
                                        doc_type=Contribution.type,
                                        seq_no_primary_term=Contribution.needs_seq_no_primary_term)
            total_hits = response['hits']['total']
            if total_hits <= page_size:
                hits = response['hits']['hits']
                if len(hits) != total_hits:
                    message = f'Search returned {len(hits)} hits but reports total to be {total_hits}'
                    raise EventualConsistencyException(message)
            else:
                log.info('Expected only %i contribution(s) but got %i.', num_contributions, total_hits)
                num_contributions = total_hits
        if hits is None:
            log.info('Reading %i expected contribution(s) using scan().', num_contributions)
            hits = scan(es_client,
                        index=index,
                        query=query,
                        size=page_size,
                        doc_type=Contribution.type,
                        seq_no_primary_term=Contribution.needs_seq_no_primary_term)
        contributions = [
            Contribution.from_index(self.catalogued_field_types(), hit)
            for hit in hits
        ]
        log.info('Read %i contribution(s). ', len(contributions))
        if log.isEnabledFor(logging.DEBUG):
            entity_ref = attrgetter('entity')
            log.debug(
                'Number of contributions read, by entity: %r',
                {
                    f'{entity.entity_type}/{entity.entity_id}': sum(1 for _ in contribution_group)
                    for entity, contribution_group in groupby(sorted(contributions, key=entity_ref), key=entity_ref)
                }
            )
        return contributions

    def _aggregate(self, contributions: List[CataloguedContribution]) -> List[Aggregate]:
        # Group contributions by entity and bundle UUID
        contributions_by_bundle: Mapping[
            Tuple[CataloguedEntityReference, BundleUUID],
            List[CataloguedContribution]
        ] = defaultdict(list)
        tallies: MutableCataloguedTallies = Counter()
        for contribution in contributions:
            entity = contribution.coordinates.entity
            bundle_uuid = contribution.coordinates.bundle.uuid
            contributions_by_bundle[entity, bundle_uuid].append(contribution)
            # Track the raw, unfiltered number of contributions per entity.
            assert isinstance(contribution.coordinates.entity, CataloguedEntityReference)
            tallies[contribution.coordinates.entity] += 1

        # For each entity and bundle, find the most recent contribution that is not a deletion
        contributions_by_entity: MutableMapping[
            CataloguedEntityReference, List[CataloguedContribution]] = defaultdict(list)
        for (entity, bundle_uuid), contributions in contributions_by_bundle.items():
            contributions = sorted(contributions,
                                   key=attrgetter('coordinates.bundle.version', 'coordinates.deleted'),
                                   reverse=True)
            for bundle_version, group in groupby(contributions, key=attrgetter('coordinates.bundle.version')):
                contribution: Contribution = next(group)
                if not contribution.coordinates.deleted:
                    assert bundle_uuid == contribution.coordinates.bundle.uuid
                    assert bundle_version == contribution.coordinates.bundle.version
                    assert entity == contribution.coordinates.entity
                    contributions_by_entity[entity].append(contribution)
                    break
        log.info('Selected %i contribution(s) to be aggregated.',
                 sum(len(contributions) for contributions in contributions_by_entity.values()))
        if log.isEnabledFor(logging.DEBUG):
            log.debug(
                'Number of contributions selected for aggregation, by entity: %r',
                {
                    f'{entity.entity_type}/{entity.entity_id}': len(contributions)
                    for entity, contributions in sorted(contributions_by_entity.items())
                }
            )

        # Create lookup for transformer by entity type
        transformers: Dict[Tuple[CatalogName, str], Type[Transformer]] = {
            (catalog, transformer.entity_type()): transformer
            for catalog in config.catalogs
            for transformer in self.transformers(catalog)
        }

        # Aggregate contributions for the same entity
        aggregates = []
        for entity, contributions in contributions_by_entity.items():
            transformer = transformers[entity.catalog, entity.entity_type]
            contents = self._aggregate_entity(transformer, contributions)
            bundles = [
                dict(uuid=c.coordinates.bundle.uuid,
                     version=c.coordinates.bundle.version)
                for c in contributions
            ]
            sources = set(c.source for c in contributions)
            aggregate_cls = self.aggregate_class(entity.catalog)
            aggregate = aggregate_cls(coordinates=AggregateCoordinates(entity=entity),
                                      version=None,
                                      sources=sources,
                                      contents=contents,
                                      bundles=bundles,
                                      num_contributions=tallies[entity])
            aggregates.append(aggregate)

        return aggregates

    def _aggregate_entity(self,
                          transformer: Type[Transformer],
                          contributions: List[Contribution]) -> MutableJSON:
        contents = self._select_latest(contributions)
        aggregate_contents = {}
        inner_entity_types = transformer.inner_entity_types()
        inner_entity_counts = []
        for entity_type, entities in contents.items():
            num_entities = len(entities)
            if entity_type in inner_entity_types:
                assert num_entities <= 1
                inner_entity_counts.append(num_entities)
            else:
                aggregator = transformer.get_aggregator(entity_type)
                if aggregator is not None:
                    entities = aggregator.aggregate(entities)
            aggregate_contents[entity_type] = entities
        if inner_entity_counts:
            assert sum(inner_entity_counts) > 0
        return aggregate_contents

    def _select_latest(self, contributions: Sequence[Contribution]) -> MutableMapping[EntityType, Entities]:
        """
        Collect the latest version of each inner entity from multiple given documents.

        If two or more contributions contain copies of the same inner entity, potentially with different contents, the
        copy from the contribution with the latest bundle version will be selected.
        """
        if len(contributions) == 1:
            return one(contributions).contents
        else:
            contents: MutableMapping[EntityType, CollatedEntities] = defaultdict(dict)
            for contribution in contributions:
                for entity_type, entities in contribution.contents.items():
                    collated_entities = contents[entity_type]
                    entity: JSON
                    for entity in entities:
                        entity_id = entity['document_id']  # FIXME: the key 'document_id' is HCA specific
                        cur_bundle_uuid, cur_bundle_version, cur_entity = \
                            collated_entities.get(entity_id, (None, '', None))
                        if cur_entity is not None and entity.keys() != cur_entity.keys():
                            symmetric_difference = set(entity.keys()).symmetric_difference(cur_entity)
                            log.warning('Document shape of `%s` entity `%s` does not match between bundles '
                                        '%s, version %s and %s, version %s: %s',
                                        entity_type, entity_id,
                                        cur_bundle_uuid, cur_bundle_version,
                                        contribution.coordinates.bundle.uuid,
                                        contribution.coordinates.bundle.version,
                                        symmetric_difference)
                        if cur_bundle_version < contribution.coordinates.bundle.version:
                            collated_entities[entity_id] = (
                                contribution.coordinates.bundle.uuid,
                                contribution.coordinates.bundle.version,
                                entity
                            )
            return {
                entity_type: [entity for _, _, entity in entities.values()]
                for entity_type, entities in contents.items()
            }

    def _create_writer(self, catalog: Optional[CatalogName]) -> 'IndexWriter':
        # We allow one conflict retry in the case of duplicate notifications and
        # switch from 'add' to 'update'. After that, there should be no
        # conflicts because we use an SQS FIFO message group per entity. For
        # other errors we use SQS message redelivery to take care of the
        # retries.
        return IndexWriter(catalog,
                           self.catalogued_field_types(),
                           refresh=False,
                           conflict_retry_limit=1,
                           error_retry_limit=0)

class IndexWriter:

    def __init__(self,
                 catalog: Optional[CatalogName],
                 field_types: CataloguedFieldTypes,
                 refresh: Union[bool, str],
                 conflict_retry_limit: int,
                 error_retry_limit: int) -> None:
        """
        :param field_types: A mapping of field paths to field type

        :param refresh: https://www.elastic.co/guide/en/elasticsearch/reference/5.5/docs-refresh.html

        :param conflict_retry_limit: The maximum number of retries (the second
                                     attempt is the first retry) on version
                                     conflicts. Specify 0 for no retries or None
                                     for unlimited retries.

        :param error_retry_limit: The maximum number of retries (the second
                                  attempt is the first retry) on other errors.
                                  Specify 0 for no retries or None for
                                  unlimited retries.
        """
        super().__init__()
        self.catalog = catalog
        self.field_types = field_types
        self.refresh = refresh
        self.conflict_retry_limit = conflict_retry_limit
        self.error_retry_limit = error_retry_limit
        self.es_client = ESClientFactory.get()
        self.errors: MutableMapping[DocumentCoordinates, int] = defaultdict(int)
        self.conflicts: MutableMapping[DocumentCoordinates, int] = defaultdict(int)
        self.retries: Optional[MutableSet[DocumentCoordinates]] = None

    bulk_threshold = 32

    def write(self, documents: List[Document]):
        """
        Make an attempt to write the documents into the index, updating local
        state with failures and conflicts

        :param documents: Documents to index
        """
        self.retries = set()
        if len(documents) < self.bulk_threshold:
            self._write_individually(documents)
        else:
            self._write_bulk(documents)

    def _write_individually(self, documents: Iterable[Document]):
        log.info('Writing documents individually')
        for doc in documents:
            try:
                method = self.es_client.delete if doc.delete else self.es_client.index
                method(refresh=self.refresh, **doc.to_index(self.catalog, self.field_types))
            except ConflictError as e:
                self._on_conflict(doc, e)
            except ElasticsearchException as e:
                self._on_error(doc, e)
            else:
                self._on_success(doc)

    def _write_bulk(self, documents: Iterable[Document]):
        # FIXME: document this quirk
        documents: Dict[DocumentCoordinates, Document] = {
            doc.coordinates.with_catalog(self.catalog): doc
            for doc in documents
        } if self.catalog is not None else {
            doc.coordinates: doc
            for doc in documents
        }
        actions = [
            doc.to_index(self.catalog, self.field_types, bulk=True)
            for doc in documents.values()
        ]
        log.info('Writing documents using streaming_bulk().')
        # We cannot use parallel_bulk() for 1024+ actions because Lambda doesn't
        # support shared memory. See
        # https://github.com/DataBiosphere/azul/issues/3200
        response = streaming_bulk(client=self.es_client,
                                  actions=actions,
                                  refresh=self.refresh,
                                  raise_on_error=False,
                                  max_chunk_bytes=config.max_chunk_size)
        for success, info in response:
            op_type, info = one(info.items())
            assert op_type in ('index', 'create', 'delete')
            coordinates = DocumentCoordinates.from_hit(info)
            doc = documents[coordinates]
            if success:
                self._on_success(doc)
            else:
                if info['status'] == 409:
                    self._on_conflict(doc, info)
                else:
                    self._on_error(doc, info)

    def _on_success(self, doc: Document):
        coordinates = doc.coordinates
        self.conflicts.pop(coordinates, None)
        self.errors.pop(coordinates, None)
        if isinstance(doc, Aggregate):
            log.debug('Successfully wrote %s with %i contribution(s).',
                      coordinates, doc.num_contributions)
        else:
            log.debug('Successfully wrote %s.', coordinates)

    def _on_error(self, doc: Document, e: Union[Exception, JSON]):
        self.errors[doc.coordinates] += 1
        if self.error_retry_limit is None or self.errors[doc.coordinates] <= self.error_retry_limit:
            action = 'retrying'
            self.retries.add(doc.coordinates)
        else:
            action = 'giving up'
        log.warning('There was a general error with document %r: %r. Total # of errors: %i, %s.',
                    doc.coordinates, e, self.errors[doc.coordinates], action,
                    exc_info=isinstance(e, Exception))

    def _on_conflict(self, doc: Document, e: Union[Exception, JSON]):
        self.conflicts[doc.coordinates] += 1
        self.errors.pop(doc.coordinates, None)  # a conflict resets the error count
        if self.conflict_retry_limit is None or self.conflicts[doc.coordinates] <= self.conflict_retry_limit:
            action = 'retrying'
            self.retries.add(doc.coordinates)
        else:
            action = 'giving up'
        if doc.version_type is VersionType.create_only:
            log.warning('Writing document %r requires overwrite. Possible causes include duplicate notifications '
                        'or reindexing without clearing the index.', doc.coordinates)
            # Try again but allow overwriting
            doc.version_type = VersionType.none
        else:
            log.warning('There was a conflict with document %r: %r. Total # of errors: %i, %s.',
                        doc.coordinates, e, self.conflicts[doc.coordinates], action)

    def raise_on_errors(self):
        if self.errors or self.conflicts:
            log.warning('Failures: %r', self.errors)
            log.warning('Conflicts: %r', self.conflicts)
            raise RuntimeError('Failed to index documents. Failures: %i, conflicts: %i.' %
                               (len(self.errors), len(self.conflicts)))

class EventualConsistencyException(RuntimeError):
    pass


import turtle
import math

def square(turt, length):
    """
    Draws a square with the given side length. turt is a turtle.
    """
    for i in range(4):
        turt.fd(length)
        turt.lt(90)
    turtle.mainloop()

def polygon(turt, length, n):
    """
    Draws n-sided polygon with the given side length. turt is a turtle.
    """
    for i in range(n):
        turt.fd(length)
        turt.lt(360/n)
    turtle.mainloop()

def circle(turt, r):
    """
    Draws a circle with radius r. turt is a turtle.
    """
    n = 360
    length = (2 * math.pi * r) / n
    polygon(turt, length, n)

def arc(turt, r, angle):
    """
    Draws an angle-length arc with radius r. turt is a turtle.
    """
    length = (2 * math.pi * r) / 360
    for i in range(angle):
        turt.fd(length)
        turt.lt(1)
    turtle.mainloop()

bob = turtle.Turtle()
arc(bob, 200, 270)


'''
Use these codes to view datasets.
'''

import os, sys
from argparse import ArgumentParser

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

from skimage.restoration import unwrap_phase

def make_segmented_cmap(wrap=0):
    white = '#ffffff'
    black = '#000000'
    red = '#ff0000'
    blue = '#0000ff'
    if isinstance(wrap, int):
        if wrap == 0:
            wrap = None
        else:
            wrap = (wrap, wrap)
    if wrap is not None:
        mapind = [white, red, black, blue] * (wrap[0] // 2) + [white]
        if wrap[0] % 2 != 0:
            mapind = [black, blue] + mapind
        mapind = mapind + [red, black, blue, white] * (wrap[1] // 2)
        if wrap[1] % 2 != 0:
            mapind = mapind + [red, black]
        N = 256*(wrap[1] + wrap[0])
    else:
        mapind = [black, blue, white, red, black]
        N = 256
    anglemap = mpl.colors.LinearSegmentedColormap.from_list(
        'anglemap', mapind, N=N, gamma=1)
    return anglemap

def draw_colorbar(fig, ax, im):
    divider = make_axes_locatable(ax)
    cax = divider.append_axes('right', size='8%', pad=0.08)
    fig.colorbar(im, cax=cax, orientation='vertical')

class Loader:

    def __init__(self):
        self.configs = {
            'num_shot': 56,
            'num_recv': 112,
            'num_time': 2500,
            'nyquist': 500
        }

    def get_one_shot(self, dset_name, n_shot):
        dset_name = os.path.splitext(dset_name)[0] + '.BIN'
        num_recv, num_time = self.configs['num_recv'], self.configs['num_time']
        with open(dset_name, 'rb') as f:
            f.seek(n_shot*num_recv*num_time*4, os.SEEK_SET)
            data_shot = f.read(num_recv*num_time*4)
            data_shot = np.frombuffer(data_shot, dtype=np.float32)
            data_shot = np.reshape(data_shot, (num_recv, num_time))
            data_shot = np.transpose(data_shot)
        return data_shot

    def get_one_trace(self, dset_name, n_shot, n_recv):
        dset_name = os.path.splitext(dset_name)[0] + '.BIN'
        num_recv, num_time = self.configs['num_recv'], self.configs['num_time']
        with open(dset_name, 'rb') as f:
            f.seek((n_shot*num_recv + n_recv)*num_time*4, os.SEEK_SET)
            data = f.read(num_time*4)
            data = np.frombuffer(data, dtype=np.float32)
        return data

    def get_phase(self, dset_name, freq=3.0):
        num_shot, num_time = self.configs['num_shot'], self.configs['num_time']
        n_f = np.nonzero(np.fft.rfftfreq(n=num_time, d=1/self.configs['nyquist']) > freq)[0][0]
        data_phase = []
        for s in range(num_shot):
            data = self.get_one_shot(dset_name, s)
            data = np.fft.rfft(data, axis=0)
            data = np.angle(data[n_f, ...])
            data_phase.append(data)
        data_phase = np.stack(data_phase, axis=0)
        return data_phase

class Drawer(Loader):

    def draw_shot_view(self, dpath, dpath_true=None, shot_num=25):
        if dpath_true is not None:
            fig, axes = plt.subplots(1, 3, sharex=True, sharey=True)

            data = self.get_one_shot(dpath, shot_num)
            max_v = np.percentile(np.abs(data), 99)
            norm = mpl.colors.Normalize(vmin=-max_v, vmax=max_v, clip=True)
            im = axes[0].imshow(data, aspect='auto', norm=norm, cmap='Greys')
            axes[0].set_title('Prediction'), axes[0].set_xlabel('receiver'), axes[0].set_ylabel('time')
            draw_colorbar(fig, axes[0], im)

            data_true = self.get_one_shot(dpath_true, shot_num)
            max_v = np.percentile(np.abs(data_true), 99)
            norm = mpl.colors.Normalize(vmin=-max_v, vmax=max_v, clip=True)
            im = axes[1].imshow(data_true, aspect='auto', norm=norm, cmap='Greys')
            axes[1].set_title('Ground truth'), axes[1].set_xlabel('receiver')
            draw_colorbar(fig, axes[1], im)

            data_res = data - data_true
            max_v = max(1.0, np.percentile(np.abs(data_res), 99))
            norm = mpl.colors.Normalize(vmin=-max_v, vmax=max_v, clip=True)
            im = axes[2].imshow(data_res, aspect='auto', norm=norm, cmap='Greys')
            axes[2].set_title('Residual'), axes[2].set_xlabel('receiver')
            draw_colorbar(fig, axes[2], im)
        else:
            n = 3
            fig, axes = plt.subplots(1, n, sharex=True, sharey=True)
            n_list = np.sort(np.random.RandomState(1000).randint(0, self.configs['num_shot'], size=n))
            for i, n_shot in enumerate(n_list):
                data = self.get_one_shot(dpath, n_shot)
                max_v = np.percentile(np.abs(data), 99)
                norm = mpl.colors.Normalize(vmin=-max_v, vmax=max_v, clip=True)
                im = axes[i].imshow(data, aspect='auto', norm=norm, cmap='Greys')
                axes[i].set_title('Shot {0}'.format(n_shot)), axes[i].set_xlabel('receiver')
                draw_colorbar(fig, axes[i], im)
                if i == 0:
                    axes[i].set_ylabel('time')
        plt.gcf().set_size_inches([10.0, 5.0])
        plt.tight_layout()
        plt.show()

    def draw_traces_view(self, dpath, dpath_true=None, t_range=(0, None)):
        n = 5
        with_truth = dpath_true is not None
        t_range = (0 if t_range[0] is None else t_range[0], self.configs['num_time'] if t_range[1] is None else t_range[1])
        fig, axes = plt.subplots(1, n, sharex=True, sharey=True)
        st = np.random.RandomState(1000)
        n_shot_list = np.sort(st.randint(0, self.configs['num_shot'], size=n))
        n_recv_list = st.randint(0, self.configs['num_recv'], size=n)
        time_axis = np.arange(*t_range)
        for i, (n_shot, n_recv) in enumerate(zip(n_shot_list, n_recv_list)):
            data = self.get_one_trace(dpath, n_shot, n_recv)
            axes[i].plot(data[t_range[0]:t_range[1]], time_axis, label='Prediction')
            if with_truth:
                data = self.get_one_trace(dpath_true, n_shot, n_recv)
                axes[i].plot(data[t_range[0]:t_range[1]], time_axis, label='Ground truth')
            axes[i].set_title('Trace ({0}, {1})'.format(n_shot, n_recv))
            axes[i].invert_yaxis()
            if i == 0:
                axes[i].set_ylabel('time')
                if with_truth:
                    plt.figlegend(*axes[i].get_legend_handles_labels(), ncol=2, loc='lower center')
        plt.gcf().set_size_inches([9.0, 5.0])
        plt.tight_layout(rect=[0.0, 0.05, 1.0, 1.0])
        plt.show()

    @staticmethod
    def _draw_im_wcolor(fig, ax, im):
        divider = make_axes_locatable(ax)
        cax = divider.append_axes('right', size='8%', pad=0.08)
        fig.colorbar(im, cax=cax, orientation='vertical')

    @staticmethod
    def _draw_phase_im_unwrap(data_phase, fig, ax):
        data_phase = unwrap_phase(data_phase, wrap_around=False)
        wrap = (int(np.ceil(-np.amin(data_phase)/np.pi)), int(np.ceil(np.amax(data_phase)/np.pi)))
        ax.imshow(data_phase, cmap=make_segmented_cmap(wrap=wrap), vmin=-wrap[0]*np.pi, vmax=wrap[1]*np.pi,
            interpolation='bilinear', aspect='auto')
        divider = make_axes_locatable(ax)
        cax = divider.append_axes('right', size='8%', pad=0.08)
        fig.colorbar(mappable=mpl.cm.ScalarMappable(norm=mpl.colors.Normalize(vmin=-np.pi, vmax=np.pi, clip=False), cmap=make_segmented_cmap(wrap=0)), cax=cax, ax=ax)

    @staticmethod
    def _draw_phase_im_plain(data_phase, fig, ax, residual=False):
        max_v = max(1.0, np.percentile(np.abs(data_phase), 99))
        norm = mpl.colors.Normalize(vmin=(-max_v if not residual else 0.0), vmax=max_v, clip=True)
        im = ax.imshow(data_phase, aspect='auto', norm=norm, cmap='viridis', interpolation='bilinear')
        draw_colorbar(fig, ax, im)

    @classmethod
    def _draw_phase_im(cls, data_phase, fig, ax):
        cls._draw_phase_im_plain(data_phase, fig, ax)

    def draw_phase_view(self, dpath, dpath_true=None, freq=3.0):
        if dpath_true is not None:
            fig, axes = plt.subplots(1, 3, sharex=True, sharey=True)

            data = self.get_phase(dpath, freq=freq)
            self._draw_phase_im(data, fig, axes[0])
            axes[0].set_title('Prediction'), axes[0].set_xlabel('receiver'), axes[0].set_ylabel('shot')
            #self._draw_im_wcolor(fig, axes[0], im)

            data_true = self.get_phase(dpath_true, freq=freq)
            self._draw_phase_im(data_true, fig, axes[1])
            axes[1].set_title('Ground truth'), axes[1].set_xlabel('receiver')

            data_res = np.abs(data - data_true)
            data_res = np.minimum(np.minimum(data_res, np.abs(data_res - 2*np.pi)), np.abs(data_res + 2*np.pi))
            self._draw_phase_im_plain(data_res, fig, axes[2], residual=True)
            axes[2].set_title('Residual'), axes[2].set_xlabel('receiver')
            plt.gcf().set_size_inches([9.0, 5.0])
        else:
            fig, ax = plt.subplots(1, 1, sharex=True, sharey=True)
            data = self.get_phase(dpath, freq=freq)
            self._draw_phase_im(data, fig, ax)
            ax.set_xlabel('receiver'), ax.set_ylabel('shot')
            plt.gcf().set_size_inches([4.0, 5.0])
        plt.tight_layout()
        plt.show()

if __name__ == '__main__':

    parser = ArgumentParser()

    parser.add_argument('-mode',
                        help='Mode for showing datasets. Could be "shot", "phase", or "trace"')
    parser.add_argument('-setpath',
                        help='Paths for the dataset.')
    parser.add_argument('-trueset',
                        help='Path for the true set. If given, would make comparison.')
    parser.add_argument('-shotnum', type=int, default=25,
                        help='Shot number when setting the -trueset for -mode shot.')
    args = parser.parse_args()

    ld = Drawer() # Set up the loader.

    if args.mode == 'shot':
        ld.draw_shot_view(args.setpath, args.trueset, shot_num=args.shotnum)
    elif args.mode == 'phase':
        ld.draw_phase_view(args.setpath, args.trueset, freq=3.0)
    elif args.mode == 'trace':
        ld.draw_traces_view(args.setpath, args.trueset, t_range=(0,None))


# https://leetcode.com/problems/shortest-unsorted-continuous-subarray/
# T: O(n)
# S: O(1)

class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        length = len(nums)
        i, j = 0, length - 1

        while i < length - 1 and nums[i] <= nums[i + 1]:
            i += 1
        while j > 0 and nums[j] >= nums[j - 1]:
            j -= 1

        min_val, max_val= 2 ** 31, - (2 ** 31)
        for k in range(i, j + 1):
            min_val = min(nums[k], min_val)
            max_val = max(nums[k], max_val)
        while i >= 0 and min_val < nums[i]:
            i -= 1
        while j < length and max_val > nums[j]:
            j += 1
        # i + 1 ~ j - 1
        return max(j - i - 1, 0)


t = int(input())
answer = []
for a in range(t):
    n = int(input())
    count = [0 for i in range(26)]
    for j in range(n):
        line = list(input())
        for k in line:
            count[ord(k)-97] += 1
        ans = True
    for k in count:
        if(k%n != 0):
            ans = False
            break
    if(ans):
        answer.append("YES")
    else:
        answer.append("NO")
for b in answer:
    print(b)


def text_to_binary(text):
    binary = ""
    for char in text:
        # Convert each character to its ASCII value
        ascii_value = ord(char)

        # Convert the ASCII value to binary and append it to the result
        binary += bin(ascii_value)[2:].zfill(8)

    return binary

# Example usage
text = "عاشت ايدك ربي يجازيك ع فعل الخير"
binary_text = text_to_binary(text)
print(binary_text)


import random
import copy

SCORE = [0, 0, 0]

def play_again():
    """
    게임 재시도 여부를 질문
    :return: 재시도하지 않는 경우 True
    """
    print("한 판 더?[Y/N]\n", end=">>> ")
    ans = input().upper()
    while ans != "Y" and ans != "N":  # 다른 답변을 입력한 경우
        print("한 판 더 할거냐고;;;\n", end=">>> ")
        ans = input().upper()
    if ans == "N":
        return True

def choose_OX():
    """
    사용자가 사용할 문자를 선택하는 함수
    :return: O/X 중 사용자가 선택한 문자
    """
    print("O/X 중에서 선택하세요. X가 먼저 시작합니다.\n", end=">>> ")
    char = input().upper()
    while char != "O" and char != "X":  # O/X가 아닌 값을 입력한 경우
        print("O.X. 중에서 선택하라고;;;\n", end=">>> ")
        char = input().upper()
    return char

def show_board(map_list):
    """
    사용자에게 게임판 보여주기
    :param map_list: 게임판을 저장한 list
    """
    print(map_list[1] + ' | ' + map_list[2] + ' | ' + map_list[3])
    print(map_list[4] + ' | ' + map_list[5] + ' | ' + map_list[6])
    print(map_list[7] + ' | ' + map_list[8] + ' | ' + map_list[9])

def player_choose(map_list):
    """
    사용자가 빈칸 중 하나 선택.
    :param map_list: 현재 게임판 상태
    :return: 사용자가 선택한 칸
    """
    show_board(map_list)
    print("빈칸 중 하나를 선택하세요\n", end=">>> ")
    site = input()
    while site not in map_list:  # 빈칸을 선택하지 않은 경우
        print("빈.칸. 중에서 하나 선택하라고;;;\n", end=">>> ")
        site = input()
    return int(site)

def board_check(map_list):
    """
    게임판에 우승자가 있는지 확인해보자
    :param map_list: 현재 게임판 상태
    :return: 우승자 있는 경우 우승한 문자를 return
    """
    if map_list[1] == map_list[2] and map_list[2] == map_list[3]:
        return map_list[1]
    elif map_list[4] == map_list[5] and map_list[5] == map_list[6]:
        return map_list[4]
    elif map_list[7] == map_list[8] and map_list[8] == map_list[9]:
        return map_list[7]
    elif map_list[1] == map_list[4] and map_list[4] == map_list[7]:
        return map_list[1]
    elif map_list[2] == map_list[5] and map_list[5] == map_list[8]:
        return map_list[2]
    elif map_list[3] == map_list[6] and map_list[6] == map_list[9]:
        return map_list[3]
    elif map_list[1] == map_list[5] and map_list[5] == map_list[9]:
        return map_list[1]
    elif map_list[3] == map_list[5] and map_list[5] == map_list[7]:
        return map_list[3]

def record_score(winner, player, computer):
    """
    사용자의 승/무/패를 기록하자
    :param winner: 승리한 문자(O/X)
    :param player: 사용자의 문자
    :param computer: 컴퓨터의 문자
    """
    if winner == player:
        SCORE[0] += 1
    elif winner == computer:
        SCORE[2] += 1
    else:
        SCORE[1] += 1

def com_choose(map_list, player):
    """
    컴퓨터가 고를 칸을 선택한다.
    :param map_list: 현재 게임판의 상태
    :param player: 사용자의 문자
    :return: 컴퓨터가 선택한 칸의 숫자, 빈칸이 없는 경우 0
    """
    possible_site = []  # 입력 가능한 자리
    for i in [1, 2, 3, 4, 5, 6, 7, 8, 9]:
        if map_list[i] != "O" and map_list[i] != "X":
            possible_site.append(i)
    for i in possible_site:  # 입력 가능한 자리 중에서 사용자를 방어할 수 있는 자리
        fake_map = copy.copy(map_list)
        fake_map[i] = player
        if board_check(fake_map) == player:
            return i
    if len(possible_site) != 0:  # 방어할 필요 없는 경우에는 랜덤
        return random.choice(possible_site)

while True:
    Game_Board = [' ', '1', '2', '3', '4', '5', '6', '7', '8', '9']
    Player = choose_OX()  # 사용자의 문자
    if Player == "X":
        Computer = "O"  # 컴퓨터의 문자
        turn = 0  # 0이면 사용자 차례, 1이면 컴퓨터 차례
    else:
        Computer = "X"
        turn = 1
    time = 9  # 게임을 주고받는 횟수, 0이 되면 게임을 무조건 종료

    while True:
        if turn == 0:  # 사용자 차례
            pick = player_choose(Game_Board)  # 사용자가 선택한 위치
            Game_Board[pick] = Player  # 선택한 위치에 사용자의 문자 입력
            time -= 1
            if board_check(Game_Board) == Player:  # 사용자가 승리한 경우
                record_score(Player, Player, Computer)
                show_board(Game_Board)
                print("승리!!!")
                print("%d승 %d무 %d 패" % (SCORE[0], SCORE[1], SCORE[2]))
                break
            elif time == 0:  # 무승부인 경우
                record_score(' ', Player, Computer)
                show_board(Game_Board)
                print("무승부!!!")
                print("%d승 %d무 %d 패" % (SCORE[0], SCORE[1], SCORE[2]))
                break
            else:
                turn = 1  # 컴퓨터의 차례

        else:
            pick2 = com_choose(Game_Board, Player)  # 컴퓨터가 선택한 위치
            Game_Board[pick2] = Computer  # 선택한 위치에 컴퓨터의 문자 입력
            time -= 1
            if board_check(Game_Board) == Computer:  # 컴퓨터가 승리한 경우
                record_score(Computer, Player, Computer)
                show_board(Game_Board)
                print("패배!!!")
                print("%d승 %d무 %d 패" % (SCORE[0], SCORE[1], SCORE[2]))
                break
            elif time == 0:  # 무승부인 경우
                record_score(' ', Player, Computer)
                show_board(Game_Board)
                print("무승부!!!")
                print("%d승 %d무 %d 패" % (SCORE[0], SCORE[1], SCORE[2]))
                break
            else:
                turn = 0  # 사용자의 차례

    if play_again():  # 게임을 재도전하지 않는 경우
        break

print("Bye~!")


"""
URL configuration for estoque project.

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from app import views
from django.contrib.staticfiles.urls import staticfiles_urlpatterns

urlpatterns = [
    path('admin/', admin.site.urls),
    # Home
    path('', views.home, name="home"),

    # Adicionar Produtos
    path('adicionar', views.adicionar, name="adicionar"),

    # Ver Produto Individualmente
    path('produto/<str:id>', views.ver_produto, name="ver_produto"),

    # Editar Produto
    path('editar', views.editar_produto, name="editar"),

    # Deletar Produto
    path('deletar/<str:id>', views.deletar_produto, name="deletar"),

    # Login
    path('login', views.loginUser, name="login"),

    # Criar Conta
    path('register', views.registerUser, name="register"),

    # Logout
    path('logout', views.logoutUser, name='logout'),

]

urlpatterns += staticfiles_urlpatterns()


from unittest import TestCase
from ..distance import relative_dtw
import numpy as np

class TestRelative_dtw(TestCase):

    def test_relative_dtw(self):
        "Given"
        x = np.array([1.2, 1.18, 1.95, 2.09])
        y = np.array([1.2, 1.18, 1.95, 2.09])

        "When"
        similarity = relative_dtw(x, y)

        "Then"
        self.assertEqual(similarity, 1.0)


import argparse
import subprocess
import os
import commands
import sys

from lib.resource import load_template
from lib.selinux import Sepolicy, user_selinux_context
from selinux_te_tester import te_file
from lib.process import execute_and_read_lines, silent_execute

import string
import random
import datetime

def load_data(path):
  with open(path) as f:
    return [ line.strip() for line in f.readlines()]

def file_name(n=10):
  c = string.ascii_lowercase + string.ascii_uppercase + string.digits
  number = ''.join([random.choice(c) for i in range(n)])
  now = datetime.datetime.now()
  return "{0:%Y%m%d%H%M%S%f}_{1}".format(now, number)

def list_path(data):
  for path in data:
    yield path

if __name__ == "__main__":

  parser = argparse.ArgumentParser(description='SELinux TE Destroy Tester.')
  parser.add_argument('--disabled-uninstall-policy', action='store_true',
                       help='Disabled to uninstall the policy')
  parser.add_argument('domain', help='SELinux domain applied to the test process.')
  parser.add_argument('config', help='Config file.')
  args = parser.parse_args()

  target_domain = args.domain
  config_path = args.config

  DATA = load_data(config_path)

  module_dir = "module"
  module_name = "te-tester-write"
  work_dir = "work"
  policy = Sepolicy(module_name)
  policy.set_disabled_uninstall(args.disabled_uninstall_policy)

  _, user_role, user_domain, _ = user_selinux_context()

  if not os.path.isdir(module_dir):
    os.mkdir(module_dir)

  if not os.path.isdir(work_dir):
    os.mkdir(work_dir)

  map = {}
  for path in list_path(DATA):
    cmd = "ls -Z {0}".format(path)
    output = commands.getoutput(cmd)
    label = output.split(" ")[3]
    type = label.split(":")[2]
    dummy_file_name = file_name()
    dummy_path = os.path.abspath(os.path.join(work_dir, dummy_file_name))
    policy.append_fc_with(dummy_path, type)
    with open(dummy_path, "w") as f:
      f.write("Dummy File")
    map[path] = dummy_path

  te_content = te_file(module_name, user_role, user_domain, target_domain)
  policy.append_te(te_content)

  cmd_path = "script/destroy.py"
  cmd_path = os.path.abspath(cmd_path)
  policy.append_fc_with(cmd_path, "{}_exec_t".format(module_name))
  policy.append_fc_with(os.path.abspath("script/access.py"),
                            "{}_config_t".format(module_name))
  with policy.install_customize_policy(module_dir, user_domain):
    for path in list_path(DATA):
      dummy_path = map[path]
      for line in execute_and_read_lines("./script/destroy.py {0} {1}".format(dummy_path, path)):
        sys.stdout.write(line)
      #subprocess.call("./script/destroy.py {0} {1}".format(dummy_path, path), shell=True)

  for path in list_path(DATA):
    dummy_path = map[path]
    if os.path.isfile(dummy_path):
      silent_execute(["chcon", "-t", "user_tmp_t", dummy_path])
      os.remove(dummy_path)

  if args.disabled_uninstall_policy:
    sys.stderr.write("[WARNING]The policy module hasn't be uninstalled. You MUST run 'semodule -r {0}'.\n".format(module_name) )


import time
import requests
import json

crontable = []
outputs = []

def check_query(arg):
    if len(arg) == 40:
        return arg
    elif len(arg) == 32:
        return arg
    else:
        return 'error1'

def get_shadow_data(query):
    base_url = 'http://innocuous.shadowserver.org/api/?query=%s'
    refined_url = base_url % query
    response = requests.get(refined_url)
    return response

def make_json(response):
    if '! No match found for' in response:
        return response
    else:
        list1 = response.split('\n')
        file_info1 = list1[0]
        file_info_list = file_info1.split(',')
        file_info = "*md5:* %s\n*sha1:* %s\n*First Seen:* %s\n*Last Seen:* %s\n*FileType:* %s\n*ssdeep:* %s\n" % (file_info_list[0], file_info_list[1], file_info_list[2], file_info_list[3], file_info_list[4], file_info_list[-1])
        json_string = list1[1]
        json_data = json.loads(json_string.encode('utf-8'))
        av_engine_list = []
        signature_list = []
        for k, v in json_data.iteritems():
            av_engine_list.append(k)
            signature_list.append(v)
        av_list = []
        length = len(av_engine_list)
        for x in range(0, length):
            a = av_engine_list[x]
            b = signature_list[x]
            string_vals = "%s: %s\n" % (a, b)
            av_list.append(string_vals)
        av_string = ''.join(av_list)
        shadow_results = "%s\n----------------------------------------\n*AV Hits:*\n%s" % (file_info, av_string)
        return shadow_results

def process_message(data):
    channel = data["channel"]
    text = data["text"]
    string = text.lower()
    alist = string.split(' ')
    if alist[0] == '!shadow':
        time.sleep(1)
        hash1 = alist[1]
        query1 = check_query(hash1)
        if query1 == 'error1':
            outputs.append([channel, 'please submit md5 or sha1'])
        else:
            response = get_shadow_data(query1)
            shadow_results = make_json(response.content)
            outputs.append([channel, shadow_results])


# URI 1018 em Python 3.9
# Programador: Matheus Felipe Alves Durães
# Não copie códigos, apenas leia-os e
# tente entender O QUE e POR QUE fazem o que fazem.

def mainSIMPLES():
    # Variavel dinheiro recebe o valor inteiro a ser processado
    dinheiro = int(input())

    # Imprimos o valor conforme o exercicio pede
    print(dinheiro)

    # Variavel temporaria para pegar o troco baseado na divisão inteira
    # da variavel dinheiro pela nota que queremos de troco
    temp = dinheiro//100

    # Em sequencia precismos reduzir do montante de dinheiro o troco que pegamos
    dinheiro = dinheiro - (temp*100)

    # E então imprimimos o troco
    print("%i nota(s) de R$ 100,00" %(temp) )

    # Agora repetimos o mesmo passo somente alterando os valores
    # Por isso vou condensar e deixar agrupado por montante

    # Para o troco de R$50.00
    temp = dinheiro//50
    dinheiro = dinheiro - (temp*50)
    print("%i nota(s) de R$ 50,00" %(temp) )

    # Para o troco de R$20.00
    temp = dinheiro//20
    dinheiro = dinheiro - (temp*20)
    print("%i nota(s) de R$ 20,00" %(temp) )

    # Para o troco de R$10.00
    temp = dinheiro//10
    dinheiro = dinheiro - (temp*10)
    print("%i nota(s) de R$ 10,00" %(temp) )

    # Para o troco de R$5.00
    temp = dinheiro//5
    dinheiro = dinheiro - (temp*5)
    print("%i nota(s) de R$ 5,00" %(temp) )

    # Para o troco de R$2.00
    temp = dinheiro//2
    dinheiro = dinheiro - (temp*2)
    print("%i nota(s) de R$ 2,00" %(temp) )

    # Para o troco de R$1.00 é somente printar o resultado final
    print("%i nota(s) de R$ 1,00" %(dinheiro) )

mainSIMPLES()

# Abaixo está uma solução um pouco mais complexa porém mais eficaz
# A solução abaixo contêm LISTA e FOR

def mainFOR():
    # Variavel dinheiro recebe o valor inteiro a ser processado
    dinheiro = int(input())

    # Lista com os valores que usaremos no for para os calculos
    lista_de_valores = [100, 50, 20, 10, 5, 2, 1]

    # Imprimos o valor conforme o exercicio pede
    print(dinheiro)

    for c in range(7):
        # Primeiro pegamos o valor do vetor para calcular o restante
        valor = lista_de_valores[c]

        # Após pegarmos o valor fazemos o calculo, assim como faziamos na forma simples
        temp = dinheiro//valor

        # Em seguida diminuimos do montante de dinheiro
        dinheiro = dinheiro - (temp * valor)

        # Então printamos o resultado, juntamente ao valor do vetor
        # baseado no iteravel do for ou seja o "c"
        print("%i nota(s) de R$ %i,00" %(temp, valor) )

mainFOR()


from django.utils.cache import patch_vary_headers
from django.utils import translation
from djoe.base.backends import oe_session
from django.conf import settings

class LocaleMiddleware(object):
    """
    Copy of django.locale middleware
    """

    def _get_lang_code(self, request):
        full_path = request.get_full_path()
        w_path = full_path[1:].split('/', 1)
        request.PATH_LANG = ''
        request.PATH_WITHOUT_LANG = ''
        language = settings.LANGUAGE_CODE
        request.LANGUAGE_ID = None

        if len(w_path[0]) == 2:
            try:
                lang = oe_session.get_model('res.lang').objects.get(iso_code=w_path[0])
            except:
                pass
            else:
                language = lang.code
                request.PATH_LANG = w_path[0]
                request.LANGUAGE_ID = lang.id
            if len(w_path) == 2:
                request.PATH_WITHOUT_LANG = w_path[1]
        else:
            request.PATH_WITHOUT_LANG = full_path
        if oe_session._default_context is None:
            oe_session._default_context = {}
        oe_session._default_context.update(lang=language)
        return language

    def process_request(self, request):
        language = self._get_lang_code(request)
        translation.activate(language)
        request.LANGUAGE_CODE = translation.get_language()

    def process_response(self, request, response):
        patch_vary_headers(response, ('Accept-Language',))
        if 'Content-Language' not in response:
            response['Content-Language'] = translation.get_language()
        translation.deactivate()
        return response