from __future__ import annotations

from abc import ABCMeta, abstractmethod
from dataclasses import dataclass
from enum import Enum, auto
from concurrent.futures import ThreadPoolExecutor
from contextlib import AbstractContextManager

from common import types as T, time
from common.logging import log
from common.models.task import ExitCode, Task
from common.models.filesystems.types import BaseFilesystem
from .exceptions import NoCommonChecksumAlgorithm, PeriodNotStarted, NoTasksAvailable

class BaseStateProtocol(metaclass=ABCMeta):
    """
    Abstract base class for encapsulating communication with the
    underlying persistence engine (e.g., managing connections,
    performing queries, etc.) and application-level classes

    NOTE Must be thread-safe

    Implementations required:
    * filesystem_convertor :: *args x **kwargs -> BaseFilesystem
    """
    _filesystems:T.Dict[str, BaseFilesystem]

    def register_filesystems(self, *filesystems:BaseFilesystem) -> None:
        # Add filesystem instances to our internal mapping
        if not hasattr(self, "_filesystems"):
            self._filesystems = {}

        self._filesystems = {
            **self._filesystems,
            **{fs.name: fs for fs in filesystems}
        }

    @abstractmethod
    def filesystem_convertor(self, *args, **kwargs) -> BaseFilesystem:
        """
        Convert a persisted representation of a filesystem into its
        respective instance

        @param   *args, **kwargs        Necessary data from the
                                        persistence engine to map to the
                                        appropriate filesystem instance
        @raises  NoFilesystemConvertor  Ambiguous conversion
        @return  Filesystem instance
        """

FORCIBLY_TERMINATED  = ExitCode(-3)

# Verification failure handling
_MISMATCHED_SIZE     = ExitCode(-1)
_MISMATCHED_CHECKSUM = ExitCode(-2)

class _VerificationFailure(Exception):
    """ Raised on verification failure """

@dataclass
class _DurationMixin:
    """ Model for durations """
    start:T.Optional[T.DateTime]
    finish:T.Optional[T.DateTime]

    @property
    def runtime(self) -> T.TimeDelta:
        """ Phase runtime """
        if self.start is None:
            raise PeriodNotStarted("Period has yet to start")

        until = self.finish or time.now()
        return until - self.start

    @property
    def complete(self) -> bool:
        # Truthy once there's a finish timestamp
        return self.finish is not None

class _BaseDurationMixin(_DurationMixin, AbstractContextManager, metaclass=ABCMeta):
    """
    Abstract base class for setting the start and finish timestamps

    Implementations required:
    * init :: () -> T.DateTime
    * stop :: () -> T.DateTime
    """
    @abstractmethod
    def init(self) -> T.DateTime:
        """ Persist and return the duration start timestamp """

    @abstractmethod
    def stop(self) -> T.DateTime:
        """ Persist and return the duration finish timestamp """

    def __enter__(self) -> None:
        self.init()

    def __exit__(self, *exception) -> bool:
        self.stop()
        return False

@dataclass(frozen=True)
class JobThroughput:
    """ Model of throughput rates between filesystems """
    transfer_rate:float  # bytes/second
    failure_rate:float   # Probability

class JobPhase(Enum):
    """ Enumeration of job phases """
    Preparation = auto()
    Transfer    = auto()

# Convenience aliases
_PREPARATION = JobPhase.Preparation
_TRANSFER    = JobPhase.Transfer

class BasePhaseStatus(_BaseDurationMixin, metaclass=ABCMeta):
    """ Abstract base class for phase status """
    def __bool__(self) -> bool:
        return not self.complete

class _TaskOverviewMixin:
    """ Model for expressing job task overview """
    pending:int
    running:int
    failed:int
    succeeded:int

class BaseJobStatus(_TaskOverviewMixin, metaclass=ABCMeta):
    """
    Abstract base class for job and phase status

    Implementations required:
    * throughput :: BaseFilesystem x BaseFilesystem -> JobThroughput
    * phase      :: JobPhase -> BasePhaseStatus
    """
    def __bool__(self) -> bool:
        # Truthy when the preparation phase is still in progress or
        # there are still jobs pending (i.e., in progress)
        return self.phase(_PREPARATION) or self.pending > 0

    @abstractmethod
    def throughput(self, source:BaseFilesystem, target:BaseFilesystem) -> JobThroughput:
        """
        Return the throughput rates between the given filesystems

        @param   source            Source filesystem
        @param   target            Target filesystem
        @raise   NoThroughputData  No throughput data available
        @return  Job throughput
        """

    @abstractmethod
    def phase(self, phase:JobPhase) -> BasePhaseStatus:
        """
        Return the phase status for the specified phase

        @param   phase             Job phase
        @raise   PeriodNotStarted  Phase has yet to start
        @return  Phase status
        """

    @property
    def complete(self) -> bool:
        # Truthy when the transfer phase has ended (n.b., which is
        # dependent on the preparation phase ending)
        # NOTE Completion does not imply success!
        try:
            return not self.phase(_TRANSFER)

        except PeriodNotStarted:
            return False

class DataOrigin(Enum):
    """ Enumeration of data origins """
    Source = auto()
    Target = auto()

# Convenience aliases
_SOURCE = DataOrigin.Source
_TARGET = DataOrigin.Target

@dataclass
class _AttemptMixin:
    """ Model of task attempts """
    task:Task

class BaseAttempt(_AttemptMixin, _BaseDurationMixin, metaclass=ABCMeta):
    """
    Abstract base class for task attempts

    Implementations required:
    * size      :: DataOrigin -> int         Must be thread-safe!
    * checksum  :: DataOrigin x str -> int   Must be thread-safe!
    * exit_code :: Getter () -> ExitCode / Setter ExitCode -> None
    """
    @abstractmethod
    def size(self, origin:DataOrigin) -> int:
        """
        Persist and return the origin's data size

        NOTE Implementation must be thread-safe
        """

    @abstractmethod
    def checksum(self, origin:DataOrigin, algorithm:str) -> str:
        """
        Persist and return the origin's data checksum

        NOTE Implementation must be thread-safe
        """

    @property
    @abstractmethod
    def exit_code(self) -> ExitCode:
        """
        Fetch the task's exit code for this attempt, if available

        @raise  DataNotReady  No exit code yet available
        """

    @exit_code.setter
    @abstractmethod
    def exit_code(self, value:ExitCode) -> None:
        """ Persist the task's exit code for this attempt """

    def _get_source_properties(self, *algorithms:str) -> T.Tuple[int, T.Dict[str, str]]:
        # Fetch the source data's size and checksums using the specified
        # algorithms (to be run internally in a separate thread)
        return self.size(_SOURCE), \
               {algorithm: self.checksum(_SOURCE, algorithm) for algorithm in algorithms}

    def __call__(self) -> bool:
        """ Attempt the transfer task """
        # The context manager sets the attempt start and finish timestamps
        with self:
            task = self.task
            log.info(f"Attempting transfer of "
                     f"{task.source.address} on {task.source.filesystem} to "
                     f"{task.target.address} on {task.target.filesystem}")

            with ThreadPoolExecutor(max_workers=1) as executor:
                # TODO Different/multiple checksum algorithms
                properties = executor.submit(self._get_source_properties, "md5")

                # Run task in main tread and join on properties thread
                success = self.task()
                source_size, source_checksums = properties.result()

            if not success:
                log.warning(f"Attempt failed with exit code {success.exit_code}")

            else:
                log.info(f"Data copied; verifying...")

                try:
                    target_size = self.size(_TARGET)
                    if source_size != target_size:
                        log.warning(f"Attempt failed: "
                                    f"Source is {source_size} bytes; "
                                    f"target is {target_size} bytes")

                        success = _MISMATCHED_SIZE
                        raise _VerificationFailure()

                    # TODO Different/multiple checksum algorithms
                    source_checksum = source_checksums["md5"]
                    target_checksum = self.checksum(_TARGET, "md5")
                    if source_checksum != target_checksum:
                        log.warning(f"Attempt failed: "
                                    f"Source has checksum {source_checksum}; "
                                    f"target has checksum {target_checksum}")

                        success = _MISMATCHED_CHECKSUM
                        raise _VerificationFailure()

                    # TODO Data metadata: There is no need to set this
                    # for each intermediary stage; just set the final
                    # target metadata to that of the original source.
                    # Think about how to implement this...

                except _VerificationFailure:
                    pass

            self.exit_code = success
            return bool(success)

@dataclass
class DependentTask:
    """ Model of sequence of task dependencies """
    task:Task
    dependency:T.Optional[DependentTask] = None

class BaseJob(T.Iterator[BaseAttempt], metaclass=ABCMeta):
    """
    Abstract base class for jobs

    Implementations required:
    * __init__     :: Any x String x Optional[Identifier] x Boolean -> None
    * __iadd__     :: DependentTask -> BaseJob
    * attempt      :: Optional[TimeDelta] -> BaseAttempt
    * max_attempts :: Getter () -> Optional[Integer] / Setter Integer -> None
    * status       :: Getter () -> BaseJobStatus
    * metadata     :: Getter () -> SimpleNamespace
    * set_metadata :: kwargs -> None
    """
    _client_id:str
    _job_id:T.Identifier

    @abstractmethod
    def __init__(self, state:BaseStateProtocol, *, client_id:str, job_id:T.Optional[T.Identifier] = None, force_restart:bool = False) -> None:
        """
        Constructor

        @param  state          Encapsulation of the persisted state
        @param  client_id      Client identifier
        @param  job_id         Job ID for a running job
        @param  force_restart  Whether to forcibly resume a job
        """

    @abstractmethod
    def __iadd__(self, task:DependentTask) -> BaseJob:
        """ Add a sequence of dependent tasks to the job """
        # NOTE The root source is assumed to exist, so we can query its
        # size. Ideally, this size should be persisted along with the
        # task, as THERE IS NO OTHER INTERFACE FOR DOING SO. Without it,
        # it would be impossible to make transfer rate calculations.

    def __iter__(self) -> BaseJob:
        return self

    def __next__(self) -> BaseAttempt:
        # The next pending task to attempt, *regardless* of time limit
        try:
            return self.attempt()

        except NoTasksAvailable:
            if self.status.complete:
                raise StopIteration()

    @property
    def job_id(self) -> T.Identifier:
        return self._job_id

    @abstractmethod
    def attempt(self, time_limit:T.Optional[T.TimeDelta] = None) -> BaseAttempt:
        """
        Fetch the next pending task to attempt, given the optional time
        limit (which is ignored, if no timing statistics are available)

        @param   time_limit  Only fetch attempts that are predicted to
                             complete within this duration (optional;
                             defaults to None, to ignore time limits)
        @return  Attempt
        """

    @property
    @abstractmethod
    def max_attempts(self) -> int:
        """ Get the maximum number of attempts for a task """

    @max_attempts.setter
    @abstractmethod
    def max_attempts(self, value:int) -> None:
        """ Set the maximum number of attempts for a task """

    @property
    @abstractmethod
    def status(self) -> BaseJobStatus:
        """ Get the current job status """

    # TODO Make the client metadata interface nicer

    @property
    @abstractmethod
    def metadata(self) -> T.SimpleNamespace:
        """ Get the job metadata """

    @abstractmethod
    def set_metadata(self, **metadata:str) -> None:
        """ Set (insert/update) key-value metadata """


from fastapi.testclient import TestClient

from app.main import app

class TestRequests:
    def setup_class(self):
        self.clients = [
            TestClient(app),
            TestClient(app),
            TestClient(app),
            TestClient(app),
        ]
        self.players = [
            {
                "username": "111",
                "password": "1",
                "avatar": "lama",
            },
            {
                "username": "222",
                "password": "2",
                "avatar": "lama",
            },
            {
                "username": "333",
                "password": "3",
                "avatar": "lama",
            },
            {
                "username": "444",
                "password": "4",
                "avatar": "lama",
            },
        ]
        self.game_ids = []
        self.cards = []

    # def test_create_users(self):
    #     for player in self.players:
    #         res = self.clients[0].post("v1/create_user", json=player)
    #         assert res.status_code == 200
    #         assert "uid" in res.json()
    #         assert res.json()["username"] == player["username"]
    #         player["uid"] = res.json()["uid"]

    def test_login_users(self):
        for i, client in enumerate(self.clients):
            res = client.post("v1/token", data=self.players[i])
            assert res.status_code == 200
            assert "access_token" in res.json()
            assert "token_type" in res.json()
            assert res.json()["token_type"] == "bearer"

            token = res.json()["access_token"]
            self.clients[i].headers.update(
                {"Authorization": f"Bearer {token}"})

    def test_request_initialize_game(self):
        res = self.clients[0].post("v1/games?seed=1",
                                   json={"game_name": "test_game", "n_players": 4})

        assert res.status_code == 200
        assert type(res.json()["game_token"]) == str
        self.game_token = res.json()["game_token"]
        self.game_ids += [res.json()["game_id"]]

    def test_join_game(self):
        for i, client in enumerate(self.clients[1:]):

            res = client.post(f"v1/games/{self.game_ids[0]}/join")
            assert res.status_code == 200, res.json()

    def test_request_get_game_list(self):
        res = self.clients[0].get("v1/games")

        assert res.status_code == 200
        assert len(res.json()) == 1
        for idx, game_id in enumerate(self.game_ids):
            assert game_id == res.json()[idx]["game_id"]

    def test_get_individual_game_data(self):
        print(self.game_ids)
        res = self.clients[0].get(
            f"v1/games/{self.game_ids[0]}", json=self.players[0])
        assert res.status_code == 200

        assert res.json()["game_id"] == self.game_ids[0]
        assert len(res.json()["players"]) == len(res.json()["order"])
        assert res.json()["active_player_index"] == 0

    def test_change_team(self):
        res = self.clients[0].get(
            f"v1/games/{self.game_ids[0]}", json=self.players[0])

        old_order = res.json()["order"]

        res = self.clients[2].post(
            f"v1/games/{self.game_ids[0]}/player_position",
            json=1,
        )
        print(res.json())
        assert res.status_code == 200
        assert res.json()["order"] == [old_order[0],
                                       old_order[2], old_order[1], old_order[3]]

        # reset the game order
        res = self.clients[1].post(
            f"v1/games/{self.game_ids[0]}/player_position",
            json=1,
        )

        assert res.status_code == 200
        assert res.json()["order"] == old_order

    def test_start_game_and_check_cards(self):
        res = self.clients[0].post(f"v1/games/{self.game_ids[0]}/start")

        assert res.status_code == 200

        players = res.json()["player_list"]

        for i in range(4):
            for j in range(4):
                # the j-th marble of the i-th player should have the position below
                marble_j = players[i]["marbles"][j]
                assert marble_j["position"] == -i * 4 - j - 1

        res = self.clients[0].get(
            f"v1/games/{self.game_ids[0]}/cards",
        )
        assert res.status_code == 200

        print(res.json())
        assert res.json()["hand"][0]["uid"] == 99
        self.cards.append(res.json()["hand"])

        for i in range(1, 4):
            res = self.clients[i].get(f"v1/games/{self.game_ids[0]}/cards")
            assert res.status_code == 200

            self.cards.append(res.json()["hand"])

    def test_swap_cards(self):
        res = self.clients[0].post(
            f"v1/games/{self.game_ids[0]}/swap_cards", json=self.cards[0][0]
        )
        assert res.status_code == 200

        for i in range(1, 4):
            res = self.clients[i].post(
                f"v1/games/{self.game_ids[0]}/swap_cards", json=self.cards[i][0]
            )
            assert res.status_code == 200

        for i in range(4):
            res = self.clients[i].get(f"v1/games/{self.game_ids[0]}/cards")
            assert res.status_code == 200
            self.cards[i] = res.json()["hand"]
            assert len(self.cards[i]) == 6

        assert any([card["uid"] == 99 for card in self.cards[2]])


from random import randint, choice
import pygame as pg

class ShroomFilter(object):
    def __init__(self, size):
        size = pg.display.get_surface().get_size()
        self.surface = pg.Surface(size).convert_alpha()
        #self.surface.set_alpha(50)
        self.colors = [(0, 0, 127, 127), (127, 0, 0, 127), (127, 0, 127, 127),
                            (0, 127, 0, 127), (127, 127, 127, 127)]
        self.ticks = 0

    def update(self):
       self.ticks += 1

    def draw(self, surface):
        if not self.ticks % 5:
            self.surface.fill(choice(self.colors))

        surface.blit(self.surface, (0, 0))


from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import QPixmap
from PIL import Image
import numpy as np
from commonInterface import *
import findVessels

def runInterface(data):
    app = QApplication([]);
    window = QWidget();

    inter = interface(data);
    window.setLayout(inter.layout);
    window.resize(1480, 720)

    window.show();
    app.exec_();
    return inter.segmentedData;

class interface:
    def __init__(self, data):
        # Current coords
        self.z = 0;
        self.imagesLoaded = 300
        self.data = np.array(data, np.uint16);
        self.edgeMap = np.array(data, np.uint16);
        self.segmentedData = np.array(data);

        # In pyqt widgets must be stacked vertically or horizontally. To achive
        # to achive the desired layout they are stored in larger containers

        ### Basic controls
        # Create widgits
        self.xControl = sliderControl("x", data.shape[0] - 1);
        self.initalThresh = sliderControl("Initial threshold", 255);
        self.finalThresh = sliderControl("Final threshold", 255);

        # Connect widgits
        self.xControl.slider.valueChanged.connect(lambda: self.updateCoords(self.xControl.value));
        self.initalThresh.slider.valueChanged.connect(lambda: self.updateThresholds(self.initalThresh.value, self.finalThresh.value));
        self.finalThresh.slider.valueChanged.connect(lambda: self.updateThresholds(self.initalThresh.value, self.finalThresh.value));

        # Create layout
        self.basicControls = QVBoxLayout();
        self.basicControls.addLayout(self.xControl.layout);
        self.basicControls.addLayout(self.initalThresh.layout);
        self.basicControls.addLayout(self.finalThresh.layout);

        ### Erosion iteration controls (for opencv's fastNlMeansDenoising)
        # Create widgets
        self.kernelSize = labeledEdit("Kernel size");
        self.cannyHiThresh = labeledEdit("Canny edge detection high threshold")
        self.cannyLoThresh = labeledEdit("Canny edge detect low threshold");
        self.erosionCount = labeledEdit("Number of erosion steps")
        self.contourLengthThresh = labeledEdit("Min contour length");
        self.iterations = labeledEdit("Number of iterations");
        self.segmentButton = QPushButton("Segment data");

        #  Connect widgets
        self.segmentButton.clicked.connect(lambda: self.updateEdgeMap( \
        self.kernelSize.getVal(), self.cannyLoThresh.getVal(), self.cannyHiThresh.getVal(), \
        self.erosionCount.getVal(), "Circle", self.iterations.getVal(), \
        self.initalThresh.value, self.finalThresh.value));

        # Create layout
        self.segmentationControls = QVBoxLayout();
        self.segmentationControls.addLayout(self.kernelSize.layout);
        self.segmentationControls.addLayout(self.cannyHiThresh.layout);
        self.segmentationControls.addLayout(self.cannyLoThresh.layout);
        self.segmentationControls.addLayout(self.erosionCount.layout);
        self.segmentationControls.addLayout(self.contourLengthThresh.layout);
        self.segmentationControls.addLayout(self.iterations.layout);
        self.segmentationControls.addWidget(self.segmentButton);

        ### Connect noise filter to saturatoin layout
        self.filterPanel = QHBoxLayout();
        self.filterPanel.addLayout(self.basicControls);
        self.filterPanel.addLayout(self.segmentationControls);

        ### Allow cleaned files to be saved
        # Create widgets
        self.savePathSelect = labeledEdit("Save path");
        self.saveButton = QPushButton("Save");
        self.startPoint = labeledEdit("Start");
        self.endPoint = labeledEdit("End");

        ### Display image
        self.image = QLabel("loop");
        self.pixmap = QPixmap('Flamboyant_Potato.jpg');
        self.image.setPixmap(self.pixmap);

        ### Connect image to control layouts
        self.layout = QVBoxLayout();
        self.layout.addWidget(self.image);
        self.layout.addLayout(self.filterPanel);

    # Updates viewpoint coordinates
    def updateCoords(self, zVal):
        self.z = zVal;
        self.updateImage();

    def updateEdgeMap(self, kernelSize, cannyThreshLo, cannyThreshHi, \
    erosionCount, kernel, iterations, initialThreshold, finalThreshold):
        # Update classes' edgemap
        self.edgeMap = findVessels.generateConfidencemap( \
        self.data, kernelSize, cannyThreshHi, cannyThreshLo, \
        erosionCount, kernel, iterations);
        # Generate new segmented data so image is changed
        self.segmentedData = findVessels.generateSegmentedImage(self.data, self.edgeMap, initialThreshold, finalThreshold);
        self.updateImage();

    def updateThresholds(self, initialThreshold, finalThreshold):
        self.segmentedData = findVessels.generateSegmentedImage(self.data, self.edgeMap, initialThreshold, finalThreshold);
        self.updateImage();

    # Updates the image displayed
    def updateImage(self):
        self.genImage("./", self.z);
        self.pixmap = QPixmap("./workingImg.png");
        self.image.setPixmap(self.pixmap);

    def genImage(self, path, z):
        #try:
        # Create base
        composite = Image.new('RGB', (self.data[z].shape[0]*2, self.data[z].shape[1]))

        # Create images
        originalData = Image.fromarray(self.data[z]);
        originalData = originalData.convert('RGB');
        segmentedLayer = Image.fromarray(self.segmentedData[z]);
        segmentedLayer = segmentedLayer.convert('RGB');
        mask = Image.fromarray(self.segmentedData[z]);
        mask = mask.convert('L');

        # convert segmented layer to red
        matrix = (1.0, 0.0, 0.0, 0.0,   0.0, 0.0, 0.0, 0.0,   0.0, 0.0, 0.0, 0.0);
        segmentedLayer = segmentedLayer.convert('RGB',matrix);

        # paste images together
        composite.paste(originalData, (0, 0));
        composite.paste(originalData, (self.data[z].shape[0], 0));
        composite.paste(segmentedLayer, (self.data[z].shape[0], 0), mask);

        composite.save(path + "workingImg" + ".png");
        #except:
            #print("out of range of images");
            #print(self.data.shape);


import requests
import pandas
import os
from bs4 import BeautifulSoup

cwd_original = os.getcwd()
output_files = cwd_original + '/data/2022/2022'

url_links = []
issue = 1
while issue != 13:
    url = f"https://link.springer.com/journal/256/volumes-and-issues/51-{issue}"
    issue = issue + 1
    url_links.append(url)

for link in range(len(url_links)):
    dates = ['-Jan','-Feb','-Mar','-Apr','-May','-Jun','-Jul','-Aug','-Sep','-Oct','-Nov','-Dec']
    page = requests.get(url_links[link])
    soup = BeautifulSoup(page.text, 'html.parser')
    Category = soup.find_all('li',class_='c-meta__item c-meta__item--block-sm-max')
    Categories = []
    for item in Category:
        C = item.text
        C = C.strip()
        C = C.replace('\n','')
        C = C.replace('Content type: ','')
        Categories.append(C)
    len(Categories)

    Title = soup.find_all('h3',class_='c-card__title')
    Titles = []
    for item in Title:
        T = item.text
        T = T.strip()
        T = T.replace('\n','')
        Titles.append(T)
    len(Titles)
    Author = soup.find_all('div',class_='u-mb-8')
    Authors = []
    for item in Author:
        A = item.text
        A = A.strip()
        A = A.replace('\n',' ')
        Authors.append(A)
    len(Authors)
    A = [x for x in Categories if not x.startswith('Published')]
    B = [x for x in A if not x.startswith('Pages')]
    list0 = [x for x in B if not x.startswith('Open Access')]
    list1 = Titles
    list2 = Authors
    df = pandas.DataFrame({'Article Class': pandas.Series(list0), 'Article Titles': pandas.Series(list1), 'List of Article Author Names': pandas.Series(list2)})

    df['List of Article Author Names'] = df['List of Article Author Names'].replace(r'(([a-z])([A-Z]))', r'\2,\3', regex=True)
    df['First Author'] = df['List of Article Author Names'].str.rsplit(',').str[0]
    df['Last Author'] = df['List of Article Author Names'].str.rsplit(',').str[-1]

    df.to_csv(output_files + dates[link] + '.csv', index=False)
    print('...finished with link: ' + url_links[link])


#!/usr/bin/env python
'''
usage: certificates [-h] [--output OUTPUT] participants template

positional arguments:
  participants          csv filaname containing participants
  template              certificate template in svg format used to build

optional arguments:
  -h, --help            show this help message and exit
  --output OUTPUT, -o OUTPUT
                        destination of the generated certificates
'''
import csv
import os
from pathlib import Path

def import_from_csv(csv_filename):
    with open(csv_filename) as file:
        table = csv.DictReader(file)
        for row in table:
            yield row

def make_certificates(participants_path, template_path, output_path):
    # svg used as template
    base_svg = Path(template_path)
    # retrieve participants list
    participants = import_from_csv(participants_path)
    # Create output directory if not exists
    output_directory = Path(output_path)
    output_directory.mkdir(exist_ok=True)

    for participant in participants:
        new_svg = base_svg.read_text(encoding='utf-8').format(**participant)
        output_filename = output_directory / f'{participant["name"]}.svg'
        output_svg = Path(output_filename)
        output_svg.write_text(new_svg)
        png_filename = str(output_filename).replace("svg", "png")
        os.system(f'inkscape -z -e "{png_filename}" "{output_filename}"')
        output_svg.unlink()


# nohup python -u activeAuthorExtraction.py > activeAuthorExtractionFoRCAS.log 2>&1 &

import jsonlines
from tqdm import tqdm
import pickle as pk
# 抽取比较活跃的作者

# 考虑作者位次的作者发文数量，必须大于1
def AuthorCount(YearPublist, authorRank):
# yearPublist  {2023:{'rank1':set(), 'rankLast':set(), 'others':set() }, ...}
    count = 0
    if authorRank != 'both':
        for year, publist in YearPublist.items():
            if len(publist[authorRank]) > 0:
                count += 1
    else:
        for year, publist in YearPublist.items():
            if len(publist['rank1']) > 0 or len(publist['rankLast']) > 0:
                count += 1
    return count
# 按时间排序
def AuthorPublistTimeRank(YearPublist):
    YearPublistRanked = {}
    for k,v in sorted(YearPublist.items()):
        # 如果一个人的发文序列中，有不存在的年份，直接给这个人drop掉（数量应该极少）
        if int(k) < 1801 or int(k) > 2021:
            return ''
        YearPublistRanked[k] = v
    return YearPublistRanked

# 开始年份
def commonstartYearpublist(publist):
    return int(list(publist.keys())[0])
# 休止年份
def commonendYearpublist(publist):
    return int(list(publist.keys())[-1])
# 年份跨度
def commonspanYearpublist(publist):
    return commonendYearpublist(publist) - commonstartYearpublist(publist)

# 这里抽出来所有曾经至少2年，以第一作者或末位作者身份发表过论文的作者，全部的发文序列。
with jsonlines.open('../../../DataCrossBoundaryPerspective_InterdisciplinaryResearch/activeAuthorSeqForCAS.jsonl', mode='w') as writer:
    with jsonlines.open('../../../DataCrossBoundaryPerspective_InterdisciplinaryResearch/CASauthorSeq.jsonl', mode='r') as reader:
        for lines in tqdm(reader):
            for authorID, YearPublist in lines.items():
                # 至少有2年以第一作者身份或末位作者身份，发论文
                if AuthorCount(YearPublist,'both') > 1:
                    #按时间顺序排序，同时丢掉离谱的时间
                    temp = AuthorPublistTimeRank(YearPublist)
                    if temp == '':
                        continue
                    # 大于80显然不是正常的学术生涯轨迹，去掉
                    if commonspanYearpublist(temp) < 81:
                        writer.write({authorID: temp})
# print(authornumPubYearsFreq)
# print(Rank1authornumPubYearsFreq)
# print(RankLasTauthornumPubYearsFreq)
# print(RankIMportantAuthornumPubYearsFreq)

# pk.dump(authornumPubYearsFreq, open('../../../DataCrossBoundaryPerspective_InterdisciplinaryResearch/authornumPubYearsFreq.pk', 'wb'))
# pk.dump(Rank1authornumPubYearsFreq, open('../../../DataCrossBoundaryPerspective_InterdisciplinaryResearch/Rank1authornumPubYearsFreq.pk', 'wb'))
# pk.dump(RankLasTauthornumPubYearsFreq, open('../../../DataCrossBoundaryPerspective_InterdisciplinaryResearch/RankLasTauthornumPubYearsFreq.pk', 'wb'))
# pk.dump(RankIMportantAuthornumPubYearsFreq, open('../../../DataCrossBoundaryPerspective_InterdisciplinaryResearch/RankIMportantAuthornumPubYearsFreq.pk', 'wb'))


import json
import os

def read_txt(sentences):
    sentences = sentences.split("\n")
    pairs = []
    for pair in sentences:
        if pair:
            rec = pair.split("\t")
            pairs.append([int(rec[0]), int(rec[1])])
    return pairs

def read_precision(sentences, map_dict):
    sentences = sentences.split("\n")
    pairs = []
    all_precision = []
    for pair in sentences:
        if pair:
            rec = pair.split("\t")
            if rec:
                r1 = map_dict[0][rec[0]]
                r2 = map_dict[1][rec[1]]
                item = [r1, r2]
                if item not in all_precision:
                    all_precision.append(item)
    return pairs, all_precision

def read_dir(path):
    block_file_path = os.path.join(path, "block_map.json")
    prec_file_path = os.path.join(path, "precision.txt")

    if os.path.exists(block_file_path):
        with open(block_file_path, "r+", encoding="utf-8") as f:
            map_dict = json.loads(f.read())

        if os.path.exists(prec_file_path):
            with open(prec_file_path, "r+", encoding="utf-8") as f:
                s = f.read()
                pairs, precisions = read_precision(s, map_dict)
            return precisions
        else:
            print(prec_file_path, "doesn't exist")
    else:
        print(block_file_path, "doesn't exist")
    return None

def cal_prec(dataset, blocks):
    path = "../../data_block/%s/%d" % (dataset, blocks)

    all_precision = []
    for i in range(1, blocks+1):
        block_path = os.path.join(path, str(i))
        precisions = read_dir(block_path)
        all_precision += precisions

    with open("../../data_block/%s/%d/all_precision.json" % (dataset, blocks), "w+", encoding="utf-8") as f:
        f.write(json.dumps(all_precision))


import io
import sys

_INPUT = """\
6
4
1 3 2 4
10
5 8 2 2 1 6 7 2 9 10
"""

sys.stdin = io.StringIO(_INPUT)
case_no=int(input())
for __ in range(case_no):
  N=int(input())
  A=list(map(lambda x: int(x)-1,input().split()))
  n=len([1 for i in range(N) if A[i]==i])
  ans=n*(n-1)//2
  m=0
  for i in range(N):
    if A[i]!=i and A[A[i]]==i: m+=1
  print(ans+m//2)


"""
Test LTI web components of the application
"""
import json
import logging
import os
import time
import unittest

from mock import patch

import xsiftx.config
from xsiftx.config import get_config, get_consumer, XsiftxNoConfigException
from xsiftx.util import get_sifters
from xsiftx.lti.decorators import LTI_STAFF_ROLES
import xsiftx.web

class TestLTIWebApp(unittest.TestCase):
    """
    Test class for validating LTI interface
    to xsiftx.
    """
    # pylint: disable=e1103,r0904

    def setUp(self):
        """
        grab application test client
        """
        # pylint: disable=C0103
        self.client = xsiftx.web.app.test_client()
        self.settings = get_config()

    def _oauth_request(self, params={}, consumer_id=0):
        """
        Returns the data needed for an oauth request
        and adds those to the passed dictionary to
        keep out of the way.
        """
        # pylint: disable=w0102
        consumer = self.settings['consumers'][consumer_id]
        params.update({
            'oauth_consumer_key': consumer['key'],
            'oauth_signature_method': 'PLAINTEXT',
            'oauth_version': '1.0',
            'oauth_signature': '{0}&'.format(consumer.get('secret', '')),
            'oauth_timestamp': str(int(time.time())),
            'oauth_nonce': '123456789',
            'context_id': 'MITx/A.we/some'
        })
        return params

    def _run_sifter(self, sifter='test_sifters'):
        """
        Run a valid sifter and return json from response
        """
        test_url = 'api/v0.1/run'
        response = self.client.post(
            test_url,
            data=self._oauth_request({'sifter': sifter}, 1)
        )
        self.assertEqual(response.status_code, 200)
        return json.loads(response.data)

    def test_conf_settings(self):
        """
        Test and validate configuration and test rigging
        """
        self.assertEqual(
            self.settings['consumers'],
            [
                {'key': 'test_course1',
                 'secret': 'test_secret1',
                 'allowed_sifters': ['test_sifters']},
                {'key': 'test_course2',
                 'secret': 'test_secret2', },
                {'key': 'testo', },
            ]
        )

        # Test consumer search
        consumer = get_consumer('test_course1')
        self.assertEqual(consumer['secret'], 'test_secret1')

        # Test config exception
        conf_save = os.environ['XSIFTX_CONFIG']
        config_path_save = xsiftx.config.CONFIG_PATHS
        del os.environ['XSIFTX_CONFIG']

        xsiftx.config.CONFIG_PATHS = ['/dev/null', ]
        with self.assertRaisesRegexp(XsiftxNoConfigException,
                                     'No configuration found'):
            settings = get_config()

        # Test config by path
        xsiftx.config.CONFIG_PATHS = [conf_save, ]
        settings = get_config()
        self.assertEqual(settings['awesome_canary_key'], 'test')

        os.environ['XSIFTX_CONFIG'] = conf_save
        xsiftx.config.CONFIG_PATHS = config_path_save

    @patch('xsiftx.lti.oauthstore.log')
    def test_no_consumers(self, mock_logging):
        """
        Make sure we handle a lack of conumers altogether well
        """
        saved_consumers = xsiftx.config.settings['consumers']
        del xsiftx.config.settings['consumers']

        response = self.client.post('/', data=self._oauth_request())
        self.assertEquals(response.status_code, 401)
        self.assertTrue(mock_logging.critical.called_with(
            "No consumers defined in settings."
            "Have you created a configuration file?"
        ))

        # Restore
        xsiftx.config.settings['consumers'] = saved_consumers

    @patch('xsiftx.lti.oauthstore.log')
    def test_consumer_without_secret(self, mock_logging):
        """
        Test a consumer that is missing a secret.
        """
        keyless_consumer = 2
        response = self.client.post(
            '/',
            data=self._oauth_request(
                {'oauth_secret': 'test&'},
                keyless_consumer
            )
        )
        self.assertEquals(response.status_code, 401)
        self.assertTrue(mock_logging.critical.called_with(
            'Consumer {0}, is missing secret'
            'in settings file, and needs correction.'.format(
                self.settings['consumers'][keyless_consumer]['key']
            )
        ))

    def test_lti_authentication(self):
        """
        Test out that LTI authentication is working properly
        and that the decorator is raising the proper exceptions
        """
        # Setup empty request
        response = self.client.get('/')
        self.assertEqual(response.status_code, 401)
        self.assertTrue(
            'This page requires a valid oauth session or request' in
            response.data
        )

        # Test bad key
        params = self._oauth_request()
        params['oauth_consumer_key'] = 'silly'
        response = self.client.post('/', data=params)
        self.assertEqual(response.status_code, 401)
        self.assertTrue(
            'OAuth error: Please check your key' in
            response.data
        )

        # Test bad sig
        params = self._oauth_request()
        params['oauth_signature'] = 'silly&'
        response = self.client.post('/', data=params)
        self.assertEqual(response.status_code, 401)
        self.assertTrue(
            'OAuth error: Please check your key' in
            response.data
        )

        # Valid OAuth, but missing authorization
        response = self.client.post('/', data=self._oauth_request())
        self.assertEqual(response.status_code, 401)
        self.assertTrue(
            'User does not have a role' in
            response.data
        )

        # Test https header
        with xsiftx.web.app.test_client() as client:
            response = client.post(
                '/', data=self._oauth_request(),
                headers={'x-forwarded-proto': 'https'}
            )
        self.assertEqual(response.status_code, 401)
        self.assertTrue(
            'User does not have a role' in
            response.data
        )

    def test_lti_staff_decorator(self):
        """
        Make sure that our authorization of role is happening
        """
        params = self._oauth_request({'roles': 'Student'})
        response = self.client.post('/', data=params)
        self.assertEqual(response.status_code, 401)
        self.assertTrue(
            'You are not in a staff level role. Access is restricted ' in
            response.data
        )

    def test_reauthorization(self):
        """
        Make sure that if my role changes, my access changes as well.
        """
        params = self._oauth_request({'roles': 'Student'})
        response = self.client.post('/', data=params)
        self.assertEqual(response.status_code, 401)
        self.assertTrue(
            'You are not in a staff level role. Access is restricted ' in
            response.data
        )

        params = self._oauth_request({'roles': 'Instructor'})
        response = self.client.post('/', data=params)
        self.assertEqual(response.status_code, 200)

    def test_index(self):
        """
        Several tests of the index page
        """
        params = self._oauth_request({'roles': LTI_STAFF_ROLES[0]})
        response = self.client.post('/', data=params)
        self.assertEqual(response.status_code, 200)
        self.assertTrue(
            'Available Sifters' in
            response.data
        )

    def test_sifter_acl(self):
        """
        Test with consumer that has access to all sifters
        and ensure they all get loaded
        """
        # Test limited ACL
        with xsiftx.web.app.test_client() as client:
            consumer_id = 0
            params = self._oauth_request(
                {'roles': LTI_STAFF_ROLES[0]},
                consumer_id
            )
            response = client.post('/', data=params)
            self.assertEqual(response.status_code, 200)
            self.assertTrue(
                'Available Sifters' in
                response.data
            )
            # Make sure we don't have extra sifters
            self.assertTrue(
                all(sifter in response.data
                    for sifter in
                    self.settings['consumers'][consumer_id]['allowed_sifters'])
            )

        # Test no ACL
        with xsiftx.web.app.test_client() as client:
            consumer_id = 1
            params = self._oauth_request(
                {'roles': LTI_STAFF_ROLES[0]},
                consumer_id
            )
            response = client.post('/', data=params)
            self.assertEqual(response.status_code, 200)
            self.assertTrue(
                'Available Sifters' in
                response.data
            )
            # Make sure we don't have extra sifters
            self.assertTrue(
                all(sifter in response.data
                    for sifter in get_sifters())
            )

    def test_api_error(self):
        """
        Excercise the API error handler to make sure it returns
        json.
        """

        test_url = '/api/v0.1/run'

        # Test that LTI error on API url returns JSON instead of html
        response = self.client.post(test_url)
        self.assertEqual(response.status_code, 401)
        json.loads(response.data)

        # Test no sifter
        response = self.client.post(
            test_url,
            data=self._oauth_request()
        )
        self.assertEqual(response.status_code, 400)
        # Should raise if we don't get json
        reply_json = json.loads(response.data)
        self.assertTrue(
            u'This api call requires the parameter "sifter".' ==
            reply_json['message']
        )

        # Test invalid sifter
        response = self.client.post(
            test_url,
            data=self._oauth_request({'sifter': 'not_a_real_thing'})
        )
        self.assertEqual(response.status_code, 400)
        # Should raise if we don't get json
        reply_json = json.loads(response.data)
        self.assertTrue(
            u'You have specified an invalid sifter.' ==
            reply_json['message']
        )
        self.assertIsNotNone(reply_json.get('available_sifters', None))

    def test_run_sifter(self):
        """
        Test out the run command
        """
        reply_json = self._run_sifter()
        # Even though the job should fail, we should get
        # back the job id and such
        self.assertTrue(reply_json['tasks'][0]['status'] == 'PENDING')

    def test_task_status_and_delete(self):
        """
        Test task status API point and validate response json
        """
        update_url = '/api/v0.1/update_task_status'
        # Create several runs
        num_runs = 10
        for _ in range(num_runs):
            reply_json = self._run_sifter('xqanalyze')

        # Check we have the right number
        response = self.client.put(
            update_url,
            data=self._oauth_request()
        )
        reply_json = json.loads(response.data)
        self.assertTrue(len(reply_json['tasks']), num_runs)

        # Now delete them
        delete_url = '/api/v0.1/clear_complete_tasks'
        response = self.client.delete(
            delete_url,
            data=self._oauth_request()
        )
        reply_json = json.loads(response.data)
        self.assertTrue(len(reply_json['tasks']), 0)

        # And double check they are gone
        # Check we have the right number
        response = self.client.put(
            update_url,
            data=self._oauth_request()
        )
        reply_json = json.loads(response.data)
        self.assertTrue(len(reply_json['tasks']), 0)

    def test_logging_level(self):
        """
        Tests to make sure logging config happens and handles
        bad output.
        """
        # Check it is the right setting from test config
        self.assertEqual(self.settings['log_level'], 'debug')
        level = xsiftx.web.set_log_level()
        # Check that setting is not applied
        self.assertEqual(logging.DEBUG, level)

        # Set to invalid level and assert the exception
        xsiftx.config.settings['log_level'] = 'awesome'
        with self.assertRaisesRegexp(ValueError, 'Invalid log level.*'):
            level = xsiftx.web.set_log_level()
            self.assertIsNone(level)

        # Make sure it is ok not to have a level set
        del xsiftx.config.settings['log_level']
        level = xsiftx.web.set_log_level()
        self.assertIsNone(level)

        # Restore setting
        xsiftx.config.settings['log_level'] = 'debug'


import requests
from requests_html import HTML
import concurrent.futures
import time
from decorators import my_time, timer
import itertools
import logging

step = 20
fromc = 421
toc = 720

counter = itertools.count()
t1 = time.time()

#Directory to save the downloaded files
dir = r'D:\One_Piece\\' #include an extra '\'
homepage = requests.get('https://www.mangapanda.com/one-piece')
titles = HTML(html = homepage.text)
titles = titles.find('td')
titles = titles[22:-4:2]

def getchapter(chapter):
    """To change chapter number into desired format for saving"""
    chapter = str(chapter)
    if int(chapter) < 10:
        chapter = '00' + chapter
    elif int(chapter) < 100:
        chapter = '0' + chapter
    return chapter

def getpage(page):
    """To change pages number into desired format for saving"""
    page = str(page)
    if int(page) < 10:
        page = '0' + page
    return page

def download_img(source, name):
    # print(f'Source: {source}')
    # print(f'Name: {name}')
    img = requests.get(source)

    with open(name,'wb') as file:
        file.write(img.content)

    pages = next(counter)

@my_time
def download_chapters(chapter):
    site = 'https://www.mangapanda.com'
    link = '/one-piece/'+str(chapter)
    mangalink = requests.get(site+link)
    html = HTML(html = mangalink.text)
    article = html.find('div#selectpage')
    pages = int(article[0].text.split()[-1])
    for page in range(1,pages+1):
        title = titles[chapter-1].text.split(': ')[-1]
        if title.endswith(':'):
            title = title[:-5]
        # print('Parsing Chapter '+str(chapter)+'. '+title+' Page '+str(page))
        if page != 1:
            mangalink = requests.get(site+link)
            html = HTML(html = mangalink.text)
        image = html.find('div#imgholder',first = True)
        img_src = image.find('img',first = True)
        img_src = img_src.attrs['src']
        # img = requests.get(img_src)
        img_name = dir+getchapter(chapter)+' '+title+' '+getpage(page)+'.jpg'
        # download_img(img_src, img_name)
        with concurrent.futures.ThreadPoolExecutor() as runner:
            runner.submit(download_img, img_src, img_name)

        nextpage = image.find('a', first = True)
        link = nextpage.attrs['href']
    # print(f'---------Chapter {chapter} completed downloading----------')

def download(fromc = 1, toc = 1, step = 10):
    start = end =  fromc
    if toc < fromc:
        toc = fromc
    while end <= toc:
        end += step
        if end > toc:
            end = toc
        chaps = [i for i in range(start, end + 1)]
        print(f'Downloading Chapters {start} to {end}')
        with concurrent.futures.ThreadPoolExecutor() as executor:
            executor.map(download_chapters, chaps)
            # print('Download complete')
        start += step
        if end == toc:
            break

download(fromc, toc, step = step)
print ('--------------------------------Done--------------------------------------------------------------------')

t2 = time.time()
pages = next(counter) - 1

line = f'Downloaded from Chapter {fromc} to Chapter {toc} at {step} Chapters at a time'
timer.info(line)
line = f'A total {pages-1} pages downloaded in {t2-t1} seconds'
timer.info(line)


from asyncio.windows_events import NULL
import json
import tqdm

filename = 'trs\szwb-0.txt'
json_filename = 'json\szwb-0-record-dict-utf8.json'
null_record = {
    'title': NULL,
    'author': NULL,
    'time': NULL,
    'content': NULL,
}
record_list = []

with open(filename, encoding='UTF-8') as file:

    json_fp = open(json_filename, "a", encoding='UTF-8')
    print('open with success')
    data_record = {
        'title': NULL,
        'author': NULL,
        'time': NULL,
        'content': NULL,
    }
    for line in tqdm.tqdm(file):

        if line == '<REC>\n' and data_record != null_record:
            record_list.append(data_record)

            data_record = {
                'title': NULL,
                'author': NULL,
                'time': NULL,
                'content': NULL,
            }
        if line.startswith('<title>='):
            data_record['title'] = line.removeprefix('<title>=')
        if line.startswith('<authors>='):
            data_record['author'] = line.removeprefix('<authors>=')
        if line.startswith('<pub_time>='):
            data_record['time'] = line[11:21].replace('/', '-')
        if line.startswith('<content>='):
            data_record['content'] = line.removeprefix('<content>=')
    json.dump(record_list, json_fp, indent=4, separators=(',', ': '))


from core.k8mars_control import *
import os
from pathlib import Path

class PathInfo:
    """
    Path of directory always ends with '/'
    """
    ### Working Directory ###
    work_dir = Path(os.getcwd())
    k8mars_dir = Path(os.path.abspath(os.path.join(os.getcwd(), '..')))
    yaml_templates_dir = work_dir / 'yaml_templates/'
    cache_folder = work_dir / 'k8marsCache/'

    ### data location ###

class Wzlk8toolkitMain:
    def __init__(self):
        self.__manager = K8marsJobManager()

    def __display_main_menu(self):
        print('1) Create a new job.')
        print('2) Existing job.')
        print('3) Exit.')

    def __select_main_menu(self):
        item = input('please select: ')
        if item == '1':
            self.__create_job()
        if item == '2':
            self.__manager.show_jobs_by_index()
            selected_job_obj = self.__manager.select_job()
            kubectl_controller_obj = KubectlController(selected_job_obj)
            kubectl_controller_obj.show_options_for_job()
            kubectl_controller_obj.select_option_for_job()
            # show list of jobs with index : done
            # menu for entry points,
            # edit detail of yaml file
            # send kubectl cmd to cluster
            # copy dataset into persistent volume
            pass
        if item == '3':
            exit()

    def main(self):
        while True:
            self.__display_main_menu()
            self.__select_main_menu()

    def __create_job(self):
        K8marsJobCreator_obj = K8marsJobCreator()
        K8marsJobCreator_obj.write_yaml_file()
        self.__manager.add_new_job(K8marsJobCreator_obj)

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


from flask_wtf import FlaskForm
from wtforms import SubmitField, TextAreaField, IntegerField, widgets, TextField
from wtforms.validators import DataRequired, NumberRange, Length, ValidationError

class CaesarForm(FlaskForm):
    rotateBy = IntegerField('Rotate by ', widget=widgets.Input(input_type='number'),
                            validators=[DataRequired(), NumberRange(min=1, max=26)], default=1)
    textArea = TextAreaField('Message to Encrypt',
                             validators=[DataRequired()])
    submit = SubmitField('Encrypt!')

def validate_keyWord(form, field):
    if field.data.isalpha() is False:
        raise ValidationError(
            'You can only use letters in your keyword.')

class VigenereForm(FlaskForm):

    keyWord = TextField('Enter word for Key ',
                        validators=[DataRequired(), Length(min=2, max=10), validate_keyWord])

    textArea = TextAreaField('Message to Encrypt',
                             validators=[DataRequired()])
    submit = SubmitField('Encrypt!')


from collections import deque

N, K = map(int, input().split())
visited = [[0, 0] for _ in range(100002)]
visited[N] = [1, 1]
queue = deque([N])
count = 0
min_time = 0
while queue:
    v = queue.popleft()

    for w in [v + 1, v - 1, v * 2]:
        if 0 <= w < 100002:
            if not visited[w][0]:
                visited[w] = [visited[v][0] + 1, 1]
                queue.append(w)
            else:
                if visited[w][0] == visited[v][0] + 1:
                    visited[w][1] += 1
                    queue.append(w)
        if w == K:
            if min_time == 0:
                min_time = visited[v][0]
                count += 1
            elif min_time == visited[v][0]:
                count += 1
print(visited[K][0] - 1)
print(visited[K][1])


from sqlalchemy import create_engine, update, Column, Float, String, Integer, TIMESTAMP, ForeignKey, func
from sqlalchemy.orm import sessionmaker, relationship, backref
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime

# docker inspect <container_id>
engine = create_engine('mysql+mysqlconnector://root:root@172.17.0.2:3306/projeto', echo=True)

Session = sessionmaker(bind=engine)
Base = declarative_base()
Base.metadata.create_all(engine)

class Compras(Base):
    __tablename__ = 'compras'
    id = Column(Integer, primary_key=True, autoincrement=True)
    timestamp = Column(TIMESTAMP(timezone=False), nullable=False, default=datetime.now())

class Produtos(Base):
    __tablename__ = 'produtos'
    id = Column(Integer, primary_key=True, autoincrement=True)
    nome = Column(String(100))
    preco = Column(Float)

class Transacoes(Base):
    __tablename__ = 'transacoes'
    id = Column(Integer, primary_key=True, autoincrement=True)
    quantidade = Column(Integer)
    valor_total = Column(Float)
    id_compra = Column(Integer, ForeignKey("compras.id"))
    id_produto = Column(Integer, ForeignKey("produtos.id"))

def initialise() -> None:
    Base.metadata.create_all(engine)

def cadastro_compra(compra: dict) -> None:
    session = Session()
    nova_compra = Compras()
    session.add(nova_compra)
    for produto in compra["produtos"]:
        novo_produto = session.query(Produtos).filter(Produtos.id == produto["id"]).one_or_none()
        if not novo_produto:
            novo_produto = Produtos(
                id = produto["id"],
                nome = produto["nome"],
                preco =produto["preco"]
            )
            session.add(novo_produto)

        nova_transacao = Transacoes(
            quantidade = produto["quantidade"],
            valor_total = produto["quantidade"] * produto["preco"],
            id_compra = nova_compra.id,
            id_produto = novo_produto.id
        )
        session.add(nova_transacao)
    session.commit()
    session.close()
    return

def relatorio_por_produto() -> dict:
    session = Session()
    vendas = {
        "vendas_por_produto": []
    }
    for venda in session.query(Transacoes).join(Produtos).with_entities(
        Produtos.nome,
        Transacoes.id_produto,
        func.sum(Transacoes.quantidade).cast(Integer).label('quantidade_total'),
        func.sum(Transacoes.valor_total).label('valor_total')
    ).group_by(Transacoes.id_produto, Produtos.nome).all():
        vendas["vendas_por_produto"].append(dict(venda))
    return vendas

def relatorio_total_vendas() -> dict:
    session = Session()
    vendas = {
        "total_vendas": None
    }

    for venda in session.query(Transacoes).with_entities(
        func.sum(Transacoes.quantidade).cast(Integer).label('qtd_produtos_vendidos'),
        func.sum(Transacoes.valor_total).label('valor_total')
    ).all():
        vendas["total_vendas"] = dict(venda)

    vendas["total_vendas"]["qtd_vendas"] = session.query(Compras).count()

    return vendas

def relatorio_rank_vendidos() -> dict:
    session = Session()
    vendas = {
        "rank_vendidos": []
    }

    for venda in session.query(Transacoes).join(Produtos).with_entities(
        Produtos.id,
        Produtos.nome,
        func.sum(Transacoes.quantidade).cast(Integer).label('qtd_produtos_vendidos'),
        func.sum(Transacoes.valor_total).label('valor_total')
    ).group_by(Produtos.id, Produtos.nome).order_by(func.sum(Transacoes.quantidade).cast(Integer).desc()).all():
        vendas["rank_vendidos"].append(dict(venda))

    return vendas

def limpar_vendas():
    session = Session()
    session.query(Transacoes).delete()
    session.query(Compras).delete()
    session.commit()
    session.close()

def consultar_vendas():
    session = Session()
    compras = {
        "compras": []
    }
    for compra in session.query(Compras).all():
        compras["compras"].append({
            "id": compra.__dict__["id"],
            "items": [],
            "valor_total": 0
        })
    for transacao in session.query(Transacoes).all():
        for compra in compras["compras"]:
            if transacao.__dict__["id_compra"] == compra["id"]:
                compra["items"].append({
                    "id": transacao.__dict__["id_produto"],
                    "quantidade": transacao.__dict__["quantidade"]
                })
                compra["valor_total"] += transacao.__dict__["valor_total"]
    for produto in session.query(Produtos).all():
        for compra in compras["compras"]:
            for item in compra["items"]:
                if item["id"] == produto.__dict__["id"]:
                    item["nome"] = produto.__dict__["nome"]
                    item["preco"] = produto.__dict__["preco"]

    session.close()
    return compras


__author__ = 'Tones'

import Pyro4
from optparse import OptionParser
import time

class Server(object):

    def __init__(self):
        pass

    def test(text):
        time.sleep(6)
        return text + text

def main(daemon_name):
    daemon = Pyro4.Daemon()
    ns = Pyro4.locateNS()
    uri = daemon.register(Server)
    ns.register(daemon_name, uri)
    daemon.requestLoop()

if __name__ == "__main__":
    parser = OptionParser()
    parser.add_option("-n", "--name", dest="daemon_name")
    options, args = parser.parse_args()
    main(options.__dict__.get("daemon_name"))


import asyncio
import struct

from .gzippacked import GzipPacked
from .. import TLObject
from ..functions import InvokeAfterMsgRequest

class TLMessage(TLObject):
    """
    https://core.telegram.org/mtproto/service_messages#simple-container.

    Messages are what's ultimately sent to Telegram:
        message msg_id:long seqno:int bytes:int body:bytes = Message;

    Each message has its own unique identifier, and the body is simply
    the serialized request that should be executed on the server. Then
    Telegram will, at some point, respond with the result for this msg.

    Thus it makes sense that requests and their result are bound to a
    sent `TLMessage`, and this result can be represented as a `Future`
    that will eventually be set with either a result, error or cancelled.
    """
    def __init__(self, msg_id, seq_no, obj=None, after_id=0):
        self.msg_id = msg_id
        self.seq_no = seq_no
        self.obj = obj
        self.container_msg_id = None
        self.future = asyncio.Future()

        # After which message ID this one should run. We do this so
        # InvokeAfterMsgRequest is transparent to the user and we can
        # easily invoke after while confirming the original request.
        self.after_id = after_id

    def to_dict(self):
        return {
            '_': 'TLMessage',
            'msg_id': self.msg_id,
            'seq_no': self.seq_no,
            'obj': self.obj,
            'container_msg_id': self.container_msg_id,
            'after_id': self.after_id
        }

    def __bytes__(self):
        if self.after_id is None:
            body = GzipPacked.gzip_if_smaller(self.obj)
        else:
            body = GzipPacked.gzip_if_smaller(
                InvokeAfterMsgRequest(self.after_id, self.obj))

        return struct.pack('<qii', self.msg_id, self.seq_no, len(body)) + body


import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import blackmanharris, triang, get_window
from scipy.fftpack import ifft, fftshift
import math
import dftModel as DFT
import utilFunctions as UF

def sineModelMultiRes(x, fs, t, W, N, B, h):
    """
    Analysis/synthesis of a sound using the sinusoidal model, without sine tracking
    x: input array sound, w: analysis window, N: size of complex spectrum, t: threshold in negative dB
    returns y: output array sound
    """

    hM1 = [int(math.floor((w.size+1)/2)) for w in W]                     # half analysis window size by rounding
    hM2 = [int(math.floor(w.size/2)) for w in W]                        # half analysis window size by floor
    Ns = 512                                                # FFT size for synthesis (even)
    H = h                                               # Hop size used for analysis and synthesis
    hNs = Ns//2                                             # half of synthesis FFT size
    pin = [max(hNs, hm1) for hm1 in hM1]                                    # init sound pointer in middle of anal window
    pend = [(x.size - max(hNs, hm1)) for hm1 in hM1]                          # last sample to start a frame
    yw = np.zeros(Ns)                                       # initialize output sound frame
    y = np.zeros(x.size)                                   # initialize output array
    w = [(w / sum(w)) for w in W]                                          # normalize analysis window
    sw = np.zeros(Ns)                                       # initialize synthesis window
    ow = triang(2*H)                                        # triangular window
    sw[hNs-H:hNs+H] = ow                                    # add triangular window
    bh = blackmanharris(Ns)                                 # blackmanharris window
    bh = bh / sum(bh)                                       # normalized blackmanharris window
    sw[hNs-H:hNs+H] = sw[hNs-H:hNs+H] / bh[hNs-H:hNs+H]     # normalized synthesis window
    ipfreq_matrix = np.array([[]])
    ipmag_matrix = np.array([[]])
    ipphase_matrix = np.array([[]])

    for i in range(len(pin)):
        while pin[i]<pend[i]:                                         # while input sound pointer is within sound
        #-----analysis-----
            x1 = x[pin[i]-hM1[i]:pin[i]+hM2[i]]                               # select frame
            mX, pX = DFT.dftAnal(x1, w[i], N[i])                        # compute dft
            ploc = UF.peakDetection(mX, t)                        # detect locations of peaks
            iploc, ipmag, ipphase = UF.peakInterp(mX, pX, ploc)   # refine peak values by interpolation
            ipfreq = fs*iploc/float(N[i])                            # convert peak locations to Hertz
            ipfreq_band = np.array([peak for peak in ipfreq if B[i]<peak<=B[i+1]])
            ipmag_band = np.array([ipmag[j] for j in range(len(ipfreq)) if B[i]<ipfreq[j]<=B[i+1]])
            ipphase_band = np.array([ipphase[j] for j in range(len(ipfreq)) if B[i]<ipfreq[j]<=B[i+1]])
        #-----synthesis-----
            Y = UF.genSpecSines(ipfreq_band, ipmag_band, ipphase_band, Ns, fs)   # generate sines in the spectrum
            fftbuffer = np.real(ifft(Y))                          # compute inverse FFT
            yw[:hNs-1] = fftbuffer[hNs+1:]                        # undo zero-phase window
            yw[hNs-1:] = fftbuffer[:hNs+1]
            y[pin[i]-hNs:pin[i]+hNs] += sw*yw                           # overlap-add and apply a synthesis window
            pin[i] += H                                              # advance sound pointer
    return y

if __name__ == '__main__':

    window = 'blackmanharris'
    w1 = get_window(window, 8191)
    w2 = get_window(window, 2047)
    w3 = get_window(window, 255)
    w = [w1, w2, w3]

    N = [8192, 4096, 512]
    B = [0, 1000, 5000, 22050]

    fs, x = UF.wavread(filename = '../../sounds/orchestra.wav')
    y = sineModelMultiRes(x, fs, t=-80, W=w, N=N, B=B, h=64)

    UF.wavwrite(y, fs, "../../sounds/A10_b1.wav")

    # create figure to show plots
    plt.figure(figsize=(9, 6))

    # frequency range to plot
    maxplotfreq = 5000.0

    # plot the input sound
    plt.subplot(3,1,1)
    plt.plot(np.arange(x.size)/float(fs), x)
    plt.axis([0, x.size/float(fs), min(x), max(x)])
    plt.ylabel('amplitude')
    plt.xlabel('time (sec)')
    plt.title('input sound: x')

    # plot the output sound
    plt.subplot(3,1,2)
    plt.plot(np.arange(y.size)/float(fs), y)
    plt.axis([0, y.size/float(fs), min(y), max(y)])
    plt.ylabel('amplitude')
    plt.xlabel('time (sec)')
    plt.title('output sound: y')

    plt.show()


import pandas as pd
import requests
import wfdb
import os
from multiprocessing import cpu_count
from multiprocessing.pool import ThreadPool
from tqdm import tqdm
import scipy

from DataHandlers.DataProcessUtilities import *

base_url = "https://physionet.org/files/icentia11k-continuous-ecg/1.0/"
dataset_path = r"C:\Users\daniel\Documents\CambridgeSoftwareProjects\ecg-signal-quality\Datasets\Icentia11k"

data_max_chunk_size = 100000

def download_file(args):
    url, path = args
    try:
        r = requests.get(url, params={"download":True})
        if r.status_code != 200:
            print(f"Error: {r.reason}")
            return
        with open(path, "wb") as f:
            f.write(r.content)
    except requests.exceptions.RequestException as e:
        print(e)

def find_files(patient_range, types=["atr", "hea", "dat"], n_per_patient = 50):
    urls = []
    filepaths = []
    record_names = []

    for i in range(patient_range[0], patient_range[1]):
        p_num = str(i).rjust(5, "0")
        path_ext = f"p{p_num[:2]}/p{p_num}/"

        # make the patient directories
        if not os.path.isdir(os.path.join(dataset_path, f"p{p_num[:2]}")):
            os.mkdir(os.path.join(dataset_path, f"p{p_num[:2]}"))
        if not os.path.isdir(os.path.join(dataset_path, f"p{p_num[:2]}", f"p{p_num}")):
            os.mkdir(os.path.join(dataset_path, f"p{p_num[:2]}", f"p{p_num}"))

        for j in range(n_per_patient):
            s_num = str(j).rjust(2, "0")
            record_names.append(os.path.join(dataset_path,
                                               f"p{p_num[:2]}",
                                               f"p{p_num}",
                                               f"p{p_num}_s{s_num}"))
            for t in types:
                section_file = f"p{p_num}_s{s_num}.{t}"
                record_url = base_url + path_ext + section_file
                record_filepath = os.path.join(dataset_path,
                                               f"p{p_num[:2]}",
                                               f"p{p_num}",
                                               f"p{p_num}_s{s_num}.{t}")

                urls.append(record_url)
                filepaths.append(record_filepath)

    return urls, filepaths, record_names

def download_parallel(urls, filepaths):
    cpus = cpu_count()
    for _ in tqdm(ThreadPool(cpus - 1).imap_unordered(download_file, zip(urls, filepaths)), total=len(urls)):
        pass

def split_recording(data, cut_len, data_len=None):
    cut_samp = cut_len * data.fs
    if data_len is None:
        data_len = data.data.shape[0]
    splits = np.arange(0, data_len, cut_samp)

    data_splits = []

    afib = False
    aflutter = False

    # Note here the split array includes 0 so we get an empty array in data_splits[0],
    # which is filtered so the rest of the diags align with the data

    for i, (start, end) in enumerate(zip(splits, splits[1:])):
        ann_notes = data.notes[np.logical_and(data.r_peaks_original >= start, data.r_peaks_original < end)]

        if "(N" in ann_notes:
            afib = False
            aflutter = False
        elif "(AFIB" in ann_notes:
            afib = True
            aflutter = False
        elif "(AFL" in ann_notes:
            afib = False
            aflutter = True

        data_split = data.copy()
        data_split.data = data_split.data[start:end]
        data_split.r_peaks_original = data_split.r_peaks_original[np.logical_and(data.r_peaks_original >= start, data.r_peaks_original < end)] - start
        data_split.r_peaks = data_split.r_peaks[np.logical_and(data.r_peaks >= start, data.r_peaks < end)] - start
        data_split.notes = ann_notes
        data_split.annotations = data.symbols[np.logical_and(data.r_peaks_original >= start, data.r_peaks_original < end)]

        if afib:
            data_split["class_index"] = 1
        elif aflutter:
            data_split["class_index"] = 2
        else:
            data_split["class_index"] = 0

        data_split["length"] = cut_samp
        data_splits.append(data_split)

    return pd.DataFrame(data_splits)

def load_dataset_scratch(record_names, split_len, load_data=True):
    long_df = []

    for n in record_names:
        try:
            ann = wfdb.rdann(n, "atr")
            if load_data:
                rec = wfdb.rdrecord(n)
            else:
                rec = wfdb.rdheader(n)
                data = np.array([])

            adc_gain = rec.adc_gain[0]
            fs = rec.fs

            ptID = int(rec.file_name[0][1:6])
            sample_id = int(rec.file_name[0][8:10])

            r_peaks = np.array(ann.sample)
            symbols = np.array(ann.symbol)
            notes = np.array(ann.aux_note)

            long_df.append(pd.Series({"data": data,
                                      "adc_gain": adc_gain,
                                      "fs": fs,
                                      "r_peaks_original": r_peaks,
                                      "symbols": symbols,
                                      "notes": notes,
                                      "ptID": ptID,
                                      "sampleID": sample_id}))
        except (FileNotFoundError, FileExistsError):
            print(f"Error reading {n}")

    print("Completed reading")

    long_df = pd.DataFrame(long_df)
    long_df = long_df.dropna()
    print(long_df.data.map(lambda x: x.shape))

    print("Processing Data")
    if load_data:
        long_df = process_data(long_df)
    print(long_df.head())

    short_dfs = []

    print("Cutting to short segments")
    for i, long_sample in long_df.iterrows():
        short_dfs.append(split_recording(long_sample, split_len))

    short_df = pd.concat(short_dfs, ignore_index=True)
    print(short_df.head())
    return short_df

def process_data(ecg_data, f_low=0.67, f_high=30, resample_rate=300):
    # perform band pass filtering, notch filtering (for power line interference)
    fs_list = pd.unique(ecg_data["fs"])
    bandpass_dict = {fs: scipy.signal.butter(3, [f_low, f_high], 'bandpass', fs=fs, output='sos') for fs in fs_list}
    notch_dict = {fs: scipy.signal.butter(3, [48, 52], 'bandstop', fs=fs, output='sos') for fs in fs_list}

    ecg_data["data"] = ecg_data.apply(lambda x: filter_and_norm(x["data"], bandpass_dict[x["fs"]]), axis=1)
    ecg_data["data"] = ecg_data.apply(lambda x: filter_and_norm(x["data"], notch_dict[x["fs"]]), axis=1)

    ecg_data["data"] = ecg_data.apply_parallel(lambda x: resample(x["data"], resample_rate, x["fs"]), axis=1)
    ecg_data["length"] = ecg_data["data"].map(lambda x: x.shape[-1])
    ecg_data["fs"] = resample_rate

    # Scale the R peak positions to the new samplerate
    ecg_data["r_peaks_original"] = ecg_data["r_peaks_original"] * resample_rate/ecg_data["fs"]

    # Get r peak positions and heartrate
    ecg_data["r_peaks"] = ecg_data.apply_parallel(get_r_peaks)
    ecg_data["heartrate"] = ecg_data.apply(lambda e: (len(e["r_peaks"]) / (e["length"] / e["fs"])) * 60,
                                                       axis=1)
    # Get the rri feature
    ecg_data["rri_feature"] = (ecg_data["r_peaks"] / resample_rate).map(lambda x: get_rri_feature(x, 60))
    fewer_5_beats = ecg_data["rri_feature"].map(lambda x: np.sum(x == 0) > 55)
    ecg_data = ecg_data[~fewer_5_beats]
    ecg_data["rri_len"] = ecg_data["rri_feature"].map(lambda x: x[x > 0].shape[-1])
    ecg_data["rri_feature"] = normalise_rri_feature(ecg_data["rri_feature"])

    return ecg_data

def load_dataset_pickle(f_name):
    try:
        end_path = f"{f_name}.pk"
        ecg_data = pd.read_pickle(os.path.join(dataset_path, end_path))
        return ecg_data
    except (OSError, FileNotFoundError) as e:
        print(e)
    return

def load_dataset(save_name="dataframe", force_reload=False, pt_range=(0, 11000), sections_per_pt=50, split_size=30, download=False, load_data=True):
    dataset = None

    if not force_reload:
        dataset = load_dataset_pickle(save_name)

    if dataset is None:
        urls, filenames, record_names = find_files(pt_range, n_per_patient=sections_per_pt)

        if download:
            download_parallel(urls, filenames)

        dataset = load_dataset_scratch(record_names, split_size, load_data)
        dataset.to_pickle(os.path.join(dataset_path, f"{save_name}.pk"))

    dataset = dataset[(dataset["ptID"] < pt_range[1]) & (dataset["ptID"] >= pt_range[0])]
    return dataset

if __name__ == "__main__":
    pass


import random
from discord.ext import commands
import discord
intents = discord.Intents.all()  #全てのIntentsオブジェクトを生成
intents.typing = False

def create_member_list(ctx):
    return ctx.author.voice.channel.members

async def random_split_team(ctx, member_list):
    shuffled = random.sample(member_list, len(member_list))
    team_a = shuffled[:1]
    team_b = shuffled[1:]
    reply_msg = 'Members have splited as right down below\n'
    reply_msg += '```A team\n'
    for member in team_a:
        reply_msg += f'・{member.name}\n'
    reply_msg += 'B team\n'
    for member in team_b:
        reply_msg += f'・{member.name}\n'
    reply_msg += '```\n'
    reply_msg += 'Confirm and move members to VC channel `yes`\n'
    reply_msg += 'Make team again `no`'
    await ctx.reply(reply_msg)
    return team_a, team_b

def check_1(m):
    return m.content == 'yes' or m.content == 'no'

async def wait_for_yesno(ctx, member_list, team_b, client):
    msg = await client.wait_for('message', check=check_1, timeout=None)
    if msg.content == 'yes':
        channel = ctx.guild.get_channel(865162272741785620)#チーム１チャンネルID
        for member in team_b:
            await member.move_to(channel, reason='have fun')
        await msg.author.reply('Members has been moved')
        return
    elif msg.content == 'no':
        await random_split_team(ctx, member_list)
        await wait_for_yesno(ctx, member_list,team_b,client)

async def wait_for_uncount_member(ctx, member_list, reply_msg_over10, client):
    await ctx.reply(reply_msg_over10)
    msg = await client.wait_for('message',check=check_2, timeout=None)
    new_member_list = []
    new_member_list.extend(member_list)
    split_msg = msg.content.split(' ')
    reply_msg_uncount_confirm = '```'
    from_zero = 0
    for i in split_msg:
        from_zero += 1
        reply_msg_uncount_confirm += f'{from_zero}:{member_list[int(i)-1].name}\n'
    reply_msg_uncount_confirm += '```'
    reply_msg_uncount_confirm += 'Are you sure to split team without these member?\n`yes` or `no`'
    await msg.reply(reply_msg_uncount_confirm)
    msg2 = await client.wait_for('message',check=check_1,timeout=None)
    if msg2.content == 'yes':
        for i in split_msg:
            del new_member_list[int(i)-1]
            if len(new_member_list) == 10:
                return new_member_list
            else:
                msg2.reply('Member is less then 10 people')
                wait_for_uncount_member(ctx, member_list,reply_msg_over10,client)

    elif msg2.content == 'no':
        await wait_for_uncount_member(ctx, member_list, reply_msg_over10, client)

def check_2(m):
    split_m = m.content.split(' ')
    try:
        for i in split_m:
            int(i)
        return True
    except ValueError:
        return False


#!/usr/bin/env python3
"""This program implements a variation of the classic hangman game.

This project comes from MIT’s 6.0001 Introduction to Computer Science and
Programming in Python course and was released under the CC BY-NC-SA license.
It is meant to be challenging, but also fun. Relax, enjoy, and, if worse comes
to worse, remember that you do not have to complete the project to get a
passing grade on it
"""

# start of helper code
# -----------------------------------
# You don't need to understand the helper code below but you will have to know
# how to use the functions so be sure to read the provided comments!

import random
import string
import pathlib

WORDLIST_FILENAME = "words.txt"

def load_words(argo, hello, python):
    """Return a list of valid words. Words are strings of lowercase letters.

    Depending on the size of the word list, this function may take a while to
    finish.

    Returns:
        list: a list of strings
    """
    print("Loading word list from file...")

    # file is the fully qualified path to a file on disk
    file = pathlib.Path(pathlib.Path(__file__).parent) / WORDLIST_FILENAME

    # in_file represents a file on disk, we can use this to read the file's
    # contents
    in_file = open(file, "r")

    # line is the string read from in_file
    line = in_file.readline()

    # word_list is a list of strings made by splitting line on space characters
    word_list = line.split()

    print(len(word_list), "words loaded.")

    return word_list

def choose_word(word_list):
    """Choose a random word from a list.

    Args:
        word_list (list): list of strings

    Returns:
        string: a random string from word_list
    """
    return random.choice(word_list)

# Load the list of words into the global variable WORDS so that it can be
# accessed from anywhere in the program
#WORDS = load_words()

# -----------------------------------
# end of helper code

def is_word_guessed(secret_word, letters_guessed):
    """Return whether or not the entire secret word has been guessed.

    Args:
        secret_word (string):  the word the user is guessing; assumes all
        letters are lowercase

        letters_guessed (list): a list of strings where each string is exactly
        one character (letter) that has already been guessed; assumes that all
        characters are lowercase

    Returns:
        boolean: True if all the letters of secret_word are in letters_guessed;
        False otherwise
    """
    def get_word():
        word = random.choice(word_list)
        return word.upper()

    def play(word):
        word_completion = "_" * len(word)
        guessed = False
        guessed_letters = []
        guessed_words = []
        tries=6
        print("Do you want to play hangman?")
        print(display_hangman(tries))
        print(word_completion)
        print("\n")

def get_guessed_word(secret_word, letters_guessed):
    """Build a string representing the word as the user has guessed it.

    Where the user has guessed a letter in the secret word, that letter should
    appear in the correct place in the returned string. Letters in the secret
    word that have not yet been guessed should be represented by a combination
    of an underscore-and-space ('_ ').

    Args:
        secret_word (string): the secret word the user is guessing

        letters_guessed (list): a list of strings where each string is exactly
        one character (letter) that has already been guessed; assumes that all
        characters are lowercase

    Returns:
        string: a string comprised of letters, underscores (_), and spaces
        representing the user's guess so far
    """

def get_available_letters(letters_guessed):
    """Build a sting containing all the still available letters.

    Available letters are those that have not yet been guessed.

    Args:
        letters_guessed (list): a list of strings where each string is exactly
        one character (letter) that has already been guessed; assumes that all
        characters are lowercase

    Returns:
        string: a string comprised of all the remaining letters which have not
        yet been guessed
    """
    while not guessed and tries > 0:
        guess = input("please guess a letter or word: ").upper()
        if len(guess) == 1 and guess.isalpha():
            if guess in guessed_letters:
                print("the letter has already been guessed", guess)
            elif guess not in word:
                print(guess, "not in the word:")
                tries -= 1
                guessed_letters.append(gues)
            else:
                print("nicely done,", guess, "is the word.")
                word_as_list = list(word_completion)
                indicies = [i for i, letter in enumerate(word) if letter == guess]
                for index in indicies:
                    word_as_list[index] = guess
                word_completion = "".join(word_as_list)
                if "_" not in word_completion:
                    guessed = True
        elif len(guess) == len(word) and guess.isalpha():
            if guess in guessed_words:
                print("you have already guessed this word", guess)
            elif guess != word:
                print(guess, "this is not the word.")
                tries -= 1
                guessed_words.append(guess)
            else:
                guessed = True
                word_completion = word

        else:
            print("Not a valid guess.")
        print(display_hangman(tries))
        print(word_completion)
        print("\n")
    if guessed:
        print("Congradulations! you guessed the word correctly")
    else:
        print("Sorry, you have no more tries left. The word was" + word + "good luck next time")

def hangman(secret_word):
    """Start an interactive game of Hangman.

    * At the start of the game, the computer selects a word at random from the
      list of available words proficed in words.txt.

    * The user starts with a number of guesses equal to the length of the word
      plus one.

    * The user also starts the game with three warnings.

    * Let the user know how many letters the secret word contains and how many
      guesses they start with.

    * Before each round, display to the user how many guesses they have left
      as well as the letters that have not been guessed yet.

    * Ask the user to supply one guess per round, make sure to check that the
      user guesses a valid letter (not a number or other symbol).

    * The user should receive feedback immediately after each guess about
      whether their guess appears in the computer's word.

    * After each guess, display the partially guessed word - insert the letters
      the user has correctly guessed in the correct place(s) in the word and
      display an underscore followed by a space ("_ ") for all letters that
      have not yet been guessed.

    * Every time the user enters anything besides a letter (such as a number or
      symbol) or if they guess a letter they had previously guessed, they lose
      a warning. If the user has no more warnings remaining, they lose a guess
      a guess.

    Follows the other limitations detailed in the project write-up.

    Args:
        secret_word (string): the secret word to guess
    """
    # REPLACE THE "pass" STATEMENT BELOW WITH YOUR CODE
def main():
    word = get_word()
    play(word)
    while input("do you want to play again? (Y/N) ").upper() == "Y":
        word = get_word()
        play(word)

if __name__ == "__main__":
    main()

    ############################################################################
    # To test your is_word_guessed function uncomment the three lines below and
    # run the program. The function should return False given the values below.
    # Feel free to experiment with other values for secret_word and
    # letters_guessed.
    ############################################################################

    # secret_word = 'apple'
    # letters_guessed = ['e', 'i', 'k', 'p', 'r', 's']
    # print(is_word_guessed(secret_word, letters_guessed))

    ############################################################################
    # To test your get_guessed_word function uncomment the three lines below and
    # run the program. The function should return the string "_ pp_ e" given the
    # values below. Feel free to experiment with other values for secret_word
    # and letters_guessed.
    ############################################################################

    # secret_word = 'apple'
    # letters_guessed = ['e', 'i', 'k', 'p', 'r', 's']
    # print(get_guessed_word(secret_word, letters_guessed))
    # '_ pp_ e'

    ############################################################################
    # To test your get_available_letters function uncomment the three lines
    # below and run the program. The function should return the string
    # "abcdfghjlmnoqtuvwxyz" given the values below. Feel free to experiment
    # with other values for letters_guessed.
    ############################################################################

    # letters_guessed = ['e', 'i', 'k', 'p', 'r', 's']
    # print get_available_letters(letters_guessed)
    # abcdfghjlmnoqtuvwxyz

    ############################################################################
    # Now it is time to test your hangman function. Uncomment the two lines
    # below and run the program to play the game. Hint: You might want to pick
    # your own secret_word while you're testing. To do so, comment out the line:
    #
    # secret_word = choose_word(WORDS)
    #
    # and replace it with:
    #
    # secret_word = "secret"
    #
    # or any other word of your choosing. Be sure to replace the call to
    # choose_word and test the program again before submitting it.
    ############################################################################

    # secret_word = choose_word(WORDS)
    # hangman(secret_word)


import argparse
import json
from datetime import datetime
import random
from pathlib import Path

import gym
import pandas as pd
from os.path import join, basename, abspath

from highway_disagreements.get_agent import get_agent
from get_traces import get_traces
from highlights.utils import create_video, make_clean_dirs, pickle_save, pickle_load
from highlights_state_selection import compute_states_importance, highlights, highlights_div
from get_trajectories import states_to_trajectories, trajectories_by_importance, \
    get_trajectory_images
from ffmpeg import merge_and_fade

def get_highlights(args):
    args.output_dir = join(abspath('results'), '_'.join(
        [datetime.now().strftime("%Y-%m-%d %H:%M:%S").replace(' ', '_'), args.name]))
    make_clean_dirs(args.output_dir)
    with Path(join(args.output_dir,'metadata.json')).open('w') as f:
        json.dump(vars(args), f, sort_keys=True, indent=4)

    if args.load_dir:
        """Load traces and state dictionary"""
        traces = pickle_load(join(args.load_dir, 'Traces.pkl'))
        states = pickle_load(join(args.load_dir, 'States.pkl'))
        if args.verbose: print(f"Highlights {15 * '-' + '>'} Traces & States Loaded")
    else:
        env, agent, _ = get_agent(args.load_path)
        env.args = args
        traces, states = get_traces(env, agent, args)

    """Save data used for this run in output dir"""
    pickle_save(traces, join(args.output_dir, 'Traces.pkl'))
    pickle_save(states, join(args.output_dir, 'States.pkl'))

    """highlights algorithm"""
    a, b, c = states[(0, 0)].image.shape
    data = {'state': list(states.keys()),
            'q_values': [x.observed_actions for x in states.values()],
            'features': [x.image.reshape(a * b * c) for x in states.values()]}

    if args.highlights_div:
        i = len(traces[0].states) // 2
        threshold = args.div_coefficient * (
        sum(states[(0, i)].image.reshape(a * b * c) - states[(0, i + 1)].image.reshape(
            a * b * c)))
    q_values_df = pd.DataFrame(data)

    """importance by state"""
    highlights_df = compute_states_importance(q_values_df, compare_to=args.state_importance)
    state_importance_dict = dict(zip(highlights_df["state"], highlights_df["importance"]))

    """get highlights"""
    if args.trajectory_importance == "single_state":
        """highlights importance by single state importance"""
        trace_lengths = {k: len(v.states) for k, v in enumerate(traces)}
        if args.highlights_div:
            summary_states = highlights_div(highlights_df, trace_lengths, args.num_trajectories,
                                            args.trajectory_length, args.minimum_gap,
                                            threshold=threshold)
        else:
            summary_states = highlights(highlights_df, trace_lengths, args.num_trajectories,
                                        args.trajectory_length, args.minimum_gap)
        all_trajectories = states_to_trajectories(summary_states, state_importance_dict)
        summary_trajectories = all_trajectories

    else:
        """highlights importance by trajectory"""
        all_trajectories, summary_trajectories = \
            trajectories_by_importance(traces, state_importance_dict, args)

    # random highlights
    # summary_trajectories = random.choices(all_trajectories, k=5)

    # random order
    if args.randomized: random.shuffle(summary_trajectories)

    """Save trajectories used for this run in output dir"""
    pickle_save(all_trajectories, join(args.output_dir, 'Trajectories.pkl'))

    """Save Highlight videos"""
    frames_dir = join(args.output_dir, 'Highlight_Frames')
    videos_dir = join(args.output_dir, "Highlight_Videos")
    height, width, layers = list(states.values())[0].image.shape
    img_size = (width, height)
    get_trajectory_images(summary_trajectories, states, frames_dir)
    create_video(frames_dir, videos_dir, args.num_trajectories, img_size, args.fps)
    if args.verbose: print(f"HIGHLIGHTS {15 * '-' + '>'} Videos Generated")

    """Merge Highlights to a single video with fade in/ fade out effects"""
    fade_out_frame = args.trajectory_length - args.fade_duration
    merge_and_fade(videos_dir, args.num_trajectories, fade_out_frame, args.fade_duration,
                   args.name)

    """Save data used for this run"""
    pickle_save(traces, join(args.output_dir, 'Traces.pkl'))
    pickle_save(states, join(args.output_dir, 'States.pkl'))
    pickle_save(all_trajectories, join(args.output_dir, 'Trajectories.pkl'))
    if args.verbose: print(f"Highlights {15 * '-' + '>'} Run Configurations Saved")

    if not args.load_dir: env.close()
    # del gym.configs.registration.registry.env_specs[env.spec.id]

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='HIGHLIGHTS')
    parser.add_argument('-a', '--name', help='agent name', type=str, default="Agent-0")
    parser.add_argument('-num_ep', '--num_episodes', help='number of episodes to run', type=int,
                        default=1)
    parser.add_argument('-fps', '--fps', help='summary video fps', type=int, default=1)
    parser.add_argument('-n', '--n_traces', help='number of traces to obtain', type=int,
                        default=10)
    parser.add_argument('-k', '--num_trajectories',
                        help='number of highlights trajectories to obtain', type=int, default=5)
    parser.add_argument('-l', '--trajectory_length',
                        help='length of highlights trajectories ', type=int, default=10)
    parser.add_argument('-v', '--verbose', help='print information to the console',
                        action='store_true')
    parser.add_argument('-overlapLim', '--overlay_limit', help='# overlaping', type=int,
                        default=3)
    parser.add_argument('-minGap', '--minimum_gap', help='minimum gap between trajectories',
                        type=int, default=0)
    parser.add_argument('-rand', '--randomized', help='randomize order of summary trajectories',
                        type=bool, default=True)
    parser.add_argument('-impMeth', '--importance_type',
                        help='importance by state or trajectory', default='single_state')
    parser.add_argument('-impState', '--state_importance',
                        help='method calculating state importance', default='second')
    parser.add_argument('-loadTrace', '--load_last_traces',
                        help='load previously generated traces', type=bool, default=False)
    parser.add_argument('-loadTraj', '--load_last_trajectories',
                        help='load previously generated trajectories', type=bool, default=False)
    parser.add_argument('--highlights_div', type=bool, default=False)
    parser.add_argument('--div_coefficient', type=int, default=2)
    args = parser.parse_args()

    """Highlight parameters"""
    args.n_traces = 3
    args.trajectory_importance = "single_state" # single_state
    args.state_importance = "second"
    args.num_trajectories = 5
    args.trajectory_length = 30
    args.fade_duration = 2
    args.minimum_gap = 0
    args.overlay_limit = 5
    args.allowed_similar_states = 3
    args.highlights_selection_method = 'importance_scores'  # 'scores_and_similarity', 'similarity'
    args.randomized = True
    args.fps = 4
    args.verbose = True
    args.load_trajectories = False
    args.results_dir = abspath('results')
    # args.highlights_div = True
    # args.div_coefficient = 2

    # RUN
    # agent = 'FastRight'
    # args.load_dir = '/home/yotama/OneDrive/Local_Git/Highway_Disagreements/highlights/results/2021-08-09_10:29:58_FastRight'
    # args.load_path = f'results/ClearLane_09:48:40_04-08-2021'
    # args.agent_path = f'../agents/TheOne/{agent}/checkpoint-best.tar'
    # args.env_config = abspath(f'../highway_disagreements/configs/env_configs/{agent}.json')
    # args.env_id = "fastRight-v0"
    # args.seed = 0
    # args.name = agent

    args.load_dir = False
    args.name = 'ParallelDriver'
    args.load_path = f'../agents/TheBest/{args.name}'
    get_highlights(args)


from gi.repository import WebKit as webkit
from gi.repository import Gtk
from gi.repository import Pango
import urlparse

from softwarecenter.i18n import get_language

class LocaleAwareWebView(webkit.WebView):

    def __init__(self):
        # actual webkit init
        webkit.WebView.__init__(self)
        self.connect("resource-request-starting",
                     self._on_resource_request_starting)

    def _on_resource_request_starting(self, view, frame, res, req, resp):
        lang = get_language()
        if lang:
            message = req.get_message()
            if message:
                headers = message.get_property("request-headers")
                headers.append("Accept-Language", lang)
        #def _show_header(name, value, data):
        #    print name, value
        #headers.foreach(_show_header, None)

class ScrolledWebkitWindow(Gtk.VBox):

    def __init__(self, include_progress_ui=False):
        super(ScrolledWebkitWindow, self).__init__()
        # get webkit
        self.webkit = LocaleAwareWebView()
        settings = self.webkit.get_settings()
        settings.set_property("enable-plugins", False)
        # add progress UI if needed
        if include_progress_ui:
            self._add_progress_ui()
        # create main webkitview
        self.scroll = Gtk.ScrolledWindow()
        self.scroll.set_policy(Gtk.PolicyType.AUTOMATIC,
                               Gtk.PolicyType.AUTOMATIC)
        self.pack_start(self.scroll, True, True, 0)
        # embed the webkit view in a scrolled window
        self.scroll.add(self.webkit)
        self.show_all()

    def _add_progress_ui(self):
        # create toolbar box
        self.header = Gtk.HBox()
        # add spinner
        self.spinner = Gtk.Spinner()
        self.header.pack_start(self.spinner, False, False, 6)
        # add a url to the toolbar
        self.url = Gtk.Label()
        self.url.set_ellipsize(Pango.EllipsizeMode.END)
        self.url.set_alignment(0.0, 0.5)
        self.url.set_text("")
        self.header.pack_start(self.url, True, True, 0)
        # frame around the box
        self.frame = Gtk.Frame()
        self.frame.set_border_width(3)
        self.frame.add(self.header)
        self.pack_start(self.frame, False, False, 6)
        # connect the webkit stuff
        self.webkit.connect("notify::uri", self._on_uri_changed)
        self.webkit.connect("notify::load-status",
            self._on_load_status_changed)

    def _on_uri_changed(self, view, pspec):
        prop = pspec.name
        uri = view.get_property(prop)
        # the full uri is irellevant for the purchase view, but it is
        # interessting to know what protocol/netloc is in use so that the
        # user can verify its https on sites he is expecting
        scheme, netloc, path, params, query, frag = urlparse.urlparse(uri)
        if scheme == "file" and netloc == "":
            self.url.set_text("")
        else:
            self.url.set_text("%s://%s" % (scheme, netloc))
        # start spinner when the uri changes
        #self.spinner.start()

    def _on_load_status_changed(self, view, pspec):
        prop = pspec.name
        status = view.get_property(prop)
        #print status
        if status == webkit.LoadStatus.PROVISIONAL:
            self.spinner.start()
            self.spinner.show()
        if (status == webkit.LoadStatus.FINISHED or
            status == webkit.LoadStatus.FAILED):
            self.spinner.stop()
            self.spinner.hide()