import numpy as np
import healpy as hp
import matplotlib.pylab as plt
import matplotlib

plt.rcParams.update({'axes.labelsize': 'x-large'})
plt.rcParams.update({'axes.titlesize': 'x-large'})
plt.rcParams.update({'xtick.labelsize': 'large', 'ytick.labelsize': 'large'})

# Just make a few example plots for the document
filterName = 'R'
twi = np.load('TwilightMaps/twiMaps_'+filterName+'.npz')

sunAlts = twi['sunAlts'].copy()
magMaps = twi['magMap'].copy()
rmsMaps = twi['rmsMap'].copy()

nside = hp.npix2nside(magMaps[:, 0].size)
npix = magMaps[:, 0].size
hpid = np.arange(magMaps[:, 0].size)

lat, az = hp.pix2ang(nside, np.arange(npix))
alt = np.pi/2.-lat
airmass = 1./np.cos(np.pi/2.-alt)

useAlts = [-12.5, -14, -16.5, -18.]

# Make the masked data white
cmap0 = matplotlib.cm.jet
newcm = matplotlib.colors.LinearSegmentedColormap('newcm', cmap0._segmentdata, cmap0.N)
newcm.set_over(newcm(1.0))
newcm.set_under('w')
newcm.set_bad('w')

for i, alt in enumerate(useAlts):
    fig = plt.figure(1)
    good = np.where(sunAlts == np.radians(alt))[0]
    toShow = magMaps[:, good[0]]
    toShow[np.where((airmass < 1) | (airmass > 10))] = hp.UNSEEN
    hp.mollview(toShow, rot=(0, 90),
                title=' Sun Alt = %.1f deg' % alt, fig=1, min=4.5, max=9.5,
                unit='%s mags' % filterName, sub=(2, 2, i+1), cmap=newcm)

# fig.tight_layout()
fig.savefig('Plots/twiExamples.pdf')
plt.close(fig)


from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from time import sleep
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.edge.service import Service

from bs4 import BeautifulSoup
import os
import datetime

current_time = datetime.datetime.now()
# current_time = datetime.datetime(2023, 7, 1)
time = str(current_time.month) + "-" + str(current_time.year)
month_time = str(current_time.month)
# print(month_time)
print(str(current_time.month) + "-" + str(current_time.year))

path = "//172.23.3.44/public/Energy/" + time
month = ""

if month_time == "1":
    month = 'มกราคม'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "2":
    month = 'กุมภาพันธ์'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "3":
    month = 'มีนาคม'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "4":
    month = 'เมษายน'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "5":
    month = 'พฤษภาคม'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "6":
    month = 'มิถุนายน'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "7":
    month = 'กรกฎาคม'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "8":
    month = 'สิงหาคม'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "9":
    month = 'กันยายน '
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "10":
    month = 'ตุลาคม'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "11":
    month = 'พฤศจิกายน'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)
elif month_time == "12":
    month = 'ธันวาคม'
    try:
        os.mkdir(path)
        print("Folder %s created!" % path)
    except FileExistsError:
        print("Folder %s already exists" % path)

if __name__ == "__main__":
    edgeService = Service(r"msedgedriver.exe")
    browser = webdriver.Edge(service=edgeService)
    # Simply just open a new Edge browser and go to lambdatest.com
    browser.maximize_window()
    browser.get("https://www.amr.pea.co.th/AMRWEB/Index.aspx")
    wait = WebDriverWait(browser, 10)
    try:
        myElem_1 = WebDriverWait(browser, 10).until(
            EC.presence_of_element_located((By.ID, "txtUserName"))
        )
        myElem_1.send_keys("020025150027")
        myElem_1.click()
        myElem_2 = WebDriverWait(browser, 10).until(
            EC.presence_of_element_located((By.ID, "txtPassword"))
        )
        myElem_2.send_keys("denso1234")
        myElem_2.click()
        myElem_3 = (
            WebDriverWait(browser, 10)
            .until(
                EC.element_to_be_clickable(
                    (By.ID, "btnOK")
                )
            )
            .click()
        )
        sleep(3)
        myElem_4 = (
            WebDriverWait(browser, 10)
            .until(
                EC.element_to_be_clickable(
                    (By.XPATH, "//*[contains(text(), 'โหลดโปรไฟล์')]")
                )
            )
            .click()
        )
        sleep(3)
        myElem_5 = (
            WebDriverWait(browser, 10)
            .until(
                EC.element_to_be_clickable(
                    (By.XPATH, "//div[@id='divMenu3']/div[@class='menusub']/span[contains(text(), 'รายเดือน')]")
                )
            )
            .click()
        )
        radio_button = browser.find_element(By.XPATH, "//div[@id='divMenu3']/div[@class='menusub']/span[contains(text(), 'รายเดือน')]")
        # print(radio_button.text)
        soup = BeautifulSoup(browser.page_source, "lxml")
        # print(soup)
        sleep(30)
        print("Completed!")
        browser.close()
    except Exception as error:
        print("An exception occurred:", type(error).__name__)
    sleep(50)
    browser.close()


import serial
import array

class SerialPort (serial.Serial):

    def __init__(self):
        serial.Serial.__init__(self)

        settings = self.getSettingsDict()
        self.applySettingsDict(settings)
        self.baudrate = 115200
        self.port = "COM9"

        pass

    def calculate_crc(self, data):
        crc = 0
        for x in data:
            crc += x

        return crc

    def transmit_binary(self, data):
        #
        # http://stackoverflow.com/questions/472977/binary-data-with-pyserialpython-serial-port
        #

        transmit = array.array('B', data).tostring()
        print(transmit)
        self.write(transmit)

    def send_ping(self):
        packet = [0x0C, 0x03, 0xF0, 0xAA, 0x00]
        print(packet)
        crc = self.calculate_crc(packet)
        crc = crc.to_bytes(2, byteorder='big')
        print(crc)
        for x in crc:
            print(x)
            packet.append(x)
        packet.append(0x0D)
        print(packet)
        self.transmit_binary(packet)

    def character(self, b):
        return b.decode('latin1')

    def send_help(self):
        packet = [0x68, 0x65, 0x6C, 0x70, 0x0D]
        self.transmit_binary(packet)
        while (1):
            data = self.character(self.read(1))
            print(data)


"""add BackTestTrade

Revision ID: af41b751b50f
Revises: d194e8be4f48
Create Date: 2022-01-16 03:16:51.583115

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'af41b751b50f'
down_revision = 'd194e8be4f48'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('beck_test_trades',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('symbol', sa.String(), nullable=False),
    sa.Column('buy_time', sa.String(), nullable=False),
    sa.Column('sell_time', sa.String(), nullable=False),
    sa.Column('profit', sa.Float(), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    op.alter_column('trades', 'createdAt', existing_type=sa.Integer(), type_=sa.BigInteger())
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('beck_test_trades')
    op.alter_column('trades', 'createdAt', existing_type=sa.BigInteger(), type_=sa.Integer())
    # ### end Alembic commands ###


def printData(num):
        if (num%2 == 0):
                data = '*' #we take a variable with a value
                num = num * 2 # whatever the highest value we want to print we double the value so that we have a mid point to roll back the loop
                for i in range(1, num+1): #next we run the loop from 1 because the inner loop will not iterate on 0
                        if (i <= int(num/2)): #now we check whether we have reached the mid point or not if not then
                                j = 0 #we create another loop where we start printing in each row
                                while (j < i): # the first iteration will print only one stars, the next will print two stars and the next will print 3 stars and so on so forth
                                        print(data, end=" ")
                                        j += 1
                                print("\n")
                        else:
                                k = 0 #once our mid point crosses we have to run the loop in reverse order that is every time the loop should iterate -1 times for the next loop
                                while(k < (num-i)): #then this prints the loop 3 times then 2 times then 1 times then 0 times
                                        print(data, end=" ")
                                        k += 1
                                print("\n")
        else:
                print("Please provide an even number")
printData(50)


#   Crie um programa que leia nome, ano de nascimento e
#   carteira de trabalho e cadastre-os (com idade) em um dicionário.
#    Se por acaso a CTPS for diferente de 0, o dicionário
#     receberá também o ano de contratação e o salário. Calcule e acrescente ,
#     , com quantos anos a pessoa vai se aposentar.
#     Considere que o trabalhador deve contribuir por 35 anos para se aposentar.
dados=dict()
dados['nome']=str(input('Nome:  '))
nasc=int(input('Ano de nascimento:'))
dados['idade']=2021-nasc
dados['ctps']=int(input('Carteira de trabalho (0 não tem):'))
if dados ['ctps'] !=0:
    dados['contratação']= int(input('Ano de contratação: '))
    dados['salário']=float(input('salário: R$'))
    dados['aposentadoria']=dados['idade']+((dados['contratação']+ 35 )-2021 )
print('-='*30)
print(dados)


from .base import *

import time, datetime

class Drop(SitCommand):
	def set_parameters(self):
		self.minArgs = 0

	def perform_action(self, args):
		db = self.sess.get_db()
		projname = self.sess.require('project')
		taskname = self.sess.require('task')
		username = self.sess.require('user')

		print("No implementation yet")

class Main(CommandFactory):
	def make_action(self, sess):
		action = Drop(
			"drop", sess
		)
		return action


s = input()
n = int(input())
length = 0
for i in s:
    if i != '*' and i != '?':
        length += 1

if length > n and s.count('?') + s.count('*') < length - n:
    print('Impossible')
elif length < n and s.count('*') == 0:
    print('Impossible')
else:
    res = []
    for i in range(len(s)):
        if length != n:
            if length > n:
                if s[i] == '?':
                    del(res[-1])
                    length -= 1
                if s[i] == '*':
                    del(res[-1])
                    length -= 1
            else:
                if s[i] == '*':
                    res += [s[i-1]] *  (n - length)
                    length += n - length
        if s[i] != '*' and s[i] != '?':
            res.append(s[i])

    print(''.join(res))


enemy = {
    'loc_x': 70,
    'loc_y': 50,
    'color': 'green',
    'health': 100,
    'name': 'Mudillo',
    'image': ['image1.jpg', 'image2.jpg', 'image3.jpg'],
    'awards': ['Za Stalina', 'Za Lenina']
}

all_enemys = []

for x in range(0, 10):
    all_enemys.append(enemy.copy())
for ene in all_enemys:
    print(ene)

print("-----------------------")

all_enemys[5]['health'] = 30
all_enemys[9]['name'] = 'XXXX'
all_enemys[2]['loc_x'] += 20
for ene in all_enemys:
    print(ene)

# print(enemy)

# print("Location X = " + str(enemy['loc_x']))
# print("Location Y = " + str(enemy['loc_y']))
# print("His name is : " + enemy['name'])

# enemy['rank'] = 'Admiral'

# print(enemy)

# del enemy ['rank']

# print(enemy)

# enemy['loc_x'] = enemy['loc_x'] + 40
# enemy['health'] = enemy['health'] - 30
# if enemy['health'] < 80:
#     enemy['color'] = 'yellow'

# print (enemy)

# print(enemy.keys())
# print(enemy.values())


import re
import logging
from feedoo.abstract_action import AbstractAction
from feedoo.event import Event

# parse a string and return a dict
# dict' keys is defines by tag (?P<name>)

class ParserRegex(AbstractAction):
    def __init__(self, match, regex, key, mode="merge"):
        AbstractAction.__init__(self, match)
        self._regex = regex
        self._names = tuple(re.findall(r"\(\?P<(.+?)>", regex))
        self._key = key
        self._mode = mode
        self._log.info("Create regex parser with '{}', key={}, mode={}".format(regex, key, mode))

    def do(self, event):
        record = dict(event.record)
        to_parse = record.get(self._key)

        if to_parse is None:
            self._log.debug("Failed to parse '{}', key doesn't exist".format(to_parse))
            return

        result = self.match(to_parse)
        if result is None:
            return

        if self._mode == "tree":
            record[self._key] = result
        elif self._mode == "merge":
            del record[self._key]
            record.update(result)
        elif self._mode == "add":
            record.update(result)
        else:
            self._log.error("Bad mode '{}' ! (check the configuration)".format(self._mode))
            raise Exception("Bad mode '{}'".format(self._mode))

        return Event(event.tag, event.timestamp, record)

    def match(self, field):
        matched = re.match(self._regex, field)
        output = dict()

        if not matched:
            self._log.debug("Not matching '{}' and '{}'".format(self._regex, field))
            return

        for k in self._names:
            output[k] = matched.group(k)

        return output

    def update(self):
        pass


"""
File: hangman.py
Name: Jerry Ju
-----------------------------
This program plays hangman game.
Users sees a dashed word, trying to
correctly figure the un-dashed word out
by inputting one character each round.
If the user input is correct, show the
updated word on console. Players have N_TURNS
chances to try and win this game.
"""

import random

# This constant controls the number of guess the player has.
N_TURNS = 7

def main():
    """
    This program produces the hangman game
    """
    life = N_TURNS
    answer = random_word()
    guess = ''
    for i in range(len(answer)):
        guess += '-'
    while True:
        print('The word looks like: ' + guess)
        print('You have ' + str(life) + ' guesses left.')
        input_ch = input('Your guess: ')
        if input_ch.isalpha() and len(input_ch) == 1:  # make sure input is a single letter
            input_ch = input_ch.upper()
            if input_ch in answer:
                print('You are correct!')
                guess = change_answer(input_ch, guess, answer)
            else:
                print('There is no ' + input_ch + '\'s in the word.')
                life -= 1
            if guess == answer:  # win condition
                print('You win!!')
                break
            if life == 0:  # lose condition
                print('You are completely hung :(')
                break
        else:
            print('illegal format.')
    print('The word was: ' + answer)

def change_answer(a, b, c):
    """
    :param a: str, the input character to replace the guess answer
    :param b: str, the previous guess answer to be replaced
    :param c: str, the right answer
    :return: str, the new guess answer
    """
    new_guess = ''
    for i in range(len(c)):
        if a == c[i]:
            new_guess += a
        else:
            new_guess += b[i]
    return new_guess

def random_word():
    num = random.choice(range(9))
    if num == 0:
        return "NOTORIOUS"
    elif num == 1:
        return "GLAMOROUS"
    elif num == 2:
        return "CAUTIOUS"
    elif num == 3:
        return "DEMOCRACY"
    elif num == 4:
        return "BOYCOTT"
    elif num == 5:
        return "ENTHUSIASTIC"
    elif num == 6:
        return "HOSPITALITY"
    elif num == 7:
        return "BUNDLE"
    elif num == 8:
        return "REFUND"

#####  DO NOT EDIT THE CODE BELOW THIS LINE  #####
if __name__ == '__main__':
    main()


from list_display import list_of_skills
from dict_response import dict_response
from manipulate_dic import manipulate_dic
response = 2

while response == 2:
	print("Welcome to Skill-Learning Progress Evaluation")
	print("What action do you want to be performed?\n\t1. Output list\n\t2. Evaluate progress\n\t3. Check progress")
	action = input("Give your response in terms of the number of the action as listed: ")
	if not isinstance(action, int):
	    print("Invalid input. Only numbers allowed")

	elif int(action) < 1:
	    print("Invalid input")

	elif int(action) > 3:
	    print("Invalid input")

	else:
	    if int(action) == 1:
	          print(list_of_skills())

	    elif int(action) == 2:
	          evaluation = dict_response()

	          next = input("Do you wish to view your progress?(You will not be able to view it once you select no)\n\t1. Yes\n\t2. No\nGive your response: ")

	          if int(next) == 1:
	          	print(manipulate_dic(evaluation))

	    elif int(action) == 3:
	    	next1 = input(" You cannot check progress without evaluation. Would you like to do the evaluation?\n\t1. Yes\n\t2. No\nGive your response: ")

	    	if int(next1) == 1:
	    		evaluation1 = dict_response()
	    		manipulate_dic(evaluation1)

	response = input("Do you want to exit?\n\t1. Yes\n\t2. No\n\nEnter your response: ")


"""
Basic Code Using Turtle Library (just for fun)

Haven't used turtle before so I decided to try it out.

Stuff that I can add;
-make it faster
-print final image once done

Garrett Miller-Junk
"""

# import the turtle library
import turtle

# initializes the screen
screen = turtle.Screen()

# declares the size of the screen
screen.setup(1000, 1000)

# background colour of screen
screen.bgcolor("black")

# creates a turtle to draw on the screen
marker = turtle.Turtle()

# how fast the turtle will move
marker.speed(100)

# creates a tuple to store the RGB values as floats from 0.00-1.00 (I only go up to 0.99)
RGB = (0.99, 0.00, 0.00)

# creates a list from the tuple
RBG_list = list(RGB)

# just made relatively large for loop so that it would go through a lot of iteration, but eventually stop
for i in range(3000):
    # make a list out of the tuple
    RGB_list = list(RGB)

    # increase the amount of red (if possible) if it is not at its max and if there is currently no green.
    if (RGB_list[0] < 0.99) and (RGB_list[1] <= 0.00):
        RGB_list[0] += 0.01
    # if there is still red left and green is at its max value, decrease the amount of red
    elif (RGB_list[0] > 0.00) and (RGB_list[1] >= 0.99):
        RGB_list[0] -= 0.01

    # do the same process to increase green (now with respect to blue) and blue (with respect to red)
    if (RGB_list[1] < 0.99) and (RGB_list[2] <= 0.00):
        RGB_list[1] += 0.01
    elif (RGB_list[1] > 0.00) and (RGB_list[2] >= 0.99):
        RGB_list[1] -= 0.01
    if (RGB_list[2] < 0.99) and (RGB_list[0] <= 0.00):
        RGB_list[2] += 0.01
    elif (RGB_list[2] > 0.00) and (RGB_list[0] >= 0.99):
        RGB_list[2] -= 0.01

    #turn the new list into a touple and make that the new RGB touple
    RGB = tuple(RGB_list)

    #moves forward the marker a small amount (chose this a i^2 base so that the spiral would get larger and larger, but start small)
    marker.forward((i / 200) * (i / 5000))

    #turn right by 1 degree
    marker.right(1)

    #change the colour to the new touple
    marker.color(RGB)


#!/usr/bin/env python3
# @Time    : 2020-04-09
# @Author  : caicai
# @File    : poc_struts2_048.py

import random, copy
from myscan.config import scan_set
from myscan.lib.parse.dictdata_parser import dictdata_parser  # 写了一些操作dictdata的方法的类
from myscan.lib.parse.response_parser import response_parser  ##写了一些操作resonse的方法的类
from myscan.lib.helper.request import request  # 修改了requests.request请求的库，建议使用此库，会在redis计数
from myscan.lib.helper.helper_socket import socket_send_withssl, socket_send  # 如果需要，socket的方法封装

class POC():
    def __init__(self, workdata):
        self.dictdata = workdata.get("dictdata")  # python的dict数据，详情请看docs/开发指南Example dict数据示例
        # scheme的poc不同perfoler和perfile,没有workdata没有data字段,所以无self.url
        self.result = []  # 此result保存dict数据，dict需包含name,url,level,detail字段，detail字段值必须为dict。如下self.result.append代码
        self.name = "Struts2-048"
        self.vulmsg = "Struts2-048远程代码执行"
        self.level = 3  # 0:Low  1:Medium 2:High

    def verify(self):
        # 添加限定条件
        if self.dictdata.get("url").get("extension").lower() not in ["do", "action"]:
            return
        self.parser = dictdata_parser(self.dictdata)
        params = self.dictdata.get("request").get("params").get("params_url") + \
                 self.dictdata.get("request").get("params").get("params_body")
        ran_a = random.randint(10000000, 20000000)
        ran_b = random.randint(1000000, 2000000)
        ran_number = '${%d-%d}' % (ran_a, ran_b)
        payloads = [
            ran_number,
        ]
        checks = [str(ran_a - ran_b)]
        headers = copy.deepcopy(self.dictdata.get("request").get("headers"))
        headers['Content-Type'] = 'application/x-www-form-urlencoded'
        if params:
            for param in params:
                for payload in payloads:
                    req = self.parser.getreqfromparam(param, "w", payload)
                    r = request(**req)
                    if r != None:
                        for check in checks:
                            if check.encode() in r.content:
                                self.save(r, payload)
                                return

    def save(self, r, payload):
        parser_ = response_parser(r)
        self.result.append({
            "name": self.name,
            "url": parser_.geturl().split("?")[0],
            "level": self.level,  # 0:Low  1:Medium 2:High
            "detail": {
                "vulmsg": self.vulmsg,
                "payload": payload,
                "request": parser_.getrequestraw(),
                "response": parser_.getresponseraw(),
            }
        })


#!/usr/bin/env python3

# InChI to SMILES conversion

import argparse
import rdkit
import sys
from rdkit import Chem

def RobustMolSupplier(filename):
    with open(filename) as f:
        for line in f:
            words = line.split()
            name = words[0]
            inchi = words[1]
            yield (name, Chem.MolFromInchi(inchi))

if __name__ == '__main__':
    # parse CLI
    # show help in case user has no clue of what to do
    if len(sys.argv) != 3:
        sys.stderr.write("%s input.inchi output.smi\n" % sys.argv[0])
        sys.exit(1)
    input_inchi = sys.argv[1]
    output_smi = sys.argv[2]
    output = open(output_smi, 'w')
    for name, mol in RobustMolSupplier(input_inchi):
        if mol is None:
            continue
        smi = Chem.MolToSmiles(mol)
        output.write("%s\t%s\n" % (smi, name))
    output.close()


import json
import os

def save_file(my_dict, file_name):
    with open(file_name, 'a+', encoding='utf-8') as f3:
        json.dump(my_dict, f3, ensure_ascii=False, indent=4)
        f3.write(',')

def test_save_to_file(file_name):
    with open(file_name, 'r', encoding='utf-8', errors='ignore') as f3:
        data_file = json.load(f3)
        print('\n'.join(map(str, data_file)))

def clear_file(f_name_x):
    with open(f_name_x, 'w', encoding='utf-8') as f3:
        f3.write('[')
        f3.close()

def Lost_line(f_name_x):
    with open(f_name_x, 'rb+') as fileh:
        fileh.seek(-1, os.SEEK_END)
        fileh.truncate()

def Lost_symbol(f_name_x):
    with open(f_name_x, 'a+', encoding='utf-8') as f5:
        f5.write(']')
        f5.close()

def task_5(f_name_1, f_name_2, f_name_3):
    clear_file(f_name_3)
    empty_list = {}
    with open(f_name_1, 'r+', encoding='utf-8') as f1:
        with open(f_name_2, 'r+', encoding='utf-8') as f2:
            while True:
                row_1 = f1.readline()
                row_2 = f2.readline()

                if not row_1:
                    Lost_line(f_name_3)
                    Lost_symbol(f_name_3)
                    test_save_to_file(f_name_3)
                    break

                else:
                    User_Name = row_1.splitlines()
                    User_Name = ' '.join(map(str, User_Name))
                    User_Name_2 = User_Name.split(',')
                    empty_list['Surname'] = User_Name_2[0]
                    empty_list['Name'] = User_Name_2[1]
                    empty_list['Lastname'] = User_Name_2[2]
                    Hobby_Name = row_2.splitlines()
                    Hobby_Name = ' '.join(map(str, Hobby_Name))
                    if Hobby_Name == '':
                        Hobby_Name = None
                    else:
                        Hobby_Name = Hobby_Name.split(',')
                    empty_list['Hobby'] = Hobby_Name
                    save_file(empty_list, f_name_3)

# task_5 ( 'users.csv', 'hobby.csv', 'result2.json' )

if __name__ == "__main__":
    var1 = input("Please enter path (full path+name_file.csv) to users: ")
    f_name_1 = str(var1)
    var2 = input("Please enter path (full path++name_file.csv) to hobby: ")
    f_name_2 = str(var2)
    var3 = input("Please enter path (full path++name_file.csv) to back_up: ")
    f_name_3 = str(var3)
    task_5(f_name_1, f_name_2, f_name_3)


from datetime import datetime
from random import randint
from typing import Dict, Tuple

from tabulate import tabulate
from nonebot import get_driver, on_command, on_message
from nonebot.adapters import Message
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent
from nonebot.matcher import Matcher
from nonebot.params import CommandArg, EventToMe

from .config import Config

config = Config.parse_obj(get_driver().config)
rp = on_command("rp")

def get_current_date():
    return datetime.now().strftime("%Y.%m.%d")

def clear_old_record():
    now = get_current_date()
    for record in config.rp:
        if record != now:
            config.rp.pop(record)

@rp.handle()
async def handle_rp(
    bot: Bot,
    event: GroupMessageEvent,
    to_me: bool = EventToMe(),
    args: Message = CommandArg(),
):
    if not to_me:
        return
    clear_old_record()
    now = get_current_date()
    plain_text = args.extract_plain_text()
    if config.rp.get(now, None) is None:
        config.rp[now] = {}
    today = config.rp[now]
    if today.get(event.group_id, None) is None:
        today[event.group_id] = {}
    group_rp = today[event.group_id]
    if plain_text == "rank":
        ranked: Dict[str, int] = dict(
            sorted(group_rp.items(), key=lambda item: item[1], reverse=True)
        )
        rank_cleaned = []
        for i, user in enumerate(ranked, 1):
            username = (await bot.get_group_member_info(
                group_id=event.group_id, user_id=user
            ))['nickname']
            rank_cleaned.append([i, username, ranked[user]])
        rank_table = tabulate(rank_cleaned, ["Rank", "Username", "Rp"])
        await bot.send_group_msg(group_id=event.group_id, message=rank_table)
        return
    sender = event.sender.user_id
    if group_rp.get(sender, None) is None:
        config.rp[now][event.group_id][sender] = group_rp[sender] = randint(0, 100)
        await bot.send_group_msg(
            group_id=event.group_id,
            message=f"[CQ:reply,id={event.message_id}]Your rp for today is {group_rp[sender]}.",
        )
    else:
        await bot.send_group_msg(
            group_id=event.group_id,
            message=f"[CQ:reply,id={event.message_id}]"
            f"You've already tested your rp today. The result is {group_rp[sender]}.",
        )


import json

def imgPathsCreate(pathImgResource):

    imgPath = "./src/ProjectCore/pathImgUser.json"
    with open(imgPath, "r") as f:
        data = json.load(f)

    if data["system"]["firstOpen"] != pathImgResource:
        for key, value in data.items():
            for subkey, subvalue in value.items():
                data[key][subkey] = f"{pathImgResource}{subvalue}"

        with open(imgPath, "w") as f:
            json.dump(data, f, indent=4)


# encoding: utf-8

from __future__ import unicode_literals

import unittest

try:
    from unittest import mock
except ImportError:
    import mock

from django.contrib.auth.models import User
from django.test import TestCase
from django.test.utils import override_settings

from simple_auth.middleware import SimpleAuthMiddleware

class GatekeeperTests(unittest.TestCase):

    def setUp(self):
        self.user = mock.MagicMock()
        self.request = mock.MagicMock()
        self.request.session = {}
        self.request.user = self.user

    def test_authenticated_user(self):
        """Normally authenticated users should be allowed"""
        self.request.user.is_authenticated.return_value = True
        assert SimpleAuthMiddleware(None).allow_user(self.request)

    def test_has_session(self):
        """If the user has already entered a good password, allow"""
        self.request.user.is_authenticated.return_value = False
        self.request.session['simple_auth'] = 'kjdk'
        assert SimpleAuthMiddleware(None).allow_user(self.request)

    def test_no_session(self):
        """If user has no session key, redirect"""
        self.request.user.is_authenticated.return_value = False
        self.request.session['simple_auth'] = None
        assert not SimpleAuthMiddleware(None).allow_user(self.request)

class URLTests(TestCase):

    def test_protect_test_url(self):
        self.client.logout()
        response = self.client.get("/tester/hello/")
        self.assertRedirects(response, "/password/?url=%2Ftester%2Fhello%2F")

    def test_default_admin_ignored(self):
        """Admin URLs ignored by default"""
        response = self.client.get("/admin/")
        self.assertRedirects(response, "/admin/login/?next=/admin/")

    @override_settings(SIMPLE_AUTH_IGNORE=[])
    def test_no_ignored(self):
        """Even admin URLs are protected"""
        response = self.client.get("/admin/")
        self.assertRedirects(response, "/password/?url=%2Fadmin%2F")

    @override_settings(SIMPLE_AUTH_IGNORE=[r'^test'])
    def test_test_ignored(self):
        """Ignore specified URLs"""
        response = self.client.get("/tester/hello/")
        self.assertEqual(response.status_code, 200)

    @override_settings(SIMPLE_AUTH_IGNORE=[r'^test'],
                       SIMPLE_AUTH_PROTECT=[r'^test'])
    def test_ignore_protec_conflict(self):
        """Ignore always trumps protect"""
        response = self.client.get("/tester/hello/")
        self.assertEqual(response.status_code, 200)

    @override_settings(SIMPLE_AUTH_PROTECT=[r'^test'])
    def test_only_specified_protected(self):
        response = self.client.get("/tester/hello/")
        self.assertEqual(response.status_code, 302)
        response = self.client.get("/goodbye/world/")
        self.assertEqual(response.status_code, 200)

    def test_allowed_authed_user(self):
        user = User.objects.create(username="bob")
        self.client.force_login(user)
        response = self.client.get("/tester/hello/")
        self.assertEqual(response.status_code, 200)
        self.client.logout()


#!/usr/bin/env python

"""
**************************************************************************************************************
Description:
Prints a list of EC2 IP's based on the tag key that you specify.
If you use the -r or --reboot flag, it will also reboot the EC2's listed
If you want to be more specific with your search then use the -v or --value flag to search for a specific tag value

**************************************************************************************************************
Prerequisite:
Uses python2.7, if using python3 changed all occurences of 'raw_input()' to 'input()'
Must have aws cli installed
Must have boto3 installed
Must have aws secret key and id that can access EC2 information configured

**************************************************************************************************************
Usage:
./reboot_ec2.py -k Env -v Production -r

**************************************************************************************************************
Required arguement:
-k, --key       The tag key you used on AWS. An example is Key: Name, Value: EC2Test1

**************************************************************************************************************
Optional arguements:
-v, --value     The tag value you used on AWS. An example is Key: Env, Value: Production
-r, --reboot    This will reboot the EC2 instance with the applied filter

**************************************************************************************************************
"""

import boto3
import argparse

#Reboots ec2 instance_id's provided
def reboot_ec2(instance_id, instance_ip, reboot_key):
    client = boto3.client('ec2')

    response = client.reboot_instances(InstanceIds = [instance_id,])

    #If http status code is 200 then it will notify you if reboot was succesful
    if response["ResponseMetadata"]["HTTPStatusCode"] >= 200 and response["ResponseMetadata"]["HTTPStatusCode"] < 300:
        print("EC2 with the public IP {} has been rebooted".format(instance_ip))

    else:
        print("{} was not able to reboot".format(instance_ip))

def get_instance_descriptions(tag_key, tag_value, reboot_key):
    client = boto3.client('ec2')

    #List instances with the tag key of tag_key variable, and tag_value(default is *)
    response = client.describe_instances(
        Filters=[
            {
                'Name': 'tag:' + tag_key,
                'Values': [
                    tag_value
                ]
            },
        ]

    )
    reservations = response["Reservations"]

    #Iterate through each instance description and go through the one with assigned Public IP's
    for instances in reservations:
        described_instances = instances['Instances'][0]
        if "PublicIpAddress" in described_instances:

            instance_id = described_instances["InstanceId"]
            instance_ip = described_instances['PublicIpAddress']

            #If -r or --reboot flag was used, call reboot func
            if reboot_key:
                reboot_ec2(instance_id, instance_ip, reboot_key)
            else:
                print("{}".format(described_instances['PublicIpAddress']))

#Arg parse for tag key and reboot
def parse_args():
    parser = argparse.ArgumentParser(description="Reboot EC2 instances based on key tag that you specify")

    parser.add_argument("-k", "--key", dest="tag_key", type=str, action="store", help="input tag's key")

    parser.add_argument("-v", "--value", dest="tag_value", type=str, action="store", help="input tag's value")

    parser.add_argument("-r", "--reboot", dest="reboot_key", action="store_true", help="reboot ec2's ")

    return parser.parse_args()

#Main function to run
def main():
    args = parse_args()

    if args.tag_key == None:
        tag_key = str(raw_input("Enter the tag key for the EC2 you are searching for (Ex: Name): ").replace(" ", ""))
    else:
        tag_key = str(args.tag_key)

    if args.tag_value:
        tag_value = str(args.tag_value)
    else:
        tag_value = "*"

    if not args.reboot_key:
        print("\nBelow is a list of EC2 IP's that have the tag key: {}\nIf you wish to reboot the instances please rerun the script with -r or --reboot command flag\n".format(tag_key))

    get_instance_descriptions(tag_key, tag_value, args.reboot_key)

if __name__ == "__main__":
    main()


from math import inf

class Edge:
    def __init__(self, u, v, cap, flow):
        self.u = u
        self.v = v
        self.cap = cap
        self.flow = flow

def push_flow(v, t, cur_flow, used):
    global edges
    used[v] = True
    if v == t:
        return cur_flow
    for cur_edge in edges[v]:
        if cur_edge is not None:
        #cur_edge is from v to cur_edge.v
            if not used[cur_edge.v] and cur_edge.flow < cur_edge.cap:
                next_flow = min(cur_flow, cur_edge.cap - cur_edge.flow)
                print(next_flow)
                delta = push_flow(cur_edge.v, t, next_flow, used)
                if delta > 0:
                    edges[cur_edge.v][cur_edge.u].flow += delta
                    edges[cur_edge.u][cur_edge.v].flow -= delta
                    return delta
    return 0

def ford_fulkerson(start, finish):
    ans = 0
    while True:
        used = [False for _ in range(n + 1)]
        delta = push_flow(start, finish, inf, used)
        if delta > 0:
            ans += delta
        else:
            break
    return ans

n = int(input())
m = int(input())
edges = [[None for i in range(n + 1)] for _ in range(n + 1)]
for i in range(m):
    u, v, cap = map(int, input().split())
    u, v = min(u, v), max(u, v)
    if edges[u][v] is None:
        edges[u][v] = Edge(u, v, cap, 0)
        edges[v][u] = Edge(v, u, 0, 0)
    else:
        edges[u][v].cap += cap
print(ford_fulkerson(1, n))


#Carson James last edited on 6/29/2022
#This is a python version on the game mastermind
#The imports are for random number generation and number rounding
import random
import math

#This is an introduction and explains the rules to the player
print("Hello, welcome to mastermind, the goal of the game is to guess the number in a certain amount of guesses you will be told if the number is in the correct position or if the number is correct but not in the correct position")

#This boolean is used to make it so the game can continue after it is beaten
PlayAgain = True

#This while loop is
while PlayAgain == True:

    #These declare variables for the correct position and correct number
    CorPos = 0
    CorNum = 0

    #This sets up the boolean for the game so the game can run after one turn
    GameWon = False

    #These set up the game by getting the number of guesses through user input and creates the random digits that makes the mystery number
    Numturns = int(input("How many guesses would you like? "))

    #This if and while loop is for players who try to break the code
    if Numturns < 1:
        while Numturns < 1:
            Numturns = int(input("Please enter a positive number that isn't 0, how many guesses would you like?"))

    #This is for storing the user input for later use
    RNumturns = int(Numturns)

    #This list is the range of the 4 digits
    list1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    #These 4 functions select a random number from the lists and then set them to variables
    rand1 = int(random.choice(list1))
    rand2 = int(random.choice(list1))
    rand3 = int(random.choice(list1))
    rand4 = int(random.choice(list1))

    #This equation makes the mystery number to be used
    Mystery = int((rand1 * 1000) + (rand2 * 100) + (rand3 * 10) + rand4)

    #This is for making the mystery number is always for digits
    format(Mystery, "04")
    #print(Mystery)

    #This is the main game the loop continues until the RNumturns varaible is 0 or if the play wins by guessing the correct number
    while RNumturns > 0 and GameWon == False:

    #This gets the players guess
        Guess =int(input("Please input a positive 4 digit number "))

        #This if statement and while loop is for people who try to break the code
        if Guess < 0:
            while Guess < 0:
                Guess = int(input("Please input a positive 4 digit number "))

        #These equations are for number isolation with a mix of modulo and division the math.floor function is to make it a whole number and round down to prevent any errors with comparing
        #This isolates the number in the 1000th position
        Guessp1 = Guess /1000
        Guessp1 = math.floor(Guessp1)
        #print(Guessp1) debugging

        #This isolates the number in the 100th position
        Guessp2 = (Guess / 100) % 10
        Guessp2 = math.floor(Guessp2)
        #print(Guessp2) debugging

        #This isolates the number in the 10th position
        Guessp3 = (Guess % 100)/10
        Guessp3 = math.floor(Guessp3)
        #print(Guessp3) debugging

        #This isolates the number in the 1st position
        Guessp4 = (Guess % 10)
        Guessp4 = math.floor(Guessp4)
        #print(Guessp4) debugging

        #These if statements are for checking if the player got any correct numbers if they do the appropriate varaible will increase
        #These statements are for the correct position
        if rand1 == Guessp1:
            CorPos = CorPos + 1
            # print("1 Working") debugging

        if rand2 == Guessp2:
            CorPos = CorPos + 1
           # print("2 working") debugging

        if rand3 == Guessp3:
            CorPos = CorPos + 1
           # print("3 working") debugging

        if rand4 == Guessp4:
            CorPos = CorPos + 1
            #print("4 working") debugging

        #These statements are for the correct number but not the correct position
        if Guessp1 != rand1 and Guessp1 == rand2 or Guessp1 == rand3 or Guessp1 == rand4:
            CorNum = CorNum + 1
        if Guessp2 != rand2 and Guessp2 == rand1 or Guessp2 == rand3 or Guessp2 == rand4:
            CorNum = CorNum + 1
        if Guessp3 != rand3 and Guessp3 == rand1 or Guessp3 == rand2 or Guessp3 == rand4:
            CorNum = CorNum + 1
        if Guessp4 != rand4 and Guessp4 == rand1 or Guessp4 == rand2 or Guessp4 == rand3:
            CorNum = CorNum + 1

        #These are debugs in case the combined value of the correct number and position go over 4
        TotalNum = CorNum + CorPos
        if TotalNum == 5:
            CorNum = 1
        if TotalNum == 6:
            CorNum = 1
        if TotalNum == 7:
            CorNum = 0
        if TotalNum == 8:
            CorNum = 0

        #These print statements are after the calculations and tell the player how close they were to mystery number the if statements are for grammar purposes
            print("You have ", CorNum, " correct")

            if CorNum == 1:
                print(" number")
            if CorNum > 1 or CorNum == 0:
                print(" numbers")
            print(" and ", CorPos, )
            if CorPos == 0:
                print(" is")
            if CorPos > 1 or CorPos == 0:
                print(" are")
            print(" in the correct position")
        #This equation makes the game countdown so that there is a way to loose
        RNumturns = RNumturns -1

        #This if statement is for if the player won the game by their guess being correct
        if CorPos == 4:
            #This equation shows how many turns it took for the player to get the correct number
            Remaining = Numturns - RNumturns
            #This if statement is for grammar purposes in chance the player guesses the mystery number in one turn
            if Remaining == 1:
                print("Congratulations you guessed the correct number ", Mystery, " in ", Remaining, " turn which means you've won the game")
            if Remaining > 1:
            #This if statement is for everything above one
                print("Congratulations you guessed the correct number ", Mystery, " in ", Remaining, " turns which means you've won the game")
            GameWon = True
        if RNumturns == 0:
            print("Sorry but you weren't able to guess the correct number ", Mystery)

        #These reset the CorNum and CorPos varaible at the end of each guess so the code does not store the number increase from the previous attempts
        CorNum = 0
        CorPos = 0

    #This is for playing the game again
    #This gets the user input for if the player wants to play again 1 and 0 are used due to problems with string comparison
    Question = int(input("Would you like to play again? Press 1 to play again or press 0 to quit"))

    #This while loop is for players trying to break the code
    while Question > 1 or Question < 0:
        if Question > 1 or Question < 0:

            #This is for anyone who tries to input a different answer than the expected one
            print("Please answer with y or n")
            Question = input("Would you like to play again?")

            #This is so the loop can break and the game can end
            if Question == 'n':
                PlayAgain = False

#This print statment is for when to game ends it also helps to know that the program has gone through it also references how old aracade games would have a game over screen
print("Game Over")


from configparser import ConfigParser
import json
import cv2
import numpy as np
from os.path import join as pjoin
import os
import shutil
from activitygen.compo_detector.drawer import ImageDrawer
from activitygen.compo_classifier.classifier import ClassifierPipeline
from activitygen.config.parameter_config import CONFIG_PARSER
from .element import Element

drawer = ImageDrawer()

def show_elements(
    org_img, eles, show=False, win_name="element", wait_key=0, shown_resize=None, line=8
):
    # color_map = {'Text':(0, 0, 255), 'Compo':(0, 255, 0), 'Block':(0, 255, 0), 'Text Content':(255, 0, 255)}
    img = org_img.copy()
    for ele in eles:
        # color = color_map[ele.category]
        ele.visualize_element(img, (0, 0, 255), line, ele.category)
    img_resize = img
    if shown_resize is not None:
        img_resize = cv2.resize(img, shown_resize)
    if show:
        cv2.imshow(win_name, img_resize)
        cv2.waitKey(wait_key)
        if wait_key == 0:
            cv2.destroyWindow(win_name)
    return img_resize

def save_elements(output_file, elements, img_shape, raw_texts):
    info_obj = {"compos": [], "img_shape": img_shape, "raw_texts": raw_texts}
    for i, ele in enumerate(elements):
        c = ele.wrap_info()
        # c['id'] = i
        info_obj["compos"].append(c)
    json.dump(info_obj, open(output_file, "w"), indent=4)
    return info_obj

def reassign_ids(elements):
    for i, element in enumerate(elements):
        element.id = i

def refine_texts(texts, img_shape):
    refined_texts = []
    for text in texts:
        # remove potential noise
        if len(text.text_content) > 1 and text.height / img_shape[0] < 0.075:
            refined_texts.append(text)
    return refined_texts

def merge_text_line_to_paragraph(elements, max_line_gap=5):
    texts = []
    non_texts = []
    for ele in elements:
        if ele.category == "Text":
            texts.append(ele)
        else:
            non_texts.append(ele)

    changed = True
    while changed:
        changed = False
        temp_set = []
        for text_a in texts:
            merged = False
            for text_b in temp_set:
                inter_area, _, _, _ = text_a.calc_intersection_area(
                    text_b, bias=(0, max_line_gap)
                )
                if inter_area > 0:
                    text_b.element_merge(text_a)
                    merged = True
                    changed = True
                    break
            if not merged:
                temp_set.append(text_a)
        texts = temp_set.copy()
    return non_texts + texts

def refine_elements(compos, texts, intersection_bias=(2, 2), containment_ratio=0.8):
    """
    1. remove compos contained in text
    2. remove compos containing text area that's too large
    3. store text in a compo if it's contained by the compo as the compo's text child element
    """
    elements = []
    contained_texts = []
    for compo in compos:
        is_valid = True
        text_area = 0
        for text in texts:
            inter, iou, ioa, iob = compo.calc_intersection_area(
                text, bias=intersection_bias
            )
            if inter > 0:
                # the non-text is contained in the text compo
                if ioa >= containment_ratio:
                    is_valid = False
                    break
                text_area += inter
                # the text is contained in the non-text compo
                if iob >= containment_ratio and compo.category != "Block":
                    contained_texts.append(text)
        if is_valid and text_area / compo.area < containment_ratio:
            # for t in contained_texts:
            #     t.parent_id = compo.id
            # compo.children += contained_texts
            elements.append(compo)

    # elements += texts
    for text in texts:
        # if text not in contained_texts:
        elements.append(text)
    return elements

def refine_tables(elements, tables, intersection_bias=(2, 2), containment_ratio=0.8):
    """
    Omit all components that are in tables.
    """
    refined_elements = []
    for element in elements:
        is_valid = True
        for table in tables:
            inter, _, _, _ = element.calc_intersection_area(
                table, bias=intersection_bias
            )
            if inter > 0:
                is_valid = False
                break
        if is_valid:
            refined_elements.append(element)
    for table in tables:
        # if text not in contained_texts:
        refined_elements.append(table)
    return refined_elements

def refine_matches(elements, matches, intersection_bias=(2, 2), containment_ratio=0.1):
    refined_elements = []
    for ele in elements:
        is_valid = True
        for match in matches:
            inter, iou, ioa, iob = ele.calc_intersection_area(
                match, bias=intersection_bias
            )
            if inter > 0:
                if containment_ratio <= iou:
                    is_valid = False
                    break
        if is_valid:
            refined_elements.append(ele)

    for match in matches:
        if not match.negative_template:
            refined_elements.append(match)
    return refined_elements

def remove_negative_templates(elements):
    refined_elements = []
    for ele in elements:
        if not ele.negative_template:
            refined_elements.append(ele)
    return refined_elements

def only_allow_vism(elements):
    vism_elements = []
    for ele in elements:
        if ele.is_vism:
            vism_elements.append(ele)
    return vism_elements

def check_containment(elements):
    for i in range(len(elements) - 1):
        for j in range(i + 1, len(elements)):
            relation = elements[i].element_relation(elements[j], bias=(2, 2))
            if relation == -1:
                elements[j].children.append(elements[i])
                elements[i].parent_id = elements[j].id
            if relation == 1:
                elements[i].children.append(elements[j])
                elements[j].parent_id = elements[i].id

def reset_containment(elements):
    for i in range(len(elements)):
        elements[i].children = []
        elements[i].parent_id = None

def remove_top_bar(elements, img_height):
    new_elements = []
    max_height = img_height * CONFIG_PARSER.getfloat(
        "MAIN", "remove_top_bar_ratio"
    )  # Param for remove bar, 0.04 for mobile, 0.1 for desktop
    for ele in elements:
        if ele.y1 < max_height:
            continue
        new_elements.append(ele)
    return new_elements

def remove_children_from_image(elements):
    new_elements = []
    for ele in elements:
        has_image_ancestor = False
        current_element = ele
        while current_element and current_element.parent_id is not None:
            parent = next(
                (e for e in elements if e.id == current_element.parent_id), None
            )
            if parent and parent.category == "Image":
                has_image_ancestor = True
                break
            current_element = parent

        if has_image_ancestor:
            continue

        new_elements.append(ele)

    return new_elements

def remove_children_from_button(elements):
    new_elements = []
    for ele in elements:
        has_btn_ancestor = False
        current_element = ele
        while current_element and current_element.parent_id is not None:
            parent = next(
                (e for e in elements if e.id == current_element.parent_id), None
            )
            if parent and parent.category == "Button":
                has_btn_ancestor = True
                break
            current_element = parent

        # print(ele.category)
        if has_btn_ancestor:
            if ele.category != "Text":
                # print(has_btn_ancestor)
                # print(ele.category)
                continue

        new_elements.append(ele)

    return new_elements

def remove_children_from_icon(elements):
    new_elements = []
    for ele in elements:
        has_icon_ancestor = False
        current_element = ele
        while current_element and current_element.parent_id is not None:
            parent = next(
                (e for e in elements if e.id == current_element.parent_id), None
            )
            if parent and "Icon" in parent.category:
                has_icon_ancestor = True
                break
            current_element = parent

        if has_icon_ancestor:
            continue

        new_elements.append(ele)

    return new_elements

def remove_bottom_bar(elements, img_height):
    new_elements = []
    for ele in elements:
        # parameters for 800-height GUI
        if ele.y1 > 750 and 20 <= ele.height <= 30 and 20 <= ele.width <= 30:
            continue
        new_elements.append(ele)
    return new_elements

# def remove_bottom_bar(elements, img_height):
#     new_elements = []
#     max_height = img_height * CONFIG_PARSER.getfloat(
#         "MAIN", "remove_bottom_bar_ratio"
#     )  # Param for remove bar, 0.04 for mobile, 0.1 for desktop
#     for ele in elements:
#         if ele.y2 > img_height - max_height:
#             continue
#         new_elements.append(ele)
#     return new_elements

def compos_clip_and_fill(clip_root, org, compos):
    def most_pix_around(pad=6, offset=2):
        """
        determine the filled background color according to the most surrounding pixel
        """
        up = y1 - pad if y1 - pad >= 0 else 0
        left = x1 - pad if x1 - pad >= 0 else 0
        bottom = y2 + pad if y2 + pad < org.shape[0] - 1 else org.shape[0] - 1
        right = x2 + pad if x2 + pad < org.shape[1] - 1 else org.shape[1] - 1
        most = []
        for i in range(3):
            val = np.concatenate(
                (
                    org[up : y1 - offset, left:right, i].flatten(),
                    org[y2 + offset : bottom, left:right, i].flatten(),
                    org[up:bottom, left : x1 - offset, i].flatten(),
                    org[up:bottom, x2 + offset : right, i].flatten(),
                )
            )
            most.append(int(np.argmax(np.bincount(val))))
        return most

    if os.path.exists(clip_root):
        shutil.rmtree(clip_root)
    os.mkdir(clip_root)

    bkg = org.copy()
    cls_dirs = []
    for compo in compos:
        cls = compo["class"]
        if cls == "Background":
            compo["path"] = pjoin(clip_root, "bkg.png")
            continue
        c_root = pjoin(clip_root, cls)
        c_path = pjoin(c_root, str(compo["id"]) + ".jpg")
        compo["path"] = c_path
        if cls not in cls_dirs:
            os.mkdir(c_root)
            cls_dirs.append(cls)

        position = compo["position"]
        x1, y1, x2, y2 = (
            position["x1"],
            position["y1"],
            position["x2"],
            position["y2"],
        )
        cv2.imwrite(c_path, org[y1:y2, x1:x2])
        # Fill up the background area
        cv2.rectangle(bkg, (x1, y1), (x2, y2), most_pix_around(), -1)
    cv2.imwrite(pjoin(clip_root, "bkg.png"), bkg)

# def get_text_color(text_img):
#     return "black"

def merge(
    img_path,
    compo_path,
    text_path,
    table_path=None,
    tm_path=None,
    fm_path=None,
    merge_root=None,
    classifier=None,
    show=False,
    wait_key=0,
):
    compo_json = json.load(open(compo_path, "r"))
    text_json = json.load(open(text_path, "r"))

    img = cv2.imread(img_path)
    img_resize = cv2.resize(
        img, (compo_json["img_shape"][1], compo_json["img_shape"][0])
    )
    img_resize_unchanged = img_resize.copy()

    # load text and non-text compo
    ele_id = 0
    compos = []
    for compo in compo_json["compos"]:
        element = Element(
            ele_id,
            (
                compo["x1"],
                compo["y1"],
                compo["x2"],
                compo["y2"],
            ),
            compo["class"],
        )
        compos.append(element)
        ele_id += 1
    texts = []
    for text in text_json["texts"]:
        element = Element(
            ele_id,
            (text["x1"], text["y1"], text["x2"], text["y2"]),
            "Text",
            text_content=text["content"],
        )
        # element.text_color = get_text_color(element.compo_clipping(img_resize.copy()))
        # print("element.text_color")
        # print(element.text_color)
        texts.append(element)
        ele_id += 1
    tables = []
    if table_path:
        table_json = json.load(open(table_path, "r"))
        for table in table_json["tables"]:
            element = Element(
                ele_id,
                (
                    table["x1"],
                    table["y1"],
                    table["x2"],
                    table["y2"],
                ),
                "Table",
            )
            element.is_custom = True
            tables.append(element)
            ele_id += 1
    tm_matches = []
    if tm_path:
        tm_json = json.load(open(tm_path, "r"))
        for tm_match in tm_json["matches"]:
            element = Element(
                ele_id,
                (
                    tm_match["x1"],
                    tm_match["y1"],
                    tm_match["x2"],
                    tm_match["y2"],
                ),
                tm_match["template_name"],
            )
            # print("tm_match[template_name]")
            # print(tm_match["template_name"])
            negative_template_val = tm_match["negative_template"].lower()
            negative_template = False
            if negative_template_val == "true":
                negative_template = True
            element.negative_template = negative_template
            element.is_custom = True
            if "activity_name" in tm_match:
                element.activity_name = tm_match["activity_name"]
            tm_matches.append(element)
            ele_id += 1
    fm_matches = []
    if fm_path:
        fm_json = json.load(open(fm_path, "r"))
        for fm_match in fm_json["matches"]:
            element = Element(
                ele_id,
                (
                    fm_match["x1"],
                    fm_match["y1"],
                    fm_match["x2"],
                    fm_match["y2"],
                ),
                fm_match["template_name"],
            )
            negative_template_val = fm_match["negative_template"].lower()
            negative_template = False
            if negative_template_val == "true":
                negative_template = True
            element.negative_template = negative_template
            element.is_custom = True
            if "activity_name" in fm_match:
                element.activity_name = fm_match["activity_name"]
            fm_matches.append(element)
            ele_id += 1
    if compo_json["img_shape"] != text_json["img_shape"]:
        resize_ratio = compo_json["img_shape"][0] / text_json["img_shape"][0]
        for text in texts:
            text.resize(resize_ratio)

    # check the original detected elements
    show_elements(
        img_resize,
        texts + compos,
        show=show,
        win_name="all elements before merging",
        wait_key=wait_key,
    )

    # refine elements
    texts = refine_texts(texts, compo_json["img_shape"])
    elements = refine_elements(compos, texts)
    if tables:
        elements = refine_tables(elements, tables)
    if tm_matches:
        elements = refine_matches(elements, tm_matches)
    if fm_matches:
        elements = refine_matches(elements, fm_matches)
    if CONFIG_PARSER.getboolean("MAIN", "remove_bar"):
        elements = remove_top_bar(elements, img_height=compo_json["img_shape"][0])
        elements = remove_bottom_bar(elements, img_height=compo_json["img_shape"][0])
    if CONFIG_PARSER.getboolean("MAIN", "merge_line_to_paragraph"):
        elements = merge_text_line_to_paragraph(
            elements, max_line_gap=CONFIG_PARSER.getfloat("MAIN", "max_line_gap")
        )
    reassign_ids(elements)
    check_containment(elements)

    # Classify components
    if classifier:
        classifier.predict(
            [elem.compo_clipping(img_resize.copy()) for elem in elements], elements
        )

    # elements = remove_children_from_image(elements)
    # elements = remove_children_from_button(elements)
    # elements = remove_children_from_icon(elements)
    remove_negative_templates(elements)
    if CONFIG_PARSER.getboolean("MAIN", "only_allow_vism"):
        elements = only_allow_vism(elements)
    reset_containment(elements)
    reassign_ids(elements)
    check_containment(elements)

    board = show_elements(
        img_resize,
        elements,
        show=show,
        win_name="elements after merging",
        wait_key=wait_key,
    )

    raw_texts = ""
    for element in elements:
        if element.category == "Text" and element.text_content:
            raw_texts += element.text_content + "; "
    raw_texts = raw_texts[:-2]
    # save all merged elements, clips and blank background
    name = img_path.replace("\\", "/").split("/")[-1][:-4]
    info_obj = save_elements(
        pjoin(merge_root, name + ".json"), elements, img_resize.shape, raw_texts
    )
    cv2.imwrite(pjoin(merge_root, name + ".jpg"), board)
    if CONFIG_PARSER.getboolean("STEPS", "log_inbetween_outputs"):
        print(
            "[Merge Completed] Input: %s Output: %s"
            % (img_path, pjoin(merge_root, name + ".jpg"))
        )
    return img_resize.shape, img_resize_unchanged, info_obj


import logging
import struct

import serial
import numpy as np
from PyQt6.QtGui import QImage, QPixmap

from NanoVNASaver.Hardware.Serial import drain_serial, Interface
from NanoVNASaver.Hardware.VNA import VNA

logger = logging.getLogger(__name__)

class TinySA(VNA):
    name = "tinySA"
    screenwidth = 320
    screenheight = 240
    valid_datapoints = (290,)

    def __init__(self, iface: Interface):
        super().__init__(iface)
        self.features = {"Screenshots"}
        logger.debug("Setting initial start,stop")
        self.start, self.stop = self._get_running_frequencies()
        self.sweep_max_freq_Hz = 950e6
        self._sweepdata = []
        self.validateInput = False

    def _get_running_frequencies(self):
        logger.debug("Reading values: frequencies")
        try:
            frequencies = super().readValues("frequencies")
            return frequencies[0], frequencies[-1]
        except Exception as e:
            logger.warning("%s reading frequencies", e)
            logger.info("falling back to generic")

        return VNA._get_running_frequencies(self)

    def _capture_data(self) -> bytes:
        timeout = self.serial.timeout
        with self.serial.lock:
            drain_serial(self.serial)
            self.serial.write("capture\r".encode("ascii"))
            self.serial.readline()
            self.serial.timeout = 4
            image_data = self.serial.read(
                self.screenwidth * self.screenheight * 2
            )
            self.serial.timeout = timeout
        self.serial.timeout = timeout
        return image_data

    def _convert_data(self, image_data: bytes) -> bytes:
        rgb_data = struct.unpack(
            f">{self.screenwidth * self.screenheight}H", image_data
        )
        rgb_array = np.array(rgb_data, dtype=np.uint32)
        return (
            0xFF000000
            + ((rgb_array & 0xF800) << 8)
            + ((rgb_array & 0x07E0) << 5)
            + ((rgb_array & 0x001F) << 3)
        )

    def getScreenshot(self) -> QPixmap:
        logger.debug("Capturing screenshot...")
        if not self.connected():
            return QPixmap()
        try:
            rgba_array = self._convert_data(self._capture_data())
            image = QImage(
                rgba_array,
                self.screenwidth,
                self.screenheight,
                QImage.Format.Format_ARGB32,
            )
            logger.debug("Captured screenshot")
            return QPixmap(image)
        except serial.SerialException as exc:
            logger.exception("Exception while capturing screenshot: %s", exc)
        return QPixmap()

    def resetSweep(self, start: int, stop: int):
        return

    def setSweep(self, start, stop):
        self.start = start
        self.stop = stop
        list(self.exec_command(f"sweep {start} {stop} {self.datapoints}"))
        list(self.exec_command("trigger auto"))

    def readFrequencies(self) -> list[int]:
        logger.debug("readFrequencies")
        return [int(line) for line in self.exec_command("frequencies")]

    def readValues(self, value) -> list[str]:
        def conv2float(data: str) -> float:
            try:
                return 10 ** (float(data.strip()) / 20)
            except ValueError:
                return 0.0

        logger.debug("Read: %s", value)
        if value == "data 0":
            self._sweepdata = [
                f"{conv2float(line)} 0.0"
                for line in self.exec_command("data 0")
            ]
        return self._sweepdata

class TinySA_Ultra(TinySA):
    name = "tinySA Ultra"
    screenwidth = 480
    screenheight = 320
    valid_datapoints = (450, 51, 101, 145, 290)

    def __init__(self, iface: Interface):
        super().__init__(iface)
        self.features = {"Screenshots", "Customizable data points"}
        logger.debug("Setting initial start,stop")
        self.start, self.stop = self._get_running_frequencies()
        self.sweep_max_freq_Hz = 5.4e9
        self._sweepdata = []
        self.validateInput = False


dias = int(input("Quantos dias quer analisar? "))
choveu = 0
fez_frio = 0
usou_guarda_chuva = 0
usou_casaco = 0

n = 1
while n <= dias:
    chuva = input("Choveu? ")
    if chuva == 's' or chuva == 'S':
        choveu += 1

    temp_min = float(input("Temperatura mínima: "))
    if temp_min < 20:
        fez_frio += 1

    guarda_chuva = input("Tinha guarda-chuva? ")
    if guarda_chuva == 's' or guarda_chuva == 'S':
        if chuva == 's' or chuva == 'S':
            usou_guarda_chuva += 1

    casaco = input("Usou casaco? ")
    if casaco == 's' or casaco == 'S':
        if temp_min < 20:
            usou_casaco += 1

    n += 1

print(f"Choveu em {choveu} de {dias} dias")
print(f"Fez frio em {fez_frio} de {dias} dias")
print(f"Usou guarda-chuva em {usou_guarda_chuva} de {choveu} dias de chuva")
print(f"Usou casaco em {usou_casaco} de {fez_frio} dias de frio")


import numpy as np
import pandas as pd
import os
import random

from BorealWeights import BorealWeightedProblem
from kmeans import kmeans, randomsample
from pyomo.opt import SolverFactory

def nan_to_bau(frame):
    return frame.transpose().fillna(frame.iloc[:, 0]).transpose()

def ideal(dictionary=True):
    if dictionary:
        return {'revenue': 249966739.00009939,
                'deadwood': 218153.21549812937,
                'ha': 20225.257707161425,
                'carbon': 4449001.4721100219}
    else:
        return np.array((249966739.00009939,
                         4449001.4721100219,
                         218153.21549812937,
                         20225.257707161425))

def nadir(dictionary=True):
    if dictionary:
        return {'revenue': 3.09084573e+07,
                'carbon': 2.83139915e+06,
                'deadwood': 8.02116726e+04,
                'ha': 1.19880519e+04}
    else:
        return np.array((3.09084573e+07,
                         2.83139915e+06,
                         8.02116726e+04,
                         1.19880519e+04))

def init_boreal():
    data_dir = os.path.join(os.getcwd(), '../boreal_data')
    carbon = pd.read_csv(os.path.join(data_dir, 'Carbon_storage.csv'))
    HA = pd.read_csv(os.path.join(data_dir, 'Combined_HA.csv'))
    deadwood = pd.read_csv(os.path.join(data_dir, 'Deadwood_volume.csv'))
    revenue = pd.read_csv(os.path.join(data_dir, 'Timber_revenues.csv'))
    return revenue, carbon, deadwood, HA

def init_norms():
    revenue, carbon, deadwood, ha = init_boreal()
    n_revenue = nan_to_bau(revenue)
    n_carbon = nan_to_bau(carbon)
    n_deadwood = nan_to_bau(deadwood)
    n_ha = nan_to_bau(ha)
    norm_revenue = new_normalize(n_revenue.values)
    norm_carbon = new_normalize(n_carbon.values)
    norm_deadwood = new_normalize(n_deadwood.values)
    norm_ha = new_normalize(n_ha.values)
    x = np.concatenate((n_revenue, n_carbon, n_deadwood, n_ha), axis=1)
    x_norm = np.concatenate((norm_revenue,
                             norm_carbon,
                             norm_deadwood,
                             norm_ha), axis=1)
    x_stack = np.dstack((n_revenue, n_carbon, n_deadwood, n_ha))
    x_norm_stack = np.dstack((norm_revenue,
                              norm_carbon,
                              norm_deadwood,
                              norm_ha))
    return {'x': x,
            'x_norm': x_norm,
            'x_stack': x_stack,
            'x_norm_stack': x_norm_stack}

def normalize(data):
    norm_data = data.copy()
    inds = np.where(np.isnan(norm_data))
    norm_data[inds] = np.take(np.nanmin(norm_data, axis=0)
                              - np.nanmax(norm_data, axis=0),
                              inds[1])
    norm_data -= np.min(norm_data, axis=0)
    with np.errstate(invalid='ignore'):
        normax = np.max(norm_data, axis=0)
        norm_data = np.where(normax != 0., norm_data / normax, 0)
    return norm_data

def new_normalize(data):
    norm_data = data.copy()
    norm_data -= np.min(norm_data)
    with np.errstate(invalid='ignore'):
        normax = np.max(norm_data)
        norm_data = np.where(normax != 0., norm_data / normax, 0)
    return norm_data

def optimize_all(combined_data, weights, opt):
    problem1 = BorealWeightedProblem(combined_data[:, :7], weights)
    res1 = opt.solve(problem1.model, False)

    problem2 = BorealWeightedProblem(combined_data[:, 7:14], weights)
    res2 = opt.solve(problem2.model, False)

    problem3 = BorealWeightedProblem(combined_data[:, 14:21], weights)
    res3 = opt.solve(problem3.model, False)

    problem4 = BorealWeightedProblem(combined_data[:, 21:], weights)
    res4 = opt.solve(problem4.model, False)

    return (problem1, res1), (problem2, res2),\
           (problem3, res3), (problem4, res4)

def res_to_list(model):
    resdict = model.x.get_values()
    reslist = np.zeros(model.n.value)
    for i, j in resdict.keys():
        if resdict[i, j] == 1.:
            reslist[i] = j
    return reslist

def res_value(res):
    return res['Problem'][0]['Upper bound']

def cluster_to_value(cluster_data, cluster_list, weights):
    ''' Returns the optimization values of the cluster, based
    on the data of the clusters (cluster_data), the list of
    decision variables options (cluster_list) and the proportion
    of each cluster (weights)'''
    return sum([cluster_data[ind, int(cluster_list[ind])] * weights[ind]
                for ind in range(len(cluster_list))])

def clusters_to_origin(data, xtoc, cluster_list):
    return sum([sum(data[xtoc == ind][:, int(cluster_list[ind])])
                for ind in range(len(cluster_list))])

def model_to_real_values(data, model, xtoc=None):
    if xtoc is None:
        return sum(values_to_list(model, data))
    else:
        return clusters_to_origin(data, xtoc, res_to_list(model))

def values_to_list(model, data):
    lst = []
    for i in model.I:
        for j in model.J:
            if model.x[i, j].value == 1:
                lst.append(data[i, j])
    return lst

def cluster(data, nclust, seed, delta=.0001, maxiter=100,
            metric='cosine', verbose=1):
    random.seed(seed)
    np.random.seed(seed)
    data[np.isnan(data)] = np.nanmin(data) - np.nanmax(data)
    randomcenters = randomsample(data, nclust)
    centers, xtoc, dist = kmeans(data,
                                 randomcenters,
                                 delta=delta,
                                 maxiter=maxiter,
                                 metric=metric,
                                 verbose=verbose)
    return centers, xtoc, dist

def cNopt(orig_data, clust_data, opt_data, opt, nclust='10', seed=2):
    c, xtoc, dist = cluster(clust_data, nclust, seed, verbose=0)
    nvar = len(orig_data)
    weights = np.array([sum(xtoc == i) for i in range(len(c))])/nvar
    opt_x = np.array([opt_data[xtoc == i].mean(axis=0)
                      for i in range(nclust)])
    problem1, problem2, problem3, problem4 = optimize_all(opt_x,
                                                          weights,
                                                          opt)
    res1 = model_to_real_values(orig_data[:, :7], problem1[0].model, xtoc)
    res2 = model_to_real_values(orig_data[:, 7:14], problem2[0].model, xtoc)
    res3 = model_to_real_values(orig_data[:, 14:21], problem3[0].model, xtoc)
    res4 = model_to_real_values(orig_data[:, 21:], problem4[0].model, xtoc)

    return res1, res2, res3, res4

def calc_ideal_n_nadir(data, xtoc=None, weights=None):
    '''
    Calculate ideal and nadir from the data where different
    objectives are at the "last" level
    '''
    solver = SolverFactory('glpk')
    problems = []
    for i in range(np.shape(data)[-1]):
        problems.append(BorealWeightedProblem(data[:, :, i], weights))

    for j in range(len(problems)):
        solver.solve(problems[j].model)

    if xtoc is None:
        payoff = [[np.sum(values_to_list(problems[j], data[:, :, i]))
                   for i in range(np.shape(data)[-1])]
                  for j in range(len(problems))]
    else:
        payoff = [[cluster_to_value(data[:, :, i],
                                    res_to_list(problems[j].model),
                                    weights)
                   for i in range(np.shape(data)[-1])]
                  for j in range(len(problems))]

    ideal = np.max(payoff, axis=0)
    nadir = np.min(payoff, axis=0)
    return ideal, nadir

if __name__ == '__main__':
    seed = 2
    nclust = 50
    revenue, carbon, deadwood, ha = init_boreal()
    x = np.concatenate((revenue, carbon, deadwood, ha), axis=1)

    norm_x = np.concatenate((normalize(revenue.values),
                             normalize(carbon.values),
                             normalize(deadwood.values),
                             normalize(ha.values)), axis=1)

    no_nan_x = x.copy()
    inds = np.where(np.isnan(no_nan_x))
    no_nan_x[inds] = np.take(np.nanmin(no_nan_x, axis=0)
                             - np.nanmax(no_nan_x, axis=0), inds[1])
    opt = SolverFactory('glpk')

    res1, res2, res3, res4 = cNopt(x, norm_x, no_nan_x, opt, nclust, seed)

    print('Results when surrogate mapped to real values:')
    print('(i) Harvest revenues {: .0f} M€'.format(res1/1000000))
    print('(ii) Carbon storage {: .0f} x 100 MgC'.format(res2/100))
    print('(iii) Deadwood index {: .0f} m3'.format(res3))
    print('(iv) Combined Habitat {: .0f}'.format(res4))


from model.contact import Contact
import re
from selenium.webdriver.support.ui import Select

class ContactHelper:

    def __init__(self, app):
        self.app = app

    def create(self, contact):
        wd = self.app.wd
        wd.find_element_by_link_text("add new").click()
        self.fill_contact_form(contact)
        wd.find_element_by_xpath("//div[@id='content']/form/input[21]").click()
        self.return_to_home_page()
        self.contact_cache = None

    def fill_contact_form(self, contact):
        self.change_field_value("firstname", contact.firstname)
        self.change_field_value("middlename", contact.middlename)
        self.change_field_value("lastname", contact.lastname)
        self.change_field_value("address", contact.address)
        self.change_field_value("home", contact.homephone)
        self.change_field_value("mobile", contact.mobilephone)
        self.change_field_value("work", contact.workphone)
#        wd.find_element_by_name("address2").click()
#        wd.find_element_by_name("address2").clear()
#       wd.find_element_by_name("address2").send_keys(contact.address2)
#        wd.find_element_by_name("phone2").click()
#        wd.find_element_by_name("phone2").clear()
#        wd.find_element_by_name("phone2").send_keys(contact.phone2)

    def change_field_value(self, field_name, text):
        wd = self.app.wd
        if text is not None:
            wd.find_element_by_name(field_name).click()
            wd.find_element_by_name(field_name).clear()
            wd.find_element_by_name(field_name).send_keys(text)

    def delete_first_contact(self):
        self.delete_contact_by_index(0)

    def delete_contact_by_index(self, index):
        wd = self.app.wd
        self.select_contact_by_index(index)
        # submit deletion
        wd.find_element_by_xpath("//div[@id='content']/form[2]/div[2]/input").click()
        wd.switch_to_alert().accept()
        self.return_to_home_page()
        self.contact_cache = None

    def select_contact_by_index(self,index):
        wd = self.app.wd
        wd.find_elements_by_name("selected[]")[index].click()

    def select_first_contact(self):
        wd = self.app.wd
        wd.find_element_by_name("selected[]").click()

    def modify_first_contact(self):
        self.modify_contact_by_index(0)

    def modify_contact_by_index(self, index, new_contact_data):
        wd = self.app.wd
        self.return_to_home_page()
        # self.select_contact_by_index(index)
        # open modification form
        wd.find_element_by_xpath("//div[@id='content']/form[@name='MainForm']/table/tbody/tr[" + str(index + 2) + "]/td[8]/a/img").click()
        # fill contact form
        self.fill_contact_form(new_contact_data)
        # submit modification
        wd.find_element_by_name("update").click()
        self.return_to_home_page()
        self.contact_cache = None

    def return_to_home_page(self):
        wd = self.app.wd
        if not(wd.current_url.endswith("/addressbook")):
            wd.find_element_by_link_text("home").click()

    def count(self):
        wd = self.app.wd
        self.return_to_home_page()
        return len(wd.find_elements_by_name("selected[]"))

    contact_cache = None

    def get_contact_list(self):
        if self.contact_cache is None:
            wd = self.app.wd
            self.return_to_home_page()
            self.contact_cache = []
            for row in wd.find_elements_by_name("entry"):
                cells = row.find_elements_by_tag_name("td")
                lastname = cells[1].text
                firstname = cells[2].text
                address = cells[3].text
                id = cells[0].find_element_by_tag_name("input").get_attribute("value")
                all_phones = cells[5].text
                all_emails = cells[4].text
                self.contact_cache.append(Contact(firstname=firstname, lastname=lastname, id=id, address=address,
                                                  all_phones_from_home_page=all_phones, all_emails_from_home_page=all_emails))
        return list(self.contact_cache)

    def open_contact_to_edit_by_index(self, index):
        wd = self.app.wd
        self.app.open_home_page()
        row = wd.find_elements_by_name("entry")[index]
        cell = row.find_elements_by_tag_name("td")[7]
        cell.find_element_by_tag_name("a").click()

    def open_contact_view_by_index(self, index):
        wd = self.app.wd
        self.app.open_home_page()
        row = wd.find_elements_by_name("entry")[index]
        cell = row.find_elements_by_tag_name("td")[6]
        cell.find_element_by_tag_name("a").click()

    def get_contact_info_from_edit_page(self, index):
        wd = self.app.wd
        self.open_contact_to_edit_by_index(index)
        firstname = wd.find_element_by_name("firstname").get_attribute("value")
        lastname = wd.find_element_by_name("lastname").get_attribute("value")
        id = wd.find_element_by_name("id").get_attribute("value")
        homephone = wd.find_element_by_name("home").get_attribute("value")
        workphone = wd.find_element_by_name("work").get_attribute("value")
        mobilephone = wd.find_element_by_name("mobile").get_attribute("value")
        secondaryphone = wd.find_element_by_name("phone2").get_attribute("value")
        address = wd.find_element_by_name("address").get_attribute("value")
        email = wd.find_element_by_name("email").get_attribute("value")
        email2 = wd.find_element_by_name("email2").get_attribute("value")
        email3 = wd.find_element_by_name("email3").get_attribute("value")
        return Contact(firstname=firstname, lastname=lastname, id=id, address=address,
                       homephone=homephone, workphone=workphone,
                       mobilephone=mobilephone, secondaryphone=secondaryphone, email=email, email2=email2, email3=email3)

    def get_contact_from_view_page(self, index):
        wd = self.app.wd
        self.open_contact_view_by_index(index)
        text = wd.find_element_by_id("content").text
        homephone = re.search("H: (.*)", text).group(1)
        workphone = re.search("W: (.*)", text).group(1)
        mobilephone = re.search("M: (.*)", text).group(1)
        secondaryphone = re.search("P: (.*)", text).group(1)
        return Contact(homephone=homephone, workphone=workphone,
                       mobilephone=mobilephone, secondaryphone=secondaryphone)

    def delete_contact_by_id(self, id):
        wd = self.app.wd
        self.select_contact_by_id(id)
        # submit deletion
        wd.find_element_by_xpath("//div[@id='content']/form[2]/div[2]/input").click()
        wd.switch_to_alert().accept()
        self.return_to_home_page()
        self.contact_cache = None

    def select_contact_by_id(self, id):
        wd = self.app.wd
        wd.find_element_by_css_selector("input[value='%s']" % id).click()

    def modify_contact_by_id(self, id, new_contact_data):
        wd = self.app.wd
        self.return_to_home_page()
        self.select_contact_by_id(id)
        # open modification form
        wd.find_element_by_css_selector("a[href='edit.php?id=%s']" % str(id)).click()
        # fill contact form
        self.fill_contact_form(new_contact_data)
        # submit modification
        wd.find_element_by_name("update").click()
        self.return_to_home_page()
        self.contact_cache = None

    def add_contact_to_group(self, contact_id, group):
        wd = self.app.wd
        self.app.open_home_page()
        self.select_contact_by_id(contact_id)
        select = Select(wd.find_element_by_name("to_group"))
        select.select_by_visible_text(group.name.strip())
        wd.find_element_by_name("add").click()
        self.return_to_home_page()

    def delete_from_group(self, contact_id, group):
        wd = self.app.wd
        self.app.open_home_page()
        select = Select(wd.find_element_by_name("group"))
        select.select_by_visible_text(group.name.strip())
        wd.find_element_by_id("%s" % contact_id).click()
        wd.find_element_by_name("remove").click()
        self.return_to_home_page()


from typing import List

class Solution:
    def setZeros(self, matrix: List[List[int]]) -> None:
        num_rows = len(matrix)
        num_cols = len(matrix[0])
        for i in range(num_rows):
            for j in range(1, num_cols):
                # If an element is zero, we set the first element of the corresponding row and column to 0?
                if matrix[i][j] == 0:
                    matrix[0][j] = 0
                    matrix[i][0] = 0

        # Iterate over the array once again and using the first row and first column, update the elements.
        for i in range(1, num_rows):
            for j in range(1, num_cols):
                if not matrix[i][0] or not matrix[0][j]:
                    matrix[i][j] = 0

        # See if the first row needs to be set to zero as well
        if matrix[0][0] == 0:
            for j in range(1, num_cols):
                matrix[0][j] = 0
            for i in range(1, num_rows):
                matrix[i][0] = 0

if __name__ == '__main__':

    # Inputs
    matrix_1 = [[1, 1, 1], [1, 0, 1], [1, 1, 1]]
    matrix_2 = [[0, 1, 2, 0], [3, 4, 5, 2], [1, 3, 1, 5]]

    # Run tests

    solution_1 = Solution()
    solution_2 = Solution()

    test_1 = solution_1.setZeros(matrix_1)
    test_2 = solution_2.setZeros(matrix_2)

    print(f"Test 1: {matrix_1}")
    print("Expected Output 1: [[1,0,1],[0,0,0],[1,0,1]]")
    print(f"Test 2: {matrix_2}")
    print("Expected Output 2: [[0, 0, 0, 0], [0, 4, 5, 0], [0, 3, 1, 0]]")


# https://www.geeksforgeeks.org/the-stock-span-problem/
# Similar : https://leetcode.com/problems/daily-temperatures/
# Question : The stock span problem is a financial problem where we have a series of n daily price
# quotes for a stock and we need to calculate span of stock’s price for all n days.The span Si
# of the stock’s price on a given day i is defined as the maximum number of consecutive days
# just before the given day, for which the price of the stock on the current day is less than
# or equal to its price on the given day.
#
# Example : Input : {100, 80, 60, 70, 60, 75, 85}
# Output : {1, 1, 1, 2, 1, 4, 6}
#
# Question Type : Generic
# Used : Loop over the given inpArr. If current element is higher than previous element,
#        add its span to current span. Jump in left by current span value.
#        Repeat the above process.
#        calculateSpan(inpArr):
#        n = len(inpArr), span = [0] * n
#        span[0] = 1
#        for i in range(1, n):
#           counter = 1
#           while (i - counter) >= 0 and inpArr[i] >= inpArr[i - counter]:
#               counter += span[i - counter]
#           span[i] = counter
#        return span
# Complexity : O(2n)

def calculateSpan(inpArr):
    n = len(inpArr)
    span = [0] * n
    # Span value of first element is always 1
    span[0] = 1

    # Calculate span values for rest of the elements
    for i in range(1, n):
        counter = 1
        while (i - counter) >= 0 and inpArr[i] >= inpArr[i - counter]:
            counter += span[i - counter]
        span[i] = counter
    return span

if __name__ == "__main__":
    price = [10, 4, 5, 90, 120, 80]
    print(calculateSpan(price))

    price = [100, 80, 60, 70, 60, 75, 85]
    print(calculateSpan(price))


from datetime import datetime, timedelta, timezone

import connexion
import six
from werkzeug.exceptions import BadRequest, NotFound, Conflict, Unauthorized

from src.constants_enums.obj_keys import *
from src.utils.date_utils import compare_date_strings, TimeRelations
from src.utils.election_parsing import parse_election_tuples
from swagger_server.models.election import Election  # noqa: E501
from swagger_server.models.inline_response2004 import InlineResponse2004  # noqa: E501
from swagger_server.models.inline_response2005 import InlineResponse2005  # noqa: E501
from swagger_server import util
import src.db.mysql_interface as db
from src.db.rollbacks import rollback_create_election
from src.db.org_election_query_helper import *
from src.constants_enums.datetime_format import DateFormats

def create_election(body):  # noqa: E501
    """Create election

    Create election # noqa: E501

    :param body: Election ID is not required to POST
    :type body: dict | bytes

    :rtype: InlineResponse2005
    """

    start_time = body[ElectionKeys.START_TIME]
    end_time = body[ElectionKeys.END_TIME]
    anonymous = body[ElectionKeys.ANONYMOUS]
    verified = body[ElectionKeys.VERIFIED]
    public_results = body[ElectionKeys.PUBLIC_RESULTS]
    questions = body[ElectionKeys.QUESTIONS]
    election_description = body[ElectionKeys.ELECTION_DESCRIPTION]
    org_id = body[OrgInfoKeys.ORG_ID]

    try:
        start_end_delta = compare_date_strings(start_time, end_time, DateFormats.ELECTION_TIME_FORMAT)
    except ValueError:
        raise BadRequest("Incorrect date format")

    if not start_end_delta == TimeRelations.LFT_EARLIER:
        raise BadRequest("End time must strictly be later than start time")

    if len(questions) < 1:
        raise BadRequest("Elections must have at least one question")

    election_id = db.create_election(org_id, election_description, start_time, end_time, anonymous, public_results,
                                     verified)

    add_questions(election_id, questions)
    return InlineResponse2005(election_id[0])

def add_questions(election_id, questions):
    question_id_list = []
    option_id_list = []
    for question in questions:
        question_description = question[QuestionKeys.QUESTION_DESCRIPTION]
        max_selection_count = question[QuestionKeys.MAX_SELECTION_COUNT]
        min_selection_count = question[QuestionKeys.MIN_SELECTION_COUNT]
        prioritized_choices = question[QuestionKeys.ORDERED_CHOICES]
        if max_selection_count < 1:
            rollback_create_election(election_id, question_id_list, option_id_list)
            raise BadRequest(
                "You must be able to choose at least one option in every question: max_selection_count < 1")
        try:
            question_id = db.add_question(election_id, question_description, min_selection_count, max_selection_count,
                                          prioritized_choices)
        except Exception as e:
            rollback_create_election(election_id, question_id_list, option_id_list)
            raise e
        question_id_list.append(question_id)
        if len(question[QuestionKeys.OPTIONS]) < 2:
            rollback_create_election(election_id, question_id_list, option_id_list)
            raise BadRequest("Every question must contain at least 2 options")
        add_options(election_id, question, question_id, question_id_list, option_id_list)

def add_options(election_id, question, question_id, question_id_list, option_id_list):
    for option in question[QuestionKeys.OPTIONS]:
        option_description = option[QuestionKeys.OPTION_DESCRIPTION]
        try:
            option_id = db.add_question_opt(question_id, option_description)
        except Exception as e:
            rollback_create_election(election_id, question_id_list, option_id_list)
            raise e
        option_id_list.append(option_id)

def delete_election(election_id):  # noqa: E501
    """Delete election

    Elections can only be deleted before they have commenced.  # noqa: E501

    :param election_id: The id of the election
    :type election_id: int

    :rtype: None
    """
    election = get_election(election_id)
    now_date = datetime.now(timezone(timedelta(0)))
    now_string = now_date.strftime(DateFormats.ELECTION_TIME_FORMAT)
    if compare_date_strings(election.start_time, now_string, DateFormats.ELECTION_TIME_FORMAT) \
            != TimeRelations.LFT_EARLIER:
        Conflict("Cannot delete election after it has started")
    db.remove_election(election_id)
    return None

def get_election(election_id):  # noqa: E501
    """Get election info

    Get one election # noqa: E501

    :param election_id: The id of the election
    :type election_id: int

    :rtype: Election
    """
    election = get_election_with_results(election_id)
    for question in election.questions:
        new_options = []
        for option in question.options:
            new_options.append(Option(option.option_id, option.option_description))
        question.options = new_options
    return election

def get_election_list(org_id):  # noqa: E501
    """Get election info list

    Get list of elections for a given org # noqa: E501

    :param org_id: The id of the org
    :type org_id: int

    :rtype: InlineResponse2004
    """
    election_list_tuple = db.get_org_elections(org_id)
    parsed_elections = parse_election_tuples(election_list_tuple)
    return InlineResponse2004(parsed_elections)

def update_options(option_list):
    for option in option_list:
        option_id = option[QuestionKeys.OPTION_ID]
        option_description = option[QuestionKeys.OPTION_DESCRIPTION]
        db.update_question_opt(option_id, option_description)

def update_questions(question_list):
    for question in question_list:
        options = question[QuestionKeys.OPTIONS]
        question_id = question[QuestionKeys.QUESTION_ID]
        min_selection_count = question[QuestionKeys.MIN_SELECTION_COUNT]
        max_selection_count = question[QuestionKeys.MAX_SELECTION_COUNT]
        ordered_choices = question[QuestionKeys.ORDERED_CHOICES]
        description = question[QuestionKeys.QUESTION_DESCRIPTION]
        db.update_question(question_id, description, min_selection_count, max_selection_count, ordered_choices)
        update_options(options)

def delete_questions(question_id_list):
    for question_id in question_id_list:
        db.remove_question(question_id)

def validate_with_set(id_set, expected_id_set):
    for _id in id_set:
        if _id not in id_set:
            return False
    return True

def get_question_option_id_set(questions):
    question_id_set = set()
    option_id_set = set()
    for question in questions:
        question_id_set.add(question.question_id)
        for option in question.options:
            option_id_set.add(option.option_id)
    return question_id_set, option_id_set

def get_question_option_id_set_from_question_dict(questions):
    question_id_set = set()
    option_id_set = set()
    for question in questions:
        question_id_set.add(question[QuestionKeys.QUESTION_ID])
        for option in question[QuestionKeys.OPTIONS]:
            option_id_set.add(option[QuestionKeys.OPTION_ID])
    return question_id_set, option_id_set

def update_election(body):  # noqa: E501
    """update election

    Update election. Elections can only be updated before they have commenced.  # noqa: E501

    :param body: Election ID is not required to POST
    :type body: dict | bytes

    :rtype: None
    """

    election_id = body[ElectionKeys.ELECTION_ID]
    start_time = body[ElectionKeys.START_TIME]
    end_time = body[ElectionKeys.END_TIME]
    anonymous = body[ElectionKeys.ANONYMOUS]
    verified = body[ElectionKeys.VERIFIED]
    public_results = body[ElectionKeys.PUBLIC_RESULTS]
    questions = body[ElectionKeys.QUESTIONS]
    election_description = body[ElectionKeys.ELECTION_DESCRIPTION]
    org_id = body[OrgInfoKeys.ORG_ID]

    now_date = datetime.now(timezone(timedelta(0)))
    now_string = now_date.strftime(DateFormats.ELECTION_TIME_FORMAT)
    try:
        actual_given_delta = compare_date_strings(start_time, now_string, DateFormats.ELECTION_TIME_FORMAT)
    except ValueError:
        raise BadRequest("Incorrect date format")
    if actual_given_delta != TimeRelations.LFT_EARLIER:
        Conflict("Cannot update election after it has started")

    try:
        start_end_delta = compare_date_strings(start_time, end_time, DateFormats.ELECTION_TIME_FORMAT)
    except ValueError:
        raise BadRequest("Incorrect date format")
    if not start_end_delta == TimeRelations.LFT_EARLIER:
        raise BadRequest("End time must strictly be later than start time")

    actual_election = get_election(election_id)

    actual_question_ids, actual_option_ids = get_question_option_id_set(actual_election.questions)
    sent_question_ids, sent_option_ids = get_question_option_id_set_from_question_dict(questions)
    if not validate_with_set(sent_question_ids, actual_question_ids):
        Unauthorized("Attempting to edit question that does not belong to this election")
    if not validate_with_set(sent_option_ids, actual_option_ids):
        Unauthorized("Attempting to edit option that does not belong to this election")

    questions_to_delete = actual_question_ids.difference(sent_question_ids)
    db.update_election(election_id, election_description, start_time, end_time, anonymous, public_results, verified)

    update_questions(questions)

    delete_questions(questions_to_delete)
    return None


s=input()
a=[]
for i in s:
    if(i==' '):
        continue
    else:
        a.append(ord(i))
k=min(a)
t=max(a)
cnt,c,p,n=0,0,0,0
for j in a:
    p=a.count(k)
    n=a.count(t)
print(chr(k),p,chr(t),n,end=' ')