from __future__ import unicode_literals

from django.test import TestCase

from nose.plugins.attrib import attr

from candidates.models import PersonExtra, SiteSettings
from candidates.tests import factories
from candidates.tests.uk_examples import UK2015ExamplesMixin

@attr(country='uk')
class CSVTests(UK2015ExamplesMixin, TestCase):

    def setUp(self):
        super(CSVTests, self).setUp()
        # The second person's name (and party name) have diacritics in
        # them to test handling of Unicode when outputting to CSV.
        self.gb_person_extra = factories.PersonExtraFactory.create(
            base__id=2009,
            base__name='Tessa Jowell',
            base__honorific_suffix='DBE',
            base__honorific_prefix='Ms',
            base__email='jowell@example.com',
            base__gender='female',
        )
        camberwell_area_extra = self.camberwell_post_extra.base.area.extra
        camberwell_area_extra.base.other_identifiers.create(
            scheme='mapit-area-url',
            identifier='http://mapit.mysociety.org/area/65913',
        )
        camberwell_area_extra.base.other_identifiers.create(
            scheme='gss',
            identifier='E14000615',
        )
        dulwich_area_extra = self.dulwich_post_extra.base.area.extra
        dulwich_area_extra.base.other_identifiers.create(
            scheme='mapit-area-url',
            identifier='http://mapit.mysociety.org/area/65808',
        )
        dulwich_area_extra.base.other_identifiers.create(
            scheme='gss',
            identifier='E14000673',
        )
        factories.CandidacyExtraFactory.create(
            election=self.election,
            base__person=self.gb_person_extra.base,
            base__post=self.camberwell_post_extra.base,
            base__on_behalf_of=self.labour_party_extra.base
        )
        factories.CandidacyExtraFactory.create(
            election=self.earlier_election,
            base__person=self.gb_person_extra.base,
            base__post=self.dulwich_post_extra.base,
            base__on_behalf_of=self.labour_party_extra.base
        )
        self.gb_person_extra.base.identifiers.create(
            identifier='uk.org.publicwhip/person/10326',
            scheme='uk.org.publicwhip',
        )
        self.labour_party_extra.base.identifiers.create(
            identifier='PP53',
            scheme='electoral-commission',
        )

    def test_as_list_single_dict(self):
        person_extra = PersonExtra.objects \
            .joins_for_csv_output().get(pk=self.gb_person_extra.id)
        # So that we predictably do need to perform the settings query
        # below, make sure it isn't cached:
        SiteSettings.objects.clear_cache()
        # After the select_related and prefetch_related calls
        # PersonExtra there should two more queries - that to
        # find the complex fields mapping and another for settings:
        with self.assertNumQueries(2):
            person_dict_list = person_extra.as_list_of_dicts(self.election)
        self.assertEqual(len(person_dict_list), 1)
        person_dict = person_dict_list[0]
        self.assertEqual(len(person_dict), 35)
        self.assertEqual(person_dict['id'], 2009)

        # Test the extra CSV fields:
        self.assertEqual(person_dict['gss_code'], 'E14000615')
        self.assertEqual(person_dict['parlparse_id'], 'uk.org.publicwhip/person/10326')
        self.assertEqual(person_dict['theyworkforyou_url'], 'http://www.theyworkforyou.com/mp/10326')
        self.assertEqual(person_dict['party_ec_id'], 'PP53')


'''
******* 문제 푼 후 느낀 것 *********
진짜 개 ㅂㄷㅂㄷ하다.
파이썬은 속도가 느려서 dfs 또는 bfs를 이용해서 풀게되면 시간초과가 발생한다..
따라서 C 언어와 같이 빠른 언어를 사용하거나, DP 를 이용하여 풀어야한다.

그런데 DP 로 푸는 방법은 감조차 오지 않는다...
'''
import sys
from collections import deque
input = sys.stdin.readline

N = int(input())

house_map = []
for _ in range(N):
    house_map.append(list(map(int,input().split())))

def move(start, end):
    global house_map
    global N
    (start_x, start_y) = start
    (end_x, end_y, position_type) = end
    # 가로 0, 세로 1, 대각 2
    return_list = []

    if position_type == 0:
        if end_y + 1 < N and house_map[end_x][end_y+1] == 0 :
            return_list.append((end_x, end_y+1, 0))

        if end_y + 1 < N and end_x + 1 < N:
            if house_map[end_x][end_y+1] == 0 and house_map[end_x+1][end_y] == 0 and house_map[end_x+1][end_y+1] == 0:
                return_list.append((end_x+1, end_y+1, 2))
    elif position_type == 1:
        if end_x + 1 < N and house_map[end_x+1][end_y] == 0 :
            return_list.append((end_x+1, end_y, 1))

        if end_y + 1 < N and end_x + 1 < N:
            if house_map[end_x][end_y+1] == 0 and house_map[end_x+1][end_y] == 0 and house_map[end_x+1][end_y+1] == 0:
                return_list.append((end_x+1, end_y+1, 2))
    else:
        if end_y + 1 < N and house_map[end_x][end_y+1] == 0 :
            return_list.append((end_x, end_y+1, 0))

        if end_x + 1 < N and house_map[end_x+1][end_y] == 0 :
            return_list.append((end_x+1, end_y, 1))

        if end_y + 1 < N and end_x + 1 < N:
            if house_map[end_x][end_y+1] == 0 and house_map[end_x+1][end_y] == 0 and house_map[end_x+1][end_y+1] == 0:
                return_list.append((end_x+1, end_y+1, 2))
    return return_list

def dfs(start, end) :
    global count
    if end[0] == N -1 and end[1] == N - 1:
        count += 1
        return
    else :
        result = move(start, end)
        for item in result :
            dfs((end[0], end[1]), (item[0], item[1], item[2]))
count = 0
dfs((0,0), (0,1,0))
print(count)

'''
queue = deque()
queue.append(((0,0), (0,1)))
count = 0

if house_map[N-1][N-1] == 1 :
    print(count)
else :
    while(queue):
        (start, end) = queue.popleft()
        result = move(start, end)
        for item in result :
            start = end
            new_end = item

            (end_x, end_y) = new_end
            if end_x == N-1 and end_y == N-1:
                count += 1
            else :
                queue.append((start, new_end))

    print(count)
'''


import os
import pathlib
import logging
from rest_framework import serializers

from base.serializer import ICBaseModelSerializer, ICBaseSerializer
from base.utils.format import format_completed_process
from website.applications.app_factory import AppFactory
from website.models import WebsiteModel
from website.models.utils import get_section, insert_section, update_nginx_server_name

class SSLConfigSerializer(ICBaseSerializer):
    class CertbotSerializer(ICBaseSerializer):
        email = serializers.EmailField(
            required=False, allow_null=True, help_text="defaults to current user."
        )
        provider = serializers.CharField(default="letsencrypt", allow_null=True)

    class PathSerializer(ICBaseSerializer):
        certificate = serializers.CharField(
            required=False,
            allow_null=True,
            help_text="specify the path to save the certificate.",
        )
        key = serializers.CharField(
            required=False,
            allow_null=True,
            help_text="specify the path to save the key.",
        )

    certbot = CertbotSerializer(
        required=False,
        allow_null=True,
    )
    path = PathSerializer(
        required=False,
        allow_null=True,
    )
    method = serializers.CharField(default="http-01")

class WebsiteDomainConfigSerializer(ICBaseSerializer):
    domain = serializers.CharField(max_length=512)
    extra_domain = serializers.CharField(max_length=10240, allow_null=True)

    def update(self, instance: WebsiteModel, validated_data):
        domain = validated_data.get("domain")
        extra_domain = validated_data.get("extra_domain")
        old_domain = instance.domain
        if domain and domain != instance.domain:
            os.system(f"rm -rf  /etc/nginx/sites-enabled/{instance.domain}.conf")
            os.system(f"rm -rf  /etc/nginx/sites-available/{instance.domain}.conf")
            instance.ssl_enable = False
            instance.domain = domain

        if extra_domain and extra_domain != instance.extra_domain:
            instance.ssl_enable = False
            instance.extra_domain = extra_domain
            # 1.domain.com,2.domain,3.domain -> 1.domain.com 2.domain 3.domain
            # or
            # 1.domain.com
            # 2.domain
            # 3.domain
            # -> 1.domain.com 2.domain 3.domain
            extra_domain = instance.extra_domain.replace(",", " ").replace("\n", " ")

            instance.valid_web_server_config = update_nginx_server_name(
                instance.valid_web_server_config, instance.domain, extra_domain
            )

        available_nginx_config = f"/etc/nginx/sites-available/{instance.domain}.conf"
        enabled_nginx_config = f"/etc/nginx/sites-enabled/{instance.domain}.conf"

        with open(available_nginx_config, "w") as f:
            f.write(instance.valid_web_server_config)

        if not pathlib.Path(enabled_nginx_config).exists():
            os.system(f"ln -s {available_nginx_config} {enabled_nginx_config}")

        os.system("systemctl reload nginx")

        instance.save()
        instance.get_application().update_domain(old_domain, instance.domain)
        return validated_data

    def validate_extra_domain(self, val: str):
        if val:
            val = val.replace("\n", " ").replace("\t", " ")
            val = val.replace("  ", " ").replace("  ", " ").replace(" ", ",")
        return val

class DefaultWebsuteConfigSerializer(ICBaseSerializer):
    web_server_config = serializers.CharField(max_length=204800)

    def update(self, instance: WebsiteModel, validated_data):
        app = instance.get_application_module(instance.get_app_website_config())
        web_server_config = instance.get_nginx_config()

        if isinstance(app.read(), str):
            user_area_config = app.read()
        else:
            user_area_config = app.read().nginx

        web_server_config = insert_section(web_server_config, user_area_config, "user")
        return {"web_server_config": web_server_config}

class WebsiteConfigSerializer(ICBaseSerializer):
    web_server_config = serializers.CharField(max_length=204800)

    def update(self, instance: WebsiteModel, validated_data):
        web_server_config = validated_data.get("web_server_config")

        app = instance.get_application_module(instance.get_app_website_config())

        data = instance.get_nginx_config()
        user_config = get_section(web_server_config, "user")
        data = insert_section(data, user_config, "user")

        instance.valid_web_server_config = data

        r = instance.is_valid_configuration_001()
        if r.returncode != 0:
            raise serializers.ValidationError(
                {
                    "web_server_config": "Invalid configuration 001:"
                    + format_completed_process(r)
                }
            )
        else:
            if instance.is_valid_configuration_002(instance.valid_web_server_config):
                instance.save()
            else:
                raise serializers.ValidationError(
                    {
                        "web_server_config": "Invalid configuration 002:"
                        + format_completed_process(r)
                    }
                )
            return instance.valid_web_server_config

class WebsiteModelSerializer(ICBaseModelSerializer):
    ssl_config = SSLConfigSerializer(required=False)
    # ssl_config = serializers.SerializerMethodField('_ssl_config')
    database_id = serializers.SerializerMethodField("_get_database_id")
    database_name = serializers.SerializerMethodField()
    web_server_type_text = serializers.SerializerMethodField("_web_server_type_text")
    status_text = serializers.SerializerMethodField("_status_text")

    class Meta:
        model = WebsiteModel
        fields = "__all__"

    def create(self, validated_data):
        instance: WebsiteModel = super(WebsiteModelSerializer, self).create(
            validated_data
        )

        # 1.Create folder and file
        if instance.index_root == "/var/www/html":
            logging.info(f"mkdir -p  /var/www/{instance.domain}")
            logging.info(f"chown www-data.www-data -R {instance.index_root}")
            instance.index_root = f"/var/www/{instance.domain}"

        else:
            logging.info(f"mkdir -p  {instance.index_root}")
            logging.info(f"chown www-data.www-data -R {instance.index_root}")

        try:
            os.system(f"mkdir -p  {instance.index_root}")
            os.system(f"chown www-data.www-data -R {instance.index_root}")
        except Exception as e:
            logging.exception(f"create and chmod {instance.index_root} failed!")
        nginx_config_path = f"/etc/nginx/sites-available/{instance.domain}.conf"
        os.system(f"touch {nginx_config_path}")

        # 2.Init SSL config
        instance.or_create_ssl_config()

        # 3.Reset created instance 'ssl_enable',
        # enable website ssl: post website/{instance_pk}/enable_ssl/
        # disable website ssl: post website/{instance_pk}/disable_ssl/
        instance.ssl_enable = False

        # 4.Write web server config

        app_factory = AppFactory
        app_factory.load()

        if instance.application is None:
            text = "与君初相识，犹如故人归。嗨，别来无恙！ <br> Hello World！"
            app = app_factory.get_application_module(
                "NginxApplication",
                instance.get_app_website_config(),
                {"name": "New website", "text": text},
            )
            instance.application = "NginxApplication"
        else:
            app = app_factory.get_application_module(
                instance.application,
                instance.get_app_website_config(),
                instance.application_config,
            )

        web_server_config = instance.get_nginx_config()

        if isinstance(app.read(), str):
            user_area_config = app.read()
        else:
            user_area_config = app.read().nginx

        web_server_config = insert_section(web_server_config, user_area_config, "user")
        old_config = instance.valid_web_server_config
        instance.valid_web_server_config = web_server_config

        is_valid_configuration_001 = instance.is_valid_configuration_001()
        logging.debug(is_valid_configuration_001)

        if is_valid_configuration_001.returncode == 0:
            logging.debug("instance.is_valid_configuration_001()")
            if instance.is_valid_configuration_002(web_server_config):
                os.system("systemctl reload nginx")
                instance.status = instance.StatusType.VALID
                instance.status_info = "ok"
            else:
                instance.status = instance.StatusType.ERROR
                instance.status_info = "002:nginx configuration error.r"

        else:
            if old_config is None:
                raise serializers.ValidationError(
                    {
                        "cmd": format_completed_process(is_valid_configuration_001),
                        "valid_web_server_config": instance.valid_web_server_config,
                    }
                )
            instance.valid_web_server_config = old_config
            instance.status = instance.StatusType.ERROR
            instance.status_info = "001:nginx configuration error."

        if instance.extra_domain is None:
            extra_domain = None
        else:
            extra_domain = instance.extra_domain.replace(",", " ").replace("\n", " ")

        instance.valid_web_server_config = update_nginx_server_name(
            instance.valid_web_server_config, instance.domain, extra_domain
        )

        # 5.Create application instance
        # post application/{instance_pk}/app_create/

        instance.save()
        return instance

    def update(self, instance, validated_data):
        return super(WebsiteModelSerializer, self).update(instance, validated_data)

    def _ssl_config(self, obj: WebsiteModel) -> SSLConfigSerializer:
        return SSLConfigSerializer(obj.ssl_config)

    def _get_database_id(self, obj: WebsiteModel):
        if hasattr(obj, "databasemodel"):
            return obj.databasemodel.id

    def _web_server_type_text(self, obj: WebsiteModel):
        return obj.get_web_server_type_display()

    def _status_text(self, obj: WebsiteModel):
        return obj.get_status_display()

    def get_database_name(self, obj: WebsiteModel):
        if hasattr(obj, "databasemodel"):
            return obj.databasemodel.name

    def validate(self, data):
        return data


import torch
import torch.nn as nn
from espnet.nets.pytorch_backend.backbones.modules.resnet import ResNet, BasicBlock
from espnet.nets.pytorch_backend.transformer.convolution import Swish

def threeD_to_2D_tensor(x):
    n_batch, n_channels, s_time, sx, sy = x.shape
    x = x.transpose(1, 2)
    return x.reshape(n_batch * s_time, n_channels, sx, sy)

class Conv3dResNet(torch.nn.Module):
    """Conv3dResNet module
    """

    def __init__(self, backbone_type="resnet", relu_type="swish"):
        """__init__.

        :param backbone_type: str, the type of a visual front-end.
        :param relu_type: str, activation function used in an audio front-end.
        """
        super(Conv3dResNet, self).__init__()
        self.frontend_nout = 64
        self.trunk = ResNet(BasicBlock, [2, 2, 2, 2], relu_type=relu_type)
        self.frontend3D = nn.Sequential(
            nn.Conv3d(1, self.frontend_nout, (5, 7, 7), (1, 2, 2), (2, 3, 3), bias=False),
            nn.BatchNorm3d(self.frontend_nout),
            Swish(),
            nn.MaxPool3d((1, 3, 3), (1, 2, 2), (0, 1, 1))
        )

    def forward(self, xs_pad):
        B, C, T, H, W = xs_pad.size()
        xs_pad = self.frontend3D(xs_pad)
        Tnew = xs_pad.shape[2]
        xs_pad = threeD_to_2D_tensor(xs_pad)
        xs_pad = self.trunk(xs_pad)
        return xs_pad.view(B, Tnew, xs_pad.size(1))


import torch
import torch.nn as nn
import torch.optim as optim
from prot2vec.tools.datasets import FastSemanticSimilarityDataset
from prot2vec.tools.utils import TrainingProgress
from datetime import datetime
import matplotlib.pyplot as plt
from prot2vec.models import (SiameseSimilarityNet, SiameseSimilarityPerceptronNet,
                             SiameseSimilaritySmall, SiameseSimilaritySmallPerceptron)
from prot2vec.models import count_parameters, save_checkpoint
from itertools import product
from prot2vec.Utils import Configuration
import pickle
import os

def run(run_config, gpu_device, train_only):
    # this is a best effort thing, the user must know the name of the device
    # otherwise this script will simply fail
    device = gpu_device if torch.cuda.is_available() else 'cpu'
    print(f'Using {device} device')

    config = Configuration.load_run(run_config)

    batch_size_train = config["model"]["batch_size_train"]
    batch_size_val = config["model"]["batch_size_val"]

    dir_train = config["dataset"]["dir_train"]
    dir_val = config["dataset"]["dir_val"]

    interpro_pca = config["dataset"]["interpro_pca"]
    num_pca = config["dataset"]["num_pca"]
    interpro_filename = config["dataset"]["interpro_filename"]
    semantic_similarity_filename = config["dataset"]["semantic_similarity_filename"]

    print('Loading training set...')
    ss_bp_train = FastSemanticSimilarityDataset(dir_train,
                                                batch_size=batch_size_train,
                                                shuffle=True,
                                                interpro_pca=interpro_pca,
                                                num_pca=num_pca,
                                                interpro_filename=interpro_filename,
                                                semantic_similarity_filename=semantic_similarity_filename)
    print("train", ss_bp_train.dataset_len)
    print("train", ss_bp_train.interpro_df.shape)

    if not train_only:
        print('Loading validation set...')
        ss_bp_val = FastSemanticSimilarityDataset(dir_val,
                                                  batch_size=batch_size_val,
                                                  shuffle=True,
                                                  interpro_pca=interpro_pca,
                                                  num_pca=num_pca,
                                                  interpro_filename=interpro_filename,
                                                  semantic_similarity_filename=semantic_similarity_filename)
    # ss_bp_train = SemanticSimilarityOnDeviceDataset('../83333/train_data/', device)
    # ss_bp_val = SemanticSimilarityOnDeviceDataset('../83333/val_data/', device)
    # ss_bp_test = SemanticSimilarityOnDeviceDataset('../83333/test_data/', device)

    # ss_bp_train = SemanticSimilarityDatasetDevice('E:/prot2vec/83333/train_data/',
    #                                               device, 'E:/prot2vec/83333/train_data/tensor.pt')
    # ss_bp_val = SemanticSimilarityDatasetDevice('E:/prot2vec/83333/val_data/',
    #                                             device, 'E:/prot2vec/83333/val_data/tensor.pt')
    # ss_bp_test = SemanticSimilarityDatasetDevice('E:/prot2vec/83333/test_data/',
    #                                              device, 'E:/prot2vec/83333/test_data/tensor.pt')

        print("validation", ss_bp_val.dataset_len)
        print("validation", ss_bp_val.interpro_df.shape)

    model_classes = [
        SiameseSimilarityNet, SiameseSimilarityPerceptronNet,
        SiameseSimilaritySmall, SiameseSimilaritySmallPerceptron
    ]
    model_classes = [SiameseSimilarityNet]

    activations = ['relu', 'sigmoid']
    activations = ['sigmoid']

    num_interpro_features = ss_bp_train.interpro_df.shape[1]

    for model_class, activation in product(model_classes, activations):

        model = model_class(num_interpro_features,
                            activation=activation,
                            dim_first_hidden_layer=config["model"]["dim_first_hidden_layer"]).to(device)

        count_parameters(model)

        optimizer = optim.Adam(model.parameters(),
                               lr=config["optimizer"]["learning_rate"])
        num_epochs = config["training"]["num_epochs"]
        criterion = nn.MSELoss()
        save_name = f'[{model.name()}]-{num_epochs}_epochs.pt'
        alias = config["model"]["alias"]
        print(f'running {save_name} with alias {alias}')
        save_name = save_name if alias == "infer" else alias
        save_filename_model = os.path.join(config["model"]["dir_model_output"], save_name)

        best_val_loss = float("Inf")
        train_losses = []
        val_losses = []

        with TrainingProgress() as progress:
            epochs = progress.add_task("[green]Epochs", progress_type="epochs", total=num_epochs)
            for epoch in range(num_epochs):
                running_loss = 0.0
                model.train()
                training = progress.add_task(f"[magenta]Training [{epoch+1}]",
                                             total=len(ss_bp_train), progress_type="training")
                if not train_only:
                    validation = progress.add_task(f"[cyan]Validation [{epoch+1}]",
                                                   total=len(ss_bp_val), progress_type="validation")

                for curr_batch, (p1, p2, sim) in enumerate(ss_bp_train):
                    # forward
                    p1 = p1.to(device)
                    p2 = p2.to(device)
                    sim = sim.to(device)
                    outputs = model(p1, p2)
                    loss = criterion(outputs, sim)

                    # backward and optimize
                    optimizer.zero_grad()
                    loss.backward()
                    optimizer.step()
                    running_loss += loss.item()
                    progress.advance(training)

                n = len(ss_bp_train)
                avg_train_loss = running_loss / n
                train_losses.append(avg_train_loss)

                if not train_only:
                    val_running_loss = 0.0
                    with torch.no_grad():
                        model.eval()
                        for num_batch, (p1, p2, sim) in enumerate(ss_bp_val):
                            p1 = p1.to(device)
                            p2 = p2.to(device)
                            sim = sim.to(device)
                            outputs = model(p1, p2)
                            loss = criterion(outputs, sim)
                            val_running_loss += loss.item()
                            progress.advance(validation)
                    avg_val_loss = val_running_loss / len(ss_bp_val)
                    val_losses.append(avg_val_loss)

                    print('Epoch [{}/{}],Train Loss: {:.4f}, Valid Loss: {:.8f}'
                          .format(epoch + 1, num_epochs, avg_train_loss, avg_val_loss))
                    if avg_val_loss < best_val_loss:
                        best_val_loss = avg_val_loss
                        save_checkpoint(save_filename_model, model, optimizer, best_val_loss)
                else:
                        save_checkpoint(save_filename_model, model, optimizer, -1)

                progress.tasks[training].visible = False
                if not train_only:
                    progress.tasks[validation].visible = False
                progress.advance(epochs)

        # plotting of training and validation loss
        fix, axs = plt.subplots(nrows=2, figsize=(10, 10), facecolor='white')
        for i, ax in enumerate(axs):
            ax.set_xlabel('Epoch')
            ax.set_ylabel('Loss')
            ax.grid(ls=':', zorder=1)
            if i != 0:
                ax.set_yscale('log')
                ax.set_ylabel('Loss (log scale)')
            ax.plot(train_losses, label='Train Loss')
            ax.plot(val_losses, label="Validation Loss")
            ax.legend(loc='upper right')
        basename = os.path.join(
            config["training"]["dir_training_out"],
            f"loss-evol-[{save_name}]-[{datetime.today().strftime('%Y-%m-%d-%H-%M-%S')}]"
        )
        figname = f'{basename}.png'
        dataname = f'{basename}.pkl'
        plt.savefig(figname)
        plt.close('all')
        with open(dataname, 'wb') as f:
            pickle.dump(train_losses, f)
            pickle.dump(val_losses, f)

    print("Finished Training")

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser("Train a prot2vec model.")
    parser.add_argument("--run-config", "--c",
                        help="Path to the run configuration file",
                        required=True)
    parser.add_argument("--gpu-device", "--g",
                        help="The name of the gpu device, `cuda` by default",
                        default="cuda",
                        required=False)
    parser.add_argument("--train-only", "--t", action="store_true")
    args = parser.parse_args()
    run(args.run_config, args.gpu_device, args.train_only)


soma2 = 0
soma = 0
for c in range(1, 11):
    print('-=-=-=-=-=-=-=-=-=-=-=-= ')
    num = float(input('Digite um número: '))
    if num % 2 == 1:
        soma += num
    if num % num == 0:
        soma2 += num
print(f'A soma dos números ímpares foi: {soma} ')
print(f'A soma dos números primos foi: {soma2} ')


from collections import Counter

def solution(k, tangerine):
    counter = Counter(tangerine)
    lst = list(counter.values())
    lst.sort(reverse=True)

    answer = 0
    value = 0
    for count in lst:
        if value >= k:
            break
        answer += 1
        value += count
    return answer

print(solution(6, [1, 3, 2, 5, 4, 5, 2, 3]))


"""
    gitdata utils
"""

import collections
import datetime
import decimal
import inspect
import logging
import os
import string
import uuid

logger = logging.getLogger(__name__)

chars = ''.join(map(chr, range(256)))
keep_these = string.ascii_letters + string.digits + '-_ '
delete_these = chars.translate(str.maketrans(chars, chars, keep_these))
allowed = str.maketrans(keep_these, keep_these, delete_these)

def new_uid():
    """returns a unique id"""
    return uuid.uuid4().hex

def test_uid_maker(start=0):
    """return a simple uid generator for testing

    Returns a simple uid generator that with a given integer
    and increments by one each time its called which allows
    predictable uid values for testing.

    >>> id_maker = test_uid_maker(4)
    >>> id_maker()
    '5'
    >>> id_maker()
    '6'

    """
    n = [start]
    def _new_id():
        n[0] += 1
        return str(n[0])
    return _new_id

def id_for(*args):
    """Calculates a valid hyphenated id given an arbitrary string.

    >>> id_for('Test 123')
    'test-123'
    >>> id_for('New Record')
    'new-record'
    >>> id_for('New "special" Record')
    'new-special-record'
    >>> id_for("hi", "test")
    'hi~test'
    >>> id_for("hi test")
    'hi-test'
    >>> id_for("hi-test")
    'hi-test'
    >>> id_for(1234)
    '1234'
    >>> id_for('this %$&#@^is##-$&*!it')
    'this-is-it'
    >>> id_for('test-this')
    'test-this'
    """
    def id_(text):
        return str(text).strip().translate(allowed).lower().replace(' ', '-')

    return '~'.join([id_(arg) for arg in args])

def name_for(text):
    """Calculates a valid underscored name given an arbitrary string.

    >>> name_for('Test 123')
    'test_123'
    >>> name_for('New Record')
    'new_record'
    >>> name_for('New "special" Record')
    'new_special_record'
    >>> name_for("hi test")
    'hi_test'
    >>> name_for("hi-test")
    'hi_test'
    >>> name_for(1234)
    '1234'
    >>> name_for('this %$&#@^is##-$&*!it')
    'this_is_it'
    >>> name_for('test-this')
    'test_this'
    """
    return id_for(text).replace('-', '_')

def libpath(*args):
    """Returns the location of a standard gitdata-lib asset

    >>> import os
    >>> asset_path = libpath('assets', 'README.md')
    >>> os.path.exists(asset_path)
    True

    """
    realpath = os.path.realpath
    dirname = os.path.dirname
    join = os.path.join
    return realpath(join(realpath(dirname(__file__)), *args))

def thispath(*args):
    """Returns a location in the same directory as the

    >>> path = thispath('file.py')

    """
    realpath = os.path.realpath
    join = os.path.join
    root = realpath(os.path.dirname(inspect.stack()[1][1]))
    return join(root, *args)

def obfuscate(text):
    """obfuscate text so it is recognizable without divulging it

    >>> obfuscate('12345')
    '1***5'

    >>> obfuscate('')
    ''

    """
    return text[:1] + '*' * (len(text) - 2) + text[-1:]

def parents(path):
    """Return list of parent directories"""
    if not os.path.isdir(path):
        return parents(os.path.split(os.path.abspath(path))[0])
    parent = os.path.abspath(os.path.join(path, os.pardir))
    if path == parent:
        return []
    else:
        return [path] + parents(parent)

def trim(text):
    """Remove excess spaces from a block of text

    >>> trim('remove right ')
    'remove right'

    >>> trim(' remove left')
    'remove left'

    >>> print(trim(' remove spaces\\n    from block\\n    of text'))
    remove spaces
       from block
       of text

    >>> print(
    ...     trim(
    ...     '    \\n'
    ...     '    remove spaces\\n'
    ...     '        from block\\n'
    ...     '        of text\\n'
    ...     '    \\n'
    ...     '\\n'
    ...     )
    ... )
    <BLANKLINE>
    remove spaces
        from block
        of text
    <BLANKLINE>
    <BLANKLINE>

    >>> print(trim('    remove spaces\\n  from block\\n  of text\\n    '))
      remove spaces
    from block
    of text
    <BLANKLINE>

    >>> print(trim('    remove spaces\\n  from block\\n  of text'))
      remove spaces
    from block
    of text

    >>> print(trim('\\n  remove spaces\\n    from block\\n  of text'))
    <BLANKLINE>
    remove spaces
      from block
    of text

    >>> text = '\\nremove spaces  \\n    from block\\nof text'
    >>> print('\\n'.join(repr(t) for t in trim(text).splitlines()))
    'remove spaces  '
    '    from block'
    'of text'

    >>> text = (
    ...     '\\nremove spaces'
    ...     '\\n    from block'
    ... )
    >>> print(trim(text))
    remove spaces
        from block

    """
    trim_size = None
    lines = text.splitlines()
    for line in lines:
        if not line or line.isspace():
            continue
        n = len(line) - len(line.lstrip())
        trim_size = min([trim_size, n]) if trim_size is not None else n
    if trim_size:
        result = []
        for line in lines:
            result.append(line[trim_size:])
        return '\n'.join(result)
    else:
        return text.strip()

def sorted_column_names(names):
    """Return column names sorted in a more typically expected order"""

    def looks_like_an_id(text):
        return text.endswith('_id')

    id_names = sorted(name for name in names if looks_like_an_id(name))
    special_names = id_names + [
        'id', 'userid', 'groupid', 'key',
        'name', 'title', 'description',
        'first_name', 'middle_name', 'last_name', 'fname', 'lname'
    ]
    result = []
    for name in special_names:
        if name in names:
            result.append(name)
    for name in sorted(names, key=lambda a: (len(a), a)):
        if name not in result:
            result.append(name)
    return result

def kind(o):
    """
    returns a text version of an object class name
    """
    n = []
    for c in o.__class__.__name__:
        if c.isalpha() or c == '_':
            if c.isupper() and len(n):
                n.append('_')
            n.append(c.lower())
    return ''.join(n)

class Bunch:
    """a handy bunch of variables

    >>> something = Bunch(name='Cat', colour='Brown')
    >>> something.name
    'Cat'
    """
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

class Record(dict):
    """Record Class

    A dict that provides attribute access, printability and
    attribute access.

    >>> import decimal
    >>> class Person(Record):
    ...    @property
    ...    def full_name(self):
    ...        return ' '.join([self.name, self.surname])
    >>> joe = Person(name='Joe', surname='Smith')
    >>> joe.name
    'Joe'
    >>> joe['name']
    'Joe'

    >>> joe.age = 20
    >>> joe['age']
    20

    >>> joe.full_name
    'Joe Smith'

    >>> del joe.age
    >>> joe.age

    >>> try:
    ...     del joe.missing
    ... except AttributeError:
    ...     print('missing attribute cannot be deleted!')
    missing attribute cannot be deleted!

    >>> try:
    ...     joe.missing
    ... except KeyError:
    ...     print('missing attribute should not raise exception!')

    >>> joe.missing

    >>> print(Person(name='Pat', surname='Jones', age=21, salary=decimal.Decimal(1000)))
    Person
      name ................: 'Pat'
      age .................: 21
      salary ..............: Decimal('1000')
      surname .............: 'Jones'
      full_name ...........: 'Pat Jones'

    >>> Person(name='Pat', surname='Jones', age=21, salary=decimal.Decimal(1000))
    <Person {'name': 'Pat', 'age': 21, 'salary': Decimal('1000'), 'surname': 'Jones', 'full_name': 'Pat Jones'}>

    """

    __setattr__ = dict.__setitem__

    def __getitem__(self, name):
        try:
            value = dict.__getitem__(self, name)
            if hasattr(value, '__get__'):
                getter = getattr(value, '__get__')
                if getter is not None:
                    return getter(self)
                else:
                    return value
            else:
                return value
        except KeyError as k:
            try:
                value = self.__class__.__dict__[name]
                if hasattr(value, '__get__'):
                    getter = getattr(value, '__get__')
                    if getter:
                        return getter(self)
                    else:
                        return value
                else:
                    return value
            except KeyError as k:
                raise k

    def __getattr__(self, key):
        try:
            return self.__getitem__(key)
        except KeyError:
            return None

    def __delattr__(self, key):
        try:
            del self[key]
        except KeyError as k:
            raise AttributeError from k

    def attributes(self):
        """Return propoerties and members as one set"""
        return get_attributes(self)

    def __str__(self):
        name = self.__class__.__name__
        attributes = self.attributes()
        t = []

        items = [
            (key, getattr(self, key, None)) for key in attributes
            if not key.startswith('_')
        ]

        for key, value in items:
            if callable(value):
                v = value()
            else:
                v = value
            t.append('  {} {}: {!r}'.format(
                key,
                '.'*(20-len(key[:20])),
                v
            ))
        return '\n'.join([name] + t)

    def __repr__(self):
        name = self.__class__.__name__
        attributes = self.attributes()
        t = []

        items = [
            (key, getattr(self, key, None)) for key in attributes
            if not key.startswith('_')
        ]

        for key, value in items:
            if callable(value):
                v = value()
            else:
                v = value
            t.append((repr(key), repr(v)))
        return '<%s {%s}>' % (
            name, ', '.join('%s: %s' % (k, v) for k, v in t)
        )

    def save(self):
        """save record to originating store"""
        record_id = self['__store'].put(self)
        key = self['__store'].id_name
        logger.debug(
            'saved record %s(%s=%r) to %r',
            self.__class__.__name__,
            key,
            self[key],
            self['__store']
        )
        return record_id

class ItemList(list):
    """
    list of data items

    >>> items = ItemList()
    >>> items.append(['Joe', 12, 125])
    >>> items
    [['Joe', 12, 125]]
    >>> print(items)
    Column 0 Column 1 Column 2
    -------- -------- --------
    Joe            12      125

    >>> items.insert(0, ['Name', 'Score', 'Points'])
    >>> print(items)
    Name Score Points
    ---- ----- ------
    Joe     12    125

    >>> data = [
    ...     ['Joe', 12, 125],
    ...     ['Sally', 13, 1354],
    ... ]
    >>> items = ItemList(data)
    >>> print(items)
    Column 0 Column 1 Column 2
    -------- -------- --------
    Joe            12      125
    Sally          13    1,354

    >>> data = [
    ...     ['Joe', 12, 125],
    ...     ['Sally', 13, 135],
    ... ]
    >>> items = ItemList(data, labels=['Name', 'Score', 'Points'])
    >>> print(items)
    Name  Score Points
    ----- ----- ------
    Joe      12    125
    Sally    13    135

    >>> data = [
    ...     [10000, 'Joe', 12, 125],
    ...     [10001, 'Sally', 13, 135],
    ... ]
    >>> items = ItemList(data, labels=['_id', 'Name', 'Score', 'Points'])
    >>> print(items)
    _id   Name  Score Points
    ----- ----- ----- ------
    10000 Joe      12    125
    10001 Sally    13    135

    >>> now = datetime.date(2020, 2, 1)
    >>> data = [
    ...     [10000, 'Joe', now - datetime.date(1980, 1, 20)],
    ...     [10001, 'Sally', now - datetime.date(1984, 9, 20)],
    ... ]
    >>> items = ItemList(data, labels=['_id', 'Name', 'Age'])
    >>> print(items)
    _id   Name  Age
    ----- ----- -------------------
    10000 Joe   14622 days, 0:00:00
    10001 Sally 12917 days, 0:00:00

    >>> now = datetime.date(2020, 2, 1)
    >>> data = [
    ...     [10000, 'Joe', now - datetime.date(1980, 1, 20)],
    ...     [10001, 'Sally', now - datetime.date(1984, 9, 20)],
    ... ]
    >>> items = ItemList(data, labels=['user_id', 'Name', 'Age'])
    >>> print(items)
    user_id Name  Age
    ------- ----- -------------------
      10000 Joe   14622 days, 0:00:00
      10001 Sally 12917 days, 0:00:00

    >>> import datetime
    >>> now = datetime.date(2020, 2, 1)
    >>> data = [
    ...     [9000, 'Greens', 1234],
    ...     [10000, 'Browns', 1203],
    ... ]
    >>> items = ItemList(data, labels=['id', 'customer', 'invoice_number'])
    >>> print(items)
    id    customer invoice_number
    ----- -------- --------------
     9000 Greens             1234
    10000 Browns             1203
    """
    def __init__(self, *args, **kwargs):
        self.labels = kwargs.pop('labels', None)
        list.__init__(self, *args, **kwargs)

    def __str__(self):
        def is_text(value):
            return type(value) in [str, bytes]

        def name_column(number):
            return 'Column {}'.format(number)

        def is_homogeneous(values):
            return any([
                len(values) <= 1,
                all(type(values[0]) == type(i) for i in values[1:]),
            ])

        def get_format(label, values):
            first_non_null = list(
                map(type, [a for a in values if a is not None])
            )[:1]
            if first_non_null:
                data_type = first_non_null[0]
                if label in ['_id', 'userid']:
                    return '{:>{width}}'
                elif label == 'id':
                    return '{:>{width}}'
                elif label.endswith('_id'):
                    return '{:>{width}}'
                elif label.endswith('_number'):
                    return '{:>{width}}'
                elif data_type in [int, float, decimal.Decimal]:
                    return '{:{width},}'
                elif data_type in [datetime.date]:
                    return '{:%Y-%m-%d}'
                elif data_type in [datetime.timedelta]:
                    return '{:}'
                elif data_type in [datetime.datetime]:
                    return '{:%Y-%m-%d %H:%M:%S}'
            return '{:<{width}}'

        def nvl(value):
            if value is None:
                return 'None'
            elif isinstance(value, str):
                return value.strip()
            return value

        if len(self) == 0:
            return ''

        num_columns = len(list(self[0]))
        columns = list(range(num_columns))

        # calculate labels
        if self.labels:
            labels = self.labels
            offset = 0
        else:
            if not all(is_text(label) for label in self[0]):
                labels = [name_column(i) for i in range(num_columns)]
                offset = 0
            else:
                labels = self[0]
                offset = 1

        # rows containing data
        rows = [list(nvl(v) for v in row) for row in self[offset:]]

        # calculate formats
        formats = []
        for col in columns:
            values = [row[col] for row in rows]
            if is_homogeneous(values):
                formats.append(get_format(labels[col], values))
            else:
                formats.append('{}')

        # calulate formatted values
        formatted_values = [labels] + [
            [
                formats[col].format(row[col], width=0)
                for col in columns
            ] for row in rows
        ]

        # calculate column widths
        data_widths = {}
        for row in formatted_values:
            for col in columns:
                n = data_widths.get(col, 0)
                m = len(row[col])
                if n < m:
                    data_widths[col] = m

        label_format = '{:<{width}}'
        formatted_labels = [
            label_format.format(l, width=data_widths[i])
            for i, l in enumerate(labels)
        ]

        sorted_names = sorted_column_names(labels)

        for i, v in enumerate(formats):
            formats[i] = v if v != '{}' else '{:<{width}}'

        if not self.labels:
            columns = sorted(columns, key=lambda a: sorted_names.index(labels[a]))
        dashes = ['-' * data_widths[col] for col in columns]
        sorted_labels = [formatted_labels[col] for col in columns]

        aligned_rows = [sorted_labels] + [dashes] + [
            [
                formats[col].format(row[col], width=data_widths[col])
                for col in columns
            ] for row in rows
        ]

        lines = [' '.join(row).rstrip() for row in aligned_rows]

        return '\n'.join(lines)

def get_properties(obj):
    if type(obj) == dict:
        return []
    klass = obj.__class__
    return [
        i for i, j in (
            (n, getattr(klass, n)) for n in dir(klass)
        ) if type(j) == property
    ]

def get_attributes(obj):
    names = list(obj.keys()) + get_properties(obj)
    return sorted_column_names(names)

class RecordList(list):
    """a list of Records"""

    def __init__(self, *a, **k):
        list.__init__(self, *a, **k)
        self._n = 0

    def __iter__(self):
        self._n = 0
        return self

    def __next__(self):
        if self._n >= len(self):
            raise StopIteration
        else:
            result = self[self._n]
            self._n += 1
        return result

    def __str__(self):
        """
        represent as a string

        >>> import datetime
        >>> class Person(Record): pass
        >>> class People(RecordList): pass
        >>> people = People()
        >>> people.append(Person(_id=1, name='Joe', age=20,
        ...     birthdate=datetime.date(1992,5,5)))
        >>> people.append(Person(_id=2, name='Samuel', age=25,
        ...     birthdate=datetime.date(1992,4,5)))
        >>> people.append(Person(_id=3, name='Sam', age=35,
        ...     birthdate=datetime.date(1992,3,5)))
        >>> print(people)
        person
        _id name   age birthdate
        --- ------ --- ----------
          1 Joe     20 1992-05-05
          2 Samuel  25 1992-04-05
          3 Sam     35 1992-03-05
        3 person records

        >>> class Player(Person):
        ...    @property
        ...    def score(self):
        ...        return 10
        >>> people = People()
        >>> people.append(Player(userid=1, name='Joe', age=20,
        ...     birthdate=datetime.date(1992,5,5)))
        >>> people.append(Player(userid=2, name='Samuel', age=25,
        ...     birthdate=datetime.date(1992,4,5)))
        >>> people.append(Player(userid=3, name='Sam', age=35,
        ...     birthdate=datetime.date(1992,3,5)))
        >>> print(people)
        player
        userid name   age score birthdate
        ------ ------ --- ----- ----------
             1 Joe     20    10 1992-05-05
             2 Samuel  25    10 1992-04-05
             3 Sam     35    10 1992-03-05
        3 player records

        """

        def visible(name):
            hidden = getattr(self[0], 'hidden', None) or [] if self != [] else []
            return not name.startswith('__') and not name in hidden

        if not bool(self):
            return 'Empty list'

        title = '%s\n' % kind(self[0])

        keys = labels = list(filter(visible, get_attributes(self[0])))
        rows = [[getattr(record, key, record.get(key)) for key in keys] for record in self]

        footer = '\n{} {} records'.format(len(self), kind(self[0]))

        return title + str(ItemList(rows, labels=labels)) + footer

class OrderedSet(collections.MutableSet):
    """OrderedSet

    A set that preserves the order of the elements

    >>> s = OrderedSet('abracadaba')
    >>> t = OrderedSet('simsalabim')
    >>> print(s | t)
    OrderedSet(['a', 'b', 'r', 'c', 'd', 's', 'i', 'm', 'l'])
    >>> print(s & t)
    OrderedSet(['a', 'b'])
    >>> print(s - t)
    OrderedSet(['r', 'c', 'd'])
    >>> print(OrderedSet(reversed(s - t)))
    OrderedSet(['d', 'c', 'r'])
    >>> OrderedSet(['d', 'c', 'd']) == OrderedSet(['c', 'd', 'd'])
    False

    credit: http://code.activestate.com/recipes/576694/
    Licensed under MIT License
    """

    def __init__(self, iterable=None):
        self.end = end = []
        end += [None, end, end]         # sentinel node for doubly linked list
        self.map = {}                   # key --> [key, prev, next]
        if iterable is not None:
            self |= iterable

    def __len__(self):
        return len(self.map)

    def __contains__(self, key):
        """test if item is present

            >>> s = OrderedSet([1, 2, 3])
            >>> 'c' in s
            False
            >>> 2 in s
            True
        """
        return key in self.map

    def add(self, key):
        """add an item

            >>> s = OrderedSet([1, 2, 3])
            >>> s.add(4)
            >>> s
            OrderedSet([1, 2, 3, 4])
        """
        if key not in self.map:
            end = self.end
            curr = end[1]
            curr[2] = end[1] = self.map[key] = [key, curr, end]

    def discard(self, key):
        """discard an item by key

            >>> s = OrderedSet([1, 2, 3])
            >>> s.discard(1)
            >>> s
            OrderedSet([2, 3])
        """
        if key in self.map:
            key, prev, _next = self.map.pop(key)
            prev[2] = _next
            _next[1] = prev

    def __iter__(self):
        end = self.end
        curr = end[2]
        while curr is not end:
            yield curr[0]
            curr = curr[2]

    def __reversed__(self):
        end = self.end
        curr = end[1]
        while curr is not end:
            yield curr[0]
            curr = curr[1]

    def pop(self, last=True):
        """pop an item

            >>> s = OrderedSet([1, 2, 3])
            >>> s.pop(2)
            3
            >>> s
            OrderedSet([1, 2])
        """
        if not self:
            raise KeyError('set is empty')
        key = self.end[1][0] if last else self.end[2][0]
        self.discard(key)
        return key

    def __repr__(self):
        if not self:
            return '%s()' % (self.__class__.__name__,)
        return '%s(%r)' % (self.__class__.__name__, list(self))

    def __eq__(self, other):
        if isinstance(other, OrderedSet):
            return len(self) == len(other) and list(self) == list(other)
        return set(self) == set(other)


from gpiozero import Button
from signal import pause
import pygame, pygame.mixer
import os

pygame.mixer.init()

def say_hello():
    pygame.mixer.music.stop()
    print("hi")
def say_goodbye():
    print("bye")
    pygame.mixer.music.load(os.path.join("/home/pi/Doorcode/opendoor.mp3"))
    pygame.mixer.music.play()

button1 = Button(3)
button1.when_pressed = say_hello
button1.when_released = say_goodbye

button2 = Button(4)
button2.when_pressed = say_hello
button2.when_released = say_goodbye

button3 = Button(17)
button3.when_pressed = say_hello
button3.when_released = say_goodbye

button4 = Button(27)
button4.when_pressed = say_hello
button4.when_released = say_goodbye
pause()


import numpy as np

def find_rotation(q):
    R = np.empty([3,3])

    aa = q[0]*q[0]
    ab = q[0]*q[1]
    ac = q[0]*q[2]
    ad = q[0]*q[3]
    bb = q[1]*q[1]
    bc = q[1]*q[2]
    bd = q[1]*q[3]
    cc = q[2]*q[2]
    cd = q[2]*q[3]
    dd = q[3]*q[3]

    roll = np.arctan2(2*(cd+ab), 1.0-2.0*(bb + cc)) #atan2(2.0 * (d * c + a * b) , 1.0 - 2.0 * (q.q1 * q.q1 + q.q2 * q.q2))
    pitch = np.arcsin(2*(ac-bd))
    yaw = np.arctan2(2*(bc+ad), -1.0+2.0*(aa + bb))

    R[0,0] = aa+bb-cc-dd
    R[0,1] = 2*(bc-ad)
    R[0,2] = 2*(bd+ac)
    R[1,0] = 2*(bc+ad)
    R[1,1] = aa-bb+cc-dd
    R[1,2] = 2*(cd-ab)
    R[2,0] = 2*(bd-ac)
    R[2,1] = 2*(cd+ab)
    R[2,2] = aa-bb-cc+dd

    return R, roll, pitch, yaw

def transform_to_local(vec, q): #vec is a 3x1 vector, q is a 4x1 vector, outputs the transformed 3x1 vector vec_loc
    R = find_rotation(q)
    return R @ vec


class Solution:
    def pivotIndex(self, nums: [int]) -> int:
        """
        前缀和应用，找到一个点左右和相等
        :param nums:
        :return:
        """
        total = sum(nums)

        left_sum = 0

        for i in range(len(nums)):
            if left_sum == total - nums[i] - left_sum:
                return i
            left_sum += nums[i]

        return -1


# Import Library
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tqdm import tqdm
#%%
# 버스 이용률 시각화
# 데이터 제공 : 전주시 버스 정책과

data = pd.read_csv('C:/Users/hyunj/Desktop/전주공모전자료/제공받은데이터/버스이용률.csv', encoding='utf-8')
data.info()
#%%
# 한글 폰트 사용을 위해서 세팅
from matplotlib import font_manager, rc
font_path = "C:/Windows/Fonts/NGULIM.TTF"
font = font_manager.FontProperties(fname=font_path).get_name()
rc('font', family=font)
#%%
# 승차인원 ',' 전처리하기 : object -> int

for i in tqdm(range(len(data)), desc = "승차인원 object -> int 데이터 전처리 중") :
    temp = data.loc[i, '승차인원']
    temp_list = temp.split(',')
    temp_num = int(temp_list[0] + temp_list[1])
    data.loc[i, '승차인원'] = temp_num
#%%
'''
===============================================================================
버스 이용률 시각화
===============================================================================
'''

# 코로나 발생은 2019년 12월 31일 -> 2019년 & 2020년 비교, 2019년 & 2021년 비교, 2019년 & 2022년 비교

total_2019 = sum(data.loc[(data['연도'] == 2019), '승차인원'])
total_2020 = sum(data.loc[(data['연도'] == 2020), '승차인원'])
total_2021 = sum(data.loc[(data['연도'] == 2021), '승차인원'])
total_2019_6 = sum(data.loc[(data['연도'] == 2019) &
                            ((data['월'] == 1) | (data['월'] == 2) | (data['월'] == 3) | (data['월'] == 4) | (data['월'] == 5) | (data['월'] == 6)), '승차인원'])
total_2022_6 = sum(data.loc[(data['연도'] == 2022) &
                            ((data['월'] == 1) | (data['월'] == 2) | (data['월'] == 3) | (data['월'] == 4) | (data['월'] == 5) | (data['월'] == 6)), '승차인원'])

# 2019 - 2020 - 2021 전체 버스 이용률 꺾은선 그래프
plt.figure(figsize=(10,8))
x_axis = [0,1,2]
label_x_axis = ['2019', '2020', '2021']
plt.plot(x_axis, [total_2019, total_2020, total_2021], marker = "*")
plt.axvline(x=0.5, color='r', linestyle='--', linewidth=3)
plt.xticks(x_axis, label_x_axis)
plt.title('연도별 버스 이용률')
plt.show()
#%%
# 2019년 6월까지의 데이터와 2022년 6월까지의 데이터 비교하기
plt.figure(figsize=(10,8))
x_axis = [0,1]
label_x_axis = ['2019년 6월까지', '2022년 6월까지']
plt.plot(x_axis, [total_2019_6, total_2022_6], marker = "*")
plt.axvline(x=0.5, color='r', linestyle='--', linewidth=3)
plt.xticks(x_axis, label_x_axis)
plt.title('연도별 버스 이용률')
plt.show()
#%%
# 2019 & 2020 & 2021 & 2022년 6월까지의 데이터 비교하기
#%%
# 월 별로 데이터 분석해보기
years = [2019, 2020, 2021, 2022]
months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

month_2019 = []
month_2020 = []
month_2021 = []
month_2022 = []
for year in years :
    for month in months :
        if(year == 2022 and month == 7) :
            break
        temp = data.loc[(data['연도'] ==year) & (data['월'] == month), '승차인원']
        exec("month_{}.append(temp)".format(year))

# 2019 - 2020 - 2021 - 2022 월 별로 데이터 시각화
plt.figure(figsize=(10,8))
x_axis = [i for i in range(12)]
label_x_axis = [str(i) + '월' for i in range(12)]
plt.xticks(x_axis, label_x_axis)
plt.plot(x_axis, month_2019, color = 'red', label = '2019', marker = "*")
plt.plot(x_axis, month_2020, color = 'blue', label = '2020', marker = "*")
plt.plot(x_axis, month_2021, color = 'green', label = '2021', marker = "*")
plt.plot([0, 1, 2, 3, 4, 5], month_2022, color = 'violet', label = '2022', marker = "*")
plt.title('월별 버스 이용률')
plt.legend()
plt.show()
#%%


#!/usr/bin/env python
# -*- coding:utf8 -*-
"""
    @author:huang xiaoqin
    @time: 2020/7/22
    @desc:
"""
class Solution(object):
    # def fourSum(self, nums, target):
    #     nums.sort()
    #     results = []
    #     self.findNsum(nums, target, 4, [], results)
    #     return results
    #
    # def findNsum(self, nums, target, N, result, results):
    #     if len(nums) < N or N < 2: return
    #
    #     # solve 2-sum
    #     if N == 2:
    #         l,r = 0,len(nums)-1
    #         while l < r:
    #             if nums[l] + nums[r] == target:
    #                 results.append(result + [nums[l], nums[r]])
    #                 l += 1
    #                 r -= 1
    #                 while l < r and nums[l] == nums[l - 1]:
    #                     l += 1
    #                 while r > l and nums[r] == nums[r + 1]:
    #                     r -= 1
    #             elif nums[l] + nums[r] < target:
    #                 l += 1
    #             else:
    #                 r -= 1
    #     else:
    #         for i in range(0, len(nums)-N+1):   # careful about range
    #             if target < nums[i]*N or target > nums[-1]*N:  # take advantages of sorted list
    #                 break
    #             if i == 0 or i > 0 and nums[i-1] != nums[i]:  # recursively reduce N
    #                 self.findNsum(nums[i+1:], target-nums[i], N-1, result+[nums[i]], results)
    #     return

    def threeSum(self, nums, target):
        rs = []
        for i in range(len(nums) - 2):
            if target - nums[i] < 2 * nums[i + 1]:
                break
            if target - nums[i] > 2 * nums[len(nums) - 1]:
                continue
            if i > 0 and nums[i] == nums[i - 1]: continue
            l, r = i + 1, len(nums) - 1
            while l < r:
                if nums[i] + nums[l] + nums[r] == target:
                    rs.append([nums[i], nums[l], nums[r]])
                    # 跳过重复
                    while l < r and nums[l] == nums[l + 1]:
                        l += 1
                    while l < r and nums[r] == nums[r - 1]:
                        r -= 1
                    l += 1
                    r -= 1
                elif nums[i] + nums[l] + nums[r] > target:
                    r -= 1
                else:
                    l += 1
        return rs

    def fourSum(self, nums, target):
        nums.sort()
        results = []
        for i in range(len(nums) - 3):
            if i > 0 and nums[i] == nums[i - 1]: continue
            if target - nums[i] < 3 * nums[i + 1]:
                break
            if target - nums[i] > 3 * nums[len(nums) - 1]:
                continue
            rs = self.threeSum(nums[i + 1:], target - nums[i])
            for sub in rs:
                results.append(sub+[nums[i]])
        return results

if __name__ == '__main__':
    sol = Solution()
    print(sol.fourSum([-1,-5,-5,-3,2,5,0,4], -7))


from rest_framework import serializers
from rest_framework.fields import SlugField

from api.models import (
    TrainingConfiguration,
    TrainingTask
)

class TrainingConfigurationSerializer(serializers.ModelSerializer):
    class Meta:
        model = TrainingConfiguration
        fields = (
            'id', 'algorithm', 'dockerfile', 'created_on',
        )

    algorithm = SlugField(label='name', required=False)
    dockerfile = SlugField(label='name', required=False)

class TrainingTaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = TrainingTask
        fields = (
            'training_configuration',
            'id',
            'status',
            'created_on',
            'started_on',
            'terminated_on',
            'failure_message',
            'test_loss',
            'test_accuracy',
            'docker_id',
        )

    docker_id = serializers.CharField(allow_null=True)
    failure_message = serializers.CharField(allow_blank=True)
    id = serializers.IntegerField(read_only=True)
    training_configuration = serializers.PrimaryKeyRelatedField(read_only=True)
    started_on = serializers.DateTimeField(allow_null=True)
    terminated_on = serializers.DateTimeField(allow_null=True)


#Importa bibliotecas
import smbus2 as smbus
import time

#Inicia SMbus
bus = smbus.SMBus(1)

#Define endereço do arduino
slaveAddress = 0x08

#Funcao que faz o request dos valores do arduino
def RequestArduinoData():
	#le valor do arduino
	data_received_Arduino = bus.read_byte ( slaveAddress)
	print(data_received_Arduino)

while 1:
	#Requisita valor do arduino e aguarda 250ms
	RequestArduinoData()
	time.sleep(0.25)


# libs
import os
from dotenv import load_dotenv

# carrega variáveis de ambiente no script
load_dotenv()

# carrega a variável da chave de api no script
API_KEY_LEADS_SIGA = os.environ.get("API_KEY_LEADS_SIGA")
URL_SIGA = os.environ.get("URL_SIGA")
def get_siga(chave:str = API_KEY_LEADS_SIGA):
    import requests
    #Conexão com api siga.
    params={
        "chave_abrasel":chave,
        "accept" : "*",
        }
    response = requests.get(URL_SIGA,headers=params, verify=False)
    data = response.json()
    base = []
    for d in data:
        base.append({
            "SEC_REG": d.get("S/R", "não informado").upper(),
            "NOME_FANTASIA": d.get("Nome Fantasia", ""),
            "CNPJ": d.get("CNPJ", "não informado"),
            "ENDERECO": f"{d.get('Logradouro', '')}, {d.get('Numero', 'SN')} {d.get('Comp.', '')}".upper(),
            "BAIRRO": d.get("Bairro", "não informado"),
            "CEP": d.get("CEP", "não informado"),
            "CIDADE": d.get("Cidade", "não informado"),
            "UF": d.get("UF", "não informado"),
            "ASSOCIADO": d["Status"].upper(),
            "SOU_ABRASEL": d["Status_SouAbrasel"].upper()
        })

    return base

#Visualizar dados.
def visualizar_associados_ativos():
    import pandas as pd
    import duckdb as db
    associados=pd.DataFrame(get_siga())
    return db.query("""select * from associados """).to_df()


from django.shortcuts import render, get_object_or_404
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User, Group

from proyecto.decorators import *
from .forms import *
from actividades.funciones import *
from proyecto.models import RegistroPerfil, ProyectoDeGrado
from .funciones import *
from proyecto.funciones import comprobar

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente','tutor','tribunal'])
def revisiones(request, pk):
    usuario = request.user
    grupo = usuario.groups.get().name
    equipo = get_object_or_404(Equipo, id=pk)

    if comprobar(grupo, equipo, usuario):
        return HttpResponse('error')

    salas_documentos = SalaDocumentoDoc.objects.filter(revisor=usuario, equipo=equipo)

    is_perfil_habilitado = isActividad(equipo, "imprimir carta tutoria")
    is_perfil_terminado = isActividad(equipo, "imprimir formulario")
    is_proyecto_terminado = isActividad(equipo, "nota docente proyecto")
    is_vb_proyecto_tutor = isActividad(equipo, "visto bueno proyecto tutor")
    is_vb_perfil_tutor = isActividad(equipo, "visto bueno perfil tutor")

    context = {
        'grupo': grupo,
        'equipo': equipo,
        'salas_documentos': salas_documentos,
        'is_perfil_habilitado': is_perfil_habilitado,
        'is_perfil_terminado': is_perfil_terminado,
        'is_proyecto_terminado': is_proyecto_terminado,
        'is_vb_proyecto_tutor': is_vb_proyecto_tutor,
        'is_vb_perfil_tutor': is_vb_perfil_tutor,
    }
    return render(request, 'revisar_documentos/revisiones.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente','tutor'])
def configurar(request, pk):
    revisor = request.user
    grupo = revisor.groups.get().name
    equipo = get_object_or_404(Equipo, id=pk)

    if grupo=='docente':
        docente = revisor.datosdocente
        if not Equipo.objects.filter(docente=docente):
            return HttpResponse('error')

    configuracion, created = ConfiguracionSala.objects.get_or_create(usuario=revisor)
    salas = RevisarDocPersonalizado.objects.filter(usuario=revisor).order_by('orden')
    salas_pre = RevisarDocPredeterminado.objects.all().order_by('orden')
    suma_max = 0
    for sala in salas:
        suma_max += sala.nota_max

    context = {
        'grupo': grupo,
        'revisor': revisor,
        'equipo': equipo,
        'salas': salas,
        'salas_pre': salas_pre,
        'configuracion': configuracion,
        'suma_max': suma_max
    }
    if grupo == 'docente':
        return render(request, 'revisar_documentos/configurar.html', context)
    else:
        return render(request, 'revisar_documentos/configurar_revisor.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente', 'tutor'])
def cambiarPredeterminado(request, pk):
    revisor = request.user
    grupo = revisor.groups.get().name
    equipo = get_object_or_404(Equipo, id=pk)
    configuracion = ConfiguracionSala.objects.get(usuario=revisor)

    if grupo=='docente':
        docente = revisor.datosdocente
        if not Equipo.objects.filter(docente=docente):
            return HttpResponse('error')

    if request.method == 'POST':
        if configuracion.is_predeterminado == False:
            configuracion.is_predeterminado = True
            configuracion.save()
        else:
            configuracion.is_predeterminado = False
            configuracion.save()
        return redirect('revisar_documentos:configurar', pk=equipo.id)

    context = {
        'grupo': grupo,
        'revisor': revisor,
        'equipo': equipo,
    }

    return render(request, 'revisar_documentos/cambiar_predeterminado.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente','tutor','tribunal'])
def crearSalaPersonal(request, pk):
    revisor = request.user
    grupo = revisor.groups.get().name
    equipo = get_object_or_404(Equipo, id=pk)

    if grupo=='docente':
        docente = revisor.datosdocente
        if not Equipo.objects.filter(docente=docente):
            return HttpResponse('error')

    if grupo=='tutor':
        tutor = revisor.datostutor
        if not Equipo.objects.filter(tutor=tutor):
            return HttpResponse('error')

    if grupo=='docente':
        form = crearRevisarDocPersonalizadoForm()
    else:
        form = crearRevisarDocPersonalizadoRevisorForm()

    if request.method == 'POST':
        if grupo=='docente':
            form = crearRevisarDocPersonalizadoForm(request.POST)
        else:
            form = crearRevisarDocPersonalizadoRevisorForm(request.POST)
        if form.is_valid():
            form.instance.usuario = revisor
            form.instance.tipo = "proyecto"
            form.save()
            return redirect('revisar_documentos:configurar', pk=equipo.id)

    salas = RevisarDocPersonalizado.objects.filter(usuario=revisor, tipo='proyecto')
    suma_max = 0
    for sala in salas:
        suma_max += sala.nota_max

    context = {
        'grupo': grupo,
        'revisor': revisor,
        'equipo': equipo,
        'suma_max': suma_max,
        'form': form,
    }
    return render(request, 'revisar_documentos/crear_sala_personalizado.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente','tutor','tribunal'])
def eliminarSalaPersonal(request, pk_equipo, pk):
    revisor = request.user
    grupo = revisor.groups.get().name
    sala = get_object_or_404(RevisarDocPersonalizado, id=pk)
    equipo = get_object_or_404(Equipo, id=pk_equipo)

    if not RevisarDocPersonalizado.objects.filter(usuario=revisor):
        return HttpResponse('error')

    if request.method == 'POST':
        sala.delete()
        return redirect('revisar_documentos:configurar', pk=equipo.id)

    context = {
        'grupo': grupo,
        'revisor': revisor,
        'equipo': equipo,
    }
    return render(request, 'revisar_documentos/eliminar_sala.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente','tutor','tribunal'])
def modificarSalaPersonal(request, pk_equipo, pk):
    revisor = request.user
    grupo = revisor.groups.get().name
    sala = get_object_or_404(RevisarDocPersonalizado, id=pk)
    equipo = get_object_or_404(Equipo, id=pk_equipo)

    if not RevisarDocPersonalizado.objects.filter(usuario=revisor):
        return HttpResponse('error')

    if grupo=='docente':
        form = crearRevisarDocPersonalizadoForm(instance=sala)
    else:
        form = crearRevisarDocPersonalizadoRevisorForm(instance=sala)

    if request.method == 'POST':
        if grupo=='docente':
            form = crearRevisarDocPersonalizadoForm(request.POST, instance=sala)
        else:
            form = crearRevisarDocPersonalizadoRevisorForm(request.POST, instance=sala)
        if form.is_valid():
            form.save()
        return redirect('revisar_documentos:configurar', pk=equipo.id)

    salas = RevisarDocPersonalizado.objects.filter(usuario=revisor, tipo='proyecto')
    suma_max = 0
    for sala in salas:
        suma_max += sala.nota_max

    context = {
        'grupo': grupo,
        'revisor': revisor,
        'equipo': equipo,
        'suma_max': suma_max,
        'form': form,
    }
    return render(request, 'revisar_documentos/modificar_sala_personal.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['estudiante'])
def revisarDocumentoEstudiante(request, documento, id_revisor):
    usuario = request.user
    grupo = usuario.groups.get().name
    revisor = User.objects.get(id=id_revisor)
    estudiante = request.user.datosestudiante
    grupo_revisor = revisor.groups.get()
    sala_doc = SalaDocumentoDoc.objects.filter(revisor=revisor, grupo_revisor=grupo_revisor, equipo=estudiante.equipo, tipo=documento).first()
    salas_revisar = SalaRevisarDoc.objects.filter(sala_documento=sala_doc).order_by('-fecha_creacion')
    dicc_salas = {}
    for sala in salas_revisar:
        mensajes = MensajeRevisarDoc.objects.filter(sala=sala).exclude(usuario=usuario)
        no_visto = 0
        for mensaje in mensajes:
            if not mensaje.visto:
                no_visto += 1
        dicc_salas[sala] = no_visto
    suma = 0
    if grupo_revisor.name == 'docente' and sala_doc.tipo == 'proyecto' and salas_revisar.count() > 0:
        suma = 0
        for sala in salas_revisar:
            suma += sala.nota
    context = {
            'sala_doc':sala_doc,
            'dicc_salas':dicc_salas,
            'suma': suma,
            'grupo':grupo}
    return render(request, 'revisar_documentos/revisar_documento_estudiante.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['tutor','docente','tribunal'])
def revisarDocumentoRevisor(request, documento, id_equipo):
    grupo = request.user.groups.get().name
    revisor = request.user
    equipo = get_object_or_404(Equipo, id=id_equipo)
    grupo_revisor = revisor.groups.get()

    if documento=='proyecto' and not isActividad(equipo, "imprimir formulario"):
        return HttpResponse('error')
    if documento=='perfil' and not isActividad(equipo, "imprimir carta tutoria"):
        return HttpResponse('error')
    if documento=='proyecto' and grupo=="docente" and not isActividad(equipo, "visto bueno proyecto tutor"):
        return HttpResponse('error')

    sala_doc, created = SalaDocumentoDoc.objects.get_or_create(revisor=revisor, grupo_revisor=grupo_revisor, equipo=equipo, tipo=documento)
    salas_revisar = SalaRevisarDoc.objects.filter(sala_documento=sala_doc).order_by('-fecha_creacion')

    dicc_salas = {}
    for sala in salas_revisar:
        mensajes = MensajeRevisarDoc.objects.filter(sala=sala).exclude(usuario=request.user)
        no_visto = 0
        for mensaje in mensajes:
            if not mensaje.visto:
                no_visto += 1
        dicc_salas[sala] = no_visto
    suma = 0
    suma_max = 0
    if grupo_revisor.name == 'docente' and sala_doc.tipo == 'proyecto' and salas_revisar.count() > 0:
        suma = 0
        for sala in salas_revisar:
            suma += sala.nota

        # suma de nota max
        suma_max = 0
        for sala in salas_revisar:
            suma_max += sala.nota_max

    context = {
            'sala_doc':sala_doc,
            'dicc_salas':dicc_salas,
            'equipo':equipo,
            'suma': suma,
            'suma_max': suma_max,
            'grupo':grupo}

    return render(request, 'revisar_documentos/revisar_documento_revisor.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['tutor','docente','tribunal'])
def modificarNotaMax(request, id_sala):
    grupo = request.user.groups.get().name
    revisor = request.user
    sala_revisar = get_object_or_404(SalaRevisarDoc, id=id_sala)
    if sala_revisar.is_calificado:
        return HttpResponse('error')
    documento = sala_revisar.sala_documento.tipo
    equipo = sala_revisar.sala_documento.equipo

    salas_revisar = sala_revisar.sala_documento.salarevisardoc_set.all()
    # suma de nota max
    suma_max = 0
    for sala in salas_revisar:
        suma_max += sala.nota_max

    form = NotaMaxForm(instance=sala_revisar)
    if request.method == 'POST':
        form = NotaMaxForm(request.POST, instance=sala_revisar)
        if form.is_valid():
            form.save()
            return redirect('revisar_documentos:revisar_documento_revisor', documento=documento, id_equipo=equipo.id)
    context = {
            'form': form,
            'suma': suma_max,
            'grupo': grupo,}

    return render(request, 'revisar_documentos/modificar_nota_max.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente', 'tutor', 'tribunal'])
def crearSalaRevisar(request, documento, id_sala_doc):
    sala_doc = SalaDocumentoDoc.objects.get(id=id_sala_doc)
    equipo = sala_doc.equipo
    primer_estudiante = equipo.datosestudiante_set.first()
    grupo = request.user.groups.get().name
    salas_revisar = sala_doc.salarevisardoc_set.all()
    form = SalaRevisarDocForm
    if request.method == 'POST':
        form = SalaRevisarDocForm(request.POST, request.FILES)
        if form.is_valid():
            form.instance.sala_documento = sala_doc
            form.save()
            return redirect('revisar_documentos:revisar_documento_revisor', documento=sala_doc.tipo, id_equipo=equipo.id)
    suma_max = 0
    for sala in salas_revisar:
        suma_max += sala.nota_max

    context = {'form':form,
            'suma_max': suma_max,
            'grupo': grupo}
    return render(request, 'revisar_documentos/crear_sala_revisar.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente', 'tutor', 'tribunal'])
def crearSalaSinNota(request, documento, id_sala_doc):
    sala_doc = SalaDocumentoDoc.objects.get(id=id_sala_doc)
    equipo = sala_doc.equipo
    primer_estudiante = equipo.datosestudiante_set.first()
    grupo = request.user.groups.get().name
    form = SalaRevisarDocSinNotaForm
    if request.method == 'POST':
        form = SalaRevisarDocSinNotaForm(request.POST, request.FILES)
        if form.is_valid():
            form.instance.sala_documento = sala_doc
            form.save()
            return redirect('revisar_documentos:revisar_documento_revisor', documento=sala_doc.tipo, id_equipo=equipo.id)

    context = {'form':form,
            'grupo': grupo}

    return render(request, 'revisar_documentos/crear_sala_sin_nota.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente', 'tutor', 'tribunal'])
def eliminarSalaRevisar(request, id_sala_rev):
    sala_rev = SalaRevisarDoc.objects.get(id=id_sala_rev)
    if not sala_rev.sala_documento.revisor == request.user:
        return HttpResponse('error')
    if sala_rev.is_calificado:
        return HttpResponse('error')
    documento = sala_rev.sala_documento.tipo
    id_equipo = sala_rev.sala_documento.equipo.id
    grupo = request.user.groups.get().name
    if request.method == 'POST':
        sala_rev.delete()
        return redirect('revisar_documentos:revisar_documento_revisor', documento=documento, id_equipo=id_equipo)
    context = {
            'grupo': grupo}
    return render(request, 'revisar_documentos/eliminar_sala.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente', 'tutor', 'tribunal'])
def cerrarSalaRevisar(request, id_sala_rev):
    sala_rev = SalaRevisarDoc.objects.get(id=id_sala_rev)

    if not sala_rev.sala_documento.revisor == request.user:
        return HttpResponse('error')
    if sala_rev.is_calificado:
        return HttpResponse('error')

    documento = sala_rev.sala_documento.tipo
    id_equipo = sala_rev.sala_documento.equipo.id
    grupo = request.user.groups.get().name

    if request.method == 'POST':
        sala_rev.is_calificado = True
        sala_rev.save()
        return redirect('revisar_documentos:revisar_documento_revisor', documento=documento, id_equipo=id_equipo)

    context = {
        'grupo': grupo,
        'sala': sala_rev,
    }

    return render(request, 'revisar_documentos/cerrar_sala.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['estudiante'])
def subirDocumento(request, pk):
    sala_revisar = SalaRevisarDoc.objects.get(id=pk)
    estudiante = request.user.datosestudiante
    documento = sala_revisar.sala_documento.tipo
    revisor = sala_revisar.sala_documento.revisor
    grupo_revisor = sala_revisar.sala_documento.grupo_revisor.name
    equipo = estudiante.equipo
    if sala_revisar.sala_documento.equipo != equipo:
        return HttpResponse('error')
    grupo = request.user.groups.get().name
    form = SubirDocumentoForm(instance=sala_revisar)
    if request.method == 'POST':
        form = SubirDocumentoForm(request.POST, request.FILES, instance=sala_revisar)
        if form.is_valid():
            form.save()
            if grupo_revisor == "tribunal":
                tribunales = equipo.tribunales.all()
                if revisor.datostribunal == tribunales[0]:
                    numero = '1'
                else:
                    numero = '2'
                agregarAviso('revisar '+ documento + ' ' + numero, equipo, revisor)
                agregarActividadEquipo('revisar ' + documento + ' ' + numero, equipo)
            else:
                agregarAviso('revisar '+ documento + ' ' + grupo_revisor, equipo, revisor)
                agregarActividadEquipo('revisar ' + documento + ' ' + grupo_revisor, equipo)
            return redirect('revisar_documentos:revisar_documento_estudiante', documento=documento, id_revisor=revisor.id)
    context = {'form':form,
            'grupo': grupo}
    return render(request, 'revisar_documentos/subir_documento.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente'])
def calificarSalaRevision(request, pk):
    usuario = request.user
    grupo = usuario.groups.get().name
    sala_revisar = get_object_or_404(SalaRevisarDoc, id=pk)
    if sala_revisar.is_calificado:
        return HttpResponse('error')
    documento = sala_revisar.sala_documento
    equipo = documento.equipo
    equipo = sala_revisar.sala_documento.equipo
    form = NotaSalaRevisarDocForm(instance=sala_revisar)
    if request.method == 'POST':
        form = NotaSalaRevisarDocForm(request.POST, instance=sala_revisar)
        if form.is_valid():
            form.instance.is_calificado = True
            form.save()
            # return redirect('progreso_estudiante',pk=equipo.pk)
            return redirect('revisar_documentos:revisar_documento_revisor', documento=documento.tipo, id_equipo=equipo.id)
    sala_documento = SalaDocumentoDoc.objects.get(revisor=usuario, equipo=equipo, tipo='proyecto')
    numero_salas = sala_documento.salarevisardoc_set.count()
    salas_revisar = sala_documento.salarevisardoc_set.all()
    suma = 0
    for sala in salas_revisar:
        suma += sala.nota

    context = {
            'grupo':grupo,
            'sala_revisar': sala_revisar,
            'equipo': equipo,
            'form': form,
            'suma': suma,
            }
    return render(request, 'revisar_documentos/calificar_sala_revision.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['tutor','docente','tribunal','estudiante'])
def mensajes(request, id_sala_rev):
    usuario = request.user
    grupo = usuario.groups.get()
    sala = SalaRevisarDoc.objects.get(id=id_sala_rev)
    ultima_sala = sala.sala_documento.salarevisardoc_set.all().last()
    is_ultima_sala = sala == ultima_sala
    form = MensajeRevisarDocForm
    if request.method == "POST":
        form= MensajeRevisarDocForm(request.POST)
        if form.is_valid():
            file = form.save(commit=False)
            file.sala = sala
            file.usuario = usuario
            file.save()
        return redirect('revisar_documentos:mensajes', id_sala_rev=id_sala_rev)
    mensajes = MensajeRevisarDoc.objects.filter(sala=sala).order_by('-fecha_creacion')
    mensajes_no_vistos = MensajeRevisarDoc.objects.filter(sala=sala, visto=False).exclude(usuario=usuario)
    for mensaje in mensajes_no_vistos:
        mensaje.visto = True
        mensaje.save()
    context = {
            'form':form,
            'mensajes':mensajes,
            'sala':sala,
            'grupo':grupo.name,
            'is_ultima_sala':is_ultima_sala,
            }
    return render(request, 'revisar_documentos/mensajes.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['tutor','docente','tribunal'])
def darVistoBueno(request, id_sala_doc):
    sala_doc = get_object_or_404(SalaDocumentoDoc, id=id_sala_doc)
    salas_revisar = SalaRevisarDoc.objects.filter(sala_documento=sala_doc)
    grupo_revisor = sala_doc.revisor.groups.get().name
    grupo = request.user.groups.get().name
    equipo = sala_doc.equipo
    # suma de nota max
    suma_max = 0
    for sala in salas_revisar:
        suma_max += sala.nota_max
    # calificacion
    for sala in salas_revisar:
        if sala.nota == 0:
            is_calificacion_todo = False
        else:
            is_calificacion_todo = True

    # cerrados, utilizare el is_calificado para este fin.
    vector_is_calificado = [v.is_calificado for v in salas_revisar]
    is_cerrado = all(vector_is_calificado)

    if grupo_revisor == 'tribunal':
        if actividadRealizadaEstudiante("visto bueno tribunal 1", sala_doc.equipo.datosestudiante_set.first()):
            texto_actividad = f"visto bueno {sala_doc.tipo} 2"
        else:
            texto_actividad = f"visto bueno {sala_doc.tipo} 1"
    else:
        texto_actividad = f"visto bueno {sala_doc.tipo} {sala_doc.revisor.groups.get()}"

    if request.method == 'POST':
        # if grupo_revisor == 'docente':
            # if sala_doc.tipo == 'perfil':
                # RegistroPerfil.objects.create(
                    # equipo = sala_doc.equipo,
                    # perfil = sala_doc.salarevisardoc_set.last().archivo_corregir,
                # )
            # elif sala_doc.tipo == 'proyecto':
                # suma = 0
                # for sala in salas_revisar:
                    # suma += sala.nota
                # proyecto, created = ProyectoDeGrado.objects.get_or_create(equipo=equipo)
                # proyecto.nota_informes_trabajo = suma
                # proyecto.archivo = sala_doc.salarevisardoc_set.last().archivo_corregir
                # proyecto.save()
        # agregarActividadEquipo('revisar proyecto', equipo)
        if grupo_revisor == 'docente' and sala_doc.tipo == "proyecto":
            suma = 0
            for sala in salas_revisar:
                suma += sala.nota
            proyecto, created = ProyectoDeGrado.objects.get_or_create(equipo=equipo)
            proyecto.nota_informes_trabajo = suma
            proyecto.save()
        sala_doc.visto_bueno = True
        sala_doc.save()
        agregarActividadEquipo(texto_actividad, sala_doc.equipo)
        return redirect('progreso_estudiante', pk=sala_doc.equipo.id)
    registro_perfil, created = RegistroPerfil.objects.get_or_create(
        equipo=sala_doc.equipo)
    registro_proyecto, created = ProyectoDeGrado.objects.get_or_create(
        equipo=sala_doc.equipo)
    context = {'sala_doc': sala_doc,
            'suma_max': suma_max,
            'is_calificacion_todo': is_calificacion_todo,
            'is_cerrado': is_cerrado,
            'registro_perfil': registro_perfil,
            'registro_proyecto': registro_proyecto,
            'grupo': grupo,
            }
    return render(request, 'revisar_documentos/dar_visto_bueno.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['tutor','docente','tribunal'])
def registrarDocumento(request, id_sala_doc):
    sala_doc = get_object_or_404(SalaDocumentoDoc, id=id_sala_doc)
    grupo = request.user.groups.get().name
    equipo = sala_doc.equipo
    if sala_doc.tipo == "perfil":
        perfil = RegistroPerfil.objects.get(equipo=equipo)
        form = RegistroPerfilForm(instance=perfil)
        if request.method == 'POST':
            form = RegistroPerfilForm(request.POST, request.FILES, instance=perfil)
            if form.is_valid():
                form.save()
                if grupo == 'docente':
                    agregarActividadEquipo('registro perfil', equipo)
                return redirect('revisar_documentos:dar_visto_bueno', id_sala_doc=sala_doc.id)
    elif sala_doc.tipo == "proyecto":
        proyecto = ProyectoDeGrado.objects.get(equipo=equipo)
        form = RegistroProyectoDeGradoForm(instance=proyecto)
        if request.method == 'POST':
            form = RegistroProyectoDeGradoForm(request.POST, request.FILES, instance=proyecto)
            if form.is_valid():
                form.save()
                if grupo == 'docente':
                    agregarActividadEquipo('registro proyecto', equipo)
                return redirect('revisar_documentos:dar_visto_bueno', id_sala_doc=sala_doc.id)

    context = {
            'sala_doc': sala_doc,
            'form': form,
            'grupo': grupo,
            }
    return render(request, 'revisar_documentos/registrar_documento.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente',])
def calificarSeminario(request, pk):
    grupo = request.user.groups.get().name
    equipo = get_object_or_404(Equipo, id=pk)
    proyecto, created = ProyectoDeGrado.objects.get_or_create(equipo=equipo)
    nota = proyecto.nota_expos_seminarios
    context = {
        'grupo':grupo,
        'nota': nota,
        'pk':pk,
    }
    return render(request, 'revisar_documentos/calificar_seminario.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente',])
def registrarParticipacionSeminario(request, pk):
    grupo = request.user.groups.get().name
    equipo = get_object_or_404(Equipo, id=pk)
    proyecto, created = ProyectoDeGrado.objects.get_or_create(equipo=equipo)
    nota = proyecto.nota_expos_seminarios
    if nota == 6:
        return redirect('revisar_documentos:calificar_seminario', pk=pk)
    if request.method == 'POST':
        proyecto.nota_expos_seminarios = nota + 2
        proyecto.save()
        return redirect('revisar_documentos:calificar_seminario', pk=pk)
    context = {
        'grupo':grupo,
        'nota': nota,
        'pk':pk,
    }
    return render(request, 'revisar/registrar_seminario.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente',])
def calificarCronograma(request, pk):
    grupo = request.user.groups.get().name
    equipo = get_object_or_404(Equipo, id=pk)
    proyecto, created = ProyectoDeGrado.objects.get_or_create(equipo=equipo)
    nota = proyecto.nota_cumplimiento_cronograma
    context = {
        'grupo':grupo,
        'nota': nota,
        'pk':pk,
    }
    return render(request, 'revisar_documentos/calificar_cronograma.html', context)

@login_required(login_url='login')
@allowed_users(allowed_roles=['docente',])
def registrarCumplimientoCronograma(request, pk):
    grupo = request.user.groups.get().name
    equipo = get_object_or_404(Equipo, id=pk)
    proyecto, created = ProyectoDeGrado.objects.get_or_create(equipo=equipo)
    nota = proyecto.nota_cumplimiento_cronograma
    if nota == 3:
        return redirect('revisar_documentos:calificar_cronograma', pk=pk)
    if request.method == 'POST':
        proyecto.nota_cumplimiento_cronograma = nota + 1
        proyecto.save()
        return redirect('revisar_documentos:calificar_cronograma', pk=pk)
    context = {
        'grupo':grupo,
        'nota': nota,
        'pk':pk,
    }
    return render(request, 'revisar_documentos/registrar_cronograma.html', context)


'''
109. Convert Sorted List to Binary Search Tree
Medium
6.6K
141
Companies
Given the head of a singly linked list where elements are sorted in ascending order, convert it to a
height-balanced
 binary search tree.

Example 1:

Input: head = [-10,-3,0,5,9]
Output: [0,-3,9,-10,null,5]
Explanation: One possible answer is [0,-3,9,-10,null,5], which represents the shown height balanced BST.
Example 2:

Input: head = []
Output: []

Constraints:

The number of nodes in head is in the range [0, 2 * 104].
-105 <= Node.val <= 105
Accepted
461.3K
Submissions
771.2K
Acceptance Rate
59.8%
'''

# Definition for singly-linked list.
from typing import Optional

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def getArrayFromLinkedList(self, head):
        cursor = head
        arr = []
        while cursor:
            arr.append(cursor.val)
            cursor = cursor.next
        return arr

    def getBST(self, arr, node):
        if len(arr) == 0:
            return None
        mid = (len(arr) - 1) // 2
        node.val = arr[mid]
        node.left = self.getBST(arr[:mid], TreeNode())
        node.right = self.getBST(arr[mid + 1:], TreeNode())
        return node

    def sortedListToBST(self, head: Optional[ListNode]) -> Optional[TreeNode]:
        return self.getBST(self.getArrayFromLinkedList(head), TreeNode())


import scipy.io as sio
import numpy as np
from liegroups import SE3, SO3

def load_data_1(data_filename):
    #Data loader for Emmett's Synethetic datasets
    data_dict = sio.loadmat(data_filename)
    pose_array = data_dict['T_vki_list']
    T_vki = [SE3.from_matrix(pose_array[i, :, :]) for i in range(pose_array.shape[0])]
    pose_array = data_dict['T_ci_list']
    T_ci = [SE3.from_matrix(pose_array[i, :, :]) for i in range(pose_array.shape[0])]
    extcal = data_dict['extcal']
    return T_vki, T_ci, extcal

def load_data_from_numpy(data_filename):
    pose_array = np.load(data_filename)
    T = [SE3.from_matrix(pose_array[i, :, :]) for i in range(pose_array.shape[0])]

    return T

def load_data_from_txt(data_filename):
    raw_data = np.loadtxt(data_filename)
    mat_list = []
    for row in range(raw_data.shape[0]):
        matrix = np.eye(4)
        matrix[:3, :] = np.reshape(raw_data[row, :], (3, 4))
        mat_list.append(matrix)

    T = [SE3.from_matrix(mat_list[i]) for i in range(len(mat_list))]

    return T

def load_brookshire_data(data_filename):
    data_dict = sio.loadmat(data_filename)
    pose_array = data_dict['T_v_rel_list']
    T_v_rel = [SE3.from_matrix(pose_array[:, :, i]) for i in range(pose_array.shape[2])]
    pose_array = data_dict['T_c_rel_list']
    T_c_rel = [SE3.from_matrix(pose_array[:, :, i]) for i in range(pose_array.shape[2])]
    extcal = data_dict['extcal']
    return T_v_rel, T_c_rel, extcal

def results_saver(data_filename, results):
    results_name_base = data_filename.replace(".mat", "")
    keys = results.keys()
    for key in keys:
        results_dict = results[key]
        results_filename = results_name_base + "_" + key + ".mat"
        sio.savemat(results_filename, results_dict)
    return

def print_brookshire_results():
    results = sio.loadmat("../results/brookshire_data_RCH.mat")
    print(results["dual_trans_error"])
    print(results["dual_rot_error"])
    print(results["dual_alpha_error"])
    print(results["rel_trans_error"])
    print(results["rel_rot_error"])
    print(results["rel_alpha_error"])
    return

def results_loader(prefixes, dataset_name, constraints):
    data_dict = {}
    for prefix in prefixes:
        prefix_dict = {}
        for constraint in constraints:
            filename = "../results/" + prefix + "_" + dataset_name + "_" + constraint
            prefix_dict[constraint] =sio.loadmat(filename)
        data_dict[prefix] = prefix_dict
    return data_dict

def inertial_to_relative(pose_list, offset=1, reverse=False):
    #Changes SE3 poses from relative to intertial to relative vs timestamps
    if not reverse:
        rel_pose_list = [pose_list[i].dot(pose_list[i + offset].inv()) for i in range(0, len(pose_list) - offset, offset)] #This makes the poses T_{s_is_i+1}
    else:
        rel_pose_list = [pose_list[i].inv().dot(pose_list[i + offset]) for i in range(0, len(pose_list) - offset, offset)] #This makes the poses T_{s_is_i+1}

    return rel_pose_list

def inertial_to_relative_numpy(pose_list, offset=1):
    rel_pose_list = [pose_list[i].dot(np.linalg.inv(pose_list[i + offset])) for i in range(0, len(pose_list) - offset, offset)]

    return rel_pose_list

def add_noise(pose_list, trans_noise, rot_noise):
    ''' Add Noise to the pose measurements as a percentage of the translation and rotation magnitude'''
    #Create the translation noise vectors
    trans_noise_sigma = trans_noise * np.linalg.norm(np.array([pose.trans  for pose in pose_list]), axis=1)
    trans_noise_vec = [np.random.randn((3))*trans_noise_sigma[i] for i in range(len(pose_list))]

    #Create the rotation noise vectors
    rot_noise_sigma = rot_noise *np.linalg.norm(np.array([pose.rot.log()  for pose in pose_list]), axis=1)
    rot_noise_unit_vecs = np.random.rand(3, len(pose_list))
    rot_noise_unit_vecs=  rot_noise_unit_vecs/ np.linalg.norm(rot_noise_unit_vecs, axis=0)
    rot_noise_vec = [rot_noise_sigma[i] * np.random.randn() * rot_noise_unit_vecs[:, i]  for i in range(len(pose_list))]

    #Add the noise to the poses
    noisy_poses = [SE3(rot=SO3.exp(rot_noise_vec[i]).dot(pose.rot), trans=pose.trans + trans_noise_vec[i]) for i, pose in enumerate(pose_list)]

    return noisy_poses


import pandas as pd
import numpy as np
from sklearn.metrics import r2_score
import statsmodels.api as sm

pizza = pd.read_csv("pizza.csv")

X = pizza['Promote']
X = sm.add_constant(X)
y = pizza['Sales']
model = sm.OLS(y,X)
results = model.fit()

print(results.params)
print(results.summary())

### Credit Approval
import os
os.chdir(r"C:\Training\Academy\Business Analytics 3e Resources\Excel Datasets\eba3e_datasets_xls")
cred = pd.read_excel("CreditApprovalDecisions.xlsx",sheet_name="Data",
                     usecols="A:F",skiprows=2)
X = cred[['Years of Credit History',
          'Revolving Balance', 'Revolving Utilization']]
y = cred['Credit Score']

X = sm.add_constant(X)

model = sm.OLS(y,X)
results = model.fit()

print(results.params)
print(results.summary())

StudetDataBackup/8. Covariance Correlation & Regression/sm_ols.py