import requests
import time

from urllib.robotparser import RobotFileParser
from urllib.parse import urlparse
from urllib.error import URLError

from file_io_handler import FileHandler
from sql_io_handler import SQLHandler
from io_handler import CacheData
from titles_request_processor import TitlesProcessor

class Crawler:
    def __init__(self, index):
        self._index = index
        self._useragent = "jwli"

        self._io_handler = SQLHandler(index)
        self._rp = RobotFileParser()
        self._request_processor = TitlesProcessor(self._io_handler)

        self._stop_crawl = False

    def crawl(self):
        print(f"Crawler {self._index} started")

        while True:
            url = self._get_next_url()
            if url == None:
                time.sleep(0.1)
                continue

            self._process_url(url)

            self._io_handler.dump()

            if self._check_stop_crawling():
                break

            time.sleep(1.0)

        print(f"Crawler {self._index} terminated")

    def stop_crawl(self):
        self._stop_crawl = True

    def _process_url(self, url):
        self._record_visit(url)

        try:
            req = requests.get(url)
        except:
            return

        self._request_processor.process(req)

    def _get_next_url(self):
        lines = self._io_handler.read_queue()

        for line in lines:
            allow_crawl = self._get_allow_crawl(line)

            if allow_crawl == -1:
                self._io_handler.erase_from_queue(line)
            if allow_crawl == 1:
                self._io_handler.erase_from_queue(line)
                return line

        return None

    def _get_domain(self,url):
        netloc = urlparse(url).netloc
        split = netloc.split(".")
        domain = split[len(split) - 2] + "." + split[len(split) - 1]

        return domain

    def _get_allow_crawl(self, url):
        cache_data = self._io_handler.read_cache(self._get_domain(url))

        if cache_data.cache_hit:
            if time.time() > cache_data.last_visited + cache_data.crawl_delay:
                return 1
        else:
            self._rp.set_url(url)
            try:
                self._rp.read()
                if not self._rp.can_fetch(self._useragent,url):
                    return -1
            except:
                return -1

            crawl_delay = self._rp.crawl_delay(self._useragent)
            if crawl_delay == None:
                crawl_delay = 5

            self._io_handler.write_cache(self._get_domain(url), time.time(), crawl_delay)
            return 0

        return 0

    def _record_visit(self,url):
        self._io_handler.record_visit_in_cache(self._get_domain(url), time.time())

    def _check_stop_crawling(self):
        return self._stop_crawl or (self._io_handler.count_pages() >= 1000)


import os
import numpy as np
import random
from tqdm import tqdm
from torch.utils.data import Dataset
from medvqa.datasets.chest_imagenome import CHEST_IMAGENOME_NUM_BBOX_CLASSES
from medvqa.datasets.chest_imagenome.chest_imagenome_dataset_management import (
    get_dicomId2gender,
    load_chest_imagenome_silver_bboxes_as_numpy_array,
    load_chest_imagenome_label_names,
)
from medvqa.datasets.dataloading_utils import INFINITE_DATASET_LENGTH
from medvqa.datasets.mimiccxr.mimiccxr_vision_dataset_management import (
    _AlbumentationAdapter,
    _BalancedSamplingMode,
    _create_dataset_and_dataloader,
    _define_allowed_dicom_ids,
    _load_chest_imagenome_labels,
)
from medvqa.datasets.mimiccxr import (
    MIMICCXR_CACHE_DIR,
    MIMICCXR_IMAGE_ORIENTATIONS,
    MIMICCXR_ImageSizeModes,
    MIMICCXR_ViewModes,
    get_dicom_id_and_orientation_list,
    get_image_path_getter,
    load_mimiccxr_reports_detailed_metadata,
)
from medvqa.utils.files import get_cached_pickle_file
from medvqa.utils.logging import print_bold, print_magenta, print_orange

class MIMICCXR_Image2Report_Dataset(Dataset):
    def __init__(self, indices, reports, report_ids, image_paths, image_transform,
                data_augmentation_enabled=False,
                shuffle=False,
                infinite=False,
                # aux task: genders
                classify_gender=False,
                genders=None,
                # aux task: chexpert labels
                classify_chexpert=False,
                chexpert_labels=None,
                # aux task: chest imagenome labels
                classify_chest_imagenome=False,
                chest_imagenome_labels=None,
                # aux task: chest imagenome bboxes
                predict_bboxes_chest_imagenome=False,
                dicom_idxs=None,
                gt_bbox_coords=None,
                gt_bbox_presence=None,
                flipped_gt_bbox_coords=None, # for data augmentation
                flipped_gt_bbox_presence=None, # for data augmentation
                horizontal_flip=False,
                # aux task: local feature coords
                predict_local_feature_coords=False,
                local_feature_coords=None,
                # yolov8
                use_yolov8=False,
            ):
        self.indices = indices
        self.reports = reports
        self.report_ids = report_ids
        self.data_augmentation_enabled = data_augmentation_enabled
        self.image_paths = image_paths
        self.image_transform = image_transform
        self.classify_gender = classify_gender
        self.genders = genders
        self.classify_chexpert = classify_chexpert
        self.chexpert_labels = chexpert_labels
        self.classify_chest_imagenome = classify_chest_imagenome
        self.chest_imagenome_labels = chest_imagenome_labels
        self.predict_bboxes_chest_imagenome = predict_bboxes_chest_imagenome
        self.dicom_idxs = dicom_idxs
        self.gt_bbox_coords = gt_bbox_coords
        self.gt_bbox_presence = gt_bbox_presence
        self.horizontal_flip = horizontal_flip
        self.flipped_gt_bbox_coords = flipped_gt_bbox_coords
        self.flipped_gt_bbox_presence = flipped_gt_bbox_presence
        self.use_yolov8 = use_yolov8
        self.predict_local_feature_coords = predict_local_feature_coords

        if self.predict_bboxes_chest_imagenome:
            assert self.gt_bbox_coords is not None
            assert self.gt_bbox_presence is not None

        if self.predict_bboxes_chest_imagenome:
            if self.data_augmentation_enabled:
                if horizontal_flip:
                    if self.predict_bboxes_chest_imagenome:
                        assert flipped_gt_bbox_coords is not None
                        assert flipped_gt_bbox_presence is not None
                num_bbox_classes = CHEST_IMAGENOME_NUM_BBOX_CLASSES
                self.albumentation_adapter = _AlbumentationAdapter(num_bbox_classes)

        if self.predict_local_feature_coords:
            assert local_feature_coords is not None
            self.local_feature_coords = local_feature_coords

        if shuffle:
            random.shuffle(self.indices) # shuffle in place
        self.infinite = infinite
        if infinite:
            self._len = INFINITE_DATASET_LENGTH
        else:
            self._len = len(self.indices)

    def __len__(self):
        return self._len

    def __getitem__(self, i):
        if self.infinite:
            i = i % len(self.indices)
        idx = self.indices[i]
        rid = self.report_ids[idx]
        output = { 'idx': idx, 'report': self.reports[rid] }
        image_path = self.image_paths[idx]
        # handle transform differently for chest imagenome bboxes
        if self.predict_bboxes_chest_imagenome:
            dicom_idx = self.dicom_idxs[idx]
            gt_bbox_coords = self.gt_bbox_coords[dicom_idx]
            gt_bbox_presence = self.gt_bbox_presence[dicom_idx]
            if self.data_augmentation_enabled: # data augmentation with albumentations
                if self.horizontal_flip:
                    tmp = self.image_transform(
                        image_path=image_path,
                        bboxes=gt_bbox_coords,
                        presence=gt_bbox_presence,
                        albumentation_adapter=self.albumentation_adapter,
                        flipped_bboxes=self.flipped_gt_bbox_coords[dicom_idx],
                        flipped_presence=self.flipped_gt_bbox_presence[dicom_idx],
                        return_image_size=self.use_yolov8,
                    )
                else:
                    tmp = self.image_transform(
                        image_path=image_path,
                        bboxes=gt_bbox_coords,
                        presence=gt_bbox_presence,
                        albumentation_adapter=self.albumentation_adapter,
                        return_image_size=self.use_yolov8,
                    )
                if self.use_yolov8:
                    image, gt_bbox_coords, gt_bbox_presence, image_size_before, image_size_after = tmp
                else:
                    image, gt_bbox_coords, gt_bbox_presence = tmp
            else: # no data augmentation
                tmp = self.image_transform(image_path, return_image_size=self.use_yolov8)
                if self.use_yolov8:
                    image, image_size_before, image_size_after = tmp
                else:
                    image = tmp
            assert len(gt_bbox_coords.shape) == 2
            output['chest_imagenome_bbox_coords'] = gt_bbox_coords
            output['chest_imagenome_bbox_presence'] = gt_bbox_presence
        elif self.use_yolov8:
            image, image_size_before, image_size_after = self.image_transform(image_path, return_image_size=True)
        else:
            image = self.image_transform(image_path)
        output['i'] = image
        if self.classify_gender:
            output['gender'] = self.genders[idx]
        if self.classify_chexpert:
            output['chexpert'] = self.chexpert_labels[rid]
        if self.classify_chest_imagenome:
            output['chest_imagenome'] = self.chest_imagenome_labels[rid]
        if self.predict_local_feature_coords:
            output['local_feature_coords'] = self.local_feature_coords
        if self.use_yolov8:
            # We need to adapt the output a little bit to make it compatible with YOLOv8
            output['im_file'] = image_path
            output['ori_shape'] = image_size_before
            output['resized_shape'] = image_size_after
            output['img'] = output['i']
            del output['i']
        return output

class MIMICCXR_Image2ReportTrainer():

    def __init__(self,
                qa_adapted_reports_filename, tokenizer, batch_size, collate_batch_fn, num_workers,
                train_image_transform=None,
                val_image_transform=None,
                use_test_set=False,
                use_all_data=False,
                use_chest_imagenome_bbox_gold_set=False,
                use_chest_imagenome_label_gold_set=False,
                use_val_set_only=False,
                test_image_transform=None,
                data_augmentation_enabled=False,
                horizontal_flip=False,
                source_image_size_mode=MIMICCXR_ImageSizeModes.SMALL_256x256,
                view_mode=MIMICCXR_ViewModes.ANY_SINGLE,
                use_decent_images_only=False,
                classify_gender=False,
                classify_chexpert=False,
                chexpert_labels_filename=None,
                classify_chest_imagenome=False,
                predict_bboxes_chest_imagenome=False,
                predict_labels_and_bboxes_chest_imagenome=False,
                clamp_bboxes_chest_imagenome=False,
                chest_imagenome_labels_filename=None,
                chest_imagenome_label_names_filename=None,
                balanced_sampling_mode=None,
                balanced_batch_size=None,
                use_yolov8=False,
                predict_local_feature_coords=False,
                local_features_width=None,
                local_features_height=None,
                **unused_kwargs,
            ):

        train_collate_batch_fn = lambda batch: collate_batch_fn(batch, training_mode=True)
        eval_collate_batch_fn = lambda batch: collate_batch_fn(batch, training_mode=False)

        if len(unused_kwargs) > 0:
            # Print warning in orange and bold
            print_orange('Warning: unused kwargs in MIMICCXR_Image2ReportTrainer: {}'.format(unused_kwargs), bold=True)
        # Sanity checks
        assert sum([use_test_set, use_val_set_only,
                    use_chest_imagenome_bbox_gold_set,
                    use_chest_imagenome_label_gold_set,
                    use_all_data]) <= 1 # at most one of these can be true
        if use_test_set or use_chest_imagenome_bbox_gold_set or use_chest_imagenome_label_gold_set or use_all_data:
            assert test_image_transform is not None
            assert not data_augmentation_enabled
        else:
            assert val_image_transform is not None
            if not use_val_set_only:
                assert train_image_transform is not None
        if classify_gender:
            assert view_mode == MIMICCXR_ViewModes.CHEST_IMAGENOME

        self.use_yolov8 = use_yolov8

        if chest_imagenome_label_names_filename is not None:
            self.chest_imagenome_label_names = load_chest_imagenome_label_names(chest_imagenome_label_names_filename)
        elif chest_imagenome_labels_filename is not None:
            self.chest_imagenome_label_names = load_chest_imagenome_label_names(
                chest_imagenome_labels_filename.replace('imageId2labels', 'labels'))
        else:
            self.chest_imagenome_label_names = None

        self.tokenizer = tokenizer
        self.qa_adapted_reports_filename = qa_adapted_reports_filename
        self.train_image_transform = train_image_transform
        self.val_image_transform = val_image_transform
        self.test_image_transform = test_image_transform
        self.data_augmentation_enabled = data_augmentation_enabled
        self.horizontal_flip = horizontal_flip
        self.batch_size = batch_size
        self.train_collate_batch_fn = train_collate_batch_fn
        self.eval_collate_batch_fn = eval_collate_batch_fn
        self.num_workers = num_workers

        BIG_ENOGUGH = 1000000
        dicom_ids = [None] * BIG_ENOGUGH
        image_paths = [None] * BIG_ENOGUGH
        report_ids = [None] * BIG_ENOGUGH
        orientations = [None] * BIG_ENOGUGH
        if use_all_data:
            all_indices = []
        elif use_test_set or use_chest_imagenome_bbox_gold_set or use_chest_imagenome_label_gold_set:
            test_indices = []
        else:
            train_indices = []
            val_indices = []
        idx = 0

        image_path_getter = get_image_path_getter(source_image_size_mode, verbose=True)

        allowed_dicom_ids = _define_allowed_dicom_ids(view_mode, use_all_data, use_test_set,
                                      use_chest_imagenome_bbox_gold_set, use_chest_imagenome_label_gold_set,
                                      use_decent_images_only)

        mimiccxr_metadata = load_mimiccxr_reports_detailed_metadata(qa_adapted_reports_filename, exclude_invalid_sentences=True)
        reports = [None] * len(mimiccxr_metadata['reports'])

        max_idx_count = 0

        if use_test_set or use_chest_imagenome_label_gold_set:
            tokenize_func = tokenizer.string2ids
        else:
            tokenize_func = tokenizer.tokenize

        for rid, (part_id, subject_id, study_id, report, dicom_id_view_pairs, split) in \
            tqdm(enumerate(zip(mimiccxr_metadata['part_ids'],
                mimiccxr_metadata['subject_ids'],
                mimiccxr_metadata['study_ids'],
                mimiccxr_metadata['reports'],
                mimiccxr_metadata['dicom_id_view_pos_pairs'],
                mimiccxr_metadata['splits'])), mininterval=2):

            max_idx_count += len(dicom_id_view_pairs)
            reports[rid] = tokenize_func(report)

            for dicom_id, view in get_dicom_id_and_orientation_list(dicom_id_view_pairs, view_mode, allowed_dicom_ids):
                dicom_ids[idx] = dicom_id
                image_paths[idx] = image_path_getter(part_id, subject_id, study_id, dicom_id)
                report_ids[idx] = rid
                orientations[idx] = MIMICCXR_IMAGE_ORIENTATIONS.index(view)
                if use_all_data:
                    all_indices.append(idx)
                elif use_test_set or use_chest_imagenome_bbox_gold_set or use_chest_imagenome_label_gold_set:
                    if use_test_set:
                        if split == 'test':
                            test_indices.append(idx)
                    else:
                        test_indices.append(idx)
                else:
                    if split == 'train':
                        train_indices.append(idx)
                    elif split == 'validate':
                        val_indices.append(idx)
                    elif split == 'test':
                        pass
                    else:
                        raise ValueError(f'Unknown split {split}')
                idx += 1

        print('max_idx_count =', max_idx_count)
        print('actual_idx_count =', idx)
        if idx < max_idx_count:
            print(f'** NOTE: {max_idx_count - idx} images were skipped because they were not in the allowed DICOM IDs')

        # Print a random report to make sure the tokenization is correct
        random_report = random.choice(reports)
        print_bold('Random report:')
        print_magenta(tokenizer.ids2string(random_report), bold=True)

        self.reports = reports
        self.dicom_ids = np.array(dicom_ids[:idx])
        self.image_paths = np.array(image_paths[:idx])
        self.report_ids = np.array(report_ids[:idx])
        self.orientations = np.array(orientations[:idx])
        if use_all_data:
            self.all_indices = np.array(all_indices)
            print(f'len(self.all_indices) = {len(self.all_indices)}')
        elif use_test_set or use_chest_imagenome_bbox_gold_set or use_chest_imagenome_label_gold_set:
            self.test_indices = np.array(test_indices)
            print(f'len(self.test_indices) = {len(self.test_indices)}')
        else:
            self.train_indices = np.array(train_indices)
            self.val_indices = np.array(val_indices)
            print(f'len(self.train_indices) = {len(self.train_indices)}')
            print(f'len(self.val_indices) = {len(self.val_indices)}')

        # Optional data to load
        self.classify_gender = classify_gender
        self.classify_chexpert = classify_chexpert
        self.classify_chest_imagenome = classify_chest_imagenome
        self.predict_bboxes_chest_imagenome = predict_bboxes_chest_imagenome
        self.predict_local_feature_coords = predict_local_feature_coords
        if self.predict_local_feature_coords:
            assert local_features_width is not None
            assert local_features_height is not None
            coords = []
            for y in range(local_features_height):
                for x in range(local_features_width):
                    coords.append(((x + 0.5) / local_features_width, (y + 0.5) / local_features_height))
            self.local_feature_coords = np.array(coords, dtype=np.float32)
            print(f'local_feature_coords.shape: {self.local_feature_coords.shape}')
        else:
            self.local_feature_coords = None

        if classify_gender:
            print('Loading Chest Imagenome genders...')
            dicomId2gender = get_dicomId2gender()
            def _get_gender_label(x):
                if x == 'F': return 0
                if x == 'M': return 1
                assert np.isnan(x)
                return 2
            self.genders = np.array([_get_gender_label(dicomId2gender[dicom_id]) for dicom_id in self.dicom_ids])
        else:
            self.genders = None

        if classify_chexpert or balanced_sampling_mode in (
            _BalancedSamplingMode.BALANCED_CHEXPERT_LABELS,
            _BalancedSamplingMode.BALANCED_CHEXPERT_LABELS_BATCHWISE,
        ):
            print('Loading CheXpert labels...')
            assert chexpert_labels_filename is not None
            chexpert_labels_path = os.path.join(MIMICCXR_CACHE_DIR, chexpert_labels_filename)
            self.chexpert_labels = get_cached_pickle_file(chexpert_labels_path)
            self.chexpert_labels = np.array(self.chexpert_labels)
        else:
            assert chexpert_labels_filename is None
            self.chexpert_labels = None

        if predict_labels_and_bboxes_chest_imagenome:
            assert classify_chest_imagenome
            assert chest_imagenome_label_names_filename is not None
            assert not use_chest_imagenome_bbox_gold_set # Not supported in this mode yet

        if classify_chest_imagenome or balanced_sampling_mode in (
            _BalancedSamplingMode.BALANCED_CHEST_IMAGENOME_GLOBAL_LABELS,
            _BalancedSamplingMode.BALANCED_CHEST_IMAGENOME_GLOBAL_LABELS_BATCHWISE,
        ):
            _load_chest_imagenome_labels(self, chest_imagenome_labels_filename, use_chest_imagenome_label_gold_set,
                                            chest_imagenome_label_names_filename)
        else:
            self.chest_imagenome_labels = None

        if predict_bboxes_chest_imagenome:
            assert not use_chest_imagenome_bbox_gold_set, 'Not supported yet'
            print('Loading Chest Imagenome bounding boxes...')
            self.dicom_idxs, self.bbox_coords, self.bbox_presence =\
                load_chest_imagenome_silver_bboxes_as_numpy_array(self.dicom_ids, clamp_bboxes_chest_imagenome)
            print(f'self.bbox_coords.shape = {self.bbox_coords.shape}')
            print(f'self.bbox_presence.shape = {self.bbox_presence.shape}')
            if horizontal_flip:
                assert data_augmentation_enabled
                print('Loading Chest Imagenome bounding boxes (flipped)...')
                _, self.flipped_bbox_coords, self.flipped_bbox_presence =\
                    load_chest_imagenome_silver_bboxes_as_numpy_array(
                        self.dicom_ids, clamp_bboxes_chest_imagenome, flipped=True)
            else:
                self.flipped_bbox_coords = None
                self.flipped_bbox_presence = None
        else:
            self.dicom_idxs = None
            self.bbox_coords = None
            self.bbox_presence = None
            self.flipped_bbox_coords = None
            self.flipped_bbox_presence = None

        if use_all_data:
            # Create all dataset and dataloader
            self.all_dataset, self.all_dataloader = self._create_dataset_and_dataloader(
            all_indices, test_image_transform, self.eval_collate_batch_fn)
        elif use_test_set or use_chest_imagenome_bbox_gold_set or use_chest_imagenome_label_gold_set:
            # Create test dataset and dataloader
            self.test_dataset, self.test_dataloader = self._create_dataset_and_dataloader(
                self.test_indices, test_image_transform, self.eval_collate_batch_fn)
        else:
            if not use_val_set_only:
                # Create train dataset and dataloader
                self.balanced_batch_size = balanced_batch_size
                self.train_dataset, self.train_dataloader = self._create_dataset_and_dataloader(
                    self.train_indices, train_image_transform, self.train_collate_batch_fn,
                    data_augmentation_enabled=self.data_augmentation_enabled,
                    shuffle=True, balanced_sampling_mode=balanced_sampling_mode)

            # Create validation dataset and dataloader
            self.val_dataset, self.val_dataloader = self._create_dataset_and_dataloader(
                self.val_indices, val_image_transform, self.eval_collate_batch_fn)

    def _create_dataset(self, indices, image_transform, data_augmentation_enabled=False, shuffle=False, infinite=False):
        return MIMICCXR_Image2Report_Dataset(
            indices=indices,
            reports=self.reports,
            report_ids=self.report_ids,
            image_paths=self.image_paths,
            image_transform=image_transform,
            data_augmentation_enabled=data_augmentation_enabled,
            shuffle=shuffle,
            infinite=infinite,
            classify_gender=self.classify_gender,
            genders=self.genders,
            classify_chexpert=self.classify_chexpert,
            chexpert_labels=self.chexpert_labels,
            classify_chest_imagenome=self.classify_chest_imagenome,
            chest_imagenome_labels=self.chest_imagenome_labels,
            predict_bboxes_chest_imagenome=self.predict_bboxes_chest_imagenome,
            dicom_idxs=self.dicom_idxs,
            gt_bbox_coords=self.bbox_coords,
            gt_bbox_presence=self.bbox_presence,
            flipped_gt_bbox_coords=self.flipped_bbox_coords,
            flipped_gt_bbox_presence=self.flipped_bbox_presence,
            horizontal_flip=self.horizontal_flip,
            use_yolov8=self.use_yolov8,
            predict_local_feature_coords=self.predict_local_feature_coords,
            local_feature_coords=self.local_feature_coords,
        )

    def _create_dataset_and_dataloader(self, indices, image_transform, collate_batch_fn, data_augmentation_enabled=False,
                                       shuffle=False, balanced_sampling_mode=None):
        return _create_dataset_and_dataloader(self, indices, image_transform, collate_batch_fn, data_augmentation_enabled,
                                              shuffle, balanced_sampling_mode)


from django.db import models
from base.models import BaseModel
from django.conf import settings

class Customer(BaseModel):
    """Customer Model"""

    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    email = models.EmailField(unique=True)
    phone = models.CharField(max_length=200)
    address = models.TextField(max_length=200)
    picture = models.ImageField(upload_to="profile/images")
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    class Meta:
        """Meta"""

        ordering = ["first_name", 'last_name']
        indexes = [models.Index(fields=["user", 'email', 'phone'])]

    def __str__(self):
        """Module name"""
        return f'{self.first_name} {self.last_name}'


from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

# Serializers imports
from ..serializers import *

class ShowMyUserProfileView(GenericAPIView):
    permission_classes = (
        IsAuthenticated,
    )

    def get(self, request, userName, **kwargs):

        requested_user: Usuario = Usuario.objects.get(username=userName)

        albums = [Album.objects.filter(usuario=requested_user),]

        data = {
            "result": {
                "user": UsuarioProfileSerializer(requested_user).data,
                "albums": [AlbumSerializer(a, many=True).data for a in albums]
            },
            "errors": None,
        }

        return Response(data, status=200)


# coding: utf-8

import webapp2
import time

from webapp2_extras import jinja2
from webapp2_extras.users import users
from datetime import datetime

from model.comentario import Comentario

class ModificaComentarioHandler(webapp2.RequestHandler):
    def get(self):

        usr = users.get_current_user()

        comentario = Comentario.recupera(self.request)

        valores_plantilla = {
            "usr": usr,
            "comentario": comentario
        }

        jinja = jinja2.get_jinja2(app=self.app)
        self.response.write(
            jinja.render_template("modifica_comentario.html",
            **valores_plantilla))

    def post(self):
        autor = self.request.get("edAutor", "")
        contenido = self.request.get("edContenido", "")

        if (not autor
            or not contenido):
                return self.redirect("/home")
        else:
            comentario = Comentario.recupera(self.request)
            clave_post = comentario.clave_post.urlsafe()
            # Obtenemos la hora actual, si se modifica el comentario dicha hora debe ser actualizada
            hora = datetime.today()
            comentario.autor = autor
            comentario.contenido = contenido
            comentario.hora = hora
            # Modificamos comentario con los nuevos cambios
            comentario.put()
            time.sleep(1)
            return self.redirect("/comentarios/ver?post="+clave_post)

app = webapp2.WSGIApplication([
    ('/comentarios/modifica', ModificaComentarioHandler)
], debug=True)


import requests
import os
import subprocess
import hashlib

'''
Use this script to download various different Text Summarization datasets such as Big Patent, Arxiv, Pubmed, CNN, Daily Mail, and Gigaword

Assumes Linux/Bash OS for tgz extraction (using subprocess.run())
'''

def download_file(destination, id_=None, url=None):
#This funciton is copied from stack overflow <https://stackoverflow.com/questions/25010369/wget-curl-large-file-from-google-drive>
    def get_confirm_token(response):
        for key, value in response.cookies.items():
            if key.startswith('download_warning'):
                return value
        return None

    def save_response_content(response, destination):
        CHUNK_SIZE = 32768
        with open(destination, "wb") as f:
            for chunk in response.iter_content(CHUNK_SIZE):
                if chunk: # filter out keep-alive new chunks
                    f.write(chunk)

    params = {}
    if id_ and not url: #i.e. from Google Drive
        url = "https://docs.google.com/uc?export=download"
        params = { 'id' : id_ }

    session = requests.Session()
    response = session.get(url, params = params, stream = True)
    token = get_confirm_token(response)

    if token:
        params = {'confirm' : token }
        if id_:
            params = { 'id' : id_, 'confirm' : token }
    response = session.get(url, params = params, stream = True)
    save_response_content(response, destination)

def find_size_of_dir(path_dir):
    totsize= 0
    for dirpath, dirnames, filenames in os.walk(path_dir):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            totsize += os.path.getsize(fp)
    return totsize

def find_num_examples_in_dir(path_dir):
    totsize= 0
    for dirpath, dirnames, filenames in os.walk(path_dir):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            totsize += find_num_examples(fp)
    return totsize

def find_num_examples(file_name):
    with open(file_name) as f:
        num_examples = 0
        for l in f:
            num_examples += 1
    return num_examples

# def delete_get_checksum(file_name):
#     #this doesn't work for large files. runs into memory error.
#     # Open,close, read file and calculate MD5 on its contents
#     with open(file_name, "rb") as f:
#         # read contents of the file
#         data = f.read()
#         # pipe contents of the file through
#         md5_returned = hashlib.md5(data).hexdigest()
#     return md5_returned

def get_checksum(file_name, block_size=128*64):
    # Open in blocks to fit in memory,close, read file and calculate MD5 on its contents
    md5 = hashlib.md5()
    with open(file_name, "rb") as f:
        while True:
            # read contents of the file
            chunk = f.read(block_size)
            if not chunk: break
            md5.update(chunk)
    # pipe contents of the file through
    md5_returned = md5.hexdigest()
    return md5_returned

def get_big_patent():
    #get BigPatent
    print('Geting BigPatent Data...')
    id_ = '1J3mucMFTWrgAYa3LuBZoLRR3CzzYD3fa'
    destination = './bigPatentData.tar.gz'
    download_file(destination, id_=id_)
    checksum = get_checksum(destination)
    subprocess.run(args=['tar', 'xzf', destination])
    subprocess.run(args=['rm', '-f', destination])
    print('Done Unzipping')
    subprocess.run(args=['tar', 'xzf', './bigPatentData/train.tar.gz', '-C', './bigPatentData'])
    subprocess.run(args=['rm', '-f', './bigPatentData/train.tar.gz'])
    # subprocess.run(args=['gzip', '-dr', './bigPatentData/train']) #recursively unzip all files in this folder and delete the .gz files
    subprocess.run(args=['tar', 'xzf', './bigPatentData/val.tar.gz', '-C', './bigPatentData'])
    subprocess.run(args=['rm', '-f', './bigPatentData/val.tar.gz'])
    # subprocess.run(args=['gzip', '-dr', './bigPatentData/val']) #recursively unzip all files in this folder and delete the .gz files
    subprocess.run(args=['tar', 'xzf', './bigPatentData/test.tar.gz', '-C', './bigPatentData'])
    subprocess.run(args=['rm', '-f', './bigPatentData/test.tar.gz'])
    # subprocess.run(args=['gzip', '-dr', './bigPatentData/test']) #recursively unzip all files in this folder and delete the .gz files
    print('Done Unzipping all the files inside the main data folder')
    data = 'n/a' #find_num_examples_in_dir('./bigPatentData/train')
    totsize = find_size_of_dir('./bigPatentData')
    print(f'The BigPatent dataset has {data} training examples and is {totsize/1e6:.1f}MB in size.')
    print(f'The BigPatent dataset md5 checksum (for *.tar.gz) is: {checksum}\n')

def get_scientific_papers():
    #get Scientific Papers (ArXiv & PubMed)
    print('Geting Arxiv Data...')
    url = 'https://archive.org/download/armancohan-long-summarization-paper-code/arxiv-dataset.zip'
    destination = './arxiv-dataset.zip'
    download_file(destination, url=url)
    checksum = get_checksum(destination)
    print('Running Unzip...')
    subprocess.run(args=['unzip', '-q', destination])
    print('Done Unzipping')
    data = find_num_examples('./arxiv-dataset/train.txt')
    totsize = find_size_of_dir('./arxiv-dataset')
    print(f'The Arxiv dataset has {data} training examples and is {totsize/1e6:.1f}MB in size.')
    print(f'The Arxiv dataset md5 checksum (for *.zip) is: {checksum}\n')
    subprocess.run(args=['rm', '-f', destination])
    subprocess.run(args=['rm', '-rf', './__MACOSX'])

    print('Geting Pubmed Data...')
    url = 'https://archive.org/download/armancohan-long-summarization-paper-code/pubmed-dataset.zip'
    destination = './pubmed-dataset.zip'
    download_file(destination, url=url)
    checksum = get_checksum(destination)
    print('Running Unzip...')
    subprocess.run(args=['unzip', '-q', destination])
    print('Done Unzipping')
    data = find_num_examples('./pubmed-dataset/train.txt')
    totsize = find_size_of_dir('./pubmed-dataset')
    print(f'The Pubmed dataset has {data} training examples and is {totsize/1e6:.1f}MB in size.')
    print(f'The Pubmed dataset md5 checksum (for *.zip) is: {checksum}\n')
    subprocess.run(args=['rm', '-f', destination])

def get_cnn_dailymail():
    #get CNN dataset
    print('Geting CNN Data...')
    id_ = '0BwmD_VLjROrfTHk4NFg2SndKcjQ'
    destination = './cnn.tgz'
    download_file(destination, id_=id_)
    checksum = get_checksum(destination)
    subprocess.run(args=['tar', 'xzf', destination])
    subprocess.run(args=['rm', '-f', destination])
    print('Done Unzipping')
    data = len(os.listdir('./cnn/stories/'))
    totsize = find_size_of_dir('./cnn')
    print(f'The CNN dataset has {data} examples and is {totsize/1e6:.1f}MB in size.')
    print(f'The CNN dataset md5 checksum (for *.tgz) is: {checksum}\n')

    #get Daily mail dataset
    print('Geting Daily Mail Data...')
    id_ = '0BwmD_VLjROrfM1BxdkxVaTY2bWs'
    destination = './dailymail.tgz'
    download_file(destination, id_=id_)
    checksum = get_checksum(destination)
    subprocess.run(args=['tar', 'xzf', destination])
    subprocess.run(args=['rm', '-f', destination])
    print('Done Unzipping')
    data = len(os.listdir('./dailymail/stories'))
    totsize = find_size_of_dir('./dailymail')
    print(f'The Daily Mail dataset has {data} examples and is {totsize/1e6:.1f}MB in size.')
    print(f'The Daily Mail dataset md5 checksum (for *.tgz) is: {checksum}\n')

def get_gigaword():
#Gigaword dataset
    print('Geting Gigaword Data...')
    id_ = '0B6N7tANPyVeBNmlSX19Ld2xDU1E'
    destination = './gigaword.tar.gz'
    download_file(destination, id_=id_)
    checksum = get_checksum(destination)
    subprocess.run(args=['tar', 'xzf', destination])
    subprocess.run(args=['rm', '-f', destination])
    print('Done Unzipping')
    os.rename('sumdata', 'gigaword')
    subprocess.run(args=['gzip', '-dr', './gigaword/train']) #recursively unzip all files in this folder and delete the .gz files
    gigword_num_examples = find_num_examples('./gigaword/train/train.title.txt')
    gigword_num_examples += find_num_examples('./gigaword/train/valid.title.filter.txt')
    totsize = find_size_of_dir('./gigaword')
    print(f'The Gigaword dataset has {gigword_num_examples} examples and is {totsize/1e6:.1f}MB in size.')
    print(f'The Gigaword dataset md5 checksum (for *.tar.gz) is: {checksum}\n')

if __name__ == '__main__':
    get_big_patent()
    # get_scientific_papers()
    # get_cnn_dailymail()
    # get_gigaword()


import datetime
import sqlite3

from bs4 import BeautifulSoup as bs
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

db = sqlite3.connect('ljmu_jobs.db')
c = db.cursor()

WEBPAGE = 'https://jobs.ljmu.ac.uk/vacancies.html'
job_details_required = ['Contract Type', 'Hours', 'Job Type',
                        'Salary', 'Vacancy Type', 'Closing Date', 'Ref No']

def open_chrome():
    path = r'/home/levo/Documents/projects/ChromeDriver/chromedriver'
    chrome_options = Options()
    chrome_options.add_argument("--headless")
    chrome_options.add_argument("--disable-gpu")
    browser = webdriver.Chrome(path, chrome_options=chrome_options)
    browser.set_page_load_timeout(60)
    browser.implicitly_wait(20)
    return browser

def jobpost_body(soup):
    return soup.find_all('div', class_='jobpost')

def title(jobpost_body):
    return jobpost_body.h2.text.strip()

def job_details(jobpost_body, detail):
    details = jobpost_body.p.find_all('span')
    for info in details:
        if info.text.strip().startswith(detail):
            return info.text.replace(f'{detail}:', '').strip()

def does_record_exist(ref_no):
    c.execute(''' SELECT ref FROM jobs WHERE ref=? ''', (int(ref_no),))
    if c.fetchone() is None:
        return False
    else:
        return True

def add_job(job):
    job_title = title(job)
    job_fields = {i: job_details(job, i) for i in job_details_required}
    c.execute(''' INSERT INTO jobs(ref, "date added", title, "contract type", hours, "job type", salary, "vacancy type", "closing date")
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ''',
              (
                  int(job_fields['Ref No']),
                  datetime.date.today().strftime("%B %d %Y"),
                  job_title,
                  job_fields['Contract Type'],
                  job_fields['Hours'],
                  job_fields['Job Type'],
                  job_fields['Salary'],
                  job_fields['Vacancy Type'],
                  job_fields['Closing Date']
              ))
    db.commit()

browser = open_chrome()
browser.get(WEBPAGE)
jobs = jobpost_body(bs(browser.page_source, 'html.parser'))

for i in jobs:
    if not does_record_exist((job_details(i, 'Ref No'))):
        add_job(i)

db.close()


#code to automate the acquisition of "just the two of us" images from youtube and crop them

import math
import os
from time import perf_counter

import cv2
import googleapiclient.discovery  # google's youtube API
import numpy as np
from vidgear.gears import CamGear

from api_key import key  # requires a api_key.py file containing the variable 'key' with a google api key as the value

cache_file = "video_list_cache.txt" # file where retrieved playlist content will be stored

youtube = googleapiclient.discovery.build("youtube", "v3", developerKey = key)

def create_dir(path): # create directory with given name (relative to current file)
    try:
        if not os.path.exists(path):
            os.makedirs(path)
    except OSError:
        print(f"ERROR: creating directory with name {path}")

# removes black border that exists around most images for some reason
def trim_border(image): # solution by https://stackoverflow.com/a/30540322/
    threshold = 4 # 0 = pure black
    if len(image.shape) == 3:
        flatImage = np.max(image, 2)
    else:
        flatImage = image
    assert len(flatImage.shape) == 2

    rows = np.where(np.max(flatImage, 0) > threshold)[0]
    if rows.size:
        cols = np.where(np.max(flatImage, 1) > threshold)[0]
        image = image[cols[0]: cols[-1] + 1, rows[0]: rows[-1] + 1]
    else:
        image = image[:1, :1]

    return image

def save_frame(stream, save_dir, name): #get frame from video and save to specified directory
    create_dir(save_dir) # check if directory exits, else creates one

    metadata = stream.ytv_metadata
    total_frames = metadata['fps'] * metadata['duration']
    target_frame = math.ceil(total_frames/5) # the frame of the video that will be captured (5% through the video)

    frame_pos = 0 # currently iterated frame
    while frame_pos < target_frame: # go to specified frame
        frame = stream.read()

        if (frame is None):
            break

        frame_pos+=1

    frame = trim_border(frame) # remove black border
    cv2.imwrite(f"{save_dir}\\{name}.png", frame) # save frame to image file

    stream.stop() # release stream
    print("Completed Capturing A Frame Of " + str(name))

if __name__ == "__main__": # you know the drill

    # Code to get list of videos in playlist
    print("Aquiring Playlist...")

    tik = perf_counter()
    playlist_id = "PL-vSysBoeI98daMpbj5V5vtRf-qxI0qAJ" # https://www.youtube.com/playlist?list=PL-vSysBoeI98daMpbj5V5vtRf-qxI0qAJ

    if (not os.path.isfile(cache_file)): # check if cache file exists
        print("Requesting Playlist from Youtube...")
        request = youtube.playlistItems().list( # request playlist from youtube
            part = "snippet",
            playlistId = playlist_id,
            maxResults = 50
        )
        response = request.execute()

        playlist_items = []
        while request is not None: # put response in list
            response = request.execute()
            playlist_items += response["items"]
            request = youtube.playlistItems().list_next(request, response)

        video_list = [f'https://www.youtube.com/watch?v={t["snippet"]["resourceId"]["videoId"]}' for t in playlist_items] # construct list of video urls

        with open(cache_file, "w") as f: # save urls to file
            for vid_url in video_list:
                f.write(vid_url+"\n")
    else:
        # get links from file
        print("Getting Playlist from Cache...")
        video_list = []
        with open(cache_file) as f:
            video_list = [line.rstrip("\n") for line in f]

    tok = perf_counter()

    print(f"Got playlist in {tok - tik:0.4} seconds")
    print(f"total: {len(video_list)}")

    vid_count = 1

    skip_to_vid = 0 # used for debugging (0 or less to disable)

    options = {"STREAM_RESOLUTION": "720p"}
    for vid in video_list:
        try:
            if (skip_to_vid <= 0 or vid_count >= skip_to_vid): # check for debug flag and act on it
                print(f"Starting on {vid_count}")
                stream = CamGear(source=vid, # get yt video
                                stream_mode=True,
                                logging=False,
                                time_delay=0.5,
                                **options).start()

                print("Completed Downloading of Video")

                print(vid)

                save_frame(stream, "saves", vid_count)
        except ValueError as e:
            print("Private Video Detected! Skipping...")

        vid_count += 1

print("Done!")
print(f"Completed: {len(video_list)} videos")


# -*- coding: utf-8 -*-
"""
Created on Sun Nov  6 23:20:31 2022

@author: Jim Achterberg
"""
import numpy as np
import pandas as pd
from numpy import random as rd
from sklearn.datasets import make_spd_matrix
from scipy.stats import ortho_group as og
from scipy.stats import rv_discrete

def VAR_gaussian(shape):
    N,T,F = shape
    sigma = make_spd_matrix(n_dim=F)
    err_mean = np.zeros(shape=F)
    errors = rd.multivariate_normal(err_mean,sigma,size=(N,T))
    V = rd.uniform(low=0,high=1,size=(F)) * np.identity(n=F)
    Q = og.rvs(dim=F)
    A = np.matmul(np.matmul(Q,V),np.linalg.inv(Q))
    data = np.empty((N,T,F))
    for t in range(T):
        if t==0:
            data[:,t,:] = errors[:,t,:]
        else:
            data[:,t,:] = np.matmul(errors[:,t-1,:],A)+errors[:,t,:]
    return data

def attributes(shape,n_cat,probs):
    N,A = shape
    vals = list(range(n_cat))
    distr = rv_discrete(a=0,b=n_cat-1,values=(vals,probs))
    attr = distr.rvs(size=(N,A))
    return attr

data = attributes((100,5),5,[.2]*5)


from .core import encode, decode, alabel, ulabel, IDNAError
import codecs
import re
from typing import Tuple, Optional

_unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]')

class Codec(codecs.Codec):

    def encode(self, data: str, errors: str = 'strict') -> Tuple[bytes, int]:
        if errors != 'strict':
            raise IDNAError('Unsupported error handling \"{}\"'.format(errors))

        if not data:
            return b"", 0

        return encode(data), len(data)

    def decode(self, data: bytes, errors: str = 'strict') -> Tuple[str, int]:
        if errors != 'strict':
            raise IDNAError('Unsupported error handling \"{}\"'.format(errors))

        if not data:
            return '', 0

        return decode(data), len(data)

class IncrementalEncoder(codecs.BufferedIncrementalEncoder):
    def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[str, int]:  # type: ignore
        if errors != 'strict':
            raise IDNAError('Unsupported error handling \"{}\"'.format(errors))

        if not data:
            return "", 0

        labels = _unicode_dots_re.split(data)
        trailing_dot = ''
        if labels:
            if not labels[-1]:
                trailing_dot = '.'
                del labels[-1]
            elif not final:
                # Keep potentially unfinished label until the next call
                del labels[-1]
                if labels:
                    trailing_dot = '.'

        result = []
        size = 0
        for label in labels:
            result.append(alabel(label))
            if size:
                size += 1
            size += len(label)

        # Join with U+002E
        result_str = '.'.join(result) + trailing_dot  # type: ignore
        size += len(trailing_dot)
        return result_str, size

class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
    def _buffer_decode(self, data: str, errors: str, final: bool) -> Tuple[str, int]:  # type: ignore
        if errors != 'strict':
            raise IDNAError('Unsupported error handling \"{}\"'.format(errors))

        if not data:
            return ('', 0)

        labels = _unicode_dots_re.split(data)
        trailing_dot = ''
        if labels:
            if not labels[-1]:
                trailing_dot = '.'
                del labels[-1]
            elif not final:
                # Keep potentially unfinished label until the next call
                del labels[-1]
                if labels:
                    trailing_dot = '.'

        result = []
        size = 0
        for label in labels:
            result.append(ulabel(label))
            if size:
                size += 1
            size += len(label)

        result_str = '.'.join(result) + trailing_dot
        size += len(trailing_dot)
        return (result_str, size)

class StreamWriter(Codec, codecs.StreamWriter):
    pass

class StreamReader(Codec, codecs.StreamReader):
    pass

def getregentry() -> codecs.CodecInfo:
    # Compatibility as a search_function for codecs.register()
    return codecs.CodecInfo(
        name='idna',
        encode=Codec().encode,  # type: ignore
        decode=Codec().decode,  # type: ignore
        incrementalencoder=IncrementalEncoder,
        incrementaldecoder=IncrementalDecoder,
        streamwriter=StreamWriter,
        streamreader=StreamReader,
    )


import sys
from collections import deque

N = int(sys.stdin.readline())
tree = list([] for _ in range(N+1))
for i in range(N-1):
    x, y = map(int, sys.stdin.readline().split())
    tree[x].append(y)
    tree[y].append(x)
# print(tree)

def BFS(start):
    q = deque()
    q.append(start)
    visited = [0] * (N+1)
    visited[start] = 1
    while q:
        temp = int(q.popleft())
        for node in tree[temp]:
            if visited[node] == 0:
                visited[node] = 1
                result.append((node, temp))
                q.append(node)

result = list()
BFS(1)
# print(result)
result.sort()
for ans in result:
    print(ans[1])


import logging
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import unittest

class ChromeWow:
    def __init__(self):
        self.driver = webdriver.Chrome()
        self.url = "https://eu.gear.blizzard.com/"
        self.logger = self._set_logger()

    def _set_logger(self):
        logger = logging.getLogger('Selenium')
        logger.setLevel(logging.INFO)
        handler = logging.StreamHandler()
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        return logger

    def run_add_product_to_cart_and_ship_test(self):
        self.logger.info("Open WoW Gear URL")
        self.driver.get(self.url)
        sleep(4)

        self.logger.info("Search for a product")
        self.driver.find_element(By.NAME, 'q').send_keys('horde beanie')
        self.driver.find_element(By.CSS_SELECTOR, "button[type='submit']").submit()

        self.logger.info("Check if search was successfull")
        search_successfull = self.driver.find_element(By.CSS_SELECTOR, ".search-page>.container>.page-header>h1>span:nth-child(3)").text
        tc = unittest.TestCase()
        tc.assertEqual("REVEALED THE FOLLOWING:", search_successfull)

        self.logger.info("Click on first returned product")
        self.driver.find_element(By.CSS_SELECTOR, ".product-collection>div>div:nth-child(1)").click()

        self.logger.info("Get rid of a promo popup")
        popup_close = WebDriverWait(self.driver,10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".klaviyo-close-form")))
        popup_close.click()
        sleep(2)

        self.logger.info("Add product to cart")
        self.driver.find_element(By.CSS_SELECTOR, "#product-add-to-cart").click()
        sleep(2)

        self.logger.info("Checkout")
        self.driver.find_element(By.CSS_SELECTOR, ".btn-checkout").click()
        sleep(2)

        self.logger.info("Add shipping details")
        self.driver.find_element(By.CSS_SELECTOR, "#checkout_email").send_keys("john.doe@example.com")
        sleep(1)
        self.driver.find_element(By.CSS_SELECTOR, "#checkout_shipping_address_first_name").send_keys("John")
        sleep(1)
        self.driver.find_element(By.CSS_SELECTOR, "#checkout_shipping_address_last_name").send_keys("Doe")
        sleep(1)
        self.driver.find_element(By.CSS_SELECTOR, "#checkout_shipping_address_address1").send_keys("Targ Drzewny")
        sleep(2)
        self.driver.find_element(By.CSS_SELECTOR, "#checkout_shipping_address_address2").send_keys("9/11")
        sleep(2)
        self.driver.find_elements(By.CSS_SELECTOR, ".ui-button-text")[0].click()
        self.driver.find_element(By.CSS_SELECTOR, "#checkout_shipping_address_city").send_keys("Gdansk")
        sleep(1)
        self.driver.find_element(By.CSS_SELECTOR, "#checkout_shipping_address_zip").send_keys("80-001")
        sleep(1)
        self.driver.find_element(By.CSS_SELECTOR, "#checkout_shipping_address_phone").send_keys("+48606606606")
        sleep(1)
        self.driver.find_element(By.CSS_SELECTOR, "#continue_button").submit()
        sleep(2)

        self.logger.info("Continue to payment")
        self.driver.find_element(By.CSS_SELECTOR, "#continue_button").submit()
        sleep(2)

        self.driver.quit()


"""Define types for airports in the network."""
from dataclasses import dataclass, field
from typing import Optional

import pyro
import pyro.distributions as dist

from bayes_air.types.flight import Flight
from bayes_air.types.util import AirportCode, Time

@dataclass
class QueueEntry:
    """An entry in a runway queue.

    Attributes:
        flight: The flight associated with this queue entry.
        queue_start_time: The time at which the flight entered the queue.
        total_wait_time: The total duration the flight has spent in the queue.
        assigned_service_time: The time at which the flight will be serviced.
    """

    flight: Flight
    queue_start_time: Time
    total_wait_time: Time = field(default_factory=lambda: Time(0.0))
    assigned_service_time: Optional[Time] = None

@dataclass
class Airport:
    """Represents a single airport in the network.

    Attributes:
        code: The airport code.
        mean_service_time: The mean service time for departing and arriving aircraft
        runway_use_time_std_dev: The standard deviation of the runway use time for
            departing and arriving aircraft.
        mean_turnaround_time: The nominal turnaround time for aircraft landing at
            this airport.
        turnaround_time_std_dev: The standard deviation of the turnaround time for
            aircraft landing at this airport.
        runway_queue: The queue of aircraft waiting to take off or land.
        turnaround_queue: The queue of aircraft waiting to be cleaned/refueled/etc..
            Each entry in this queue represents a time at which the aircraft will be
            ready for its next departure.
        available_aircraft: a list of times at which aircraft became available (after
            turnaround).
        available_crew: a list of times at which crew become available (after
            turnaround). Treats crew for 1 aircraft as a single unit.
        last_departure_time: The time at which the last aircraft departed.
    """

    code: AirportCode
    mean_service_time: Time = field(default_factory=lambda: Time(1.0))
    runway_use_time_std_dev: Time = field(default_factory=lambda: Time(1.0))
    mean_turnaround_time: Time = field(default_factory=lambda: Time(1.0))
    turnaround_time_std_dev: Time = field(default_factory=lambda: Time(1.0))
    runway_queue: list[QueueEntry] = field(default_factory=list)
    turnaround_queue: list[Time] = field(default_factory=list)
    available_aircraft: list[Time] = field(default_factory=list)
    available_crew: list[Time] = field(default_factory=list)
    last_departure_time: Time = field(default_factory=lambda: Time(0.0))

    @property
    def num_available_aircraft(self) -> int:
        """Return the number of available aircraft"""
        return len(self.available_aircraft)

    @property
    def num_available_crew(self) -> int:
        """Return the number of available crew"""
        return len(self.available_crew)

    def update_available_aircraft(self, time: Time) -> None:
        """Update the number of available aircraft by checking the turnaround queue.

        Args:
            time: The current time.
        """
        new_turnaround_queue = []
        for turnaround_time in self.turnaround_queue:
            if turnaround_time <= time:
                # The aircraft is ready to depart, so add it to the available aircraft
                self.available_aircraft.append(turnaround_time)
                self.available_crew.append(turnaround_time)
            else:
                # The aircraft is not yet ready to depart, so add it to the new
                # turnaround queue
                new_turnaround_queue.append(turnaround_time)

        # Update the turnaround queue
        self.turnaround_queue = new_turnaround_queue

    def update_runway_queue(
        self, time: Time, var_prefix: str = ""
    ) -> tuple[list[Flight], list[Flight]]:
        """Update the runway queue by removing flights that have been serviced.

        Args:
            time: The current time.
            var_prefix: the prefix for sampled variable names

        Returns: a list of flights that have departed and a list of flights that have
            landed.
        """
        # While the flight at the front of the queue is ready to be serviced, service it
        departed_flights = []
        landed_flights = []
        while self.runway_queue and (
            self.runway_queue[0].assigned_service_time is None
            or self.runway_queue[0].assigned_service_time <= time
        ):
            # If no service time is assigned, assign one now by sampling from
            # the service time distribution
            if self.runway_queue[0].assigned_service_time is None:
                self._assign_service_time(self.runway_queue[0], time, var_prefix)

            # If the service time has elapsed, it takes off or lands
            if self.runway_queue[0].assigned_service_time <= time:
                queue_entry = self.runway_queue.pop(0)
                flight = queue_entry.flight

                departing = flight.origin == self.code
                if departing:
                    # Takeoff! Assign a departure time and add the flight to the
                    # list of departed flights
                    self._assign_departure_time(queue_entry, var_prefix)
                    departed_flights.append(flight)
                else:
                    # Landing! Assign an arrival time and add the aircraft to the
                    # turnaround queue
                    self._assign_arrival_time(queue_entry, var_prefix)
                    self._assign_turnaround_time(flight, var_prefix)
                    landed_flights.append(flight)

        return departed_flights, landed_flights

    def _assign_service_time(
        self, queue_entry: QueueEntry, time: Time, var_prefix: str = ""
    ) -> None:
        """Sample a random service time for an entry in the runway queue.

        Args:
            queue_entry: The queue entry to assign a service time to.
            time: The current time.
            var_prefix: prefix for sampled variable names.
        """
        departing = queue_entry.flight.origin == self.code
        var_name = var_prefix + str(queue_entry.flight)
        var_name += "_departure" if departing else "_arrival"
        var_name += "_service_time"
        service_time = pyro.sample(
            var_name,
            dist.Exponential(1.0 / self.mean_service_time.reshape(-1)),
        )

        # Update the waiting times for all aircraft
        for other_queue_entry in self.runway_queue:
            other_queue_entry.total_wait_time = (
                other_queue_entry.total_wait_time + service_time
            )

        # Update the time at which this aircraft leaves the queue
        queue_entry.assigned_service_time = (
            queue_entry.queue_start_time + queue_entry.total_wait_time
        )

        # print(
        #     f"\t{queue_entry.flight} assigned service time {queue_entry.assigned_service_time} (entered queue {queue_entry.queue_start_time} and sampled service time {service_time})"
        # )

    def _assign_departure_time(
        self,
        queue_entry: QueueEntry,
        var_prefix: str = "",
    ) -> None:
        """Sample a random departure time for a flight that is using the runway.

        Args:
            queue_entry: The queue entry for the flight to assign a departure time to.
            var_prefix: prefix for sampled variable names.
        """
        # TODO should this be sampling or deterministic
        queue_entry.flight.simulated_departure_time = pyro.sample(
            var_prefix + str(queue_entry.flight) + "_simulated_departure_time",
            dist.Normal(
                queue_entry.queue_start_time + queue_entry.total_wait_time,
                self.runway_use_time_std_dev,
            ),
        )
        # queue_entry.flight.simulated_departure_time = (
        #     queue_entry.queue_start_time + queue_entry.total_wait_time
        # )

        # print(
        #     f"\t{queue_entry.flight} departing at {queue_entry.flight.simulated_departure_time} (entered queue {queue_entry.queue_start_time} and waited {queue_entry.total_wait_time})"
        # )

    def _assign_arrival_time(
        self, queue_entry: QueueEntry, var_prefix: str = ""
    ) -> None:
        """Sample a random arrival time for a flight that is using the runway.

        Args:
            queue_entry: The queue entry for the flight to assign a arrival time to.
            var_prefix: prefix for sampled variable names.
        """
        # TODO should this be sampling or deterministic?
        queue_entry.flight.simulated_arrival_time = pyro.sample(
            var_prefix + str(queue_entry.flight) + "_simulated_arrival_time",
            dist.Normal(
                queue_entry.queue_start_time + queue_entry.total_wait_time,
                self.runway_use_time_std_dev,
            ),
        )
        # queue_entry.flight.simulated_arrival_time = (
        #     queue_entry.queue_start_time + queue_entry.total_wait_time
        # )

        # print(
        #     f"\t{queue_entry.flight} arriving at {queue_entry.flight.simulated_arrival_time} (entered queue {queue_entry.queue_start_time} and waited {queue_entry.total_wait_time})"
        # )

    def _assign_turnaround_time(self, flight: Flight, var_prefix: str = "") -> None:
        """Sample a random turnaround time for an arrived aircraft.

        Args:
            flight: The flight to assign a turnaround time to.
            var_prefix: prefix for sampled variable names.
        """
        turnaround_time = pyro.sample(
            var_prefix + str(flight) + "_turnaround_time",
            dist.Normal(self.mean_turnaround_time, self.turnaround_time_std_dev),
        )
        self.turnaround_queue.append(flight.simulated_arrival_time + turnaround_time)


import scrapy
from scrapy.http import FormRequest
from scrapy.http import Request
from datetime import datetime
from scrapy.selector import Selector
from dgut_spider.handlePic import handle

class GetClassCourseSpider(scrapy.Spider):
    name = 'ClassCourse'

    def __init__(self):
        self.getUrl = 'http://jwxt.dgut.edu.cn/jwweb/ZNPK/KBFB_ClassSel.aspx' # first
        self.vcodeUrl = 'http://jwxt.dgut.edu.cn/jwweb/sys/ValidateCode.aspx' # second
        self.postUrl = 'http://jwxt.dgut.edu.cn/jwweb/ZNPK/KBFB_ClassSel_rpt.aspx' # third
        self.CourseUrl = 'http://jwxt.dgut.edu.cn/jwweb/ZNPK/drawkbimg.aspx'
        self.findSessionId = None # to save the cookies

    def start_requests(self):
        request = scrapy.Request(self.getUrl,
                callback = self.downloadPic)
        yield request

    def downloadPic(self, response):
        # download the picture
        # find the session id
        self.findSessionId = response.headers.getlist('Set-Cookie')[0].decode().split(';')[0].split('=')
        request = scrapy.Request(self.vcodeUrl,
                cookies = {self.findSessionId[0]: self.findSessionId[1]},
                callback = self.getAndHandleYzm)
        yield request

    def getAndHandleYzm(self, response):
        yzm = handle(response.body)

        yield FormRequest(self.postUrl,
                formdata = {'Sel_XNXQ': '20151',
                            'Sel_XZBJ': '1101201201',
                            'txt_yzm': yzm,
                            'txtzxbj': '',
                            'type': '2'},
                headers = {
                    'Referer': self.getUrl,
                    'Cookies': self.findSessionId[0] + '=' + self.findSessionId[1]
                    },
                callback = self.parse
                )

    def parse(self, response):
        body = response.body.decode('gbk')
        num = body.find('alert')
        if num != -1:
            yield scrapy.Request(self.vcodeUrl+'?t='+'%.f' % (datetime.now().microsecond / 1000),
                    headers = {
                        'Referer': self.getUrl,
                        'Cookies': self.findSessionId[0] + '=' + self.findSessionId[1]
                        },
                    callback = self.getAndHandleYzm
                    )

        else:
            sel = Selector(text = body)
            # to find the src tag, find the url
            self.CourseUrl = sel.xpath('//img/@src').extract()[0]
            self.CourseUrl = 'http://jwxt.dgut.edu.cn/jwweb/ZNPK/' + self.CourseUrl

            headers = {#'Cookie': self.findSessionId[0] + '=' + self.findSessionId[1],
                'Referer': 'http://jwxt.dgut.edu.cn/jwweb/ZNPK/KBFB_ClassSel_rpt.aspx',
                   'User-Agert': 'Mozilla/5.0 (X11; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0'
                }
            request = Request(self.CourseUrl, headers = headers, callback = self.parseData
                    )
            yield request

    def parseData(self, response):
        with open('three.jpg', 'wb') as f:
            f.write(response.body)


from utils.testcase import TestCase
from player.serializers import RoomSerializer, RoomsSerializer

import sure

class SerializersTestCase(TestCase):
    def test_room_serializer(self):
        expected_result = {
            'name': 'a',
            'current_music': None,
            'shuffle': False,
            'can_adjust_volume': False,
            'count_left': 0,
            'time_left': 0,
            'current_time_left': 0,
            'playlist': [],
            'volume': 10,
            'token': self.r.token,
            'current_time_past': 0,
            'current_time_past_percent': 0,
            'listeners': 0,
        }

        dict(RoomSerializer(self.r).data).should.eql(expected_result)

    def test_rooms_serializer(self):
        expected_result = {
            'name': 'a',
            'current_music': None,
            'shuffle': False,
            'can_adjust_volume': False,
            'count_left': 0,
            'time_left': 0,
            'current_time_left': 0,
            'playlist': [],
            'volume': 10,
            'listeners': 0,
        }

        dict(RoomsSerializer(self.r).data).should.eql(expected_result)


#If 'NoneType' error happen try the steps below. Then Restart Kernel and run the Program.

#!pip uninstall googletrans -y         #To uninstall current version of googletrans
#!pip install googletrans==4.0.0rc1
#import googletrans
#print(googletrans.__version__)

#importing modules
from tkinter import *
from googletrans import Translator

# initializing window
Screen = Tk()
Screen.title("Language Translator with GUI by- TechVidvan")

InputLanguageChoice = StringVar()
TranslateLanguageChoice = StringVar()

#tuple for choosing languages
LanguageChoices = {'Hindi','English','French','German','Spanish'}
InputLanguageChoice.set('English')
TranslateLanguageChoice.set('Hindi')

def Translate():
    translator = Translator()
    Translation = translator.translate(TextVar.get(), src=InputLanguageChoice.get(), dest=TranslateLanguageChoice.get())
    OutputVar.set(Translation.text)

#choice for input language
InputLanguageChoiceMenu = OptionMenu(Screen,InputLanguageChoice,*LanguageChoices)
Label(Screen,text="Choose a Language").grid(row=0,column=1)
InputLanguageChoiceMenu.grid(row=1,column=1)

#choice in which the language is to be translated
NewLanguageChoiceMenu = OptionMenu(Screen,TranslateLanguageChoice,*LanguageChoices)
Label(Screen,text="Translated Language").grid(row=0,column=2)
NewLanguageChoiceMenu.grid(row=1,column=2)

Label(Screen,text="Enter Text").grid(row=2,column =0)
TextVar = StringVar()
TextBox = Entry(Screen,textvariable=TextVar).grid(row=2,column = 1)

Label(Screen,text="Output Text").grid(row=2,column =2)
OutputVar = StringVar()
TextBox = Entry(Screen,textvariable=OutputVar).grid(row=2,column = 3)

#Button for calling function
B = Button(Screen,text="Translate",command=Translate, relief = GROOVE).grid(row=3,column=1,columnspan = 3)

mainloop()

#For Reference regarding googletrans api: https://stackabuse.com/text-translation-with-google-translate-api-in-python/
#For Reference regarding Tkinter application: https://techvidvan.com/tutorials/python-language-translator/

3. Advanced/5. Language Translator/Language Translator with GUI.py


import os
from flask import Flask, request, jsonify, abort
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_cors import CORS
from .auth import AuthError

db = SQLAlchemy()
migrate = Migrate()

def create_app():
    app = Flask(__name__)
    app.config.from_mapping(
        SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev_key',
        SQLALCHEMY_DATABASE_URI = os.environ.get('POSTGRES_URL') or \
            'sqlite:///' + os.path.join(app.instance_path, 'casting.sqlite'),
        SQLALCHEMY_TRACK_MODIFICATIONS = False
    )

    CORS(app)

    # CORS Headers
    @app.after_request
    def after_request(response):
        response.headers.add(
            "Access-Control-Allow-Headers", "Content-Type, Authorization, true"
        )
        response.headers.add(
            "Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS"
        )
        return response

    db.init_app(app)
    migrate.init_app(app, db)

    from . import models

    from . import routes
    app.register_blueprint(routes.bp)

    #Error Handling

    @app.errorhandler(422)
    def unprocessable(error):
        return jsonify({
            "success": False,
            "error": 422,
            "message": "unprocessable"
        }), 422

    @app.errorhandler(404)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 404,
            "message": "resource not found"
        }), 404

    @app.errorhandler(401)
    def unauthorized(error):
        return jsonify({
            "success": False,
            "error": 401,
            "message": "unauthorized"
        }), 401

    # error handler for Auth
    @app.errorhandler(AuthError)
    def handle_auth_error(ex):
        response = jsonify(ex.error)
        response.status_code = ex.status_code
        return response

    # error handler for 400
    @app.errorhandler(400)
    def bad_request(error):
        return jsonify({
            "success": False,
            "error": 400,
            "message": "bad request"
        }), 400

    # error handler for 405
    @app.errorhandler(405)
    def not_found(error):
        return jsonify({
            "success": False,
            "error": 405,
            "message": "method not allowed"
        }), 405

    # error handler for 500
    @app.errorhandler(500)
    def internal_error(error):
        return jsonify({
            "success": False,
            "error": 500,
            "message": "internal server error"
        }), 500

    return app


"""Module provider for Linode V4"""
import json
import logging
from argparse import ArgumentParser
from typing import List

import requests

from lexicon.exceptions import AuthenticationError
from lexicon.interfaces import Provider as BaseProvider

LOGGER = logging.getLogger(__name__)

class Provider(BaseProvider):
    """Provider class for Linode V4"""

    @staticmethod
    def get_nameservers() -> List[str]:
        return ["linode.com"]

    @staticmethod
    def configure_parser(parser: ArgumentParser) -> None:
        parser.add_argument("--auth-token", help="specify api key for authentication")

    def __init__(self, config):
        super(Provider, self).__init__(config)
        self.domain_id = None
        self.api_endpoint = "https://api.linode.com/v4/"

    def authenticate(self):
        self.domain_id = None
        payload = self._get(
            "domains", query_params={"filter": {"domain": self.domain.lower()}}
        )
        if payload["data"]:
            self.domain_id = payload["data"][0]["id"]
        else:
            raise AuthenticationError("Domain not found")

    def cleanup(self) -> None:
        pass

    def create_record(self, rtype, name, content):
        if not self.list_records(rtype, name, content):
            if name:
                name = self._relative_name(name).lower()

            self._post(
                f"domains/{self.domain_id}/records",
                data={"name": name, "type": rtype, "target": content, "ttl_sec": 0},
            )

        return True

    # List all records. Return an empty list if no records found
    # type, name and content are used to filter records.
    # If possible filter during the query, otherwise filter after response is received.
    def list_records(self, rtype=None, name=None, content=None):
        resources_url = f"domains/{self.domain_id}/records"

        if name:
            name = self._relative_name(name).lower()

        processed_records = []

        payload = self._get(resources_url)
        for page in range(1, payload["pages"] + 1, 1):
            if page > 1:
                payload = self._get(resources_url, query_params={"page": page})

            resource_list = payload["data"]
            if rtype:
                resource_list = [
                    resource for resource in resource_list if resource["type"] == rtype
                ]
            if name:
                resource_list = [
                    resource
                    for resource in resource_list
                    if self._relative_name(resource["name"]).lower() == name
                ]
            if content:
                resource_list = [
                    resource
                    for resource in resource_list
                    if resource["target"] == content
                ]

            for resource in resource_list:
                processed_records.append(
                    {
                        "id": resource["id"],
                        "type": resource["type"],
                        "name": self._full_name(resource["name"]).lower(),
                        "ttl": resource["ttl_sec"],
                        "content": resource["target"],
                    }
                )

        LOGGER.debug("list_records: %s", processed_records)
        return processed_records

    # Create or update a record.
    def update_record(self, identifier, rtype=None, name=None, content=None):
        if not identifier:
            resources = self.list_records(rtype, name, None)
            identifier = resources[0]["id"] if resources else None

        LOGGER.debug("update_record: %s", identifier)

        if name:
            name = self._relative_name(name).lower()

        url = f"domains/{self.domain_id}/records/{identifier}"
        self._put(
            url,
            data={
                "name": name.lower() if name else None,
                "type": rtype if rtype else None,
                "target": content if content else None,
            },
        )

        return True

    # Delete an existing record.
    # If record does not exist, do nothing.
    def delete_record(self, identifier=None, rtype=None, name=None, content=None):
        delete_resource_id = []
        if not identifier:
            resources = self.list_records(rtype, name, content)
            delete_resource_id = [resource["id"] for resource in resources]
        else:
            delete_resource_id.append(identifier)

        LOGGER.debug("delete_records: %s", delete_resource_id)

        for resource_id in delete_resource_id:
            self._delete(f"domains/{self.domain_id}/records/{resource_id}")

        return True

    # Helpers
    def _request(self, action="GET", url="", data=None, query_params=None):
        if data is None:
            data = {}
        if query_params is None:
            query_params = {}
        default_headers = {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self._get_provider_option('auth_token')}",
        }

        request_filter = query_params["filter"] if "filter" in query_params else None
        if request_filter is not None:
            default_headers["X-Filter"] = json.dumps(request_filter)
            del query_params["filter"]

        request_url = f"{self.api_endpoint}{url}"

        response = requests.request(
            action,
            request_url,
            params=query_params,
            data=json.dumps(data),
            headers=default_headers,
        )
        # if the request fails for any reason, throw an error.
        response.raise_for_status()
        if action == "DELETE":
            return ""
        result = response.json()
        return result


from xml.etree import ElementTree

import yaml
import pytest

from vuecli.provider.provider import Provider

@pytest.fixture
def render_index(tmp_path):
    def render(config=None):
        tmp_path.joinpath("vuepy.yml").write_text(yaml.dump(config or {}))
        provider = Provider(tmp_path)
        return provider.render_index()

    return render

def parse_index(index):
    et = ElementTree.fromstring(index)
    return {
        "stylesheets": [e.attrib["href"] for e in et.findall("head/link")],
        "scripts": [e.attrib["src"] for e in et.findall("head/script")],
        "templates": {
            e.attrib["id"]: e.text.strip()
            for e in et.findall("body/script[@type='x-template']")
        },
        "brython": et.find("body").attrib["onload"],
    }

class TestRenderIndex:
    def test_defaults(self, render_index):
        index = render_index()
        assert parse_index(index) == {
            "stylesheets": [],
            "scripts": ["vuepy.js", "vue.js"],
            "templates": {},
            "brython": "brython();",
        }

    def test_custom_stylesheets(self, render_index):
        index = render_index({"stylesheets": ["first.css", "second.css"]})
        assert parse_index(index)["stylesheets"] == ["first.css", "second.css"]

    @pytest.mark.parametrize(
        "ext, js", [("vuex", "vuex.js"), ("vue-router", "vue-router.js")]
    )
    def test_enable_builtin_script(self, render_index, ext, js):
        index = render_index({"scripts": {ext: True}})
        assert js in parse_index(index)["scripts"]

    @pytest.mark.parametrize("ext", ["vue", "brython", "vuex", "vue-router"])
    def test_customize_builtin_script(self, render_index, ext):
        index = render_index({"scripts": {ext: "custom"}})
        assert "custom" in parse_index(index)["scripts"]

    def test_custom_script(self, render_index):
        index = render_index({"scripts": ["myscript.js"]})
        assert "myscript.js" in parse_index(index)["scripts"]

    def test_custom_template(self, render_index, tmp_path):
        tmp_path.joinpath("my.html").write_text("content")
        index = render_index({"templates": {"my": "my.html"}})
        assert parse_index(index)["templates"] == {"my": "content"}

    def test_custom_brython_args(self, render_index):
        index = render_index({"brython_args": {"debug": 10}})
        assert parse_index(index)["brython"] == "brython({ debug: 10 });"


from typing import List,Set,Dict
from collections import Counter
import re

def find_model_names(text : str) -> Dict[str, int]:
  '''
  This functions find all the model names in the text string.
  The model names are expected to be the model names introduced in the paper
  so 'nic' 'transformer' etc ...
  Arguments
  ---------
  text : str
      Text extracted from the output text file for specific model.
  Returns
  -------
  Set[str]
      The set containing the model names and how many times the model was encountered.
  '''
  # Define the regex to match the group after the --cap_model. This is our caption model.
  match_string = r'--cap_model ([a-zA-Z0-9]+_[a-zA-Z0-9]+|[a-zA-Z0-9]+)'
  model_names = Counter()
  for matches in re.finditer(match_string, text):
    name = matches.group(1)
    model_names[name] += 1
  return model_names

def find_seeds(text: str) -> List[List[int]]:
  '''
  This functions find all the seeds in the text string.
  Arguments
  ---------
  text : str
      Text extracted from the output text file for specific model.
  Returns
  -------
  List[List[int]]
      The list of lists containing the seeds for each model.
  '''
  # First find the model names.
  model_names = find_model_names(text).keys()
  match_string = r'--seed (\d+)(?=.*{} )'
  seeds = []
  for model in model_names:
    # Do lookup regular expression with the model name.
    # So this ensures that we are extracting the seeds for the specified model
    # in the model name.
    match_string_ = match_string.format(model)
    seed = []
    for matches in re.finditer(match_string_, text):
      seed.append(int(matches.group(1)))
    seeds.append(seed)
  return seeds

def find_lic_scores(text: str) -> List[List[float]]:
  '''
  This functions find all LIC scores in the text.
  Arguments
  ---------
  text : str
      Text extracted from the output text file for specific model.
  Returns
  -------
  List[List[int]]
      The list of lists containing the LIC scores for each model.
  '''
  # Find all the model names.
  model_names = find_model_names(text).keys()
  # This string extracts the section of the text that belongs to the model.
  match_string = r"--cap_model {} .*?#############################"
  # This string extracts the LIC score.
  score_string = r"LIC score .*: (\d+\.\d+)%"
  lic_scores = []
  for model in model_names:
    matches = re.findall(match_string.format(model), text, re.DOTALL)
    lic_score = []
    # Extract the section of the text given the model.
    for match in matches:
      for scores in re.finditer(score_string, match):
        # From this section, extract the LIC score.
        lic_score.append(float(scores.group(1)))
    lic_scores.append(lic_score)
  return lic_scores

def find_epochs(text: str) -> List[List[int]]:
  '''
  This functions find all epochd in the text.
  Arguments
  ---------
  text : str
      Text extracted from the output text file for specific model.
  Returns
  -------
  List[List[int]]
      The list of lists containing the epochs for each model.
  '''
  # Find all the model names.
  model_names = find_model_names(text).keys()
  # This string extract the epochs given the model name.
  match_string = r'--num_epochs (\d+)(?=.*{} )'
  epochs = []
  for model in model_names:
    # Match the epochs for the specified model.
    match_string_ = match_string.format(model)
    epoch = []
    # For the match in the match_string, append it to the epoch array.
    for matches in re.finditer(match_string_, text):
      epoch.append(int(matches.group(1)))
    epochs.append(epoch)
  return epochs


from aiogram import types
from aiogram.dispatcher import FSMContext

from handlers.workers.cargoman import Cargonist
from loader import dp
from states.cargo import CargoState, AddProductState, ProductState

@dp.message_handler(state=[CargoState.start, ProductState.start], text='Создать продукт')
async def add_product(message: types.Message, state=FSMContext):
    await state.set_state(AddProductState.start)
    await message.answer('наименование продукта ?')

@dp.message_handler(state=AddProductState.start, content_types=types.ContentType.TEXT)
async def get_name(message: types.Message, state=FSMContext):
    if message.text:
        await state.update_data(name=message.text)
        await state.set_state(AddProductState.box)
        await message.answer('количество коробок на поддоне?')

@dp.message_handler(state=AddProductState.box, content_types=types.ContentType.TEXT)
async def get_name(message: types.Message, state=FSMContext):
    if message.text.isdigit():
        await state.update_data(boxs=int(message.text))
        await state.set_state(AddProductState.weight)
        await message.answer('сколько весит одна бутылка, если это весовой маргарин, то отправте цифру 1 ?')

@dp.message_handler(state=AddProductState.weight)
async def weight(message:types.Message, state:FSMContext):
    await state.update_data(weight=float(message.text))
    await state.set_state(AddProductState.quantity)
    await message.answer('сколько бутылок или килограмм в коробле ?')

@dp.message_handler(state=AddProductState.quantity, content_types=types.ContentType.TEXT)
async def get_price(message: types.Message, state=FSMContext):
    if message.text.isdigit():
        await state.update_data(quantity=int(message.text))
        await state.set_state(AddProductState.price)
        await message.answer('цена за бутылку или килограмм ?')

@dp.message_handler(state=AddProductState.price, content_types=types.ContentType.TEXT)
async def get_name(message: types.Message, state=FSMContext):
    try:
        price = float(message.text)
        data = await state.get_data()
        name = data['name']
        boxs = data['boxs']
        quantity = data['quantity']
        weight=data['weight']

        cargo = Cargonist()
        result = await cargo.add_product(name,boxs,quantity,price,weight)
        await state.set_state(CargoState.start)
        if result:
            await message.answer('товар добавлен в базу')
        else:
            await message.answer('ОШИБКА !!! товар с таким названием уже существует в методе add_product')
    except Exception as er:
        await message.answer(f'ОШИБКА !!! {er}')


#!/usr/bin/env python

import cv2
from cv2 import cv

def run(img):
  """
  Extract the channels
  """
  # If we pass None objects to cv.Split it will throw an assertion error,
  # so create three new matrices to hold the output.
  red = cv.CreateMat(img.height, img.width, cv2.CV_8UC1)
  green = cv.CreateMat(img.height, img.width, cv2.CV_8UC1)
  blue = cv.CreateMat(img.height, img.width, cv2.CV_8UC1)

  # Split the img into three channels
  cv.Split(img, red, green, blue, None)

  # Display the green channel (assuming RGB order)
  display(green, 'Green Channel')

  # Clone the green channel twice
  (clone1,clone2) = (cv.CloneMat(green),cv.CloneMat(green))

  # Find the green channel's min and max
  (minval,maxval,minloc,maxloc) = cv.MinMaxLoc(green)

  # Set the first clone to be some kind of threshold value
  # and the second to zeroes.
  thresh = int((maxval-minval)/2.0)
  cv.Set(clone1, thresh)
  cv.SetZero(clone2)

  # Then generate a mask from the original green channel and the matrix
  # of threshold values.
  cv.Cmp(green, clone1, clone2, cv.CV_CMP_GE)

  # Subtract half the threshold value from elements that exceed the threshold
  # (i.e. those matching the mask we generated).
  cv.SubS(green, thresh/2, green, clone2)
  display(green, 'Thresholded green')

def display(img, name):
  """
  Display the image
  """
  cv.NamedWindow(name, cv.CV_WINDOW_AUTOSIZE)
  cv.ShowImage(name, img)

  # Wait for a key press
  c = cv.WaitKey(0)

if __name__ == "__main__":
  # Load an example image
  img = cv.LoadImage('picture.jpg')
  run(img)


import os
import sys
import json
import logging
from http import HTTPStatus

import aiohttp

logger = logging.getLogger('user_info')

async def fetch(session, url, params):
    async with session.get(url, params=params) as resp:
        if resp.status == HTTPStatus.OK:
            data = await resp.json()
            if data['success']:
                return data
            else:
                code, msg = data['error']
                logger.error('Не удалось получить данные: %s, %s' % (code, msg))
        else:
            logger.critical('API не отвечает status_code=%d' % resp.status)
    return None

async def get_symbols():
    path = os.path.dirname(os.path.abspath(__file__))
    path = os.path.join(path, 'currencies.txt')
    if not (os.path.exists(path) and os.path.isfile(path)):
        logger.warning('Файла с валютами не существует %s' % path)

        async with aiohttp.ClientSession() as session:
            url = 'http://api.exchangeratesapi.io/v1/symbols'
            params = {'access_key': os.getenv('ACCESS_KEY')}
            data = await fetch(session, url, params=params)

        with open(path, mode='w') as f:
            if data is not None:
                f.write(json.dumps(data['symbols']))
                logger.info('Файл с валютами создан')
            else:
                logger.critical('Файл с валютами не создан')
                sys.exit()

    with open(path, mode='r') as f:
        # Получаем наименования всех валют
        return json.loads(f.read())


# import the necessary packages
from keras.models import Sequential
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dense
from keras import backend as K

class LeNet:
    @staticmethod
    def build(width, height, depth, classes):
        # initialize the model
        model = Sequential()
        inputShape = (height, width, depth)

        # if we are using "channels first", update the input shape
        if K.image_data_format() == "channels_first":
            inputShape = (depth, height, width)

        # first set of CONV => RELU => POOL layers
        model.add(Conv2D(20, (5, 5), padding="same",
                         input_shape=inputShape))
        model.add(Activation("relu"))
        model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

        # second set of CONV => RELU => POOL layers
        model.add(Conv2D(50, (5, 5), padding="same"))
        model.add(Activation("relu"))
        model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

        # first (and only) set of FC => RELU layers
        model.add(Flatten())
        model.add(Dense(500))
        model.add(Activation("relu"))

        # softmax classifier
        model.add(Dense(classes))
        model.add(Activation("softmax"))

        # return the constructed network architecture
        return model

"""
Lines 2-8 handle importing our required Python packages. The Conv2D  class is responsible for performing convolution.
We can use the MaxPooling2D  class for max-pooling operations.
As the name suggests, the Activation  class applies a particular activation function.
When we are ready to Flatten  our network topology into fully-connected, Dense  layer(s) we can use the respective class names.

The LeNet  class is defined on Line 10 followed by the build  method on Line 12.
Whenever I defined a new Convolutional Neural Network architecture I like to:

Place it in its own class (for namespace and organizational purposes)
Create a static build  function that builds the architecture itself
The build  method, as the name suggests, takes a number of parameters, each of which I discuss below:

width : The width of our input images
height : The height of the input images
depth : The number of channels in our input images (
    1  for grayscale single channel images,
    3  for standard RGB images which we’ll be using in this tutorial)
classes : The total number of classes we want to recognize (in this case, two)
We define our model  on Line 14. We use the Sequential  class since we will be sequentially adding layers to the model .

Line 15 initializes our inputShape  using channels last ordering (the default for TensorFlow).
If you are using Theano (or any other backend to Keras that assumes channels first ordering),
Lines 18 and 19 properly update the inputShape .

Now that we have initialized our model, we can start adding layers to it:

The CONV  layer will learn 20 convolution filters, each of which are 5×5.

We then apply a ReLU activation function followed by 2×2 max-pooling in both the x and y direction with a stride of two.
To visualize this operation, consider a sliding window that “slides” across the activation volume,
taking the max operation over each region, while taking a step of two pixels in both the horizontal and vertical direction.

Let’s define our second set of CONV => RELU => POOL  layers:

This time we are learning 50 convolutional filters rather than the 20 convolutional filters as in the previous layer set.
It’s common to see the number of CONV  filters learned increase the deeper we go in the network architecture.

Our final code block handles flattening out the volume into a set of fully-connected layers:

On Line 33 we take the output of the preceding MaxPooling2D  layer and flatten it into a single vector.
This operation allows us to apply our dense/fully-connected layers.

Our fully-connected layer contains 500 nodes (Line 34) which we then pass through another nonlinear ReLU activation.

Line 38 defines another fully-connected layer,
but this one is special — the number of nodes is equal to the number of classes  (i.e., the classes we want to recognize).

This Dense  layer is then fed into our softmax classifier which will yield the probability for each class.

Finally, Line 42 returns our fully constructed deep learning + Keras image classifier to the calling function.
"""


# project: p4
# submitter: kgschears@wisc.edu
# partner: none
# hours: 5
# Data: https://www.kaggle.com/datasets/equinxx/spotify-top-50-songs-in-2021
import pandas as pd
from flask import Flask, request, jsonify, Response
import re
import time
import matplotlib
# !!!!!!!
matplotlib.use('Agg') #very important for using matplotlib in the backend
#!!!!!!!

import matplotlib.pyplot as plt
from io import StringIO
# !!!!!!!
matplotlib.use('Agg') #very important for using matplotlib in the backend
#!!!!!!!

users={}
User_Count=0
Version_A=True
clicked_A=0
clicked_B=0
Version_B=None
data= pd.read_csv("main.csv")
app = Flask(__name__)
# df = pd.read_csv("main.csv")

@app.route('/')
def home():
    global User_Count
    global Version_A
    global clicked_A
    global clicked_B
    global Version_B
    User_Count+=1
    if Version_A and User_Count < 10 or User_Count > 10 and clicked_A > clicked_B:
        with open("index.html") as f:
            html = f.read()
    else:
        if not Version_B:
            new_html=""
            with open("index.html","r") as f:
                f.seek(0)
                old_html=f.readlines()
                new_html+="".join(old_html[:2])
                new_html+="\n \n"
                new_html+="".join(old_html[2:])
                Version_B = new_html
        html=Version_B
    Version_A= not Version_A #toggle boolean to switch to Version_B
    return Response(html,status=200)

# @app.route('/')
# def home():
#     global User_Count
#     global Version_A
#     global clicked_A
#     global clicked_B
#     User_Count+=1
#     if Version_A and User_Count < 10 or User_Count > 10 and clicked_A > clicked_B:
#         with open("index_Version_A.html") as f:
#             html = f.read()
#     else:
#         with open("index_Version_B.html") as f:
#             html = f.read()
#     Version_A= not Version_A #toggle boolean to switch to Version_B
#     return html

@app.route('/browse.html')
def browse():
    global data
    html="
Spotify Top 50 2021 Dataset
"
    html+=data.to_html()
    return Response(html,status=200)

@app.route('/browse.json')
def browse_json():
    global users
    global data
    # request.remote_addr a flask client variable that holds the clients IP address
    found= False
    if users.get(request.remote_addr):
        found=True
    if  not found or found and time.time()-users[request.remote_addr] > 60 :

        data_dict=data.to_dict("index")
        users[request.remote_addr]=time.time()
        return jsonify(data_dict)
    else:
        return Response(f"
Retry-After: {60-(time.time()-users[request.remote_addr])} seconds
",status=429, headers={"Retry-After": 60-(time.time()-users[request.remote_addr])})

@app.route('/donate.html')
def donate():
    global User_Count
    if User_Count < 10:
        global Version_A
        global clicked_A
        global clicked_B
        if not Version_A: # not Version_A means it is Version_A because boolean toggle at end of home() function!
            clicked_A+=1
        else:
            clicked_B+=1
    with open("donate.html") as f:
        html=f.read()
    return Response(html,status=200)

@app.route('/email', methods=["POST"])
def email():
    email = str(request.data, "utf-8")
    if re.match(r"^[a-zA-Z0-9]?[a-zA-Z0-9]*@{1}[a-zA-Z0-9]*\.com$", email): # 1
        with open("emails.txt", "a+") as f: # open file in append mode
            f.write(email + "\n") # 2
            f.seek(0)
            num_subscribed= len(f.readlines())
        return jsonify(f"thanks, you're subscriber number {num_subscribed}!")
    return jsonify("Enter vaild email or Will Smith will slap you in your sleep!") # 3

@app.route('/dashboard_1.svg', methods=["GET"])
def scatter_plot():
    fig, ax = plt.subplots(figsize=(5,5))
    global data
    args = request.args
    x_axis = args.get("x_axis")
    y_axis = args.get("y_axis")
    if x_axis and y_axis:
        x_ax=x_axis
        y_ax=y_axis
    else:
        # dancability vs acousticness  scatter plot
        x_ax="tempo"
        y_ax="acousticness"

    ax.scatter(x=data[x_ax], y=data[y_ax]) # same as data.plot.scatter(ax=ax, x=x_ax,y=y_ax)
    ax.set_xlabel(x_ax)
    ax.set_ylabel(y_ax)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.set_title(f"{x_ax} vs {y_ax} Top 50 song 2021")
    f = StringIO()
    fig.savefig(f, format="svg")
    plt.close() # closes the most recent fig

    svg = f.getvalue()

    hdr = {"Content-Type": "image/svg+xml"}
    return Response(svg, headers=hdr)

@app.route('/dashboard_2.svg')
def hist_plot():
    global data
    # histogram of artists and the number of count in the top 50 song list
    fig, ax = plt.subplots(figsize=(7,7))
    data["artist_name"].hist(ax=ax, bins=35)
    plt.xticks(rotation = 90)
    ax.margins(x=0)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.grid(False)
    ax.set_xlabel("Artist name")
    #----Need this block for every svg graph------
    f = StringIO()
    fig.savefig(f, format="svg", bbox_inches='tight',pad_inches = 0)
    plt.close() # closes the most recent fig
    svg = f.getvalue()
    hdr = {"Content-Type": "image/svg+xml"}
    #--------------------------------------------
    return Response(svg, headers=hdr)

if __name__ == '__main__':
    app.run(host="0.0.0.0", debug=True, threaded=False) # don't change this line!