import subprocess
import random
import uuid
from typing import List

from src.core.Box import Box
from src.dto.RequestRunDTO import RequestRunDTO
from src.dto.RequestRunStepDTO import RequestRunStepDTO
from src.dto.ResultStepDTO import ResultStepDTO
from src.utils.FilesUtils import decode_base64

async def run_command(command):
    print('command : ' + ' '.join(command))
    process = subprocess.Popen(' '.join(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    process.wait()
    out, err = process.communicate()
    return out.decode('utf-8'), err.decode('utf-8')

async def cleanup_box(box_id):
    command_cleanup = ['isolate', '--cg', '-b', box_id, '--cleanup']
    out, err = await run_command(command_cleanup)
    if len(err) > 0:
        raise Exception('Fail to cleanup Sandbox')
    return out, err

async def exec_step(box, script, meta_data_file):
    command_to_exec = ['isolate', '--cg', '-b', box.box_id, '-M {}/box/{}'.format(box.workdir, meta_data_file)]
    command_to_exec += box.exec_settings
    command_to_exec += ['--run', '--']
    command_to_exec.append('/bin/bash /box/{}'.format(script))
    return await run_command(command_to_exec)

async def add_right_to_exec(file):
    command_to_exec = ['chmod', '+x', file]
    await run_command(command_to_exec)

def IsolateSingleton(class_):
    instances = {}

    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]

    return getinstance

@IsolateSingleton
class Isolate:
    MIN_BOX_ID = 1
    MAX_BOX_ID = 999

    def __init__(self):
        self.boxes: dict[str, Box] = dict()

    async def init_box(self, request: RequestRunDTO):
        box_id = random.randint(self.MIN_BOX_ID, self.MAX_BOX_ID)
        while str(box_id) in self.boxes.keys():
            box_id = random.randint(self.MIN_BOX_ID, self.MAX_BOX_ID)
        box_id_str = str(box_id)
        command_init = ['isolate', '--cg', '-b', box_id_str, '--init']
        out, err = await run_command(command_init)
        if len(err) > 0:
            print('err : {}'.format(err))
            raise Exception('Fail to create Sandbox')
        work_dir = out.strip()
        box = Box.init_box(box_id=box_id_str, workdir=work_dir)
        if request.settings is None:
            box.default_exec_settings()
        else:
            box.set_exec_settings(request.settings)

        zipped_file_path = box.write_file_in_box('', 'file.zip', decode_base64(request.files), True)
        box.write_files_zipped(zipped_file_path, 'box')

        self.boxes[box_id_str] = box
        print('New box id : {} are up'.format(box_id_str))
        return box_id_str

    async def run_steps(self, box_id, steps: List[RequestRunStepDTO]):
        box = self.boxes[box_id]
        steps_result = []

        for step in steps:
            step_id = uuid.uuid1()
            script_to_exec = box.write_script('box', step.script, step_id)
            await add_right_to_exec('{}/box/{}'.format(box.workdir, script_to_exec))
            meta_data_filename = 'meta-data-{}.txt'.format(step_id)
            out, err = await exec_step(box, script_to_exec, meta_data_filename)
            meta_data_file = '{}/box/{}'.format(box.workdir, meta_data_filename)
            meta_data = {}
            with open(meta_data_file, 'r') as f:
                for line in f:
                    tab_line = line.strip().split(':')
                    meta_data[tab_line[0]] = tab_line[1]
            steps_result.append(
                ResultStepDTO(
                    name=step.name,
                    status=int(meta_data['exitcode']),
                    stdout=out,
                    stderr=err,
                    time=meta_data['time'],
                    time_wall=meta_data['time-wall'],
                    memory_used=int(meta_data['cg-mem'])
                )
            )

        print('Results : {}'.format(steps_result))
        return steps_result

    async def delete_box(self, box_id):
        await cleanup_box(box_id)
        del self.boxes[box_id]
        print('Box id : {} are deleting'.format(box_id))

    def get_box(self, box_id: str):
        if box_id in self.boxes:
            return self.boxes[box_id]
        return None


import torch.nn as nn
from ..utils import _triple_same

class BaseConverter(object):
    """
    base class for converters
    """
    converter_attributes = []
    target_conv = None

    def __init__(self, model):
        """ Convert the model to its corresponding counterparts and deal with original weights if necessary """
        pass

    def convert_module(self, module):
        """
        A recursive function.
        Treat the entire model as a tree and convert each leaf module to
            target_conv if it's Conv2d,
            3d counterparts if it's a pooling or normalization module,
            trilinear mode if it's a Upsample module.
        """
        for child_name, child in module.named_children():
            if isinstance(child, nn.Conv2d):
                arguments = nn.Conv2d.__init__.__code__.co_varnames[1:]

                # cleaning the tuple due to new PyTorch namming schema (or added new variables)
                arguments = [a for a in arguments if a not in ['device', 'dtype', 'factory_kwargs','kernel_size_', 'stride_', 'padding_', 'dilation_']]

                kwargs = {k: getattr(child, k) for k in arguments}
                kwargs = self.convert_conv_kwargs(kwargs)
                setattr(module, child_name, self.__class__.target_conv(**kwargs))
            elif hasattr(nn, child.__class__.__name__) and \
                ('pool' in child.__class__.__name__.lower() or
                'norm' in child.__class__.__name__.lower()):
                if hasattr(nn, child.__class__.__name__.replace('2d', '3d')):
                    TargetClass = getattr(nn, child.__class__.__name__.replace('2d', '3d'))
                    arguments = TargetClass.__init__.__code__.co_varnames[1:]
                    arguments = [a for a in arguments if a not in ['device', 'dtype', 'factory_kwargs']]
                    kwargs = {k: getattr(child, k) for k in arguments}
                    if 'adaptive' in child.__class__.__name__.lower():
                        for k in kwargs.keys():
                            if not isinstance(kwargs[k], bool):
                                kwargs[k] = _triple_same(kwargs[k])
                    setattr(module, child_name, TargetClass(**kwargs))
                else:
                    raise Exception('No corresponding module in 3D for 2d module {}'.format(child.__class__.__name__))
            elif isinstance(child, nn.Upsample):
                arguments = nn.Upsample.__init__.__code__.co_varnames[1:]
                kwargs = {k: getattr(child, k) for k in arguments}
                kwargs['mode'] = 'trilinear' if kwargs['mode']=='bilinear' else kwargs['mode']
                setattr(module, child_name, nn.Upsample(**kwargs))
            else:
                self.convert_module(child)
        return module

    def convert_conv_kwargs(self, kwargs):
        """
        Called by self.convert_module. Transform the original Conv2d arguments
        to meet the arguments requirements of target_conv.
        """
        raise NotImplementedError

    def __getattr__(self, attr):
        return getattr(self.model, attr)

    def __setattr__(self, name, value):
        if name in self.__class__.converter_attributes:
            return object.__setattr__(self, name, value)
        else:
            return setattr(self.model, name, value)

    def __call__(self, x):
        return self.model(x)

    def __repr__(self):
        return self.__class__.__name__ + '(\n' + self.model.__repr__() + '\n)'


from django.db import IntegrityError
from rest_framework.exceptions import PermissionDenied
from notifications.tasks import create_notification
from notifications import events as notification_events
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from core.logging import logger, events
from votable.viewsets import VotableVieset
from study_resource import serializers
from app.settings import rewards

class ReviewVieset(VotableVieset):
    serializer_class = serializers.ReviewSerializer
    queryset = serializers.ReviewSerializer.queryset.order_by('-created_at')
    permission_classes = [IsAuthenticatedOrReadOnly]

    def list(self, request, *args, **kwargs):
        raise PermissionDenied(detail='Not allowed to list all reviews')

    def perform_create(self, serializer):
        try:
            serializer.save(author=self.request.user)
            self.request.user.positive_score += rewards.REVIEW_CREATE
            create_notification(serializer.instance.study_resource._meta.model, serializer.instance.study_resource.pk,
                                self.request.user.pk,
                                notification_events.VERB_REVIEW_NEW)
            logger.log_review(serializer.instance, events.OP_CREATE)
        except IntegrityError:
            raise PermissionDenied(
                detail='You already reviewed this. Only one review per resource is allowed for any user')

    def perform_destroy(self, instance):
        super(ReviewVieset, self).perform_destroy(instance)
        self.request.user.positive_score -= rewards.REVIEW_DELETE
        create_notification(instance.study_resource._meta.model, instance.study_resource.pk,
                            self.request.user.pk,
                            notification_events.VERB_REVIEW_REMOVE)
        logger.log_review(instance, events.OP_DELETE)


import sys

# Module docstring
"""
This script calculates total seconds from hours, minutes, and seconds passed as command line arguments.
"""

# Constants
SEC_PER_MIN = 60

# Main Body
def main():
    """ Main Body of Script """
    # Get command line arguments
    hours = sys.argv[1]
    minutes = sys.argv[2]
    seconds = sys.argv[3]

    # Calculate total seconds
    total_seconds = calc_total_seconds(hours, minutes, seconds)

    # Print results
    if total_seconds is None:
        print("Please enter valid numbers for hours, minutes, and seconds.")
    else:
        print(f"{hours}:{minutes}:{seconds} == {total_seconds} seconds")

# Functions
def calc_total_seconds(hours, minutes, seconds):
    """ Calculate total seconds from hours, minutes, and seconds """
    try:
        total_seconds = int(hours) * 3600 + int(minutes) * SEC_PER_MIN + int(seconds)
        return total_seconds
    except:
        return None

# Main script
if __name__ == "__main__":
    main()


from datetime import datetime

from dto.http_communication import HTTPCommunication, is_request_and_response_pair
from common.filters.http_filter import HttpFilter
from common.logging.logger_factory import LoggerFactory

class BrowsingReconstruct:
    def __init__(self, browsing_dao, timeout=10):
        self._logger = LoggerFactory.create_logger(self)
        self._http_comms = {}
        self._timeout = timeout  # Seconds
        self._counter = 0
        self._browsing_dao = browsing_dao
        self._filters = HttpFilter()

    def add_http_result(self, http_result):
        http_comm = HTTPCommunication(http_result.id, http_result.src_ip,
                                      http_result.dst_ip, http_result.src_port,
                                      http_result.dst_port, http_result.timestamp,
                                      http_result.stream_id)

        key = http_comm.five_tuple_key
        if http_result.pattern == 'GET':
            http_comm.uri = http_result.result
            self._http_comms[key] = http_comm

        if http_result.pattern == 'Host:':
            if key not in self._http_comms:
                return

            if self._http_comms[key].stream_id == http_comm.stream_id:
                self._http_comms[key].host = http_result.result

        if http_result.pattern == 'Content-Type:':
            if key not in self._http_comms:
                return

            if is_request_and_response_pair(self._http_comms[key], http_comm):
                self._http_comms[key].content_type = http_result.result

        if http_result.pattern == '<title':
            if key not in self._http_comms:
                return

            if is_request_and_response_pair(self._http_comms[key], http_comm):
                self._http_comms[key].title = http_result.result

                # Check http comm is valid or not
                if self._is_http_comm_valid(key):
                    if self._apply_filters(self._http_comms[key]):
                        self._save_browsing(key)
                del self._http_comms[key]

        self._counter += 1
        if self._counter > 100000:
            self._gc()
            self._counter = 0

    def _is_http_comm_valid(self, key):
        http_comm = self._http_comms[key]
        if not http_comm.is_valid():
            return False

        if not http_comm.content_type == 'text/html':
            return False

        if not http_comm.title:
            return False

        return True

    def _apply_filters(self, http_comm):
        if not self._filters.url(http_comm.url):
            return False

        if not self._filters.title(http_comm.title):
            return False

        return True

    def _save_browsing(self, key):
        self._browsing_dao.save(self._http_comms[key])

    def _gc(self):
        current_time = datetime.now()
        gc_keys = []

        for key, http_comm in self._http_comms.items():
            d = current_time - http_comm.created_at
            if d.total_seconds() > self._timeout:
                gc_keys.append(key)

        for key in gc_keys:
            del self._http_comms[key]

        self._logger.info("{0} record are deleted".format(len(gc_keys)))


import time
import torch
import numpy as np
from tqdm import tqdm
from models import model_utils as mu

def train_v3(model,
             optimizer,
             criterion,
             nepochs,
             device,
             config,
             train_dataloader = None,
             valid_dataloader = None
             ):

    #---------- logs and metrics
    eval_metrics   = mu.get_evaluation_metrics()
    eval_collector = mu.MetricsCollector(eval_metrics, config)
    eval_counter   = 0

    #---------- init steps
    saver     = mu.MSaver(config.path_to_models, config.experiment_name)

    scheduler = None
    if config.use_scheduler == True:
        scheduler = mu.LRScheduler(optimizer, train_dataloader, nepochs, config.which_scheduler, config)

    earlystopper = None
    if config.use_early_stopping == True:
        earlystopper = mu.EarlyStopping(patience = config.patience)

    #---------- TRAINNING & VALIDATION
    for tepoch in range(nepochs):
        epoch_start_time   = time.time()
        print(f'{time.ctime(epoch_start_time)}: epoch: {tepoch}/{nepochs}')

        #---------- TRAINNING LOOP
        model.train()
        train_counter      = 0
        running_loss_train = 0.0
        # each batch contains n_images, n_patches, 1 channel, patch_size_x, patch_size_y, patch_size_z
        with tqdm(train_dataloader, unit='batch') as tqdm_loader:
            for _, image, _, segm_image in tqdm_loader:
                train_counter += 1
                image          = image.to(device)
                segm_image     = segm_image.to(device)

                optimizer.zero_grad()
                image      = model(image)
                loss_train = criterion(image, segm_image)
                loss_train.backward()
                optimizer.step()
                running_loss_train   += loss_train.item()

                del loss_train, image, segm_image
        #---------- print out message
        train_end_time   = time.time()
        print(f'TRAINING: {time.ctime(train_end_time)}: epoch: {tepoch}/{nepochs} loss: {running_loss_train/train_counter}')
        #----------

        #---------- VALIDATION LOOP
        model.eval()
        with torch.no_grad():
            valid_counter    = 0
            running_loss_val = 0.0
            eval_epoch       = mu.MetricsClass(eval_metrics, config.experiment_type)
            # each batch contains n_images, n_patches, 1 channel, patch_size_x, patch_size_y, patch_size_z
            with tqdm(valid_dataloader, unit='batch') as tqdm_loader:
                for _, image, _, segm_image in tqdm_loader:
                    valid_counter    += 1
                    image             = image.to(device)
                    segm_image        = segm_image.to(device)
                    image             = model(image)
                    loss_val          = criterion(image, segm_image)
                    running_loss_val += loss_val.item()

                    # compute evaluation metrics
                    eval_epoch(image, segm_image)

                    del loss_val, image, segm_image
        #---------- print out message
        valid_end_time   = time.time()
        print(f'VALIDATION: {time.ctime(valid_end_time)}: epoch: {tepoch}/{nepochs} loss: {running_loss_val/valid_counter}')
        eval_epoch.print_aggregate_results()
        eval_collector.add_epoch(eval_epoch, tepoch, running_loss_train/train_counter, running_loss_val/valid_counter)
        #----------

        #---------- update parameters
        eval_counter += 1
        if eval_counter > 15:
            eval_counter = 0
            eval_collector.save_config()
            eval_collector.save_logs()
            eval_collector.save_training_figs()

        if scheduler != None: scheduler(running_loss_val)

        saver(model, eval_epoch.get_metric('dice_score'), tepoch)
        stop_flag = False
        if earlystopper != None:
            stop_flag = earlystopper(running_loss_val, tepoch)
        if stop_flag == True:
            print(f'INFO: Early stopping {tepoch}')
            break

    return eval_collector


from rest_framework import viewsets
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import *
from .models import Currency
import requests
from django.contrib.auth.models import User
import os
from dotenv import dotenv_values
config = dotenv_values("../../.env")

@api_view()
def CallApiView(request):
    url = 'http://data.fixer.io/api/latest?access_key='+os.getenv('API_KEY')

    r = requests.get(url)
    data = r.json()
    for key, value in data['rates'].items():
        Currency.objects.create(name=key, rate=value)

    return Response('Tiedot haettu API:sta')

class CurrencyView(viewsets.ModelViewSet):
    serializer_class = CurrencySerializer
    queryset = Currency.objects.all()

@api_view()
def DeleteView(request):
    currencies = Currency.objects.all()
    queryset = currencies.delete()
    return Response('Paikallinen tietokanta tyhjennetty')

# kaikki käyttäjät
class UserView(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.all()

@api_view()
def UserLogout(request):
    request.session.delete()
    return Response('Kirjauduttu ulos')

# Vaihtoehtoinen tapa hakea lokaalin kantaan talletut valuuttakurssit
@api_view(['GET'])
def getCurrencies(request):
    queryset = Currency.objects.all()
    serializer = CurrencySerializer(queryset, many=True)
    return Response(serializer.data)


import sys
import os

current = os.path.dirname(os.path.realpath(__file__))
parent_directory = os.path.dirname(current)

sys.path.append(parent_directory)

import unittest
from word import Word
from tile import Tile
import json

class WordTestCase(unittest.TestCase):
    def setUp(self):
        self.word = Word()

    def tearDown(self):
        self.word.reset()

    def test_get_dict_repr(self):
        self.word.add_tile(Tile('h', 0))
        self.word.add_tile(Tile('e', 0))
        self.word.add_tile(Tile('l', 0))
        self.word.add_tile(Tile('l', 1))
        self.word.add_tile(Tile('o', 0))
        dict_repr = self.word.get_dict_repr()
        self.assertEqual(len(dict_repr), 5)
        self.assertIn('h0', dict_repr)
        self.assertIn('e0', dict_repr)
        self.assertIn('l0', dict_repr)
        self.assertIn('l1', dict_repr)
        self.assertIn('o0', dict_repr)

if __name__ == '__main__':
    unittest.main()


"""

"""

import os
import sys
import argparse
import yaml
import torch
import torch.nn.functional as F
# from prettytable import PrettyTable
from torch.utils.data import DataLoader
from test_protocol.utils.model_loader import ModelLoader
from test_protocol.utils.extractor.feature_extractor import CommonExtractor
from data_processor.test_dataset import CommonTestDataset
from backbone.backbone_def import BackboneFactory
from data_processor.train_dataset import ImageDataset

import random
import cv2
import numpy as np
from torch.utils.data import Dataset

def accu_key(elem):
    return elem[1]

class myImageDataset(Dataset):
    def __init__(self, data_root, train_file, crop_eye=False):
        self.data_root = data_root
        self.train_list = []
        train_file_buf = open(train_file)
        line = train_file_buf.readline().strip()
        while line:
            image_path, image_label = line.split(' ')
            self.train_list.append((image_path, int(image_label)))
            line = train_file_buf.readline().strip()
        self.crop_eye = crop_eye
    def __len__(self):
        return len(self.train_list)
    def __getitem__(self, index):
        image_path, image_label = self.train_list[index]
        image_path = os.path.join(self.data_root, image_path)
        image = cv2.imread(image_path)
        if self.crop_eye:
            image = image[:60, :]
        #image = cv2.resize(image, (128, 128)) #128 * 128
        # if random.random() > 0.5:
        #     image = cv2.flip(image, 1)
        if image.ndim == 2:
            image = image[:, :, np.newaxis]
        image = (image.transpose((2, 0, 1)) - 127.5) * 0.0078125
        image = torch.from_numpy(image.astype(np.float32))
        return image, image_path

# def extract_online(self, model, data_loader):
#     """Extract and return features.

#     Args:
#         model(object): initialized model.
#         data_loader(object): load data to be extracted.

#     Returns:
#         image_name2feature(dict): key is the name of image, value is feature of image.
#     """
#     model.eval()
#     image_name2feature = {}
#     with torch.no_grad():
#         for batch_idx, (images, filenames) in enumerate(data_loader):
#             images = images.to(self.device)
#             features = model(images)
#             features = F.normalize(features)
#             features = features.cpu().numpy()
#             for filename, feature in zip(filenames, features):
#                 image_name2feature[filename] = feature
#     return image_name2feature

if __name__ == '__main__':
    # conf = argparse.ArgumentParser(description='apd test protocal.')
    # conf.add_argument("--test_set", type = str,
    #                   help = "apd, lfw, cplfw, calfw, agedb, rfw_African, \
    #                   rfw_Asian, rfw_Caucasian, rfw_Indian.")
    # conf.add_argument("--data_conf_file", type = str,
    #                   help = "the path of data_conf.yaml.")
    # conf.add_argument("--backbone_type", type = str,
    #                   help = "Resnet, Mobilefacenets..")
    # conf.add_argument("--backbone_conf_file", type = str,
    #                   help = "The path of backbone_conf.yaml.")
    # conf.add_argument('--batch_size', type = int, default = 1024)
    # conf.add_argument('--model_path', type = str, default = 'mv_epoch_8.pt',
    #                   help = 'The path of model or the directory which some models in.')
    # args = conf.parse_args()
    # parse config.
    # with open(args.data_conf_file) as f:
    #     data_conf = yaml.load(f)[args.test_set]
    #     pairs_file_path = data_conf['pairs_file_path']
    #     cropped_face_folder = data_conf['cropped_face_folder']
    #     image_list_file_path = data_conf['image_list_file_path']
    # # define pairs_parser_factory
    # pairs_parser_factory = PairsParserFactory(pairs_file_path, args.test_set)
    # define dataloader
    # data_loader = DataLoader(CommonTestDataset(cropped_face_folder, image_list_file_path, False),
    #                          batch_size=args.batch_size, num_workers=4, shuffle=False)

    #model def
    backbone_factory = BackboneFactory('MobileFaceNet', '/home/chihyuan/ntuammai21s/hw1/project/test_protocol/backbone_conf.yaml')
    model_loader = ModelLoader(backbone_factory)
    feature_extractor = CommonExtractor('cuda:0')
    # lfw_evaluator = LFWEvaluator(data_loader, pairs_parser_factory, feature_extractor)
    # if os.path.isdir(args.model_path):
    #     accu_list = []
    #     model_name_list = os.listdir(args.model_path)
    #     for model_name in model_name_list:
    #         if model_name.endswith('.pt'):
    #             model_path = os.path.join(args.model_path, model_name)
    #             model = model_loader.load_model(model_path)
    #             mean, std = lfw_evaluator.test(model)
    #             accu_list.append((os.path.basename(model_path), mean, std))
    #     accu_list.sort(key = accu_key, reverse=True)
    # else:
    model = model_loader.load_model('/home/chihyuan/ntuammai21s/hw1/project/training_mode/conventional_training/out_dir/Epoch_199.pt')

    data_loader = DataLoader(myImageDataset('/home/chihyuan/ntuammai21s/hw1/project/data/train/C_prep', '/home/chihyuan/ntuammai21s/hw1/project/data/files/train_list.txt'),
                             batch_size=128, shuffle=False, num_workers = 4)
    model.eval()
    image_name2feature = feature_extractor.extract_online(model, data_loader)
    print(len(image_name2feature), len(image_name2feature['/home/chihyuan/ntuammai21s/hw1/project/data/train/C_prep/陳玉珍_10.jpg']))
    print(np.linalg.norm(image_name2feature['/home/chihyuan/ntuammai21s/hw1/project/data/train/C_prep/黃義交_5.jpg']))
    feat1 = image_name2feature['/home/chihyuan/ntuammai21s/hw1/project/data/train/C_prep/陳玉珍_10.jpg']
    # feat2 = image_name2feature['/home/chihyuan/ntuammai21s/hw1/project/data/train/C_prep/黃義交_13.jpg']
    # feat3 = image_name2feature['/home/chihyuan/ntuammai21s/hw1/project/data/train/C_prep/青木愛_13.jpg']
    cur_score = np.dot(feat1, feat1)
    for key, value in image_name2feature.items():
        if 0.5 < np.dot(feat1, value):
            print(key, np.dot(feat1, value))

    # print(cur_score)
    # cur_score2 = np.dot(feat1, feat2)
    # cur_score3 = np.dot(feat1, feat3)
    # print(cur_score2, cur_score3)


import os

class math():
    def add(x,y):
        return x+y

    def subtrac(x,y):
        return x-y

    def divide(x,y):
        return x/y

    def multiply(x,y):
        return x*y

    def square(x):
        return x**2

class solver():

    def add(total,x,y):
        total.append(math.add(x,y))
        x = total[-1]
        res = int(x)
        x = res
        total = []
        return x

    def subtrac(total,x,y):
        total.append(math.subtrac(x,y))
        x = total[-1]
        res = int(x)
        x = res
        total = []
        return x

    def devide(total,x,y):
        total.append(math.divide(x,y))
        x = total[-1]
        res = int(x)
        x = res
        total = []
        return x

    def multiply(total,x,y):
        total.append(math.multiply(x,y))
        x = total[-1]
        res = int(x)
        x = res
        total = []
        return x

    def square(total,x):
        total.append(math.square(x))
        x = total[-1]
        res = int(x)
        x = res
        total = []
        return x

def view():
    print('============================')
    print('\t Calculator ')
    print('============================')

view()
total = []
x = int(input("num: "))
z = ''
while z != '=':
    z = input("Operator: ")
    if z == '+':
        y = int(input("num: "))
        x = solver.add(total,x,y)
        os.system('clear')
        view()
        print("num: ",x)
    elif z == '-':
        y = int(input("num: "))
        x = solver.subtrac(total,x,y)
        os.system('clear')
        view()
        print("num: ",x)
    elif z == '/' or z ==':':
        y = int(input("num: "))
        x = solver.devide(total,x,y)
        os.system('clear')
        view()
        print("num: ",x)
    elif z == 'x' or z == '*':
        y = int(input("num: "))
        x = solver.multiply(total,x,y)
        os.system('clear')
        view()
        print("num: ",x)
    elif z == 'sqrt' or z == '^2':
        x = solver.square(total,x)
        os.system('clear')
        view()
        print("num: ",x)
    else:
        print('Operator not available')

os.system('clear')

view()
print("num: ",x)


from TikTokApi import TikTokApi
import pandas as pd
import json
from video import Videos

class analyticsEngineTrends(object):
    def __init__(self, api, seedUsers=None, nbTrendingVids = 1000) -> None:
        self.api = api
        self.seedUsers = seedUsers
        self.trending_videos = []

        if self.seedUsers:
            seedUsersId = [self.api.getUser(username)["userInfo"]["user"]["id"]
                           for username in seedUsers]
            suggested = [self.api.getSuggestedUserbyID(count=25, startingId=s_id)
                         for s_id in seedUsersId]

            for user in suggested:
                print(user)
                userVids = api.byUsername(user, count=10)
                temp = Videos(userVids)
                self.videos += temp

        else:
            temp = api.trending(count=nbTrendingVids,
                                          custom_verifyFp="")
            self.trending_videos = Videos(temp)

        return

def main():
    api = TikTokApi()
    n_videos = 100
    username = "tiktok"
    output_file_json = "./output/videos.json"
    output_file_csv = "./output/videos.csv"
    userVids = api.byUsername(username, count=n_videos)
    users = api.getUser(username)

    analysticsEngine = analyticsEngineTrends(api, nbTrendingVids=100000)
    trending_videos = analysticsEngine.videos

    with open("./output/trends.json", 'w') as outfile:
        json.dump(trending_videos, outfile)

    trending_videos.toDataframe().to_csv("./output/videos_trending.csv", sep=";", index=False, encoding="utf-8")

    with open("./output/user.json", 'w') as outfile:
        json.dump(users, outfile)

    with open("./output/response.json", 'w') as outfile:
        json.dump(userVids, outfile)

    videos = Videos(userVids)

    with open(output_file_json, 'w') as outfile:
        json.dump(videos.toList(), outfile)

    videos.toDataframe().to_csv(output_file_csv, sep=";", index=False, encoding="utf-8")

if __name__ == "__main__":
    main()


from telegram import Update
from telegram.ext import ConversationHandler, CallbackContext

from flowershop_bot.handlers.clients import texts
from flowershop_bot.models import User
from flowershop_bot.handlers.clients.keyboard import (make_keyboard_for_start_command)

def command_start(update: Update, context):
    print('command_start')
    if update.message:
        user_info = update.message.from_user.to_dict()
    else:
        user_info = {}
        user_info['id'] = context.user_data['user_id']
        user_info['first_name'] = context.user_data['first_name']
        #user_info['username'] = context.user_data['username']
    created = User.objects.get_or_create(tg_id=user_info['id'],)

    #args = context.args
    #if args:
    #    link_id = args[0]
    #    try:
    #        invitation_link = InvitationLink.objects.get(link_id=link_id)
    #        invitation_link.click_count += 1
    #        invitation_link.save()
    #    except InvitationLink.DoesNotExist:
    #        pass

    if created:
        text = texts.start_created.format(
            first_name=user_info['first_name']
        )
    else:
        text = texts.start_not_created.format(
            first_name=user_info['first_name']
        )

    context.bot.send_message(
        chat_id=update.effective_chat.id,
        text=text,
        reply_markup=make_keyboard_for_start_command(),
    )

def command_cancel(update: Update, _):
    print('command_cancel')
    text = texts.cancel_text
    update.message.reply_text(
        text=text,
        reply_markup=make_keyboard_for_start_command(),
    )
    return ConversationHandler.END


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

@author: gustavo
"""

import numpy as np
from random import random

def choleski(a):
    n = len(a)

    for k in range(n):
        try:
            a[k,k] = np.sqrt(a[k,k] - np.dot(a[k,0:k], a[k,0:k]))
        except ValueError:
            err('La matriz no es definida positiva')

        for i in range(k+1, n):
            a[i,k] = (a[i,k] - np.dot(a[i,0:k], a[k,0:k]))/a[k,k]

    for k in range(1,n): a[0:k,k] = 0.0

    return a

def LUdescomp(a):
    n = len(a)

    for k in range(0, n-1):
        for i in range(k+1, n):
           if a[i,k] != 0.0:
               lam = a [i,k]/a[k,k]
               a[i,k+1:n] = a[i,k+1:n] - lam * a[k,k+1:n]
               a[i,k] = lam
    return a

def LUsoluc(a,b):
    n = len(a)

    for k in range(1, n):
        b[k] = b[k] - np.dot(a[k,0:k],b[0:k])

    b[n-1] = b[n-1]/a[n-1,n-1]

    for k in range(n-2,-1,-1):
       b[k] = (b[k] - np.dot(a[k,k+1:n],b[k+1:n]))/a[k,k]

    return b

def LUdescomp3(c, d, e):
    c.setflags(write=True)
    n = len(d)
    for k in range(1, n):
        lam = c[k-1]/d[k-1]
        d[k] = d[k] - lam * e[k-1]
        c[k-1] = lam

    return c, d, e

def LUsoluc3(c, d, e, b):
    n = len(d)

    for k in range(1, n):
        b[k] = b[k] - c[k-1] * b[k-1]

    b[n-1] = b[n-1]/d[n-1]

    for k in range(n-2, -1, -1):
        b[k] = (b[k] - e[k] * b[k+1])/d[k]

    return b

def LUdescomp5(d, e, f):
    n = len(d)

    for k in range(n-2):
        lam = e[k]/d[k]
        d[k+1] = d[k+1] - lam * e[k]
        e[k+1] = e[k+1] - lam * f[k]
        e[k] = lam
        lam = f[k]/d[k]
        d[k+2] = d[k+2] - lam * f[k]
        f[k] = lam

    lam = e[n-2]/d[n-2]
    d[n-1] = d[n-1] - lam * e[n-2]
    e[n-2] = lam

    return d, e, f

def LUsoluc5(d, e, f, b):
    n = len(d)
    b[1] = b[1] - e[0] * b[0]

    for k in range(2, n):
        b[k] = b[k] - e[k-1] * b[k-1] - f[k-2] * b[k-2]

    b[n-1] = b[n-1]/d[n-1]
    b[n-2] = b[n-2]/d[n-2] - e[n-2] * b[n-1]

    for k in range(n-3, -1, -1):
        b[k] = b[k]/d[k] - e[k] * b[k+1] - f[k] * b[k+2]

    return b

def jacobi(a, tol = 1.0e-8):

    def umbral(a):
        suma = 0.0

        for i in range(n-1):
            for j in range(i+1, n):
                suma = suma + abs(a[i, j])

        return 0.5*suma/n/(n-1)

    def rotacion(a, p, k, l): # Rotacion para hacer a[k,l] = 0
        aDiff = a[l,l] - a[k,k]

        if abs(a[k,l]) < abs(aDiff) * 1.0e-36: t = a[k,l]/aDiff
        else:
            phi = aDiff/(2.0 * a[k,l])
            t = 1.0/(abs(phi) + np.sqrt(phi**2 + 1.0))

            if phi < 0.0: t = -t

        c = 1.0/np.sqrt(t**2 + 1.0); s = t*c
        tau = s/(1.0 + c)
        temp = a[k,l]
        a[k,l] = 0.0
        a[k,k] = a[k,k] - t * temp
        a[l,l] = a[l,l] + t * temp

        for i in range(k): # Caso i < k
            temp = a[i,k]
            a[i,k] = temp - s * (a[i,l] + tau * temp)
            a[i,l] = a[i,l] + s * (temp - tau * a[i,l])

        for i in range(k+1, l):  # Caso k < i < l
            temp = a[k,i]
            a[k,i] = temp - s * (a[i,l] + tau * a[k,i])
            a[i,l] = a[i,l] + s * (temp - tau * a[i,l])

        for i in range(l+1, n):  # Caso i > l
            temp = a[k,i]
            a[k,i] = temp - s * (a[l,i] + tau * temp)
            a[l,i] = a[l,i] + s *(temp - tau * a[l,i])

        for i in range(n):  # Actualizacion matriz de transformacion
            temp = p[i,k]
            p[i,k] = temp - s * (p[i,l] + tau * p[i,k])
            p[i,l] = p[i,l] + s * (temp - tau * p[i,l])

    n = len(a)
    p = np.identity(n, float)

    for k in range(20):
         mu = umbral(a) # Calcula un nuevo umbral

         for i in range(n-1):  # Barrido en la matriz
            for j in range(i+1, n):
                if abs(a[i,j]) >= mu:
                    rotacion(a, p, i, j)

         if mu <= tol: return np.diagonal(a), p

    print('El método de Jacobi no converge')

def swapRenglon(v, i, j):
    v.setflags(write=True)
    if len(v.shape) == 1:
        v[i], v[j] = v[j] , v[i]
    else:
        v[[i,j],:] = v[[j,i],:]

def swapColumna(v, i, j):
    # v.setflags(write=True)
    v[:,[i,j]] = v[:,[j,i]]

def ordenaJacobi(lam, x):
    n = len(lam)

    for i in range(n-1):
        index = i
        val = lam[i]

        for j in range(i+1, n):
            if lam[j] < val:
                index = j
                val = lam[j]

        if index != i:
            swapRenglon(lam, i, index)
            swapColumna(x, i, index)

def formaEstd(a, b):

    def invierte(L): # Invierte una matriz L
        n = len(L)

        for j in range(n-1):
            L[j,j] = 1.0/L[j,j]

            for i in range(j+1,n):
                L[i,j] = -np.dot(L[i,j:i],L[j:i,j])/L[i,i]

        L[n-1,n-1] = 1.0/L[n-1,n-1]

    n = len(a)
    L = choleski(b)
    invierte(L)
    h = np.dot(b,np.inner(a,L))
    return h, np.transpose(L)

def potenciaInversa(a, s, tol=1.0e-6):
    n = len(a)
    aAst = a - np.identity(n) * s  # Forma [a*] = [a] - s[I]
    aAst = LUdescomp(aAst)       # Descompone [a*]
    x = np.zeros(n)

    for i in range(n):          # Semilla [x] para los numeros aleatorios
        x[i] = random()

    xMag = np.sqrt(np.dot(x,x)) # Normaliza [x]
    x =x/xMag

    for i in range(50):         # Comienzan las iteraciones
        xAnterior = x.copy()         # Guarda el actual [x]
        x = LUsoluc(aAst, x)      # Resuelve [a*][x] = [xOld]
        xMag = np.sqrt(np.dot(x,x)) # Normaliza [x]
        x = x/xMag

        if np.dot(xAnterior,x) < 0.0:  # Detecta cambio de signo de [x]
            sign = -1.0
            x = -x
        else: sign = 1.0

        if np.sqrt(np.dot(xAnterior - x, xAnterior - x)) < tol:
            return s + sign/xMag, x, i

    print('El método de la potencia inversa no converge')

def potenciaInversa5(Bv, d, e, f, tol=1.0e-6):

    n = len(d)
    d, e, f = LUdescomp5(d, e, f)
    x = np.random.rand(n)
    xMag = np.sqrt(np.dot(x,x))
    x = x/xMag

    for i in range(30):
        xAnterior = x.copy()
        x = Bv(xAnterior)
        x = LUsoluc5(d, e, f, x)
        xMag = np.sqrt(np.dot(x,x))
        x = x/xMag

        if np.dot(xAnterior,x) < 0.0:
            sign = -1.0
            x = -x
        else: sign = 1.0

        if np.sqrt(np.dot(xAnterior - x,xAnterior - x)) < tol:
            return sign/xMag, x

    print('El método de la potencia inversa no converge')

def ridder(f, a, b, tol=1.0e-9):
    fa = f(a)
    if fa == 0.0: return a

    fb = f(b)
    if fa == 0.0: return b

    if np.sign(fa) == np.sign(fb): print('La raíz no está en el intervalo')

    for i in range(30):

        # Calcula la raiz x con la formula de Ridder
        c = 0.5 * (a + b); fc = f(c)
        s = np.sqrt(fc**2 - fa * fb)

        if s == 0.0: return None

        dx = (c - a) * fc/s

        if (fa - fb) < 0.0: dx = -dx

        x = c + dx; fx = f(x)

        # Prueba de convergencia
        if i > 0:
            if abs(x - xAnterior) < tol*max(abs(x), 1.0): return x

        xAnterior = x

        # Vuelva a "encerrar" a la raíz lo más ajustada posible
        if np.sign(fc) == np.sign(fx):
            if np.sign(fa)!= np.sign(fx): b = x; fb = fx
            else: a = x; fa = fx
        else:
            a = c; b = x; fa = fc; fb = fx

    return None

    print('Son demasiadas iteraciones')

def householder(a):
    n = len(a)

    for k in range(n-2):
        u = a[k+1:n,k]
        uMag = np.sqrt(np.dot(u,u))

        if u[0] < 0.0: uMag = -uMag

        u[0] = u[0] + uMag
        h = np.dot(u,u)/2.0
        v = np.dot(a[k+1:n,k+1:n],u)/h
        g = np.dot(u,v)/(2.0*h)
        v = v - g * u
        a[k+1:n,k+1:n] = a[k+1:n,k+1:n] - np.outer(v,u)- np.outer(u,v)
        a[k,k+1] = -uMag

    return np.diagonal(a), np.diagonal(a,1)

def calculaP(a):

    n = len(a)
    p = np.identity(n) * 1.0

    for k in range(n-2):
        u = a[k+1:n,k]
        h = np.dot(u,u)/2.0
        v = np.dot(p[1:n,k+1:n],u)/h
        p[1:n,k+1:n] = p[1:n,k+1:n] - np.outer(v,u)

    return p

def sturmSuc(d, c, lam):
    n = len(d) + 1
    p = np.ones(n)
    p[1] = d[0] - lam

    for i in range(2, n):
        p[i] = (d[i-1] - lam) * p[i-1] - (c[i-2]**2) * p[i-2]

    return p

def numLambdas(p):
    n = len(p)
    signAnterior = 1
    numLam = 0

    for i in range(1, n):
        if p[i] > 0.0: sign = 1
        elif p[i] < 0.0: sign = -1
        else: sign = -signAnterior

        if sign * signAnterior < 0: numLam = numLam + 1

        signAnterior = sign

    return numLam

def gerschgorin(d, c):
    n = len(d)

    lamMin = d[0] - abs(c[0])
    lamMax = d[0] + abs(c[0])

    for i in range(1, n-1):
        lam = d[i] - abs(c[i]) - abs(c[i-1])

        if lam < lamMin: lamMin = lam

        lam = d[i] + abs(c[i]) + abs(c[i-1])

        if lam > lamMax: lamMax = lam

    lam = d[n-1] - abs(c[n-2])

    if lam < lamMin: lamMin = lam

    lam = d[n-1] + abs(c[n-2])

    if lam > lamMax: lamMax = lam

    return lamMin, lamMax

def lamRango(d, c, N):

    lamMin, lamMax = gerschgorin(d, c)

    r = np.ones(N+1)

    r[0] = lamMin

    # Busca eigenvalores en orden descendente
    for k in range(N, 0, -1):

        # primera biseccion del intervalo (lamMin, lamMax)
        lam = (lamMax + lamMin)/2.0
        h = (lamMax - lamMin)/2.0

        for i in range(1000):

            # Encuentra el numero de eigenvalores menores que lam
            p = sturmSuc(d, c, lam)

            numLam = numLambdas(p)

            # De nuevo bisección y encuentra la mitad que contiene lam
            h = h/2.0

            if numLam < k: lam = lam + h
            elif numLam > k: lam = lam - h
            else: break

        # Si encuentra el eigenvalor, cambia el limite superior
        # de busqueda y lo guarda en [r]
        lamMax = lam
        r[k] = lam

    return r

def eigenvalores3(d, c, N):

    def f(x):
        p = sturmSuc(d, c, x)

        return p[len(p)-1]

    lam = np.zeros(N)
    r = lamRango(d, c, N)

    for i in range(N):
        lam[i] = ridder(f,r[i],r[i+1])

    return lam

def potenciaInversa3(d, c, s, tol=1.0e-6):
    n = len(d)

    e = c.copy()
    dAst = d - s

    LUdescomp3(c, dAst, e)
    x = np.random.rand(n)
    xMag = np.sqrt(np.dot(x,x))
    x =x/xMag
    bandera = 0

    for i in range(30):
        xAnterior = x.copy()
        LUsoluc3(c, dAst, e, x)
        xMag = np.sqrt(np.dot(x,x))
        x = x/xMag

        if np.dot(xAnterior,x) < 0.0:
            sign = -1.0
            x = -x
        else: sign = 1.0

        if np.sqrt(np.dot(xAnterior - x,xAnterior - x)) < tol:
            return s + sign/xMag, x

    print('El método de la potencia inversa no converge')

Tema 4 - Algebra matricial/Codigos python/moduloMatrices.py


"""
    This script will create a GitHub repository, Trello Board, and a directory
    in the personal projects area.

    Could use githubpy3 but wanna create my own
"""

import os
import requests
import sys
import json
import pprint
import logging

# Project location
projectLocation = ''
# User Data
user = ""
token = ""
#GitHub preferences
license_template = ''
auto_init = ''
# Github REST API URL
url = "https://api.github.com/"

def set_global_variables(configFile='.create_github_repo_config.json'):
    """
    This cuntion reads the json config file to find the preferences the user set to send to
    GitHub API and also to set a project folder location. MAKE SURE THE LOCATION EXISTS ALREADY.
    @param: configFile: A user can pass in a custom config file for one off runs or it will use the
                        default config file
    """
    # Gets the path of the JSON file, it should be in the same directory as the python file
    json_file_path = str(os.path.dirname(os.path.realpath(__file__))+'/'+str(configFile))
    # Opens file in read mode
    json_file = open(json_file_path, 'r')
    # Loads JSON file
    config = json.load(json_file)

    # Sets global variables so the API function can use it
    global projectLocation
    projectLocation = config['project_folder']
    logging.debug('Setting project location to: '+projectLocation)
    global user
    user = config['user']
    logging.debug('Setting user to: '+user)
    global token
    token = config['token']
    logging.debug('Setting token to: '+token)
    global license_template
    license_template = config['license_template']
    logging.debug('Setting license_template to: '+license_template)
    global auto_init
    auto_init = config['auto_init']
    logging.debug('Setting auto_init to: '+auto_init)

    return

def create_git_project(projectName):

    # Setting the Accept header to accept the preview API
    headers = {'Accept':'application/vnd.github.inertia-preview+json'}
    logging.debug('The user is '+user)
    logging.debug('Token is '+token)

    # Setting up the endpoint to get resource
    url_extra = 'repos/{0}/{1}/projects'.format(user, projectName)

    # Setting the payload to create project
    payload = {'name': projectName}

    # Making the request
    r = requests.post(url+url_extra, headers=headers, auth=(user,token), json=payload)

    return

def create_folder(projectName):
    """
    This function creates the folder for the project in the Projects directory
    @param: projectName: Name of the project, which will also be the name of the folder
    """
    # Make directory
    try:
        # ###########FIX: This will later become a config file setting
        os.mkdir(projectLocation+projectName)
        logging.debug("Directory created")
        return True
    except FileExistsError:
        logging.error("Folder already exists")
        return False

def create_repository(projectName, visibility):
    """
    This function will use GitHub's API with the users authentication token and user name,
    to create the repository for the new project with an empty README.
    @param: projectName: Name of the project and the GitHub repository
            visibility: Either a private or public repository
            description: Description of the new project
    """

    logging.debug("Describe the project:")
    description = input()
    # Payload to create a repository
    payload = {'name': projectName,
                'description': description,
                'private': visibility,
                'auto_init': auto_init,
                'license_template': license_template}

    # Make POST request to create repository
    r = requests.post((url+'user/repos'), auth=(user,token), json=payload)
    logging.debug("Response Status code is "+str(r.status_code))

    # Convert data to JSON
    data = r.json()

    if r.status_code == 201:
        clone_url = data['clone_url']
        logging.debug("Clone URL -> "+str(clone_url))
        logging.debug("Repository creation for project " + projectName + " in GitHub is complete")
        return clone_url
    else:
        logging.error("API call failed")
        logging.error(str(data['message']) +"  "+ str(data['errors'][0]['message']))
        return ''

if __name__ == "__main__":

    if sys.argv[1] == 'debug':
        #logging settings
        logging.basicConfig(level=logging.DEBUG)
        logging.debug('YOU ARE ON DEBUG MODE')
        set_global_variables(configFile='.custom_config_file.json')
    else:
        # Getting config file preferences
        if len(sys.argv) == 4:
            set_global_variables(configFile=sys.argv[3])
            logging.debug("Using CUSTOM config file " + sys.argv[3])
        else:
            set_global_variables()
            logging.debug("Using DEFAULT config file .create_github_repo_config.json")

        #logging settings
        logging.basicConfig(level=logging.DEBUG)

        # Project name and folder name in Project folder
        projName = str(sys.argv[1])
        logging.debug("Setting the projName var to -> "+projName)
        # Is project private or public on GitHub
        visibility = str(sys.argv[2]).lower()
        logging.debug("Setting the visibility var to -> "+visibility)

        # Set visibility on GitHub
        if visibility == 'private':
            visibility = 'true'
        elif visibility == 'public':
            visibility = 'false'
        else:
            logging.error('Set visibility to either "private" or "public"')
            print('ERROR')
            exit()
        logging.debug("visibility set to -> "+visibility)

        folder = create_folder(projName)

        if folder:
            repo = create_repository(projName, visibility)
            if repo == '':
                print('ERROR')
            else:
                print(repo)
                logging.debug(repo[1])
                create_git_project(projName)
        else:
            print('ERROR')


from flask_wtf.form import Form
from wtforms.fields.core import StringField, RadioField
from wtforms.fields.simple import SubmitField
from wtforms import validators

class FinderForm(Form):
    query = StringField('', [validators.Required()])
    query_type = RadioField('query_type',
                            choices=[('title', 'Specific title'),
                                     ('all', 'All books'),
                                     ('isbn', 'ISBN'),
                                     ('author_name', 'Author'),
                                     ('publisher_name', 'Publisher'),
                                     ('book_summary', 'Topics')],
                            default='title'
                            )
    submit = SubmitField('Find book')


acronyms = ['LOL','IDK','SMH','TBH']

acronyms.append('OMG')
acronyms.remove('SMH')
del acronyms[2]

print(acronyms)

if 'LOL' in acronyms:
    print('True')
else:
    print('False')

for acronym in acronyms:
    print(acronym)

expenses = [142,414,444,11,2,77]

total = sum(expenses)
print(f'You spent ${str(total)} at Gucci today')

total = 0

expenses = []

for i in range(7):
    expenses.append(float(input('Enter an expense:')))

total = sum(expenses)
print(f'You spent ${str(total)} at Gucci today')


"""
Analysis of model properties, independent of data.
"""

from __future__ import absolute_import, division, print_function
from mmtbx.validation import atom, residue, validation, dummy_validation
from libtbx import slots_getstate_setstate
from libtbx.test_utils import approx_equal
import sys
from six.moves import zip

class model_statistics(slots_getstate_setstate):
  """
  Atom statistics for the overall model, and various selections within.
  This does not actually contain individual outliers, which are instead held
  in the xray_structure_statistics objects for subsets of the model.
  """
  __slots__ = [
    "all",
    "_macromolecules",
    "_ligands",
    "_water",
    "n_models",
    "n_atoms",
    "n_hydrogens",
    "n_waters",
    "n_polymer",
    "n_protein",
    "n_nuc",
    "ignore_hd",
  ]
  def __init__(self, pdb_hierarchy,
      xray_structure,
      all_chain_proxies=None,
      ignore_hd=True,
      ligand_selection=None):
    for name in self.__slots__ :
      setattr(self, name, None)
    from six import string_types
    if isinstance(ligand_selection, string_types):
      if (all_chain_proxies is not None):
        ligand_selection = all_chain_proxies.selection(ligand_selection)
      else :
        ligand_selection = pdb_hierarchy.atom_selection_cache().selection(
          ligand_selection)
    self.ignore_hd = ignore_hd
    self.n_atoms = xray_structure.scatterers().size()
    self.n_hydrogens = xray_structure.hd_selection().count(True)
    self.n_models = len(pdb_hierarchy.models())
    counts = pdb_hierarchy.overall_counts()
    resnames = counts.resnames
    self.n_waters = resnames.get("HOH", 0) + resnames.get("WAT", 0)
    self.n_polymer = 0
    self.n_nuc = self.n_protein = 0
    hierarchy_tmp = pdb_hierarchy
    # make sure the ligand selection is not counted as part of the protein
    # chains
    if (ligand_selection is not None):
      hierarchy_tmp = pdb_hierarchy.select(~ligand_selection)
    first_model = hierarchy_tmp.models()[0]
    # FIXME not totally confident that this will always work...
    for chain in first_model.chains():
      is_protein = chain.is_protein()
      is_na = False
      chain_type = "other"
      if (not is_protein):
        is_na = chain.is_na()
        chain_type = "nucleic acid"
      else :
        chain_type = "protein"
      residue_groups = chain.residue_groups()
      if (is_protein) or (is_na):
        n_res = len(residue_groups)
        self.n_polymer += n_res
        if (is_protein):
          self.n_protein += n_res
        else :
          self.n_nuc += n_res
    self.all = xray_structure_statistics(
      pdb_hierarchy=pdb_hierarchy,
      xray_structure=xray_structure,
      ignore_hd=ignore_hd)
    if (all_chain_proxies is not None):
      macro_sel = all_chain_proxies.selection("protein or rna or dna")
      water_sel = all_chain_proxies.selection("water")
      if (ligand_selection is None):
        ligand_selection = all_chain_proxies.selection(
          "not (protein or dna or rna or water)")
      # make sure we exclude ligands from the "macromolecule" selection!
      macro_sel &= ~ligand_selection
      if (macro_sel.count(True) > 0):
        self._macromolecules = xray_structure_statistics(
          pdb_hierarchy=pdb_hierarchy.select(macro_sel),
          xray_structure=xray_structure.select(macro_sel),
          ignore_hd=ignore_hd)
      if (water_sel.count(True) > 0):
        self._water = xray_structure_statistics(
          pdb_hierarchy=pdb_hierarchy.select(water_sel),
          xray_structure=xray_structure.select(water_sel),
          ignore_hd=ignore_hd)
    if (ligand_selection is not None) and (ligand_selection.count(True) > 0):
      self._ligands = xray_structure_statistics(
        pdb_hierarchy=pdb_hierarchy.select(ligand_selection),
        xray_structure=xray_structure.select(ligand_selection),
        ignore_hd=ignore_hd)
    # make sure original i_seq is used
    #pdb_hierarchy.atoms().reset_i_seq()

  def show(self, out=sys.stdout, prefix=""):
    print(prefix+"Overall:", file=out)
    self.all.show_summary(out=out, prefix=prefix+"  ")
    self.all.show_bad_occupancy(out=out, prefix=prefix+"  ")
    if (self.ligands) or (self.water):
      for label, props in zip(["Macromolecules", "Ligands", "Waters"],
          [self.macromolecules, self.ligands, self.water]):
        if (props):
          print(prefix+"%s:" % label, file=out)
          props.show_summary(out=out, prefix=prefix+"  ")
    if (self.ignore_hd) and (self.n_hydrogens > 0):
      print(prefix+"(Hydrogen atoms not included in overall counts.)", file=out)

  @property
  def macromolecules(self):
    if (self._macromolecules is None):
      return dummy_validation()
    return self._macromolecules

  @property
  def water(self):
    if (self._water is None):
      return dummy_validation()
    return self._water

  @property
  def ligands(self):
    if (self._ligands is None):
      return dummy_validation()
    return self._ligands

class residue_occupancy(residue):
  __slots__ = residue.__slots__ + ["chain_type", "b_iso"]

  def as_string(self, prefix=""):
    return " %3s%2s%5s (all)  occ=%.2f" % (self.resname, self.chain_id,
      self.resid, self.occupancy)

  def as_table_row_phenix(self):
    return [ self.id_str(), "residue", self.occupancy, self.b_iso ]

class atom_occupancy(atom):
  """
  Container for single-atom occupancy outliers (usually atoms with zero
  occupancy).
  """
  def id_str(self):
    return super(atom_occupancy, self).id_str(ignore_segid=True)

  def as_string(self, prefix=""):
    return "%s %4s   occ=%.2f" % (self.atom_group_id_str(), self.name,
      self.occupancy)

  def as_table_row_phenix(self):
    return [ self.id_str(), "atom", self.occupancy, self.b_iso ]

class residue_bfactor(residue_occupancy):

  def as_string(self, prefix=""):
    return "%s %4s   b_iso=%.2f" % (self.atom_group_id_str(), self.name,
      self.b_iso)

class atom_bfactor(atom_occupancy):
  pass

# FIXME redundant with model_vs_data, but what can I do???
# TODO add validation stuff
class xray_structure_statistics(validation):
  """
  Occupancy and B-factor statistics.
  """
  __slots__ = validation.__slots__ + [
    "n_all",
    "n_atoms",
    "n_non_hd",
    "n_hd",
    "n_aniso",
    "n_aniso_h",
    "n_zero_b",
    "n_zero_occ",
    "n_npd",
    "b_mean",
    "b_min",
    "b_max",
    "o_mean",
    "o_min",
    "o_max",
    "zero_occ",
    "partial_occ",
    "different_occ",
    "bad_adps",
    "b_histogram",
  ]
  gui_list_headers = ["Atom(s)", "Type", "Occupancy", "Isotropic B-factor"]
  gui_formats = ["%s","%s","%.2f", "%.2f"]
  wx_column_widths = [300,100,100,200]
  def __init__(self, pdb_hierarchy, xray_structure, ignore_hd=True,
      collect_outliers=True):
    for name in self.__slots__ :
      setattr(self, name, None)
    validation.__init__(self)
    assert len(xray_structure.scatterers()) != 0
    from cctbx import adptbx
    from scitbx.array_family import flex
    xrs = xray_structure
    self.n_total = xrs.scatterers().size() # always include H/D
    self.results = None
    pdb_atoms = pdb_hierarchy.atoms()
    pdb_atoms.reset_i_seq()
    hd_selection = xrs.hd_selection()
    subtract_hd = True
    self.n_all = hd_selection.size()
    self.n_hd = hd_selection.count(True)
    if (ignore_hd) and (0 < self.n_hd < self.n_all):
      xrs = xrs.select(~hd_selection)
      subtract_hd = False
    u_isos = xrs.extract_u_iso_or_u_equiv()
    occ = xrs.scatterers().extract_occupancies()
    self.n_atoms = xrs.scatterers().size()
    self.n_non_hd = self.n_all - self.n_hd
    self.n_aniso = xrs.use_u_aniso().count(True)
    self.n_aniso_h = (xray_structure.use_u_aniso() & hd_selection).count(True)
    self.n_npd = xrs.is_positive_definite_u().count(False)
    self.n_zero_b = (u_isos == 0).count(True)
    self.n_zero_occ = (occ == 0).count(True)
    u_cutoff_high = sys.maxsize
    u_cutoff_low = 0
    u_non_zero = u_isos.select(u_isos > 0)
    if (len(u_non_zero) > 1):
      mv = flex.mean_and_variance(u_non_zero)
      sigma = mv.unweighted_sample_standard_deviation()
      u_cutoff_high = mv.mean() + (4.0 * sigma)
      u_cutoff_low = mv.mean() - (4.0 * sigma)
    self.b_mean = adptbx.u_as_b(flex.mean(u_isos))
    self.b_min = adptbx.u_as_b(flex.min(u_isos))
    self.b_max = adptbx.u_as_b(flex.max(u_isos))
    self.o_mean = flex.mean(occ)
    self.o_min = flex.min(occ)
    self.o_max = flex.max(occ)
    self.n_outliers = self.n_aniso_h + self.n_npd
    self.zero_occ = []
    self.partial_occ = []
    self.different_occ = []
    self.bad_adps = []
    self.b_histogram = None # TODO
    def is_u_iso_outlier(u):
      return (u < u_cutoff_low) or (u > u_cutoff_high) or (u <= 0)
    # these statistics cover all atoms!
    occupancies = xray_structure.scatterers().extract_occupancies()
    u_isos = xray_structure.extract_u_iso_or_u_equiv()
    collected = flex.bool(occupancies.size(), False)
    if (collect_outliers):
      for i_seq, occ in enumerate(occupancies):
        if (hd_selection[i_seq] and ignore_hd) or collected[i_seq] :
          continue
        pdb_atom = pdb_atoms[i_seq]
        parent = pdb_atom.parent()
        if (occ <= 0):
          group_atoms = parent.atoms()
          labels = pdb_atom.fetch_labels()
          if (len(group_atoms) > 1) and (group_atoms.extract_occ().all_eq(0)):
            i_seqs = group_atoms.extract_i_seq()
            b_mean = adptbx.u_as_b(flex.mean(u_isos.select(i_seqs)))
            outlier = residue_occupancy(
              chain_id=labels.chain_id,
              resseq=labels.resseq,
              icode=labels.icode,
              altloc=labels.altloc,
              resname=labels.resname,
              occupancy=occ,
              outlier=True,
              xyz=group_atoms.extract_xyz().mean(),
              b_iso=b_mean)
            self.zero_occ.append(outlier)
            self.n_outliers += 1
            collected.set_selected(i_seqs, True)
          else :
            assert (pdb_atom.occ == occ), "%s: %s <--> %s" % (pdb_atom.id_str(),
              pdb_atom.occ, occ)
            outlier = atom_occupancy(
              pdb_atom=pdb_atom,
              occupancy=occ,
              b_iso=adptbx.u_as_b(u_isos[i_seq]),
              xyz=pdb_atom.xyz,
              outlier=True)
            self.zero_occ.append(outlier)
            self.n_outliers += 1
        elif is_u_iso_outlier(u_isos[i_seq]):
          # zero displacements will always be recorded on a per-atom basis
          if (u_isos[i_seq] <= 0):
            outlier = atom_bfactor(
              pdb_atom=pdb_atom,
              occupancy=occ,
              b_iso=adptbx.u_as_b(u_isos[i_seq]),
              xyz=pdb_atom.xyz,
              outlier=True)
            self.bad_adps.append(outlier)
            self.n_outliers += 1
          else :
            # if the average displacement for the entire residue falls outside
            # the cutoffs, save as a single residue outlier
            group_atoms = parent.atoms()
            i_seqs = group_atoms.extract_i_seq()
            u_mean = flex.mean(u_isos.select(i_seqs))
            if is_u_iso_outlier(u_mean):
              labels = pdb_atom.fetch_labels()
              outlier = residue_bfactor(
                chain_id=labels.chain_id,
                resseq=labels.resseq,
                icode=labels.icode,
                altloc=labels.altloc,
                resname=labels.resname,
                occupancy=occ,
                outlier=True,
                xyz=group_atoms.extract_xyz().mean(),
                b_iso=adptbx.u_as_b(u_mean))
              self.bad_adps.append(outlier)
              self.n_outliers += 1
              collected.set_selected(i_seqs, True)
            # otherwise, just save this atom
            else :
              outlier = atom_bfactor(
                pdb_atom=pdb_atom,
                occupancy=occ,
                b_iso=adptbx.u_as_b(u_isos[i_seq]),
                xyz=pdb_atom.xyz,
                outlier=True)
              self.bad_adps.append(outlier)
              self.n_outliers += 1

      # analyze occupancies for first model
      model = pdb_hierarchy.models()[0]
      for chain in model.chains():
        residue_groups = chain.residue_groups()
        for residue_group in chain.residue_groups():
          # get unique set of atom names
          atom_names = set()
          for atom in residue_group.atoms():
            atom_names.add(atom.name.strip())

          # check total occupancy for each atom
          for name in atom_names:
            occupancy = 0.0
            atoms = list()
            for atom_group in residue_group.atom_groups():
              atom = atom_group.get_atom(name)
              if (atom is not None):
                occupancy += atom.occ
                atoms.append(atom)

            if ( not approx_equal(occupancy, 1.0, out=None, eps=1.0e-3) ):
              for atom in atoms:
                outlier = atom_occupancy(
                  pdb_atom=atom,
                  occupancy=atom.occ,
                  b_iso=adptbx.u_as_b(atom.b),
                  xyz=atom.xyz,
                  outlier=True)
                self.partial_occ.append(outlier)
                self.n_outliers += 1

          # check that atoms in an atom group have the same occupancy
          for atom_group in residue_group.atom_groups():
            residue_is_okay = True
            base_occupancy = atom_group.atoms()[0].occ
            for atom in atom_group.atoms():
              if (not approx_equal(base_occupancy, atom.occ,
                                   out=None, eps=1.0e-3)):
                labels = atom.fetch_labels()
                i_seqs = atom_group.atoms().extract_i_seq()
                b_mean = adptbx.u_as_b(flex.mean(u_isos.select(i_seqs)))
                outlier = residue_occupancy(
                  chain_id=labels.chain_id,
                  resseq=labels.resseq,
                  icode=labels.icode,
                  altloc=labels.altloc,
                  resname=labels.resname,
                  occupancy=occ,
                  outlier=True,
                  xyz=atom_group.atoms().extract_xyz().mean(),
                  b_iso=b_mean)
                self.different_occ.append(outlier)
                self.n_outliers += 1
                residue_is_okay = False
                break
            if (not residue_is_okay):
              break

  def show_summary(self, out=sys.stdout, prefix=""):
    print(prefix + "Number of atoms = %d  (anisotropic = %d)" % \
      (self.n_atoms, self.n_aniso), file=out)
    print(prefix + "B_iso: mean = %5.1f  max = %5.1f  min = %5.1f" % \
      (self.b_mean, self.b_max, self.b_min), file=out)
    if (self.n_aniso_h > 0):
      print(prefix + "  warning: %d anisotropic hydrogen atoms" % \
        self.n_aniso_h, file=out)
    if (self.o_min != 1.0):
      print(prefix + \
        "Occupancy: mean = %4.2f  max = %4.2f  min = %4.2f" % \
        (self.o_mean, self.o_max, self.o_min), file=out)
      if (self.n_zero_occ > 0):
        print(prefix + "  warning: %d atoms with zero occupancy" % \
          self.n_zero_occ, file=out)
    if (self.n_outliers > 0):
      print(prefix + \
        "%d total B-factor or occupancy problem(s) detected" % \
        self.n_outliers, file=out)

  def show_bad_occupancy(self, out=sys.stdout, prefix=""):
    if (len(self.zero_occ) > 0):
      print(prefix + "Atoms or residues with zero occupancy:", file=out)
      for outlier in self.zero_occ :
        print(prefix + str(outlier), file=out)

  def show_bfactors(self, out=sys.stdout, prefix=""):
    print(prefix + "B_iso: mean = %5.1f  max = %5.1f  min = %5.1f" % \
      (self.b_mean, self.b_max, self.b_min), file=out)

  def iter_results(self, property_type=None, outliers_only=True):
    if (property_type is None):
      outliers = self.zero_occ + self.partial_occ + self.different_occ +\
                 self.bad_adps
    elif (property_type == "occupancy"):
      outliers = self.zero_occ + self.partial_occ + self.different_occ
    elif (property_type == "b_factor"):
      outliers = self.bad_adps
    else :
      raise RuntimeError("Unknown property type '%s'" % property_type)
    for result in outliers :
      if (result.is_outlier()) or (not outliers_only):
        yield result

  def as_gui_table_data(self, property_type=None, outliers_only=True,
      include_zoom=False):
    table = []
    for result in self.iter_results(property_type=property_type,
        outliers_only=outliers_only):
      extra = []
      if (include_zoom):
        extra = result.zoom_info()
      row = result.as_table_row_phenix()
      assert (len(row) == len(self.gui_list_headers) == len(self.gui_formats))
      table.append(row + extra)
    return table


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

import time
import requests
import json
import os
CORPID = ""
CORPSECRET = ""
AGENTID = ""
TOUSER = ""
try:
    TOUSER = os.environ['TOUSER']  # 接收者用户名,多个用户用|分割
    CORPID = os.environ['CORPID']  # 企业ID，在管理后台获取
    CORPSECRET = os.environ['CORPSECRET']  # 自建应用的Secret，每个自建应用里都有单独的secret
    AGENTID = os.environ['AGENTID']  # 应用ID，在后台应用中获取
except :
    pass

def get_access_token():
    url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken'
    values = {'corpid': CORPID,
              'corpsecret': CORPSECRET,
              }
    try:
        req = requests.post(url, params=values)
    except :
        return None
    data = json.loads(req.text)
    return data["access_token"]

def send_data(message):
    try:
        send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + get_access_token()
        send_values = {
            "touser": TOUSER,
            "msgtype": "text",
            "agentid": AGENTID,
            "text": {
                "content": str(message)
            },
            "safe": "0"
        }
        send_msges = (bytes(json.dumps(send_values), 'utf-8'))
        respone = requests.post(send_url, send_msges)
        respone = respone.json()  # 当返回的数据是json串的时候直接用.json即可将respone转换成字典
        return respone["errmsg"]
    except :
        pass

if __name__ == '__main__':
    testms = "test"
    send_data(testms)


#Symmetric Difference

M=int(input())
x=list(map(int,input().split()[:M]))
N=int(input())
y=list(map(int,input().split()[:N]))

x = set(x)
y = set(y)

c = x.difference(y)
d = y.difference(x)

result = list(c.union(d))

for element in sorted(result):
    print(element)

'''
Input (stdin)
4
2 4 5 9
4
2 4 11 12
Your Output (stdout)
5
9
11
12
Expected Output
5
9
11
12
'''


# Humber flood embankment analysis

# A suite of shapefile data for understanding spatial distribution of available LIDAR and Geophysical
# survey-derived geotechnical data for engineered flood defence embankments on the Humber estuary, England.

import os
import geopandas as gpd
import matplotlib.pyplot as plt
from cartopy.feature import ShapelyFeature
import cartopy.crs as ccrs
import matplotlib.patches as mpatches
import matplotlib.lines as mlines
# these are modules that require importing

# generates a legend to be populated by the datesets later;
# for more info see https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html
def generate_handles(labels, colors, edge='k', alpha=1):
    lc = len(colors)
    handles = []
    for i in range(len(labels)):
        handles.append(mpatches.Rectangle((0, 0), 1, 1, facecolor=colors[i % lc], edgecolor=edge, alpha=alpha))
    return handles

# set up the scale bar in preparation for finalised map, based on scale of Humber estuary, 20km fits best
# for for info see https://stackoverflow.com/q/32333870 and also https://stackoverflow.com/a/35705477
def scale_bar(ax, location=(0.92, 0.95)):
    x0, x1, y0, y1 = ax.get_extent()
    sbx = x0 + (x1 - x0) * location[0]
    sby = y0 + (y1 - y0) * location[1]

    ax.plot([sbx, sbx - 20000], [sby, sby], color='k', linewidth=9, transform=ax.projection)
    ax.plot([sbx, sbx - 10000], [sby, sby], color='k', linewidth=6, transform=ax.projection)
    ax.plot([sbx-10000, sbx - 20000], [sby, sby], color='w', linewidth=6, transform=ax.projection)

    ax.text(sbx, sby-4500, '20 km', transform=ax.projection, fontsize=10)
    ax.text(sbx-12500, sby-4500, '10 km', transform=ax.projection, fontsize=10)
    ax.text(sbx-24500, sby-4500, '0 km', transform=ax.projection, fontsize=10)

    # open Flood Areas polygon shapefile as this will be the basemap for subsequent data;
    # note that this and subsequent shapefiles are loaded using Geopandas, which associates each with a GeoDataFrame;
    # GeoDataFrame - tabular data structure, adds 'geometry' column to the shaoefile attribute table.
    areas = gpd.read_file('HSCR_Flood_Areas/HSCR_FloodAreas_2080406.shp')

    # see a subset of the first 5 lines, the key column is FloodArea_ and basemap will be rendered on this basis;
    # note the additional 'geometry' column, as this is a GeoDataFrame.
    areas.head(5)

    # open flood embankment network polylines shapefile; contains all the earth flood defence embankments around the Humber
    defences = gpd.read_file('Flood_embankment_network/Embankment_alignment_Humber_primary.shp')

    # open low sections polyline shapefile; contains LIDAR-derived data of where flood embankments are lower in height
    # than adjacent sections and could present a flood risk from overtopping during storm events when water levels are high
    Low_sections = gpd.read_file('LIDAR_derived_data/Embankment_low_sections_defects.shp')

    # open steep slopes polygon shapefile; contains LIDAR-derived data of where flood embankments slopes, either front (facing the water) or rear (facing the land),
    # are steeper than the standard angle of repose and could theoretically affect the long-term stability of the embankments
    Steep_slopes = gpd.read_file('LIDAR_derived_data/Embankment_steep_slope_anomalies.shp')

    # open palaeochannels point data shapefile; contains LIDAR-derived data of where infilled former channels, either natural
    # or engineered are situated directly below earth embankments and may theoretically affect the structural stability
    Palaeochannels = gpd.read_file('LIDAR_derived_data/Palaeochannel_anomalies_intersect_embank.shp')

    # open geophysical survey polyline shapefile; contains interpreted data from DEMP (Dipole Electromagnetic Profiling)
    # as to the material composition of surveyed flood embankments, which provide geotechnical context to assessments
    Geophysical_survey_bank_materials = gpd.read_file(
        'Geophysical_survey_data_material_composition/Geophysical_survey_embankment_materials.shp')

    # now the key datasets are opened, comparative analysis can be started; first on the defence, see subset of columns, rows
    # in the GeoDataFrame.
    defences.head(5)

    # to establish the linear length of earth embankment flood defences on the Humber estuary and main tidal tributary
    # rivers, the 'Shape_Leng' column is totalled up in metres and converted to kilometres (divide by 1000).
    defences['Shape_Leng'].sum() / 1000

    # the next dataset to be compared is the low sections; see subset of the data and note again a 'Shape_Leng' column
    Low_sections.head(5)

    # sum and convert to km
    Low_sections['Shape_Leng'].sum() / 1000

    # find low sections linear length as a percentage of defences to understand the scale of this type of this issue.
    # output should be 1.5% rounded up, so an issue which only affects a tiny proportion of the embankments.
    Low_sections['Shape_Leng'].sum() / defences['Shape_Leng'].sum() * 100

    # Steep slopes is a polygonal dataset; in this instance Shape_Leng refers to the perimeter of each polygon in the dataset,
    # rather than the linear length of embankment which is affected; Shape_Area does not relate to linear length either.
    Steep_slopes.head(5)

    # Alternative analysis can be carried out on how many of these occurrences are present.
    Steep_slopes['Face'].count()

    # There are over 4000 instances, more context can be derived from understanding which face (slope) of the embankments
    # are affected, the subset of the GeoDataframe above just indicated 'front' but a check can be carried out to
    # establish whether rear slopes are also listed.
    type_Steep_slopes = list(Steep_slopes.Face.unique())
    print('Name of unique features: {}'.format(type_Steep_slopes))

    # Calculate how many of the 4029 are affecting the front slope/face
    Steep_slopes[Steep_slopes['Face'] == 'Front'].count()

    # Calculate how many are affecting the rear slope/face
    Steep_slopes[Steep_slopes['Face'] == 'Rear'].count()

    # Calculate the instances of rear slope/face as a percentage of the total instance and by deduction,
    # the remaining percentage of front slope: 74.3 % rear (to 1 d.p) and 25.7 % front.
    2995 / 4029 * 100

    # See a subset of the Palaeochannels point data; the key column for further analysis is 'Class'.
    Palaeochannels.head(5)

    # Given the data are points, linear length calculation is not applicable; instead calculate instances.
    Palaeochannels['Class'].count()

    # 53 palaeochannels are identified in the data; define how many descriptive types there are.
    num_Palaeochannels = len(Palaeochannels.channel.unique())
    print('Number of unique features: {}'.format(num_Palaeochannels))

    # List the names of these 2 unique features.
    type_Palaeochannels = list(Palaeochannels.channel.unique())
    print('Name of unique features: {}'.format(type_Palaeochannels))

    # Calculate how many of the overall 53 are classed as 'depression'
    # 'depression' means a palaeochannel is lower in elevation than the surrounding land, as identified in LIDAR analysis.
    Palaeochannels.loc[Palaeochannels['channel'] == 'Depression'].count()

    # Calculate 49 depressions as a % of total 53 palaeochannels; answer is 92.5% (1 d.p), therefore 'extrusions'
    # where a palaeochannel is higher in elevation than the surrounding land constitute 7.5% of the total.
    49 / 53 * 100

    # Final data to analyse are the geophysical survey results; note there are a significant number of columns (27).
    Geophysical_survey_bank_materials.head(5)

    # List the column headings to aid appreciation of what data are included.
    Geophysical_survey_bank_materials.columns

    # Now establish the number of features i.e. the rows.
    rows, cols = Geophysical_survey_bank_materials.shape
    print('Number of features: {}'.format(rows))

    # Calculate the linear distance of survey conducted, using 'Tot_dist_m' which accurately reflects the actual length of
    # survey undertaken, rather than 'Shape_leng', which is a measure of the polyline lengths. Convert to km.
    Geophysical_survey_bank_materials['Tot_dist_m'].sum() / 1000

    # As these data are linear, a percentage calculation can be made in respect to the overall lemgth of earth embankments;
    # 37.2 % (to 1 d.p) has been surveyed, leaving 62.3 % available for future survey.
    Geophysical_survey_bank_materials['Tot_dist_m'].sum() / defences['Shape_Leng'].sum() * 100

    # The geophysical results have been interpreted in respect of the types of material within the embankments;
    # Create a list of all these material types;
    # Material types are based on four standard material types - clay, silt, sand, gravel. Where any of these materials
    # are considered the dominant constiuents, the name is shown in upper case, with lesser constituents in lower case.
    type_materials = list(Geophysical_survey_bank_materials.Material.unique())
    print('Name of unique features: {}'.format(type_materials))

    # Flood embankments should optimally be constructed from finer-grained, cohesive materials - clays and silts;
    # Where coarser-grained, less cohesive (and therefore more permeable) materials predominate there is theoretically
    # a greater risk of seepage of water through an embankment body and possibly also increased settlement of the crest
    # height as there are moe micro voids in coarser-grained materials;
    # This analysis, by linear length of material types will give a valuable overview.
    Geophysical_survey_bank_materials.groupby(['Material'])['Tot_dist_m'].sum() / 1000

    # The inherent saturation levels of the flood embankments is also a key factor in understanding embankment effectivness;
    # 'High' saturation indicates waterlogging,which is sub-optimal, as is 'Low' , which indicates excessive permeability;
    # By definition 'Normal' is optimal and from this analysis is the dominant Saturation type - 85 of 125 km.
    Geophysical_survey_bank_materials.groupby(['Saturation'])['Tot_dist_m'].sum() / 1000

    # To understand the spatial coverage of geophysical survey, data can be grouped by Hydraulic Units, into which the
    # Humber estuary interest area is sub-divided based on it's hydraulic functioning in times of flood.
    # Calculate and convert to km.
    Geophysical_survey_bank_materials.groupby(['HS_Hyd_Uni'])['Tot_dist_m'].sum() / 1000

    # Calculate the number of Hydraulic Units in which geophysical survey was carried out.
    num_Units_surveyed = len(Geophysical_survey_bank_materials.HS_Hyd_Uni.unique())
    print('Number of unique features: {}'.format(num_Units_surveyed))

    # Create the full list of Hydraulic Units on the Humber, based on the Areas GeoDataFrame.
    full_list_Units = list(areas.UNIT.unique())
    print('Name of unique features: {}'.format(full_list_Units))

    # Count the total number of Hydraulic Units
    # There are 15, therefore geophysical survey has been carried out in 10 of 15.
    num_Units = len(areas.UNIT.unique())
    print('Number of unique features: {}'.format(num_Units))

    # Create map displaying above data

    myFig = plt.figure(figsize=(16, 16))  # creates figure with definied dimensions in inches

    myCRS = ccrs.OSGB()  # Set the CartoPy Coordinate reference system to the Ordnance Survey Great Britain to ensure
    # compatibility with all the datasets.

    ax = plt.axes(projection=myCRS)  # create axes using the OSGB projection.

    # Add the Areas basemap, edged in light grey and with a white face colour.
    areas_feature = ShapelyFeature(areas['geometry'], myCRS, edgecolor='lightgray', facecolor='w')
    xmin, ymin, xmax, ymax = areas.total_bounds
    # Add this feature to the map
    ax.add_feature(areas_feature)

    # set the zoom extent to match the basemap shapefile extent with a 10km buffer on the x and y axes
    ax.set_extent([xmin - 10000, xmax + 10000, ymin - 10000, ymax + 10000], crs=myCRS)

    myFig  # draw the updated map

    # To colour in the Areas basemap, the number of colours required will be the total Flood Area features.
    num_areas = len(areas.FloodArea_.unique())
    print('Number of unique features: {}'.format(num_areas))

    # choose 35 colours from here https://matplotlib.org/stable/gallery/color/named_colors.html
    areas_colors = ['sandybrown', 'bisque', 'tan', 'moccasin', 'floralwhite', 'gold', 'darkkhaki',
                    'lightgoldenrodyellow', 'olivedrab', 'chartreuse', 'palegreen', 'mediumspringgreen',
                    'lightseagreen', 'paleturquoise', 'darkturquoise', 'deepskyblue', 'mediumpurple', 'darkorchid',
                    'plum', 'm', 'palevioletred', 'lightgray', 'lightcoral', 'mistyrose', 'peachpuff', 'navajowhite',
                    'orange', 'lemonchiffon', 'yellowgreen', 'c', 'skyblue', 'violet', 'fuchsia', 'indianred', 'salmon',
                    'y']

    # list and sort the areas
    area_numbers = list(areas.FloodArea_.unique())
    area_numbers.sort()

    # set more parameters as arguments, including the geometry (from the GeoDataFrame), edge colour, line width
    # and transparency (alpha - on a scale 0 to 1); face colour is set to the listed colours above.
    for ii, name in enumerate(area_numbers):
        feat = ShapelyFeature(areas.loc[areas['FloodArea_'] == name, 'geometry'],
                              myCRS,
                              edgecolor='w',
                              facecolor=areas_colors[ii],
                              linewidth=0.1,
                              alpha=0.25)
        ax.add_feature(feat)  # add features to map

    myFig  # draw updated map

    # Add defences in the same way
    defences = ShapelyFeature(defences['geometry'],
                              myCRS,
                              edgecolor='b',  # blue
                              linewidth=2.0,
                              alpha=0.25
                              )
    ax.add_feature(defences)  # add features to the map

    myFig  # draw updated map

    # Add geophysical survey data
    Geophysical_survey_bank_materials = ShapelyFeature(Geophysical_survey_bank_materials['geometry'],
                                                       myCRS,
                                                       edgecolor='lime',
                                                       linewidth=1.0,
                                                       )
    ax.add_feature(Geophysical_survey_bank_materials)

    myFig

    # Add low sections data
    Low_sections = ShapelyFeature(Low_sections['geometry'],
                                  myCRS,
                                  edgecolor='darkorange',
                                  linewidth=1.0)
    ax.add_feature(Low_sections)

    myFig

    # Add Steep slopes, note as these data are polygons, the facecolor needs to be set
    Steep_slopes = ShapelyFeature(Steep_slopes['geometry'],
                                  myCRS,
                                  edgecolor='k',  # black
                                  facecolor='k',  # due to scale of map, a separate colour will not be discernible
                                  linewidth=0.1)
    ax.add_feature(Steep_slopes)

    myFig

    # Palaeochannels are point data so do not need the ShapelyFeature class from cartopy.feature, ax.plot can be used directly.

    Palaeochannels_handle = ax.plot(Palaeochannels.geometry.x, Palaeochannels.geometry.y, 'o', color='0.7', ms=3,
                                    transform=myCRS)
    # 'o' is circle, courtesy of list here https://stackoverflow.com/questions/8409095/set-markers-for-individual-points-on-a-line
    # colour is String representation of float value in closed interval [0, 1] for grayscale values, os 0.7 is light grey
    # see https://matplotlib.org/stable/tutorials/colors/colors.html

    myFig

    # Use generate-handles function to add labels and colours. Note - Areas is omitted for visual clarity, given there
    # are 35 areas.

    defences_handle = generate_handles(['Flood embankments'], ['b'], alpha=0.25)

    Low_sections_handle = generate_handles(['Low sections of embankments'], ['darkorange'])

    Steep_slopes_handle = generate_handles(['Steep embankment slopes'], ['k'])

    Palaeochannels_handle = generate_handles(['Palaeochannel intersections'], ['chocolate'])

    Geophysical_survey_bank_materials_handle = generate_handles(['Geophysical survey extents'], ['lime'])

    # generate legend content and parameters
    # for more info see https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html

    handles = defences_handle + Low_sections_handle + Steep_slopes_handle + Palaeochannels_handle + Geophysical_survey_bank_materials_handle  # use '+' to concatenate (combine) lists
    labels = ['Flood embankments', 'Low sections of embankments', 'Steep embankment slopes',
              'Palaeochannel intersections', 'Geophysical survey extents']

    leg = ax.legend(handles, labels, title='Legend', title_fontsize=14,
                    fontsize=12, loc='upper left', frameon=True, framealpha=1)

    myFig

    # now add scale bar which was previously specified
    scale_bar(ax)

    myFig

    # save the map to the current folder in png format; also specify no border (bbox) and resolution in dpi (dots per inch).
    myFig.savefig('Humber_flood_embankment_data.png', bbox_inches='tight', dpi=800)


# Online Python compiler (interpreter) to run Python online.
# Write Python 3 code in this online editor and run it.
# Get started with interactive Python!
# Supports Python Modules: builtins, math,pandas, scipy
# matplotlib.pyplot, numpy, operator, processing, pygal, random,
# re, string, time, turtle, urllib.request
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import scipy as sp

td = pd.read_csv(r'covid_19_india.csv');
newtd = td.loc[:,~td.columns.isin(['Sno','Date','Time','State/UnionTerritory'])];
#print(newtd.mean);
#print(newtd.median);
#Q1 = pd.percentile(newtd,25);
#Q2 = pd.percentile(newtd,50);
#Q3 = pd.percentile(newtd,75);
#Q4 = pd.percentile(newtd,95);
#print(Q1);
#print(Q3);
a = (td.describe([.25,.50,.75,.95,.99]));
print(a.loc['25%']['Confirmed'])
iqr = (a.loc['75%']['Confirmed'] - a.loc['25%']['Confirmed'])

#apply condition on confirmed column where the values are outliers and then display those values in a separate column named as Outlier
highOutlier = (td.loc[(td['Confirmed'] > (a.loc['75%']['Confirmed'] + iqr))]);
print(highOutlier)
print(highOutlier['State/UnionTerritory'].unique())
#b.rename(columns={"Confirmed":"Outlier"})
#print(a(['Confirmed'] > (a.loc['75%']['Confirmed'] + iqr)]))
#print(td.mean(1));
perMillionFig =  10000000

MergedData = statesData.merge(agg,left_on='State',right_on='State/UnionTerritory')
print(MergedData);
MergedData['PerMillion'] = (MergedData['Confirmed']/MergedData['Area (per sq km)'])*perMillionFig;
print(MergedData['PerMillion']);

print(indiv.columns);
a = indiv['nationality'].unique();
print(type(a));
b = (np.isin(["India","INDIAN"],a));
print (b);

# condition = a[a.isin(["India","INDIAN"])];
# print(indiv[condition]);

#Count the number of males and females.
numOfMalesAndFemales = indiv['gender'].value_counts();
print(numOfMalesAndFemales);

a = indiv['detected_state'].groupby(indiv['gender'].value_counts()).count();
a = indiv['gender'].groupby(indiv['detected_state'].value_counts()).count();
a= indiv.groupby(['detected_state','gender']).size();
print(a);
at = (td['Cured'].groupby(td['State/UnionTerritory'])).sum();
print((at));

# State with maximum recoveries.
StateWithMaxRecoveries = at.idxmax();
print(StateWithMaxRecoveries);

at1 = (indiv['gender'].groupby(indiv['detected_state'])).value_counts();
print(at1);

# a = [[1,2],[3,4],[5,6],[7,8]];
# b = pd.DataFrame((a),index=['a1','a2','a3','n4'],columns = ['c1','c2']);
# print(b);
# print(b.a1)
# print(b[['c1']])
# print(b[['c1']].filter(like='a')).head();
# print(b[b[]]);
d = td.groupby(['Date','Time','Confirmed']).size();
e = td['Confirmed'].groupby(td['Date']).sum();
print(e );


"""
Given a column title as appear in an Excel sheet, return its corresponding column number.

For example:
    A -> 1
    B -> 2
    C -> 3
    ...
    Z -> 26
    AA -> 27
    AB -> 28
    ...
Example 1:
Input: "ZY"
Output: 701
"""

def titleToNumber(s):
    ans = 0
    for c in s:
        ans = (ans * 26) + ord(c)-64

    return ans

s = "AAA"
print(titleToNumber(s))


# %% imports
from abc import abstractmethod
import datetime as dt
import numpy as np
import os
import pandas as pd
import sys
from collections import OrderedDict

from nba_pbp_analysis.data.cf import MASTER_COLUMN_MAP_FILEPATH, MASTER_PLAYER_ID_MAP_FILEPATH

class PBPCleaner:

    # region setup
    def __init__(self, **kwargs):
        self.raw_to_clean_filepath_map = self._build_raw_clean_filepath_map(**kwargs)
        self.player_map = self._build_player_map()
        self.column_map = self._build_column_map()

    @staticmethod
    @abstractmethod
    def _build_raw_clean_filepath_map(raw_dir: str, clean_dir: str, generic_filename: str = "clean_nba_pbp",
                                      output_filetype: str = ".csv") -> OrderedDict:
        raise NotImplementedError

    def _build_player_map(self):
        df_player_map = pd.read_csv(MASTER_PLAYER_ID_MAP_FILEPATH, index_col=0)
        return df_player_map.set_index("PERSON_ID")["DISPLAY_FIRST_LAST"].to_dict()

    def _build_column_map(self):
        df_column_map = pd.read_csv(MASTER_COLUMN_MAP_FILEPATH)
        df_column_map.loc[:, ['col_BDB', 'col_834']] = df_column_map.loc[:, ['col_BDB', 'col_834']].replace("[X]",
                                                                                np.nan)
        df_column_map.loc[df_column_map['col_834'] == '[map player id]', 'col_834'] = df_column_map.loc[
            df_column_map['col_834'] == '[map player id]', 'master_col']
        return df_column_map

    # endregion

    # region cleaning
    def clean_raw_files(self, input_filetype: str = ".csv", output_filetype: str = ".csv",
                        overwrite: bool = True) -> None:
        for (raw_filepath, clean_filepath) in self.raw_to_clean_filepath_map.items():
            if (overwrite is not True) and (os.path.exists(clean_filepath)):
                print("skipping overwrite; file exists: {}".format(clean_filepath))
            else:
                self._read_clean_save(player_map=self.player_map, column_map=self.column_map, raw_filepath=raw_filepath,
                                      input_filetype=input_filetype, clean_filepath=clean_filepath,
                                      output_filetype=output_filetype)

    @classmethod
    def _read_clean_save(cls, player_map, column_map, raw_filepath: str, clean_filepath: str,
                         input_filetype: str = ".csv", output_filetype: str = ".csv"):
        # this is a function so that the df gets removed from the cache between loops for better performance
        print("starting cleaning for file {}...".format(raw_filepath))
        df = cls._read_file_to_df(filepath=raw_filepath, filetype=input_filetype)
        df = cls._clean_data(df=df, player_map=player_map, column_map=column_map)
        cls._save_data_to_file(df, filepath=clean_filepath, filetype=output_filetype)

    @staticmethod
    def _read_file_to_df(filepath: str, filetype: str = ".csv") -> pd.DataFrame:
        """read file to dataframe. method can be overridden to specify index, chunking, etc."""
        if filetype == ".csv":
            return pd.read_csv(filepath, index_col=0)
        elif filetype == ".pkl":
            return pd.read_pickle(filepath)
        else:
            raise NotImplementedError

    # region cleaning_functions
    @classmethod
    def _clean_data(cls, df: pd.DataFrame, player_map, column_map) -> pd.DataFrame:
        df.reset_index(drop=True, inplace=True)
        df = cls._parse_src_errors(df)
        df = cls._map_player_ids_to_names(df, player_map=player_map)
        df.columns = cls._map_src_columns_to_master(src_columns=df.columns, column_map=column_map)
        df = cls._retype_data(df)
        df = cls._calc_derived_data(df)
        return df

    @staticmethod
    @abstractmethod
    def _parse_src_errors(df: pd.DataFrame) -> pd.DataFrame:
        """map source error vals to master error vals"""
        raise NotImplementedError

    @staticmethod
    @abstractmethod
    def _map_player_ids_to_names(df: pd.DataFrame, player_map) -> pd.DataFrame:
        """map player ids to player names"""
        raise NotImplementedError

    @staticmethod
    @abstractmethod
    def _map_src_columns_to_master(src_columns, column_map):
        """rename dataframe columns (map source data columns to master columns)"""
        raise NotImplementedError

    @staticmethod
    @abstractmethod
    def _retype_data(df):
        """parse and re-type data as necessary (to match master spec's)"""
        raise NotImplementedError

    @classmethod
    def _calc_derived_data(cls, df: pd.DataFrame) -> pd.DataFrame:
        return df

    # endregion

    @staticmethod
    def _save_data_to_file(df: pd.DataFrame, filepath: str, filetype: str = ".csv") -> None:
        if filetype == ".csv":
            df.to_csv(filepath)
            print("saved df ({}) to {}".format(df.shape, filepath))
        elif filetype == ".pkl":
            df.to_pickle(filepath)
            print("saved df ({}) to {}".format(df.shape, filepath))
        else:
            raise NotImplementedError
    # endregion


from flask import render_template
from hello import app

# Create routes for our app
@app.route('/')
def index():
    user_info = {
        'username': 'sbabu',
        'email': 'loudnclear@gyoke.com'
    }
    food = ['fries', 'bananasplit', 'warheads', 'greeneggs', 'ham', 'babycarrots', 'liver']
    return render_template('index.html', user=user_info, food=food)

@app.route('/posts')
def posts():
    return 'Hi this is Posts!'


def menu():
    print("\t\t1 - Cargar paciente")
    print("\t\t2 - Buscar paciente por nombre")
    print("\t\t3 - Listar pacientes")
    print("\t\t4 - Salir")
    return int(input("Ingresa tu seleccion -> "))

def welcome():
    print("*************************")
    print("* Mensaje de bienvenida *")
    print("*************************")

def loadData(pacientes=list()):
    p = dict()
    p["nombre"]=input("Ingrese el nombre -> ")
    p["edad"]=input("Ingrese la edad -> ")
    p["peso"]=input("Ingrese el peso -> ")
    pacientes.append(p)

def findXName(pacientes=list(), name=str()):
    for paciente in pacientes:
        if(paciente['nombre']==name):
            print(paciente)

def printData(pacientes=list()):
    for paciente in pacientes:
        print(paciente)

running = True
pacientes = list()
welcome()
while(running):

    selection = menu()
    if selection == 1:
        loadData(pacientes)
        print(pacientes)
    elif selection == 2:
        name = input("Ingrese el nombre del paciente -> ")
        findXName(pacientes, name)
    elif selection == 3:
        printData(pacientes)
    elif selection == 4:
        running = False
    else:
        print("******** Valor Inválido ********")


from collections import defaultdict as dfd
def solution(A, K):
    l = len(A)
    book = dfd(int)
    book[A[0]] += 1
    big = 1
    left, right = 0, 0
    while right < l-1:
        right += 1
        book[A[right]] += 1
        big = max(big, book[A[right]])
        if right-left+1-big > K: # overstride
            book[A[left]] -= 1
            left += 1
    return right - left + 1