import asyncio
import logging
import os
import re
import warnings
from asyncio import Future
from functools import wraps
from inspect import signature
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union

from tqdm.auto import tqdm

from rubrix._constants import (
    DATASET_NAME_REGEX_PATTERN,
    DEFAULT_API_KEY,
    RUBRIX_WORKSPACE_HEADER_NAME,
)
from rubrix.client.apis.datasets import Datasets
from rubrix.client.apis.metrics import MetricsAPI
from rubrix.client.apis.searches import Searches
from rubrix.client.datasets import (
    Dataset,
    DatasetForText2Text,
    DatasetForTextClassification,
    DatasetForTokenClassification,
)
from rubrix.client.metrics.models import MetricResults
from rubrix.client.models import (
    BulkResponse,
    Record,
    Text2TextRecord,
    TextClassificationRecord,
    TokenClassificationRecord,
)
from rubrix.client.sdk.client import AuthenticatedClient
from rubrix.client.sdk.commons.api import async_bulk
from rubrix.client.sdk.commons.errors import RubrixClientError
from rubrix.client.sdk.datasets import api as datasets_api
from rubrix.client.sdk.datasets.models import CopyDatasetRequest, TaskType
from rubrix.client.sdk.metrics import api as metrics_api
from rubrix.client.sdk.metrics.models import MetricInfo
from rubrix.client.sdk.text2text import api as text2text_api
from rubrix.client.sdk.text2text.models import (
    CreationText2TextRecord,
    Text2TextBulkData,
    Text2TextQuery,
)
from rubrix.client.sdk.text_classification import api as text_classification_api
from rubrix.client.sdk.text_classification.models import (
    CreationTextClassificationRecord,
    LabelingRule,
    LabelingRuleMetricsSummary,
    TextClassificationBulkData,
    TextClassificationQuery,
)
from rubrix.client.sdk.token_classification import api as token_classification_api
from rubrix.client.sdk.token_classification.models import (
    CreationTokenClassificationRecord,
    TokenClassificationBulkData,
    TokenClassificationQuery,
)
from rubrix.client.sdk.users import api as users_api
from rubrix.client.sdk.users.models import User
from rubrix.utils import setup_loop_in_thread

_LOGGER = logging.getLogger(__name__)

class _RubrixLogAgent:
    def __init__(self, api: "Api"):
        self.__api__ = api
        self.__loop__, self.__thread__ = setup_loop_in_thread()

    @staticmethod
    async def __log_internal__(api: "Api", *args, **kwargs):

        try:
            return await api.log_async(*args, **kwargs)
        except Exception as ex:
            _LOGGER.error(
                f"Cannot log data {args, kwargs}\n"
                f"Error of type {type(ex)}\n: {ex}. ({ex.args})"
            )
            raise ex

    def log(self, *args, **kwargs) -> Future:
        return asyncio.run_coroutine_threadsafe(
            self.__log_internal__(self.__api__, *args, **kwargs), self.__loop__
        )

class Api:
    # Larger sizes will trigger a warning
    _MAX_CHUNK_SIZE = 5000

    def __init__(
        self,
        api_url: Optional[str] = None,
        api_key: Optional[str] = None,
        workspace: Optional[str] = None,
        timeout: int = 60,
        extra_headers: Optional[Dict[str, str]] = None,
    ):
        """Init the Python client.

        We will automatically init a default client for you when calling other client methods.
        The arguments provided here will overwrite your corresponding environment variables.

        Args:
            api_url: Address of the REST API. If `None` (default) and the env variable ``RUBRIX_API_URL`` is not set,
                it will default to `http://localhost:6900`.
            api_key: Authentification key for the REST API. If `None` (default) and the env variable ``RUBRIX_API_KEY``
                is not set, it will default to `rubrix.apikey`.
            workspace: The workspace to which records will be logged/loaded. If `None` (default) and the
                env variable ``RUBRIX_WORKSPACE`` is not set, it will default to the private user workspace.
            timeout: Wait `timeout` seconds for the connection to timeout. Default: 60.
            extra_headers: Extra HTTP headers sent to the server. You can use this to customize
                the headers of Rubrix client requests, like additional security restrictions. Default: `None`.

        Examples:
            >>> import rubrix as rb
            >>> rb.init(api_url="http://localhost:9090", api_key="4AkeAPIk3Y")
            >>> # Customizing request headers
            >>> headers = {"X-Client-id":"id","X-Secret":"secret"}
            >>> rb.init(api_url="http://localhost:9090", api_key="4AkeAPIk3Y", extra_headers=headers)

        """
        api_url = api_url or os.getenv("RUBRIX_API_URL", "http://localhost:6900")
        # Checking that the api_url does not end in '/'
        api_url = re.sub(r"\/$", "", api_url)
        api_key = api_key or os.getenv("RUBRIX_API_KEY", DEFAULT_API_KEY)
        workspace = workspace or os.getenv("RUBRIX_WORKSPACE")
        headers = extra_headers or {}

        self._client: AuthenticatedClient = AuthenticatedClient(
            base_url=api_url,
            token=api_key,
            timeout=timeout,
            headers=headers.copy(),
        )

        self._user: User = users_api.whoami(client=self._client)
        if workspace is not None:
            self.set_workspace(workspace)

        self._agent = _RubrixLogAgent(self)

    def __del__(self):
        if hasattr(self, "_client"):
            del self._client
        if hasattr(self, "_agent"):
            del self._agent

    @property
    def client(self):
        """The underlying authenticated client"""
        return self._client

    @property
    def datasets(self) -> Datasets:
        return Datasets(client=self._client)

    @property
    def searches(self):
        return Searches(client=self._client)

    @property
    def metrics(self):
        return MetricsAPI(client=self.client)

    def set_workspace(self, workspace: str):
        """Sets the active workspace.

        Args:
            workspace: The new workspace
        """
        if workspace is None:
            raise Exception("Must provide a workspace")

        if workspace != self.get_workspace():
            if workspace == self._user.username:
                self._client.headers.pop(RUBRIX_WORKSPACE_HEADER_NAME, workspace)
            elif (
                self._user.workspaces is not None
                and workspace not in self._user.workspaces
            ):
                raise Exception(f"Wrong provided workspace {workspace}")
            self._client.headers[RUBRIX_WORKSPACE_HEADER_NAME] = workspace

    def get_workspace(self) -> str:
        """Returns the name of the active workspace.

        Returns:
            The name of the active workspace as a string.
        """
        return self._client.headers.get(
            RUBRIX_WORKSPACE_HEADER_NAME, self._user.username
        )

    def copy(self, dataset: str, name_of_copy: str, workspace: str = None):
        """Creates a copy of a dataset including its tags and metadata

        Args:
            dataset: Name of the source dataset
            name_of_copy: Name of the copied dataset
            workspace: If provided, dataset will be copied to that workspace

        Examples:
            >>> import rubrix as rb
            >>> rb.copy("my_dataset", name_of_copy="new_dataset")
            >>> rb.load("new_dataset")
        """
        datasets_api.copy_dataset(
            client=self._client,
            name=dataset,
            json_body=CopyDatasetRequest(name=name_of_copy, target_workspace=workspace),
        )

    def delete(self, name: str) -> None:
        """Deletes a dataset.

        Args:
            name: The dataset name.

        Examples:
            >>> import rubrix as rb
            >>> rb.delete(name="example-dataset")
        """
        datasets_api.delete_dataset(client=self._client, name=name)

    def log(
        self,
        records: Union[Record, Iterable[Record], Dataset],
        name: str,
        tags: Optional[Dict[str, str]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        chunk_size: int = 500,
        verbose: bool = True,
        background: bool = False,
    ) -> Union[BulkResponse, Future]:
        """Logs Records to Rubrix.

        The logging happens asynchronously in a background thread.

        Args:
            records: The record, an iterable of records, or a dataset to log.
            name: The dataset name.
            tags: A dictionary of tags related to the dataset.
            metadata: A dictionary of extra info for the dataset.
            chunk_size: The chunk size for a data bulk.
            verbose: If True, shows a progress bar and prints out a quick summary at the end.
            background: If True, we will NOT wait for the logging process to finish and return an ``asyncio.Future``
                object. You probably want to set ``verbose`` to False in that case.

        Returns:
            Summary of the response from the REST API.
            If the ``background`` argument is set to True, an ``asyncio.Future`` will be returned instead.

        Examples:
            >>> import rubrix as rb
            >>> record = rb.TextClassificationRecord(
            ...     text="my first rubrix example",
            ...     prediction=[('spam', 0.8), ('ham', 0.2)]
            ... )
            >>> rb.log(record, name="example-dataset")
            1 records logged to http://localhost:6900/datasets/rubrix/example-dataset
            BulkResponse(dataset='example-dataset', processed=1, failed=0)
            >>>
            >>> # Logging records in the background
            >>> rb.log(record, name="example-dataset", background=True, verbose=False)
            <Future at 0x7f675a1fffa0 state=pending>
        """
        future = self._agent.log(
            records=records,
            name=name,
            tags=tags,
            metadata=metadata,
            chunk_size=chunk_size,
            verbose=verbose,
        )
        if background:
            return future

        try:
            return future.result()
        finally:
            future.cancel()

    async def log_async(
        self,
        records: Union[Record, Iterable[Record], Dataset],
        name: str,
        tags: Optional[Dict[str, str]] = None,
        metadata: Optional[Dict[str, Any]] = None,
        chunk_size: int = 500,
        verbose: bool = True,
    ) -> BulkResponse:
        """Logs Records to Rubrix with asyncio.

        Args:
            records: The record, an iterable of records, or a dataset to log.
            name: The dataset name.
            tags: A dictionary of tags related to the dataset.
            metadata: A dictionary of extra info for the dataset.
            chunk_size: The chunk size for a data bulk.
            verbose: If True, shows a progress bar and prints out a quick summary at the end.

        Returns:
            Summary of the response from the REST API

        Examples:
            >>> # Log asynchronously from your notebook
            >>> import asyncio
            >>> import rubrix as rb
            >>> from rubrix.utils import setup_loop_in_thread
            >>> loop, _ = setup_loop_in_thread()
            >>> future_response = asyncio.run_coroutine_threadsafe(
            ...     rb.log_async(my_records, dataset_name), loop
            ... )
        """
        tags = tags or {}
        metadata = metadata or {}

        if not name:
            raise InputValueError("Empty dataset name has been passed as argument.")

        if not re.match(DATASET_NAME_REGEX_PATTERN, name):
            raise InputValueError(
                f"Provided dataset name {name} does not match the pattern {DATASET_NAME_REGEX_PATTERN}. "
                "Please, use a valid name for your dataset"
            )

        if chunk_size > self._MAX_CHUNK_SIZE:
            _LOGGER.warning(
                """The introduced chunk size is noticeably large, timeout errors may occur.
                Consider a chunk size smaller than %s""",
                self._MAX_CHUNK_SIZE,
            )

        if isinstance(records, Record.__args__):
            records = [records]
        records = list(records)

        try:
            record_type = type(records[0])
        except IndexError:
            raise InputValueError("Empty record list has been passed as argument.")

        if record_type is TextClassificationRecord:
            bulk_class = TextClassificationBulkData
            creation_class = CreationTextClassificationRecord
        elif record_type is TokenClassificationRecord:
            bulk_class = TokenClassificationBulkData
            creation_class = CreationTokenClassificationRecord
        elif record_type is Text2TextRecord:
            bulk_class = Text2TextBulkData
            creation_class = CreationText2TextRecord
        else:
            raise InputValueError(
                f"Unknown record type {record_type}. Available values are {Record.__args__}"
            )

        processed, failed = 0, 0
        progress_bar = tqdm(total=len(records), disable=not verbose)
        for i in range(0, len(records), chunk_size):
            chunk = records[i : i + chunk_size]

            response = await async_bulk(
                client=self._client,
                name=name,
                json_body=bulk_class(
                    tags=tags,
                    metadata=metadata,
                    records=[creation_class.from_client(r) for r in chunk],
                ),
            )

            processed += response.parsed.processed
            failed += response.parsed.failed

            progress_bar.update(len(chunk))
        progress_bar.close()

        # TODO: improve logging policy in library
        if verbose:
            _LOGGER.info(
                f"Processed {processed} records in dataset {name}. Failed: {failed}"
            )
            workspace = self.get_workspace()
            if (
                not workspace
            ):  # Just for backward comp. with datasets with no workspaces
                workspace = "-"
            print(
                f"{processed} records logged to {self._client.base_url}/datasets/{workspace}/{name}"
            )

        # Creating a composite BulkResponse with the total processed and failed
        return BulkResponse(dataset=name, processed=processed, failed=failed)

    def delete_records(
        self,
        name: str,
        query: Optional[str] = None,
        ids: Optional[List[Union[str, int]]] = None,
        discard_only: bool = False,
        discard_when_forbidden: bool = True,
    ) -> Tuple[int, int]:
        """Delete records from a Rubrix dataset.

        Args:
            name: The dataset name.
            query: An ElasticSearch query with the `query string syntax
                <https://rubrix.readthedocs.io/en/stable/guides/queries.html>`_
            ids: If provided, deletes dataset records with given ids.
            discard_only: If `True`, matched records won't be deleted. Instead, they will be marked as `Discarded`
            discard_when_forbidden: Only super-user or dataset creator can delete records from a dataset.
                So, running "hard" deletion for other users will raise an `ForbiddenApiError` error.
                If this parameter is `True`, the client API will automatically try to mark as ``Discarded``
                records instead. Default, `True`

        Returns:
            The total of matched records and real number of processed errors. These numbers could not
            be the same if some data conflicts are found during operations (some matched records change during
            deletion).

        Examples:
            >>> ## Delete by id
            >>> import rubrix as rb
            >>> rb.delete_records(name="example-dataset", ids=[1,3,5])
            >>> ## Discard records by query
            >>> import rubrix as rb
            >>> rb.delete_records(name="example-dataset", query="metadata.code=33", discard_only=True)
        """
        return self.datasets.delete_records(
            name=name,
            query=query,
            ids=ids,
            mark_as_discarded=discard_only,
            discard_when_forbidden=discard_when_forbidden,
        )

    def load(
        self,
        name: str,
        query: Optional[str] = None,
        ids: Optional[List[Union[str, int]]] = None,
        limit: Optional[int] = None,
        id_from: Optional[str] = None,
        as_pandas=None,
    ) -> Dataset:
        """Loads a Rubrix dataset.

        Parameters:
        -----------
            name:
                The dataset name.
            query:
                An ElasticSearch query with the
                `query string syntax <https://rubrix.readthedocs.io/en/stable/guides/queries.html>`_
            ids:
                If provided, load dataset records with given ids.
            limit:
                The number of records to retrieve.

            id_from:
                If provided, starts gathering the records starting from that Record. As the Records returned with the
                load method are sorted by ID, ´id_from´ can be used to load using batches.

            as_pandas:
                DEPRECATED! To get a pandas DataFrame do ``rb.load('my_dataset').to_pandas()``.

        Returns:
        --------
            A Rubrix dataset.

        Examples:
            **Basic Loading**: load the samples sorted by their ID
            >>> import rubrix as rb
            >>> dataset = rb.load(name="example-dataset")

            **Iterate over a large dataset:**
                When dealing with a large dataset you might want to load it in batches to optimize memory consumption
                and avoid network timeouts. To that end, a simple batch-iteration over the whole database can be done
                employing the `from_id` parameter. This parameter will act as a delimiter, retrieving the N items after
                the given id, where N is determined by the `limit` parameter. **NOTE** If
                no `limit` is given the whole dataset after that ID will be retrieved.

            >>> import rubrix as rb
            >>> dataset_batch_1 = rb.load(name="example-dataset", limit=1000)
            >>> dataset_batch_2 = rb.load(name="example-dataset", limit=1000, id_from=dataset_batch_1[-1].id)

        """
        if as_pandas is False:
            warnings.warn(
                "The argument `as_pandas` is deprecated and will be removed in a future version. "
                "Please adapt your code accordingly. ",
                FutureWarning,
            )
        elif as_pandas is True:
            raise ValueError(
                "The argument `as_pandas` is deprecated and will be removed in a future version. "
                "Please adapt your code accordingly. ",
                "If you want a pandas DataFrame do `rb.load('my_dataset').to_pandas()`.",
            )

        response = datasets_api.get_dataset(client=self._client, name=name)
        task = response.parsed.task

        task_config = {
            TaskType.text_classification: (
                text_classification_api.data,
                TextClassificationQuery,
                DatasetForTextClassification,
            ),
            TaskType.token_classification: (
                token_classification_api.data,
                TokenClassificationQuery,
                DatasetForTokenClassification,
            ),
            TaskType.text2text: (
                text2text_api.data,
                Text2TextQuery,
                DatasetForText2Text,
            ),
        }

        try:
            get_dataset_data, request_class, dataset_class = task_config[task]
        except KeyError:
            raise ValueError(
                f"Load method not supported for the '{task}' task. Supported tasks: "
                f"{[TaskType.text_classification, TaskType.token_classification, TaskType.text2text]}"
            )
        response = get_dataset_data(
            client=self._client,
            name=name,
            request=request_class(ids=ids, query_text=query),
            limit=limit,
            id_from=id_from,
        )

        records = [sdk_record.to_client() for sdk_record in response.parsed]
        try:
            records_sorted_by_id = sorted(records, key=lambda x: x.id)
        # record ids can be a mix of int/str -> sort all as str type
        except TypeError:
            records_sorted_by_id = sorted(records, key=lambda x: str(x.id))

        return dataset_class(records_sorted_by_id)

    def dataset_metrics(self, name: str) -> List[MetricInfo]:
        response = datasets_api.get_dataset(self._client, name)
        response = metrics_api.get_dataset_metrics(
            self._client, name=name, task=response.parsed.task
        )

        return response.parsed

    def get_metric(self, name: str, metric: str) -> Optional[MetricInfo]:
        metrics = self.dataset_metrics(name)
        for metric_ in metrics:
            if metric_.id == metric:
                return metric_

    def compute_metric(
        self,
        name: str,
        metric: str,
        query: Optional[str] = None,
        interval: Optional[float] = None,
        size: Optional[int] = None,
    ) -> MetricResults:
        response = datasets_api.get_dataset(self._client, name)

        metric_ = self.get_metric(name, metric=metric)
        assert metric_ is not None, f"Metric {metric} not found !!!"

        response = metrics_api.compute_metric(
            self._client,
            name=name,
            task=response.parsed.task,
            metric=metric,
            query=query,
            interval=interval,
            size=size,
        )

        return MetricResults(**metric_.dict(), results=response.parsed)

    def fetch_dataset_labeling_rules(self, dataset: str) -> List[LabelingRule]:
        response = text_classification_api.fetch_dataset_labeling_rules(
            self._client, name=dataset
        )

        return [LabelingRule.parse_obj(data) for data in response.parsed]

    def rule_metrics_for_dataset(
        self, dataset: str, rule: LabelingRule
    ) -> LabelingRuleMetricsSummary:
        response = text_classification_api.dataset_rule_metrics(
            self._client, name=dataset, query=rule.query, label=rule.label
        )

        return LabelingRuleMetricsSummary.parse_obj(response.parsed)

__ACTIVE_API__: Optional[Api] = None

def active_api() -> Api:
    """Returns the active API.

    If Active API is None, initialize a default one.
    """
    global __ACTIVE_API__
    if __ACTIVE_API__ is None:
        __ACTIVE_API__ = Api()
    return __ACTIVE_API__

def api_wrapper(api_method: Callable):
    """Decorator to wrap the API methods in module functions.

    Propagates the docstrings and adapts the signature of the methods.
    """

    def decorator(func):
        if asyncio.iscoroutinefunction(api_method):

            @wraps(api_method)
            async def wrapped_func(*args, **kwargs):
                return await func(*args, **kwargs)

        else:

            @wraps(api_method)
            def wrapped_func(*args, **kwargs):
                return func(*args, **kwargs)

        sign = signature(api_method)
        wrapped_func.__signature__ = sign.replace(
            parameters=[val for key, val in sign.parameters.items() if key != "self"]
        )
        return wrapped_func

    return decorator

@api_wrapper(Api.__init__)
def init(*args, **kwargs):
    global __ACTIVE_API__
    __ACTIVE_API__ = Api(*args, **kwargs)

@api_wrapper(Api.set_workspace)
def set_workspace(*args, **kwargs):
    return active_api().set_workspace(*args, **kwargs)

@api_wrapper(Api.get_workspace)
def get_workspace(*args, **kwargs):
    return active_api().get_workspace(*args, **kwargs)

@api_wrapper(Api.copy)
def copy(*args, **kwargs):
    return active_api().copy(*args, **kwargs)

@api_wrapper(Api.delete)
def delete(*args, **kwargs):
    return active_api().delete(*args, **kwargs)

@api_wrapper(Api.log)
def log(*args, **kwargs):
    return active_api().log(*args, **kwargs)

@api_wrapper(Api.log_async)
def log_async(*args, **kwargs):
    return active_api().log_async(*args, **kwargs)

@api_wrapper(Api.load)
def load(*args, **kwargs):
    return active_api().load(*args, **kwargs)

@api_wrapper(Api.delete_records)
def delete_records(*args, **kwargs):
    return active_api().delete_records(*args, **kwargs)

class InputValueError(RubrixClientError):
    pass


import openai
import csv
import argparse
from collections import Counter
from typing import List
from data.discourse_connectors import discourse_connectors

# Ihr OpenAI GPT-3 API-Schlüssel
api_key = "[insert your API KEY here]"

def parse_arguments() -> argparse.Namespace:
    """CLI-Argumente parsen."""
    parser = argparse.ArgumentParser(description='Vergleicht die Häufigkeit von Diskursmarkern in Artikeln und GPT-3 Texten.')
    parser.add_argument('korpus', help='Pfad zum TSV-Korpus')
    parser.add_argument('--anzahl_artikel', type=int, default=10, help='Anzahl der zu vergleichenden Artikel')
    return parser.parse_args()

def count_connectors(text: str, connectors, List) -> Counter:
    """Zählt die Diskursmarker im Text."""
    words = text.lower().split()
    return Counter([word for word in words if word in connectors])

def get_gpt_text(prompt: str, token_limit: int) -> str:
    """Holt den generierten Text von GPT-3."""
    openai.api_key = api_key
    response = openai.Completion.create(
        engine="text-davinci-002",
        prompt=prompt,
        max_tokens=token_limit
    )
    return response.choices[0].text.strip()

def trim_to_same_length(article_text: str, gpt_text: str) -> (str, str):
    """Kürzt die Texte auf die gleiche Länge."""
    token_limit = min(len(article_text.split()), len(gpt_text.split()))
    return ' '.join(article_text.split()[:token_limit]), ' '.join(gpt_text.split()[:token_limit])

def sum_total_connectors(counter: Counter) -> int:
    """Berechnet die Gesamtanzahl der Diskursmarker in einem Counter."""
    return sum(counter.values())

def main():
    """
    Pseudo-Code für main():

    1. CLI-Argumente parsen.
    2. Öffne den Korpus und lese die angegebene Anzahl an Artikeln.
    3. Für jeden Artikel:
        a. Nutze die ersten 10 Sätze als Prompt für GPT-3.
        b. Generiere den GPT-3 Text.
        c. Kürze Artikel und GPT-3 Text auf die gleiche Länge.
        d. Zähle die Diskursmarker in beiden Texten.
        e. Schreibe die Ergebnisse in die CSV-Datei.
    4. Berechne die Durchschnittswerte und gib sie im Terminal aus.
    """

    args = parse_arguments()

    # Ausgabe-CSV-Datei vorbereiten
    with open('output.csv', 'w', newline='', encoding='utf-8') as csvfile:
        fieldnames = ['Head', 'Article_Connectors', 'Article_Text', 'GPT_Connectors', 'GPT_Text']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()

        article_connector_totals = []
        gpt_connector_totals = []

        # Korpus öffnen und Artikel lesen
        with open(args.korpus, 'r', encoding='utf-8') as f:
            reader = csv.DictReader(f, delimiter='\t')

            for i, row in enumerate(reader):
                if i >= args.anzahl_artikel:
                    break

                # Prompt für GPT-3 erstellen
                article_text = row['content']
                head = row['head']
                prompt = '. '.join(article_text.split('. ')[:10])

                # GPT-3 Text generieren
                token_limit = len(article_text.split())
                gpt_text = get_gpt_text(prompt, token_limit)

                # Texte auf gleiche Länge kürzen
                article_text, gpt_text = trim_to_same_length(article_text, gpt_text)

               # Diskursmarker zählen
                article_counts = count_connectors(article_text, discourse_connectors)
                gpt_counts = count_connectors(gpt_text, discourse_connectors)

                article_total = sum_total_connectors(article_counts)
                gpt_total = sum_total_connectors(gpt_counts)

                # Ergebnisse in der CSV-Datei speichern
                writer.writerow({'Head': head, 'Article_Connectors': article_total, 'Article_Text': article_text, 'GPT_Connectors': gpt_total, 'GPT_Text': gpt_text})

                article_connector_totals.append(article_total)
                gpt_connector_totals.append(gpt_total)

        # Durchschnittswerte berechnen
        avg_article_total = sum(article_connector_totals) / args.anzahl_artikel
        avg_gpt_total = sum(gpt_connector_totals) / args.anzahl_artikel

        # Durchschnittswerte im Terminal ausgeben
        print(f"Durchschnittliche Diskursmarker im Artikel: {avg_article_total}")
        print(f"Durchschnittliche Diskursmarker im GPT-Text: {avg_gpt_total}")

if __name__ == '__main__':
    main()

"""
Output:
Durchschnittliche Diskursmarker im Artikel: 26.1
Durchschnittliche Diskursmarker im GPT-Text: 24.6
"""


import random

# Print board
def print_board(board):
    print("+---+---+---+")
    for i in range(3):
        print("|", end=" ")
        for j in range(3):
            print(board[i * 3 + j], end=" | ")
        print("\n+---+---+---+")

# Check who is the winner
def check_winner(board):
    winning_combos = [(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)]
    for combo in winning_combos:
        if board[combo[0]] == board[combo[1]] == board[combo[2]] != " ":
            return board[combo[0]]
    return None

# Get human move
def get_human_move(board):
    while True:
        move = input("Enter a move (1-9): ")
        if not move.isdigit() or int(move) < 1 or int(move) > 9 or board[int(move) - 1] != " ":
            print("Invalid move, try again.")
            continue
        return int(move) - 1

# Get computer move
def get_computer_move(board):
    available_moves = [i for i in range(9) if board[i] == " "]

    # Check if any move can win the game
    for move in available_moves:
        test_board = list(board)
        test_board[move] = "O"
        if check_winner(test_board) == "O":
            return move

    # Check if any move can prevent the human from winning the game
    for move in available_moves:
        test_board = list(board)
        test_board[move] = "X"
        if check_winner(test_board) == "X":
            return move

    # Choose a random available move
    return random.choice(available_moves)

def main():
    board = [" " for i in range(9)]
    while True:
        print_board(board)
        winner = check_winner(board)
        if winner:
            print(f"{winner} wins!")
            break
        if " " not in board:
            print("Tie!")
            break
        if len([i for i in board if i != " "]) % 2 == 0:
            move = get_computer_move(board)
            board[move] = "O"
            print(f"Computer played move {move + 1}.")
        else:
            move = get_human_move(board)
            board[move] = "X"
            print(f"Human played move {move + 1}.")

if __name__ == "__main__":
    main()


Denominations = {1:[2000,500,200,100,50,20,10,5,2,1],2:[100,50,20,10,5,2,1,0.50,0.25,0.10,0.05,0.01],3:[50,20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01],4:[10000,5000,2000,1000,500,100,50,10,5,1],5:[100,50,20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01]}
def checkval(s):
    while(True):
        value = input("-->  Enter the amount you wish to obtain the equivalent change for: ")
        try:
            value = float(value)
            if value < 0:
                print(".\n"*3)
                print(" ERROR !!! YOU HAVE ENTERED A NEGATIVE VALUE !!! PLEASE TRY AGAIN !!!")
            else:
                low_val_check = min(Denominations[s])
                if value<=low_val_check:
                    print(".\n"*3)
                    print(" ERROR !!! LOWER DENOMINATION DOES NOT EXIST, PLEASE ENTER A VALUE FOR WHICH CHANGE CAN BE OBTAINED !!!")
                else:
                    if s == 1 or s == 4:
                        print("\nYour Number Might be Rounded to the nearest integer due to Notes existing only in integer formats given the chosen currency. . . . ")
                        return round(value)
                    elif s == 2 or s==3 or s==5 :
                        print("\nYour Number Might be Rounded to 2 decimal places due to Notes existing only in integer formats given the chosen currency. . . . ")
                        return round(value,2)
        except ValueError:
            print(".\n"*3)
            print("YOUR ENTRY HAS INVALID CHARACTERS IN IT !!! PLEASE ENTER A NUMERICAL AMOUNT !!!")

def checkcurr(s):
    while(True):
        try:
            s = int(s)
            if 1<=s<=5:
                return s
            else:
                print(".\n"*3)
                print("ERROR !!! NUMBER NOT IN SPECIFIED RANGE !!! PLEASE TRY AGAIN !!! \n")
                s = input("Enter The Numerical Value for your desired currency: ")
        except ValueError:
            print(".\n"*3)
            print("ERROR !!! ENTRY CONTAINS INVALID CHARACTERS !!! PLEASE TRY AGAIN !!! \n")
            s = input("Enter The Numerical Value for your desired currency: ")

def calc_change(c,a):
    list_of_denominations = Denominations[c]
    string = "Your Change is :"
    flag = 0
    for i in list_of_denominations:
        if a!=i:
            flag = 1
        if a >= i and flag == 1:
            part_of_change = int(a/i)
            part_of_change = str(part_of_change)
            a = a%i
            if c == 1:
                if i > 5:
                    string += " ' "+part_of_change+"'  "+str(i)+'  Rupee Note/s'
                else:
                    string += " ' "+part_of_change+"'  "+str(i)+'  Rupee Coin/s'
            elif c== 4:
                if i >= 1000:
                    string += " ' "+part_of_change+"'  "+str(i)+'  Yen Note/s'
                else:
                    string += " ' "+part_of_change+"'  "+str(i)+'  Yen Coin/s'
            elif c== 2:
                if i >= 1:
                    string += " ' "+part_of_change+"'  "+str(i)+'  Dollar Note/s'
                elif i == 0.01:
                    temp = int(i*100)
                    string += " ' "+part_of_change+"'  "+str(temp)+'  Penny/ies'
                elif i == 0.05:
                    temp = int(i*100)
                    string += " ' "+part_of_change+"'  "+str(temp)+'  nickel/s'
                elif i == 0.1:
                    temp = int(i*100)
                    string += " ' "+part_of_change+"'  "+str(temp)+'  Dime/s'
                elif i==0.25:
                    temp = int(i*100)
                    string += " ' "+part_of_change+"'  "+str(temp)+'  Quarter/s'
                elif i==0.5:
                    temp = int(i*100)
                    string += " ' "+part_of_change+"' "+str(temp)+'Half Dollar/s'
            elif c == 3:
                if i >= 5:
                    string += "' "+part_of_change+"'  "+str(i)+'  Pound Note/s'
                elif i==2 or i == 1:
                    string += " ' "+part_of_change+"'  "+str(i)+'  Pound Coin/s'
                else:
                    string += " ' "+part_of_change+"'  "+str(i)+'  Pence'
            else:
                if i >= 0.1:
                    temp = int(i*100)
                    string += " ' "+part_of_change+"'  "+str(temp)+'  Yuan Note/s'
                else:
                    temp = int(i*100)
                    string += " ' "+part_of_change+"'  "+str(temp)+'  Yuan Coin/s'
    return string

def main():
    ans = 'y'
    while(ans == 'y'):
        print(" "*10+"*-"*35+"*")
        print(" "*35+"COIN CHANGE MAKER")
        print(" "*10+"*-"*35+"*","\n")
        print("-->  Choose the NUMERICAL VALUE corresponding to the currency you wish to obtain the change in :\n1) Indian Rupee (₹) \n2) American Dollar ($) \n3) British Pound (£) \n4) Japanese Yen (¥) \n5) Chinese Yuan (CN¥) \n")
        int_value = input("Enter The Numerical Value for your desired currency: ")
        currency = checkcurr(int_value)
        print(".\n"*3)
        print("OPTION SAVED......\n")
        amount = checkval(currency)
        print(".\n"*3)
        print("OPTION SAVED......\n")
        answer = calc_change(currency,amount)
        print(answer)
        print("Do you wish to continue using the Program ? Press 'y' to continue and 'n' to terminate")
        ans = input()
        while(True):
            if ans not in ['y','n']:
                print("ERROR !!! INVALID ENTRY DETECTED !!! PLEASE TRY AGAIN !!!")
                print(".\n"*3)
                print("Do you wish to continue using the Program ? Press 'y' to continue and 'n' to terminate")
                ans = input()
            else:
                break

if __name__ == "__main__":
    main()


import os, glob
from sqlalchemy import *
import sqlalchemy.exc
from sqlalchemy.orm import sessionmaker
from parse import *
from lxml import etree
from datetime import datetime, date, time

step_types = {
    'given': 0,
    'when': 1,
    'then': 2
}

curpath = os.path.basename(os.getcwd())
if curpath == 'steps':
    os.chdir('..')

if curpath == 'features':
    os.chdir('..')

global_vars = dict()
connect_config = dict()
link_config = dict()

try:
    exec(open("./settings.py").read(), global_vars)
except FileNotFoundError:
    try:
        exec(open("../settings.py").read(), global_vars)
    except FileNotFoundError:
        pass

try:
    connect_config = global_vars['connect_config']
    link_config = global_vars['link_config']
except:
    pass

class TestModule:

    def __init__(self, module_name):
        self.module_name = module_name
        self.results = []
        self.connect_list = dict()

    def run_predicate_from_file(self, predicate, step_type):
        predicate_template = "./features/steps/{step_type}*.sql"
        param_value_tmpl = "--!{param}={value}"
        predicate_format = predicate_template.format(step_type=step_type)

        params = dict()
        filename_params = dict()
        sql_command = ""
        is_sql_command = 0
        filename = ""
        cmd = ""
        decl = 'DECLARE @context XML,\n@table XML,\n'
        prms = "\t@context = @context OUTPUT,\n"
        prms += "\t@table = @table,\n"

        def process_file(fn):
            sql_command = ""
            is_sql = 0
            schema = ""
            proc_name = ""

            with open(g, 'r') as f:
                for line in f:
                    p = parse(param_value_tmpl, line)
                    if p != None and len(p.named) > 0:
                        params[p.named['param']] = p.named['value']

                    sql_command += line

                try:
                    sql_command = 'EXEC {}.{}'.format(params['schema_name'], params['proc_name'])
                    schema, proc_name = params['schema_name'], params['proc_name']
                except:
                    is_sql = 1

            return sql_command, is_sql, schema, proc_name

        for g in glob.iglob(predicate_format):
            filename = os.path.basename(os.path.splitext(g)[0])
            step_filename = "{0} {1}".format(step_type, predicate)
            if filename == step_filename:
                cmd, is_sql_command, schema, proc_name = process_file(g)
                break
            else:
                fd = parse(filename, step_filename)
                if fd != None and len(fd.named) > 0:
                    for k in fd.named:
                        vl = fd.named[k]
                        decl += "\t@{} NVARCHAR(128) = '{}',\n".format(k, vl)
                        prms += "\t@{} = @{},\n".format(k, k)

                    cmd, is_sql_command, schema, proc_name = process_file(g)
                    break

        context = etree.Element("context")
        table = etree.SubElement(context, "table")
        if self.ctx_table is not None:
            for ct in self.ctx_table:
                row = etree.SubElement(table, 'row')
                for hd in ct.headings:
                    row.set(hd, ct[hd])

        ctx_str = etree.tostring(context)

        if len(cmd) > 0:
            ctx_str = str(ctx_str.decode("utf-8")).replace("'", "''")
            decl = decl[:-2] + "\n\nSET @table = '{}'".format(ctx_str)

            try:
                decl += "\n\nSET @context = '{}'".format(self.ctx_xml)
            except AttributeError:
                pass

            cmd = decl + "\n\n" + cmd + "\n"
            cmd += prms[:-2] if is_sql_command == 0 else ''
            cmd += "\n\nSELECT @context AS behave_result"

        if params['connect'] in link_config:
            params['connect'] = link_config[params['connect']]

        engine = create_engine(params['connect'])

        maker = sessionmaker(bind=engine)
        session = maker()

        row = None
        trans = session.begin(subtransactions=True)
        try:
            session.execute("SET DATEFORMAT dmy;")
            res = session.execute(text(cmd))
            if res.cursor != None:

                while 'behave_result' != res.cursor.description[0][0]:
                    names = [c[0] for c in res.cursor.description]
                    store_results = []
                    while 1:
                        row_raw = res.cursor.fetchone()
                        if row_raw is None:
                            break

                        row = dict(zip(names, row_raw))
                        store_results.append(row)

                    self.results.append(store_results)
                    res.cursor.nextset()

                row = res.cursor.fetchone()
                res.close()
                session.execute('IF @@TRANCOUNT > 0 BEGIN COMMIT END')
        except:
            print(cmd)
            raise

        # процедура или скрипт вернули данные
        rs_xml = etree.Element("results")
        rs_xml.set('step_type', step_type)
        rs_xml.set('predicate', predicate)
        for res_set in self.results:
            rset_xml = etree.SubElement(rs_xml, "result_set")
            for res_row in res_set:
                rrow_xml = etree.SubElement(rset_xml, "row")
                for res_col in res_row:
                    res_col4xml = 'empty' if len(res_col) == 0 else res_col
                    rrow_xml.set(res_col4xml, str(res_row[res_col]))

        session.close()

        if row != None:
            if row[0] is None:
                ctx_out_xml = etree.Element("context")
            else:
                ctx_out_xml = etree.XML(row[0])
            ctx_out_xml.append(rs_xml)
            return etree.tostring(ctx_out_xml).decode('utf-8')

        return None


n = int(input())

cached = {}
def f(n):
    if n in cached:
        return cached[n]
    if 0 <= n <= 1:
        return 1
    f_n = f(n-1) + f(n-2)
    cached[n] = f_n
    return f_n

print(f(n))


# 퐁당퐁당 안된다 선입후출 !

import sys
input = sys.stdin.readline

n = int(input())

count = 0
for _ in range(n) :
    word = list(map(str, input()))
    word.pop() # 맨뒤에 '/n'를 제거 위함

    stack = []
    for i in range(len(word)) :
        if len(stack) == 0 :
            stack.append(word[i])
        else :
            if word[i] == stack[-1] :
                stack.pop()
            else :
                stack.append(word[i])

    if len(stack) == 0 :
        count += 1

print(count)


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

import logging

import tempfile
from subprocess import PIPE, Popen
import os
import random
import codecs
import math

from sklearn.pipeline import FeatureUnion
from sklearn.pipeline import Pipeline

from resources import SEMEVAL_SCORER_PATH

logger = logging.getLogger(__name__)

def pretty_pipeline(obj):
    """Pretty print a sklearn Pipeline.

    This function is especially useful to extract information within
    FeatureUnion Pipeline.

    Args:
        obj: A sklearn Pipeline.

    Returns:
        A flat version of the Pipeline object.

    """
    if isinstance(obj, list):
        return [pretty_pipeline(o) for o in obj]
    elif isinstance(obj, FeatureUnion):
        return {'n_jobs': obj.n_jobs,
                'transformer_list': obj.transformer_list,
                'transformer_weights': obj.transformer_weights}
    elif isinstance(obj, Pipeline):
        return {'steps': pretty_pipeline(obj.steps)}
    elif isinstance(obj, tuple):
        return pretty_pipeline(list(obj))
    else:
        return obj

def strings_to_integers(strings, labels):
    """Convert an array of strings to an array of integers.

    Convert an array of strings to an array of integers where the same
    string will always have the same integers value.

    Args:
        strings: An array of strings.

    Returns:
        An array of integers
    """
    integers = []
    for string in strings:
        integers.append(labels.index(string))
    return integers

def integers_to_strings(integers, labels):
    """Convert an array of integers to an array of strings using labels as
reference.

    Args:
        integers: An array of integers.
        labels: An array of strings where each integers will be
        replaced by the string at the index.

    Returns:
        An array of strings.
    """
    strings = []
    for integer in integers:
        strings.append(labels[integer])
    return strings

def merge_classes(lst, classes, new_class):

    """Merge classes from lst into one new_class.

    Args:
        lst: A list of classes that will be replaced (strings).
        classes: A list of classes to replace (strings).
        new_class: The new class (string).

    Returns:
        The list with all occurences of classes replaced by new_class.
    """
    for i in range(len(lst)):
        if lst[i] in classes:
            lst[i] = new_class
    return lst

def eval_with_semeval_script(test, predicted):
    """Eval prediction on test with semeval script (T4SA).

    Args:
        test: variable documentation.
        predicted: variable documentation.

    Returns:
        Returns information

    Raises:
        IOError: An error occurred.
    """
    predicted = integers_to_strings(predicted, test.labels)
    ofile = tempfile.NamedTemporaryFile(mode='w+', delete=False)
    ret = None
    try:
        for (sid, pred) in zip(test.sid, predicted):
            ofile.write('%s\t%s\n' % (sid, pred))
        ofile.close()
        p = Popen(['_scripts/SemEval2016_task4_test_scorer_subtaskA.pl',
                   ofile.name], stdout=PIPE, stderr=PIPE, cwd=SEMEVAL_SCORER_PATH)
        out, err = p.communicate()
        ret = out + err
        ret = ret.decode()
        with open(ofile.name + '.scored', 'r') as ifile:
            for line in ifile:
                ret += line
    finally:
        if not ofile.closed:
            ofile.close()
        os.remove(ofile.name)
        os.remove(ofile.name + '.scored')
    return ret

def assoc_value(lst, value):
    """Return the element associated to value and its index.

    Args:
        lst: A associative array/list.
        value: The value to match on.

    Returns:
        The element associated to value (with the value itself) and
        its index.
    """
    for (idx, el) in enumerate(lst):
        if el[0] == value:
            return el, idx

def invert_dict_nonunique(d):
    newdict = {}
    for k in d:
        newdict.setdefault(d[k], []).append(k)
    return newdict

def split_train_valid(input_path, valid_num=3000):
    """Split a file in two (.valid and .train) with valid_num lines in
.valid and everything else in .train.
    """
    train_path = input_path + '.train'
    valid_path = input_path + '.valid'
    nb_line = 0
    with codecs.open(input_path, 'r', 'utf-8') as ifile:
        nb_line = len([line for line in ifile])
    if valid_num <= 1 and valid_num >= 0:
        valid_num = math.floor(nb_line * valid_num)

    valid_indexes = random.sample(range(nb_line), valid_num)
    try:
        ifile = codecs.open(input_path, 'r', 'utf-8')
        train_file = codecs.open(train_path, 'w+', 'utf-8')
        valid_file = codecs.open(valid_path, 'w+', 'utf-8')
        idx = 0
        for line in ifile:
            try:
                v_idx = valid_indexes.index(idx)
                valid_file.write(line)
                del valid_indexes[v_idx]
            except ValueError:
                train_file.write(line)
            idx += 1
    finally:
        ifile.close()
        train_file.close()
        valid_file.close()

def opinion_lexicon_to_graph(lexicon):
    """Return a undirected graph from lexicon.

LEXICON is an opinion lexicon where each key is a class and the value
associated to it is a list of words that belongs to the class.

This function will build a undirected graph where each node are words
and the edges between nodes represent a similarity relationship. There
will be an edge between two words if they belong to the same class.

In practice, this method returns a dictionnary where a key is a word
of LEXICON and the value associated to it are all words from the same
class.

This is intended to be used by emb.build_custom3
"""
    ret = {}
    lexicon_inv = invert_dict_nonunique(lexicon)
    for c in lexicon_inv:
        words = lexicon_inv[c]
        for word in words:
            ret[word] = words
    return ret

def split_lexicon_train_test(lexicon, ratio=0.9, shuffle=False):
    """Split each class of the lexicon in train and test.

    Args:
        lexicon: A lexicon to split.
        ratio: The ratio of train/test. 0.9 means 90% of the lexicon
        will go in the train lexicon.
        shuffle: A boolean to specify that the lexicon should be
        shuffled before splitting.

    Returns:
        A train lexicon and a test lexicon.
    """
    train_lexicon = {}
    test_lexicon = {}
    lexicon_inv = invert_dict_nonunique(lexicon)
    for c in lexicon_inv:
        c_words = lexicon_inv[c]
        n = len(c_words)
        if shuffle:
            random.shuffle(c_words)
        limit = math.floor(n * ratio)
        for w in c_words[:limit]:
            train_lexicon[w] = c
        for w in c_words[limit:]:
            test_lexicon[w] = c

    return train_lexicon, test_lexicon

def remove_multi_words_in_lexicon(lexicon):
    """Remove multi-words in lexicon"""
    ret = {}
    for w in lexicon:
        if len(w.split(' ')) == 1:
            ret[w] = lexicon[w]
    return ret


#!/usr/bin/env python
import unittest

from network import Arc, Node, Network

class NetworkTestCase(unittest.TestCase):
    def test_basic(self):
        node = Node('one')
        nw = Network([node])
        self.assertEqual(nw.find_node('one'), node)
        node = Node(('two', 2))
        nw.add_node(node)
        self.assertEqual(nw.find_node(('two', 2)), node)
        three = Node('three')
        arc = Arc(three, 1)
        nw.find_node('one').add_arc(arc)
        self.assertEqual(nw.find_node('three'), three)

    def test_dont_lose_nodes(self):
        n1 = Node(1)
        n2 = Node(2)
        n1.add_arc(Arc(n2))
        nw = Network([n1])
        self.assertEqual(nw.find_node(2), n2)
        n3 = Node(3)
        n2.add_arc(Arc(n3))
        self.assertEqual(nw.find_node(3), n3)

    def test_has_arc(self):
        n1 = Node(1)
        n2 = Node(2)
        a = Arc(n2)
        n1.add_arc(a)
        self.assertTrue(n1.has_arc(a))

    def test_to_node(self):
        n2 = Node(2)
        a = Arc(n2)
        self.assertTrue(a.to_node() == n2)

    def test_flow(self):
        n2 = Node(1)
        a = Arc(n2)
        self.assertTrue(a.total_flow() == 0)
        self.assertTrue(a.flow() == 0)
        a.set_flow(3)
        self.assertTrue(a.flow() == 3)
        a.set_flow(3, 'red')
        self.assertTrue(a.flow('red') == 3)
        self.assertEqual(a.total_flow(), 6)

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


#!/usr/bin/env python3
import jetson.inference
import jetson.utils
import rospy
import os
import numpy as np
import cv2
import ctypes
from sensor_msgs.msg import Image, CameraInfo
from cv_bridge import CvBridge, CvBridgeError

class semanticSegmentation:
	def __init__(self, topics_to, network, labels_file, camera_info):
		# Create labels name list
		with open(labels_file) as labels:
			lines = labels.readlines()
			self._object_class = [label.strip() for label in lines]

		# Camera width and height
		self._CAMERA_WIDTH = camera_info.width
		self._CAMERA_HEIGHT = camera_info.height

		self._FILTER_MODE = "point"
		self._IGNORE_CLASS = "void"
		self._ALPHA = 175.0

		# Initialize network
		self._net = jetson.inference.segNet(network)
		# set the alpha blending value
		self._net.SetOverlayAlpha(self._ALPHA)
		# allocate the output images for the overlay & mask
		self._img_overlay = jetson.utils.cudaAllocMapped(self._CAMERA_WIDTH * self._CAMERA_HEIGHT * 4 * ctypes.sizeof(ctypes.c_float))
		self._img_mask = jetson.utils.cudaAllocMapped(self._CAMERA_WIDTH * self._CAMERA_HEIGHT * 4 * ctypes.sizeof(ctypes.c_float))

		self._bridge = CvBridge()
		# Create semantic segmentation overlay and mask frame publisher
		self._overlay_publisher = rospy.Publisher(topics_to['overlay'], Image, queue_size=1)
		self._mask_publisher = rospy.Publisher(topics_to['mask'], Image, queue_size=1)

	def detect(self, data):
		# Receive frame from camera
		try:
			frame = self._bridge.imgmsg_to_cv2(data, "rgb8")
		except CvBridgeError as e:
       			print(e)

		# Convert frame to RGBA
		rgba_frame = cv2.cvtColor(frame, cv2.COLOR_RGB2RGBA)
		# Convert frame to CUDA
		cuda_mem = jetson.utils.cudaFromNumpy(rgba_frame)

		# process the segmentation network
		self._net.Process(cuda_mem, self._CAMERA_WIDTH, self._CAMERA_HEIGHT, self._IGNORE_CLASS)

		# generate the overlay and mask
		self._net.Overlay(self._img_overlay, self._CAMERA_WIDTH, self._CAMERA_HEIGHT, self._FILTER_MODE)
		self._net.Mask(self._img_mask, self._CAMERA_WIDTH, self._CAMERA_HEIGHT, self._FILTER_MODE)

		# Return frame to numpy arrray
		overlay_frame = jetson.utils.cudaToNumpy(self._img_overlay, self._CAMERA_WIDTH, self._CAMERA_HEIGHT, 4)
		mask_frame = jetson.utils.cudaToNumpy(self._img_mask, self._CAMERA_WIDTH, self._CAMERA_HEIGHT, 4)

		# Convert RGBA frame to RGB
		overlay_frame = cv2.cvtColor(overlay_frame, cv2.COLOR_RGBA2RGB).astype(np.uint8)
		mask_frame = cv2.cvtColor(mask_frame, cv2.COLOR_RGBA2RGB).astype(np.uint8)

		test_frame = np.zeros_like(mask_frame)
		test_frame[np.where((mask_frame==[220, 20, 60]).all(axis=2))] = (255, 255, 255)

		# Publish semantic segmentation frame
		try:
			self._overlay_publisher.publish(self._bridge.cv2_to_imgmsg(overlay_frame, encoding="rgb8"))
			self._mask_publisher.publish(self._bridge.cv2_to_imgmsg(test_frame, encoding="rgb8"))
			rospy.loginfo("Published semantic segmentation frame")
		except CvBridgeError as e:
			print(e)

def main():
	rospy.init_node('semantic_segmentation')
	NETWORK = rospy.get_param('network', "fcn-resnet18-cityscapes-512x256")
	LABELS_FILE = rospy.get_param('labels_file', '/home/gradproj2020/catkin_ws/src/graduation_project_simulation/scripts/semantic_segmentation/networks/FCN-ResNet18-Cityscapes-512x256/classes.txt')

	LEFT_CAMERA_INFO = rospy.wait_for_message('/prius/right_camera/camera_info', CameraInfo)

	os.chdir('/home/gradproj2020/catkin_ws/src/graduation_project_simulation/scripts/semantic_segmentation')

	TOPIC_FROM = "/prius/left_camera/image_raw"
	TOPICS_TO = {'overlay':"/semantic_segmentation/image_overlay",
		     'mask':"/semantic_segmentation/image_mask"}

	semantic_segmentation = semanticSegmentation(TOPICS_TO, NETWORK, LABELS_FILE, LEFT_CAMERA_INFO)

	rawframe_subscriber = rospy.Subscriber(TOPIC_FROM, Image, semantic_segmentation.detect, buff_size=2**24, queue_size=2)
	rate = rospy.Rate(30)
	try:
		while not rospy.is_shutdown():
			rate.sleep()
			rospy.spin()

	except rospy.ROSInterruptException:
		rospy.loginfo("Shutting down")

if __name__ == "__main__":
	main()


import numpy as np
import rogues

def dramadah(n, k=1):
    """
    dramadah  a (0,1) matrix whose inverse has large integer entries.
          An anti-hadamard matrix a is a matrix with elements 0 or 1 for
          which mu(a) := norm(inv(a),'fro') is maximal.
          a = dramadah(n, k) is an n-by-n (0,1) matrix for which mu(a) is
          relatively large, although not necessarily maximal.
          Available types (the default is k = 1):
          k = 1: a is toeplitz, with abs(det(a)) = 1, and mu(a) > c(1.75)^n,
                 where c is a constant.
          k = 2: a is upper triangular and toeplitz.
          the inverses of both types have integer entries.

          Another interesting (0,1) matrix:
          k = 3: A has maximal determinant among (0,1) lower Hessenberg
          matrices: det(A) = the n'th Fibonacci number.  A is Toeplitz.
          The eigenvalues have an interesting distribution in the complex
          plane.

          References:
          R.L. Graham and N.J.A. Sloane, Anti-Hadamard matrices,
             Linear Algebra and Appl., 62 (1984), pp. 113-137.
          L. Ching, The maximum determinant of an nxn lower Hessenberg
             (0,1) matrix, Linear Algebra and Appl., 183 (1993), pp. 147-153.
    """

    if k == 1:
        # Toeplitz
        c = np.ones(n)
        for i in range(1, n, 4):
            m = min(1, n - i)
            c[i:i + m + 1] = 0

        r = np.zeros(n)
        r[0:4] = np.array([1, 1, 0, 1])
        if n < 4:
            r = r[0:n]

        a = rogues.toeplitz(c, r)

    elif k == 2:
        # Upper triangular and Toeplitz
        c = np.zeros(n)
        c[0] = 1
        r = np.ones(n)
        r[2::2] = 0

        a = rogues.toeplitz(c, r)

    elif k == 3:
        # Lower Hessenberg.
        c = np.ones(n)
        c[1::2] = 0
        a = rogues.toeplitz(c, np.hstack((np.array([1, 1]), np.zeros(n - 2))))

    return a


import allure

from integration_template.forms.main_form import MainForm, TypeOfTesting
from tests.test_base import TestBase

class TestMainForm(TestBase):
    main_form = MainForm()

    def setup(self):
        with allure.step("Go to main page"):
            self.go_to_start_page()

        with allure.step("Main page is displayed"):
            assert self.main_form.state.is_displayed()
            assert self.main_form.label_nav_header.state.wait_for_displayed()

    def test_main_page(self):
        with allure.step("Check Navigation menu items"):
            assert len(self.main_form.nav_menu_buttons()) == 4

        with allure.step("Check base elements"):
            assert self.main_form.contact_us.state.is_displayed()
            for type_of_testing in TypeOfTesting:
                assert self.main_form.type_of_testing_button(type_of_testing).state.is_displayed()


import CRUD

while True:
     ListaTareas = CRUD.Leer()
     print("\n---------------------------------------")
     print("Aplicación CRUD")
     print("1. Adicionar Tarea")
     print("2. Consultar Tareas")
     print("3. Actualizar Tarea")
     print("4. Eliminar Tarea")
     print("5. Salir")

     opcion = input("\nIngrese una opción: ")
     print("---------------------------------------\n")

     if opcion == "1":
          nombre = input("Ingrese el nombre de la tarea >> ")
          descrp = input("Describa la tarea >> ")
          estado = input("Estado actual de la tarea >> ")
          try:
               tiempo = float(input("Ingrese el tiempo destinado para la tarea (minutos) >> "))
          except:
               print("Error. Tiempo debe ser un número.")
               continue

          CRUD.Crear(
               nombre,
               {"Descripcion":descrp, "Estado Actual":estado, "Tiempo":tiempo}
               )

     elif opcion == "2":
          print("Lista de tareas guardadas:\n")
          for i, Tarea in enumerate(ListaTareas):
               print(f"{i+1}: {Tarea}:\n")
               Tarea = ListaTareas[Tarea]
               print(f"Descripción: {Tarea['Descripcion']}")
               print(f"Estado Actual: {Tarea['Estado Actual']}")
               print(f"Tiempo: {Tarea['Tiempo']}")

     elif opcion == "3":
          nombre = input("Ingrese el nombre de la tarea >> ")
          if nombre not in ListaTareas: print("La tarea no existe.")
          else:
               descrp = input("Describa la tarea >> ")
               estado = input("Estado actual de la tarea >> ")
               try:
                    tiempo = float(input("Ingrese el tiempo destinado para la tarea (minutos) >> "))
               except:
                    print("Error. Tiempo debe ser un número.")
                    continue

               CRUD.Crear(
                    nombre,
                    {"Descripcion":descrp, "Estado Actual":estado, "Tiempo":tiempo}
                    )

     elif opcion == "4":
          nombre = input("Ingrese el nombre de la tarea >> ")
          if nombre not in ListaTareas: print("La tarea no existe.")
          else:
               CRUD.Eliminar(nombre)
               print("Se ha eliminado la tarea.")

     elif opcion == "5":
          print("\nGracias por utilizar este servicio 😁\n")
          break
     else:
          print("\nOpción no disponible. Inténtelo de nuevo")

Ciclo 1 (Grupo 36)/Clases/ControladorCRUD.py


from __future__ import unicode_literals
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post, Tag
from .forms import PostAddForm
from django.contrib.auth.decorators import login_required

# Create your views here.
@login_required
def delete(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    post.delete()
    return redirect('blog_app:index')

@login_required
def edit(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    if request.method == "POST":
        #instance:オブジェクトとほぼ同義でクラスを使用したデータの実体
        form = PostAddForm(request.POST, request.FILES, instance=post)
        if form.is_valid():
            form.save()
            return redirect('blog_app:detail', post_id=post.id)
    else:
        form = PostAddForm(instance=post)
    #formにpostのデータを入れた状態のデータをadd.htmlに入れる
    return render(request, 'blog_app/edit.html', {'form': form, 'post': post})

@login_required
def add(request):
    #url/へ遷移してからPOSTでリクエスト出したとき
    if request.method == "POST":
        #リクエストがPOSTなら、formの中身とユーザーを更新してレスポンス
        form = PostAddForm(request.POST, request.FILES)#FILESは画像などのファイルデータ
        if form.is_valid():
            #保存する前にどのuserの投稿か判断
            post = form.save(commit=False)#仮登録
            post.user = request.user
            #記事の内容とuserの判別に成功したら保存
            post.save()
            return redirect('blog_app:index')
    #url/へ遷移してからPOST以外のリクエスト出したとき
    else:
        #リクエストがPOST以外なら,特になにも更新せずにレスポンスに返す
        form = PostAddForm()
    #url/へ遷移してなにもしてない状態
    #formにpostを入れていない空の状態のデータをadd.htmlに入れる
    return render(request, 'blog_app/add.html', {'form': form})

def detail(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    return render(request, 'blog_app/detail.html', {'post': post})

def index(request):
    posts = Post.objects.all().order_by('-created_at')
    return render(request, 'blog_app/index.html', {'posts': posts})


import random

# Choisi un mot
mots = []
with open("mots.txt") as fl:
    for l in fl:
        mots.append(l.rstrip("\n"))
mot = random.choice(mots)

# Variable cle
lettres = []
faux = 0
trouve = False
corps_plein = ["O", "/", "|", "\\", "/", "\\"]
corps = [" ", " ", " ", " ", " ", " "]

while not trouve:
    trouve = True
    print(" +---+")
    print(" |   |")
    print(" |   {}".format(corps[0]))
    print(" |  {}{}{}".format(corps[1], corps[2], corps[3]))
    print(" |  {} {}".format(corps[4], corps[5]))
    print("_|_")
    print("| |")
    for l in mot:
        if l in lettres:
            print(l, end=" ")
        else:
            trouve = False
            print("_", end=" ")
    print()
    print("Lettres utilisées - ", end="")
    for l in lettres:
        print(l, end=" | ")
    print()

    if faux > 5:
        print("Oh non :( Tu as perdu...")
        print("Le mot était : {}".format(mot))
        break

    if trouve:
        print("Bravo ! Tu viens de remporter La partie !")
        break

    lettre = input("Entez une lettre: ")
    lettres.append(lettre)

    if lettre not in mot:
        corps[faux] = corps_plein[faux]
        faux += 1


# -*- coding:UTF-8 -*-
import numpy as np
import xlrd as xlrd
from scipy.stats import norm
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import sys
import importlib
# 参数1 Excel文件位置 参数2 选择要作图的表格    参数3、4、5 xy轴代表含义以及标题文字 参数6列数 函数可以选择某地址文件某一个表格某一列来操作
class Make_figure:
    def result_pic(address, Excel_Choice,xlabel,ylabel,title,FormColumns):
        # 设置字体
        importlib.reload(sys)
        matplotlib.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        # 读取文件
        trainFile = address
        if(Excel_Choice==0):
            data = pd.read_excel(trainFile, 0)
        elif(Excel_Choice==1):
            data = pd.read_excel(trainFile, 1)
        elif(Excel_Choice==2):
            data = pd.read_excel(trainFile, 2)
        elif(Excel_Choice==3):
            data = pd.read_excel(trainFile, 3)
        else:
            print('输入有误！！！')

        #print(data.iloc[:, 1].describe())
        # 设置表格形式
        # 定义x轴、y轴取值范围

        x = range(0, data.iloc[:,FormColumns].count(), 1)
        y = data.iloc[:, FormColumns]
        # 定义折线
        s = plt.plot(x, y, 'b--')
        # 定义文字说明
        s1 = "以太坊区块交易数"
        plt.xlabel(xlabel)
        plt.ylabel(ylabel)
        plt.title(title)
        plt.legend([s1], loc="upper left")
        # 图片打印
        plt.show()


# Module 5
#   Programming Assignment 6
#       Prob-3.py

# Robert Ballenger

from graphics import *

def main():
    win = GraphWin(title="Shooty Shooty Bow Target", height=400, width=400)

    # Little bit of shorthand, instead of writing "Point(200, 200)" for the middle of each circle, I just assigned it a variable.
    center = Point(200, 200)

    # First up we work the white circle. The 160 radius seems random, but it's beceause this was the last one I started with.
    whiteC = Circle(center, 160)
    whiteC.setFill("white")
    whiteC.draw(win)

    # Notice here how the black circl is 30 radius smaller... HMMM.
    blackC = Circle(center, 120)
    blackC.setFill("black")
    blackC.draw(win)

    # Blue, just like the rest.
    blueC = Circle(center, 90)
    blueC.setFill("blue")
    blueC.draw(win)

    # Almost done, we do red, which is 30 less on the radius.
    redC = Circle(center, 60)
    redC.setFill("red")
    redC.draw(win)

    # This last one draws a yellow circle with a radius of 30, which is where I actually started.
    yellowC = Circle(center, 30)
    yellowC.setFill("yellow")
    yellowC.draw(win)

    # This last command just keeps the window open until the user clicks, with text to accompany it.
    Text(Point(200, 385), "Click again to quit.").draw(win)
    win.getMouse()

main()


from imath.Trainer import Trainer
import torch
import imath as pt
import os
import torch.nn as nn
import numpy as np

class VAETrainer(Trainer):

    def __init__(self, optim, lant_dim, criterion, **kwargs):
        super(VAETrainer, self).__init__(**kwargs)

        self.lant_dim = lant_dim

        self.Distribute = self.model.Distribute
        self.Decoder = self.model.Decoder

        self.optim = optim

        self.criterion = criterion

    def forward(self, data, forward_mode, **kwargs):
        img = data['x']
        # print('??')
        batch = img.size(0)

        distrib = self.Distribute(img)
        mul = distrib[:, 0:1]
        log_sig = distrib[:, 1:2]

        epi = torch.randn(batch, self.lant_dim).to(img.device)
        # print(mul.shape, log_sig.shape, epi.shape)
        z = mul + epi * torch.exp(log_sig / 2.)
        z = z.view((batch, 6, 7, 6))

        reconstrust = self.Decoder(z)

        loss = self.criterion(img, reconstrust) * 10
        self.update(self.optim, loss)

        if forward_mode == 'train':
            return {'loss': loss.item()}
        else:
            return {'rec': reconstrust}

    def evaluate(self, batch_size, device, **kwargs):
        # loss = []
        for n, data in enumerate(self._evaluate(batch_size, device, **kwargs)):
            # loss.append(data['loss'])
            rec = data['rec']
            # print(rec.shape)
            if n == 1:
                for r in rec[:2]:
                    im.imshow(r.squeeze())
                    # im.imsave('rec.png', r.squeeze()*256)
        # loss = np.mean(np.array(loss))

        return 1.


import sys
import time
import rospy
from array import array
from std_msgs.msg import String
import os

voicePublisher = rospy.Publisher('voiceOutput', String, queue_size=10)

def publishMessage(message):
    voicePublisher.publish(message)

def listenNode(data):
    print("callback " + data.data)
    if  data.data:
        print("message receiveid")
        os.system("espeak " + '"' + data.data + '"')
        publishMessage("")

def listener():
    rospy.init_node('listener', anonymous=True)
    voiceSubscriber  = rospy.Subscriber('voiceOutput', String, listenNode)
    while not rospy.is_shutdown():
        print("listening")
        rospy.spin()

if __name__ == '__main__':
    listener()


import os

import numpy as np
import tensorflow as tf

ROOT_DIR = os.path.abspath(__file__ + "/../../")

class BaseSpinFoam:
    def __init__(self, spin_j, n_boundary_intertwiners, n_vertices):
        self.n_boundary_intertwiners = n_boundary_intertwiners
        self.n_vertices = n_vertices
        self.spin_j = float(spin_j)
        self.single_vertex_amplitudes = tf.convert_to_tensor(
            _load_vertex_amplitudes(self.spin_j), dtype=tf.float64
        )

    @tf.function
    def get_spinfoam_amplitudes(self, boundary_intertwiners):
        pass

class StarModelSpinFoam(BaseSpinFoam):
    def __init__(self, spin_j):
        super().__init__(spin_j, n_boundary_intertwiners=20, n_vertices=6)

    @tf.function(input_signature=[
        tf.TensorSpec(shape=(None, 4), dtype=tf.int32),
    ])
    def _get_amplitude_per_star_edge(self, boundary_intertwiners_per_edge):
        amplitude = tf.gather_nd(
            self.single_vertex_amplitudes, boundary_intertwiners_per_edge
        )
        return amplitude

    @tf.function(input_signature=[
        tf.TensorSpec(shape=(None, 20), dtype=tf.int32),
    ])
    def get_spinfoam_amplitudes(self, boundary_intertwiners):
        vertex_1 = self._get_amplitude_per_star_edge(
            boundary_intertwiners[:, :4]
        )
        vertex_2 = self._get_amplitude_per_star_edge(
            boundary_intertwiners[:, 4:8]
        )
        vertex_3 = self._get_amplitude_per_star_edge(
            boundary_intertwiners[:, 8:12]
        )
        vertex_4 = self._get_amplitude_per_star_edge(
            boundary_intertwiners[:, 12:16]
        )
        vertex_5 = self._get_amplitude_per_star_edge(
            boundary_intertwiners[:, 16:20]
        )

        star_amplitudes = tf.einsum(
            "abcde, ie, id, ic, ib, ia -> i",
            self.single_vertex_amplitudes,
            vertex_1, vertex_2, vertex_3, vertex_4, vertex_5
        )
        return star_amplitudes

class SingleVertexSpinFoam(BaseSpinFoam):
    def __init__(self, spin_j):
        super().__init__(spin_j, n_boundary_intertwiners=5, n_vertices=1)

    @tf.function(input_signature=[
        tf.TensorSpec(shape=(None, 5), dtype=tf.int32),
    ])
    def get_spinfoam_amplitudes(self, boundary_intertwiners):
        return tf.gather_nd(self.single_vertex_amplitudes, boundary_intertwiners)

class SpinFoamEnvironment:
    """
    This class creates the hypergrid environment which the GFlowNet agent
    interacts with. Loads the precalculated amplitudes for a single vertex,
    calculates the corresponding probabilities, and stores them in self.rewards

    Parameters:
    ----------
        spin_j:    (float)
                    Length of the grid in one dimension is 2*spin_j + 1. All
                    the lengths are equal in all dimensions

        spinfoam_model: BaseSpinFoam
                    Python class representing a specific spinfoam model

                     n_boundary_intertwiners
                        - stores the number of boundary intertwiners
                        - represents the number of dimensions for the
                            environment grid

                    get_spinfoam_amplitudes()
                        - function that calculates the amplitudes of a specific
                            spinfoam model
                        - will be used to calculate the rewards for each position
                            in the environment grid
    """
    def __init__(self, spinfoam_model: BaseSpinFoam):
        self.spinfoam_model = spinfoam_model
        self.grid_dimension = self.spinfoam_model.n_boundary_intertwiners
        self.grid_length = int(2 * self.spinfoam_model.spin_j + 1)

    @tf.function(input_signature=[tf.TensorSpec(shape=None, dtype=tf.int32)])
    def reset_for_forward_sampling(self, batch_size):
        """Generate positions at the hypergrid origin of size batch_size"""
        positions = tf.zeros(
            shape=(batch_size, self.grid_dimension),
            dtype=tf.int32
        )
        return positions

    @staticmethod
    @tf.function(input_signature=[
        tf.TensorSpec(shape=(None, None), dtype=tf.int32),
        tf.TensorSpec(shape=(None, None), dtype=tf.int32),
    ])
    def step_forward(current_position, forward_action):
        new_position = current_position + forward_action[:, :-1]
        return new_position

    @tf.function(input_signature=[tf.TensorSpec(shape=(None, None), dtype=tf.int32)])
    def get_rewards(self, positions):
        """Get the corresponding rewards for positions"""
        rewards = tf.reshape(
            self._get_squared_spinfoam_amplitudes(positions), shape=(-1, 1)
        )
        return rewards

    @tf.function(input_signature=[
        tf.TensorSpec(shape=(None, None), dtype=tf.int32),
    ])
    def _get_squared_spinfoam_amplitudes(self, positions):
        return tf.math.square(
            self.spinfoam_model.get_spinfoam_amplitudes(positions)
        )

    @tf.function
    def reset_for_backward_sampling(self, batch_size):
        """Generate random positions in the hypergrid of size batch_size"""
        positions = tf.random.uniform(
            shape=(batch_size, self.grid_dimension),
            minval=0, maxval=self.grid_length, dtype=tf.int32
        )
        return positions

    @staticmethod
    @tf.function
    def step_backward(current_position, back_action):
        new_position = current_position - back_action
        return new_position

def _load_vertex_amplitudes(spin_j):
    vertex = np.load(f"{ROOT_DIR}/data/EPRL_vertices/Python/Dl_20/vertex_j_{spin_j}.npz")
    return vertex


import cv2
import numpy as np
from functions import top_offset

class SceneMoments():
    def __init__(self, sections_img, color, min_contour_size=1000, type_object="", offset=True, compl=False):
        self.min_contour_size = min_contour_size

        self.type_object = type_object

        self.bw = np.all(sections_img == color, axis=-1).astype(np.uint8)
        if offset:
            self.bw = self.bw[top_offset:,:]
        cv2.waitKey(0)

        sections_bw = self.bw * 255
        self.contours = self.get_contours(sections_bw)
        self.contour, self.contour_index = self.get_contour()
        self.defects = self.get_defects()

        self.compl = compl
        if compl:
            sections_bw_compl = 255 - sections_bw
            self.contours_compl = self.get_contours(sections_bw_compl)
            self.defects_compl = self.get_defects()

    def get_contours(self, img_bw):
        contours, _ = cv2.findContours(img_bw, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
        return contours

    def get_defects(self):
        chull_list = [cv2.convexHull(contour,returnPoints=False) for contour in self.contours]
        defects = [cv2.convexityDefects(contour, chull) for (contour,chull) in zip(self.contours, chull_list)]

        if len(defects) == 0 or np.all(np.equal(defects[0], None)):
            return []

        defect = defects[self.contour_index]
        if not isinstance(defect, np.ndarray):
            return []

        defect = defect[:,0,:].tolist()
        defect = [[start, end, mid, length] for start, end, mid, length in defect if length > self.min_contour_size]
        return defect

    '''
    Return the largest contour
    '''
    def get_contour(self):
        if len(self.contours) == 0:
            return [], -1
        largest_area = 0
        contour = self.contours[0]
        i = 0
        for _i, _contour in enumerate(self.contours):
            area = cv2.contourArea(_contour)
            if area > largest_area:
                largest_area = area
                contour = _contour
                i = _i
        return contour, i
        # return self.contours[0], 0

    '''
    Return a list of string containing useful data about the object: length of the contours and length of the defects for both, complement and normal
    '''
    def sstr(self):

        if not self.compl:
            lengths = "{} contours: {}  defects: {}".format(self.type_object, len(self.contours), len(self.defects))
            return [lengths, ""]
        else:
            lengths = "{} contours: {}  defects: {}".format(self.type_object, len(self.contours), len(self.defects))
            lengths_compl = "Compl contours: {}  defects: {}".format(len(self.contours_compl), len(self.defects_compl))
            return [lengths, lengths_compl, ""]

    def paint_defects(self, img, color):
        if len(self.contours) == 0:
            return img
        contour = self.contour
        for s, e, m, l in self.defects:
            cv2.circle(img, (contour[m][0][0], contour[m][0][1] + top_offset), 5, color, -1)
        return img

    def paint_lines(self, img, color):
        if len(self.contours) == 0:
            return img
        contour = self.contour
        for s, e, m, l in self.defects:
            cv2.line(img, (contour[s][0][0], contour[s][0][1] + top_offset), (contour[e][0][0], contour[e][0][1] + top_offset), color, 2)
        return img

    def paint_contours(self, img, color):
        if len(self.contours) == 0:
            return img
        contour = self.contour
        contour = np.array([[[c[0][0], c[0][1] + top_offset]] for c in contour])
        cv2.drawContours(img, contour, -1, color, 2)
        return img


cube = lambda x: x ** 3

def fibonacci(n):
    result = []
    i = 0
    a, b = 0, 1
    while i < n:
        result.append(a)
        a, b = b, a + b
        i += 1
    return result

print(list(map(cube, fibonacci(int(input())))))


import copy
import random

# # ---------------Input File & board dimension----------------/
input_txt = open("input15.txt", "r")
board_dimension = int(input_txt.readline())
board_area = [[0 for i in range(board_dimension)] for j in range(board_dimension)]

for i in range(0, board_dimension):
    row = input_txt.readline()
    for j in range(0, board_dimension):
        board_area[i][j] = int(row[j])

input_txt.close()

# def get_converage_array(x, y, board_area):
# 	## Set Dummy Value to identify index later
# 	board_area = copy.deepcopy(board_area)
# 	board_area[x][y] = 100
# 	matrix_dim = len(board_area)
# 	row_limit = [x - 3, x + 3 + 1]
# 	col_limit = [y - 3, y + 3 + 1]
# 	if col_limit[0] < 0:
# 		col_limit[0] = 0
# 	if col_limit[1] > matrix_dim:
# 		col_limit[1] = matrix_dim

# 	if row_limit[0] < 0:
# 		row_limit[0] = 0
# 	if row_limit[1] > matrix_dim:
# 		row_limit[1] = matrix_dim
# 	subset = [l[col_limit[0]:col_limit[1]] for l in board_area[row_limit[0]:row_limit[1]]]
# 	return subset

# def get_new_x_and_y(coverage_array):
# 	new_x, new_y = None, None

# 	## Can be optimized
# 	for i in range(len(coverage_array)):
# 		for j in range(len(coverage_array[0])):
# 			if coverage_array[i][j] == 100:
# 				new_x, new_y = i, j
# 				break
# 	return new_x, new_y

# def get_transformed_array(new_x, new_y, coverage_array):
# 	valid_coverage_array = copy.deepcopy(coverage_array)
# 	## Setting value 9 to count later
# 	for i in range(len(valid_coverage_array)):
# 		for j in range(len(valid_coverage_array[0])):
# 			if i == new_x or j == new_y or (abs(new_x - i) == abs(new_y - j)):
# 				if coverage_array[i][j] == 0:
# 					valid_coverage_array[i][j] = 9
# 	return valid_coverage_array

def get_total_cells_covered_at_point_and_covered_coordinates(x, y, inp_board):
    block_row_left = False
    block_row_right = False
    block_col_up = False
    block_col_down = False
    block_diag_lr_down = False
    block_diag_lr_up = False
    block_diag_rl_down = False
    block_diag_rl_up = False
    convered_coordinates = []

    def check_condition(x, y, board_area):
        n_row = len(board_area)
        n_col = len(board_area[0])
        n_row_index = n_row - 1
        n_col_index = n_col - 1
        if x > n_row_index or y > n_col_index or x < 0 or y < 0:
            return 0
        if board_area[x][y] != 3:
            return 1
        return 0

    i = 1
    valid_coverage_cell_count = 1
    convered_coordinates.append([x, y])
    while (i <= 3):
        # Row Left
        if not block_row_left:
            if check_condition(x, y + i, inp_board):
                convered_coordinates.append([x, y + i])
                valid_coverage_cell_count += 1
            else:
                block_row_left = True
        # Row Right
        if not block_row_right:
            if check_condition(x, y - i, inp_board):
                convered_coordinates.append([x, y - i])
                valid_coverage_cell_count += 1
            else:
                block_row_right = True
        # Col Up
        if not block_col_up:
            if check_condition(x - i, y, inp_board):
                convered_coordinates.append([x - i, y])
                valid_coverage_cell_count += 1
            else:
                block_col_up = True
        # Col Down
        if not block_col_down:
            if check_condition(x + i, y, inp_board):
                convered_coordinates.append([x + i, y])
                valid_coverage_cell_count += 1
            else:
                block_col_down = True
        # Diagnol L->R Down
        if not block_diag_lr_down:
            if check_condition(x + i, y + i, inp_board):
                convered_coordinates.append([x + i, y + i])
                valid_coverage_cell_count += 1
            else:
                block_diag_lr_down = True
        # Diagnol L->R Up
        if not block_diag_lr_up:
            if check_condition(x - i, y - i, inp_board):
                convered_coordinates.append([x - i, y - i])
                valid_coverage_cell_count += 1
            else:
                block_diag_lr_up = True
        # Diagnol R->L Down
        if not block_diag_rl_down:
            if check_condition(x - i, y + i, inp_board):
                convered_coordinates.append([x - i, y + i])
                valid_coverage_cell_count += 1
            else:
                block_diag_rl_down = True
        # Diagnol R->L Up
        if not block_diag_rl_up:
            if check_condition(x + i, y - i, inp_board):
                convered_coordinates.append([x + i, y - i])
                valid_coverage_cell_count += 1
            else:
                block_diag_rl_up = True
        i += 1
    return convered_coordinates, valid_coverage_cell_count

def simulation_action(sim_board_input):
    max_value = -99
    max_value_x = None
    max_value_y = None
    max_convered_coordinates = None
    result_dict = {}
    for i in range(len(sim_board_input)):
        for j in range((len(sim_board_input))):
            if sim_board_input[i][j] != 0:
                continue
            # coverage_array = get_converage_array(i, j, sim_board_input)
            # new_x, new_y = get_new_x_and_y(coverage_array)
            # valid_coverage_array = get_transformed_array(new_x, new_y, coverage_array)
            convered_coordinates, coverage_value = get_total_cells_covered_at_point_and_covered_coordinates(i, j,
                                                                                sim_board_input)
            if coverage_value > max_value:
                max_value = coverage_value
                max_value_x, max_value_y = i, j
                max_convered_coordinates = convered_coordinates
    result_dict['max_value'] = max_value
    result_dict['max_value_x'] = max_value_x
    result_dict['max_value_y'] = max_value_y
    result_dict['max_convered_coordinates'] = max_convered_coordinates
    return result_dict

def calculate_score(my_board, opp_board):
    my_score = sum(x.count(10) for x in my_board)
    my_score += sum(x.count(1) for x in my_board)
    opp_score = sum(x.count(20) for x in opp_board)
    opp_score += sum(x.count(2) for x in opp_board)
    return my_score - opp_score

def simulate(i, j, board_input, print_logs=False):
    my_coverage = copy.deepcopy(board_input)
    opp_coverage = copy.deepcopy(board_input)
    board_sim_input = copy.deepcopy(board_input)
    board_sim_input[i][j] = 1
    my_coverage[i][j] = 1

    convered_coordinates, coverage_value = get_total_cells_covered_at_point_and_covered_coordinates(i, j,
                                                                                board_sim_input)
    for _pos in convered_coordinates:
        my_coverage[_pos[0]][_pos[1]] = 10
        board_sim_input[_pos[0]][_pos[1]] = 10
    if print_logs:
        print('I Selected : ({}, {})'.format(i, j))
    # print('({}, {}) Simulation Base Score: {}'.format(i, j, calculate_score(my_coverage, opp_coverage)))
    # n_sim = sum(x.count(0) for x in board_sim_input)
    counter = 1
    while (sum(x.count(0) for x in board_sim_input) != 0):
        res_dict = simulation_action(board_sim_input)
        if counter % 2 == 0:
            for _pos in res_dict['max_convered_coordinates']:
                my_coverage[_pos[0]][_pos[1]] = 10
                if board_sim_input[_pos[0]][_pos[1]] != 0:
                    board_sim_input[_pos[0]][_pos[1]] = 30
                else:
                    board_sim_input[_pos[0]][_pos[1]] = 10
                board_sim_input[res_dict['max_value_x']][res_dict['max_value_y']] = 1
            if print_logs:
                print('I Selected : ({}, {})'.format(res_dict['max_value_x'], res_dict['max_value_y']))
        else:
            for _pos in res_dict['max_convered_coordinates']:
                opp_coverage[_pos[0]][_pos[1]] = 20
                if board_sim_input[_pos[0]][_pos[1]] != 0:
                    board_sim_input[_pos[0]][_pos[1]] = 30
                else:
                    board_sim_input[_pos[0]][_pos[1]] = 20
                board_sim_input[res_dict['max_value_x']][res_dict['max_value_y']] = 2
            if print_logs:
                print('Opp Selected : ({}, {})'.format(res_dict['max_value_x'], res_dict['max_value_y']))
        if print_logs:
            pass
            # print(np.matrix(my_coverage))
            # print(np.matrix(opp_coverage))
            print(np.matrix(board_sim_input))
            print('({}, {}) Simulation number: {} Score: {}'.format(i, j, counter,
                                                                    calculate_score(my_coverage, opp_coverage)))
        counter += 1
    if print_logs:
        print(np.matrix(board_sim_input))
        print('({}, {}) Simlutaion, Final Score: {}'.format(i, j, calculate_score(my_coverage, opp_coverage)))
    return calculate_score(my_coverage, opp_coverage)

def main(sim_board_input, print_logs=False):
    final_res_dict = {}
    max_value = -99
    max_value_x = None
    max_value_y = None
    sim_board_input_copy = copy.deepcopy(sim_board_input)
    for i in range(len(sim_board_input)):
        for j in range((len(sim_board_input))):
            if sim_board_input_copy[i][j] == 1:
                convered_coordinates, coverage_value = get_total_cells_covered_at_point_and_covered_coordinates(i, j,
                                                                                sim_board_input_copy)
                for _pos in convered_coordinates:
                    sim_board_input[_pos[0]][_pos[1]] = 10

            if sim_board_input_copy[i][j] == 2:
                convered_coordinates, coverage_value = get_total_cells_covered_at_point_and_covered_coordinates(i, j,
                                                                                sim_board_input_copy)
                for _pos in convered_coordinates:
                    if sim_board_input[_pos[0]][_pos[1]] == 10:
                        sim_board_input[_pos[0]][_pos[1]] = 30
                    else:
                        sim_board_input[_pos[0]][_pos[1]] = 20

    for i in range(len(sim_board_input)):
        for j in range((len(sim_board_input))):
            if sim_board_input[i][j] != 0:
                continue
            coverage_score = simulate(i, j, sim_board_input, print_logs=False)
            if coverage_score > max_value:
                max_value = coverage_score
                max_value_x, max_value_y = i, j

    if print_logs:
        print("Best Location Coordinated (X, Y) = ({}, {}) and Final Score = {}".format(max_value_x, max_value_y,
                                                                                max_value))
        print("*" * 100)
        print('Simulation: ')
        print("*" * 100)
        print('Input Matrix: ')
        print(np.matrix(sim_board_input))
        res_sim = simulate(max_value_x, max_value_y, sim_board_input, print_logs)
    final_res_dict['max_value_x'] = max_value_x
    final_res_dict['max_value_y'] = max_value_y
    final_res_dict['final_score'] = max_value

    abc = int(max_value_x)
    xyz = int(max_value_y)

    # Output Required Coordinates
    with open("output.txt", "w") as f2:
        f2.write("%d %d" % (abc, xyz))

    #print("Move coordinates: (%d, %d)" %(abc, xyz))

main(board_area)
# main(board_area, print_logs=True)


import csv
import random
import math
import numpy as np

input = open('data_pool_rabel_sorted.csv', 'r', encoding='utf-8')
input_reader = csv.reader(input)
output = open('data_rabel_pool.csv', 'w', encoding='utf-8')
output_writer = csv.writer(output)

check = 0
num = 0
length = 0
curr = -1
ret = []
for line in input_reader: #0 : length, #1 : discared, #2: rabel, #3 : id #4 : in id order, after is zum/
	if(check == 0): #real first
		check = 1
		length = int(line[0])
		ret = [int(line[3]), int(line[2])]
		curr = int(line[3])
		temp = line[5:5+int(line[0])*2]
		ret = ret + temp
		continue
	if(int(line[3]) == curr):
		length = length + int(line[0])
		temp = line[5:5+int(line[0])*2]
		ret = ret + temp
		continue
	#not same.
	ret = [length] + ret
	output_writer.writerow(ret)
	curr = int(line[3])
	ret = [int(line[3]), int(line[2])]
	temp = line[5:5+int(line[0])*2]
	ret = ret + temp
	length = int(line[0])
ret = [length] + ret
output_writer.writerow(ret)
input.close()
output.close()


import math

def primeCheck(num):
	prime = math.sqrt(num)
	for i in range(2,int(prime)) :
		if num%i == 0:
			return False
	return True

def sol(N):
	stack = []
	for num in range(pow(10,N-1),pow(10,N)) :
		if primeCheck(num) :
			stack.append(num)
	print(stack)

if __name__ == "__main__" :
	N = int(input())
	sol(N)


"""
ARGUMENTS: python3 ParseMetaFilesUpdated.py <path-to-jstor-data> <which-part> <how-many-parts> <output-path>
    <how-many-parts>: for parallel processing, this should be the number of workers available to run the program; 1 if not running in parallel.
    <which-part>: for parallel processing, this should be a unique number for each worker, from 1 to <how-many-parts>; 1 if not running in parallel.
USAGE: This program takes already-split dictionaries and reads in a batch of JSTOR article n-gram files to count the number of appearances of each n-gram in the dictionaries.
INPUT: JSTOR metadata files.
OUTPUT: A table in HDF5 format, indexed on 'file_name', consisting of 18 columns.
"""

import math
import os
import re
import sys
from tqdm import tqdm
from xml.etree import ElementTree as ET

import pandas as pd

# check if improper number of arguments; if so, return instructions and quit
if len(sys.argv) != 5:
    print(__doc__)
    exit()

# read in arguments from command line
JSTOR_HOME, NUM, NUM_CPUS, OUTPATH = sys.argv[1:]
NUM, NUM_CPUS = int(NUM), int(NUM_CPUS)

METADATA_HOME = os.path.join(JSTOR_HOME, 'metadata/')
path, dirs, files = next(os.walk(METADATA_HOME))
files = [(path + file) for file in files] # Add folder name "path" as prefix to file

NUM_EACH = math.ceil(len(files) / NUM_CPUS)
LEFT = (NUM - 1) * NUM_EACH
RIGHT = LEFT + NUM_EACH

files = files[LEFT:RIGHT]

def add(elem, attrs):
    # TO DO: Filter by article-type?

    elements = attrs['elements']
    surnames = attrs['surname']
    given_names = attrs['given-names']
    tag = elem.tag
    if tag in attrs['df_cols']:
        if tag == 'journal-id':
            tag = 'journal_id'
        elif tag == 'article':
            article_attrs = elem.attrib
            article_type = article_attrs['article-type']
            tag = 'type'
            elem.text = article_type
        elif tag =='journal-title':
            tag = 'journal_title'
        elif tag == 'article-id':
            tag = 'article_id'
        elif tag == 'article-name':
            tag = 'article_name'
        elif tag == 'surname':
            if type(elem.text) == 'str':
                surnames.append(elem.text.split(',')[0])
            else:
                surnames.append('None')
            elem.text = surnames
        elif tag == 'given-names':
            tag = 'given_names'
            given_names.append(elem.text)
            elem.text = given_names
        elif tag == 'issue-id':
            tag = 'issue_id'
        elif tag == 'ns1:ref':
            tag = 'jstor_url'
        elif tag == 'p':
            tag = 'abstract'

#        if tag not in elements:
#            elements[tag] = pd.Series([elem.text])
#        else:
#            elements[tag].append(pd.Series([elem.text]), ignore_index=True)
        len_list = len(elements[tag])
        elements[tag][len_list - 1] = elem.text

    for child in elem.findall('*'):
        add(child, attrs)

def xml2df(xml_files):
    """Transforms XML files into a Pandas DataFrame.

    Args:
        files: list of complete file paths

    Returns:
        df: DataFrame with article info"""

    all_records = {'type':[], 'journal_id':[], 'journal_title':[], 'issn':[], 'article_id':[], 'article_name':[], 'given_names':[], 'surname':[], 'day':[], 'month':[], 'year':[], 'volume':[], 'issue':[], 'issue_id':[], 'fpage':[], 'lpage':[], 'jstor_url':[], 'abstract':[]}
    attrs = {}
    attrs['elements'] = all_records
    attrs['surname'] = []
    attrs['given-names'] = []
    attrs['df_cols'] = ['article', 'journal-id', 'journal-title', 'issn', 'article-id', 'article-name', 'given-names', 'surname', 'day', 'month', 'year', 'volume', 'issue', 'issue-id', 'fpage', 'lpage', 'ns1:ref', 'p']

    for file in tqdm(xml_files):
        with open(file, 'rb') as f:
            t = ET.parse(f) # element tree
            root = t.getroot()
            for record in all_records:
                all_records[record].append('None')
            add(root, attrs)

    #print(all_records)
    print ('Start creating data frame')
    df = pd.DataFrame(all_records)
    return df

# This is definitely NOT a good practice. However, I'm trying not to break what's running properly.
def amend_df(df, files):
    file_names = []
    jstor_urls = []
    abstracts = []
    article_names = []

    for file in tqdm(files):
        file_names.append(re.findall('journal-article-.+\.xml', file)[0][:-4])
        with open(file, 'rb') as f:
            t = ET.parse(f) # element tree
            root = t.getroot()

            try:
                jstor_urls.append(root.find('front').find('article-meta').find('self-uri').items()[0][1])
            except:
                jstor_urls.append('None')

            try:
                abstracts.append(root.find('front').find('article-meta').find('abstract').find('p').text)
            except:
                abstracts.append('None')

            try:
                article_names.append(root.find('front').find('article-meta').find('title-group').find('article-title').text)
            except:
                article_names.append('None')

    df.loc[:, 'file_name'] = file_names
    df.loc[:, 'jstor_url'] = jstor_urls
    df.loc[:, 'abstract'] = abstracts
    df.loc[:, 'article_name'] = article_names

print('Start processing')
df = xml2df(files)
print('Start amending')
amend_df(df, files)

# df.to_pickle('pickles/part{}.pickle'.format(n))
df.set_index('file_name').to_hdf(os.path.join(OUTPATH, 'part{}.h5'.format(NUM)), key='metadata', mode='w')
#df.set_index('file_name').to_pickle(os.path.join(OUTPATH, 'part{}.pickle'.format(NUM)))


import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

class VizHelp():
    # Additional Usefull Display Methods
    def plotPredictions(self, predictions, targets, decoder_steps, epochs, file_name, show=True):
        stock_name = file_name.split('.')[0].upper()
        if '/' in stock_name:
            stock_name = stock_name.split('/')[-1]
        plt.plot(targets, label='Actual')
        plt.plot(predictions, label='Predicted')
        plt.legend()
        plt.xlabel('Samples')
        plt.ylabel('Scaled Price')
        plt.title(f'Price Prediction {stock_name}: D={decoder_steps}, Epoch={epochs}', fontsize=14)
        print(f'Saving image to: plots/Test_{stock_name}D{decoder_steps}_E{epochs}.png')
        plt.savefig(f'plots/Test_{stock_name}_D{decoder_steps}_E{epochs}.png')
        if show:
            plt.show()
        else:
            plt.close()

    def plotMSE(self, errors, decoder_steps, num_samples=1, name='', show=True):
        epoch_counts = [i/num_samples for i in range(len(errors))]
        plt.plot(epoch_counts, errors)
        plt.xlabel('Epochs')
        plt.ylabel('MSE')
        plt.title(f'MSE {name}: D={decoder_steps}', fontsize=14)
        print(f'Saving image to: plots/{name}D{decoder_steps}_E{epoch_counts[-1]}.png')
        plt.savefig(f'plots/{name}_D{decoder_steps}_E{epoch_counts[-1]}.png')
        if show:
            plt.show()
        else:
            plt.close()