#  Author:   Niels Nuyttens  <niels@nannyml.com>
#
#  License: Apache Software License 2.0

"""Calculates drift for individual columns.

Supported drift detection methods are:

- Kolmogorov-Smirnov statistic (continuous)
- Wasserstein distance (continuous)
- Chi-squared statistic (categorical)
- L-infinity distance (categorical)
- Jensen-Shannon distance
- Hellinger distance

For more information, check out the `tutorial`_ or the `deep dive`_.

For help selecting the correct univariate drift detection method for your use case, check the `method selection guide`_.

.. _tutorial:
    https://nannyml.readthedocs.io/en/stable/tutorials/detecting_data_drift/univariate_drift_detection.html

.. _deep dive:
    https://nannyml.readthedocs.io/en/stable/how_it_works/univariate_drift_detection.html

.. _method selection guide:
    https://nannyml.readthedocs.io/en/stable/how_it_works/univariate_drift_comparison.html
"""

from __future__ import annotations

import warnings
from typing import Any, Dict, List, Optional, Union

import pandas as pd
from pandas import MultiIndex

from nannyml.base import AbstractCalculator, _list_missing, _split_features_by_type
from nannyml.chunk import Chunker
from nannyml.drift.univariate.methods import FeatureType, Method, MethodFactory
from nannyml.drift.univariate.result import Result
from nannyml.exceptions import InvalidArgumentsException
from nannyml.thresholds import ConstantThreshold, StandardDeviationThreshold, Threshold
from nannyml.usage_logging import UsageEvent, log_usage

DEFAULT_THRESHOLDS: Dict[str, Threshold] = {
    'kolmogorov_smirnov': StandardDeviationThreshold(std_lower_multiplier=None),
    'chi2': StandardDeviationThreshold(),  # currently ignored
    'jensen_shannon': ConstantThreshold(lower=None, upper=0.1),
    'wasserstein': StandardDeviationThreshold(std_lower_multiplier=None),
    'hellinger': ConstantThreshold(lower=None, upper=0.1),
    'l_infinity': ConstantThreshold(lower=None, upper=0.1),
}

class UnivariateDriftCalculator(AbstractCalculator):
    """Calculates drift for individual features."""

    def __init__(
        self,
        column_names: Union[str, List[str]],
        treat_as_categorical: Optional[Union[str, List[str]]] = None,
        timestamp_column_name: Optional[str] = None,
        categorical_methods: Optional[Union[str, List[str]]] = None,
        continuous_methods: Optional[Union[str, List[str]]] = None,
        chunk_size: Optional[int] = None,
        chunk_number: Optional[int] = None,
        chunk_period: Optional[str] = None,
        chunker: Optional[Chunker] = None,
        thresholds: Optional[Dict[str, Threshold]] = None,
        computation_params: Optional[dict[str, Any]] = None,
    ):
        """Creates a new UnivariateDriftCalculator instance.

        Parameters
        ----------
        column_names: Union[str, List[str]]
            A string or list containing the names of features in the provided data set.
            A drift score will be calculated for each entry in this list.
        treat_as_categorical: Union[str, List[str]]
            A single column name or list of column names to be treated as categorical by the calculator.
        timestamp_column_name: str
            The name of the column containing the timestamp of the model prediction.
        categorical_methods: Union[str, List[str]], default=['jensen_shannon']
            A method name or list of method names that will be performed on categorical columns.
            Supported methods for categorical variables:

                - `jensen_shannon`
                - `chi2`
                - `hellinger`
                - `l_infinity`
        continuous_methods: Union[str, List[str]], default=['jensen_shannon']
            A method name list of method names that will be performed on continuous columns.
            Supported methods for continuous variables:

                - `jensen_shannon`
                - `kolmogorov_smirnov`
                - `hellinger`
                - `wasserstein`
        chunk_size: int
            Splits the data into chunks containing `chunks_size` observations.
            Only one of `chunk_size`, `chunk_number` or `chunk_period` should be given.
        chunk_number: int
            Splits the data into `chunk_number` pieces.
            Only one of `chunk_size`, `chunk_number` or `chunk_period` should be given.
        chunk_period: str
            Splits the data according to the given period.
            Only one of `chunk_size`, `chunk_number` or `chunk_period` should be given.
        chunker : Chunker
            The `Chunker` used to split the data sets into a lists of chunks.
        thresholds: dict

            Defaults to::

                {
                    'kolmogorov_smirnov': StandardDeviationThreshold(std_lower_multiplier=None),
                    'jensen_shannon': ConstantThreshold(upper=0.1),
                    'wasserstein': StandardDeviationThreshold(std_lower_multiplier=None),
                    'hellinger': ConstantThreshold(upper=0.1),
                    'l_infinity': ConstantThreshold(upper=0.1)
                }

            A dictionary allowing users to set a custom threshold for each method. It links a `Threshold` subclass
            to a method name. This dictionary is optional.
            When a dictionary is given its values will override the default values. If no dictionary is given a default
            will be applied. The default method thresholds are as follows:

                - `kolmogorov_smirnov`: `StandardDeviationThreshold(std_lower_multiplier=None)`
                - `jensen_shannon`: `ConstantThreshold(upper=0.1)`
                - `wasserstein`: `StandardDeviationThreshold(std_lower_multiplier=None)`
                - `hellinger`: `ConstantThreshold(upper=0.1)`
                - `l_infinity`: `ConstantThreshold(upper=0.1)`

            The `chi2` method does not support custom thresholds for now. Additional research is required to determine
            how to transition from its current p-value based implementation.

        computation_params : dict

            Defaults to::

                {
                    'kolmogorov_smirnov': {
                        'calculation_method': 'auto',
                        'n_bins':10 000
                    },
                    'wasserstein': {
                        'calculation_method': 'auto',
                        'n_bins':10 000
                    }
                }

            A dictionary which allows users to specify whether they want drift calculated on
            the exact reference data or an estimated distribution of the reference data obtained
            using binning techniques. Applicable only to Kolmogorov-Smirnov and Wasserstein.

            `calculation_method`: Specify whether the entire or the binned reference data will be stored.

                The default value is `auto`.

                - `auto` : Use `exact` for reference data smaller than 10 000 rows, `estimated` for larger.
                - `exact` : Store the whole reference data.

                    When calculating on chunk `scipy.stats.ks_2samp(reference, chunk,  method = `exact` )`
                    is called and whole reference and chunk vectors are passed.
                - `estimated` : Store reference data binned into `n_bins` (default=10 000).

                    The D-statistic will be calculated based on binned eCDF.
                    Bins are quantile-based for Kolmogorov-Smirnov and equal-width based for Wasserstein.
                    Notice that for the reference data of 10 000 rows the resulting D-statistic for exact and
                    estimated methods should be the same. The pvalue in that method is calculated using asymptotic
                    distribution of test statistic (as it is in the `scipy.stats.ks_2samp` with method = `asymp` ).

            `n_bins` : Number of bins used to bin data when calculation_method = `estimated`.

                The default value is 10 000. The larger the value the more precise the calculation
                (closer to  calculation_method = `exact` ) but more data will be stored in the fitted calculator.

        Examples
        --------
        >>> import nannyml as nml
        >>> reference, analysis, _ = nml.load_synthetic_car_price_dataset()
        >>> column_names = [col for col in reference.columns if col not in ['timestamp', 'y_pred', 'y_true']]
        >>> calc = nml.UnivariateDriftCalculator(
        ...   column_names=column_names,
        ...   timestamp_column_name='timestamp',
        ...   continuous_methods=['kolmogorov_smirnov', 'jensen_shannon', 'wasserstein'],
        ...   categorical_methods=['chi2', 'jensen_shannon', 'l_infinity'],
        ... ).fit(reference)
        >>> res = calc.calculate(analysis)
        >>> res = res.filter(period='analysis')
        >>> for column_name in res.continuous_column_names:
        ...  for method in res.continuous_method_names:
        ...    res.plot(kind='drift', column_name=column_name, method=method).show()
        """
        super(UnivariateDriftCalculator, self).__init__(
            chunk_size,
            chunk_number,
            chunk_period,
            chunker,
            timestamp_column_name,
        )
        if isinstance(column_names, str):
            column_names = [column_names]
        self.column_names = column_names

        if not treat_as_categorical:
            treat_as_categorical = []
        if isinstance(treat_as_categorical, str):
            treat_as_categorical = [treat_as_categorical]
        self.treat_as_categorical = treat_as_categorical

        if not continuous_methods:
            continuous_methods = ['jensen_shannon']
        elif isinstance(continuous_methods, str):
            continuous_methods = [continuous_methods]
        self.continuous_method_names = continuous_methods

        if not categorical_methods:
            categorical_methods = ['jensen_shannon']
        elif isinstance(categorical_methods, str):
            categorical_methods = [categorical_methods]
        self.categorical_method_names: List[str] = categorical_methods

        self.computation_params: Optional[Dict[str, Any]] = computation_params

        # Setting thresholds: update default values with custom values if given
        self.thresholds = DEFAULT_THRESHOLDS
        if thresholds is not None:
            if 'chi2' in thresholds:
                msg = "ignoring custom threshold for 'chi2' as it does not support custom thresholds for now."
                self._logger.warning(msg)
                warnings.warn(msg)

                # thresholds.pop('chi2')  # chi2 has no custom threshold support for now
            self.thresholds.update(**thresholds)

        # set to default values within the method function in methods.py

        self._column_to_models_mapping: Dict[str, List[Method]] = {column_name: [] for column_name in column_names}

        # required for distribution plots
        self.previous_reference_results: Optional[pd.DataFrame] = None
        self.previous_analysis_data: Optional[pd.DataFrame] = None

        self.result: Optional[Result] = None

    @log_usage(
        UsageEvent.UNIVAR_DRIFT_CALC_FIT, metadata_from_self=['continuous_method_names', 'categorical_method_names']
    )
    def _fit(self, reference_data: pd.DataFrame, *args, **kwargs) -> UnivariateDriftCalculator:
        """Fits the drift calculator using a set of reference data."""
        if reference_data.empty:
            raise InvalidArgumentsException('data contains no rows. Please provide a valid data set.')

        _list_missing(self.column_names, reference_data)

        self.continuous_column_names, self.categorical_column_names = _split_features_by_type(
            reference_data, self.column_names
        )

        for column_name in self.treat_as_categorical:
            if column_name not in self.column_names:
                self._logger.info(
                    f"ignoring 'treat_as_categorical' value '{column_name}' because it was not in "
                    f"listed column names"
                )
                break
            if column_name in self.continuous_column_names:
                self.continuous_column_names.remove(column_name)
            if column_name not in self.categorical_column_names:
                self.categorical_column_names.append(column_name)

        for column_name in self.continuous_column_names:
            self._column_to_models_mapping[column_name] += [
                MethodFactory.create(
                    key=method,
                    feature_type=FeatureType.CONTINUOUS,
                    chunker=self.chunker,
                    computation_params=self.computation_params or {},
                    threshold=self.thresholds[method],
                ).fit(
                    reference_data=reference_data[column_name],
                    timestamps=reference_data[self.timestamp_column_name] if self.timestamp_column_name else None,
                )
                for method in self.continuous_method_names
            ]

        for column_name in self.categorical_column_names:
            self._column_to_models_mapping[column_name] += [
                MethodFactory.create(
                    key=method,
                    feature_type=FeatureType.CATEGORICAL,
                    chunker=self.chunker,
                    threshold=self.thresholds[method],
                ).fit(
                    reference_data=reference_data[column_name],
                    timestamps=reference_data[self.timestamp_column_name] if self.timestamp_column_name else None,
                )
                for method in self.categorical_method_names
            ]

        self.result = self._calculate(reference_data)
        self.result.data['chunk', 'chunk', 'period'] = 'reference'
        self.result.reference_data = reference_data.copy()

        return self

    @log_usage(
        UsageEvent.UNIVAR_DRIFT_CALC_RUN, metadata_from_self=['continuous_method_names', 'categorical_method_names']
    )
    def _calculate(self, data: pd.DataFrame, *args, **kwargs) -> Result:
        """Calculates methods for both categorical and continuous columns."""
        if data.empty:
            raise InvalidArgumentsException('data contains no rows. Please provide a valid data set.')

        _list_missing(self.column_names, data)

        chunks = self.chunker.split(data)

        rows = []
        for chunk in chunks:
            row = {
                'key': chunk.key,
                'chunk_index': chunk.chunk_index,
                'start_index': chunk.start_index,
                'end_index': chunk.end_index,
                'start_datetime': chunk.start_datetime,
                'end_datetime': chunk.end_datetime,
                'period': 'analysis',
            }

            for column_name in self.continuous_column_names:
                for method in self._column_to_models_mapping[column_name]:
                    for k, v in _calculate_for_column(chunk.data, column_name, method).items():
                        row[f'{column_name}_{method.column_name}_{k}'] = v

            for column_name in self.categorical_column_names:
                for method in self._column_to_models_mapping[column_name]:
                    for k, v in _calculate_for_column(chunk.data, column_name, method).items():
                        row[f'{column_name}_{method.column_name}_{k}'] = v

            rows.append(row)

        result_index = _create_multilevel_index(
            continuous_column_names=self.continuous_column_names,
            continuous_method_names=[m for m in self.continuous_method_names],
            categorical_column_names=self.categorical_column_names,
            categorical_method_names=[m for m in self.categorical_method_names],
        )
        res = pd.DataFrame(rows)
        res.columns = result_index
        res = res.reset_index(drop=True)

        if self.result is None:
            self.result = Result(
                results_data=res,
                column_names=self.column_names,
                continuous_column_names=self.continuous_column_names,
                categorical_column_names=self.categorical_column_names,
                continuous_method_names=self.continuous_method_names,
                categorical_method_names=self.categorical_method_names,
                timestamp_column_name=self.timestamp_column_name,
                chunker=self.chunker,
            )
        else:
            # TODO: review subclassing setup => superclass + '_filter' is screwing up typing.
            #       Dropping the intermediate '_filter' and directly returning the correct 'Result' class works OK
            #       but this causes us to lose the "common behavior" in the top level 'filter' method when overriding.
            #       Applicable here but to many of the base classes as well (e.g. fitting and calculating)
            self.result = self.result.filter(period='reference')
            self.result.data = pd.concat([self.result.data, res]).reset_index(drop=True)
            self.result.analysis_data = data.copy()

        return self.result

def _calculate_for_column(data: pd.DataFrame, column_name: str, method: Method) -> Dict[str, Any]:
    result = {}
    value = method.calculate(data[column_name])
    result['value'] = value
    result['upper_threshold'] = method.upper_threshold_value
    result['lower_threshold'] = method.lower_threshold_value
    result['alert'] = method.alert(value)
    return result

def _create_multilevel_index(
    continuous_column_names: List[str],
    categorical_column_names: List[str],
    continuous_method_names: List[str],
    categorical_method_names: List[str],
):
    chunk_column_names = ['key', 'chunk_index', 'start_index', 'end_index', 'start_date', 'end_date', 'period']
    method_column_names = ['value', 'upper_threshold', 'lower_threshold', 'alert']
    chunk_tuples = [('chunk', 'chunk', chunk_column_name) for chunk_column_name in chunk_column_names]
    continuous_column_tuples = [
        (column_name, method_name, method_column_name)
        for column_name in continuous_column_names
        for method_name in continuous_method_names
        for method_column_name in method_column_names
    ]

    categorical_column_tuples = [
        (column_name, method_name, method_column_name)
        for column_name in categorical_column_names
        for method_name in categorical_method_names
        for method_column_name in method_column_names
    ]

    tuples = chunk_tuples + continuous_column_tuples + categorical_column_tuples

    return MultiIndex.from_tuples(tuples)


import scrapy

class ImdbSpider(scrapy.Spider):

    name = 'rottent_data'

    custom_settings = {
        "DOWNLOAD_DELAY": 1,
        "CONCURRENT_REQUESTS_PER_DOMAIN": 3,
        "HTTPCACHE_ENABLED": True
    }
    #title_names = ['the_lord_of_the_rings_the_fellowship_of_the_ring','kate_and_leopold','glitter']

    title_names = open('/Users/Adam/Metis/notebooks/data/rottentitles.ls','r').read().strip().split(',')
    start_urls = ['https://www.rottentomatoes.com/m/'+i+'/' for i in title_names]

    def parse(self, response):

        tmall = response.xpath('//*[@id="tomato_meter_link"]/span[2]/span/text()').extract()[0]
        tmallave = response.xpath('//*[@id="scoreStats"]/div[1]/text()[2]').extract()[0]

        tmtop = response.xpath('//*[@id="tomato_meter_link"]/span[2]/span/text()').extract()[1]
        tmtopave = response.xpath('//*[@id="scoreStats"]/div[1]/text()[2]').extract()[1]

        audiencescore = response.xpath('//*[@id="scorePanel"]/div[2]/div[1]/a/div/div[2]/div[1]/span/text()').extract()

        ratingRT = response.xpath('//*[@id="mainColumn"]/section[2]/div/div/ul/li[1]/div[2]/text()').extract()

        boxofficeRT = response.xpath('//*[@id="mainColumn"]/section[2]/div/div/ul/li[7]/div[2]/text()').extract()

        runtimeRT = response.xpath('//*[@id="mainColumn"]/section[2]/div/div/ul/li[8]/div[2]/time/text()').extract()

        url = response.url

        yield {
            'url': url,
            'tmall': tmall,
            'tmallave': tmallave,
            'tmtop': tmtop,
            'tmtopave': tmtopave,
            'audiencescore': audiencescore,
            'ratingRT': ratingRT,
            'boxofficeRT': boxofficeRT,
            'runtimeRT': runtimeRT,
        }


# -*- coding: utf-8 -*-

# импортирование модулей python
from tkinter import *

# класс главного окна
class main:

  count = 0

  def __init__(self, master):
    self.master = master
    self.master.title('parent')
    self.master.geometry('300x250+300+225')
    self.button = Button(self.master,
                         text = 'myButton',
                         command = self.open_child_win, font="Arial 20")
    self.button.pack(side = BOTTOM)

    # =============== class mixin ==============

    self.button2_transp = Button(self.master,
                         text = '<<< меньше прозрачность',
                         command = self.transparent_less,
                         fg = 'red',
                         bg = 'yellow',
                         font="Arial 16")
    self.button2_transp.pack(side = TOP)

    self.button3_transp = Button(self.master,
                         text = 'больше прозрачность >>>',
                         command = self.transparent_more,
                         fg = 'red',
                         bg = 'yellow',
                         font="Arial 16")
    self.button3_transp.pack(side = TOP)

    #root.wm_attributes('-alpha',0,3)
    self.master.mainloop()

  # =============== class mixin ==============
  d = 1.0
  def transparent_less(self):

    #root.wm_attributes('-alpha',0,3)
    if self.d <= 0.5:
       self.button2_transp.configure(text = '<<< дальше некуда!!!')

    else:
       if self.d > 0.6:
          self.button2_transp.configure(text = '<<< меньше призрачности')
       #self.button3_transp.configure(text = 'больше призрачности >>>')
       self.d = self.d - 0.1

    self.master.wm_attributes('-alpha',self.d)
    #w.attributes('-alpha', 0.1)
    print('self.d = ', self.d)

  def transparent_more(self):

    # self.button3_transp.configure(text = 'больше призрачности >>>')

    if self.d >= 1.0:
       self.button3_transp.configure(text = 'дальше некуда!!! >>>')

    else:
       if self.d < 0.8:
          self.button3_transp.configure(text = 'больше призрачности >>>')
       self.d = self.d + 0.1

    self.master.wm_attributes('-alpha',self.d)
    #w.attributes('-alpha', 0.1)
    print('self.d = ', self.d)

  def open_child_win(self):
    #self.count += self.count + 1
    self.count += 1
    child.counter = self.count
    ##print("child.counter = ", child.counter)
    child(self.master)

# класс дочерних окон

class child:

  def __init__(self, master):

    self.slave = Toplevel(master)
    self.slave.title('child')

    #self.counter += self.counter + 1

    self.label = Label(self.slave, text = ('Окно N '+str(self.counter)), font="Arial 18")
    #self.label = Label(self.slave, text = 'Привет, мир')
    #self.label.pack(padx = 0, pady = 0)
    self.label.pack(side = TOP)

    geometry1 = str(random.randrange(0,100))
    geometry2 = str(random.randrange(400,700))
    geometry11 = str(random.randrange(0,100))
    geometry22 = str(random.randrange(400,700))

    g1 = random.choice([geometry1,geometry2])
    g2 = random.choice([geometry11,geometry22])

    # geometry0 = '+'+geometry1+'+'+geometry2
    geometry0 = '+'+g1+'+'+g2
    geo = '200x150'+geometry0

    #self.slave.geometry('200x150+500+375')
    self.slave.geometry(geo)

    bgcolor = random.choice(colors)
    self.slave.configure(bg=bgcolor)
    #self.slave.configure(bg='green')
    #root.configure(bg='green')

import random
colors = ['red','yellow', 'green', 'orange',
          'aqua', 'blue', 'fuchsia', 'maroon',
          'pink', 'purple', 'lime',
          'violet', 'cyan', 'cornflowerblue',
          'indigo', 'chartreuse'
         ]

# bgcolor = random.choice(colors)

# создание окна
root = Tk()

# запуск окна
main(root)


# -*- coding: utf-8 -*-
"""
Created on Wed Jun 20 18:46:40 2018

@author: Deniz Timartas
"""
#This is a scatter graph named as warmth graph. This shows the density of sales and also their selling price
#according to each of the 3 year span's days. The reason we dont use scatter here is that scatter graphs only
#accepts integer values. And we also have datetime values in our case.

#These are the modules we will be using. The 'as' here means that we will use the module in the code with an acronym.
import os
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import rcParams
rcParams.update({'figure.autolayout':True,
                 'axes.titlepad':20})

#We have our data set in csv format, we show this csv's adress to a variable.
CSV_PATH = os.path.join('..','Projects','proj','transactions2.csv')

#Then we read thatdata set into a pandas dataframe variable called df. parse_dates function here forms our frame's
#date data in datetime format.
df = pd.read_csv(CSV_PATH, parse_dates=[11,10])

#We have 41 different type so we will use a cycle in range 41.
for i in range(41):

    #We will first hold a specific type_id's data in a dataframe variable.
    df1 = df[df['type_id']==i+1]

    #We also have some returns in out data set. These corrupt the outcome in many ways so we will get rid of them by
    #Just having the rows of purchase_prices that are over 1.
    df1=df1[df1['purchase_price']>1]

    #Now we will define our figure to show and save.
    #There are many interface options here that are useful, you can look them up from python
    #handbooks but I will try to cover some of them here. Here we define matplotlib figure as fig variable.
    #We will later use that to show and save the figure. In .plot function we define default x and y axis values
    #and then rot will rotate the labels so they are not on each other. There are also x and y labels as well
    #as the title over the graph. The trick here is to define the style like in scatter graph. Which is a dot.
    #And then we use alpha value to make it a little opaque over a value range of 0-1. An Voila, we got a very valuable
    #and easy to mine data to use.
    fig = plt.figure()
    subplot = fig.add_subplot(1, 1, 1)
    df1.plot(x='date', y='selling_price',ax=subplot, rot=45, style='.', grid=True, alpha=0.15)
    subplot.set_xlabel('Dates')
    subplot.set_ylabel('Selling Prices')
    subplot.locator_params(nbins=40, axis='x')
    subplot.set_title('Warmth Graph of Selling Prices by Time')
    #If you add fig.show() here, you will be overwhelmed by 41 different graphs opened as tabs.
    fig.savefig('Warmth_Graph_Dates_Selling' + str(i+1) + '.jpeg')


from rest_framework import serializers
from posting.models import Feed, Feed_image, Comment, Comment_image
from account.models import account
import os, uuid
from django.conf import settings
class FeedImageSerializer(serializers.ModelSerializer):

    image = serializers.ImageField(use_url=False)

    class Meta:
        model = Feed_image
        fields = ['image']

class FeedSerializer(serializers.ModelSerializer):

    images = FeedImageSerializer(many=True, read_only=True)
    user_id = serializers.IntegerField(write_only=True)

    class Meta:
        model = Feed
        fields = ['feed_id', 'title', 'context', 'created_date', 'updated_date', 'status', 'longitude', 'latitude','images','user_id']

    def create(self, validated_data):
        # 이미지들을 context의 request.FILES에서 가져옵니다.
        image_set = self.context['request'].FILES.getlist("FILES")
        image_data = []
        user_id = self.context['request'].data['user_id']

        for image in image_set:
            # 이미지 파일 이름을 고유하게 만듦
            unique_filename = f"{uuid.uuid4().hex}{os.path.splitext(image.name)[1]}"

            # 이미지 파일을 MEDIA_ROOT에 저장
            file_path = os.path.join(settings.MEDIA_ROOT, "posting",unique_filename)
            with open(file_path, 'wb+') as destination:
                for chunk in image.chunks():
                    destination.write(chunk)

            # 이미지 파일의 URL을 image_data에 추가
            image_data.append({'image': os.path.join(settings.MEDIA_URL,"posting", unique_filename)})

        # User 인스턴스 가져오기
        user = account.objects.get(pk=user_id)  # user_id를 이용하여 User 인스턴스 가져오기

        # Feed 객체를 생성하고 저장합니다.
        feed = Feed.objects.create(
            title=self.data.get('title'),
            context=self.data.get('context'),
            status=True,
            longitude=self.data.get('longitude'),
            latitude=self.data.get('latitude'),
            user=user,
        )

        # 이미지들을 Feed_image 모델에 저장합니다.
        for image in image_data:
            Feed_image.objects.create(feed=feed, image=image["image"])

        return feed

    def update(self, instance, validated_data):
        # User 인스턴스 가져오기
        user_id = self.context['request'].data['user_id']  # 'user_id' 키의 값을 빼고 따로 저장
        user = account.objects.get(pk=user_id)  # user_id를 이용하여 User 인스턴스 가져오기

        # Feed 객체를 업데이트합니다.
        instance.title = self.data.get('title')
        instance.context = self.data.get('context')
        instance.status=True
        instance.longitude = self.data.get('longitude')
        instance.latitude = self.data.get('latitude')
        instance.user = user
        instance.save()

        # 기존 이미지 url 삭제 후, 업데이트(재생성)
        Feed_image.objects.filter(feed_id=instance.feed_id).delete()
        image_set = self.context['request'].FILES.getlist("FILES")
        image_data = []

        for image in image_set:
            # 이미지 파일 이름을 고유하게 만듦
            unique_filename = f"{uuid.uuid4().hex}{os.path.splitext(image.name)[1]}"

            # 이미지 파일을 MEDIA_ROOT에 저장
            file_path = os.path.join(settings.MEDIA_ROOT, "posting",unique_filename)
            with open(file_path, 'wb+') as destination:
                for chunk in image.chunks():
                    destination.write(chunk)

            # 이미지 파일의 URL을 image_data에 추가
            image_data.append({'image': os.path.join(settings.MEDIA_URL,"posting", unique_filename)})

        for image in image_data:
            Feed_image.objects.create(feed=instance, image=image["image"])

            updated_feed = Feed.objects.get(pk=instance.feed_id)

        return updated_feed


from mpi4py import MPI
import time
import RPi.GPIO as GPIO
import random as rand

# Initialize parallel process
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
name = MPI.Get_processor_name()

# Initialize Pin (const)
LED = {'r' : 18, 'g' : 16, 'b' : 12}

# Initialize GPIO
GPIO.setmode(GPIO.BOARD)
for i in LED:
	GPIO.setup(LED[i], GPIO.OUT, initial=1)

print("{0} \t rank - {1} \t size - {2}".format(name, rank, size))

# Generated Array size
LEN = 40
MAX = 10**10

# Start mode
GPIO.output(LED['r'], 0)
time.sleep(1)

# Main functions

# array  --  Unsorted array of data
# range_ --  Range of array, have start and end
def ScatterData(array, range_):
	if rank == 0:
		print('Generated random array:\n{0}\n'.format(array))

		step = len(range_) // size
		index = iter(range(range_.start, range_.stop, step))

		# Don't start from range_.start
		next(index)
		pivot = [next(index) for i in range(size - 1)]

		# Show divided range
		print("Divided range -- {0} \n".format(pivot))

		# Add MAX value for add data into last list in data
		pivot.append(MAX)

		# Divide array
		data = [[] for i in range(size)]

		for i in array:
			for j in range(len(pivot)):
				if i < pivot[j]:
					data[j].append(i)
					break
	else:
		data = None

	return comm.scatter(data, root=0)

def GatherData(data):
	data = comm.gather(data, root=0)

	if rank == 0:
		result = []
		for i in data:
			result.extend(i)

		print('Sorted array :\t', result)
		time.sleep(2)

def showColor(color):
	def showRGB(index):
		for i in LED:
			GPIO.output(LED[i], 1)
		GPIO.output(LED[index], 0)

	# Set color with time division in ms
	timeScale = {i : color[i] / 255  for i in color}
	pause = 0.001

	for  k in color.keys():
		if color[k]:
			showRGB(k)
		time.sleep(pause)

	#print(timeScale)

# Source:	https://en.wikipedia.org/wiki/Quicksort

def QuickSort(array, lo, hi):
	def partition(array, lo, hi):
		pivot = array[hi]
		i = lo

		for j in range(lo, hi):
			if array[j] < pivot:
				array[i], array[j] = array[j], array[i]
				i += 1

		array[i], array[hi] = array[hi], array[i]
		return i

	if lo < hi:
		p = partition(array, lo, hi)
		QuickSort(array, lo, p - 1)
		QuickSort(array, p + 1, hi)

		# Sorting visualization
		start = time.time()

		while time.time() - start < 1:
			showColor({'r' : 250, 'g' : 0,  'b' : 250})

# Program operations

data = ScatterData([rand.randrange(-LEN, LEN) for i in range(LEN)], range(-LEN, LEN))
print('{0} \t get \t {1}'.format(name, data))

QuickSort(data, 0, len(data) - 1)
print('{0} \t sorted array \t {1}'.format(name, data))

# Sorting Complete
showColor({'r' : 0, 'g' : 200, 'b' : 0})
time.sleep(1)

# Show final result
GatherData(data)

# Wait for end progrogram
comm.bcast("End program", root=0)

# Reset all used GPIO
GPIO.cleanup()


from puzzle import Puzzle

class MNPuzzle(Puzzle):
    """
    An nxm puzzle, like the 15-puzzle, which may be solved, unsolved,
    or even unsolvable.
    """

    def __init__(self, from_grid, to_grid):
        """
        MNPuzzle in state from_grid, working towards
        state to_grid

        @param MNPuzzle self: this MNPuzzle
        @param tuple[tuple[str]] from_grid: current configuration
        @param tuple[tuple[str]] to_grid: solution configuration
        @rtype: None
        """
        # represent grid symbols with letters or numerals
        # represent the empty space with a "*"
        assert len(from_grid) > 0
        assert all([len(r) == len(from_grid[0]) for r in from_grid])
        assert all([len(r) == len(to_grid[0]) for r in to_grid])
        self.n, self.m = len(from_grid), len(from_grid[0])
        self.from_grid, self.to_grid = from_grid, to_grid

    def __eq__(self, other):
        """
        Return whether MNPuzzle self is equivalent to other.

        @type self: MNPuzzle
        @type other: MNPuzzle | Any
        @rtype: bool

        >>> mn1 = MNPuzzle(("1", "2", "3"), ("4", "5", "*"))
        >>> mn2 = MNPuzzle(("1", "2", "3"), ("4", "5", "*"))
        >>> mn3 = MNPuzzle(("1", "*", "3"), ("4", "5", "6"))
        >>> mn1 == mn2
        True
        >>> mn1 == mn3
        False
        """
        return (type(self) == type(other) and
                self.n == other.n and self.m == other.m and
                self.from_grid == other.from_grid and
                self.to_grid == other.to_grid)

    def __str__(self):
        """
        Return a user-friendly string representation.

        @type self: MNPuzzle
        @rtype: str

        >>> target_grid = (("1", "2", "3"), ("4", "5", "*"))
        >>> start_grid = (("*", "2", "3"), ("1", "4", "5"))
        >>> mn = MNPuzzle(target_grid, start_grid)
        >>> print(mn)
        ===Current Stage===
        ('1', '2', '3')
        ('4', '5', '*')
        ====Goal Board=====
        ('*', '2', '3')
        ('1', '4', '5')
        """
        def align_column(grid):
            board = ""
            for i in range(self.n):
                board += str(grid[i]) + "\n"
            return board.strip()
        return ("===Current Stage===\n"
                "{}\n"
                "====Goal Board=====\n"
                "{}".format(align_column(self.from_grid),
                            align_column(self.to_grid)))

    def extensions(self):
        """
        Return list of extensions of MNPuzzle self.

        @type self: MNPuzzle
        @rtype: list[MNPuzzle]

        >>> target_grid = (("1", "*", "3"), ("4", "5", "6"), ("7", "8", "9"))
        >>> start_grid = (("*", "2", "3"), ("1", "4", "5"), ("7", "8", "9"))
        >>> mn = MNPuzzle(target_grid, start_grid)
        >>> lst = mn.extensions()
        >>> for ext in lst:
        ...    print(ext)
        ===Current Stage===
        ('*', '1', '3')
        ('4', '5', '6')
        ('7', '8', '9')
        ====Goal Board=====
        ('*', '2', '3')
        ('1', '4', '5')
        ('7', '8', '9')
        ===Current Stage===
        ('1', '3', '*')
        ('4', '5', '6')
        ('7', '8', '9')
        ====Goal Board=====
        ('*', '2', '3')
        ('1', '4', '5')
        ('7', '8', '9')
        ===Current Stage===
        ('1', '5', '3')
        ('4', '*', '6')
        ('7', '8', '9')
        ====Goal Board=====
        ('*', '2', '3')
        ('1', '4', '5')
        ('7', '8', '9')
        """
        def check_empty_space(gridcopy):
            """
            Return the place of the empty space.

            @type gridcopy: tuple[tuple[str]]
            @rtype: tuple

            # >>> grid = (("*", "2", "3"), ("4", "5", "6"))
            # >>> check_empty_space(grid)
            # (0, 0)
            # >>> grid = (("1", "2", "3"), ("4", "5", "6"), ("7" , "8" , "*"))
            # >>> check_empty_space(grid)
            # (2, 2)
            """
            for i in range(len(gridcopy)):
                if "*" in gridcopy[i]:
                    return i, gridcopy[i].index("*")
            # Raise Error if there is no empty space in the puzzle.
            return AssertionError, "No empty space in the puzzle."

        def tuple_to_list(tup):
            """
            Return a list which was originally tuple.

            @type tup: tuple
            @rtype: list[str]
            """
            return [element for element in tup]

        def shift_right_left(gridcopy, row_num, column_num):
            """
            Return the list of affected grid. If * cannot move to the specific
            place, it returns an empty list

            @type gridcopy: tuple[tuple[str]]
            @type row_num: int
            @type column_num: int
            @rtype: list[tuple[tuple[str]]]
            """
            result = []
            # Extract the specific row to change.
            current_row = gridcopy[row_num]
            # Change the current_row to list in order to mutate.
            current_row_lst = tuple_to_list(current_row)
            if location[1] != 0:
                # Going left!
                # ("5", "*", "6") to ("*", "5", "6")
                current_row_lst[column_num] = current_row_lst[column_num - 1]
                current_row_lst[column_num - 1] = "*"
                # Switch back to tuple
                left_altered = tuple(current_row_lst)
                board_lst = tuple_to_list(gridcopy)
                board_lst[row_num] = left_altered
                result.append(tuple(board_lst))
            if location[1] != self.m - 1:
                # Going right!
                # ("5", "*", "6") to ("5", "6", "*")
                # Reset the values to swap right.
                current_row = gridcopy[row_num]
                current_row_lst = tuple_to_list(current_row)
                current_row_lst[column_num] = current_row_lst[column_num + 1]
                current_row_lst[column_num + 1] = "*"
                # Switch back to tuple
                right_altered = tuple(current_row_lst)
                board_lst = tuple_to_list(gridcopy)
                board_lst[row_num] = right_altered
                result.append(tuple(board_lst))
            return result

        def shift_down_right(gridcopy, row_num, column_num):
            """
            Return the list of affected grid. If * cannot move to the specific
            place, it returns an empty list

            @type gridcopy: tuple[tuple[str]]
            @type row_num: int
            @type column_num: int
            @rtype: list[tuple[tuple[str]]]
            """
            result = []
            if location[0] != 0:
                current_row = gridcopy[location[0]]
                upper_row = gridcopy[location[0] - 1]
                current_row_lst = tuple_to_list(current_row)
                upper_row_lst = tuple_to_list(upper_row)
                current_row_lst[column_num] = upper_row_lst[column_num]
                upper_row_lst[column_num] = "*"
                current_row, upper_row = tuple(current_row_lst), \
                                         tuple(upper_row_lst)
                board_lst = tuple_to_list(gridcopy)
                board_lst[row_num] = current_row
                board_lst[row_num - 1] = upper_row
                upper_altered = tuple(board_lst)
                result.append(upper_altered)
            if location[0] != self.n - 1:
                upper_row = gridcopy[location[0] + 1]
                lower_row = gridcopy[location[0]]
                upper_lst = tuple_to_list(upper_row)
                lower_lst = tuple_to_list(lower_row)
                lower_lst[location[1]] = upper_lst[location[1]]
                upper_lst[location[1]] = "*"
                upper_row, lower_row = tuple(upper_lst), tuple(lower_lst)
                big_lst = tuple_to_list(gridcopy)
                big_lst[location[0]] = lower_row
                big_lst[location[0] + 1] = upper_row
                changed = tuple(big_lst)
                result.append(changed)
            return result

        grid = self.from_grid
        # Location is the tuple indicator of location of the empty space.
        # (Row, Column)
        location = check_empty_space(grid)
        row = location[0]
        column = location[1]
        possibilities = shift_right_left(grid, row, column) +\
                        shift_down_right(grid, row, column)
        return [MNPuzzle(x, self.to_grid) for x in possibilities]

    # TODO
    # override is_solved
    # a configuration is solved when from_grid is the same as to_grid
    def is_solved(self):
        """
        Return whether Puzzle self is solved.

        @type self: WordLadderPuzzle
        @rtype: bool

        >>> target_grid = (("1", "2", "3"), ("4", "5", "*"))
        >>> start_grid = (("*", "2", "3"), ("1", "4", "5"))
        >>> mn = MNPuzzle(target_grid, start_grid)
        >>> mn.is_solved()
        False
        >>> current_grid = (("1", "2", "3"), ("4", "5", "*"))
        >>> mn = MNPuzzle(target_grid, current_grid)
        >>> mn.is_solved()
        True
        """
        return self.from_grid == self.to_grid

# def check_empty_space(grid):
#     """
#     Return the place of the empty space.
#
#     @type grid: tuple[tuple[str]]
#     @rtype: tuple
#
#     >>> grid = (("*", "2", "3"), ("4", "5", "6"))
#     >>> check_empty_space(grid)
#     (0, 0)
#     >>> grid = (("1", "2", "3"), ("4", "5", "6"), ("7" , "8" , "*"))
#     >>> check_empty_space(grid)
#     (2, 2)
#     """
#     for i in range(len(grid)):
#         if "*" in grid[i]:
#             return i, grid[i].index("*")

if __name__ == "__main__":
    import doctest
    doctest.testmod()
    target_grid = (("1", "2", "3"), ("4", "5", "*"))
    start_grid = (("*", "2", "3"), ("1", "4", "5"))
    from puzzle_tools import breadth_first_solve, depth_first_solve
    from time import time
    start = time()
    solution = breadth_first_solve(MNPuzzle(start_grid, target_grid))
    end = time()
    print("BFS solved: \n\n{} \n\nin {} seconds".format(
        solution, end - start))
    start = time()
    solution = depth_first_solve((MNPuzzle(start_grid, target_grid)))
    end = time()
    print("DFS solved: \n\n{} \n\nin {} seconds".format(
        solution, end - start))


#Run on QGIS Python Console

#Same as 'Layer Properties > Rendering > Scale Depent Visibility
#Souce Layer
fn = "C:/Path/of/your/shapefile.shp"

#Add the layer to canvas
iface.addVectorLayer(fn, '', 'ogr')

#make a new variale
layer = iface.activeLayer()

#Set scale of the layer
layer.setScaleBasedVisibility(True)
layer.setMaximumScale(0)
layer.setMinimumScale(30001)


from flask import Flask
from flask import jsonify, make_response

app = Flask(__name__)

@app.route('/')
def hello_world():
    message = {
        'note': 'test cronjob * * * * *',
    }
    value = {

        'full_name': "Yulyano Thomas Djaya",
        'nick_name': "Lino",
        'last_education': "Gunadarma University",
        'location': "Bogor",
        'last edit': "First day: Intern"
    }
    res = {
        'msg': message,
        'value': value
    }
    return make_response(jsonify(res)), 200

@app.route('/hello/<name>')
def hello_name(name):
    return 'Hello %s!' % name

if __name__ == '__main__':
    app.run()


t=int(input())

nums=[int(x) for x in input().split(" ")]

for i in range(t-1,0,-1):
    if(nums[i]<nums[i-1]):
        after=nums[i:]
        c=nums[i]
        for j in after:
            if(nums[i-1]>j and c<j):
                c=j
        after.remove(c)
        after.append(nums[i-1])
        after.sort(reverse=True)

        for p in range(0,i-1):
            print(nums[p], end=" ")
        print(c,end=" ")
        for t in after:
            print(t,end=" ")
        exit()
print(-1)


from tkinter import *
import tkinter.messagebox as tmsg
# import pandas as pd
import openpyxl
# from openpyxl import workbook
# import pathlib

#Logic and geometry definition
root = Tk()
root.geometry("980x580")
root.minsize(800, 550)
root.title("WFM Assistance Tool - by Ranjeet Varma (@EngiNearStrange)")

#Defining button functions
def rosterfunc():
    print("This will switch to Roster request window")

def masterfunc():
    print("This will switch to Master data edit window")

fbkvalue = ''
new_window = ''
def feedbackfunc():
    global fbkvalue
    global new_window
    new_window = Toplevel(root)
    new_window.geometry("400x250")
    new_window.title("Feedback")
    fbk = Label(new_window, text = "Please type your feedback in the box below", padx = 10, pady = 20)
    fbk.grid(row = 0, column = 0)
    fbkvalue = StringVar()
    fbkentry = Entry(new_window, textvariable = fbkvalue, width = 40)
    fbkentry.grid(row = 1, column = 0, padx = 10, pady = 10)
    Button(new_window, text = "Submit Feedback", bg = "blue", fg = "white", command = submitfeedback).grid(row = 2, column = 0, padx = 1, pady = 15)
    Button(new_window, text = "Clear", bg = "blue", fg = "white", padx = 4, command = lambda: fbkentry.delete("0", "end")).grid(row = 1, column = 1, padx = 5, pady = 15)
    Button(new_window, text = "Cancel", bg = "blue", fg = "white", command = lambda: new_window.destroy()).grid(row = 2, column = 1, padx = 5, pady = 15)

def submitfeedback():
    print("Submitting Feedback")
    with open("Feedback.txt", "a") as fbk:
        fbk.write("\n" + fbkvalue.get())
    print(f"The feedback was {fbkvalue.get()} and has been submitted")
    tmsg.showinfo("Feedback submitted", "Your feedback has been recorded, Thank You!!")
    new_window.destroy()

def aboutfunc():
    tmsg.showinfo("About","Developed for Accenture Services Pvt. Ltd. by \nRanjeet Varma - @EngiNearStrange")

def retdatafunc():
    print("This will retrieve existing alignment data from server")

def updatafunc():
    # data1 = [{"Sap ID": empidvalue.get(), "SME": smevalue.get(), "SME EID": smeeidvalue.get(),
    #           "Supervisor": supvalue.get(), "Sup Enterprise ID": supeidvalue.get(), "Shift Lead": slvalue.get(),
    #           "Shift Lead EID": sleidvalue.get(), "Ops Lead": olvalue.get(), "Ops Lead EID": oleidvalue.get()}]
    # df1 = pd.DataFrame(data1)
    # df1.to_excel('new1.csv', "a", index = False)
    # data1 = [{}]
    # print(df1)
    a = empidvalue.get()
    b = smevalue.get()
    c = smeeidvalue.get()
    d = supvalue.get()
    e = supeidvalue.get()
    f = slvalue.get()
    g = sleidvalue.get()
    h = olvalue.get()
    i = oleidvalue.get()

    file = openpyxl.load_workbook("Master1.xlsx")
    sheet = file.active
    sheet.cell(column = 1, row = sheet.max_row+1, value = a)
    sheet.cell(column = 2, row = sheet.max_row, value = b)
    sheet.cell(column = 3, row = sheet.max_row, value = c)
    sheet.cell(column = 4, row = sheet.max_row, value = d)
    sheet.cell(column = 5, row = sheet.max_row, value = e)
    sheet.cell(column = 6, row = sheet.max_row, value = f)
    sheet.cell(column = 7, row = sheet.max_row, value = g)
    sheet.cell(column = 8, row = sheet.max_row, value = h)
    sheet.cell(column = 9, row = sheet.max_row, value = i)
    file.save("Master1.xlsx")

#Defining frame 1
f1 = Frame(root, bg = "gray", borderwidth = 5, relief = SUNKEN)
f1.pack(side = LEFT, fill = Y)

#Defining labels & buttons in frame 1

acclogo = PhotoImage(file = "Accenture_logo_small.png")
Label(f1, image = acclogo).pack(side = TOP, pady = 2)

# selections = Label(f1, text = "Select from following options")
# selections.pack(pady = 5)

b1 = Button(f1, bg = "#0A7392", fg = "white", text = "Roster", font = ("Monotype Corsiva", 14),
            borderwidth = 5, relief = SUNKEN, padx = 31, command = rosterfunc)
b1.pack(pady = 35)

b2 = Button(f1, bg = "#0A7392", fg = "white", text = "Master Tracker", font = ("Monotype Corsiva", 14),
            borderwidth = 5, relief = SUNKEN, command = masterfunc)
b2.pack(pady = 35)

b3 = Button(f1, bg = "#0A7392", fg = "white", text = "Feedback", font = ("Monotype Corsiva", 14),
            borderwidth = 5, relief = SUNKEN, padx = 22, command = feedbackfunc)
b3.pack(pady = 35)

b4 = Button(f1, bg = "#0A7392", fg = "white", text = "About", font = ("Monotype Corsiva", 14),
            borderwidth = 5, relief = SUNKEN, padx = 32, command = aboutfunc)
b4.pack(pady = 35)

#Defining Frame 2
f2 = Frame(root, borderwidth = 15, relief = SUNKEN, bg = "green")
f2.pack(side = TOP, pady = 10)

#Defining labels in Frame 2
wlcmmsg = Label(f2, text = "Welcome to WFM Assistance Tool", fg = "black",
                font = ("Times New Roman", 24, "italic"))
wlcmmsg.pack(fill = X)

#Defining Frame 3
f3 = Frame(root, borderwidth = 5, relief = SUNKEN, pady = 25)
f3.pack(pady = 10, fill = X)

#Defining labels in Frame 3
empid = Label(f3, text = "Input employee ID", font = ("Times New Roman", 12), pady = 5, padx = 25)
entid = Label(f3, text = "Input enterprise ID", font = ("Times New Roman", 12), pady = 5, padx = 25)
empid.grid(row = 0, column = 1)
entid.grid(row = 1, column = 1)

#Defining data type for label values in Frame 3 and assigning them to entry box
empidvalue = IntVar()
entidvalue = StringVar()
empidentry = Entry(f3, textvariable = empidvalue)
entidentry = Entry(f3, textvariable = entidvalue)
empidentry.grid(row = 0, column = 2)
entidentry.grid(row = 1, column = 2)

#Defining Frame 4
f4 = Frame(root, borderwidth = 5, relief = SUNKEN)
f4.pack(anchor = "n", side = LEFT, fill = X, pady = 5, padx = 2)

#Defining labels & buttons inside Frame 4
Label(f4, text = "Current alignment", fg = "blue", font = ("Times New Roman", 14, "bold"), padx = 70, pady = 10).grid(row = 0, column = 3)
sme = Label(f4, text = "SME", font = ("Times New Roman", 10))
smeeid = Label(f4, text = "SME EID", font = ("Times New Roman", 10))
sup = Label(f4, text = "Supervisor", font = ("Times New Roman", 10))
supeid = Label(f4, text = "Supervisor EID", font = ("Times New Roman", 10))
sl = Label(f4, text = "Shift Lead", font = ("Times New Roman", 10))
sleid = Label(f4, text = "Shift Lead EID", font = ("Times New Roman", 10))
ol = Label(f4, text = "Ops Lead", font = ("Times New Roman", 10))
oleid = Label(f4, text = "Ops Lead EID", font = ("Times New Roman", 10))
Button(f4, text = "Retrieve data", fg = "white", bg = "#0A7392", padx = 5, pady = 5, command = retdatafunc).grid(row = 9, column = 2, padx = 10, pady = 25)
sme.grid(row = 1, column = 2)
smeeid.grid(row = 2, column = 2)
sup.grid(row = 3, column = 2)
supeid.grid(row = 4, column = 2)
sl.grid(row = 5, column = 2)
sleid.grid(row = 6, column = 2)
ol.grid(row = 7, column = 2)
oleid.grid(row = 8, column = 2)

#Defining data type for label values in Frame 4 and associating them to entry box
smevalue = StringVar()
smeeidvalue = IntVar()
supvalue = StringVar()
supeidvalue = IntVar()
slvalue = StringVar()
sleidvalue = IntVar()
olvalue = StringVar()
oleidvalue = IntVar()

smeentry = Entry(f4, textvariable = smevalue)
smeeidentry = Entry(f4, textvariable = smeeidvalue)
supentry = Entry(f4, textvariable = supvalue)
supeidentry = Entry(f4, textvariable = supeidvalue)
slentry = Entry(f4, textvariable = slvalue)
sleidentry = Entry(f4, textvariable = sleidvalue)
olentry = Entry(f4, textvariable = olvalue)
oleidentry = Entry(f4, textvariable = oleidvalue)

smeentry.grid(row = 1, column = 3)
smeeidentry.grid(row = 2, column = 3)
supentry.grid(row = 3, column = 3)
supeidentry.grid(row = 4, column = 3)
slentry.grid(row = 5, column = 3)
sleidentry.grid(row = 6, column = 3)
olentry.grid(row = 7, column = 3)
oleidentry.grid(row = 8, column = 3)

#Defining Frame 5
f5 = Frame(root, borderwidth = 5, relief = SUNKEN, padx = 10)
f5.pack(anchor = "n", side = RIGHT, fill = X, pady = 5, padx = 2)

#Defining labels & buttons inside Frame 5
Label(f5, text = "Request alignment change", fg = "blue", font = ("Times New Roman", 14, "bold"), padx = 30, pady = 10).grid(row = 0, column = 3)
sme = Label(f5, text = "SME", font = ("Times New Roman", 10))
smeeid = Label(f5, text = "SME EID", font = ("Times New Roman", 10))
sup = Label(f5, text = "Supervisor", font = ("Times New Roman", 10))
supeid = Label(f5, text = "Supervisor EID", font = ("Times New Roman", 10))
sl = Label(f5, text = "Shift Lead", font = ("Times New Roman", 10))
sleid = Label(f5, text = "Shift Lead EID", font = ("Times New Roman", 10))
ol = Label(f5, text = "Ops Lead", font = ("Times New Roman", 10))
oleid = Label(f5, text = "Ops Lead EID", font = ("Times New Roman", 10))
Button(f5, text = "Update data", fg = "white", bg = "#0A7392", padx = 5, pady = 5, command = updatafunc).grid(row = 9, column = 2, pady = 25)
sme.grid(row = 1, column = 2)
smeeid.grid(row = 2, column = 2)
sup.grid(row = 3, column = 2)
supeid.grid(row = 4, column = 2)
sl.grid(row = 5, column = 2)
sleid.grid(row = 6, column = 2)
ol.grid(row = 7, column = 2)
oleid.grid(row = 8, column = 2)

#Defining data type for label values in Frame 5 and associating them to entry box
smevalue = StringVar()
smeeidvalue = IntVar()
supvalue = StringVar()
supeidvalue = IntVar()
slvalue = StringVar()
sleidvalue = IntVar()
olvalue = StringVar()
oleidvalue = IntVar()

smeentry = Entry(f5, textvariable = smevalue)
smeeidentry = Entry(f5, textvariable = smeeidvalue)
supentry = Entry(f5, textvariable = supvalue)
supeidentry = Entry(f5, textvariable = supeidvalue)
slentry = Entry(f5, textvariable = slvalue)
sleidentry = Entry(f5, textvariable = sleidvalue)
olentry = Entry(f5, textvariable = olvalue)
oleidentry = Entry(f5, textvariable = oleidvalue)

smeentry.grid(row = 1, column = 3)
smeeidentry.grid(row = 2, column = 3)
supentry.grid(row = 3, column = 3)
supeidentry.grid(row = 4, column = 3)
slentry.grid(row = 5, column = 3)
sleidentry.grid(row = 6, column = 3)
olentry.grid(row = 7, column = 3)
oleidentry.grid(row = 8, column = 3)

# data1 = [{"Sap ID" : empidvalue.get(), "SME" : smevalue.get(), "SME EID" : smeeidvalue.get(),
#          "Supervisor" : supvalue.get(), "Sup Enterprise ID" : supeidvalue.get(), "Shift Lead" : slvalue.get(),
#          "Shift Lead EID" : sleidvalue.get(),"Ops Lead" : olvalue.get(), "Ops Lead EID" : oleidvalue.get()}]
# df1 = pd.DataFrame(data1)

#Creating an event loop
root.mainloop()


from activities.models import Post, PostInteraction
from activities.services import TimelineService
from api import schemas
from api.decorators import identity_required
from api.pagination import MastodonPaginator
from api.views.base import api_router

@api_router.get("/v1/timelines/home", response=list[schemas.Status])
@identity_required
def home(
    request,
    max_id: str | None = None,
    since_id: str | None = None,
    min_id: str | None = None,
    limit: int = 20,
):
    paginator = MastodonPaginator(Post)
    queryset = TimelineService(request.identity).home()
    events = paginator.paginate(
        queryset,
        min_id=min_id,
        max_id=max_id,
        since_id=since_id,
        limit=limit,
    )
    interactions = PostInteraction.get_event_interactions(events, request.identity)
    return [
        event.subject_post.to_mastodon_json(interactions=interactions)
        for event in events
    ]

@api_router.get("/v1/timelines/public", response=list[schemas.Status])
@identity_required
def public(
    request,
    local: bool = False,
    remote: bool = False,
    only_media: bool = False,
    max_id: str | None = None,
    since_id: str | None = None,
    min_id: str | None = None,
    limit: int = 20,
):
    if local:
        queryset = TimelineService(request.identity).local()
    else:
        queryset = TimelineService(request.identity).federated()
    if remote:
        queryset = queryset.filter(local=False)
    if only_media:
        queryset = queryset.filter(attachments__id__isnull=True)
    paginator = MastodonPaginator(Post)
    posts = paginator.paginate(
        queryset,
        min_id=min_id,
        max_id=max_id,
        since_id=since_id,
        limit=limit,
    )
    interactions = PostInteraction.get_post_interactions(posts, request.identity)
    return [post.to_mastodon_json(interactions=interactions) for post in posts]

@api_router.get("/v1/timelines/tag/{hashtag}", response=list[schemas.Status])
@identity_required
def hashtag(
    request,
    hashtag: str,
    local: bool = False,
    only_media: bool = False,
    max_id: str | None = None,
    since_id: str | None = None,
    min_id: str | None = None,
    limit: int = 20,
):
    if limit > 40:
        limit = 40
    queryset = TimelineService(request.identity).hashtag(hashtag)
    if local:
        queryset = queryset.filter(local=True)
    if only_media:
        queryset = queryset.filter(attachments__id__isnull=True)
    paginator = MastodonPaginator(Post)
    posts = paginator.paginate(
        queryset,
        min_id=min_id,
        max_id=max_id,
        since_id=since_id,
        limit=limit,
    )
    interactions = PostInteraction.get_post_interactions(posts, request.identity)
    return [post.to_mastodon_json(interactions=interactions) for post in posts]

@api_router.get("/v1/conversations", response=list[schemas.Status])
@identity_required
def conversations(
    request,
    max_id: str | None = None,
    since_id: str | None = None,
    min_id: str | None = None,
    limit: int = 20,
):
    # We don't implement this yet
    return []


"""empty message

Revision ID: 3d541ec31bb1
Revises: None
Create Date: 2015-10-07 11:40:52.366584

"""

# revision identifiers, used by Alembic.
revision = '3d541ec31bb1'
down_revision = None

from alembic import op
import sqlalchemy as sa

def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.create_table('assignment',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=64), nullable=False),
    sa.Column('room', sa.String(length=120), nullable=False),
    sa.Column('week', sa.String(length=64), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_assignment_name'), 'assignment', ['name'], unique=False)
    op.create_index(op.f('ix_assignment_room'), 'assignment', ['room'], unique=False)
    op.create_index(op.f('ix_assignment_week'), 'assignment', ['week'], unique=False)
    ### end Alembic commands ###

def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_assignment_week'), table_name='assignment')
    op.drop_index(op.f('ix_assignment_room'), table_name='assignment')
    op.drop_index(op.f('ix_assignment_name'), table_name='assignment')
    op.drop_table('assignment')
    ### end Alembic commands ###


import os
import glob
import json
import argparse

from invoicenet import FIELDS
from invoicenet.acp.acp import AttendCopyParse

def main():
    ap = argparse.ArgumentParser()

    ap.add_argument("--field", nargs='+', type=str, required=True, choices=FIELDS.keys(),
                    help="field to train parser for")
    ap.add_argument("--invoice", type=str, default=None,
                    help="path to directory containing prepared data")
    ap.add_argument("--data_dir", type=str, default='test_data/',
                    help="path to directory containing prepared data")
    ap.add_argument("--pred_dir", type=str, default='predictions/',
                    help="path to directory containing prepared data")

    args = ap.parse_args()

    paths = []
    fields = []
    predictions = {}

    if args.invoice:
        if not os.path.exists(args.invoice):
            print("Could not find file '{}'".format(args.invoice))
            return
        paths.append(args.invoice)
    else:
        paths = [os.path.abspath(f) for f in glob.glob(args.data_dir + "**/*.pdf", recursive=True)]

    if not os.path.exists('./models/invoicenet/'):
        print("Could not find any trained models!")
        return
    else:
        models = os.listdir('./models/invoicenet/')
        for field in args.field:
            if field in models:
                fields.append(field)
            else:
                print("Could not find a trained model for field '{}', skipping...".format(field))

    for field in fields:
        print("\nExtracting field '{}' from {} invoices...\n".format(field, len(paths)))
        model = AttendCopyParse(field=field, restore=True)
        predictions[field] = model.predict(paths=paths)

    os.makedirs(args.pred_dir, exist_ok=True)
    for idx, filename in enumerate(paths):
        filename = os.path.basename(filename)[:-3] + 'json'
        labels = {}
        if os.path.exists(os.path.join(args.pred_dir, filename)):
            with open(os.path.join(args.pred_dir, filename), 'r') as fp:
                labels = json.load(fp)
        with open(os.path.join(args.pred_dir, filename), 'w') as fp:
            print("\nFilename: {}".format(filename))
            for field in predictions.keys():
                labels[field] = predictions[field][idx]
                print("  {}: {}".format(field, labels[field]))
            fp.write(json.dumps(labels, indent=2))
            print('\n')

    print("Predictions stored in '{}'".format(args.pred_dir))

if __name__ == '__main__':
    main()


import re
import tkinter
import tkinter.messagebox

import requests

class CovidGUI:
    def __init__(self):
        self.main_window = tkinter.Tk()
        self.main_window.title('Information about people infected with the COVID in Poland')
        self.top_frame = tkinter.Frame(self.main_window)
        self.mid_frame = tkinter.Frame(self.main_window)
        self.bottom_frame = tkinter.Frame(self.main_window)
        self.current_data = 0
        self.saved_data = 0

        self.top_frame.pack()
        self.mid_frame.pack()
        self.bottom_frame.pack()

        self.get_www_button = tkinter.Button(self.top_frame, text='Get data(www)', command=self.show_data_from_www,
                                             relief=tkinter.GROOVE, borderwidth=5)
        self.get_www_button.pack(side='left')

        self.www_info_label = tkinter.Label(self.top_frame,
                                            text='From the website "Poland Coronavirus" infected are : ')
        self.www_info_label.pack(side='left')

        self.scraped_data = tkinter.StringVar()
        self.www_scraped_data_label = tkinter.Label(self.top_frame, textvariable=self.scraped_data)
        self.www_scraped_data_label.pack(side='left')

        self.www_info_label2 = tkinter.Label(self.top_frame, text=' people')
        self.www_info_label2.pack(side='left')

        self.get_file_button = tkinter.Button(self.mid_frame, text='Get data(file)', command=self.show_data_from_file,
                                              relief=tkinter.GROOVE, borderwidth=5)
        self.get_file_button.pack(side='left')

        self.file_info_label = tkinter.Label(self.mid_frame,
                                             text='Last data from file, infected are: ')
        self.file_info_label.pack(side='left')

        self.read_data_from_file = tkinter.StringVar()
        self.read_data_file_label = tkinter.Label(self.mid_frame, textvariable=self.read_data_from_file)
        self.read_data_file_label.pack(side='left')

        self.file_info_label2 = tkinter.Label(self.mid_frame, text=' people')
        self.file_info_label2.pack(side='left')

        self.save_file_button = tkinter.Button(self.bottom_frame, text='Save data(www) to file',
                                               command=self.save_data_to_file, relief=tkinter.GROOVE, borderwidth=5)
        self.save_file_button.pack(side='left')

        self.quit_button = tkinter.Button(self.bottom_frame, text='Quit', command=self.main_window.destroy,
                                          relief=tkinter.GROOVE, borderwidth=5)
        self.quit_button.pack(side='left')

        tkinter.mainloop()

    def get_data_from_www(self):
        page = requests.get('https://www.worldometers.info/coronavirus/country/poland/')
        pattern = r'Poland Coronavirus: (\d,{0,1}\d{0,})'
        obj = re.search(pattern, page.text)
        return obj.group(1)

    def show_data_from_www(self):
        self.scraped_data.set(self.get_data_from_www())

    def get_data_from_file(self):
        with open('data.txt', 'r') as f:
            self.saved_data = f.readline()
        return self.saved_data

    def show_data_from_file(self):
        self.read_data_from_file.set(self.get_data_from_file())

    def save_data_to_file(self):
        self.current_data = self.get_data_from_www()
        self.saved_data = self.get_data_from_file()
        if self.saved_data != self.current_data:
            with open('data.txt', 'w') as f:
                f.write(self.current_data)
        else:
            tkinter.messagebox.showinfo('Information', 'No new infected')

if __name__ == '__main__':
    my_covid_gui = CovidGUI()


# filename: average.py
# -*- coding: utf-8 -*-

import pandas as pd

def average():
    r1 = pd.read_csv('temp/rf_result_875.csv')
    r2 = pd.read_csv('temp/rf_result_875(1).csv')
    r3 = pd.read_csv('temp/rf_result_617.csv')
    r4 = pd.read_csv('temp/rf_result_282.csv')
    r5 = pd.read_csv('temp/rf_result_352.csv')
    r6 = pd.read_csv('temp/gbdt_result_351.csv')
    r7 = pd.read_csv('temp/xgb_result_722.csv')

    prob_matrix = pd.DataFrame()
    prob_matrix['r1'] = r1['rank']
    prob_matrix['r2'] = r2['rank']
    prob_matrix['r3'] = r3['rank']
    prob_matrix['r4'] = r4['rank']
    prob_matrix['r5'] = r5['rank']
    prob_matrix['r6'] = r6['rank']
    prob_matrix['r7'] = r7['rank']

    #corr = prob_matrix.corr(method='pearson')
    avg_prob = prob_matrix.mean(axis=1)
    data = pd.read_csv('rawdata/ccf_offline_stage1_test_sorted.csv')
    data['prob'] = avg_prob
    result_data = data[['User_id','Coupon_id','Date_received','prob']]
    result_data.to_csv('result/average_rank.csv', index=False)

def rank():

    data = pd.read_csv('temp/rf_result_875_0.80055397.csv')
    rank = data['prob'].rank(method='first')
    max_rank = rank.max()
    normalised_rank = rank.apply(lambda x: x/max_rank)
    data['rank'] = normalised_rank
    result_data = data[['User_id','Coupon_id','Date_received','rank']]
    result_data.to_csv('temp/rf_result_875(1).csv', index=False)

if __name__ == '__main__':

    average()
    #rank()


from rest_framework import serializers

from dice.artists.models import Artist

class ArtistSerializer(serializers.ModelSerializer):
    class Meta:
        model = Artist
        fields = [
            "name",
            "image_url",
            "embedding",
        ]

        extra_kwargs = {
            "url": {"view_name": "api:artist-detail", "lookup_field": "id"}
        }


import cv2
import numpy as np
import matplotlib.pyplot as mpl

#ALGO:
#1 IF IT'S UNPAINTED = PAINT IT
#2 IF IT'S PAINTED = PAINT THE NEXT UNPAINTED PIXEL
#  AND CLEAR ALL PIXELS ON THE LEFT TO IT

Widght, Height = 200, 200

Img = np.zeros( (Widght, Height, 3), np.uint8 )
#Widght, Height = Widght-1, Height-1 #because the counting starts from 0
Img[:,:] = (255,255,255)

#print(Img[10,10])

Cpixx = 0 #current pixel coordinate x (stands for Current PIXel X)
Cpixy = 0 #current pixel coordinate y
Black = False #if all pixels are black?
WhitePixel = np.array([255,255,255])

while Black == False:
    while Cpixx < Widght:
        while Cpixy < Height:
            #step 1 and 2
            if np.array_equal(Img[Cpixx, Cpixy], WhitePixel) == True:
                Img[Cpixx, Cpixy] = (0,0,0)
                #clearing
                for Cpixy in range(Cpixy - 1, -1, -1):
                    for Cpixx in range(Cpixx, -1, -1):
                        Img[Cpixx, Cpixy] = (255,255,255)
            elif Cpixy < Height - 1:
                Cpixy = Cpixy + 1
            else:
                Cpixy = 0
                Cpixx = Cpixx +1
                #check fullness
                if Cpixx == Widght:
                    Black = True
                    Cpixy = Height
            #output
            cv2.imshow('image', Img)
            cv2.waitKey(1)

    #cv2.imshow('image', Img)
    #cv2.waitKey(0)


import cv2
import numpy as np

img = cv2.imread('standard_test_images/BasicShapes.jpg')
imgo = img.copy()
imgGrey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

_, thrash = cv2.threshold(imgGrey, 240, 255, cv2.THRESH_BINARY)

contours, _ =  cv2.findContours(thrash, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

for contour in contours:
    approx = cv2.approxPolyDP(contour, 0.01* cv2.arcLength(contour, True), True)
    # Epsilon 0.01 is accuracy, cv2.arcL.. calculates curve length (contour param., and true is for closed contur, in both cases here.
    cv2.drawContours(img, [approx], 0, (0,255,255), 5) # We take 1 contour at a time so, 0.
    x = approx.ravel()[0] + 5
    y = approx.ravel()[1] - 9
    if len(approx) == 3:
        cv2.putText(img, "Triangle", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,100,255))
    elif len(approx) == 4:
        x1, y1, w, h = cv2.boundingRect(approx)
        aspectRatio = float(w)/h
        print(aspectRatio)
        if aspectRatio >= 0.95 and aspectRatio <= 1.05:  # Ideally it is 1 but for noise, we have these
            cv2.putText(img, "Square", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (150,99,250))
        else:
            cv2.putText(img, "Rectangle", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,0,255))
    elif len(approx) == 5:
        cv2.putText(img, "Pentagon", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,0,255))
    elif len(approx) == 10:
        cv2.putText(img, "Star", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,0,255))
    else:
        cv2.putText(img, "Circle", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255,0,255))

cv2.imshow("original", imgo)
cv2.imshow("Processed", img)
#cv2.imshow("originalGrey", imgGrey)
cv2.waitKey(0)
cv2.destroyAllWindows()


#!/usr/bin/python
# -*- coding: utf-8 -*-
"""Tests for the spotlight plist plugin."""

import unittest

# pylint: disable=unused-import
from plaso.formatters import plist as plist_formatter
from plaso.parsers import plist
from plaso.parsers.plist_plugins import spotlight

from tests.parsers.plist_plugins import test_lib

class SpotlightPluginTest(test_lib.PlistPluginTestCase):
  """Tests for the spotlight plist plugin."""

  def setUp(self):
    """Makes preparations before running an individual test."""
    self._plugin = spotlight.SpotlightPlugin()
    self._parser = plist.PlistParser()

  def testProcess(self):
    """Tests the Process function."""
    plist_name = u'com.apple.spotlight.plist'
    event_queue_consumer = self._ParsePlistFileWithPlugin(
        self._parser, self._plugin, [plist_name], plist_name)
    event_objects = self._GetEventObjectsFromQueue(event_queue_consumer)

    self.assertEqual(len(event_objects), 9)

    timestamps = []
    for event_object in event_objects:
      timestamps.append(event_object.timestamp)
    expected_timestamps = frozenset([
        1379937262090906, 1387822901900937, 1375236414408299, 1388331212005129,
        1376696381196456, 1386951868185477, 1380942616952359, 1389056477460443,
        1386111811136093])
    self.assertTrue(set(timestamps) == expected_timestamps)

    event_object = event_objects[1]
    self.assertEqual(event_object.key, u'gr')
    self.assertEqual(event_object.root, u'/UserShortcuts')
    expected_desc = (u'Spotlight term searched "gr" associate to '
                     u'Grab (/Applications/Utilities/Grab.app)')
    self.assertEqual(event_object.desc, expected_desc)
    expected_string = u'/UserShortcuts/gr {0:s}'.format(expected_desc)
    expected_short = expected_string[:77] + u'...'
    self._TestGetMessageStrings(
        event_object, expected_string, expected_short)

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


from django.core.management.base import BaseCommand
import csv

from tmap.models import ChargingStation

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        data = csv.DictReader(open("dist/data/ev_pos.csv"))
        for row in data:
            ChargingStation.objects.create(
                name=row['NAME'],
                charger_quantity=row['QUANTITY'],
                charger_type=row['TYPE'],
                address=row['ADDRESS'],
                latitude=row['LATITUDE'],
                longitude=row['LONGITUDE'],
            )


#!/usr/bin/env python3

##!/home/klinbrc/bin/python3
# package_dir_a='/home/klinbrc/.local/lib/python3.2/site-packages'
# sys.path.insert(0, package_dir_a)

import sys
import numpy

ifile=open(sys.argv[1])
domain_ids=[]
for line in ifile:
    domain_ids.append(line.split()[0])
ifile.close()

for id in domain_ids:
    ifile=open('dompdb/'+id)
    atom_lines=ifile.read().split('\n')[:-1]
    ifile.close()

    atom_xyzs=[]
    for line in atom_lines:
        xyz=numpy.array([float(line[30:38]),\
                         float(line[38:46]),\
                         float(line[46:54])])
        atom_xyzs.append(xyz)

    has_brk_res=False;
    domain_size=len(atom_xyzs)
    for i in range(domain_size):
        for j in range(i+1,domain_size):
            if atom_lines[i][21:27] != atom_lines[j][21:27]:
                continue
            dis_ij = numpy.linalg.norm(atom_xyzs[i]-atom_xyzs[j])
            if dis_ij > 11 :
                print(atom_lines[i]+'\n'+atom_lines[j])
                print('distant:','%6.3f' % dis_ij)
                has_brk_res=True

    if has_brk_res:
        print('file:',id,'\n')


from config import Config

import subprocess
import os

class Helper:
    '''
    Contains helper functions for the pipeline
    '''

    def __init__(self):
        self.cfg = Config()

    def read_link_file(self, path):
        '''
        Reads file with the links and returns as array
        '''

        with open(path, 'r') as f:
            links = f.read().split('\n')
        return links

    def get_domains(self, link, directory):
        '''
        For a given link finds all subdomains
        '''

        # find domains with amass and findomain and save them to output
        findomainOut = os.path.join(directory, 'findomain.txt')
        amassOut = os.path.join(directory, 'amass.txt')
        subprocess.check_output(self.cfg.FINDOMAIN(link, findomainOut), shell = True).decode().split('\n')
        subprocess.check_output(self.cfg.AMASS(link, amassOut), shell = True).decode().split('\n')

        # read the output files and choose only unique links from them
        with open(findomainOut, 'r') as f:
            findomainLinks = f.read().split('\n')

        with open(amassOut, 'r') as f:
            amassLinks = f.read().split('\n')

        try:
            subprocess.check_output(f'rm {findomainOut} {amassOut}', shell = True)
        except:
            pass

        links = set(findomainLinks + amassLinks)

        return links


"""
Transliterate in CLI mode
"""
from translators.translator import IndexTranslator, RuleTranslator

if __name__ == '__main__':
    print("""!!!Welcome to Places & People Automate Translator!!!
     /$$$$$$$  /$$$$$$$   /$$$$$$  /$$$$$$$$
    | $$__  $$| $$__  $$ /$$__  $$|__  $$__/
    | $$  \ $$| $$  \ $$| $$  \ $$   | $$
    | $$$$$$$/| $$$$$$$/| $$$$$$$$   | $$
    | $$____/ | $$____/ | $$__  $$   | $$
    | $$      | $$      | $$  | $$   | $$
    | $$      | $$      | $$  | $$   | $$
    |__/      |__/      |__/  |__/   |__/
    """)

    index_translator = IndexTranslator()
    rule_translator = RuleTranslator()
    s_available_codes = ''
    l_available_codes = []
    for k in rule_translator.rules.keys():
        s_available_codes += '\t' + k + '\t' + rule_translator.rules[k]['meta']['language_name'] + '\n'
        l_available_codes.append(k)
    print("""Usage:
    Type names and hit ENTER to get transliterations.
    Use option "-l" to specify language codes. Available codes are:

    {}
    Default is ALL language codes.
    Use Ctrl+C to quit.
    """.format(s_available_codes))

    while True:
        line = input('> ').split('-l')
        words = line[0].rstrip()
        lang_codes = []
        if len(line) == 2:
            lang_codes = line[1].strip().split(' ')
            for c in lang_codes:
                if c not in l_available_codes:
                    print('ERROR: "{}" is not an available language code.'.format(c))
                    exit(-1)
        print('Result:\n===================================================')
        print('From dictionary:')
        d_result = index_translator.search(words)
        print('Keyword\tLanguage\tCategory\tChinese')
        for d_r in d_result['transliterations']:
            print('{}\t{}\t{}\t{}'.format(d_r['keyword'], d_r['language'], d_r['category'], d_r['chinese']))
        print('---------------------------------------------------')
        print('From rule:')
        print('Keyword\tLanguage\tCategory\tChinese')
        r_result = rule_translator.translate(words, lang_codes)
        for d_r in r_result['transliterations']:
            print('{}\t{}\t{}\t{}'.format(d_r['keyword'], d_r['language'], d_r['category'], d_r['chinese']))
        print('===================================================')


from googletrans import Translator
from google.cloud import translate_v2 as translate
import random

sample_text = ['Blood Vial', open('sample_text.txt').read()]
random_languages = ['ru', 'de', 'fr', 'ja', 'zh-cn', 'nl', 'ko', 'no', 'it', 'ar', 'fi']

def translate_text_cloud(text, src, dst):
    translate_client = translate.Client.from_service_account_json('token.json')
    result = translate_client.translate(text, target_language=dst, source_language=src)
    return result['translatedText']

def translate_text_simple(text, src, dst):
    translator = Translator()
    result = translator.translate(text, dst, src=src)
    return result.text

def run_translation(text, n, use_cloud=True):
    src = 'en'
    for i in range(n):
        random.shuffle(random_languages)
        dst = random_languages[i] if random_languages[i] != src else random_languages[1]
        text = translate_text_cloud(text, src, dst) if use_cloud else translate_text_simple(text, src, dst)
        src = dst
    dst = 'en'
    return translate_text_cloud(text, src, dst) if use_cloud else translate_text_simple(text, src, dst)

print(run_translation(sample_text, 11, True))


import numpy as np

def BitDemapper(M, bits_per_row, rows, cols):
    m = []
    start_idx = 0
    for row in range(rows):
        num_bits = bits_per_row[row]
        for col in range(cols):
            end_idx = start_idx + num_bits
            binary_representation = [int(i) for i in format(M[row, col] % (2 ** num_bits), '0{}b'.format(num_bits))]
            m.extend(binary_representation)
            start_idx = end_idx
    return m

def BitMapper(m, bits_per_row, rows, cols):
    M = np.zeros((rows, cols), dtype=int)
    start_idx = 0
    for row in range(rows):
        num_bits = bits_per_row[row]
        for col in range(cols):
            end_idx = start_idx + num_bits
            M[row, col] = int(''.join(map(str, m[start_idx:end_idx])), 2)
            start_idx = end_idx
    return M

def L16Decoding(y):
    G1 = np.array([[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                   [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
                   [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
                   [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
                   [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], dtype=int)

    n = 16
    Dist = np.zeros(32)
    xhat = np.zeros((n, 32), dtype=int)
    for k in range(32):
        d = np.dot(G1.transpose(), np.unpackbits(np.array([k], dtype=np.uint8))[-5:])
        ybar = (y - d) / 2
        vhat = 2 * DnDecoding(ybar) + d
        xhat[:, k] = vhat
        Dist[k] = np.linalg.norm(y - vhat)
    v_final = xhat[:, np.argmin(Dist)]
    return v_final

def E8Decoding(y):
    n = y.shape[0]
    xhat1 = DnDecoding(y)

    xhat2 = DnDecoding(y - 0.5 * np.ones(n)) + 0.5 * np.ones(n)

    if np.linalg.norm(y - xhat1) <= np.linalg.norm(y - xhat2):
        xhat = xhat1
    else:
        xhat = xhat2

    return xhat

def DnDecoding(y):
    f = np.round(y)
    delta = np.abs(y - f)
    k = np.argmax(delta)
    g = f.copy()
    if f[k] <= y[k]:
        g[k] = f[k] + 1
    else:
        g[k] = f[k] - 1
    if np.sum(f) % 2 == 0:
        xhat = f
    else:
        xhat = g
    return xhat

def main():
    E8 = np.eye(8)
    E8[:, 7] = 0.5 * np.ones(8)
    E8[0, 0] = 2
    for i in range(6):
        E8[i, i + 1] = -1

    L16 = np.array([[1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,4],
                    [1,1,1,1,0,2,2,0,2,0,0,2,0,0,0,0],
                    [1,1,1,0,1,2,0,2,0,2,0,0,2,0,0,0],
                    [1,1,1,0,0,2,0,0,0,0,0,0,0,0,0,0],
                    [1,1,0,1,1,0,2,2,0,0,2,0,0,2,0,0],
                    [1,1,0,1,0,0,2,0,0,0,0,0,0,0,0,0],
                    [1,1,0,0,1,0,0,2,0,0,0,0,0,0,0,0],
                    [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                    [1,0,1,1,1,0,0,0,2,2,2,0,0,0,2,0],
                    [1,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0],
                    [1,0,1,0,1,0,0,0,0,2,0,0,0,0,0,0],
                    [1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
                    [1,0,0,1,1,0,0,0,0,0,2,0,0,0,0,0],
                    [1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],
                    [1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],
                    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]])

    npi = 640
    nbar = 8
    sigma = 5.75
    C1 = []
    q = 2 ** 15

    num_monte = int(2e3)
    BER1 = np.zeros(num_monte, dtype=int)
    BER2 = np.zeros(num_monte, dtype=int)
    BER3 = np.zeros(num_monte, dtype=int)

    for monte in range(num_monte):
        # Alice
        A = np.random.randint(0, q, size=(npi, npi))
        S = np.round(sigma * np.random.randn(npi, nbar))
        E = np.round(sigma * np.random.randn(npi, nbar))
        B = np.mod(np.dot(A, S) + E, q)

        # Bob, encryption
        Sp = np.round(sigma * np.random.randn(nbar, npi))
        Ep = np.round(sigma * np.random.randn(nbar, npi))
        Epp = np.round(sigma * np.random.randn(nbar, nbar))

        C1 = np.mod(np.dot(Sp, A) + Ep, q)  # Ciphertext 1
        V = np.mod(np.dot(Sp, B) + Epp, q)  # V matrix

        # Given 128-bit message m
        m = np.random.randint(0, 2, size=128)

        # Z based encoding and decoding
        bits_per_row = [2, 2, 2, 2, 2, 2, 2, 2]
        M = BitMapper(m, bits_per_row, 8, 8)
        C2 = np.mod(V + M * q / 4, q)  # Ciphertext 2

        # Alice again, decryption
        Y = np.mod(C2 - np.dot(C1, S), q)
        Mhat = np.zeros((8, 8), dtype=int)
        for i in range(8):
            for j in range(8):
                if np.abs(Y[i, j] - q / 4) < q / 8:
                    Mhat[i, j] = 1
                elif np.abs(Y[i, j] - q / 2) < q / 8:
                    Mhat[i, j] = 2
                elif np.abs(Y[i, j] - 3 * q / 4) < q / 8:
                    Mhat[i, j] = 3
                else:
                    Mhat[i, j] = 0

        mhat = BitDemapper(Mhat, bits_per_row, 8, 8)
        # Test the difference
        BER1[monte] = np.sum(m != mhat) > 0

        # E8 based encoding and decoding
        bits_per_row = [1, 2, 2, 2, 2, 2, 2, 3]

        M = BitMapper(m, bits_per_row, 8, 8)
        C2 = np.mod(V + (q / 4) * np.dot(E8, M), q)  # Ciphertext 2

        # Alice again, decryption
        Y = np.mod(C2 - np.dot(C1, S), q)
        Ybar = Y / (q / 4)  # Initialization
        Mhat = np.zeros((8, 8), dtype=int)
        for j in range(8):
            xhat = E8Decoding(Ybar[:8, j])
            Mhat[:8, j] = np.round(np.dot(np.linalg.inv(E8), xhat))

        mhat = BitDemapper(Mhat, bits_per_row, 8, 8)
        # Test the difference
        BER2[monte] = np.sum(m != mhat) > 0

        # BW16 based encoding and decoding
        # Given 144-bit message m
        m = np.random.randint(0, 2, size=144)

        bits_per_row = [3] * 5 + [2] * 10 + [1]

        M = BitMapper(m, bits_per_row, 16, 4)

        C2 = np.mod(V + (q / 8) * np.reshape(np.dot(L16, M), (8, 8)), q)  # Ciphertext 2

        # Alice again, decryption
        Y = np.mod(C2 - np.dot(C1, S), q)
        Ybar = np.reshape(Y / (q / 8), (16, 4))  # Initialization
        Mhat = np.zeros((16, 4), dtype=int)
        for j in range(4):
            xhat = L16Decoding(Ybar[:16, j])
            Mhat[:16, j] = np.round(np.dot(np.linalg.inv(L16), xhat))

        mhat = BitDemapper(Mhat, bits_per_row, 16, 4)
        # Test the difference
        BER3[monte] = np.sum(m != mhat) > 0

    Z_BER = np.mean(BER1)
    E8_BER = np.mean(BER2)
    L16_BER = np.mean(BER3)

    print("Z-based BER:", Z_BER)
    print("E8-based BER:", E8_BER)
    print("BW16-based BER:", L16_BER)

if __name__ == "__main__":
    main()