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

"""Network plugin."""

import base64
import operator

from gl.timer import getTimeSinceLastUpdate
from gl.plugins.glances_plugin import GlancesPlugin

import psutil

# Define the history items list
# All items in this list will be historised if the --enable-history tag is set
# 'color' define the graph color in #RGB format
items_history_list = [{'name': 'rx',
                       'description': 'Download rate per second',
                       'color': '#00FF00',
                       'y_unit': 'bit/s'},
                      {'name': 'tx',
                       'description': 'Upload rate per second',
                       'color': '#FF0000',
                       'y_unit': 'bit/s'}]

class Plugin(GlancesPlugin):

    """Glances network plugin.

    stats is a list
    """

    def __init__(self, args=None):
        """Init the plugin."""
        super(Plugin, self).__init__(args=args, items_history_list=items_history_list)

        # We want to display the stat in the curse interface
        self.display_curse = True

        # Init the stats
        self.reset()

    def get_key(self):
        """Return the key of the list."""
        return 'interface_name'

    def reset(self):
        """Reset/init the stats."""
        self.stats = []

    @GlancesPlugin._log_result_decorator
    def update(self):
        """Update network stats using the input method.

        Stats is a list of dict (one dict per interface)
        """
        # Reset stats
        self.reset()

        # Update stats using the standard system lib

        # Grab network interface stat using the PsUtil net_io_counter method
        try:
            netiocounters = psutil.net_io_counters(pernic=True)
        except UnicodeDecodeError:
            return self.stats

        # New in PsUtil 3.0: optionaly import the interface's status (issue #765)
        netstatus = {}
        try:
            netstatus = psutil.net_if_stats()
        except:
            pass

        # Previous network interface stats are stored in the network_old variable
        if not hasattr(self, 'network_old'):
            # First call, we init the network_old var
            try:
                self.network_old = netiocounters
            except (IOError, UnboundLocalError):
                pass
        else:
            # By storing time data we enable Rx/s and Tx/s calculations in the
            # XML/RPC API, which would otherwise be overly difficult work
            # for users of the API
            time_since_update = getTimeSinceLastUpdate('net')

            # Loop over interfaces
            network_new = netiocounters
            for net in network_new:
                # Do not take hidden interface into account
                if self.is_hide(net):
                    continue
                try:
                    cumulative_rx = network_new[net].bytes_recv
                    cumulative_tx = network_new[net].bytes_sent
                    cumulative_cx = cumulative_rx + cumulative_tx
                    rx = cumulative_rx - self.network_old[net].bytes_recv
                    tx = cumulative_tx - self.network_old[net].bytes_sent
                    cx = rx + tx
                    netstat = {
                        'interface_name': net,
                        'time_since_update': time_since_update,
                        'cumulative_rx': cumulative_rx,
                        'rx': rx,
                        'cumulative_tx': cumulative_tx,
                        'tx': tx,
                        'cumulative_cx': cumulative_cx,
                        'cx': cx}
                except KeyError:
                    continue
                else:
                    # Optional stats (only compliant with PsUtil 3.0+)
                    try:
                        netstat['is_up'] = netstatus[net].isup
                    except (KeyError, AttributeError):
                        pass
                    # Set the key
                    netstat['key'] = self.get_key()
                    self.stats.append(netstat)

            # Save stats to compute next bitrate
            self.network_old = network_new

        # Update the history list
        self.update_stats_history(self.get_key())

        # Update the view
        self.update_views()

        return self.stats

    def update_views(self):
        """Update stats views."""
        # Call the father's method
        super(Plugin, self).update_views()

        # Add specifics informations
        # Alert
        for i in self.stats:
            ifrealname = i['interface_name'].split(':')[0]
            self.views[i[self.get_key()]]['rx']['decoration'] = self.get_alert(int(i['rx'] // i['time_since_update'] * 8),
                                                                               header=ifrealname + '_rx')
            self.views[i[self.get_key()]]['tx']['decoration'] = self.get_alert(int(i['tx'] // i['time_since_update'] * 8),
                                                                               header=ifrealname + '_tx')

    def msg_curse(self, args=None, max_width=None):
        """Return the dict to display in the curse interface."""
        # Init the return message
        ret = []

        # Only process if stats exist and display plugin enable...
        if not self.stats or args.disable_network:
            return ret

        # Max size for the interface name
        if max_width is not None and max_width >= 23:
            # Interface size name = max_width - space for interfaces bitrate
            ifname_max_width = max_width - 14
        else:
            ifname_max_width = 9

        # Build the string message
        # Header
        msg = '{:{width}}'.format('NETWORK', width=ifname_max_width)
        ret.append(self.curse_add_line(msg, "TITLE"))
        if args.network_cumul:
            # Cumulative stats
            if args.network_sum:
                # Sum stats
                msg = '{:>14}'.format('Rx+Tx')
                ret.append(self.curse_add_line(msg))
            else:
                # Rx/Tx stats
                msg = '{:>7}'.format('Rx')
                ret.append(self.curse_add_line(msg))
                msg = '{:>7}'.format('Tx')
                ret.append(self.curse_add_line(msg))
        else:
            # Bitrate stats
            if args.network_sum:
                # Sum stats
                msg = '{:>14}'.format('Rx+Tx/s')
                ret.append(self.curse_add_line(msg))
            else:
                msg = '{:>7}'.format('Rx/s')
                ret.append(self.curse_add_line(msg))
                msg = '{:>7}'.format('Tx/s')
                ret.append(self.curse_add_line(msg))
        # Interface list (sorted by name)
        for i in sorted(self.stats, key=operator.itemgetter(self.get_key())):
            # Do not display interface in down state (issue #765)
            if ('is_up' in i) and (i['is_up'] is False):
                continue
            # Format stats
            # Is there an alias for the interface name ?
            ifrealname = i['interface_name'].split(':')[0]
            ifname = self.has_alias(i['interface_name'])
            if ifname is None:
                ifname = ifrealname
            if len(ifname) > ifname_max_width:
                # Cut interface name if it is too long
                ifname = '_' + ifname[-ifname_max_width + 1:]

            if args.byte:
                # Bytes per second (for dummy)
                to_bit = 1
                unit = ''
            else:
                # Bits per second (for real network administrator | Default)
                to_bit = 8
                unit = 'b'

            if args.network_cumul:
                rx = self.auto_unit(int(i['cumulative_rx'] * to_bit)) + unit
                tx = self.auto_unit(int(i['cumulative_tx'] * to_bit)) + unit
                sx = self.auto_unit(int(i['cumulative_rx'] * to_bit) +
                                    int(i['cumulative_tx'] * to_bit)) + unit
            else:
                rx = self.auto_unit(int(i['rx'] // i['time_since_update'] * to_bit)) + unit
                tx = self.auto_unit(int(i['tx'] // i['time_since_update'] * to_bit)) + unit
                sx = self.auto_unit(int(i['rx'] // i['time_since_update'] * to_bit) +
                                    int(i['tx'] // i['time_since_update'] * to_bit)) + unit

            # New line
            ret.append(self.curse_new_line())
            msg = '{:{width}}'.format(ifname, width=ifname_max_width)
            ret.append(self.curse_add_line(msg))
            if args.network_sum:
                msg = '{:>14}'.format(sx)
                ret.append(self.curse_add_line(msg))
            else:
                msg = '{:>7}'.format(rx)
                ret.append(self.curse_add_line(
                    msg, self.get_views(item=i[self.get_key()], key='rx', option='decoration')))
                msg = '{:>7}'.format(tx)
                ret.append(self.curse_add_line(
                    msg, self.get_views(item=i[self.get_key()], key='tx', option='decoration')))

        return ret


from flask import Blueprint, render_template, request
import re

views = Blueprint('views', __name__)

@views.route('/')
def home():
    return render_template("base.html")

@views.route('/fb', methods=['GET', 'POST'])
def face():
    if request.method == 'POST':
        fb_link = request.form.get('link')
        root = 'https://www.facebook.com/marketplace/item/'
        if re.match(root, fb_link) is not None:
            print("the link is correct")

    return render_template("face.html")

@views.route('/craig', methods=['GET', 'POST'])
def craig():
    if request.method == 'POST':
        location = request.form.get('location')
        cg_link = request.form.get('link')
        root = f'https://{location}.craigslist.org/'
        if re.match(root, cg_link) is not None:
            print("the link is correct")

    return render_template("craig.html")

@views.route('/about')
def about():
    return render_template("about.html")


import json
import os.path as pth
import base64
from io import BytesIO

import pandas as pd
import numpy as np

import matplotlib.pyplot as plt

import PIL
import PIL.ImageDraw

from jinja2 import Template

import torch
import torch.nn as nn
import torch.nn.functional as F

from torch.utils.data import DataLoader

import models.questioner
import models.answerer

import misc.utilities as utils
import misc.dataloader

# COCO meta-data
# TODO: not portable
coco_path = 'datasets/coco/'
vqa_s3_path = 'https://vqa_mscoco_images.s3.amazonaws.com'
with open(pth.join(coco_path, 'coco.json'), 'r') as f:
    cocoj = json.load(f)
cid_to_file = {d['id']: d['file_path'] for d in cocoj['images']}

# CUB meta-data
cub_meta_path = 'data/cub_meta.json'
with open(cub_meta_path, 'r') as f:
    cub_meta = json.load(f)
cub_img_id_to_idx = {im['img_id']: idx for idx, im in enumerate(cub_meta['images'])}

# AWA meta-data
awa_meta_path = 'data/awa_meta.json'
with open(awa_meta_path, 'r') as f:
    awa_meta = json.load(f)
awa_img_id_to_idx = {im['img_id']: idx for idx, im in enumerate(awa_meta['images'])}

def load_image_path(img_id, size=None, dataset_name='VQA', local=True):
    if dataset_name == 'VQA':
        coco_id = img_id
        fname = cid_to_file[coco_id]
        if local:
            file = pth.join(coco_path, 'images', fname)
        else:
            file = '/'.join([vqa_s3_path, fname.lstrip('/')])
    elif dataset_name == 'CUB':
        img_idx = cub_img_id_to_idx[img_id]
        file = cub_meta['images'][img_idx]['img_path']
    elif dataset_name == 'AWA':
        img_idx = awa_img_id_to_idx[img_id]
        file = awa_meta['images'][img_idx]['img_path']
    return file

def load_image(img_id, size=None, dataset_name='VQA'):
    file = load_image_path(img_id, size=size, dataset_name=dataset_name)
    img = PIL.Image.open(file).convert('RGB')
    if size is not None:
        img = img.resize(size)
    return img, file

def img_to_datauri(fname=None, pil_image=None, torch_image=None, size=None):
    if fname:
        assert fname[-3:] == 'jpg'
        with open(fname, 'rb') as f:
            data = base64.b64encode(f.read())
    elif pil_image:
        buffer = BytesIO()
        pil_image.save(buffer, format='jpeg')
        data = base64.b64encode(buffer.getvalue())
    elif torch_image is not None:
        pil_image = PIL.Image.fromarray(torch_image.numpy())
        if size is not None:
            pil_image = pil_image.resize(size)
        return img_to_datauri(pil_image=pil_image)
    return 'data:image/jpeg;base64,{}'.format(data.decode('utf-8'))

def get_questions(batch, qbot, z_source, inference, ind2word, nsamples=1,
                  manualz=None):
    imgs = batch['img_pool']
    #imgs, ques = batch['img_pool'], None
    output = []
    z_inference, dec_inference = inference
    if z_source is not None and z_source[:6] == 'manual':
        assert len(manualz) == nsamples
    qbot.tracking = True
    for ns in range(nsamples):
        qbot.reset()
        qbot.observe(images=batch['img_pool'])
        qbot.observe(start_question=True)
        qbot.observe(start_answer=True)
        if 'ques' in batch:
            qbot.observe(ques=batch['ques'],
                         ques_len=batch['ques_len'],
                         gt_ques=True)
        if z_source[:6] == 'manual':
            zs = manualz[ns]
        else:
            zs = z_source
        gen = qbot.forwardDecode(dec_inference=dec_inference,
                                 z_inference=z_inference,
                                 z_source=zs)

        qidx, qlen, _ = gen
        z = qbot.z
        gen_ques_str = utils.old_idx_to_str(ind2word, qidx, qlen,
                                            batch['img_id_pool'], 0, [])
        gen_ques_str = [q[0].strip('<START> ') for q in gen_ques_str]
        gen_ques_str = [q.strip(' <END>') for q in gen_ques_str]
        output.append((gen_ques_str, show_z(z, qbot)))
    return list(zip(*output))

def single_dim_manual_z(zs, qbot, dim):
    K = qbot.num_embeddings
    V = qbot.num_vars
    K = min(K, 10)
    newz = []
    assert len(zs) == 1, 'start with greedy version'
    for samplei in range(len(zs)):
        newz.append([])
        for exi in range(len(zs[samplei])):
            z = zs[samplei][exi][1]
            z = z.reshape([V, -1])
            _, ix = z.max(dim=1, keepdim=True)
            onehotz = torch.zeros_like(z).scatter_(1, ix, 1.0)
            onehotz = onehotz.reshape(-1)
            newz[samplei].append(onehotz)
        newz[samplei] = torch.stack(newz[samplei])
    # nsamples x nbatch x qbot._num_embeddings
    newz = torch.stack(newz)
    newz = newz.reshape(newz.shape[:2] + (V, K))
    newz = newz.repeat(K, 1, 1, 1)
    for k in range(K):
        newz[k, :, dim, :] = 0
        newz[k, :, dim, k] = 1.0
    newz = newz.reshape(newz.shape[:2] + (V * K,))
    return newz

def interp_manual_z(z, replications=1, max_len=200):
    assert len(z) == 1
    samplei = 0
    targeti = 0
    z_paths = []
    for exi in range(len(z[0])):
        zsource = z[samplei][exi][1]
        ztarget = z[samplei][targeti][1]

        change_idxs = (ztarget - zsource).nonzero().sort()[0]
        change_idxs.shape

        z_list = [zsource]
        z_len = change_idxs.shape[0] + 1

        if z_len > max_len:
            print('z_len {} exceeds max_len {}'.format(z_len, max_len))

        for i in change_idxs:
            newz = z_list[-1].clone()
            newz[i] = ztarget[i]
            for _ in range(replications):
                z_list.append(newz)

        z_list = z_list + z_list[-1:] * (max_len - len(z_list))
        z_exi_path = torch.stack(z_list[:max_len])
        z_paths.append(z_exi_path[:, None, :])

    z_paths = torch.cat(z_paths, dim=1)
    return z_paths

def show_z(z, qbot):
    number_of_vars_to_show = 10
    z, _ = z
    if qbot.varType == 'cont':
        return [('{:.3f}'.format(z[0][i, :].mean().item()), z[0][i]) for i in range(z[0].shape[0])]
        #return [('z', z[0][i]) for i in range(z[0].shape[0])]
    K = qbot.num_embeddings
    V = qbot.num_vars
    vs = []
    for v in range(V):
        _, v_idx = z[:, v*K:(v+1)*K].max(dim=1)
        vs.append(v_idx)
    vs = torch.stack(vs, dim=0).t().tolist()
    return [('_'.join(['{:0>2d}'.format(iv) for iv in i_vars][:number_of_vars_to_show]) + '...', z[i]) for i, i_vars in enumerate(vs)]

def pool_atten_uris(img_attn, side_length=30, cm=plt.get_cmap('viridis'), wrap_period=4):
    N, ps = img_attn.shape
    nrows = (ps-1) // wrap_period + 1
    ncols = ps if nrows == 1 else wrap_period

    imgs = []
    for exi in range(N):
        img = PIL.Image.new('RGB', (ncols * side_length, nrows * side_length), 'black')
        draw = PIL.ImageDraw.Draw(img)
        for i in range(ps):
            row = i // wrap_period
            col = i % wrap_period
            att_color = tuple([int(255 * t) for t in cm(float(img_attn[exi][i]))])
            top_left = (col * side_length, row * side_length)
            bottom_right = ((col+1) * side_length, (row+1) * side_length)
            draw.rectangle([top_left, bottom_right], fill=att_color)
        img = img_to_datauri(pil_image=img)
        imgs.append(img)
    return imgs

def bottomup_heatmap_image(img, att, spatial, cm=plt.get_cmap('viridis')):
    global hi1
    # color the background according to the colormap because everything's too small to see
    img[:] = 255.
    H, W, _ = img.shape
    n_obj, = att.shape
    att_img = torch.zeros(img.shape)
    left =   (spatial[:, 0] * W).to(torch.int).clamp(0, W-1)
    top =    (spatial[:, 1] * H).to(torch.int).clamp(0, H-1)
    right =  (spatial[:, 2] * W).to(torch.int).clamp(0, W-1)
    bottom = (spatial[:, 3] * H).to(torch.int).clamp(0, H-1)
    for k in range(n_obj):
        t, b, l, r = top[k], bottom[k], left[k], right[k]
        # this version is just black and white without using a color map
        att_img[t:b, l:r] += att[k] * img[t:b, l:r].to(att.dtype)
    att_img = att_img[:, :, 0].detach().numpy() / 255
    att_img = 255 * torch.tensor(cm(att_img))[:, :, :3]
    return att_img.to(img.dtype)

def region_att_images(img_pool_ids, region_attn, img_pool_spatial, dataset_name):
    aimgs = []
    N, pool_size = img_pool_ids.shape
    for exi in range(N):
        aimgs.append([])
        for pi in range(pool_size):
            img, _ = load_image(img_pool_ids[exi][pi].item(), size=(50, 50),
                                dataset_name=dataset_name)
            img = torch.tensor(np.array(img))
            att = region_attn[exi, pi]
            spatial = img_pool_spatial[exi, pi]
            aimg = bottomup_heatmap_image(img, att, spatial)
            aimg = img_to_datauri(torch_image=aimg)
            aimgs[-1].append(aimg)
    return aimgs


"""empty message

Revision ID: 496b9489211e
Revises: d91b2c9c21e4
Create Date: 2021-03-26 16:29:32.838914

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '496b9489211e'
down_revision = 'd91b2c9c21e4'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('_alembic_tmp_task')
    with op.batch_alter_table('task', schema=None) as batch_op:
        batch_op.drop_column('is_perfect')

    with op.batch_alter_table('user', schema=None) as batch_op:
        batch_op.add_column(sa.Column('image_file', sa.String(length=20), nullable=True))

    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('user', schema=None) as batch_op:
        batch_op.drop_column('image_file')

    with op.batch_alter_table('task', schema=None) as batch_op:
        batch_op.add_column(sa.Column('is_perfect', sa.BOOLEAN(), nullable=True))

    op.create_table('_alembic_tmp_task',
    sa.Column('id', sa.INTEGER(), nullable=False),
    sa.Column('title', sa.VARCHAR(length=80), nullable=False),
    sa.Column('description', sa.TEXT(), nullable=False),
    sa.Column('created', sa.DATETIME(), nullable=True),
    sa.Column('priority', sa.VARCHAR(length=6), nullable=True),
    sa.Column('is_done', sa.BOOLEAN(), nullable=True),
    sa.Column('category_id', sa.INTEGER(), nullable=True),
    sa.CheckConstraint('is_done IN (0, 1)'),
    sa.ForeignKeyConstraint(['category_id'], ['category.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###


"""
Attempt to load DB tables in parallel using staging tables.
This was a FAILURE.
Keeping code here for reference in case fragments prove useful in the future.
In particular, it has a use of parallel processing with a thread pool and starmap is syntactically correct.
It's just not fast for inserting records into MariaDB tables with LOAD DATA INSERT statements.

Michael S. Emanuel
2021-02-18
"""

# Algorithms
import itertools
import multiprocessing

# *********************************************************************************************************************
def make_db_engines(single_thread: bool) -> None:
    """Create a shared set of DB engine objects (global variable).  Used to support multithreading."""
    global db_engines
    if single_thread:
        db_engines = (db_engine,)
    else:
        from db_engine_pool import db_engines

# *********************************************************************************************************************
def staging_table_name(table: str, i: int):
    """Consistently generate schema_table and staging_table names. i is the chunk number."""
    # Staging table for this chunk
    staging_table = f'temp.{table}_pid_{pid}_chunk_{i:03d}'
    return staging_table

# *********************************************************************************************************************
def csv2db_ldi(schema: str, table: str, columns: List[str], fname_csv: str, conn: conn_type):
    """
    Load one CSV file directly into the named DB table using the Load Data Infile command.
    This is MUCH SLOWER than using mariadb-import
    INPUTS:
        schema:    Schema of the DB table
        table:     Name of the DB table
        columns:   List of columns of the DB table
        fname_csv: Name of the CSV file
        conn:      DB connection object
    OUTPUTS:
        None. Modifies the database table.
    """

    # Destination table name including schema
    dest_table = dest_table_name(schema=schema, table=table)
    # List of column names
    col_list = '(' + ','.join(columns) + ')'

    # SQL to Load CSV into database into staging table
    sql_load_csv = \
        f"""
        LOAD DATA LOCAL INFILE
        '{fname_csv}'
        REPLACE
        INTO TABLE {dest_table}
        FIELDS TERMINATED BY ','
        LINES TERMINATED BY '\n'
        IGNORE 1 LINES
        {col_list}
        """

    # Load the CSV file
    conn.execute(sql_load_csv)
    # Delete the CSV file after it has been successfully loaded
    os.remove(fname_csv)

# *********************************************************************************************************************
def csv2db_stage(schema: str, table: str, columns: List[str], cols_to_drop: List[str],
                 fname_csv: str, i: int, conn: conn_type):
    """
    Load one CSV file into a staging table for the named DB table.
    INPUTS:
        schema:         Schema of the DB table
        table:          Name of the DB table
        columns:        List of columns of the DB table
        cols_to_drop:   Columns to drop after cloning tabl
        fname_csv:      Name of the CSV file
        i:              Chunk number
        conn:           DB connection object
    OUTPUTS:
        staging_table: Name of the staging dable in the DB
        Modifies the database by creating a staging table
    """

    # Destination and staging table names
    dest_table = dest_table_name(schema=schema, table=table)
    staging_table = staging_table_name(table=table, i=i)
    # List of column names
    col_list = '(' + ','.join(columns) + ')'

    # SQL to create staging table
    sql_clone_table_1 = f"CREATE OR REPLACE TABLE {staging_table} LIKE {dest_table};"
    sql_clone_table_2 = f"ALTER table {staging_table} transactional=default;"
    sql_clone_table_3 = f"ALTER table {staging_table} engine='Memory';"

    # SQL to Load CSV into database into staging table
    sql_load_csv = \
        f"""
        LOAD DATA LOCAL INFILE
        '{fname_csv}'
        IGNORE
        INTO TABLE {staging_table}
        FIELDS TERMINATED BY ','
        LINES TERMINATED BY '\n'
        IGNORE 1 LINES
        {col_list}
        """

    # Clone the table; need to drop generated columns
    conn.execute(sql_clone_table_1)
    conn.execute(sql_clone_table_2)
    drop_columns(schema='', table=staging_table, cols=cols_to_drop, conn=conn)
    conn.execute(sql_clone_table_3)

    # Load the CSV file
    conn.execute(sql_load_csv)
    # Delete the CSV file after it has been successfully loaded
    os.remove(fname_csv)

    # Return the name of the staging table
    return staging_table

# *********************************************************************************************************************
def csvs2stage(schema: str, table: str, columns: List[str], fnames_csv: List[str],
                  ii: List[int], c: int, progbar: bool):
    """
    Load a batch of CSV files into a staging table for the named DB table.
    INPUTS:
        schema:         Schema of the DB table
        table:          Name of the DB table
        columns:        List of columns of the DB table
        cols_to_drop:   List of columns to be dropped (e.g. generated columns)
        fnames_csv: List of the CSV file names
        ii:         List of chunk numbers for this batch
        c:          CPU (process) number; used to choose the DB engine from the shared pool
        progbar:    Whether to show a tqdm progress bar
    OUTPUTS:
        staging_tables: List of staging table names
        Modifies the database by creating a staging table
    """
    # Calculate list of columns to drop
    cols_to_drop = get_generated_columns(schema=schema, table=table)

    # Display progress bar if requested
    if progbar:
        ii = tqdm_auto(ii)
    # List of staging tables assembled
    staging_tables: List[str] = []
    # Use the DB engine corresponding to this CPU number
    db_engine_c = db_engines[c]
    # All SQL statements on this engine use the same connection
    with db_engine_c.connect() as conn:
        for i in ii:
            staging_table = \
                csv2db_stage(schema=schema, table=table, columns=columns, cols_to_drop=cols_to_drop,
                fname_csv=fnames_csv[i], i=i, conn=conn)
            staging_tables.append(staging_table)

    return staging_tables

# *********************************************************************************************************************
def stage2db(dest_table: str, staging_table: str, columns: List[str], conn: conn_type):
    """
    Finishing loading a CSV file by inserting from the staging table into the named DB table.
    INPUTS:
        dest_table:     Fully delimited name of the destination DB table
        staging_table:  Fully delimited name of the staging DB table (source for insert)
        conn:           DB connection object
    OUTPUTS:
        None.  Modifies the database by inserting from the staging table into the main table
    """

    # List of column names
    col_list = '(' + ','.join(columns) + ')'
    # Columns to select
    select_fields = ',\n'.join(columns)

    # SQL to insert into the main table from the staging table
    sql_insert_stage = \
        f"""
        REPLACE INTO {dest_table}
        {col_list}
        SELECT
        {select_fields}
        FROM {staging_table};
        """

    # SQL to drop the staging table, which is no longer needed
    sql_drop_stage = f"DROP TABLE {staging_table};"

    # Insert from the staging table, then drop it
    conn.execute(sql_insert_stage)
    conn.execute(sql_drop_stage)

# *********************************************************************************************************************
def csvs2db_stage(schema: str, table: str,
                  fnames_csv: Optional[List[str]]=None,
                  columns: Optional[List[str]]=None,
                  single_thread: bool=False,
                  progbar: bool=True):
    """
    Load a batch of CSVs into the named DB table.
    First delegates to csv2db_stage to populate the staging tables in parallel.
    Then rolls up from all of the staging tables into the big table at the end.
    """
    # Set DB engine pool based on single_thread flag
    make_db_engines(single_thread=single_thread)

    # Get list of CSV files if they were not provided
    if fnames_csv is None:
        search_path = os.path.join(dir_csv, table, f'pid_*', f'{table}-chunk-*.csv')
        fnames_csv = glob.glob(search_path)
        fnames_csv.sort()

    # Get columns from DB metadata if they were not provided by caller
    if columns is None:
        columns = get_columns(schema=schema, table=table)

    # List of indices
    chunk_count: int = len(fnames_csv)
    ii = list(range(chunk_count))

    # Multiprocessing
    cpu_max: int = 32
    engine_count: int = len(db_engines)
    cpu_count_default: int = min(multiprocessing.cpu_count() // 2, chunk_count, cpu_max, engine_count)
    cpu_count: int = 1 if single_thread else cpu_count_default

    # Prepare inputs for CSV staging function
    stage_inputs = []
    for c in range(cpu_count):
        # The indices i handled by cpu c
        ii_c = tuple(range(c, chunk_count, cpu_count))
        progbar_c = progbar and (c==0)
        # Arguments to csv2db_stage
        args = (schema, table, columns, fnames_csv, ii_c, c, progbar_c)
        # List of argument tuples for the staging function
        stage_inputs.append(args)
    # Convert from list to tuple
    stage_inputs = tuple(stage_inputs)

    # Run in CSV staging in parallel
    pool = multiprocessing.Pool(processes=cpu_count)
    staging_tables_pool = pool.starmap(csvs2stage, stage_inputs)
    # Flatten the list of staging table collections into one complete
    staging_tables = list(itertools.chain.from_iterable(staging_tables_pool))

    # The destination table name
    dest_table = dest_table_name(schema=schema, table=table)
    # Roll up from staging table to schema on one CPU core
    with db_engine.connect() as conn:
        for staging_table in staging_tables:
            stage2db(dest_table=dest_table, staging_table=staging_table, columns=columns, conn=conn)


from random import *
N=int(input("N = ? "))
sum=0
print("랜덤한 숫자 %d개: "%(N),end="")
for i in range(N):
    data=randint(1,100)
    sum+=data
    if i==N-1:
        print(data)
    else:
        print(data,end=",")
print("합계 : %d"%(sum))
print("평균 : {}".format(round((sum/N),2)))


"""
Methods and utilities for generating composite omit maps.  The actual
end-user application, phenix.composite_omit_map, is part of the phenix
sources.
"""

from __future__ import absolute_import, division, print_function
import mmtbx.f_model
from cctbx import miller
from cctbx import maptbx
import cctbx.miller
from scitbx.array_family import flex
import boost_adaptbx.boost.python as bp
from six.moves import zip
from six.moves import range
asu_map_ext = bp.import_ext("cctbx_asymmetric_map_ext")
from libtbx import slots_getstate_setstate, \
  slots_getstate_setstate_default_initializer
from libtbx.utils import null_out
import libtbx.phil
import operator
import sys
from libtbx import adopt_init_args
import mmtbx.real_space

omit_map_phil = libtbx.phil.parse("""
n_debias_cycles = 2
  .type = int
neutral_volume_box_cushion_width = 1
  .type = float
full_resolution_map = True
  .type = bool
""")

class run(object):
  """
  Composite residual OMIT map. Details:
    Afonine et al. (2014). FEM: Feature Enhanced Map
  """
  def __init__(
        self,
        fmodel,
        crystal_gridding,
        box_size_as_fraction=0.1,
        max_boxes=2000,
        neutral_volume_box_cushion_width=2,
        full_resolution_map=True,
        log=sys.stdout):
    adopt_init_args(self, locals())
    self.map_type="mFo-DFc" # using other map types is much worse
    self.sd = self.get_p1_map_unscaled(fmodel = self.fmodel,
      map_type=self.map_type).sample_standard_deviation()
    xrs_p1 = fmodel.xray_structure.expand_to_p1(sites_mod_positive=True)
    self.sgt = fmodel.f_obs().space_group().type()
    self.r = flex.double() # for tests only
    self.acc_asu = None
    # bulk-solvent
    mp = mmtbx.masks.mask_master_params.extract()
    mp.n_real = crystal_gridding.n_real()
    mp.step=None
    mmtbx_masks_asu_mask_obj = mmtbx.masks.asu_mask(
      xray_structure = xrs_p1,
      mask_params = mp)
    self.bulk_solvent_mask = mmtbx_masks_asu_mask_obj.mask_data_whole_uc()
    self.bulk_solvent_mask_asu=self.to_asu_map(map_data=self.bulk_solvent_mask)
    # atom map
    self.atom_map = mmtbx.real_space.sampled_model_density(
      xray_structure = xrs_p1,
      n_real         = crystal_gridding.n_real()).data()
    self.n_real = self.atom_map.focus()
    self.atom_map_asu=self.to_asu_map(map_data=self.atom_map)
    # extras
    self.zero_cmpl_ma = fmodel.f_calc().customized_copy(
      data = flex.complex_double(fmodel.f_calc().size(), 0))
    self.r_factor_omit = flex.double() # for regression test only
    # result map
    self.map_result_asu = flex.double(flex.grid(self.atom_map_asu.focus()))
    # iterate over boxes
    self.box_iterator()

  def map_coefficients(self, filter_noise=True):
    map_coefficients = self.result_as_sf()
    if(filter_noise):
      return self.noise_filtered_map_coefficients(
        map_coefficients=map_coefficients)
    else:
      return map_coefficients

  def noise_filtered_map_coefficients(self, map_coefficients):
    from mmtbx.maps import fem
    f_map = self.fmodel.electron_density_map().map_coefficients(
      map_type                   = "2mFo-DFc",
      isotropize                 = True,
      exclude_free_r_reflections = False,
      fill_missing               = True)
    selection = fem.good_atoms_selection(
      crystal_gridding = self.crystal_gridding,
      map_coeffs       = f_map,#map_coefficients,
      xray_structure   = self.fmodel.xray_structure)
    fft_map = cctbx.miller.fft_map(
      crystal_gridding     = self.crystal_gridding,
      fourier_coefficients = map_coefficients)
    fft_map.apply_sigma_scaling()
    m = fft_map.real_map_unpadded()
    m = fem.low_volume_density_elimination(m=m, fmodel=self.fmodel,
      selection=selection, end=11)
    ### Filter by 2mFo-DFc filled map
    fft_map = cctbx.miller.fft_map(
      crystal_gridding     = self.crystal_gridding,
      fourier_coefficients = f_map)
    fft_map.apply_sigma_scaling()
    filter_mask = fft_map.real_map_unpadded()
    filter_mask = fem.low_volume_density_elimination(m=filter_mask,
      fmodel=self.fmodel, selection=selection, end=6)#11)
    sel = filter_mask<0.25
    filter_mask = filter_mask.set_selected(sel, 0)
    sel = filter_mask>=0.25
    filter_mask = filter_mask.set_selected(sel, 1)
    ###
    return map_coefficients.structure_factors_from_map(
      map            = m*filter_mask,
      use_scale      = True,
      anomalous_flag = False,
      use_sg         = False)

  def box_iterator(self):
    b = maptbx.boxes(
      n_real   = self.atom_map_asu.focus(),
      fraction = self.box_size_as_fraction,
      max_boxes= self.max_boxes,
      log      = self.log)
    def get_wide_box(s,e): # define wide box: neutral + phased volumes
      if(self.neutral_volume_box_cushion_width>0):
        sh = self.neutral_volume_box_cushion_width
        ss = [max(s[i]-sh,0) for i in [0,1,2]]
        ee = [min(e[i]+sh,n_real_asu[i]) for i in [0,1,2]]
      else: ss,ee = s,e
      return ss,ee
    n_real_asu = b.n_real
    n_boxes = len(b.starts)
    i_box = 0
    for s,e in zip(b.starts, b.ends):
      i_box+=1
      sw,ew = get_wide_box(s=s,e=e)
      fmodel_omit = self.omit_box(start=sw, end=ew)
      r = fmodel_omit.r_work()
      self.r.append(r) # for tests only
      if(self.log):
        print("r(curr,min,max,mean)=%6.4f %6.4f %6.4f %6.4f"%(r,
          flex.min(self.r), flex.max(self.r), flex.mean(self.r)), i_box, n_boxes, file=self.log)
      omit_map_data = self.asu_map_from_fmodel(
        fmodel=fmodel_omit, map_type=self.map_type)
      maptbx.copy_box(
        map_data_from = omit_map_data,
        map_data_to   = self.map_result_asu,
        start         = s,
        end           = e)
    self.map_result_asu.reshape(self.acc_asu)

  def result_as_sf(self):
    asu_map_omit = asu_map_ext.asymmetric_map(
      self.sgt, self.map_result_asu, self.n_real)
    map_coefficients = self.zero_cmpl_ma.customized_copy(
      indices = self.zero_cmpl_ma.indices(),
      data    = asu_map_omit.structure_factors(self.zero_cmpl_ma.indices()))
    # full resolution map (reflections in sphere, not in box!)
    if(self.full_resolution_map):
      full_set = self.zero_cmpl_ma.complete_set(d_min=self.zero_cmpl_ma.d_min())
      fill = self.zero_cmpl_ma.customized_copy(
        indices = full_set.indices(),
        data    = asu_map_omit.structure_factors(full_set.indices()))
      map_coefficients = map_coefficients.complete_with(
        other=fill, scale=True)
    return map_coefficients

  def to_asu_map(self, map_data):
    r = asu_map_ext.asymmetric_map(self.sgt, map_data).data()
    if(self.acc_asu is None): self.acc_asu = r.accessor()
    # Why I'm doing this? This may be a bug for some SG!
    # See: exercise_structure_factors_from_map_and_asu_map in miller tests.
    return r.shift_origin()

  def omit_box(self, start, end):
    def asu_omit_map_as_sf(m_asu, s, e):
      m_asu_omit = maptbx.set_box_copy(value = 0, map_data_to = m_asu,
        start = s, end = e)
      m_asu_omit.reshape(self.acc_asu)
      asu_m_omit = asu_map_ext.asymmetric_map(self.sgt, m_asu_omit, self.n_real)
      return self.zero_cmpl_ma.customized_copy(
        indices = self.zero_cmpl_ma.indices(),
        data    = asu_m_omit.structure_factors(self.zero_cmpl_ma.indices()))
    f_calc_omit = asu_omit_map_as_sf(m_asu=self.atom_map_asu, s=start, e=end)
    f_mask_omit = asu_omit_map_as_sf(m_asu=self.bulk_solvent_mask_asu,
      s=start, e=end)
    fmodel_omit = mmtbx.f_model.manager(
      f_obs        = self.fmodel.f_obs(),
      r_free_flags = self.fmodel.r_free_flags(),
      k_isotropic  = self.fmodel.k_isotropic(),
      k_anisotropic= self.fmodel.k_anisotropic(),
      k_mask       = self.fmodel.k_masks(),
      f_calc       = f_calc_omit,
      f_mask       = f_mask_omit)
    return fmodel_omit

  def as_p1_map(self, map_asu=None):
    if(map_asu is None): map_asu = self.map_result_asu
    asu_map_omit = asu_map_ext.asymmetric_map(self.sgt, map_asu, self.n_real)
    p1_map = asu_map_omit.symmetry_expanded_map()
    maptbx.unpad_in_place(map=p1_map)
    sd = p1_map.sample_standard_deviation()
    if(sd != 0):
      p1_map = p1_map/sd
    return p1_map

  def get_p1_map_unscaled(self, fmodel, map_type):
    f_map = fmodel.electron_density_map().map_coefficients(
      map_type                   = map_type,
      isotropize                 = True,
      exclude_free_r_reflections = True,
      fill_missing               = False)
    fft_map = cctbx.miller.fft_map(
      crystal_gridding     = self.crystal_gridding,
      fourier_coefficients = f_map)
    return fft_map.real_map_unpadded()

  def asu_map_from_fmodel(self, fmodel, map_type):
    map_data = self.get_p1_map_unscaled(fmodel=fmodel, map_type=map_type)
    return asu_map_ext.asymmetric_map(self.sgt, map_data).data().shift_origin()

################################################################################

########################################################################
# XXX LEGACY IMPLEMENTATION
#
# The code below is similar to the method used by CNS, which operates on
# xray scatterers rather than the map itself.  As a result it requires
# refinement (w/ annealing) of the partial model to thoroughly de-bias
# the phases, and is therefore much slower than the protocol above.  It
# is preserved for maximum flexibility and because the same underlying
# method is also useful for analyzing static disorder at high resolution.
#
# Note that most of the program logic lives in the phenix tree due to
# its use of phenix.refine.

class omit_box(slots_getstate_setstate_default_initializer):
  """
  Defines a region in fractional coordinates containing a selection of atoms
  to be omitted.
  """
  __slots__ = [ "frac_min", "frac_max", "selection", "serial" ]

  @property
  def n_atoms(self):
    return len(self.selection)

  def show(self, out=sys.stdout, prefix=""):
    print(prefix + \
      "box %d: atoms: %6d  extents: (%.4f, %.4f, %.4f) to (%.4f, %.4f, %.4f)" \
      % tuple([ self.serial, len(self.selection) ] +
        list(self.frac_min) + list(self.frac_max)), file=out)

class omit_regions(slots_getstate_setstate):
  """
  Groups together multiple omit_box objects (without any implicit spatial
  relationship); this is used to reduce the total number of bins of omitted
  atoms and to make the fraction omitted per bin approximately similar.
  """
  __slots__ = [ "boxes", "selection", "serial" ]
  def __init__(self, serial, selection=None):
    self.serial = serial
    self.boxes = []
    self.selection = selection
    if (selection is None):
      self.selection = flex.size_t()

  @property
  def n_boxes(self):
    return len(self.boxes)

  @property
  def n_atoms(self):
    return len(self.selection)

  def add_box(self, box):
    self.boxes.append(box)
    self.selection = join_selections(box.selection, self.selection)
    return self

  def combine_with(self, other):
    for box in other.boxes :
      self.add_box(box)
    return self

  def show(self, out=sys.stdout, prefix=""):
    if (len(self.boxes) == 0):
      print(prefix + "Region %d: empty" % self.serial, file=out)
    else :
      print(prefix + "Region %d:" % self.serial, file=out)
      for box in self.boxes :
        box.show(out=out, prefix=prefix+"  ")

class omit_region_results(slots_getstate_setstate_default_initializer):
  __slots__ = [ "serial", "map_coeffs_list", "r_work", "r_free" ]

def create_omit_regions(xray_structure,
    selection=None,
    fraction_omit=0.05,
    optimize_binning=True,
    box_cushion_radius=2.5,
    even_boxing=False,
    asu_buffer_thickness=1.e-5,
    log=None):
  """
  Divide the asymmetric unit into boxes of atoms to omit.  This will include
  a cushion around the actual omit region.  Although the step size is uniform,
  by default boxes will be grouped as needed to make the distribution roughly
  even and keep the total number of omit regions to a minimum.
  If a region does not contain any atoms, it will be skipped and filled in
  with the background map.

  Returns a list of omit_regions objects, which specify the selection of atoms
  to omit along with the boxes of interest (in fractional coordinates).
  """
  if (log is None) : log = null_out()
  if (selection is None):
    selection = flex.bool(xray_structure.scatterers().size(), True)
  iselection = selection.iselection()
  boxes = []
  xrs = xray_structure.sites_mod_positive()
  unit_cell = xrs.unit_cell()
  asu_mappings = xrs.asu_mappings(buffer_thickness=asu_buffer_thickness)
  asu = asu_mappings.asu()
  #print asu.box_min(), asu.box_max()
  sites_asu = flex.vec3_double()
  for i_seq, mappings in enumerate(asu_mappings.mappings()):
    if (not selection[i_seq]) : continue
    for mapping in mappings :
      site_cart = mapping.mapped_site()
      site_frac = unit_cell.fractionalize(site_cart=site_cart)
      sites_asu.append(site_frac)
      break
  x_cushion, y_cushion, z_cushion = unit_cell.fractionalize(
    site_cart=[ box_cushion_radius ] * 3)
  x_min, y_min, z_min = sites_asu.min()
  x_max, y_max, z_max = sites_asu.max()
  #print "min", x_min, y_min, z_min
  #print "max", x_max, y_max, z_max
  non_hd_sel = ~(xray_structure.hd_selection())
  n_omit_heavy_atoms = non_hd_sel.select(iselection).count(True)
  n_omit_per_box = n_omit_heavy_atoms * fraction_omit
  assert (n_omit_heavy_atoms > 0)
  if (even_boxing) : # XXX remove?
    x_step = asu_buffer_thickness + (x_max - x_min) / 4
    y_step = asu_buffer_thickness + (y_max - y_min) / 4
    z_step = asu_buffer_thickness + (z_max - z_min) / 2
  else :
    volume = n_omit_heavy_atoms * 9.0
    cube_length = (volume * fraction_omit) ** (1/3.)
    x_step, y_step, z_step = unit_cell.fractionalize(site_cart=[cube_length]*3)
  # to facilitate using the C++ loops to determine which sites fall inside the
  # box, we first split the fractional coordinates into separate x, y, z 1D
  # arrays.  not sure if there's a better way.
  sites_1d = sites_asu.as_double()
  sel_base = flex.size_t(range(len(sites_asu)))
  sites_x = sites_1d.select(sel_base*3)
  sites_y = sites_1d.select(sel_base*3+1)
  sites_z = sites_1d.select(sel_base*3+2)
  x_start = x_min
  serial = 1
  while (x_start < x_max):
    y_start = y_min
    while (y_start < y_max):
      z_start = z_min
      while (z_start < z_max):
        x_end = x_start + x_step
        y_end = y_start + y_step
        z_end = z_start + z_step
        x_min_box = x_start - x_cushion
        x_max_box = x_end + x_cushion
        y_min_box = y_start - y_cushion
        y_max_box = y_end + y_cushion
        z_min_box = z_start - z_cushion
        z_max_box = z_end + z_cushion
        box_selection = ((sites_x >= x_min_box) & (sites_x < x_max_box) &
                         (sites_y >= y_min_box) & (sites_y < y_max_box) &
                         (sites_z >= z_min_box) & (sites_z < z_max_box))
        box_iselection = box_selection.iselection()
        n_atoms_current_box = len(box_iselection)
        if (n_atoms_current_box > 0):
          frac_max = [min(x_end, 1.0), min(y_end, 1.0), min(z_end, 1.0)]
          new_box = omit_box(
            frac_min=[x_start, y_start, z_start],
            frac_max=frac_max,
            selection=iselection.select(box_iselection),
            serial=serial)
          boxes.append(new_box)
          serial += 1
        z_start += z_step
      y_start += y_step
    x_start += x_step
  groups = []
  for box in boxes :
    group = omit_regions(serial=box.serial).add_box(box)
    groups.append(group)
  if (optimize_binning):
    # http://en.wikipedia.org/wiki/Bin_packing_problem
    groups = sorted(groups, key=operator.attrgetter("n_atoms"), reverse=True)
    while True :
      n_combined = 0
      i_group = 0
      while i_group < len(groups):
        groups[i_group].serial = i_group + 1
        j_group = 0
        while j_group < i_group :
          n_atoms_combined = groups[i_group].n_atoms + groups[j_group].n_atoms
          if (n_atoms_combined <= n_omit_per_box):
            groups[j_group].combine_with(groups[i_group])
            del groups[i_group]
            n_combined += 1
            break
          j_group += 1
        i_group += 1
      if (n_combined == 0):
        break
  assert (len(set([ g.serial for g in groups ])) == len(groups))
  return groups

def join_selections(sel1, sel2):
  intersections = sel1.intersection_i_seqs(sel2)
  unique_sel = flex.bool(len(sel1), True)
  unique_sel.set_selected(intersections[0], False)
  sel1 = sel1.select(unique_sel)
  sel1.extend(sel2)
  return flex.sorted(sel1)

def combine_maps(
    map_arrays,
    omit_groups,
    background_map_coeffs,
    resolution_factor,
    flatten_background=False,
    sigma_scaling=False,
    control_map=False):
  """
  For each box, FFT the corresponding omit map coefficients, extract the
  omit regions, and copy them to the combined map, using Marat's asymmetric
  map class to handle symmetry expansion internally.
  """
  assert len(map_arrays) == len(omit_groups)
  space_group = background_map_coeffs.space_group()
  fft_map = background_map_coeffs.fft_map(
    symmetry_flags=maptbx.use_space_group_symmetry,
    resolution_factor=resolution_factor).apply_volume_scaling()
  if (sigma_scaling):
    fft_map.apply_sigma_scaling()
  background_map = fft_map.real_map_unpadded()
  #print "full map:", background_map.focus()
  if (flatten_background):
    sel_all = flex.bool(background_map.as_1d().size(), True)
    background_map.as_1d().set_selected(sel_all, 0)
  asym_map = asu_map_ext.asymmetric_map(space_group.type(), background_map)
  origin = asym_map.data().origin()
  n_real_all = background_map.focus()
  n_real_asu = asym_map.data().focus()
  m_real_asu = asym_map.data().all()
  #print "ORIGIN:", origin
  #print "N_REAL:", n_real_asu
  #print "M_REAL:", m_real_asu
  if (not control_map):
    f2g = maptbx.frac2grid(n_real_all)
    n = 0
    for group, map_coeffs in zip(omit_groups, map_arrays):
      space_group = map_coeffs.space_group()
      omit_fft_map = map_coeffs.fft_map(
        resolution_factor=resolution_factor,
        symmetry_flags=maptbx.use_space_group_symmetry).apply_volume_scaling()
      if (sigma_scaling):
        omit_fft_map.apply_sigma_scaling()
      omit_map = omit_fft_map.real_map_unpadded()
      omit_asym_map = asu_map_ext.asymmetric_map(space_group.type(), omit_map)
      assert omit_asym_map.data().focus() == n_real_asu
      for box in group.boxes :
        if (control_map) : continue
        grid_start = tuple(f2g(box.frac_min))
        grid_end = grid_max(f2g(box.frac_max), n_real_asu)
        #print grid_start, grid_end
        for u in range(grid_start[0], grid_end[0]+1):
          for v in range(grid_start[1], grid_end[1]+1):
            for w in range(grid_start[2], grid_end[2]+1):
              try :
                asym_map.data()[(u,v,w)] = omit_asym_map.data()[(u,v,w)]
              except IndexError :
                raise IndexError("n_real: %s  origin: %s  index: %s" %
                  (str(n_real_asu), str(origin), str((u,v,w))))
  return asym_map.map_for_fft()

def grid_max(grid_coords, n_real):
  return (min(grid_coords[0], n_real[0]-1), min(grid_coords[1], n_real[1]-1),
          min(grid_coords[2], n_real[2]-1))


'''
题目：
画图，综合例子。

程序分析：
利用for循环控制100-999个数，每个数分解出个位，十位，百位。。
'''
# !/usr/bin/python
# _*_ coding: UTF-8 _*_

import tkinter as tk

window = tk.Tk()            #主窗口
window.title('my window')   #窗口标题
canvas = tk.Canvas(window, bg='green', height=300, width=300)

canvas.pack()
x0 = 150
y0 = 100
canvas.create_oval(x0 - 10, y0 - 10, x0 + 10, y0 + 10)
canvas.create_oval(x0 - 20, y0 - 20, x0 + 20, y0 + 20)
canvas.create_oval(x0 - 50, y0 - 50, x0 + 50, y0 + 50)
import math
B = 0.809
for i in range(16):
	a = 2 * math.pi / 16 * i
	x = math.ceil(x0 + 48 * math.cos(a))
	y = math.ceil(y0 + 48 * math.sin(a) * B)
	canvas.create_line(x0,y0,x,y,fill='red')
canvas.create_oval(x0 - 60, y0 - 60, x0 + 60, y0 + 60)

for k in range(501):
	for i in range(17):
		a = (2 * math.pi / 16) * i + (2 * math.pi / 180) * k
		x = math.ceil(x0 + 48 * math.cos(a))
		y = math.ceil(y0 + 48 + math.sin(a) * B)
		canvas.create_line(x0,y0,x,y,fill='red')
	for j in range(51):
		a = (2 * math.pi / 16) * i + (2 * math.pi / 180) * k - 1
		x = math.ceil(x0 + 48 * math.cos(a))
		y = math.ceil(y0 + 48 * math.sin(a) * B)
		canvas.create_line(x0,y0,x,y,fill='red')

window.mainloop()


#Ejercicio-1
#Mete los valores del 1 al 50 en una lista.

lista = []
i = 1
while i <= 50:
    lista.append(i)
    i = i + 1
print(lista)

#¿Se podria hacer mucho mas compacto y eficiente?

lista = list(range(1, 101))
print(lista)

#Ejercicio -2
#Crear un diccionario con los jugadores de la Seleccion Española que gano el mundial.
#Casillas-ramos-pique-puyol-Capdevila-XabiAlonso-Busquets-xavi-Pedro-iniesta-Villa
#recorrer el diccionario e imprimir sus pares clave

futbolistas = {
    1 : "Casillas", 15 : "Ramos",
    3 : "Pique", 5 : "Puyol",
    11 : "Capdevila", 14 : "Xabi Alonso",
    16 : "Busquets", 8 : "Xavi Hernandez",
    18 : "Pedrito", 6 : "Iniesta",
    7 : "Villa" }
# Recorrer un diccionario, imprimiendo su clave-valor
for k,v in futbolistas.items():
    print ("%s -> %s" %(k,v))

#¿Cuantos elementos tiene el diccionario?
numElem = len(futbolistas)
print ("\nNumero de elementos del diccionario len(futbolistas) = %i" %numElem)

#Ejercicio - 3
#Pide un numero por teclado y guarda en una lista su tabla de multiplicar hasta el 10. Por ejemplo, si pide el 5 la lista tendrá: 5,10,15,20,25,30,35,40,45,50
numero = int(input("Dame un numero: "))
lista = []
for i in range(1, 11):
    lista.append(i * numero)
print(lista)

#Ejercicio -4
#Crea una tupla con números, pide un numero por teclado e indica cuantas veces se repite.
#la tupla sera por ejemplo: (5, 4, 3, 2, 1, 6, 45, 3, 6, 6, 6, 6, 6)

numeros = (5, 4, 3, 2, 1, 6, 45, 3, 6, 6, 6, 6, 6)
numero = int(input("Dame un numero: "))
contador = 0
for i in numeros:
    if numero == i:
        contador = contador + 1
print("Hay ", contador, " repeticion/es")

#¿Se podria hacer de forma mas compacta? Realizalo para la siguiente tupla: (7, 6, 5, 4, 3, 2, 3, 4, 5, 1, 4, 3)
numeros = (7, 6, 5, 4, 3, 2, 3, 4, 5, 1, 4, 3)
numero = int(input("Dame un numero: "))
print("Numero de repeticiones: ", numeros.count(numero))

#Ejercicio -5
#Crea una tupla con números e indica el numero con mayor valor y el que menor tenga. Realizalo para la tupla: (5, 4, 3, -2, 1, 6, 455, 3, 6, 6, 6, 6, 6)
numeros = (5, 4, 3, -2, 1, 6, 455, 3, 6, 6, 6, 6, 6)
maximo = numeros[0]
minimo = numeros[0]
for i in numeros:
    if i > maximo:
        maximo = i
    if i < minimo:
        minimo = i
print("El maximo es ", maximo)
print("El minimo es ", minimo)

#¿Se podria hacer mas eficiente? Realizalo para la tupla:(7, 6, 5, 4, 3, 2, 3, 4, 5, 1, 4, 3)
numeros = (7, 6, 5, 4, 3, 2, 3, 4, 5, 1, 4, 3)
print("Maximo: ", max(numeros))
print("Minimo: ", min(numeros))

#Ejercicio - 6
"""Crea una tupla con los meses del año, pide números al usuario, si el numero esta entre 1 y
la longitud máxima de la tupla, muestra el contenido de esa posición sino muestra un mensaje de error.
El programa termina cuando el usuario introduce un cero"""

meses = ("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre",
         "Diciembre")

salir = False
while (not salir):
    numero = int(input("Dame un numero: "))
    if (numero == 0):
        salir = True
    else:
        if (numero >= 1 and numero <= len(meses)):
            print(meses[numero - 1])
        else:
            print("Inserta un numero entre 1 y ", len(meses))

#Ejercicio-7

#Escriba un programa que permita crear una lista de palabras.
#Para ello, el programa tiene que pedir un número y luego solicitar ese número de palabras para crear la lista.
#Por último, el programa tiene que escribir la lista.

numero = int(input("Dígame cuántas palabras tiene la lista: "))

if numero < 1:
    print("¡Imposible!")
else:
    lista = []
    for i in range(numero):
        print("Dígame la palabra", str(i + 1) + ": ", end="")
        palabra = input()
        lista += [palabra]
    print("La lista creada es:", lista)

#Ejercicio - 8
#Escriba un programa que permita crear una lista de palabras y que, a continuación, pida una palabra y elimine esa palabra de la lista.
numero = int(input("Dígame cuántas palabras tiene la lista: "))

if numero < 1:
    print("¡Imposible!")
else:
    lista = []
    for i in range(numero):
        print("Dígame la palabra", str(i + 1) + ": ", end="")
        palabra = input()
        lista += [palabra]
    print("La lista creada es:", lista)

    eliminar = input("Palabra a eliminar: ")
    for i in range(len(lista)-1, -1, -1):
        if lista[i] == eliminar:
            del(lista[i])
    print("La lista es ahora:", lista)

#Ejercicio-9
"""Escriba un programa que permita crear una lista de palabras y que,
a continuación, cree una segunda lista igual a la primera, pero al revés (no se trata de escribir la lista al revés, sino de crear una lista distinta)"""

numero = int(input("Dígame cuántas palabras tiene la lista: "))

if numero < 1:
    print("¡Imposible!")
else:
    lista = []
    for i in range(numero):
        print("Dígame la palabra", str(i + 1) + ": ", end="")
        palabra = input()
        lista += [palabra]
    print("La lista creada es:", lista)

    inversa = []
    for i in lista:
        inversa = [i] + inversa
    print("La lista inversa es:", inversa)


"""Query Rewriting Retriever Pack."""

from typing import Any, Dict, List

from llama_index.indices.vector_store import VectorStoreIndex
from llama_index.llama_pack.base import BaseLlamaPack
from llama_index.schema import TextNode
from llama_index.query_engine import RetrieverQueryEngine
from llama_index.indices.service_context import ServiceContext
from llama_index.retrievers import QueryFusionRetriever

class QueryRewritingRetrieverPack(BaseLlamaPack):
    """Query rewriting retriever pack.

    Given input nodes, build a vector index.

    Then rewrite the query into multiple queries and
    rerank the results.

    """

    def __init__(
        self,
        nodes: List[TextNode] = None,
        chunk_size: int = 256,
        mode: str = "reciprocal_rerank",
        vector_similarity_top_k: int = 2,
        fusion_similarity_top_k: int = 2,
        num_queries: int = 4,
        **kwargs: Any,
    ) -> None:
        """Init params."""
        service_context = ServiceContext.from_defaults(chunk_size=chunk_size)
        index = VectorStoreIndex(nodes, service_context=service_context)
        self.vector_retriever = index.as_retriever(
            similarity_top_k=vector_similarity_top_k
        )

        self.fusion_retriever = QueryFusionRetriever(
            [self.vector_retriever],
            similarity_top_k=fusion_similarity_top_k,
            num_queries=num_queries,  # set this to 1 to disable query generation
            mode=mode,
            use_async=True,
            verbose=True,
            # query_gen_prompt="...",  # we could override the query generation prompt here
        )

        self.query_engine = RetrieverQueryEngine.from_args(self.fusion_retriever)

    def get_modules(self) -> Dict[str, Any]:
        """Get modules."""
        return {
            "vector_retriever": self.vector_retriever,
            "fusion_retriever": self.fusion_retriever,
            "query_engine": self.query_engine,
        }

    def retrieve(self, query_str: str) -> Any:
        """Retrieve."""
        return self.fusion_retriever.retrieve(query_str)

    def run(self, *args: Any, **kwargs: Any) -> Any:
        """Run the pipeline."""
        return self.query_engine.query(*args, **kwargs)


from tkinter import *
from time import sleep

from fonctionsArduino import *
from fonctionsData import *
from moyennes import *
from fonctionsLogs import *
from formatH import *

def updateData(tkVars, tkObj, moyennes, params, dataTab, data, fichier=False, tpsConsigne=0, tempo=1, donnees=0):
    #   Permet de mettre à jour les variables d'affichage de l'interface avec les données Arduino
    #
    #   @param :
    #       tkVars : dictionnaire contenant toutes les variables de l'affichage
    #       tkObj : dictionnaire contenant tous les objets à modifier
    #       moyennes : dictionnaire qui contient toutes les séries de données utilisées pour le calcul des moyennes
    #       params : dictionnaire contenant les valeurs des paramètres
    #       dataTab : liste contenant les valeurs de l'arduino (issue de decodageArduino)
    #       data : dictionnaire contenant les valeurs convertie et classées
    #       (fichier) : objet contenant le fichier de log à écrire
    #       (tempsConsigne) : variable stockant la valeur du temps limite de la tempo pour les logs
    #       (tempo) : temporisation pour enregistrer les données dans le log (en seconde)
    #       (donnees) : liste des valeurs à écrire dans le log
    #
    #

    #Vérifier si le flux est complet, sinon attendre qu'il n'y ait plus d'erreurs
    try:
        """Conversion des données Arduino"""
        convArduino(dataTab, data)

        """Mise à jour des variables de l'interface"""
        conso = moyennes["conso"]
        vite = moyennes["vite"]

        ##Accélérateur
        majProgressBar(data["valAcc"],tkVars["accelerateurValeur"],tkVars["valeurAccStr"])

        ##Frein
        majProgressBar(data["valFrein"],tkVars["freinValeur"],tkVars["valeurFreinStr"])

        ##Batterie
        majProgressBar(data["valBatt"],tkVars["batterieValeur"],tkVars["valeurBattStr"])
        Tension = data["valBatt"]*(params["maxVBat"]-params["minVBat"])/100.+params["minVBat"]
        tkVars["voltageBattStr"].set("{0:.2f}".format(Tension) + " V")

        majCouleur(data["valBatt"],tkObj["lbatt"],"green",30,"orange",10,"red")

        """Le choix de cet algorithme de calcul est à vérifier (cycle de décharge non linéaire, estimation energie à calibrer) -> cf fichier ODC"""
        energie = params["capBat"]*params["maxVBat"]*data["valBatt"]/100
        tkVars["energieBattStr"].set("{0:.2f}".format(energie) + " Wh")

        ##Consommation
        Intensite = convBinNumCentre(params["I0"],data["valIntensite"],params["Imax"])
        puissance = Tension*Intensite

        if puissance > 0:
            #Décharge
            majProgressBar(puissance,tkVars["puissanceValeurConso"],tkVars["valeurPuisConsoStr"],0,"W")
            majProgressBar(0,tkVars["puissanceValeurProd"],tkVars["valeurPuisProdStr"],0,"W")

        elif puissance < 0:
            #Charge
            majProgressBar(0,tkVars["puissanceValeurConso"],tkVars["valeurPuisConsoStr"],0,"W")
            majProgressBar(-1*puissance,tkVars["puissanceValeurProd"],tkVars["valeurPuisProdStr"],0,"W")

        else:
            #Arrêt
            majProgressBar(0,tkVars["puissanceValeurConso"],tkVars["valeurPuisConsoStr"],0,"W")
            majProgressBar(0,tkVars["puissanceValeurProd"],tkVars["valeurPuisProdStr"],0,"W")

        moyenneDynamique(conso,puissance,params["majMoy"])
        tkVars["moyenneConso"].set("{0:.0f}".format(conso["moy"]) + " W")
        majCouleur(conso["moy"],tkObj["lMoyConso"],"red",0,"green")

        if conso["moy"] > 0:
            autonomie = energie/conso["moy"]
            tkVars["estimationBatt"].set("~ " + formatH(autonomie))
        else:
            autonomie = -1
            tkVars["estimationBatt"].set("N/A")

        ##Vitesse
        vitesse = data["valVitesse"]*params["Vmax"]/100

        majProgressBar(vitesse,tkVars["vitesseValeur"],tkVars["valeurVitesseStr"],0,"km/h   <=>   "+"{0:.1f}".format(vitesse*10/36.) + " m/s")

        moyenneDynamique(vite,vitesse,params["majMoy"])
        tkVars["moyenneVitesse"].set("Vitesse moyenne : " + "{0:.1f}".format(vite["moy"]) + " km/h")

        if autonomie < 0:
            tkVars["estimationVitesse"].set("Autonomie restante : N/A")
        else:
            tkVars["estimationVitesse"].set("Autonomie restante : ~ " + "{0:.0f}".format(vite["moy"]*autonomie) + " km")

        ##Mise à jour du log si actif
        if fichier != False:
            #[tps,acc,frein,ubat,imot,vit]
            donnees[1] = str(tkVars["accelerateurValeur"].get())
            donnees[2] = str(tkVars["freinValeur"].get())
            donnees[3] = "{0:.2f}".format(Tension)
            donnees[4] = "{0:.2f}".format(Intensite)
            donnees[5] = "{0:.1f}".format(tkVars["vitesseValeur"].get())
            logSession(fichier,donnees,tpsConsigne,tempo)

    except ValueError:
        #Pause de 10ms
        sleep(0.01)
    except IndexError:
        #Pause de 10ms
        sleep(0.01)

if __name__ == '__main__':
    exit()


import socket
import packet
import sys
import threading
import time
from socket import SOCK_DGRAM
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QFont
from PyQt5.QtWidgets import QGridLayout, QScrollArea, QLabel, QListView, QProgressBar
from PyQt5.QtWidgets import QLineEdit, QComboBox, QGroupBox
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton
from PyQt5.QtWidgets import QVBoxLayout, QMessageBox, QTabWidget

FORMAT = "utf-8"

class Client(QWidget):
    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        # connection
        self.conn = socket.socket()
        self.connected = False

        # tab settings
        self.layout = QVBoxLayout(self)
        self.tabs = QTabWidget()
        self.tabs.resize(300, 200)

        self.tabHome = QWidget()
        self.tabChat = QWidget()
        self.tabFiles = QWidget()

        self.tabs.addTab(self.tabHome, "Home")
        self.tabs.addTab(self.tabChat, "Chat Room")
        self.tabs.addTab(self.tabFiles, "Files")
        self.tabs.setTabEnabled(1, False)
        self.tabs.setTabEnabled(2, False)

        # Home Page
        gridHome = QGridLayout()
        self.tabHome.setLayout(gridHome)
        self.IPBox = QGroupBox("IP")
        self.IPLineEdit = QLineEdit()
        self.IPLineEdit.setText(socket.gethostbyname(socket.gethostname()))
        IPBoxLayout = QVBoxLayout()
        IPBoxLayout.addWidget(self.IPLineEdit)
        self.IPBox.setLayout(IPBoxLayout)
        self.portBox = QGroupBox("port")
        self.portLineEdit = QLineEdit()
        self.portLineEdit.setText("5050")
        portBoxLayout = QVBoxLayout()
        portBoxLayout.addWidget(self.portLineEdit)
        self.portBox.setLayout(portBoxLayout)
        self.nameBox = QGroupBox("Name")
        self.nameLineEdit = QtWidgets.QLineEdit()
        nameBoxLayout = QVBoxLayout()
        nameBoxLayout.addWidget(self.nameLineEdit)
        self.nameBox.setLayout(nameBoxLayout)
        self.connStatus = QLabel("Status", self)

        font = QFont()
        font.setPointSize(16)

        self.connStatus.setFont(font)
        self.connButton = QPushButton("Connect")
        self.connButton.clicked.connect(self.connect_server)
        self.disconnButton = QPushButton("Disconnect")
        self.disconnButton.clicked.connect(self.disconnect_server)

        gridHome.addWidget(self.IPBox, 0, 0, 1, 1)
        gridHome.addWidget(self.portBox, 0, 1, 1, 1)
        gridHome.addWidget(self.nameBox, 1, 0, 1, 1)
        gridHome.addWidget(self.connStatus, 1, 1, 1, 1)
        gridHome.addWidget(self.connButton, 2, 0, 1, 1)
        gridHome.addWidget(self.disconnButton, 2, 1, 1, 1)
        gridHome.setColumnStretch(0, 1)
        gridHome.setColumnStretch(1, 1)
        gridHome.setRowStretch(0, 0)
        gridHome.setRowStretch(1, 0)
        gridHome.setRowStretch(2, 9)

        # Chat Room
        gridChatRoom = QGridLayout()
        self.tabChat.setLayout(gridChatRoom)
        self.messageRecords = QLabel("Welcome to chat room!", self)
        self.messageRecords.setStyleSheet("background-color: white;")
        self.messageRecords.setAlignment(QtCore.Qt.AlignTop)
        self.messageRecords.setAutoFillBackground(True)
        self.scrollRecords = QScrollArea()
        self.scrollRecords.setWidget(self.messageRecords)
        self.scrollRecords.setWidgetResizable(True)
        self.sendTo = "ALL"
        self.sendChoice = QLabel("Send to :ALL", self)
        self.sendComboBox = QComboBox(self)
        self.sendComboBox.addItem("ALL")
        self.sendComboBox.activated[str].connect(self.send_choice)
        self.lineEdit = QLineEdit()
        self.lineEnterButton = QPushButton("Enter")
        self.lineEnterButton.clicked.connect(self.enter_line)
        self.lineEdit.returnPressed.connect(self.enter_line)
        self.friendList = QListView()
        self.friendList.setWindowTitle('Friends List')
        self.model = QStandardItemModel(self.friendList)
        self.friendList.setModel(self.model)

        gridChatRoom.addWidget(self.scrollRecords, 0, 0, 1, 3)
        gridChatRoom.addWidget(self.friendList, 0, 3, 1, 1)
        gridChatRoom.addWidget(self.sendComboBox, 1, 0, 1, 1)
        gridChatRoom.addWidget(self.sendChoice, 1, 2, 1, 1)
        gridChatRoom.addWidget(self.lineEdit, 2, 0, 1, 3)
        gridChatRoom.addWidget(self.lineEnterButton, 2, 3, 1, 1)
        gridChatRoom.setColumnStretch(0, 9)
        gridChatRoom.setColumnStretch(1, 9)
        gridChatRoom.setColumnStretch(2, 9)
        gridChatRoom.setColumnStretch(3, 1)
        gridChatRoom.setRowStretch(0, 9)

        # file page init
        FilePage = QGridLayout()
        self.tabFiles.setLayout(FilePage)
        self.dFile = QLabel("Download Files", self)
        self.dFile.setFont(font)
        self.download = QComboBox()
        self.start_download = QPushButton("Start download!")
        self.start_download.pressed.connect(self.getFileName)
        self.loadingbar = QProgressBar()
        self.start_download.clicked.connect(self.progressBarUI)
        self.start_download.clicked.connect(self.files_socket)

        FilePage.addWidget(self.dFile, 0, 0, 1, 1)
        FilePage.addWidget(self.download, 0, 1, 1, 1)
        FilePage.addWidget(self.start_download, 1, 1, 1, 1)
        FilePage.addWidget(self.loadingbar, 2, 0, 1, 3)
        FilePage.setRowStretch(0, 0)
        FilePage.setColumnStretch(0, 1)
        FilePage.setRowStretch(1, 0)
        FilePage.setColumnStretch(1, 1)

        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)

    def files_socket(self):
        file_transfer_socket = socket.socket(socket.AF_INET, SOCK_DGRAM)
        file_transfer_socket.bind((socket.gethostbyname(socket.gethostname()), 8080))
        self.conn.send(("[FILEA]" + self.download.currentText()).encode())
        self.receiveFile(file_transfer_socket, self.download.currentText())

        file_transfer_socket.close()

    def receiveFile(self, sock, filename):
        # Open file for writing
        try:
            file = open(filename, 'wb')
        except IOError:
            print('Unable to open', filename)
            return
        expected_num = 0
        while True:
            # Get next packet from the sender
            pkt, addr = sock.recvfrom(1024)
            if not pkt:
                break
            seq_num, data = packet.extractPacket(pkt)
            print('Got packet', seq_num)

            # Send back an ACK
            if seq_num == expected_num:
                print('Got expected packet')
                print('Sending ACK', expected_num)
                pkt = packet.createPacket(expected_num)
                sock.sendto(pkt, addr)
                expected_num += 1
                file.write(data)
            else:
                print('Sending ACK', expected_num - 1)
                pkt = packet.createPacket(expected_num - 1)
                sock.sendto(pkt, addr)
        print('Downloaded!')

        file.close()
        sock.close()

    def progressBarUI(self):
        for i in range(101):
            time.sleep(0.05)
            self.loadingbar.setValue(i)

    def getFileName(self):
        content = self.download.currentText()
        print("--DOWNLOADING-- " + content)

    def enter_line(self):
        # before sending, check if the receiver is the room
        if self.sendTo != self.sendComboBox.currentText():
            self.message_append_to_screen("The person has left.\nThe message was not delivered")
            self.lineEdit.clear()
            return
        line = self.lineEdit.text()
        if line == "":  # prevent empty message
            return
        if self.sendTo != "ALL":  # private message, first send to myself
            send_msg = bytes("[" + self.userName + "]" + line, FORMAT)
            self.conn.send(send_msg)
            time.sleep(0.1)  # this is important for not overlapping two sending
        send_msg = bytes("[" + self.sendTo + "]" + line, FORMAT)
        self.conn.send(send_msg)
        self.lineEdit.clear()
        self.scrollRecords.verticalScrollBar().setValue(self.scrollRecords.verticalScrollBar().maximum())

    def message_append_to_screen(self, newMessage, textColor="black"):
        oldText = self.messageRecords.text()
        appendText = oldText + "
" + newMessage + ""
        self.messageRecords.setText(appendText)
        time.sleep(0.2)
        self.scrollRecords.verticalScrollBar().setValue(self.scrollRecords.verticalScrollBar().maximum())

    def updateRoom(self):
        counter = 0
        while self.connected:
            data = self.conn.recv(1024)
            data = data.decode(FORMAT)
            print(data)
            if data != "":
                if "[FILES]" in data:
                    names = data.split("[FILES]")
                    self.update_file_list(names[1])
                    counter += 1
                    continue
                if "[CLIENTS]" in data:
                    welcome = data.split("[CLIENTS]")
                    self.update_send_to_list(welcome[1])
                    self.update_room_list(welcome[1])
                    if not welcome[0][5:] == "":
                        self.message_append_to_screen(welcome[0][5:])
                        self.scrollRecords.verticalScrollBar().setValue(
                            self.scrollRecords.verticalScrollBar().maximum())
                elif data[:5] == "[MSG]":
                    self.message_append_to_screen(data[5:], "blue")
                    self.scrollRecords.verticalScrollBar().setValue(self.scrollRecords.verticalScrollBar().maximum())
                else:
                    self.message_append_to_screen("[private] " + data, "green")
                    self.scrollRecords.verticalScrollBar().setValue(self.scrollRecords.verticalScrollBar().maximum())
            # this is for saving thread cycle time
            time.sleep(0.1)

    def update_file_list(self, strList):
        L = strList.split(",")
        self.download.clear()
        for file in L:
            self.download.addItem(file)

    def connect_server(self):
        if self.connected:
            return
        name = self.nameLineEdit.text()
        if name == "":
            self.connStatus.setText("Status :" + "Please enter your name")
            return
        self.userName = name
        IP = self.IPLineEdit.text()
        if IP == "":
            IP = "127.0.0.1"
        port = self.portLineEdit.text()
        if port == "" or not port.isnumeric():
            self.portLineEdit.setText("5050")
            self.connStatus.setText("Status :" + "Port format invalid")
            return
        else:
            port = int(port)
        try:
            self.conn.connect((IP, port))
        except:
            self.connStatus.setText("Status :" + " Refused")
            self.conn = socket.socket()
            return
        send_msg = bytes("[REGISTER]" + name, FORMAT)
        self.conn.send(send_msg)
        self.connected = True
        self.connStatus.setText("Status :" + " Connected")
        self.nameLineEdit.setReadOnly(True)  # This setting is not functional well
        self.tabs.setTabEnabled(1, True)
        self.tabs.setTabEnabled(2, True)
        self.newThread = threading.Thread(target=self.updateRoom)
        self.newThread.start()

    def disconnect_server(self):
        if not self.connected:
            return
        send_msg = bytes("[QUIT]", FORMAT)
        self.conn.send(send_msg)
        self.connStatus.setText("Status :" + " Disconnected")
        self.nameLineEdit.setReadOnly(False)
        self.nameLineEdit.clear()
        self.tabs.setTabEnabled(1, False)
        self.tabs.setTabEnabled(2, False)
        self.connected = False
        self.newThread.join()
        self.conn.close()

    def update_room_list(self, strList):
        L = strList.split(",")
        self.model.clear()
        for person in L:
            item = QStandardItem(person)
            item.setCheckable(False)
            self.model.appendRow(item)

    def update_send_to_list(self, strList):
        L = strList.split(",")
        self.sendComboBox.clear()
        self.sendComboBox.addItem("ALL")
        for person in L:
            if person != self.userName:
                self.sendComboBox.addItem(person)
        previous = self.sendTo
        index = self.sendComboBox.findText(previous)
        if index != -1:
            self.sendComboBox.setCurrentIndex(index)  # updating, maintain receiver
        else:
            self.sendComboBox.setCurrentIndex(0)  # updating, the receiver left, default to "ALL"

    def send_choice(self, text):
        self.sendTo = text
        print(self.sendTo)
        self.sendChoice.setText("Send to: " + text)

class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.setGeometry(50, 50, 500, 300)
        self.setWindowTitle("Best-Chat-Ever")
        self.table_widget = Client(self)
        self.setCentralWidget(self.table_widget)
        self.show()

    def closeEvent(self, event):
        close = QMessageBox()
        close.setText("You sure?")
        close.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        close = close.exec()
        if close == QMessageBox.Yes:
            self.table_widget.disconnect_server()  # disconnect to server before exit
            event.accept()
        else:
            event.ignore()

def run():
    app = QApplication(sys.argv)
    CLIENT = Window()
    sys.exit(app.exec_())

if __name__ == "__main__":
    run()


import torch
import numpy as np
import dgl
from drugood.utils import smile2graph
from functools import reduce
from sklearn.metrics import roc_auc_score

def split_into_groups(g):
    unique_groups, unique_counts = torch.unique(
        g, sorted=False, return_counts=True
    )
    group_indices = [
        torch.nonzero(g == group, as_tuple=True)[0]
        for group in unique_groups
    ]
    return unique_groups, group_indices, unique_counts

def collect_batch_substrure_graphs(subs, return_mask=True):
    sub_struct_list = list(reduce(lambda x, y: x.update(y) or x, subs, set()))
    sub_to_idx = {x: idx for idx, x in enumerate(sub_struct_list)}
    mask = np.zeros([len(subs), len(sub_struct_list)], dtype=bool)
    for idx, sub in enumerate(subs):
        mask[idx][list(sub_to_idx[t] for t in sub)] = True

    graphs = [smile2graph(x) for x in sub_struct_list]
    batch_data = dgl.batch(graphs)
    return (batch_data, mask) if return_mask else batch_data

def evaluate(pred, gt, metric='auc'):
    if isinstance(metric, str):
        metric = [metric]
    allowed_metric = ['auc', 'accuracy']
    invalid_metric = set(metric) - set(allowed_metric)
    if len(invalid_metric) != 0:
        raise ValueError(f'Invalid Value {invalid_metric}')
    result = {}
    for M in metric:
        if M == 'auc':
            all_prob = pred[:, 0] + pred[:, 1]
            assert torch.all(torch.abs(all_prob - 1) < 1e-2), \
                "Input should be a binary distribution"
            score = pred[:, 1]
            result[M] = roc_auc_score(gt, score)
        else:
            pred = pred.argmax(dim=-1)
            total, correct = len(pred), torch.sum(pred.long() == gt.long())
            result[M] = (correct / total).item()
    return result


'''
Challenge 6
Break repeating-key XOR
'''

def hamming_weight(num):
    ''' Calculate number of set bit '''
    return bin(num).count('1')

def hamming_distance(str1, str2):
    ''' Calculate number of differing bits '''
    count = 0
    len_diff = abs(len(str1) - len(str2))
    for i in range(min(len(str1), len(str2))):
        count += hamming_weight(ord(str1[i]) ^ ord(str2[i]))

    count += (len_diff * 8)
    return count

class RepeatingXORBreaker:

    def __init__(self, c):
        self.ciphertext = c

    def guess_keylength(self, max):
        distances = {}
        for i in range(2, max+1):
            # more blocks = more accuracy
            block1 = self.ciphertext[i*0:i*1]
            block2 = self.ciphertext[i*1:i*2]
            block3 = self.ciphertext[i*2:i*3]
            block4 = self.ciphertext[i*3:i*4]
            d12 = hamming_distance(block1, block2) / float(i)
            d13 = hamming_distance(block1, block3) / float(i)
            d14 = hamming_distance(block1, block4) / float(i)
            d23 = hamming_distance(block2, block3) / float(i)
            d24 = hamming_distance(block2, block4) / float(i)
            d34 = hamming_distance(block3, block4) / float(i)
            distances[i] = (d12 + d13 + d14 + d23 + d24 + d34) / 6.0

        distances_sorted = sorted(distances.items(), key=lambda x: x[1])
        probable_keylengths = [x[0] for x in distances_sorted]

        return probable_keylengths

    def try_break(self, keylength):
        # break cipher into blocks of keylength size
        blocks = []
        for i in range(0, len(self.ciphertext) - keylength, keylength):
            blocks.append(self.ciphertext[i:i+keylength])

        # take column from each blocks
        columns = [''] * keylength
        for i in range(keylength):
            for block in blocks:
                columns[i] += block[i]

        # freq analysis each column
        guessed_key = ''
        from set1.challenge3 import break_single_xor
        for column in columns:
            dec = break_single_xor(column, alternatives=1)
            key = dec[0]['key']
            #print dec[0]['plaintext']
            guessed_key += chr(key)

        # try decrypt (= encrypt) using the guessed key
        from set1.challenge5 import encrypt_repeated_xor
        plaintext = encrypt_repeated_xor(self.ciphertext, guessed_key)

        return guessed_key, plaintext


import os
import sqlite3
from sqlite3 import Error

current_dir = os.getcwd()
myDatabasePath = current_dir+'/myDatabase.db'

class PersonRepository:

    def __init__(self):
        self.conn = None
        pass

    def getConnection(self):
        if self.conn is None:
            self.conn = sqlite3.connect(myDatabasePath)

        return self.conn

    def findAll(self):
        try:
            itemList = []

            sql = """ SELECT * from personnes """

            c = self.getConnection().cursor()
            res = c.execute(sql)
            rows = res.fetchall()

            for row in rows:
                itemList.append({"firstname": row[1], "lastname": row[2]})

            return itemList

        except Error as e:
            print(e)

    def insert(self, form):
        try:

            sql = """ INSERT INTO personnes (firstname,lastname) VALUES (:firstname,:lastname );"""

            c = self.getConnection().cursor()
            c.execute(sql, form)
            self.conn.commit()

        except Error as e:
            print(e)

    def __del__(self):
        if self.conn:
            self.conn.close()


import collections
import logging
import pdb

import numpy as np
import yaml
import yamlordereddictloader

from generator import *
from generator import Generator, get_mem_props
from synthesis import ai_utils
from utils.logger import create_logger
from utils.visualizer import *

eff = 0.5

class Mapper:
    def __init__(self, hwfile="default.yaml", stats_file="logs/stats.txt"):
        """Mapper Class that Provides Interface for Different Mappings on the Architecture

        Args:
            hwfile (str, optional): . Defaults to "default.yaml".
            stats_file (str, optional): . Defaults to "logs/stats.txt".
        """
        base_dir = "configs/"
        self.total_cycles = 0
        self.technology = [1, 1, 40]
        # maybe change this later to peripheral logic node or speed
        #     [wire_cap , sense_amp_time, plogic_node],
        self.logger = create_logger(stats_file=stats_file)
        self.config = self.complete_config(
            yaml.load(open(base_dir + hwfile), Loader=yamlordereddictloader.Loader)
        )

    def complete_config(self, config):
        """
        1. Completes the Config for Hardware Description by using Technology/Design Functions
        2. Adds State Variables as Args that are Tracked for ASAP Mapping

        Args:
            config ():

        Returns:
            :
        """

        self.logger.debug("Config Statistics : ")

        self.mle = config["memory_levels"]
        self.mem_energy = np.zeros((self.mle))
        self.compute_energy = 0
        self.mem_read_access = np.zeros((self.mle))
        self.mem_write_access = np.zeros((self.mle))
        self.mem_size = np.zeros((self.mle))
        self.mem_util = np.zeros((self.mle))
        self.mem_free = np.zeros((self.mle))
        self.mem_read_bw = np.zeros((self.mle))
        self.mem_write_bw = np.zeros((self.mle))
        self.internal_bandwidth_time = 0
        self.total_cycles = 0
        self.bandwidth_idle_time = 0
        self.compute_idle_time = 0
        self.mem_size_idle_time = 0

        self.force_connectivity = config["force_connectivity"]
        mm_compute = config["mm_compute"]
        vector_compute = config["vector_compute"]

        if mm_compute["class"] == "systolic_array":
            config["mm_compute_per_cycle"] = (
                ((mm_compute["size"]) ** 2) * mm_compute["N_PE"] / (4)
            )
            config["comp_bw"] = (
                mm_compute["size"]
                * mm_compute["N_PE"]
                * mm_compute["frequency"]
                * 2
                / 4
            )

            self.logger.debug(
                "MM Compute per cycle : %d", config["mm_compute_per_cycle"]
            )
            self.logger.debug("Compute Bandwidth Required : %d", config["comp_bw"])

        if config["mm_compute"]["class"] == "mac":
            config["mm_compute_per_cycle"] = (mm_compute["size"]) * mm_compute["N_PE"]
            config["comp_read_bw"] = (
                mm_compute["size"] * mm_compute["N_PE"] * mm_compute["frequency"]
            )

        for i in range(self.mle):
            memory = config["memory"]["level" + str(i)]
            self.mem_read_bw[i] = (
                memory["frequency"]
                * memory["banks"]
                * memory["read_ports"]
                * memory["width"]
            )
            self.mem_write_bw[i] = (
                memory["frequency"]
                * memory["banks"]
                * memory["write_ports"]
                * memory["width"]
            )
            self.mem_size[i] = memory["size"]

            self.logger.debug(
                "Memory at Level %d, Read Bandwidth %d Write Bandwidth %d",
                i,
                self.mem_read_bw[i],
                self.mem_write_bw[i],
            )
        # complete_functional_config
        # complete_performance_config
        # memory
        for i in range(self.mle - 1):
            memory = config["memory"]["level" + str(i)]
            read_energy, write_energy, leakage_power, area = get_mem_props(
                memory["size"], memory["width"], memory["banks"]
            )
            config["memory"]["level" + str(i)]["read_energy"] = str(read_energy)
            config["memory"]["level" + str(i)]["write_energy"] = str(write_energy)
            config["memory"]["level" + str(i)]["leakage_power"] = str(leakage_power)
            config["memory"]["level" + str(i)]["area"] = str(area)
        # compute
        # config["memory"] = mem_space(config["memory"], technology)
        # config["mm_compute"] = comp_space(config["mm_compute"], technology)
        return config


# 输入：matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]]
# 输出：true
# 解释：
# 在上述矩阵中, 其对角线为:
# "[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]"。
# 各条对角线上的所有元素均相同, 因此答案是 True 。

def is_toeplitz_matrix(matrix) -> bool:
    for line in range(len(matrix) - 1):
        if matrix[line][:-1] != matrix[line + 1][1:]:
            return False
    return True

if __name__ == '__main__':
    _matrix = [[1, 2, 3, 4],
               [5, 1, 2, 3],
               [9, 5, 1, 2]]
    truth = is_toeplitz_matrix(_matrix)
    print(truth)


## time, space - O(N)
class Solution:
    def earliestAcq(self, logs: List[List[int]], N: int) -> int:
        parent = [i for i in range(N)]
        size = [1] * N
        logs.sort()

        def find(x):
            if x != parent[x]:
                parent[x] = find(parent[x])
            return parent[x]

        def union(x, y):
            rootX = find(x)
            rootY = find(y)
            if rootX != rootY:
                if size[rootX] < size[rootY]:
                    rootX, rootY = rootY, rootX
                parent[rootY] = rootX
                size[rootX] += size[rootY]
            if size[rootX] == N:
                return True
            else:
                return False

        for t, a, b in logs:
            if union(a, b):
                return t

        return -1

1101_The Earliest Moment When Everyone Become Friends_UF.py


import yfinance as yf
import streamlit as st

# Logo einfügen
from PIL import Image
image = Image.open('Diversify_Logo.png')

st.image(image)

# Überschrift
st.write("""
#  **How diversified is your ETF portfolio?**
### Now choose which ETFs you have in your portfolio!
""")

# ETF 1 auswählen
title = st.text_input('Type in the ETF ISIN (for example "IE00B4L5Y983" for the iShares Core MSCI World UCITS ETF)', 'IE00B4L5Y983')
amount = st.text_input('Type in the amount of money (in $), you are invested in this specific ETF', '7.000')

# ETF 2 auswählen
title2 = st.text_input('Type in the ETF ISIN (for example "IE00B0M63177" for the iShares MSCI EM UCITS ETF USD)', 'IE00B0M63177')
amount2 = st.text_input('Type in the amount of money (in $), you are invested in this specific ETF', '3.000')

#Ticker Symbol eingeben und die Daten dazu bekommen
tickerData = yf.Ticker(title)
#get the historical prices for this ticker
tickerDf = tickerData.history(period='1d', start='2010-5-31', end='2020-5-31')

# Zusammensetzung des ETFs (Top 10 Positionen) -- muss noch bearbeitet werden
tickerHolding = tickerData.get_major_holders()
st.bar_chart(tickerHolding)

# https://towardsdatascience.com/how-to-get-stock-data-using-python-c0de1df17e75

st.write("""
## Closing Price
""")
st.line_chart(tickerDf.Close)
st.write("""
## Volume Price
""")
st.line_chart(tickerDf.Volume)


"""Unittest of redis state."""
from unittest.mock import MagicMock

import pytest
from pytest_mock.plugin import MockerFixture

from Arbie import StateError
from Arbie.Actions import Action, RedisState, Store
from Arbie.Actions.action import Argument

@pytest.fixture
def local_store():
    return Store()

@pytest.fixture
def redis_store(redis_state):
    return Store(redis_state)

class MockAction(object):
    in_variable_name = "pools"
    in_constant_name = "amount"
    out_variable_name = "tokens"

    redis_item_key = "arbie.1.amount"
    redis_collection_key = "arbie.1.pools"
    redis_collection_item_key = "arbie.1.pools.0xA1cB32"

    in_settings = {in_variable_name: "uniswap", in_constant_name: 1337}
    out_settings = {out_variable_name: "good_tokens"}

    in_settings_parsed = {
        in_variable_name: Argument("uniswap"),
        in_constant_name: Argument(1337),
    }

    redis_in_settings_parsed = {
        in_variable_name: Argument("arbie.1.pools"),
        in_constant_name: Argument(1337),
    }

    out_settings_parsed = {out_variable_name: Argument("good_tokens")}

class TestAction(object):
    def test_get_input_output_settings(self, mocker: MockerFixture):
        mocker.patch(
            "Arbie.Actions.action.yaml.safe_load",
            return_value={
                Action.input_key: MockAction.in_settings,
                Action.output_key: MockAction.out_settings,
            },
        )
        action = Action()
        assert MockAction.in_settings_parsed == action.get_input_settings()
        assert MockAction.out_settings_parsed == action.get_output_settings()

    @pytest.mark.asyncio
    async def test_on_next(self):
        with pytest.raises(NotImplementedError):
            await Action().on_next(None)

@pytest.fixture
def mock_action():
    mock = MagicMock()
    mock.get_input_settings.return_value = MockAction.in_settings_parsed
    mock.get_output_settings.return_value = MockAction.out_settings_parsed
    return mock

@pytest.fixture
def mock_action_redis():
    mock = MagicMock()
    mock.get_input_settings.return_value = MockAction.redis_in_settings_parsed
    mock.get_output_settings.return_value = MockAction.out_settings_parsed
    return mock

class TestStore(object):
    def test_get_raises(self, local_store):
        with pytest.raises(KeyError):
            local_store.get("key")

    def test_get_add(self, local_store):
        local_store.add("key", 1)
        assert local_store.get("key") == 1

    def test_create_input_value_error(self, local_store, mock_action):
        with pytest.raises(ValueError):
            local_store.create_input(mock_action)

    def test_create_input(self, local_store, mock_action):
        local_store.add("uniswap", 1337)
        local_store.create_input(mock_action)

    def test_publish(self, local_store: Store):
        with pytest.raises(StateError):
            local_store.publish("random channel", "random message")

    def test_subscribe(self, local_store: Store):
        with pytest.raises(StateError):
            local_store.subscribe("random channel")

    def test_delete(self, local_store: Store):
        with pytest.raises(StateError):
            local_store.delete("random key")

class TestRedisStore(object):
    def test_get_raises(self, redis_store):
        with pytest.raises(KeyError):
            redis_store.get("key")

    def test_get_add(self, redis_store):
        redis_store.add("key", 1)
        assert redis_store.get("key") == 1

    def test_store_get(self, redis_state, mocker: MockerFixture):
        mock_get = mocker.patch.object(RedisState, "__getitem__")
        store = Store(redis_state)

        store[MockAction.redis_item_key]  # noqa: WPS428
        assert mock_get.called

    def test_store_add(self, redis_state, mocker: MockerFixture):
        mock_set = mocker.patch.object(RedisState, "__setitem__")
        store = Store(redis_state)

        store.add(MockAction.redis_collection_key, None)
        assert mock_set.called

    def test_create_input_value_error(self, redis_store, mock_action):
        with pytest.raises(ValueError):
            redis_store.create_input(mock_action)

    def test_create_input(self, redis_store, mock_action):
        redis_store.add("uniswap", 1337)
        redis_store.create_input(mock_action)

    def test_create_input_from_redis(self, redis_store, mock_action_redis, mocker):
        mocker.patch.object(RedisState, "__contains__", return_value=True)
        redis_store.create_input(mock_action_redis)