import csv
import pandas as pd
from commit import Commit,Change

from collections import OrderedDict
from datetime import date

def read_file(changes_file):
    # use strip to strip out spaces and trim the line.
    data = [line.strip() for line in open(changes_file, 'r')]
    return data

def get_commits_and_changes(data):
    sep = 72*'-'
    commits = []
    changes = []
    current_commit = None
    new_change = None
    index = 0

    author = {}
    while True:
        try:
            # parse each of the commits and put them into a list of commits
            current_commit = Commit()
            details = data[index + 1].split('|')
            current_commit.revision = int(details[0].strip().strip('r'))
            current_commit.author = details[1].strip()
            date = details[2].strip()
            date = date.split("+")
            current_commit.date = date[0].strip()
            current_commit.comment_line_count = int(details[3].strip().split(' ')[0])

            # parse each of the commits change log and put them into a list changes
            changes_data = data[index+3:data.index('',index+1)]
            for i in changes_data:
                new_change = Change()
                if  isinstance(i,str) and i.startswith("A "):
                    new_change.type = "add"
                    new_change.revision = current_commit.revision
                    new_change.path = i.strip('A ');
                    changes.append(new_change)
                elif isinstance(i,str) and i.startswith("D "):
                    new_change.type = "delete"
                    new_change.revision = current_commit.revision
                    new_change.path = i.strip('D ')
                    changes.append(new_change)
                elif isinstance(i,str)and  i.startswith("M "):
                    new_change.type = "modify"
                    new_change.revision = current_commit.revision
                    new_change.path = i.strip('M ')
                    changes.append(new_change)

            index = data.index(sep, index + 1)
            current_commit.comment = data[index-current_commit.comment_line_count:index]
            commits.append(current_commit)
        except IndexError:
            break
    return [commits, changes]

# write the commits to cvs file
def write_commits_to_cvs(commits):
    with open('commit_log.csv', 'w') as csvfile:
        fieldnames = Commit.LABELS
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()
        for i, commit in enumerate(commits):
            writer.writerow(commits[i].get_commit())

# write the changes to cvs file, easier to data analyze when the changes are in separate file
def write_changes_to_cvs(changes):
    with open('commit_change_log.csv', 'w') as csvfile:
        fieldnames = Change.LABELS
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()
        for i, change in enumerate(changes):
            writer.writerow(changes[i].get_change())

# populate dataframe with date from cvs file
def get_commit_data_frame():
    return pd.read_csv('commit_log.csv')

# populate dataframe with date from cvs file
def get_commit_changes_data_frame():
    return pd.read_csv('commit_change_log.csv')

# Analyse date data
def analazye_date_data(df):

    df['date'] = pd.to_datetime(df['date'])
    dates = df.groupby([df.date.dt.year, df.date.dt.month, df.date.dt.day]).size()
    no_dates = dates.count();
    print("Number of different dates: " + str(no_dates))
    print("")

    most_commits_per_date = dates.max()
    print("Most number of commits made on a single day: " + str(most_commits_per_date))
    print("")

    date_most_commits = dates.idxmax()
    print("Date most changes were  commited: " + str(date_most_commits))
    print("")

def analyze_change_data(df):

    change_types = df.type.unique()
    print("Type of changes made to repository: " + str(change_types))
    print("")

    total_number_file_changes = len(df)
    print("Total number of file changes: " + str(total_number_file_changes))
    print("")

    num_file_changed = df.path.nunique()
    print("Number of different files that were altered: "  + str(num_file_changed))
    print("")

    type_counts = df.groupby('type').size()
    print("Break down of change types: " + str(type_counts))
    print("")

    file_path_counts = df['path'].value_counts()
    file_changed_most = file_path_counts.max()
    print("Most times a file was changed " + str(file_changed_most))
    print("")

    file_id = df['path'].value_counts().idxmax()
    print("File most changed:"  + str(file_id))
    print("")

    changes_per_revision =df.groupby('revision').size()

    commit_with_most_changes = df['revision'].value_counts().idxmax()
    print("Commit with most changes: " + str(commit_with_most_changes))
    print("")

    most_changes_per_commit =  df['revision'].value_counts().max()
    print("The highest number of changes per commit: " + str(most_changes_per_commit))
    print("")

    average_changes_per_commit =  df['revision'].value_counts().mean()
    print("Average changes per commit " + str(average_changes_per_commit))
    print("")

# Analyse author data
def analazye_author_data(df):

    num_authors =df.author.nunique()
    print("Number of authors: " + str(num_authors))
    print("")

    list_authors = df.author.unique()
    print("List of all authors: " + str(list_authors))
    print("")

    commits_per_author = df.groupby('author').size()
    print("Authors and the number of commits" + str(df.groupby('author').size()))
    print("")

    author_least_commits = df['author'].value_counts().idxmin()
    print("Author with the least commits: " + str(author_least_commits))
    print("")

    author_most_commits = df['author'].value_counts().idxmax()
    print("Author with most commits: " + str(author_most_commits))
    print("")

    max_commits = commits_per_author.max()
    print("Highest number of commits by author: " + str(max_commits))
    print("")

def get_authors_most_commits(df):
    return df['author'].value_counts().idxmax()

def get_most_commit_single_day(df):
    df['date'] = pd.to_datetime(df['date'])
    dates = df.groupby([df.date.dt.year, df.date.dt.month, df.date.dt.day]).size()
    return dates.max()

def get_commit_with_most_changes(df):
    return df['revision'].value_counts().idxmax()

if __name__ == '__main__':
    # open the file - and read all of the lines.
    changes_file = 'changes_python.log'
    data = read_file(changes_file)
    log = get_commits_and_changes(data)
    commits = log[0]
    changes = log[1]
    write_commits_to_cvs(commits)
    write_changes_to_cvs(changes)
    changes_df = get_commit_changes_data_frame()
    commits_df = get_commit_data_frame()
    analyze_change_data(changes_df)
    analazye_date_data(commits_df)
    analazye_author_data(commits_df)


from geopy.geocoders import Nominatim
import folium
import webbrowser

region = ["Dakar",
          "Thies",
          "Diourbel",
          "Kaolack",
          "Fatick",
          "Kaffrine",
          "Louga",
          "Matam",
          "Tambacounda",
          "Kédougou",
          "Kolda",
          "Ziguinchor",
          "Sédhiou"
          ]
liaison = [["Dakar", "Pikine", "Guediawaye", "Rufisque", "Keur Massar"],
                ["Thies", "Mbour", "Tivaoune"],
                ["Diourbel", "Bambey", "Mbacké"],
                ["Fatick", "Foundiougne","Gossas"],
                ["Kaolack", "Guingueneo", "Nioro Du Rip"],
                ["Kaffrine", "Birkelane", "Malem Hodar", "Koungheul"],
                ["Louga", "Kébémer"],
                ["Saint-Louis", "Dagana", "Podor"],
                ["Matam", "Kanel", "Ranerou"],
                ["Tambacounda", "Koumpentoum", "Goudiry", "Bakel"],
                ["Kédougou", "Sareya", "Salemata"],
                ["Kolda", "Vélingara", "Medina Yoro Foula"],
                ["Ziguinchor", "Oussouye", "Bignona",],
                ["Sédhiou", "Goudomp", "Bounkiling"],

]
Coord = []
geolocator = Nominatim(user_agent="Microsoft Edge")
for i in region:
    location = geolocator.geocode(i)
    Coord += [[location.latitude, location.longitude]]
    #print(i, " a pour coordonnées : ", location.latitude, ",", location.longitude)
    #print()
    #print("***************************************************************************")

my_map = folium.Map(location=[14.814349, -17.249890],zoom_start=6)
k = 0
for each in Coord:
    folium.Marker(location=each, popup=region[k]).add_to(my_map);
    k+=1

for i in region:
    from geopy.geocoders import Nominatim
    geolocator = Nominatim(user_agent="Microsoft Edge")
    location = geolocator.geocode(i)
    Coord += [[location.latitude,location.longitude]]
    folium.PolyLine(Coord, color="blue", weight=3, opacity=1).add_to(my_map)

my_map.save("C:\\Users\\HP\\Documents\\code_python\\macarte1.html")
url = 'C:\\Users\\HP\\Documents\\code_python\\macarte1.html'
webbrowser.open_new_tab(url)


__author__ = 'hungtantran'

import datetime
from ftplib import FTP

import logger
from constants_config import Config

def get_past_xbrl_index(target_dir='.'):
    ftp = None

    try:
        ftp = FTP(Config.sec_ftp_link)
        ftp.login()

        for year in range(2015, 2017):
            for quarter in range(1, 5):
                logger.Logger.log(logger.LogLevel.INFO, 'Downloading xbrl index of year %d, quarter %d to directory %s' % (
                    year, quarter, target_dir))
                target_file_path = "%s/%d_qtr%d_%s" % (target_dir, year, quarter, Config.sec_xbrl_index_file)
                with open(target_file_path, 'wb') as file:
                    ftp_target_directory = '%s/%d/QTR%d' % (Config.sec_ftp_full_index_path, year, quarter)
                    ftp.cwd(ftp_target_directory)
                    ftp.retrbinary("RETR " + Config.sec_xbrl_index_file, file.write)
    except Exception as e:
        logger.Logger.log(logger.LogLevel.ERROR, e)
    finally:
        if ftp is not None:
            ftp.quit()

#get_past_xbrl_index('SEC/test_output_files')


"""
Модуль для приведения выходных данных к читаемому виду.
"""
import os

from utils.manipulate_data import load_data, save_data  # pylint: disable=import-error

def fix_download_bug():
    """
    Функция правит мета данные при некорректном скачивании данных с БД.
    """

    meta_data = load_data('output/meta_data_latest.pkl')
    saved_videos = list(os.listdir("saved_data"))
    saved_videos.remove('.ipynb_checkpoints')
    latest_idx = len([i for i in meta_data['comparison_submeta'] if i is not None]) - 1
    video_not_to_delete = os.path.split(meta_data['local_features_paths'][latest_idx])[-1]
    saved_videos.remove(video_not_to_delete)
    os.remove(os.path.join("saved_data", saved_videos[0]))
    # pylint: disable=invalid-name
    for idx, (z1, z2) in enumerate(zip(meta_data['comparison_submeta'][latest_idx]['was_main_video_downloaded'],
                                       meta_data['comparison_submeta'][latest_idx][
                                           'was_main_video_compared_with_current'])):
        if z1 != z2:
            meta_data['comparison_submeta'][latest_idx]['was_main_video_downloaded'][idx] = False
            save_data(meta_data, 'output/meta_data_latest.pkl')
            break


import dis
import random

import pygame
from pygame import event

pygame.init()

pygame.display.set_caption('Snake game first trail')
display_width = 400
display_height = 400
snake_block = 10
food_block = snake_block
display_game = pygame.display.set_mode((display_width, display_height))

white = (255, 255, 255)
blue = (0, 0, 255)
red = (255, 0, 0)
green = (0, 255, 0)

clock = pygame.time.Clock()

score_font = pygame.font.SysFont("cosmeticians", 25)

def my_snake(snake_list, snake_block):
    for x in snake_list:
        pygame.draw.rect(display_game, blue, [x[0], x[1], snake_block, snake_block])

def def_game_close(game_close, snake_lenght):
    while game_close == True:
        display_game.fill(blue)
        value = score_font.render("Your Score: " + str(snake_lenght - 1), True, red)
        value1 = score_font.render("Press A-Play Again or Q-Quit", True, red)
        display_game.blit(value, [0, 0])
        display_game.blit(value1, [0, 100])
        pygame.display.update()
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_a:
                    game()
                if event.key == pygame.K_q:
                    game_close = False
                    return True

def game():
    game_over = False
    game_close = False
    snake_speed = 3
    snake_lenght = 1
    x1 = 0
    y1 = 0

    x1_change = 0
    y1_change = 0
    snake_list = []

    foodx = round(random.randrange(0, display_width - snake_block) / 10) * 10
    foody = round(random.randrange(0, display_width - snake_block) / 10) * 10

    event_key_previous = 0

    while not game_over:
        game_over = def_game_close(game_close, snake_lenght)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN and event_key_previous != event.key:
                event_key_previous = event.key
                if event.key == pygame.K_DOWN:
                    x1_change = 0
                    y1_change += 10
                if event.key == pygame.K_UP:
                    x1_change = 0
                    y1_change -= 10
                if event.key == pygame.K_RIGHT:
                    x1_change += 10
                    y1_change = 0
                if event.key == pygame.K_LEFT:
                    x1_change -= 10
                    y1_change = 0

        if y1 > display_height or y1 < 0 or x1 < 0 or x1 > display_width:
            game_close = True

        x1 += x1_change
        y1 += y1_change
        display_game.fill(white)

        pygame.draw.rect(display_game, red, [foodx, foody, food_block, food_block])

        snake_Head = []
        snake_Head.append(x1)
        snake_Head.append(y1)
        snake_list.append(snake_Head)
        if len(snake_list) > snake_lenght:
            del snake_list[0]

        # ако се върне назад умира
        for x in snake_list[:-1]:
            if x == snake_Head:
                game_close = True

        # рисува змията
        my_snake(snake_list, snake_block)

        # Изяжда храната
        if x1 == foodx and y1 == foody:
            foodx = round(random.randrange(0, display_width - snake_block) / 10) * 10
            foody = round(random.randrange(0, display_width - snake_block) / 10) * 10
            snake_speed += 1
            snake_lenght += 1

        value = score_font.render("Your Score: " + str(snake_lenght - 1), True, green)
        display_game.blit(value, [0, 0])

        pygame.display.update()
        clock.tick(snake_speed)

    pygame.quit()
    quit()

game()


from django import template

from ..models import GameGroup, Games

register = template.Library()

@register.filter(name="range")
def _range(value: int):
    return range(value)

@register.filter(name="filter_users")
def filter_users(queryset, value: int):
    length = queryset.count()
    if value > length:
        return False
    return list(queryset)[value - 1]

@register.filter(name="filter_users_id")
def filter_users_id(queryset, value: int):
    length = queryset.count()
    if value > length:
        return False
    queryset1 = list(queryset)
    return queryset1[value - 1].unique_id

@register.filter(name="check_success")
def check_success(queryset):
    payments_list = queryset.filter(payment_status="S").count()
    if (payments_list >= 1
            or Games.objects.filter(registrations_closed=False).count() == 0):
        return False
    return True

@register.filter(name="if_groups")
def if_groups(user):
    groups = GameGroup.objects.filter(users__in=[
        user,
    ]).count()
    if groups >= 1:
        return True
    return False

@register.filter(name="solo_user")
def solo_user(user):
    groups = GameGroup.objects.filter(
        users__in=[
            user,
        ],
        solo_or_squad="so",
    ).count()
    if groups >= 1:
        return True
    return False

@register.filter(name="squad_user")
def squad_user(user):
    groups = GameGroup.objects.filter(
        users__in=[
            user,
        ],
        solo_or_squad="sq",
    ).count()
    if groups >= 1:
        return True
    return False

@register.filter(name="if_user_not_payed")
def if_user_not_payed(payment_obj, user):
    if user.is_superuser:
        return False
    if payment_obj.payment_id in list(user.orders.iterator()):
        return False
    return True

@register.filter(name="if_user_not_payed_without_obj")
def if_user_not_payed_without_obj(user):
    if user.is_superuser:
        return False
    for i in user.orders.iterator():
        if i.payment_status == "S":
            return False
        if i.payment_status in ("F", "P", "R"):
            return True
    return True


from airflow import DAG
from airflow.operators.bash_operator import BashOperator
from airflow.operators.python_operator import PythonOperator, BranchPythonOperator
from datetime import datetime, timedelta
import pandas as pd
import random
import os

# DATA_FOLDER = os.getcwd()
DATA_FOLDER = '/home/phllp/dev/bootcamp_data_eng/modulo_04/docker-airflow/data/train.csv'

print(os.getcwd())
# Argumentos default
default_args = {
  'owner': 'felipe',
  'depends_on_past': False,
  'start_date': datetime(2023, 1, 27, 20),
  'email': ['random_mail@mail.com'],
  'email_on_failure': False,
  'email_on_retry': False,
  'retries':1,
  'retry_delay': timedelta(minutes=1)
}

def calculate_mean_age():
  df = pd.read_csv(f'{DATA_FOLDER}/train.csv')
  med = df['Age'].mean()
  return med

def print_age(**context):
  sex = context['task_instance'].xcom_pull(task_ids='sort_sex')

  if sex == 'male':
    task = 'male_branch'
  elif sex == 'female':
    task = 'female_branch'
  value = context['task_instance'].xcom_pull(task_ids=task)
  print(f'A idade media no Titanic era {value} anos')

def handle_sex(**context):
  value = context['task_instance'].xcom_pull(task_ids='sort_sex')
  if value == 'male':
    return 'male_branch'
  if value == 'female':
    return 'female_branch'

def sorteia_h_m():
  return random.choice(['male', 'female'])

def calculate_mean_age_male():
  df = pd.read_csv(f'{DATA_FOLDER}/train.csv')
  med = df.loc[df['Sex'] == 'male']['Age'].mean()
  return med

def calculate_mean_age_female():
  df = pd.read_csv(f'{DATA_FOLDER}/train.csv')
  med = df.loc[df['Sex'] == 'female']['Age'].mean()
  return med

dag = DAG(
  'treino_03',
  description='Extrai dados do titanic da internet e calcula a idade media para homens ou mulheres',
  default_args=default_args,
  schedule_interval=None
)

get_data = BashOperator(
  task_id='get_data',
  bash_command=F'curl -k https://raw.githubusercontent.com/phllp/public_datasets/main/train.csv -o {DATA_FOLDER}',
  dag=dag
)

sort_sex = PythonOperator(
  task_id='sort_sex',
  python_callable=sorteia_h_m,
  dag=dag
)

handle_sex_branch = BranchPythonOperator(
  task_id='handle_sex_branch',
  python_callable=handle_sex,
  provide_context=True,
  dag=dag
)

male_branch = PythonOperator(
  task_id='male_branch',
  python_callable=calculate_mean_age_male,
  dag=dag
)

female_branch = PythonOperator(
  task_id='female_branch',
  python_callable=calculate_mean_age_female,
  dag=dag
)

print_mean_age = PythonOperator(
  task_id='print_mean_age',
  python_callable=print_age,
  provide_context=True,
  dag=dag
)

get_data >> sort_sex >> handle_sex_branch >> [male_branch, female_branch]
male_branch >> print_mean_age
female_branch >> print_mean_age


import pandas as pd
from datamallet.visualization import AutoPlot
df = pd.read_csv('data/tips.csv')

autoplot = AutoPlot(df=df, filename='basic',
                    include_scatter=True)

print(autoplot.chart_type())
list_of_figures = autoplot.show()


import cv2
import numpy as np

src_img = np.load('./data/data_3df0.npy')
src_lab = np.load('./data/label_3df0.npy')
print(src_img.shape)

ind = 100
# cv2.imshow('Imgae '+str(ind)+' CPA: '+str(src_lab[ind]), src_img[ind])
# cv2.waitKey(0)
cv2.imwrite('./img/Imgae '+str(ind)+' CPA: '+str(src_lab[ind]) + '.jpg', src_img[ind])


from django.template.loader import render_to_string

# from .models import Color, Idea

# product contrast choices
DARK = 'Dark'
LIGHT = 'Light'
CONTRAST_CHOICES = (
	(DARK, 'Dark'),
	(LIGHT, 'Light'),
	)

# Filters for Product List page ``dropdown``
portfolio_filters = {'title': 'Sort A-Z',
					'-our_rating': 'Best Match',
					'-created': 'Newest',
					'sale_price': 'Price Lowest to Highest'}

# Product shuffler
# def shuffle_products():
# 	x = [[i] for i in Product.objects.all()]
# 	shuffle(x)
# 	products = []
# 	for ea in x:
# 		products.append(ea[0])
# 	return products


import pytest

from CBLClient.FileLogging import FileLogging
from keywords.utils import log_info

log_level_dict = {
    "debug": 0,
    "verbose": 1,
    "info": 2,
    "warning": 3,
    "error": 4,
}

@pytest.mark.listener
@pytest.mark.database
@pytest.mark.parametrize("log_level, plain_text, max_size, max_rotate_count", [
    pytest.param("verbose", True, 1000 * 512 * 1000, 1000, marks=pytest.mark.ce_sanity),
    ("verbose", False, 0, 0),
    ("info", False, 0, 0),
    ("warning", False, 0, 0),
    ("error", False, 0, 0),
    ("debug", True, 3 * 512 * 1000, 3),
    ("verbose", True, 4 * 512 * 1000, 4),
    ("info", True, 5 * 512 * 1000, 5),
    ("warning", True, 6 * 512 * 1000, 6),
    ("error", True, 7 * 512 * 1000, 7),
    pytest.param("verbose", True, 1000 * 512 * 1000, 1000, marks=pytest.mark.sanity)
])
def test_file_logging(params_from_base_test_setup, log_level, plain_text, max_size, max_rotate_count):
    base_url = params_from_base_test_setup["base_url"]
    liteserv_version = params_from_base_test_setup["liteserv_version"]
    liteserv_platform = params_from_base_test_setup["liteserv_platform"]
    log_info(liteserv_platform)
    log_obj = FileLogging(base_url)

    log_directory = log_obj.configure(log_level=log_level, plain_text=plain_text,
                                      max_rotate_count=max_rotate_count, max_size=max_size)
    log_info("logs are enabled at: {}".format(log_directory))
    if liteserv_version < "2.5.0":
        pytest.skip('This test cannot run with CBL version below 2.5.0')

    cbl_log_level = log_obj.get_log_level()
    cbl_plain_text = log_obj.get_plain_text_status()
    cbl_max_size = log_obj.get_max_size()
    cbl_max_rotate_count = log_obj.get_max_rotate_count()
    log_info("log_level {}, max_size {}, max_rotate_count {}, plain_text_status {}".format(cbl_log_level, cbl_max_size,
                                                                                cbl_max_rotate_count,
                                                                                cbl_plain_text))

    if max_size == 0 and "c-" not in liteserv_platform:
        max_size = 524288

    if max_rotate_count == 0 and "c-" not in liteserv_platform:
        max_rotate_count = 1

    assert log_level_dict[log_level] == cbl_log_level, "Actual log levels is not matching with the set log level"
    assert plain_text == cbl_plain_text, "Actual plain text status is not matching with set plain text status"
    assert max_size == cbl_max_size, "Actual max_size is not matching with set max_size"
    assert max_rotate_count == cbl_max_rotate_count, "Actual max_rotate_count is not matching with set max_rotate_count"


import cv2
import sys
import json
import util
import pytesseract

bw_threshold = 160
image_density_threshold = 0.001

def main():
    if len(sys.argv) < 2:
        raise Exception("Inputs:\n\tparameter 1: Test image to use for processing.")
    input_image = sys.argv[1]
    print("Image: %s" % input_image)
    image = cv2.imread(input_image)
    img_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    img_bw =cv2.imread(input_image, cv2.IMREAD_GRAYSCALE)
    x_coords, y_coords = util.get_cell_boundaries(img_bw)
    row = 0
    for y_coord in y_coords:
        column = 0
        for x_coord in x_coords:
            raw_image = img_rgb[y_coord[0]:y_coord[1], x_coord[0]:x_coord[1]]
            image_height, image_width = img_bw.shape
            image_sum = raw_image.sum()
            image_density = image_sum / (image_width * image_height * 255)
            if image_density < image_density_threshold or image_density >= 1 - image_density_threshold:
                number = 0
            else:
                custom_oem_psm_config = r'--oem 3 --psm 10'
                number = pytesseract.image_to_string(image, config=custom_oem_psm_config)
                util.show_image(raw_image,
                                title="Row %s, col %s: %s" % (row, column, number))
            print("Row %s\tColumn %s\t%s" % (row, column, number))
            column += 1
        row += 1

if __name__ == '__main__':
    main()


from random import randint

newList = [randint(0,50) for i in range(20)]

value = randint(0,50)

#newList[randint(0, len(newList))] = value

for i, n in enumerate(newList):
    print(f"{i}: {n}")

print(f"buscando o valor {value}")

valueIndex = ""
i = 0
while i < len(newList):
    if(newList[i] == value):
        valueIndex = i
        break
    i += 1

if valueIndex != "":
    print(f"o valor {value} foi encontrado na posição {i}")
else:
    print(f"valor {value} nao encontrado na lista")


from xd.definition import SimpleTypeDef, AttributeGroupDef, AttributeDec
from xd.builtins import *

def test_simple_type_def():
    decimal = SimpleTypeDef(
        name='decimal',
        basedef=anySimpleType,
        primative=primative.decimal,
    )
    decimal._validfacets = [
        totaldigits.name, fractiondigits.name, pattern.name, whitespace.name,
        enumeration.name, maxinclusive.name, maxexclusive.name,
        mininclusive.name, minexclusive.name,
    ]
    integer = SimpleTypeDef(
        name='integer',
        basedef=decimal,
    )
    integer._validfacets = [
        totaldigits.name, fractiondigits.name, pattern.name, whitespace.name,
        enumeration.name, maxinclusive.name, maxexclusive.name,
        mininclusive.name, minexclusive.name,
    ]
    # SimpleTypeDef's primative method is inherited from base
    # definition.
    assert integer.primative == primative.decimal

def test_attribute_group():
    group = AttributeGroupDef('foo')
    assert group.name == 'foo'
    group.targetns = 'bar'
    assert group.targetns == 'bar'
    group.attributes.append(AttributeDec('bang'))
    assert len(group.attributes) == 1


T = int(input())
for tc in range(T):
    N, M, L = map(int, input().split())
    adj = [0 for _ in range(N+1)]
    for i in range(M):
        n, x = map(int, input().split())
        adj[n] = x

    print('#{}'.format(tc+1), end=' ')
    for j in range(N, -1, -1):
        if j % 2 == 0:
            if j+1 <= N:
                adj[j//2] = adj[j] + adj[j+1]
            else:
                adj[j//2] = adj[j]
            if j // 2 == L:
                print(adj[L])
                break
################################################
# def dfs(idx) :
#     if idx > N : return
#     if tree[idx] > 0 : return
#     dfs(idx * 2) # left subtree 값 채우기
#     dfs(idx * 2 + 1) # right subtree 값 채우기
#
#     # tree[idx]= tree[idx * 2 ] + tree[idx * 2 + 1]
#     if idx * 2 <= N : tree[idx] += tree[idx * 2]
#     if idx * 2 + 1 <= N : tree[idx] += tree[idx * 2 + 1]
#
#
# T = int(input())
# for tc in range(1, T + 1) :
#     N,M,L = map(int, input().split())
#     tree = [0] * (N + 1)
#     for i in range(M):
#         a,b = map(int, input().split())
#         tree[a] = b
#
#     dfs(1)
#     print("#{} {}".format(tc, tree[L]))
################################################
# def dfs(idx) :
#     if idx > N : return 0
#     if tree[idx] > 0 : return tree[idx]
#     a = dfs(idx * 2) # left subtree 값 채우기
#     b = dfs(idx * 2 + 1) # right subtree 값 채우기
#     tree[idx] = a + b
#     return tree[idx]
#
#
# T = int(input())
# for tc in range(1, T + 1) :
#     N,M,L = map(int, input().split())
#     tree = [0] * (N + 1)
#     for i in range(M):
#         a,b = map(int, input().split())
#         tree[a] = b
#
#     dfs(1)
#     print("#{} {}".format(tc, tree[L]))
################################################


import tensorflow as tf

class SimpleResnetModel():
  def __init__(self, n_classes, training_phase, dropout_rate=0.4):
    self.n_classes = n_classes
    self.training_phase = training_phase
    self.dropout_rate = dropout_rate

  def residual_bn_relu_conv2d(self, x, filters, kernel_size):
    bn1 = tf.layers.batch_normalization(x, axis=1)
    relu1 = tf.nn.relu(bn1)
    conv1 = tf.layers.conv2d(relu1, filters=filters, kernel_size=kernel_size, strides=[1, 1], padding="same", activation=None)
    bn2 = tf.layers.batch_normalization(conv1, axis=1)
    relu2 = tf.nn.relu(bn2)
    conv2 = tf.layers.conv2d(relu2, filters=filters, kernel_size=kernel_size, strides=[1, 1], padding="same", activation=None)

    input_channel = x.get_shape().as_list()[-1]
    output_channel = conv2.get_shape().as_list()[-1]

    if input_channel != output_channel:
      pooled_input = tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 1, 1, 1], padding='SAME')
      padded_input = tf.pad(pooled_input, [[0, 0], [0, 0], [0, 0], [input_channel // 2, input_channel // 2]])
    else:
      padded_input = x

    return conv2 + padded_input

  def buildModel(self, x):
    nodes = {}
    conv1 = tf.layers.conv2d(x, filters=8, kernel_size=[5,5], strides=[2, 2], padding="same", activation=None)
    res_block1 = self.residual_bn_relu_conv2d(conv1, filters=16, kernel_size=[3,3])
    res_block2 = self.residual_bn_relu_conv2d(res_block1, filters=32, kernel_size=[3,3])
    res1_flat = tf.contrib.layers.flatten(res_block2)
    dense = tf.layers.dense(inputs=res1_flat, units=1024, activation=tf.nn.relu)
    dropout = tf.layers.dropout(inputs=dense, rate=self.dropout_rate, training=self.training_phase)
    nodes['logits'] = tf.layers.dense(inputs=dropout, units=self.n_classes)
    return nodes


import math
'''
Implementation of the left hand sum and the trapazoid
methods of numerical integration.
'''
def leftsum(f, a, b, n):
# f: continuous funciton to estimate the signed area for
# a and b: the limets of integration (with a<b)
# n: the number of subintervals desired
  h = (b - a) / n
  print("Left Sum: ", h * sum( f(a+i*h) for i in range(n)) )
               #      |     \                    |
               #  Step size  summation       of all my rectangles
               #  (factored out)
def trapezoid(f, a, b, n):
# f: continuous funciton to estimate the signed area for
# a and b: the limets of integration (with a<b)
# n: the number of subintervals desired
  h = (b - a) / n
  # summation form of an integral with a divide by zero check
  ival = h * sum( (f(a+i*h) + f(a+i*h+h))/2 for i in range(n))
  print("Trapazoid: ", ival)

# For 10^-12 error max, trap needs 2473082 steps
#
print("2a")
leftsum(lambda x: math.exp(math.sin(x)), 0, 3, 100)
trapezoid(lambda x: math.exp(math.sin(x)), 0, 3, 100)

# For 10^-12 error max, trap needs 9724300 steps
#
print("2b")
leftsum(lambda x: x**2 * math.log(x) + 100, 1, 1000, 100)
trapezoid(lambda x: x**2 * math.log(x) + 100, 1, 1000, 100)

# For 10^-12 error max, trap needs 14907120 steps
#
print("2c")
leftsum(lambda x: math.sin(x) / x, -10, 10, 101)
trapezoid(lambda x: math.sin(x) / x, -10, 10, 101)
# In assignment 4, the program computed the ln(b)


from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render
import re

class SessionFilter(MiddlewareMixin):
    def process_request(self,request):
        if (request.session.get('user_id') or request.session.get('customer_id')):
            return None
        else:
            #寰呮坊鍔犻�昏緫锛氭暟娆¤緭鍏ュ瘑鐮侀敊璇嫆缁濈櫥闄�
            out = ['ad/regist',
                    'ad/login',]#域名过滤列表
            f = None
            for o in out:
                n = re.search(o,request.get_full_path().lower())
                if n:
                    f = n
            if  f:
                return None
            else:
                return render(request, 'login.html')


from base64 import encode
import os.path
from flask import Blueprint, jsonify, render_template, url_for, send_file
from flask_login import login_required, current_user
from ..controller.ordemDeServicoController import (
    abertura_OrdemDeServico,
    registra_orcamento,
    aceita_ordemDeServico,
    avaliar_ordemServico,
    atender_ordemDeServico,
    concluir_ordemDeServico,
    finalizar_ordemDeServico,
    relatorio_ordemDeServico,
    busca_personalizada_ordemDeServico,
    relatorio_financeiro,
    altera_orcamento_ordemDeServico,
    total_ordemDeServico_status,
    busca_os_status_home,
    cancelar_ordemDeServico
)

ordem = Blueprint('ordem', __name__)

@ordem.route('/OrdemDeServico/Abertura', methods=['POST'])
@login_required
def abre_ordemDeServico():
    return abertura_OrdemDeServico(current_user.id)

@ordem.route('/OrdemDeServico/Alterar/<int:codigo>', methods=['POST'])
@login_required
def altera_route_financeiro(codigo):
    return altera_orcamento_ordemDeServico(codigo, current_user.id)

@ordem.route('/OrdemDeServico/Aceita/<int:codigo>', methods=['POST'])
@login_required
def aceit_ordemDeServico(codigo):
    tipo_usuario_logado = current_user.tipoFuncionario.name
    if tipo_usuario_logado == 'GERENTE' or tipo_usuario_logado == 'MECANICO':
        return aceita_ordemDeServico(codigo, current_user.id)
    else:
        return jsonify({'msg': "Usuário sem permissão"}), 401

@ordem.route('/OrdemDeServico/RegistraOrcamento/<int:codigo>', methods=['POST'])
@login_required
def regis_ordemDeServico(codigo):
    tipo_usuario_logado = current_user.tipoFuncionario.name
    if tipo_usuario_logado == 'GERENTE' or tipo_usuario_logado == 'MECANICO':
        return registra_orcamento(codigo, current_user.id)
    else:
        return jsonify({'msg': "Usuário sem permissão"}), 401

@ordem.route('/OrdemDeServico/Cancelar/<int:codigo>', methods=['POST'])
@login_required
def cancelar_ordemDeServico_route(codigo):
    return cancelar_ordemDeServico(codigo, current_user.id)

@ordem.route('/OrdemDeServico/Avaliar/<int:codigo>', methods=['POST'])
@login_required
def avalia_ordemDeServico(codigo):
    return avaliar_ordemServico(codigo, current_user.id)

@ordem.route('/OrdemDeServico/Atender/<int:codigo>', methods=['POST'])
@login_required
def atende_ordemDeServico(codigo):
    tipo_usuario_logado = current_user.tipoFuncionario.name
    if tipo_usuario_logado == 'GERENTE' or tipo_usuario_logado == 'MECANICO':
        return atender_ordemDeServico(codigo, current_user.id)
    else:
        return jsonify({'msg': "Usuário sem permissão"}), 401

@ordem.route('/OrdemDeServico/Concluir/<int:codigo>', methods=['POST'])
@login_required
def conclui_ordemDeServico(codigo):
    tipo_usuario_logado = current_user.tipoFuncionario.name
    if tipo_usuario_logado == 'GERENTE' or tipo_usuario_logado == 'MECANICO':
        return concluir_ordemDeServico(codigo, current_user.id)
    else:
        return jsonify({'msg': "Usuário sem permissão"}), 401

@ordem.route('/OrdemDeServico/Finalizar/<int:codigo>', methods=['POST'])
@login_required
def finaliza_ordemDeServico(codigo):
    return finalizar_ordemDeServico(codigo, current_user.id)

@ordem.route('/OrdemDeServico/Relatorio/OrdemDeServico', methods=['POST'])
@login_required
def relatorio_route_ordemDeServico():
    return relatorio_ordemDeServico()

@ordem.route('/OrdemDeServico/BuscaPersonalizada', methods=['POST'])
@login_required
def busca_route_ordemDeServico():
    return busca_personalizada_ordemDeServico()

@ordem.route('/OrdemDeServico/Relatorio/Financeiro', methods=['POST'])
@login_required
def relatorio_route_financeiro():
    tipo_usuario_logado = current_user.tipoFuncionario.name
    if tipo_usuario_logado == 'GERENTE':
        return relatorio_financeiro()
    else:
        return jsonify({'msg': "Usuário sem permissão"}), 401

@ordem.route('/OrdemDeServico/Home/Totais', methods=['POST'])
@login_required
def total_os_route():
    return total_ordemDeServico_status(current_user)

@ordem.route('/OrdemDeServico/Home/BuscaOS', methods=['POST'])
@login_required
def busca_os_home():
    return busca_os_status_home(current_user)


import subprocess
import json

# Get the nodePort using kubectl
node_port_command = "kubectl get --namespace default -o jsonpath='{.spec.ports[0].nodePort}' services demo-backend"
node_port_process = subprocess.Popen(node_port_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
node_port_output, node_port_error = node_port_process.communicate()

# Get the node IP using kubectl
node_ip_command = "kubectl get nodes --namespace default -o jsonpath='{.items[0].status.addresses[0].address}'"
node_ip_process = subprocess.Popen(node_ip_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
node_ip_output, node_ip_error = node_ip_process.communicate()

# Check if there were any errors
if node_port_process.returncode != 0:
    print(f"Error getting nodePort: {node_port_error.decode('utf-8')}")
    exit(1)

if node_ip_process.returncode != 0:
    print(f"Error getting node IP: {node_ip_error.decode('utf-8')}")
    exit(1)

# Extract values from the command output
node_port = node_port_output.decode('utf-8')
node_ip = node_ip_output.decode('utf-8')

# Construct the URL
url = f"http://{node_ip.strip()}:{node_port.strip()}"
print(url)


# I. INSERTION sort, O(n^2)
def insertionSort(array):
    # First step: choose next element from the unsorted (right) part
    for elem_index in range(1, len(array)):
        elem_value = array[elem_index]

        # Second step: compare the element with each position
        # on the left (sorted part) till the lower one is found
        index_to_compare = elem_index - 1
        while index_to_compare >= 0 and elem_value < array[index_to_compare]:
            array[index_to_compare + 1] = array[index_to_compare]
            index_to_compare -= 1

        # Third step: put the element at the next position after the lower value
        array[index_to_compare + 1] = elem_value
    return array

# II. HEAP sort, O(nlogn)
def heapify(array, N, i):
    # On each run of heapify, we want to find the largest value
    # among parent (i), child_1 (l) & child_2 (r)
    largest     = i
    left_child  = 2 * i + 1
    right_child = 2 * i + 2

    # Check if left child exists and is greater than parent
    if left_child < N and array[largest] < array[left_child]:
        largest = left_child

    # Check if right child exists and is greater than the largest
    if right_child < N and array[largest] < array[right_child]:
        largest = right_child

    # if parent is not largest, change their positions
    if largest != i:
        array[i], array[largest] = array[largest], array[i]
        heapify(array, N, largest)

# The main function for sorting, which is called directly by user
def heapSort(array):
    N = len(array)

    # First step: make all parents greater than their children
    # We do not need the indices after N // 2, since these are of the last level
    for i in range(N//2 - 1, -1, -1): heapify(array, N, i)

    # Second step: continue building heap and putting the max. root to the end
    for i in range(N-1, 0, -1):
        array[i], array[0] = array[0], array[i]
        heapify(array, i, 0)
    return array

# III. COUNT sort O(n+k)
def countSort(array, func=lambda x: x):
    # First step: initialize all arrays (incl. count bins)
    k      = len(array)
    output = [0] * len(array)
    count  = [0] * 10

    # Second step: count appearance of each value & where it should stand
    for i in range(k): count[func(array[i])] += 1
    for i in range(1, 10): count[i] += count[i-1]

    # Third step: place all elements on the respective place
    for i in range(k-1,-1,-1):
        output[count[func(array[i])] - 1] = array[i]
        count[func(array[i])]            -= 1

    for i in range(k): array[i] = output[i]
    return array

# IV. BINARY INSERTION sort O(n^2)
def binInsertSort(array):
    for elem_index in range(1, len(array)):
        elem_value = array[elem_index]
        j = binary_search(array, elem_value, left=0, right=elem_index-1)
        array = array[:j] + [elem_value] \
                + array[j:elem_index] + array[elem_index+1:]
    return array

def binary_search(array, value, left, right):
    if left == right:
        if array[left] > value: return left
        return left+1
    if left > right: return left

    middle = (left + right)//2
    if array[middle] < value: return binary_search(array, value, middle+1, right)
    if array[middle] > value: return binary_search(array, value, left, middle-1)
    return middle


#!/usr/bin/python3
import socket
import threading
import pygame
import widgets

class MasterWindow:
    def __init__(self):
        pygame.init()
        self.surface = pygame.Surface((1, 1))
        self.display_clock = pygame.time.Clock()
        self.recv_clock = pygame.time.Clock()
        self.framerate = 30
        self.widgets = {'conn_ip_addr': widgets.common.TextBox((0, 0, 100, 20)),
                        'conn_port': widgets.common.TextBox((110, 0, 50, 20)),
                        'connect_button': widgets.button.ButtonWithText((170, 0, 50, 20), self.connect_from_window,
                                                                        'Connect!'),
                        'connect_indicator': widgets.common.Indicator((230, 0, 20, 20))}
        self.running = True
        self.do_draw_loop = True
        self.socket = socket.socket()
        self.connected = False
        self.packets = {}
        self.packet_num = 0
        self.init_screen()
        self.draw_loop_thread = threading.Thread(target=self.draw_loop, name='draw loop', daemon=False)
        self.draw_loop_thread.start()
        self.recv_loop_thread = threading.Thread(target=self.recv_packets, name='recv loop', daemon=True)
        self.recv_loop_thread.start()

    def init_screen(self):
        self.surface = pygame.display.set_mode((400, 50))

    def connect_from_window(self):
        self.widgets['connect_indicator'].color = pygame.Color('red')
        ip = self.widgets['conn_ip_addr'].text
        port = int(self.widgets['conn_port'].text)
        self.connect(ip, port)

    def connect(self, ip: str, port: int):
        self.widgets['connect_indicator'].color = pygame.Color('red')
        try:
            self.socket = socket.socket()
            self.socket.settimeout(0.01)
            self.socket.connect((ip, port))
            self.connected = True
            self.widgets['connect_indicator'].color = pygame.Color('green')
        except (ConnectionRefusedError, ConnectionAbortedError, ConnectionResetError, socket.timeout, socket.timeout):
            pass

    def draw_loop(self):
        while self.running:
            if self.do_draw_loop:
                self.draw()

    def draw(self):
        self.display_clock.tick(self.framerate)
        self.surface.fill(pygame.Color('black'))
        for i in self.widgets:
            self.widgets[i].draw(self.surface)
        pygame.display.flip()

        for i in pygame.event.get():
            for j in self.widgets:
                self.widgets[j].inform(i)
            if i.type == pygame.QUIT:
                exit()

    def recv_packets(self):
        while self.running:
            if self.connected:
                self.recv_clock.tick(self.framerate)
                data = b''

                def eot(msg: bytes) -> bool:
                    try:
                        return msg[-1] == b'\n'[0]
                    except IndexError:
                        return False

                while not eot(data):
                    try:
                        newdata = self.socket.recv(1024)
                    except socket.timeout:
                        newdata = b''
                    except ConnectionRefusedError:
                        self.connected = False
                        self.widgets['connect_indicator'].color = pygame.Color('red')
                        break
                    data += newdata
                data = data.strip()
                self.parse_packet(data)

    def send(self, data: bytes):
        self.packet_num += 1
        self.packets.update({self.packet_num: data})
        try:
            self.socket.sendall(bytes(str(self.packet_num), 'utf8') + b':' + data)
        except BrokenPipeError:
            self.connected = False
            raise BrokenPipeError('Connection broken!')

    def parse_packet(self, data: bytes):
        id, response = data.split(b':')
        id = int(id)
        command = self.packets.pop(id)
        print(command, '->', response)

if __name__ == '__main__':
    w = MasterWindow()


# jikwon 테이블을 대상으로 사번과 이름을 입력(로그인)해 해당 자료가 있다면
# 해당 직원이 근무하는 부서 직원을 직급별 오름차순으로 모두 출력, 직급이 같다면 이름별 오름차순 출력
# 출력 형태 : 사번, 이름, 부서명, 직급, 성별
# 다음으로 해당 직원이 관리하는 고객 자료 출력
# 출력 형태 : 고객번호, 고객명, 고객전화, 나이
import MySQLdb
import pickle
with open('mydb.dat', 'rb') as obj:
    config = pickle.load(obj)

def start():
    try:
        conn = MySQLdb.connect(**config)
        cursor = conn.cursor()
        jikwon_no = input('사번 입력:')
        jikwon_name = input('이름 입력:')
        sql = '''
                select jikwon_no, jikwon_name, buser_name, jikwon_jik, jikwon_gen from jikwon
                join buser on buser_num = buser_no
                where buser_num = (select buser_num from jikwon where jikwon_no={0} and jikwon_name="{1}")
                order by jikwon_jik, jikwon_name
                '''.format(jikwon_no, jikwon_name)

        cursor.execute(sql)
        datas = cursor.fetchall()

        if len(datas) == 0:
            return
        for r in cursor:
            print(r[0], r[1], r[2], r[3], r[4])
        print('인원수 : ' + str(len(datas)))

        sql = '''
                select gogek_no, gogek_name, gogek_tel, cast(2023 -((left(gogek_jumin, 2))+1900)as signed integer) from gogek
                inner join jikwon on gogek_damsano = jikwon_no
                where gogek_damsano = (select jikwon_no from jikwon where jikwon_no={0} and jikwon_name="{1}")
                '''.format(jikwon_no, jikwon_name)

        cursor.execute(sql)
        datas2 = cursor.fetchall()

        print("\n-고객 정보-")
        if len(datas2) == 0:
            print(jikwon_name + '의 담당 고객은 없습니다')
            return
        for gogek_no, gogek_name, gogek_tel, gogek_jumin in datas2:
            print(gogek_no, gogek_name, gogek_tel, gogek_jumin)
        print('인원수 : ' + str(len(datas2)))

    except Exception as e:
        print("err : ", e)
    finally:
        cursor.close()
        conn.close()

if __name__ == '__main__':
    start()


## BOILERPLATE ##
import sys
from PySide import QtGui, QtCore
if QtCore.QCoreApplication.instance() is None:
    app = QtGui.QApplication(sys.argv)
    import qt4reactor
    qt4reactor.install()
## BOILERPLATE ##
from goto import MIN, MAX, PRECISION, SLIDER, POI, GotoWidget
from config.steppermotor import POL, SM_CONFIG
from qtutils.label import LabelWidget
from steppermotorclient import StepperMotorClient
from polarizerclient import PolarizerClient
from twisted.internet.defer  import Deferred, inlineCallbacks, returnValue
from functools import partial
from config.serverURLs import POLARIZER_SERVER, TEST_POLARIZER_SERVER, STEPPER_MOTOR_SERVER, TEST_STEPPER_MOTOR_SERVER

class PolarizerWidget(QtGui.QWidget):
    def __init__(self,polarizerProtocol,stepperMotorProtocol):
        QtGui.QWidget.__init__(self)
        self.setLayout(QtGui.QVBoxLayout())
        self.polSMC = StepperMotorClient(stepperMotorProtocol,POL)

        gotoWidget = GotoWidget(
            {
                MIN:-360,
                MAX:360,
                PRECISION:.1,
                SLIDER:2,
                POI:{}
            }
        )
        self.layout().addWidget(LabelWidget('angle',gotoWidget))

        # send command to tracking server when goto requested
        @inlineCallbacks
        def onGotoRequested(payload):
            angle, deferred = payload
            yield polarizerProtocol.sendCommand('set-angle',angle)
            deferred.callback(None)
        gotoWidget.gotoRequested.connect(onGotoRequested)

        # handle update requests (should the position fall out of sync)
        def onUpdateReqested():
            polarizerProtocol.sendCommand('get-angle').addCallback(gotoWidget.setPosition)
        gotoWidget.updateRequested.connect(onUpdateReqested)

        # send cancel request when goto widget requests
        gotoWidget.cancelRequested.connect(partial(polarizerProtocol.sendCommand,'cancel-angle-set'))

        # set goto widget position on polarizer sm position change
        self.polSMC.addListener(
            self.polSMC.POSITION,
            lambda _:polarizerProtocol.sendCommand('get-angle').addCallback(gotoWidget.setPosition)
        )

        # initialize position of goto widget
        polarizerProtocol.sendCommand('get-angle').addCallback(gotoWidget.setPosition)

        '''
        # add enable button to toggle state of sm
        enableButton = QtGui.QPushButton('enable', self)
        enableButton.clicked.connect(self.polSMC.toggleStatus)
        def adjustEnbStatus(status):
            if status == 'enabled':
                enableButton.setText('disable')
                gotoWidget.setEnabled(True)
            elif status == 'disabled':
                enableButton.setText('enable')
                gotoWidget.setEnabled(False)
        self.polSMC.addListener(self.polSMC.ENABLE,adjustEnbStatus)
        self.layout().addWidget(enableButton)
        '''

    def closeEvent(self, event):
        event.accept()
        quit()

@inlineCallbacks
def main():
    import sys
    from ab.abclient import getProtocol
    DEBUG = len(sys.argv) > 1 and sys.argv[1] == 'debug'
    polarizerProtocol = yield getProtocol(
        TEST_POLARIZER_SERVER if DEBUG else POLARIZER_SERVER
    )
    stepperMotorProtocol = yield getProtocol(
        TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER
    )
    #memory management nonsense
    container.append(PolarizerWidget(polarizerProtocol,stepperMotorProtocol))
    container[0].show()
    container[0].setWindowTitle('polarizer client ' + ('debug ' if DEBUG else 'real '))

if __name__ == '__main__':
    from twisted.internet import reactor
    container = []
    main()
    reactor.run()


import tkinter
from tkinter import *

root = Tk()
root.title("Grade calculator")
root.geometry("500x400")

def Calculation():
    english=int(englishentry.get())
    skill=int(anlytical_skillentry.get())
    general=int(generalentry.get())
    total=(english+skill+general)
    Label(text=f"{total}", font="arial 15 bold").place(x=250, y=170)

    average=int(total/3)
    Label(text=f"{average}", font="arial 15 bold").place(x=250, y=210)
    if (average>50):
        grade = "pass"
    else:
        grade = "Fail"

    Label(text=f"{grade}", font="arial 15 bold", fg="blue").place(x=250, y=250)

#coloca os nome que irão aparecer na janela
sub1 = Label(root, text="English: ", font="arial 10")
sub2 = Label(root, text="Analytical: ", font="arial 10")
sub3 = Label(root, text="General knowledge: ", font="arial 10")
total = Label(root, text="total: ", font="arial 10")
avg = Label(root, text="Average: ", font="arial 10")
grade = Label(root, text="Grade: ", font="arial 10")

sub1.place(x=50, y=20)
sub2.place(x=50, y=70)
sub3.place(x=50, y=120)
total.place(x=50, y=170)
avg.place(x=50, y=210)
grade.place(x=50, y=250)

englishvalue=StringVar()
anlytical_skillvalue=StringVar()
generalvalue=StringVar()

englishentry =Entry(root, textvariable=englishvalue, font="arial 15", width=15)
anlytical_skillentry =Entry(root, textvariable=anlytical_skillvalue, font="arial 15", width=15)
generalentry =Entry(root, textvariable=generalvalue, font="arial 15", width=15)

#Coloca as barras onde voce coloca os numeros.
englishentry.place(x=250, y=20)
anlytical_skillentry.place(x=250, y=70)
generalentry.place(x=250, y=120)

#Colocar botão de calcular e sair
Button(text="Calculate", font="arial 15", bg="white",bd=10, command=Calculation).place(x=50, y=300)
Button(text="Exit", font="arial 15", bg="white",bd=10,  width=8, command=lambda:exit()).place(x=350, y=300)
root.mainloop()


'''
UMLS Metathesaurus

Current Functionality
+ Simple Concept object (interface for definitions, term sets, etc.)
+ Build dictionaries of UMLS semantic types
+ Build positive examples of UMLS relations

There are many other tools that do similar things, though none have a
distant supervision focus (and there is a bias towards Perl-based tools)

UMLS::Interface    http://search.cpan.org/~btmcinnes/UMLS-Interface-1.47/
UMLS::Similarity   http://search.cpan.org/~btmcinnes/UMLS-Similarity-1.45/

This functionality should be eventually incorporated into bio-ddlib, esp.
the graph and path-based similarity measures.

TODO
+ implement similarity and relatedness measures from UMLS::Similarity
+ path-based feature generator
+ keyword expansion/similarity using word embeddings

@author Jason Alan Fries

'''
from __future__ import print_function

import sys
import ontologies.umls as umls
from ontologies.umls.graph import pprint_tree

meta = umls.Metathesaurus()
norm = umls.MetaNorm(function=lambda x:x.lower())

#
# UMLS Concepts and Relations
#

# UMLS Semantic Network
taxonomy = meta.semantic_network.graph(relation="isa")
root_nodes = ([node for node in taxonomy if not taxonomy.predecessors(node)])
for node in root_nodes:
    pprint_tree(taxonomy,node)

# UMLS semantic groups

print( meta.semantic_network.groups["Anatomy"] )

# UMLS normalizes concepts with a CUI (Concept Unique Identifier)
# e.g., C0002645 is 'Amoxycillin'
concept = meta.concept(cui='C3539739')
concept.print_summary()

# List all relations on a specific concept
relations = meta.relations_on_cui("C0002645",source_vocab=["SNOMEDCT_US"])
rel = list(set([rela[2] for rela in relations]))
print(rel)

# Search for concepts (CUIs) by string. This is a noisy match. We don't perform
# any disambiguation so CUIs are not guaranteed to actually be related.
matches = meta.match_concepts("Cu", match_substring=False)
print("Found %d string->concept matches" % len(matches))
for cui in matches:
    concept = meta.concept(cui=cui)
    concept.print_summary()

#
# Building Dictionaries and Relation Tuples
#

'''
# List all semantic types, relations, and source vocabularies
print(meta.get_source_vocabulary_defs())
print(sorted(meta.get_semtypes_list()))
print(sorted(meta.get_relations_list()))
'''
'''
# Build dictionaries for a given semantic type (i.e., entity)
d = meta.dictionary("Disease or Syndrome")
d = map(norm.normalize,d)
for term in sorted(d,key=lambda x:len(x.split()),reverse=1):
    print(term)
'''

# Generate relation examples from given semantic types. This is
# highly dependent on the choice of source vocabulary.
attribute ="may_prevent"
relations = meta.relations("Substance","Biologic Function",attribute)
print("Found %d distinct relation pairs" % len(relations))

# Print concept terms (this can be expanded by using concept.all_terms()
# rather than just the preferred term).
for cui1,cui2 in relations:

    terms_cui1 = map(norm.normalize, meta.concept(cui1).all_terms())
    terms_cui2 = map(norm.normalize, meta.concept(cui2).all_terms())

    terms_cui1 = "|".join(terms_cui1)
    terms_cui2 = "|".join(terms_cui2)

    row= [cui1, terms_cui1, attribute, cui2, terms_cui2 ]
    print("\t".join(row).encode("utf-8",errors="ignore"))


import re
import math
import argparse
import os.path
import yaml
import matplotlib.pyplot as plt
from tqdm.auto import tqdm
import pandas as pd
import numpy as np
import cv2
import joblib
# FLYHOSTEL_VIDEOS=os.environ["FLYHOSTEL_VIDEOS"]
FLYHOSTEL_VIDEOS="/Users/FlySleepLab Dropbox/Data/flyhostel_data/videos/"

from imgstore.interface import VideoCapture

LIVE_WRITING=False
RESOLUTION=(1000, 1000)

# data
# chunk, frame_number, experiment, roi, text, center, box, color, frame_index, identity, video
fontFace=cv2.FONT_HERSHEY_SIMPLEX
fontScale=2
right_text=(650, 100)

COLORS={
    "white": (255, 255, 255),
    "green": (0, 255, 0),
    "red": (255, 0, 0),
    "blue": (0, 0, 255),
}

def apply_roi(frame, roi):

    x, y, w, h = roi
    return frame[y:(y+h), x:(x+w)]

def roi_from_data(data, suffix=None):

    columns = ["x", "y", "w", "h"]
    if suffix is not None:
        columns = [e + f"_{suffix}" for e in columns]

    roi = data[columns]
    if all(pd.isna(roi)):
        roi=None
    else:
        roi=tuple(roi.values.tolist())

    return roi

def draw_box(frame, box, color, text, thickness):
    x, y, w, h = box
    frame=cv2.rectangle(frame, (x, y), (x+w, y+h), color, thickness=thickness)
    cv2.copyMakeBorder(frame, 50, 50, 50, 50, cv2.BORDER_CONSTANT, frame, 255)

    if not np.isnan(text):
        (width, height), baseline = cv2.getTextSize(text, fontFace, fontScale, thickness)
        width=int(width*1.1)
        height=int(height*1.1)
        tl_corner = (int(box[2]*0.9), int(box[3]*0.9))
        tl_corner = (tl_corner[0], tl_corner[1]-height)
        br_corner = (tl_corner[0]+width, box[1])
        frame = cv2.rectangle(frame, tl_corner, br_corner, COLORS[color], -1)
        frame = cv2.putText(frame, text, tl_corner, fontFace, fontScale, COLORS["white"], 1)

    return frame

def draw_text(frame, color, text, pos, thickness=6):

    (width, height), baseline = cv2.getTextSize(text, fontFace, fontScale, thickness)
    bl_corner = pos
    tl_corner = (pos[0], pos[1]-height)
    br_corner = (pos[0]+width, pos[1])
    # print(tl_corner)
    # print(br_corner)

    # frame = cv2.rectangle(frame, tl_corner, br_corner, COLORS[color], -1)
    frame=cv2.putText(frame, text, pos, fontFace, fontScale, COLORS["white"], thickness)
    return frame

def annotate_frame(frame, data):

    for i, row in data.iterrows():
        box =roi_from_data(data, "box")
        if box is not None:
            frame = draw_box(frame, box, row["color"], row["text"], thickness=2)

    return frame

def annotate_frame_resized(frame, data):
    for i, row in data.iterrows():
        frame = draw_text(frame, row["color"], row["text"], (50, 100))
    return frame

def get_parser():

    ap = argparse.ArgumentParser()
    ap.add_argument("--store-path", required=True)
    ap.add_argument("--chunk", default=50, type=int)
    ap.add_argument("--n-jobs", default=3, type=int)
    ap.add_argument("--annotation", type=str)
    return ap

def main():

    ap = get_parser()
    args = ap.parse_args()
    assert os.path.exists(args.annotation)
    data = read_user_data(args.annotation)

    experiments = list(set(data["experiment"].value.tolist()))

    joblib.Parallel(n_jobs=args.n_jobs)(
        joblib.delayed(
            make_video(data.loc[data["experiment"] == experiment])
        )
        for experiment in experiments
    )

def init_video_writer(data, fps=150):

    roi=roi_from_data(data)
    frameSize=RESOLUTION

    filename=data["video"]

    vw = cv2.VideoWriter(
        filename,
        cv2.VideoWriter_fourcc(*"mp4v"),
        fps=fps,
        frameSize=frameSize,
        isColor=True,
    )
    return vw

def build_store_path_from_experiment(experiment):
    flyhostel_id = int(re.search("FlyHostel([0-9]).*", experiment).group(1))
    number_of_animals = int(re.search("FlyHostel[0-9]_([0-9][0-9]?)X.*", experiment).group(1))
    date_time = re.search(
        "FlyHostel[0-9]_[0-9][0-9]?X_([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_[0-9][0-9]-[0-9][0-9]-[0-9][0-9])",
        experiment
    ).group(1)

    folder_structure = os.path.join(f"FlyHostel{flyhostel_id}", f"{number_of_animals}X", date_time)
    store_path = os.path.join(FLYHOSTEL_VIDEOS, folder_structure, "metadata.yaml")
    return store_path

def format_seconds(seconds):
    minutes = int(seconds // 60)
    seconds = round(seconds % 60)
    mm_ss=f"{str(minutes).zfill(2)}:{str(seconds).zfill(2)}"
    return mm_ss

def make_video(data, fps=150, before=0, after=0):

    experiment=data["experiment"].iloc[0]

    store_path = build_store_path_from_experiment(experiment)
    with open(store_path, "r") as filehandle:
        metadata = yaml.load(filehandle, yaml.SafeLoader)
        input_fps = metadata["__store"]["framerate"]

        before*=input_fps
        after*=input_fps

    n_reps = int(math.ceil(input_fps/fps))
    cap = VideoCapture(store_path, data.iloc[0]["chunk"].item())

    video_writer=init_video_writer(data.iloc[0], fps=input_fps*5)
    last_frame_number = -10

    frame_numbers=sorted(list(set(data["frame_number"].values.tolist())))
    assert all(np.diff(frame_numbers) == 1), "Videos with jumps are not supported"
    assert len(np.unique(data["experiment"])) == 1

    frame_number=frame_numbers[0]-before
    cap.set(1, frame_number)
    t0=cap.frame_time/1000
    (width, height), baseline = cv2.getTextSize("00:00", fontFace, fontScale, 6)
    timer_pos = (int(500 - width / 2), height+50)

    pb=tqdm(total=before, position=0)
    ret=True
    while frame_number < frame_numbers[0] and ret:
        ret, frame = cap.read()
        seconds=cap.frame_time/1000-t0
        mm_ss = format_seconds(seconds)

        roi=roi_from_data(data.loc[data["frame_number"] == frame_numbers[0]].iloc[0])
        if roi is not None:
            frame = apply_roi(frame, roi)
        frame = cv2.resize(frame, RESOLUTION, cv2.INTER_AREA)
        frame=cv2.putText(frame, mm_ss, timer_pos, fontFace, fontScale, COLORS["white"], 6)
        video_writer.write(frame)
        pb.update(1)
        frame_number+=1

    pb=tqdm(total=len(frame_numbers), position=1)
    for frame_number in frame_numbers:
        if (last_frame_number+1) == frame_number:
            pass
        else:
            cap.set(1, frame_number)

        last_frame_number=frame_number
        ret, frame = cap.read()
        seconds=cap.frame_time/1000-t0
        mm_ss = format_seconds(seconds)

        frame_orig = frame.copy()
        frame = annotate_frame(frame, data.loc[data["frame_number"] == frame_number])
        roi=roi_from_data(data.loc[data["frame_number"] == frame_number].iloc[0])
        if roi is not None:
            frame = apply_roi(frame, roi)

        frame = cv2.resize(frame, RESOLUTION, cv2.INTER_AREA)
        frame=annotate_frame_resized(frame, data.loc[data["frame_number"] == frame_number])

        if LIVE_WRITING:
            cv2.imshow("frame", frame)
            cv2.waitKey(1)

        frame=cv2.putText(frame, "3X slower", right_text, fontFace, fontScale, COLORS["white"], 6)
        frame=cv2.putText(frame, mm_ss, timer_pos, fontFace, fontScale, COLORS["white"], 6)

        for _ in range(n_reps):
            video_writer.write(frame)
        pb.update(1)

    if after:
        pb=tqdm(total=after, position=2)
        while frame_number < (frame_numbers[-1]+after) and ret:
            ret, frame = cap.read()
            seconds=cap.frame_time/1000-t0
            mm_ss = format_seconds(seconds)

            roi=roi_from_data(data.loc[data["frame_number"] == frame_numbers[0]].iloc[0])
            if roi is not None:
                frame = apply_roi(frame, roi)
            frame = cv2.resize(frame, RESOLUTION, cv2.INTER_AREA)

            frame=cv2.putText(frame, mm_ss, timer_pos, fontFace, fontScale, COLORS["white"], 6)
            video_writer.write(frame)
            pb.update(1)
            frame_number+=1

    cap.release()
    video_writer.release()
    return frame_orig

def read_user_data(annotation):
    data=pd.read_csv(annotation)
    data.sort_values(["experiment", "chunk", "frame_number"])
    return data


from flask import Flask, request, render_template, redirect, session
import random
import datetime
app = Flask(__name__)
app.secret_key = "SuchWowMuchNinja"

@app.route('/')
def root():
    if 'gold' not in session:
        session['gold'] = 0
    if 'strs' not in session:
        session['strs'] = []
    return render_template('index.html')

@app.route('/process/<location>', methods=['POST'])
def process_post(location):
    logStr = ""
    if location == "farm":
        result = random.randint(10,20)
    if location == "cave":
        result = random.randint(5,10)
    if location == "house":
        result = random.randint(2,5)
    if location == "casino":
        result = random.randint(-50,50)
        if result > 0:
            logStr = ("won", "Entered a Casino and won " + str(result) + " gold. Sick! " + str(datetime.datetime.now()))
        elif result < 0:
            logStr = ("lose", "Entered a Casino and lost " + str(result) + " gold. Sucks to suck. " + str(datetime.datetime.now()))
    if location != "casino":
        logStr = ("black", "Earned " + str(result) + " gold from the " + location + "! " + str(datetime.datetime.now()))
    session['gold'] += result
    new_list = session['strs']
    new_list.append(logStr)
    session['strs'] = new_list
    return redirect('/')

@app.route('/reset')
def reset():
    session.clear()
    return redirect('/')

app.run(debug=True)


from typing import List

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        n = len(nums)

        dp_max = nums[0]
        dp_min = nums[0]

        max_v = nums[0]
        min_v = nums[0]

        for i in range(1, n):
            a, b, c = dp_min*nums[i], dp_max*nums[i], nums[i]
            dp_max = max(a, b, c)
            dp_min = min(a, b, c)

            max_v = max(dp_max, max_v)
            min_v = min(dp_min, min_v)

        return max_v

nums = [-4 ,-3, -2]
ans = Solution().maxProduct(nums)
print(ans)


from enum import Enum
from .utils import val
import re

class Control:
   def GetFullName(self,enumval):
      return self.__class__._FullNameData.get(enumval.name,None)

   @property
   def ctrlcode(self):
      return f'{self.__class__._CtrlIdPrefix}{val(self)}'

def CreateControls(enumtypename,filelist,
                   name_filt_fn=None,
                   calling_module=None,
                   raw_name_regex="[\w\.]+",
                   ctrl_id_pfx='C'):

   enum_data=dict()
   full_name_data=dict()

   if not isinstance(filelist,list):
      filelist = [filelist]

   ctrls_ifh = None
   while not ctrls_ifh and len(filelist) > 0:
      filename = filelist.pop(0)
      try:
         ctrls_ifh = open(filename,'r', encoding="utf8")
      except FileNotFoundError:
         pass

   if not ctrls_ifh:
      raise FileNotFoundError("Unable to find any file in filelist")

   for line in ctrls_ifh.read().splitlines():
      ctrl_match = re.match(f"^(?P<ctrl_num>\d{{4,}})\s+(?P<raw_name>{raw_name_regex})",line)
      if ctrl_match:
         raw_name = ctrl_match.group('raw_name')
         ctrl_name = name_filt_fn(raw_name) if name_filt_fn else raw_name
         enum_data[ctrl_name] = ctrl_match.group('ctrl_num')
         full_name_data[ctrl_name] = raw_name_regex

   ctrls_ifh.close()

   if calling_module:
      enumclass = Enum(value=enumtypename,names=enum_data,type=Control,module=calling_module)
   else:
      enumclass = Enum(value=enumtypename,names=enum_data,type=Control)
   enumclass._FullNameData = full_name_data
   enumclass._CtrlIdPrefix = ctrl_id_pfx
   return enumclass

def CreateFSUIPCControls(enumtypename,filelist="fsuipc_controls.txt",
                         calling_module=None):

   return CreateControls("FsuipcCtrl",
                         filelist,
                         name_filt_fn=lambda n:
                            re.sub(pattern=r'[ /]', repl='_',
                                   string=re.sub(pattern=r'[\s*][^\w ].*',
                                                 repl='',string=n,count=1)
                                  ),
                         raw_name_regex="[\w\/ ]+\w",
                         calling_module=calling_module,
                         ctrl_id_pfx='C')


import math
def maxim(j,k):
    c=0
    for d in j:
        c=c+pow(d,2)
    print(c%k)

n,k=map(int, input().split())
j=[]
for i in range(n):
    m=input().split()
    a=list(map(int,m[1:]))
    #print(a)
    j.append(max(a))
maxim(j,k)


""" Make input station file for HypoDD
"""
import os
import config

# i/o paths
cfg = config.Config()
fout = open('input/station.dat','w')

done_list = []
f=open(cfg.fsta); lines=f.readlines(); f.close()
for line in lines:
    codes = line.split(',')
    net, sta = codes[0].split('.')
    if sta in done_list: continue
    done_list.append(sta)
    lat, lon = [float(code) for code in codes[1:3]]
    fout.write('{} {} {}\n'.format(sta, lat, lon))
fout.close()


import random
from eth2spec.test.helpers.state import (
    state_transition_and_sign_block,
    next_epoch,
)
from eth2spec.test.helpers.block import (
    build_empty_block_for_next_slot,
)
from eth2spec.test.helpers.sync_committee import (
    compute_aggregate_sync_committee_signature,
)
from eth2spec.test.context import (
    PHASE0, PHASE1,
    with_all_phases_except,
    spec_state_test,
)

def run_sync_committee_sanity_test(spec, state, fraction_full=1.0):
    committee = spec.get_sync_committee_indices(state, spec.get_current_epoch(state))
    participants = random.sample(committee, int(len(committee) * fraction_full))

    yield 'pre', state

    block = build_empty_block_for_next_slot(spec, state)
    block.body.sync_committee_bits = [index in participants for index in committee]
    block.body.sync_committee_signature = compute_aggregate_sync_committee_signature(
        spec,
        state,
        block.slot - 1,
        participants,
    )
    signed_block = state_transition_and_sign_block(spec, state, block)

    yield 'blocks', [signed_block]
    yield 'post', state

@with_all_phases_except([PHASE0, PHASE1])
@spec_state_test
def test_full_sync_committee_committee(spec, state):
    next_epoch(spec, state)
    yield from run_sync_committee_sanity_test(spec, state, fraction_full=1.0)

@with_all_phases_except([PHASE0, PHASE1])
@spec_state_test
def test_half_sync_committee_committee(spec, state):
    next_epoch(spec, state)
    yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5)

@with_all_phases_except([PHASE0, PHASE1])
@spec_state_test
def test_empty_sync_committee_committee(spec, state):
    next_epoch(spec, state)
    yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.0)

@with_all_phases_except([PHASE0, PHASE1])
@spec_state_test
def test_full_sync_committee_committee_genesis(spec, state):
    yield from run_sync_committee_sanity_test(spec, state, fraction_full=1.0)

@with_all_phases_except([PHASE0, PHASE1])
@spec_state_test
def test_half_sync_committee_committee_genesis(spec, state):
    yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.5)

@with_all_phases_except([PHASE0, PHASE1])
@spec_state_test
def test_empty_sync_committee_committee_genesis(spec, state):
    yield from run_sync_committee_sanity_test(spec, state, fraction_full=0.0)


""" Activation operators or other unary nonlinear operators"""
import torch
from torch import Tensor
from collections import OrderedDict
from .base import *
from .clampmult import multiply_by_A_signs

torch._C._jit_set_profiling_executor(False)
torch._C._jit_set_profiling_mode(False)

class BoundActivation(Bound):
    def __init__(self, attr=None, inputs=None, output_index=0, options=None):
        super().__init__(attr, inputs, output_index, options)
        self.requires_input_bounds = [0]
        self.use_default_ibp = True
        self.splittable = False

    def _init_masks(self, x):
        self.mask_pos = x.lower >= 0
        self.mask_neg = x.upper <= 0
        self.mask_both = torch.logical_not(torch.logical_or(self.mask_pos, self.mask_neg))

    def init_linear_relaxation(self, x):
        self._init_masks(x)
        self.lw = torch.zeros_like(x.lower)
        self.lb = self.lw.clone()
        self.uw = self.lw.clone()
        self.ub = self.lw.clone()

    def add_linear_relaxation(self, mask, type, k, x0, y0=None):
        if y0 is None:
            y0 = self.forward(x0)

        if type == 'lower':
            w_out, b_out = self.lw, self.lb
        else:
            w_out, b_out = self.uw, self.ub

        if mask is None:
            if isinstance(k, Tensor) and k.ndim > 0:
                w_out[:] = k
            else:
                w_out.fill_(k)
        else:
            w_out[..., mask] = (k[..., mask].to(w_out) if isinstance(k, Tensor)
                                else k)

        if (not isinstance(x0, Tensor) and x0 == 0
                and not isinstance(y0, Tensor) and y0 == 0):
            pass
        else:
            b = -x0 * k + y0
            if mask is None:
                if b.ndim > 0:
                    b_out[:] = b
                else:
                    b_out.fill_(b)
            else:
                b_out[..., mask] = b[..., mask]

    def bound_relax(self, x, init=False):
        return not_implemented_op(self, 'bound_relax')

    def bound_backward(self, last_lA, last_uA, x, reduce_bias=True, **kwargs):
        self.bound_relax(x, init=True)

        def _bound_oneside(last_A, sign=-1):
            if last_A is None:
                return None, 0
            if sign == -1:
                w_pos, b_pos, w_neg, b_neg = (
                    self.lw.unsqueeze(0), self.lb.unsqueeze(0),
                    self.uw.unsqueeze(0), self.ub.unsqueeze(0))
            else:
                w_pos, b_pos, w_neg, b_neg = (
                    self.uw.unsqueeze(0), self.ub.unsqueeze(0),
                    self.lw.unsqueeze(0), self.lb.unsqueeze(0))
            w_pos = maybe_unfold_patches(w_pos, last_A)
            w_neg = maybe_unfold_patches(w_neg, last_A)
            b_pos = maybe_unfold_patches(b_pos, last_A)
            b_neg = maybe_unfold_patches(b_neg, last_A)
            if self.batch_dim == 0:
                _A, _bias = multiply_by_A_signs(
                    last_A, w_pos, w_neg, b_pos, b_neg, reduce_bias=reduce_bias)
            elif self.batch_dim == -1:
                # FIXME: why this is different from above?
                assert reduce_bias
                mask = torch.gt(last_A, 0.).to(torch.float)
                _A = last_A * (mask * w_pos.unsqueeze(1) +
                               (1 - mask) * w_neg.unsqueeze(1))
                _bias = last_A * (mask * b_pos.unsqueeze(1) +
                                  (1 - mask) * b_neg.unsqueeze(1))
                if _bias.ndim > 2:
                    _bias = torch.sum(_bias, dim=list(range(2, _bias.ndim)))
            else:
                raise NotImplementedError

            return _A, _bias

        lA, lbias = _bound_oneside(last_lA, sign=-1)
        uA, ubias = _bound_oneside(last_uA, sign=+1)

        return [(lA, uA)], lbias, ubias

    @staticmethod
    @torch.jit.script
    def bound_forward_w(
            relax_lw: Tensor, relax_uw: Tensor, x_lw: Tensor, x_uw: Tensor, dim: int):
        lw = (relax_lw.unsqueeze(dim).clamp(min=0) * x_lw +
              relax_lw.unsqueeze(dim).clamp(max=0) * x_uw)
        uw = (relax_uw.unsqueeze(dim).clamp(max=0) * x_lw +
              relax_uw.unsqueeze(dim).clamp(min=0) * x_uw)
        return lw, uw

    @staticmethod
    @torch.jit.script
    def bound_forward_b(
            relax_lw: Tensor, relax_uw: Tensor, relax_lb: Tensor,
            relax_ub: Tensor, x_lb: Tensor, x_ub: Tensor):
        lb = relax_lw.clamp(min=0) * x_lb + relax_lw.clamp(max=0) * x_ub + relax_lb
        ub = relax_uw.clamp(max=0) * x_lb + relax_uw.clamp(min=0) * x_ub + relax_ub
        return lb, ub

    def bound_forward(self, dim_in, x):
        self.bound_relax(x, init=True)

        assert (x.lw is None) == (x.uw is None)

        dim = 1 if self.lw.ndim > 0 else 0

        if x.lw is not None:
            lw, uw = BoundActivation.bound_forward_w(
                self.lw, self.uw, x.lw, x.uw, dim)
        else:
            lw = uw = None
        lb, ub = BoundActivation.bound_forward_b(
            self.lw, self.uw, self.lb, self.ub, x.lb, x.ub)

        return LinearBound(lw, lb, uw, ub)

    def interval_propagate(self, *v):
        h_L, h_U = v[0][0], v[0][1]
        return self.forward(h_L), self.forward(h_U)

    def get_split_mask(self, lower, upper, input_index):
        """Return a mask to indicate if each neuron potentially needs a split.

        0: Stable (linear) neuron; 1: unstable (nonlinear) neuron.
        """
        return torch.ones_like(lower)

class BoundOptimizableActivation(BoundActivation):
    def __init__(self, attr=None, inputs=None, output_index=0, options=None):
        super().__init__(attr, inputs, output_index, options)
        self.optimizable = True
        # Stages:
        #   * `init`: initializing parameters
        #   * `opt`: optimizing parameters
        #   * `reuse`: not optimizing parameters but reuse saved values
        # If `None`, it means activation optimization is currently not used.
        self.opt_stage = None
        self.alpha = OrderedDict()
        # Save patch sizes during bound_backward() for each output_node.
        self.patch_size = {}
        # A torch.bool mask of shape Tensor([batch_size]) that conditions the
        # sample of alpha and beta to update
        # If set to None, update all samples
        # If not None, select those corresponding to 1 to update

    def opt_init(self):
        """Enter the stage for initializing bound optimization. Optimized bounds
        are not used in this stage."""
        self.opt_stage = 'init'

    def opt_start(self):
        """Start optimizing bounds."""
        self.opt_stage = 'opt'

    def opt_reuse(self):
        """ Reuse optimizing bounds """
        self.opt_stage = 'reuse'

    def opt_no_reuse(self):
        """ Finish reusing optimized bounds """
        if self.opt_stage == 'reuse':
            self.opt_stage = None

    def opt_end(self):
        """ End optimizing bounds """
        self.opt_stage = None

    def clip_alpha(self):
        pass

    def init_opt_parameters(self, start_nodes):
        """ start_nodes: a list of starting nodes [(node, size)] during
        CROWN backward bound propagation"""
        self.alpha = OrderedDict()
        for start_node in start_nodes:
            ns, size_s = start_node[:2]
            # TODO do not give torch.Size
            if isinstance(size_s, (torch.Size, list, tuple)):
                size_s = prod(size_s)
            self.alpha[ns] = self._init_opt_parameters_impl(size_s, name_start=ns)

    def _init_opt_parameters_impl(self, size_spec, name_start=None):
        """Implementation of init_opt_parameters for each start_node."""
        raise NotImplementedError

    def init_linear_relaxation(self, x, dim_opt=None):
        self._init_masks(x)
        # The first dimension of size 2 is used for lA and uA respectively,
        # when computing intermediate bounds.
        if self.opt_stage in ['opt', 'reuse'] and dim_opt is not None:
            # For optimized bounds, we have independent lw for each output
            # dimension for bound optimization.
            # If the output layer is a fully connected layer, len(dim_opt) = 1.
            # If the output layer is a conv layer, len(dim_opt) = 3 but we only
            # use the out_c dimension to create slopes/bias.
            # Variables are shared among out_h, out_w dimensions so far.
            if isinstance(dim_opt, int):
                dim = dim_opt
            elif isinstance(dim_opt, torch.Size):
                dim = prod(dim_opt)
            else:
                dim = dim_opt[0]
            self.lw = torch.zeros(2, dim, *x.lower.shape).to(x.lower)
        else:
            # Without optimized bounds, the lw, lb (slope, biase) etc only
            # depend on intermediate layer bounds,
            # and are shared among different output dimensions.
            self.lw = torch.zeros_like(x.lower)
        self.lb = self.lw.clone()
        self.uw = self.lw.clone()
        self.ub = self.lw.clone()

    def bound_relax(self, x, init=False, dim_opt=None):
        return not_implemented_op(self, 'bound_relax')

    def bound_backward(self, last_lA, last_uA, x, start_node=None,
                       start_shape=None, reduce_bias=True, **kwargs):
        self._start = start_node.name
        if self.opt_stage not in ['opt', 'reuse']:
            last_A = last_lA if last_lA is not None else last_uA
            # Returned [(lA, uA)], lbias, ubias
            As, lbias, ubias = super().bound_backward(
                last_lA, last_uA, x, reduce_bias=reduce_bias)
            if isinstance(last_A, Patches):
                A_prod = As[0][1].patches if As[0][0] is None else As[0][1].patches
                # FIXME: Unify this function with BoundReLU
                # Save the patch size, which will be used in init_slope() to
                # determine the number of optimizable parameters.
                if start_node is not None:
                    if last_A.unstable_idx is not None:
                        # Sparse patches, we need to construct the full patch size:
                        # (out_c, batch, out_h, out_w, c, h, w).
                        self.patch_size[start_node.name] = [
                            last_A.output_shape[1], A_prod.size(1),
                            last_A.output_shape[2], last_A.output_shape[3],
                            A_prod.size(-3), A_prod.size(-2), A_prod.size(-1)]
                    else:
                        # Regular patches.
                        self.patch_size[start_node.name] = A_prod.size()
            return As, lbias, ubias
        assert self.batch_dim == 0

        self.bound_relax(x, init=True, dim_opt=start_shape)

        def _bound_oneside(last_A, sign=-1):
            if last_A is None:
                return None, 0
            if sign == -1:
                w_pos, b_pos, w_neg, b_neg = self.lw[0], self.lb[0], self.uw[0], self.ub[0]
            else:
                w_pos, b_pos, w_neg, b_neg = self.uw[1], self.ub[1], self.lw[1], self.lb[1]
            w_pos = maybe_unfold_patches(w_pos, last_A)
            w_neg = maybe_unfold_patches(w_neg, last_A)
            b_pos = maybe_unfold_patches(b_pos, last_A)
            b_neg = maybe_unfold_patches(b_neg, last_A)
            unstable_idx = kwargs.get('unstable_idx', None)
            if unstable_idx is not None:
                assert isinstance(unstable_idx, Tensor) and unstable_idx.ndim == 1
                # Shape is (spec, batch, neurons).
                # FIXME: Sigmoid and other activation functions should also support
                # sparse-spec alpha, so alpha will be created with a smaller shape.
                w_pos = self.non_deter_index_select(w_pos, index=unstable_idx, dim=0)
                w_neg = self.non_deter_index_select(w_neg, index=unstable_idx, dim=0)
                b_pos = self.non_deter_index_select(b_pos, index=unstable_idx, dim=0)
                b_neg = self.non_deter_index_select(b_neg, index=unstable_idx, dim=0)
            A_prod, _bias = multiply_by_A_signs(
                last_A, w_pos, w_neg, b_pos, b_neg, reduce_bias)
            return A_prod, _bias

        lA, lbias = _bound_oneside(last_lA, sign=-1)
        uA, ubias = _bound_oneside(last_uA, sign=+1)

        return [(lA, uA)], lbias, ubias

    def _no_bound_parameters(self):
        raise AttributeError('Bound parameters have not been initialized.'
                             'Please call `compute_bounds` with `method=CROWN-optimized`'
                             ' at least once.')

    def dump_optimized_params(self):
        return self.alpha

    def restore_optimized_params(self, alpha):
        self.alpha = alpha


from math import *
import random
import copy

class pgrammar(object):
    """a p-grammar is a grammar that works in a probabilistic way"""
    def __init__(self, rules):
        """ initialize the pgrammar object, where rules is a dictionary
            mapping non-terminals to lists of (omega, p) tuples """
        self.rules = rules
        self.nonterminals = self.rules.keys()
        self.p_sums = {}
        self.lower_bounds = {}
        self.random_maps = {}
        for A in self.nonterminals:
            total = sum( map( lambda x: x[1], self.rules[A] ) )
            self.p_sums[A] = total
            if total <= 0.0:
                total = 1.0
            self.lower_bounds[A] = []
            bound = 0.0
            boundmapstring = "0"
            count = 0
            for r in self.rules[A]:
                self.lower_bounds[A].append(bound)
                boundmapstring = repr(count) + " if (x>=" + repr(bound/total) \
                                  + ") else " + boundmapstring
                bound += r[1]
                count += 1
            boundmapstring = "lambda x: " + boundmapstring
            #print A,':',boundmapstring
            self.random_maps[A] = lambda x,A=A,fn=eval(boundmapstring):\
                                  self.rules[A][fn(x)][0]

    def __call__(self, word):
        tokens_list = filter(lambda x: x[1], word)
        tokens = {}
        for t in tokens_list:
            T = repr(t)
            if not T in tokens:
                def rulemap(x):
                    if x[1]:
                        return (x[0],t[1]+[x[1]])
                    else:
                        return (x[0],[])
                tokens[T] = map(rulemap, \
                                self.random_maps[t[0]](random.uniform(0.0,1.0)))
        w = []
        for x in word:
            X = repr(x)
            if X in tokens:
                w.extend(tokens[X])
            else: # make unknown non-terminals terminals
                w.append((x[0],[]))
        return w

def projectTerminals(word):
    return map(lambda x: x[0], filter(lambda x: not x[1], word))

def hasNonTerminals(word):
    for k in word:
        if k[1]:
            return True
    return False

def definiteTerminals(word):
    terms = []
    for k in word:
        if k[1]:
            return terms
        terms.append(k[0])
    return terms

def countDefiniteTerminals(word):
    count = 0
    for k in word:
        if k[1]:
            return count
        count += 1
    return count

def makeRule(code):
    """ make a rule data structure from code:
    NONTERMINAL: *TERMINAL(NUMBER) ... *TERMINAL(NUMBER): PVALUE
    where NUMBER=0 means terminal, and all nonterminals with
    the same NUMBER refer to the same instances of nonterminals. """
    c = map(lambda x: x.strip(), code.split(':'))
    if len(c) == 2:
        c.append("1.0")

    if not len(c) == 3:
        raise Exception("Wrong rule format: "+str(code))

    lefthand = c[0].strip()
    pvalue = float(c[2])

    termnums = filter(lambda x:x, c[1].split(")"))

    def int0(x):
        try:
            return int(x)
        except ValueError:
            return 0

    def mk_sym(x):
        s = x.split("(")
        if not len(s) == 2:
            raise Exception("Wrong bracket format: " + str(code))
        return (s[0].strip(),int0(s[1]))

    symbols = map(mk_sym, termnums)

    righthand = [(symbols, pvalue)]

    return {lefthand: righthand}

def makeWord(code):
    termnums = filter(lambda x:x, code.split(")"))

    def int0(x):
        try:
            return int(x)
        except ValueError:
            return 0

    def lint0(x):
        q = int0(x)
        if q:
            return [q]
        else:
            return []

    def mk_sym(x):
        s = x.split("(")
        if not len(s) == 2:
            raise Exception("Wrong bracket format: " + str(code))
        return (s[0].strip(),lint0(s[1]))

    symbols = map(mk_sym, termnums)

    return symbols

def simplifyWord(word):
    simplificator = {tuple(): []}
    varc = 1
    new_word = []
    for x in word:
        try:
            v = simplificator[tuple(x[1])]
        except KeyError:
            v = simplificator[tuple(x[1])] = [varc]
            varc += 1
        new_word.append((x[0], v))
    return new_word

def addRules(x, add):
    for k in add:
        x.setdefault(k,[]).extend(add[k])

def makeRules(rules, default=None):
    rlist = filter(lambda x:x, map(lambda x:x.strip(), rules.split("\n")))
    if default:
        r = copy.deepcopy(default)
    else:
        r = {}

    for x in rlist:
        addRules(r, makeRule(x))
    return r

if __name__ == '__main__':
    rules = {}
    rules['A'] = [([('A',1),('B',1),('A',1),('A',2)], 0.5),\
                  ([('C',1)], 1.1)]
    rules['B'] = [([('!',0)],0)]
    rules['C'] = [([('_',0)],0)]
    g = pgrammar(rules)
    initial = [('A',[1]),('A',[])]

class neuron(object):
    """a neuron has an inner level, an input level and output synapses"""
    def __init__(self, level=None, synapses=None, delta=None):
        """ initialize a neuron with its level and output synapses-weighting """
        if level:
            self.level = level
        else:
            self.level = 0.5

        if synapses:
            self.synapses = synapses
        else:
            self.synapses = {}
        #
        # self.synapses maps function objects on sets of neurons
        #

        self.input = 0

        if delta:
            self.delta = delta
        else:
            self.delta = lambda x: min(1.0,max(0.0,(x+self.level)))

    def react(self):
        self.level = self.delta(self.input)
        self.input = 0

    def feed(self):
        for fn in self.synapses:
            y = fn(self.level)
            for n in self.synapses[fn]:
                n.input += y

class cluster(object):
    """a cluster is a set of neurons that may have synapse connections"""
    def __init__(self, count=32, renormalization=None):
        """ initialize a neuron cluster with count neurons """
        self.neurons = [neuron() for i in range(count)]
        self.renormalization = renormalization

    def feedback(self):
        for n in self.neurons:
            n.feed()
        for n in self.neurons:
            n.react()
        if self.renormalization:
            factor = self.renormalization / sum(map(lambda n:n.level, self.neurons))
            for n in self.neurons:
                n.level *= factor

    def shock(self, energy):
        for n in self.neurons:
            n.level += energy

    def jolt(self, energy):
        for n in self.neurons:
            n.input += energy

    def connect(self, i, fn, j):
        self.neurons[i].synapses.setdefault(fn, set()).add(self.neurons[j])

    def levels(self):
        return map(lambda n: n.level, self.neurons)

def trigger_fn(limit,high,low=0.0):
    def fn(x,limit=limit,high=high,low=low):
        if x >= limit:
            return high
        return low
    return fn


import collections
import logging
import os
import os.path
import sys

def check_file(filename):
    if ( filename is None
         or not os.path.isfile(filename)
         or not os.access(filename, os.R_OK) ):
        logging.fatal("Input file not specified or invalid. Given: '%s'.", filename)
        sys.exit("Input file '{0}' not valid.".format(filename))

def lower_triangle(n):
    v = None
    if not isinstance(n, collections.Iterable):
        v = list(range(n))
    else:
        v = list(n)

    for i2 in xrange(1, len(v)):
        for i1 in xrange(i2):
            yield (v[i1], v[i2])


"""
	Programa que analiza un documento de Word (.docx) que contenga un texto jurídico y lo estructura en una tabla .csv con los datos ordenados en las columnas "Contexto", "Ley", "Artículos" y "Fracciones". El programa utiliza expresiones regulares –escritas de acuerdo a estructuras lingüísticas– para obtener los datos deseados.

	@author: Jorge Galindo, Absalón Castañón e Ivan Salgado

	@company: GILkatón - Grupo de Ingeniería Lingüística, UNAM.

"""

import docx
import re
docs = []
docs.append("Evaluacion.docx")

#prefiltrado

lista =[]
contextos = []
licon=[]
tosave= open("output2.csv", "w")

def getArticulos():
	"""
	Función que selecciona y almacena los párrafos según si contienen una estructura de "artículo + ley que lo contiene". Además de almacenar la estructura, almacena el párrafo que la contiene como contexto

	"""
	articulos =[]
	contextos =[]
	rxentidad = re.compile("(en el |en los |del |de los |en su |en sus |los |al |el |En el |En los |Del |De los |En su |En sus |Los |Al |El )*(artículo|artículos|art.|Artículo|Artículos|Art.) [0-9]+(º|o\.)*(-[a-zA-Z])*((,)+ [0-9]+(º|o\.)*(-[a-zA-Z])*)*(( y )+[0-9]+(º|o\.)*(-[a-zA-Z])*)*((,)* (fracción |fracciones )+(I|V|X|L|C|D|M)+)*((,)+ (I|V|X|L|C|D|M)+)*(( y )+(I|V|X|L|C|D|M)+)*( inciso [a-z]\))*((, | y )+[0-9]+(º|o\.)*(-[a-zA-Z])*)*((,)* (fracción |fracciones )+(I|V|X|L|C|D|M)+)*((,)+ (I|V|X|L|C|D|M)+)*(( y )+(I|V|X|L|C|D|M)+)*( inciso [a-z]\))*( del | de la | de los | de las )+",re.UNICODE)
	for x in range(0,len(docs)):
			document=docx.Document("{}".format(docs[x]))
			for paragraph in document.paragraphs:
				res = rxentidad.search(paragraph.text)
				if res:
					var=re.sub("[[a-záéíóéúñ]*]$","",res.group())
					articulos.append(var)
					contextos.append(paragraph.text)
	return zip(articulos,contextos)

def getLey(articulos_contextos):
	"""
	Función que busca, en los párrafos del contexto, el nombre del texto legal que contiene los artículos seleccionados en la función anterior. Almacena el contexto completo, el nombre de la ley y la estructura que contiene el número y fracción de los artículos correspondientes.

	"""
	rxley = re.compile("((de la |del |de los )((Constitución|Ley|Estatuto|Lineamientos|[A-Z]{2,})(( [A-Z][a-záéíóéúñ]+)*( (a|del|las|,|sobre la|de los|de las|de||el|la|los|para|y|e) +)*){2,}(([A-Z][a-záéíóéúñ]*)*)(( (a|del|las|,|sobre la|de los|de las|de||el|la|los|para|y|e) +)*){2,}(([A-Z][a-záéíóéúñ]*)*)(( [A-Z][a-záéíóéúñ]*)*)))",re.UNICODE)

	resContextos = []
	resContLeyes = []
	resLeyes =[]

	for art,cont in articulos_contextos:
		res =  rxley.finditer(cont)
		for match in res:
			resContLeyes.append(art)
			resContextos.append(cont)
			resLeyes.append(match.group(3))

	return zip(resContextos, resLeyes, resContLeyes)

def getNumArt(contextos_leyes_contleyes):
	"""
	Función que busca, en la estructura que contiene el número y fracción de los artículos, el número correspondiente a los artículos citados del texto legal. Almacena el contexto completo, el nombre de la ley, el número del artículo y, una vez más, la estructura que contiene el número y fracción de los artículos correspondientes.

	"""
	rx ="([0-9]{1,}(º|o)*(-[a-zA-Z])*)+"

	rxnumarticulo=re.compile(rx)
	resContextos =[]
	resLeyes = []
	resNumArt = []
	resContLeyes = []
	for cont, ley, art in contextos_leyes_contleyes:
		res =  rxnumarticulo.finditer(art)
		for match in res:
			resContextos.append(cont)
			resLeyes.append(ley)
			resContLeyes.append(art)
			resNumArt.append(match.group(0))

	return zip(resContextos, resLeyes, resNumArt, resContLeyes)

def getNumFracciones(contextos_leyes_art_contleyes):
	"""
	Función que busca, en la estructura que contiene el número y fracción de los artículos, el número correspondiente a las fracciones citadas de los artículos del texto legal. Almacena el contexto completo, el nombre de la ley, el número del artículo y, finalmente, el número de fracción correspondiente.

	"""
	rx ="((I|V|X|L|C|D|M)+)"

	rxnumfracciones=re.compile(rx)

	resContextos =[]
	resLeyes = []
	resNumArt = []
	resNumFracciones = []

	for cont, ley, art, fracc in contextos_leyes_art_contleyes:
		res = rxnumfracciones.search(fracc)
		if res:
			resContextos.append(cont)
			resLeyes.append(ley)
			resNumArt.append(art)
			resNumFracciones.append(res.group(0))
		else:
			resContextos.append(cont)
			resLeyes.append(ley)
			resNumArt.append(art)
			resNumFracciones.append("")

	return zip(resContextos, resLeyes, resNumArt, resNumFracciones)

""" Se ejecutan las funciones y se obtienen los datos correspondientes """

licon = getArticulos()
licon = getLey(licon)
licon = getNumArt(licon)
licon = getNumFracciones(licon)

""" Se escriben los datos obtenidos en un tabla .csv """

tosave.write("Contexto,Ley,Artículos,Fracciones\n")
for cont,ley,art,fracc in licon:
	tosave.write('"{}","{}","{}","{}"\n'.format(cont,ley,art,fracc))

tosave.close()


import torch
from hanzi_font_deconstructor.model.unet.train_net import train_net
from hanzi_font_deconstructor.model.unet.UNet import UNet

if __name__ == "__main__":
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    print(f"Using device {device}")

    net = UNet(
        n_channels=1,
        n_classes=5,
        bilinear=False,
    )
    net.to(device=device)
    train_net(
        net,
        device,
        total_samples=10000,
        max_strokes=5,
        size_px=512,
        epochs=5,
        batch_size=1,
        lr=0.001,
        val_portion=0.1,
    )


from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
from users.models import CustomUser
import datetime

#Model for organizations
class OrgProfile(models.Model):
    title = models.CharField(max_length=200, blank=False)
    logo = models.ImageField(upload_to='org_logo')
    vision = models.CharField(max_length=250, blank=True)
    mission = models.CharField(max_length=500, blank=True)
    num_employees = models.CharField(max_length=20)
    founded = models.PositiveIntegerField(validators=[MinValueValidator(1000), MaxValueValidator(datetime.datetime.now().year)])
    email = models.EmailField(max_length=255, blank=False)

    def __str__(self):
        return f"{self.title}"

#Basic survey model. It now stores both questions and answers, this is a simple solution that needs to be rebuild.
class Survey(models.Model):
    STUDENT = 'STUD'
    EMPLOYEE = 'EMP'
    POSITION_CHOICE = [
            (STUDENT, 'Student'),
            (EMPLOYEE, 'Employee'),]

    organization = models.ForeignKey(OrgProfile, on_delete= models.CASCADE)
    satsified = models.IntegerField( validators=[MinValueValidator(1), MaxValueValidator(10)])
    period = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(40)])
    occupation = models.CharField(max_length=10, choices=POSITION_CHOICE)
    participant = models.ForeignKey(CustomUser, on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = 'Surveys'

#Model for contact form on landing page. Might create an abstract user model to store often used fields
class Contact(models.Model):
    name = models.CharField(max_length=100, name="Full name")
    organization = models.CharField(max_length=100, name = "Company")
    role = models.CharField(max_length=100, name ="Role")
    email = models.EmailField(max_length=200)
    phone_number = models.CharField(max_length=20, blank = True)

    def __str__(self):
        return f"{self.name} {self.organization}-{self.role}"