import inviwopy
import numpy as np
from scipy.special import erf
from scipy.optimize import curve_fit

from inviwopy.data import Buffer

# Calculate mean squared error
def errorForFitted(yValues, yValuesFitted):
	return np.sqrt(np.mean((yValues - yValuesFitted)**2))

# Returns the real-valued solution between xMin and xMax for the polynomial given by the coefficients
def solvePolynomial(coefficients, value, xMin, xMax):
	coeffs = coefficients.copy()
	# Last coefficient is the one for x^0
	coeffs[-1] -= value
	roots = np.roots(coeffs)
	# Only take real-valued roots and explude values smaller than xMax and larger than xMin
	return roots.real[(abs(roots.imag)<1e-5) & (roots.real>=xMin) & (roots.real<=xMax)]

def fitPolynomial(xValues,yValues,degree):
	# Fitting the polynomial
	coefficients = np.polyfit(xValues, yValues, degree)
	f = np.poly1d(coefficients)

	# Estimation of pc as the point of max derivative
	coefficients1stDerivative = np.polyder(coefficients, 1)
	coefficients2ndDerivative = np.polyder(coefficients, 2)
	xMin = np.min(xValues)
	xMax = np.max(xValues)
	zeroCrossings = solvePolynomial(coefficients2ndDerivative, 0.0, xMin, xMax)
	if zeroCrossings.size > 0:
		crossingValues = np.polyval(coefficients1stDerivative, zeroCrossings)
		maxIndex = np.argmax(abs(crossingValues))
		pc = zeroCrossings[maxIndex]
		if (abs(np.polyval(coefficients,pc)-(xMax+xMin)/2.0)>0.15*(xMax-xMin)):
			print("Pc's value is quite far from half of the data: |f(pc)-0.5(xMax+xMin)|=%f"%abs(np.polyval(coefficients,pc)-0.5))
		# Check that pc is is not too far of solution for 0.5
		SolOneHalf = solvePolynomial(coefficients, 0.5, xMin, xMax)
		if SolOneHalf.size > 0:
			if (abs(pc-SolOneHalf[0])>0.15*(xMax-xMin)):
				print("Pc is quite far from the x, where f(x)=0.5: |pc-x|=%f"%abs(pc-SolOneHalf[0]))
	else:
		print("Pc could not be estimated.")
		pc = -1

	# Estimation of delta
	SolOneTenth = solvePolynomial(coefficients, 0.1, xMin, xMax)
	SolNineTenth = solvePolynomial(coefficients, 0.9, xMin, xMax)
	if ((SolOneTenth.size > 0) and (SolNineTenth.size>0) and (pc!=-1)) :
		deltaLeft = abs(pc-SolNineTenth[0])
		deltaRight = abs(pc-SolOneTenth[0])
		delta = (deltaLeft+deltaRight)/2.0
	else:
		print("Delta could not be estimated.")
		delta = -1

	# Computation of the error
	yEstimatedValues = f(xValues)
	error = errorForFitted(yValues, yEstimatedValues)
	return f, error, coefficients, pc, delta

def erfAdapted(xValues, pc, delta):
	return (1-erf((xValues-pc)/delta))/2.0

def erfNonAdapted(xValues, pc, delta):
	return (1+erf((xValues-pc)/delta))/2.0

def fitErf(xValues, yValues):
	# Initial guess through fitting polynomical of given degree
	degree = 6
	_, errorPoly, _, pcPoly, deltaPoly = fitPolynomial(xValues,yValues,degree)
	if (pcPoly == -1):
		pcPoly = (np.max(xValues) + np.min(xValues)) / 2
	if (deltaPoly == -1):
		deltaPoly = 0.1
	initialGuess = [pcPoly, deltaPoly]

	# Fit Erf function
	if (curveFitType==1):
		solErf, pcov = curve_fit(erfAdapted, xValues, yValues, p0=initialGuess)
	else:
		solErf, pcov = curve_fit(erfNonAdapted, xValues, yValues, p0=initialGuess)
	pc = solErf[0]
	delta = solErf[1]
	def erfFitted(x):
		return erfAdapted(x, pc, delta)
	f = erfFitted

	# Computation of the error
	yEstimatedValues = f(xValues)
	error = errorForFitted(yValues, yEstimatedValues)

	if (error>errorPoly):
		print("Polynomial fit of degree %i yields lower error than fit to adapted erf: %f"%(degree,errorPoly))
	return f, error, pc, delta

# Processor is exposed as processor
# Input values are in toFitInput and toFitOutput (both buffers)
x = toFitInputBuffer.data
y = toFitOutputBuffer.data
numIterations = 1

multipleIters = processor.multipleIters.value
if (multipleIters):
	iterData = commonPerIterBuffer.data
	iterations = np.unique(iterData)
	print(iterations)
	numIterations = iterations.size
	print(numIterations)
	samplesPerIter = int(x.size / numIterations)
	print(x.size / numIterations)
	x = x.reshape((numIterations,samplesPerIter))
	x = np.unique(x, axis=0)
	print(x)
	if (x.shape[0] != 1):
		x_round = np.unique(x.round(decimals=3), axis=0)
		print(x_round.shape)
		if (x_round.shape[0] != 1):
			print("Different xValues per Iteration provided. Aborting.")
			exit()
		else:
			print("Warning: Different xValues per Iteration provided, but within tolerance.")
		#H = H[0,].reshape((1, H[0,].size))
	# Reshape x and y so that each row contains one iteration
	y = y.reshape((numIterations,samplesPerIter))
else:
	x = x.reshape((1, x.shape[0]))
	y = y.reshape((1, y.shape[0]))
	if (np.unique(x).size != x.size):
		print("X values of curve to be fitted are not unique.")
		exit()

samples = processor.samples.value
xSamples = np.zeros((numIterations, samples))
ySamples = np.zeros((numIterations, samples))

curveFitType = processor.curveFitType.value
### Fitting the curve
# polynomial
if (curveFitType==0):
	degree = processor.degree.value
	errors = np.zeros((numIterations,1))
	pcs = np.zeros((numIterations,1))
	deltas = np.zeros((numIterations,1))
	coefficientsAll = np.zeros((numIterations,degree+1))
	for index in range(0, numIterations):
		yCurr = y[index,]
		f, error, coefficients, pc, delta = fitPolynomial(x[0,],yCurr,degree)
		errors[index] = error
		pcs[index] = pc
		deltas[index] = delta
		coefficientsAll[index,] = coefficients
		# Create samples for that function
		xSamples[index,] = np.linspace(x[0,0], x[0,-1], samples)
		ySamples[index,] = f(xSamples[index,])

	# Fill buffers with those results
	for degreeIndex in range(degree, -1, -1):
		currentCoeffBuffer = globals()["coeffBuffer_%i"%degreeIndex]
		currentCoeffBuffer.size = numIterations
	pcEstimateBuffer.size = numIterations
	deltaEstimateBuffer.size = numIterations
	rmseBuffer.size = numIterations
	if multipleIters:
		commonPerIterParamsBuffer.size = numIterations

	for index in range(0, numIterations):
		for degreeIndex in range(degree, -1, -1):
			currentCoeffBuffer = globals()["coeffBuffer_%i"%degreeIndex]
			currentCoeffBuffer.data[index] = coefficientsAll[index,degree-degreeIndex]
		pcEstimateBuffer.data[index] = pcs[index]
		deltaEstimateBuffer.data[index] = deltas[index]
		rmseBuffer.data[index] = errors[index]
		if multipleIters:
			commonPerIterParamsBuffer.data[index] = iterations[index]

# Adapted erf
else:
	pcBuffer.size = numIterations
	deltaBuffer.size = numIterations
	rmseBuffer.size = numIterations
	if multipleIters:
		commonPerIterParamsBuffer.size = numIterations
	for index in range(0, numIterations):
		yCurr = y[index,]
		f, error, pc, delta = fitErf(x[0,],yCurr)
		pcBuffer.data[index] = pc
		deltaBuffer.data[index] = delta
		rmseBuffer.data[index] = error
		if multipleIters:
			commonPerIterParamsBuffer.data[index] = iterations[index]
		# Create samples for that function
		xSamples[index,] = np.linspace(x[0,0], x[0,-1], samples)
		ySamples[index,] = f(xSamples[index,])

### Update properties
# Set variables based on the (last) fit
processor.estimates.pcEstimate.value = pc
processor.estimates.deltaEstimate.value = delta
processor.estimates.error.value = error

### Update output
# Results for samples are bound to buffers xSamples, ySamples
xSamplesBuffer.size = xSamples.size
ySamplesBuffer.size = ySamples.size
if (multipleIters):
	commonPerIterSamplesBuffer.size = ySamples.size

for iterIndex in range(0, numIterations):
	for sampleIndex in range(samples):
		xSamplesBuffer.data[iterIndex*samples + sampleIndex] = xSamples[iterIndex, sampleIndex]
		ySamplesBuffer.data[iterIndex*samples + sampleIndex] = ySamples[iterIndex, sampleIndex]
		if (multipleIters):
			commonPerIterSamplesBuffer.data[iterIndex*samples + sampleIndex] = iterations[iterIndex]


# @Time : 2022-09-14 21:26
# @Author : Phalange
# @File : 1291. 顺次数.py
# @Software: PyCharm
# C'est la vie,enjoy it! :D
import math
from typing import List
"""
100 100000
123
234
345
456
678
789
1234

"""

class Solution:
    def sequentialDigits(self, low: int, high: int) -> List[int]:
        ans = []
        low_length = int(math.log10(low))+1
        high_length = int(math.log10(high))+1
        init_val = eval("".join([str(i) for i in range(1,low_length+1)]))
        val = init_val
        length = low_length
        while val <= high:
            if val >= low:
                ans.append(val)

            val += eval("1" * length)
            if str(val)[-1] <= str(val)[-2]:
                #说明要进位了
                length +=1
                val = eval(str(init_val) + str(length))
                init_val = val
        return ans

print(Solution().sequentialDigits(100,200000))


import typing as t
from pathlib import Path

from pipelime.sequences import SamplesSequence as SS
from pipelime.stages import StageRemap
from pydantic import BaseModel, Field, PrivateAttr
from rich.progress import track

from rene.utils.stages import ResizeStage

class ReneDataset(BaseModel):
    """
    A class to lazy load the ReNé dataset

    Args:
        input_folder (Path): ReNé parent folder

    Examples:
        >>> rene = ReneDataset(input_folder=Path("/path/to/rene_parent_folder"))
        >>> sample = rene["apple"][12][34]
        >>> image = sample["image"]()
    """

    input_folder: Path = Field(..., description="ReNé parent folder")
    image_max_size: int = Field(1440, description="Resize images to smallest max size")
    thumb_max_size: int = Field(1440, description="Resize thumbs to smallest max size")

    _KEYS_TO_LOAD: t.Sequence = PrivateAttr(
        [
            "apple",
            "plant",
            "fruits",
            # "empty", # Not included
            "lego",
            "tapes",
            "wooden",
            "cheetah",
            "shark",
            "lunch",
            "reflective",
            "flipflop",
            "robotoy",
            "cube",
            "trucks",
            "garden",
            "stegosaurus",
            "dinosaurs",
            "helicopters",
            "savannah",
            "kittens",
        ]
    )
    _TEST_CAMS = [4, 8, 15]
    _TEST_LIGHTS = [2, 21, 34]
    _IM_SZ = (1440, 1080)

    _data: t.MutableMapping[str, t.List[SS]] = PrivateAttr()

    def __getitem__(self, key: str) -> t.List[SS]:
        """
        Implement the __getitem__ method to allow for indexing into the dataset.

        Args:
            key (str): The key to retrieve from the dataset.

        Returns:
            List[SamplesSequence]: The list of lightsets SamplesSequence corresponding to the key.
        """
        return self._data[key]

    def __init__(self, **kwargs) -> None:
        """
        Lazy load the entire dataset.

        Args:
            input_folder (Path): ReNé parent folder.
        """
        super().__init__(**kwargs)

        i_f = self._IM_SZ[0] // self.image_max_size
        t_f = self._IM_SZ[0] // self.thumb_max_size

        rs = ResizeStage(target_size=(self._IM_SZ[0] // i_f, self._IM_SZ[1] // i_f))  # type: ignore
        rs_t = ResizeStage(target_size=(self._IM_SZ[0] // t_f, self._IM_SZ[1] // t_f))  # type: ignore
        remap = StageRemap(remap={"image": "thumb"}, remove_missing=True)

        # Loop over the subfolders of the input folder
        scenes = [x for x in list(sorted(self.input_folder.iterdir())) if x.is_dir()]

        # We lazy load the entire dataset
        self._data = {}
        for s in track(scenes, description="Lazy Loading Dataset..."):
            if s.name not in self._KEYS_TO_LOAD:
                continue
            lsets = [x for x in list(sorted(s.iterdir()))]
            ufs_t = [SS.from_underfolder(ls).map(rs_t).map(remap) for ls in lsets]
            ufs_i = [SS.from_underfolder(ls).map(rs) for ls in lsets]
            ufs_data = [ufs_i[i].zip(ufs_t[i]) for i in range(len(ufs_i))]
            self._data[s.name] = ufs_data

    def keys(self) -> t.List[str]:
        """
        Return the available keys of the dataset.

        Returns:
            List[str]: The keys of the dataset.
        """
        return list(self._data.keys())

    def get_test_cams(self) -> t.List[int]:
        """
        Return the test cameras indices.
        """
        return self._TEST_CAMS

    def get_test_lights(self) -> t.List[int]:
        """
        Return the test lights indices.
        """
        return self._TEST_LIGHTS

    def __repr__(self) -> str:
        """
        Override the __repr__ method to show the keys in the dataset.

        Returns:
            str: A string representation of the keys in the dataset.
        """
        return f"ReneDataset(available_keys={list(self._data.keys())})"


#!/usr/bin/env python3

import json
import numpy
import pandas
from argparse import ArgumentParser
from functools import partial
from pathlib import Path
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error

class StockModel:
    def __init__(self, neurons=1):
        # Import ML libraries here rather than at the top because
        # a lot of code is run at import time. Importlib will ensure
        # these imports only run once.
        from keras.models import Sequential
        from keras.layers import LSTM, Dense

        # Build model
        self.model = Sequential()
        self.model.add(LSTM(neurons, batch_input_shape=[1, 1, 1], stateful=True))
        self.model.add(Dense(1))
        self.model.compile(loss='mean_squared_error', optimizer='adam')

        # Create scaler fit to the training input
        self.scaler = PreservedScaler()

    def save(self, path):
        self.model.save(path)

    @classmethod
    def load(cls, path):
        from tensorflow import keras
        obj = cls()
        obj.model = keras.models.load_model(path)
        return obj

    def train(self, training_input, training_output, epochs=50):
        if len(training_input.shape) == 2:
            # Fit scaler before training model
            self.scaler.fit(training_input[0])
            # For each sample, go over the whole epoch of training
            for i, input_sample in enumerate(training_input):
                for _ in range(epochs):
                    output_sample = training_output[i]
                    input_sample = self.scaler.shrink(shape_3d(input_sample))
                    output_sample = self.scaler.shrink(shape_1d(output_sample))
                    self.model.fit(input_sample, output_sample, epochs=1, batch_size=1,
                            verbose=0, shuffle=False)
                    self.model.reset_states()
        elif len(training_input.shape) == 1:
            # Fit scaler before training model
            self.scaler.fit(training_input)
            # Train the model on the entire input sample per epoch
            for _ in range(epochs):
                self.model.fit(
                    self.scaler.shrink(shape_3d(training_input)),
                    self.scaler.shrink(shape_1d(training_output)),
                    epochs=1, batch_size=1, verbose=0, shuffle=False
                )
                self.model.reset_states()
        else:
            raise TypeError("Training input must be 1D or 2D with this model")

    def predict_verbose(self, input_sequence):
        # Convert the inputs to differences
        differences = []
        for i in range(1, len(input_sequence)):
            differences.append(input_sequence[i] - input_sequence[i - 1])

        # Scale the inputs down
        self.scaler.fit(differences)
        scaled_values = self.scaler.shrink(differences)

        # Make predictions
        expectations = scaled_values[1:]
        predictions = []
        for input_value in scaled_values[:-1]:
            scaled_output = self.model.predict(shape_3d(input_value), batch_size=1)
            predictions.append(shape_0d(scaled_output))

        # Scale the inputs and outputs up
        expectations = self.scaler.regrow(expectations)
        predictions = self.scaler.regrow(predictions)

        # Return the expected values and predictions made
        return predictions, expectations

    def predict(self, input_sequence):
        # Convert the inputs to differences
        differences = []
        for i in range(1, len(input_sequence)):
            differences.append(input_sequence[i] - input_sequence[i - 1])

        # Scale the inputs down
        self.scaler.fit(differences)
        scaled_values = self.scaler.shrink(differences)

        # Make predictions
        for input_value in scaled_values:
            scaled_output = self.model.predict(shape_3d(input_value), batch_size=1)

        # Return the rescaled output
        return input_sequence[-1] + shape_0d(self.scaler.regrow(scaled_output))

class PreservedScaler:
    def __init__(self, arr=None, *, feature_range=(0,1)):
        self.scaler = MinMaxScaler(feature_range=feature_range)
        if arr is not None:
            self.fit(arr)

    def fit(self, arr):
        self.scaler.fit(shape_2d(arr))

    def shrink(self, arr):
        shaper = get_shaper(arr)
        return shaper(self.scaler.transform(shape_2d(arr)))

    def regrow(self, arr):
        shaper = get_shaper(arr)
        return shaper(self.scaler.inverse_transform(shape_2d(arr)))

def get_shaper(arr):
    return partial(shape_nd, n=len(standardize_array(arr).shape))

def standardize_array(arr):
    if isinstance(arr, pandas.DataFrame):
        return arr.values
    elif isinstance(arr, numpy.ndarray):
        return arr
    elif isinstance(arr, (list, set, dict)):
        return pandas.DataFrame(arr).values
    else:
        return pandas.DataFrame([arr]).values

def shape_3d(arr):
    arr = standardize_array(arr)
    return arr.reshape((len(arr), 1, 1))

def shape_2d(arr):
    arr = standardize_array(arr)
    return arr.reshape((len(arr), 1))

def shape_1d(arr):
    arr = standardize_array(arr)
    return arr.reshape((len(arr),))

def shape_0d(arr):
    arr = shape_1d(arr)
    if len(arr) != 1:
        raise ValueError("This array hold too many values to collapse to 0d")
    return arr[0]

def shape_nd(arr, n):
    arr = standardize_array(arr)
    dimensions = [len(arr)]
    for _ in range(1, n):
        dimensions.append(1)
    return arr.reshape(dimensions)

def display_directions(arr):
    for value in arr:
        if value < 0:
            symbol = 'ðŸ¡“'
        elif value > 0:
            symbol = 'ðŸ¡‘'
        else:
            symbol = '='
        print(symbol, end='')
    print()

def perform_test(args):
    # Load data from file
    with open("data/snapshots.json") as f:
        snapshots = json.load(f)

    # Take the difference at each timestep
    data = []
    for values in snapshots.values():
        datum = []
        prev = None
        for value in values:
            if prev is not None:
                datum.append(value - prev)
            prev = value
        data.append(datum)

    # Split values into training and testing values
    training_cutoff = int(0.8 * len(values))
    training_data = [datum[:training_cutoff] for datum in data]
    testing_data = [datum[training_cutoff:] for datum in data]

    # Split training values into input and output
    training_input = pandas.DataFrame(datum[:-1] for datum in training_data).values
    training_output = pandas.DataFrame(datum[1:] for datum in training_data).values

    # Split testing values into input and output
    testing_input = pandas.DataFrame(datum[:-1] for datum in testing_data).values
    testing_output = pandas.DataFrame(datum[1:] for datum in testing_data).values

    print("----------------")
    print("Compiling model.")
    print("----------------")

    model = StockModel(neurons=args.neurons)

    print("---------------")
    print("Training model.")
    print("---------------")

    model.train(training_input, training_output, epochs=args.epochs)

    print("-------------------")
    print("Making predictions.")
    print("-------------------")

    # Gather predictions and expectations for each sample
    predictions = []
    expectations = []
    for input_sample in testing_input:
        sub_predictions, sub_expectations = model.predict_verbose(input_sample)
        predictions.extend(sub_predictions)
        expectations.extend(sub_expectations)

    print("RMSE: ", mean_squared_error(expectations, predictions) ** 0.5)

def create_model(args):
    # Load data from file
    with open("data/snapshots.json") as f:
        snapshots = json.load(f)

    # Take the difference at each timestep
    data = []
    for values in snapshots.values():
        datum = []
        prev = None
        for value in values:
            if prev is not None:
                datum.append(value - prev)
            prev = value
        data.append(datum)

    # Split training values into input and output
    training_input = pandas.DataFrame(datum[:-1] for datum in data).values
    training_output = pandas.DataFrame(datum[1:] for datum in data).values

    print("----------------")
    print("Compiling model.")
    print("----------------")

    model = StockModel(neurons=args.neurons)

    print("---------------")
    print("Training model.")
    print("---------------")

    model.train(training_input, training_output, epochs=args.epochs)

    # Save model to disk for later
    model.save(args.save_path)

def main():
    parser = ArgumentParser()
    parser.add_argument("-n", "--neurons", type=int, default=1)
    parser.add_argument("-e", "--epochs", type=int, default=50)
    parser.add_argument("-m", "--mode", choices=['test', 'create_model'], default='test')
    parser.add_argument("-p", "--save-path", default='./appdata/model/stock_lstm')
    args = parser.parse_args()

    if args.mode == 'test':
        perform_test(args)
    elif args.mode == 'create_model':
        create_model(args)

if __name__ == '__main__':
    main()


import numpy as np
from scipy.sparse import csr_matrix
from yacs.config import CfgNode as CN

class LDP:
    '''
    Class representing LDP mechanism

    _____________

    Attributes:
    ldp_config: yaml config
        yaml config for ldp mechnism
    ldp_mechanism: func
        ldp function
    ldp_name:
        name of used ldp algo
    _____________

    Methods:
        apply(self, data, priv_bud = None)
            Applying ldp mechannism on data
        _no_LDP(self, data, priv_bud=None)
            Identity ldp mech, w/o ldp
        _harmony(self, data, priv_bud=None)
            k-harmony ldp
        _laplace(self, data, priv_bud=None)
            laplace ldp
    '''
    def __init__(self, ldp_config):
        self.ldp_config = ldp_config
        self.ldp_mechanism = None
        if ldp_config.HARMONY.APPLY:
            self.ldp_mechanism = self._harmony
            self.ldp_name = "Harmony"
        elif ldp_config.LAPLACE.APPLY:
            self.ldp_mechanism = self._laplace
            self.ldp_name = "Laplace"
        else:
            self.ldp_mechanism = self._no_LDP
            self.ldp_name = "NO"
        self.test_dict = None
        self.random_ = np.random.RandomState(self.ldp_config.SEED)

    def apply(self, data, priv_bud = None):
        return self.ldp_mechanism(data, priv_bud)

    def _no_LDP(self, data, priv_bud=None):
        return data

    def _harmony(self, data, priv_bud=None):
        k = self.ldp_config.HARMONY.k
        if priv_bud is None:
            priv_bud = self.ldp_config.PRIVACY_BUDGET

        flatten_data = data.reshape(1,-1)
        dimension = flatten_data.shape[1]

        num_users = flatten_data.shape[0]
        flatten_pertubed_data = np.zeros(flatten_data.shape)
        rand_indexes = self.random_.randint(0, dimension, size = (k, num_users))
        flatten_data_max, flatten_data_min = flatten_data.max(), flatten_data.min()
        flatten_norm_data = flatten_data

        prob_pos = (flatten_norm_data[np.arange(num_users), rand_indexes]  * \
                        (np.exp(priv_bud) - 1) + np.exp(priv_bud) + 1) / 2 / (np.exp(priv_bud) + 1)
        sampled_bernoulli = self.random_.binomial(n=1,p=prob_pos, size =(k, num_users))
        sampled_sign = np.power(-1, sampled_bernoulli + 1)
        flatten_pertubed_data[np.arange(num_users), rand_indexes] = sampled_sign * dimension / k  * \
        (np.exp(priv_bud) + 1) / (np.exp(priv_bud) - 1)

        return flatten_pertubed_data.reshape(data.shape)

    def _laplace(self, data, priv_bud=None):
        if priv_bud is None:
            priv_bud = self.ldp_config.PRIVACY_BUDGET
        sensativity = (data.max() - data.min())
        dimension = data.size
        num_users = data.shape[0]

        LDP_noise = self.random_.laplace(0,  dimension * sensativity / priv_bud,
                                                    size = np.shape(data))
        return data + LDP_noise

local_factors_names = ['long-term', 'contextual']
global_factors_names = ['items', 'contexts']

# MODEL: SeqMF with eta that is a number for every user (2.3.1), no sessions

def prepare_target_update(factors, target_factor_id, update_funcs, updater, *args):
    target_factors = factors[target_factor_id]
    update_func = update_funcs[target_factor_id]
    target_update_func = updater(update_func, *args)
    return target_factors, target_update_func

# Server side:
def update_global_model(
    confidence, transitions,
    local_factors, global_factors,
    gradient_funcs, regularization, gain, n_iter,
    evaluation_callback, iterator, ldp  ### TO DEBUG
):
    """
        To fill in!
    """
    iterator = iterator or range
    for _ in iterator(n_iter):
        for factor_name in global_factors_names:
            update_global_factor(
                confidence, transitions,
                local_factors, global_factors, factor_name,
                gradient_funcs, regularization, gain, ldp
            )
        if evaluation_callback:
            evaluation_callback(local_factors, global_factors)

def update_global_factor(
    confidence, transitions,
    local_factors, global_factors, factor_name,
    gradient_funcs, regularization, gain, ldp
):
    target_factor_id = global_factors_names.index(factor_name)
    updater_args = (  # will go into `fetch_items_grad` or `fetch_context_grad`
        confidence, transitions, local_factors, global_factors
    )
    target_factor, gradient_update = prepare_target_update(
        global_factors, target_factor_id, gradient_funcs, gradient_updater, *updater_args
    )

    grad = regularization * target_factor
    n_users, _ = confidence.shape
    for user in range(n_users):
        grad += ldp.apply(gradient_update(user))
    target_factor -= gain * grad

def gradient_updater(gradient_func, confidence, transitions, local_factors, global_factors):
    Q, Qb = global_factors
    empty_Su = csr_matrix((Q.shape[0], Qb.shape[0]))
    grad_params = () # for later use with e.g. Adam
    def updater(user):
        item_transitions = transitions.get(user, empty_Su) # TODO: no need for update if user_Su's empty in the context factor case
        return gradient_func(
            confidence, item_transitions,
            *local_factors, *global_factors,
            user, *grad_params
        )
    return updater

def _compute_user_preference(Su, P, eta, Q, Qb, u):
    SuQb = (Su @ Qb)
    #seq_part = np.einsum('ij,ij->i', SuQb, Q, optimize=False)
    seq_part = (SuQb * Q).sum(axis=1)
    if eta is not None:
        seq_part *= eta[u]
    r_u = np.dot(Q, P[u]) + seq_part
    return r_u, SuQb

def _update_weighted_error(Cui, r, u):
    indptr = Cui.indptr
    inds = Cui.indices[indptr[u]:indptr[u + 1]]
    coef = Cui.data[indptr[u]:indptr[u + 1]]
    r[inds] = (r[inds] - 1.0) * coef

def fetch_items_grad(Cui, Su, P, eta, Q, Qb, u):
    r_u, SuQb = _compute_user_preference(Su, P, eta, Q, Qb, u)
    _update_weighted_error(Cui, r_u, u)
    longterm_grad = np.outer(r_u, P[u])
    sessions_grad = r_u[:, np.newaxis] * SuQb
    if eta is not None:
        return longterm_grad + eta[u] * sessions_grad
    return longterm_grad + sessions_grad

def fetch_context_grad(Cui, Su, P, eta, Q, Qb, u):
    r_u, _ = _compute_user_preference(Su, P, eta, Q, Qb, u)
    _update_weighted_error(Cui, r_u, u)
    sessions_grad = Su.T @ (r_u[:, np.newaxis] * Q)
    if eta is not None:
        return eta[u] * sessions_grad
    return sessions_grad

# Client side:
def update_local_models(
    confidence, transitions,
    local_factors, global_factors,
    least_squares_funcs, regularization
):
    for factor_name in local_factors_names:
        if local_factors[local_factors_names.index(factor_name)] is None:
            continue
        update_local_factor(
            confidence, transitions,
            local_factors, factor_name, global_factors,
            least_squares_funcs, regularization
        )

def least_squares_updater(least_squares_func, confidence, transitions, other, global_factors, regularization):
    Q, Qb = global_factors
    QtQ = np.zeros(shape=(Q.shape[1], Q.shape[1])) #TO FIX!!!!
    #QtQ = Q.T @ Q
    QtQ[np.diag_indices_from(QtQ)] += regularization #TO FIX!!!!
    empty_Su = csr_matrix((Q.shape[0], Qb.shape[0]))
    def updater(user):
        item_transitions = transitions.get(user, empty_Su) # TODO: no need for update if user_Su's empty in the context factor case
        return least_squares_func(
            confidence, item_transitions,
            other, *global_factors, QtQ, user, regularization
        )
    return updater

def update_local_factor(
    confidence, transitions,
    local_factors, factor_name, global_factors,
    least_squares_funcs, regularization
):
    '''
    Implicitly assumes there're only 2 types of user factors.
    '''
    target_factor_id = local_factors_names.index(factor_name)
    other_factor_id = 1 - target_factor_id # will break if there're >2 types of factors
    updater_args = ( # will go into `least_squares_long_term` or `least_squares_contextual`
        confidence, transitions,
        local_factors[other_factor_id], global_factors, regularization
    )
    target_factor, least_squares_update = prepare_target_update(
        local_factors, target_factor_id,
        least_squares_funcs, least_squares_updater, *updater_args
    )
    n_users, _ = confidence.shape
    for u in range(n_users):
        target_factor[u] = least_squares_update(u) # each client does independently

def least_squares_long_term(Cui, Su, eta, Q, Qb, QtQ, u, reg):
    A, b = user_linear_equation(Cui, Su, eta, Q, Qb, QtQ, u)
    return np.linalg.solve(A, b)

def least_squares_contextual(Cui, Su, P, Q, Qb, QtQ, u, reg):
    indptr = Cui.indptr
    inds = Cui.indices[indptr[u]:indptr[u + 1]]
    coef = Cui.data[indptr[u]:indptr[u + 1]]

    long_term_err = (1.0 - np.dot(Q[inds], P[u]))
    seq_part = np.einsum('ij,ij->i', Su@Qb, Q, optimize=False)
    weighted_seq_part = coef * seq_part[inds]
    denom = np.dot(seq_part[inds], weighted_seq_part)
    return np.dot(long_term_err, weighted_seq_part) / (denom + reg)

def user_linear_equation(Cui, Su, eta, Q, Qb, QtQ, u):
    indptr = Cui.indptr
    inds = Cui.indices[indptr[u]:indptr[u + 1]]
    coef = Cui.data[indptr[u]:indptr[u + 1]]

    # calculate A
    Qnnz = Q[inds]
    #A = QtQ + (Qnnz.T * (coef - 1)) @ Qnnz
    A = QtQ + (Qnnz.T * coef) @ Qnnz

    # calculate b
    seq_part = -np.einsum('ij,ij->i', Su@Qb, Q, optimize=False)
    if eta is not None:
        seq_part *= eta[u]
    seq_part[inds] = (seq_part[inds] + 1.0) * coef
    b = Q.T @ seq_part
    return A, b

def initialize_model(n_users, n_items, n_factors, seed, use_eta=False):
    random_state = np.random.RandomState(seed)
    user_factors_long_term = random_state.normal(0, 0.01, size=(n_users, n_factors))
    user_factors_contextual = None
    if use_eta:
        user_factors_contextual = random_state.normal(0, 0.01, size=(n_users,))
    local_factors = [user_factors_long_term, user_factors_contextual] # order must comply with local_factors_names
    least_squares = [least_squares_long_term, least_squares_contextual] # order must comply with local_factors_names

    item_factors = random_state.normal(0, 0.01, size=(n_items, n_factors))
    context_factors = random_state.normal(0, 0.01, size=(n_items, n_factors))
    global_factors = [item_factors, context_factors] # order must comply with global_factors_names
    gradient_funcs = [fetch_items_grad, fetch_context_grad] # order must comply with global_factors_names
    return local_factors, global_factors, least_squares, gradient_funcs

# Model training functionality:
def fit_model(
    confidence_matrix, transition_matrices, n_factors, regularization,
    gain, *, n_epochs=1, n_iter=20, seed=42, evaluation_callback=None,
    iterator=None, use_eta=False,
):
    """
        To fill in!
    """
    n_users, n_items = confidence_matrix.shape
    local_factors, global_factors, least_squares, gradient_funcs = initialize_model(
        n_users, n_items, n_factors, seed, use_eta,
    )
    common_args = dict(
        confidence = confidence_matrix,
        transitions = transition_matrices,
        local_factors = local_factors,
        global_factors = global_factors,
        regularization=regularization,
    )
    iterator = iterator or range
    for epoch in iterator(n_epochs):
        update_global_model(
            **common_args,
            gradient_funcs=gradient_funcs,
            gain=gain,
            n_iter=n_iter,
        )

        update_local_models(
            **common_args,
            least_squares_funcs=least_squares,
        )

        if evaluation_callback:
            evaluation_callback(local_factors, global_factors)

    return local_factors, global_factors

def fit_restricted(
    confidence_matrix, transition_matrices, n_factors,
    regularization, gain, *, n_iter=1, seed=42,
    evaluation_callback=None, use_eta=False, iterator=None, ldp=None,
    **kwargs # compatibility
):
    n_users, n_items = confidence_matrix.shape
    local_factors, global_factors, least_squares, gradient_funcs = initialize_model(
        n_users, n_items, n_factors, seed, use_eta,
    )
    common_args = dict(
        confidence=confidence_matrix,
        transitions=transition_matrices,
        local_factors=local_factors,
        global_factors=global_factors,
        regularization=regularization,
    )
    update_local_models(
        **common_args,
        least_squares_funcs=least_squares,
    )
    update_global_model(
        **common_args,
        gradient_funcs=gradient_funcs,
        gain=gain,
        n_iter=n_iter,
        evaluation_callback=evaluation_callback,
        iterator=iterator, ldp=ldp
    )
    update_local_models(
        **common_args,
        least_squares_funcs=least_squares,
    )
    return local_factors, global_factors

def get_scores_generator(local_factors, global_factors):
    P, eta = local_factors
    Q, Qb = global_factors
    if eta is not None:
        def generate_scores(uid, sid, sess_items, item_pool):
            scores = (P[uid] + eta[uid] * Qb[sess_items[-1]]) @ Q[item_pool].T
            return scores
        return generate_scores

    def generate_scores(uid, sid, sess_items, item_pool):
        scores = (P[uid] + Qb[sess_items[-1]]) @ Q[item_pool].T
        return scores
    return generate_scores


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from scipy import misc
from matplotlib import animation

# 解决中文乱码问题
myfont = fm.FontProperties(fname="simsun.ttc", size=14)

# 生成测试数据
x = np.arange(-10.0, 10.0, 0.1)
numPoint = len(x)

# 调试和生成gif开关
# ModeDebug=True
ModeDebug=False

def animate(index):

    if(index%10==0): # 用来压缩gif
        # 清除原有图像
        plt.cla()
        # 设定标题等
        plt.title("函数求导", fontproperties=myfont)
        plt.grid(True)
        # 得到函数y的所有值
        y = custFunction(x)
        # 得到函数导数y的所有值
        dy = misc.derivative(custFunction, x)
        # 设置X轴
        plt.xlabel("X轴", fontproperties=myfont)
        # 设置Y轴
        plt.ylabel("Y轴", fontproperties=myfont)
        # plt.xlim(-10, 10)
        plt.ylim(-10, 10)
        # 画曲线
        plt.plot(x, y, 'r-', linewidth=2.0, label="函数")
        # 画曲线导数
        plt.plot(x, dy, "g-", linewidth=2.0, label="函数的导数")
        # 得到给定x在函数上的y值
        yOfLine = custFunction(x[index])
        # 通过y值和导数方程得到此点在切线上的y值
        y_tan = misc.derivative(
            custFunction, x[index]) * (x - x[index]) + yOfLine
        # 画切线
        plt.plot(x, y_tan, 'b--', linewidth=2.0, label="函数的切线")

        # 设置图例位置,loc可以为[upper, lower, left, right, center]
        plt.legend(loc="upper left", prop=myfont, shadow=True)
        # 暂停
        plt.pause(0.001)

def custFunction(x):
     return np.sin(x)
     # return 3*x*x+2*x+1
    #  return x*x

# 生成画布
fig = plt.figure(figsize=(8, 6), dpi=80)

if(ModeDebug):
    # 打开交互模式
    plt.ion()
    for index in range(numPoint):
        animate(index)
    # 关闭交互模式
    plt.ioff()
    # 图形显示
    plt.show()
else:
    anim = animation.FuncAnimation(fig, animate, frames=numPoint)
    anim.save('hhh.gif', writer='imagemagick', fps=30)


#!/usr/bin/env python3
# Name: Louis Chatta(lchatta)
# Group Members: none
"""
This program takes a string input and loops through
all of the characters in the string as a capitalizied
string. It then checks every chararacter to see if it is
allowed. If it is not, then it starts counting the number
of bases to remove. If it is and the number of bases to remove
is greator than Zero, then insert the number in a {%d} format, and
insert the new character, and reset the counter number. If the
number of bases to remove is still 0, then we are encountering
another base and we should simply insert the base.
Notice that the each allowed base and counter string is added
to fixedDna array, in order to manipulate the new string. When
we are done adding to the fixedDna, then we create a string
from the array.
"""
dna = input("Enter a DNA sequence: ")
# the allowed bases saved in an array
allowedBases = ['A','C','G','T']
removedBaseCount = 0
# the data structure used to hold the new string
fixedDna = []
# loop through input as uppercase
for base in dna.upper():
	# increment counter if not in allowed bases
   if base not in allowedBases:
   		removedBaseCount += 1
   else:
   		# add the the number and {} if the next number
   		# is a base and we have already seen at least
   		# one non-base
   		if removedBaseCount > 0:
   			fixedDna.append('{{{}}}'.format(removedBaseCount))
   			removedBaseCount = 0
   			fixedDna.append(base)
   		# if we have not seen at least one non base
   		# then just add the base
   		else:
   			fixedDna.append(base)
# join all the elements in the array and print
print (''.join(fixedDna))


import turtle
import math

def begin():
    turtle.penup()
    turtle.setx(-450)
    turtle.sety(-300)
    turtle.pendown()

def ex1():
    a = 20
    b = a / 4
    steps = 25

    for i in range(steps):
        turtle.forward(a)
        turtle.left(90)
        turtle.forward(b)
        turtle.right(90)

    turtle.done()

def ex2():
    a = 30
    b = a * 1
    steps = 20

    for i in range(steps):
        turtle.left(90)
        turtle.forward(a)
        turtle.backward(a)
        turtle.right(90)
        turtle.forward(b)

    turtle.done()

def ex3():
    a = 20
    b = a * 1
    steps = 12

    def tr(ar, br):
        turtle.left(90)
        turtle.forward(ar)
        turtle.right(90)
        turtle.forward(br)

    def tl(al, bl):
        turtle.right(90)
        turtle.forward(al)
        turtle.left(90)
        turtle.forward(bl)

    for i in range(steps):
        tr(a, b)
        tl(a, b)

    turtle.done()

def ex4():
    a = 20
    b = 2 ** (1 / 2) * a
    steps = 12

    def tr(ar, br):
        turtle.left(90)
        turtle.forward(ar)
        turtle.right(135)
        turtle.forward(br)
        turtle.left(90)
        turtle.forward(br)
        turtle.right(45)

    def tl(al):
        bl = al
        turtle.right(90)
        turtle.forward(al)
        turtle.left(90)
        turtle.forward(bl)

    for i in range(steps):
        tr(a, b / 2)
        tl(a)

    turtle.done()

def ex5():
    a = 30
    steps = 12

    add_angle = 0
    turtle.left(45 + add_angle / 2)

    for i in range(steps):
        turtle.forward(a)
        turtle.right(90 + add_angle)
        turtle.forward(a)
        turtle.left(90 + add_angle)

    turtle.done()

def ex6():
    a = 30
    steps = 12

    add_angle = 0
    turtle.left(60 + add_angle)

    def tr(ar, angle):
        turtle.forward(ar)
        turtle.right(60 + angle)
        turtle.forward(ar)
        turtle.right(60 + angle)

    def tl(al, angle):
        turtle.forward(al)
        turtle.left(60 + angle)
        turtle.forward(al)
        turtle.left(60 + angle)

    for i in range(steps):
        tr(a, add_angle)
        tl(a, add_angle)

    turtle.done()

def ex7():
    r = 30
    steps = 12
    turtle.left(90)

    for i in range(steps):
        turtle.circle(-r, 180)
        turtle.left(180)

    turtle.done()

def ex8():
    a = 30
    steps = 10
    turtle.left(90)

    for i in range(3, steps):
        for j in range(i):
            turtle.forward(a)
            turtle.right(360 / i)
        turtle.penup()
        turtle.setx(turtle.xcor() + a * i / 2)
        turtle.pendown()

    turtle.done()

def ex9():
    a = 100
    turtle.left(90)

    for i in range(4):
        turtle.forward(a)
        turtle.right(90)
        turtle.forward(a)
        turtle.left(90)
        turtle.forward(a)
        turtle.left(90)

    turtle.done()

def ex10():
    a = 50
    turtle.left(90)

    for i in range(4):
        for j in range(5):
            turtle.forward(a)
            turtle.left(90)
        turtle.right(180)

    turtle.done()

def ex11():
    a = 100
    n = 4
    angle = 90 / (n + 1)
    turtle.left(angle)

    for i in range(n):
        for j in range(4):
            turtle.forward(a)
            turtle.left(90)
        turtle.left(angle)

    turtle.done()

def ex12():
    a = 150
    n = 4
    angle = 90 / n
    turtle.left(angle)

    for j in range(4 * n):
        for y in range(4):
            turtle.forward(a)
            turtle.right(90)

        turtle.right(angle)

    turtle.done()

def ex13():
    a = 150
    n = 5
    turtle.left(90)

    for i in range(n):
        for j in range(3):
            turtle.forward(a)
            turtle.right(120)
        turtle.left(360 / n)

    turtle.done()

def ex14():
    a = 300
    number_of_loops = 2
    step = 1
    delta = a / 360 * step
    turtle.left(90)

    for j in range(360 // step):
        for i in range(3):
            turtle.forward(a - delta * j)
            turtle.right(120)
        turtle.right(number_of_loops * step)

    turtle.done()

def ex15():
    r = 100
    n = 8

    for i in range(n):
        turtle.circle(r)
        turtle.left(360 / n)

    turtle.done()

def ex16():
    n = 20
    r = step = 5
    k = 4

    for i in range(n * k):
        turtle.circle(r, 360 / k)
        r += step

    turtle.done()

def ex17():
    side = 300
    n = 5

    for i in range(n):
        for j in (side / n, side, side / n, side):
            turtle.forward(j)
            turtle.left(90)
        turtle.forward(side / n)
    turtle.done()

def ex18():
    side = 60
    layers = 8

    for i in range(layers):
        for k in range(i + 1):
            for j in range(3):
                turtle.pendown()
                turtle.forward(side)
                turtle.left(120)
                turtle.penup()

            turtle.forward(side)

        turtle.backward(side * (i + 1))
        turtle.left(60)
        turtle.backward(side)
        turtle.right(60)

    turtle.done()

def ex19():
    begin()
    r = 100
    for i in range(4):
        turtle.circle(r, 180)
        turtle.left(90)
    turtle.done()

def ex20():
    r = 100
    for i in range(4):
        turtle.circle(-r, 180)
        turtle.left(90)

    turtle.done()

def ex21():
    r = 200
    turtle.penup()
    turtle.sety(200)
    turtle.pendown()
    turtle.circle(-r)

    n = 7
    r_list = math.sin(math.pi / n) * r

    turtle.right(270 + 180 / n)
    for i in range(n):
        turtle.circle(-r_list, 180)
        turtle.left(180 - 360 / n)

    turtle.done()

def control(ex):
    turtle.hideturtle()
    turtle.speed(0)
    if ex == 1:
        begin()
        ex1()
    elif ex == 2:
        begin()
        ex2()
    elif ex == 3:
        begin()
        ex3()
    elif ex == 4:
        begin()
        ex4()
    elif ex == 5:
        begin()
        ex5()
    elif ex == 6:
        begin()
        ex6()
    elif ex == 7:
        begin()
        ex7()
    elif ex == 8:
        begin()
        ex8()
    elif ex == 9:
        ex9()
    elif ex == 10:
        ex10()
    elif ex == 11:
        ex11()
    elif ex == 12:
        ex12()
    elif ex == 13:
        ex13()
    elif ex == 14:
        ex14()
    elif ex == 15:
        ex15()
    elif ex == 16:
        ex16()
    elif ex == 17:
        ex17()
    elif ex == 18:
        ex18()
    elif ex == 19:
        ex19()
    elif ex == 20:
        ex20()
    elif ex == 21:
        ex21()
    else:
        print("Такого задания нет")

if __name__ == "__main__":
    quiz = int(input("""Выберите задание:
     Для уроков (составитель тестов). Лесенка
     2. Частокол
     3. Прямоугольный забор
     4. "Кремлёвский" забор
     5. Треугольный забор
     6. Профиль
     7. Дуговой забор
     8. Правльные многоугольники
     9. Простой крест
    10. Крест из квадратов
    11. Веер из квадратов
    12. Платочки
    13. Цветок из треугольников
    14. Наутилус из треугольников
    15. Цветок circle()
    16. Спираль с постоянным шагом
    17. Прямоугольный забор
    18. Пирамида треугольников
    19. 4 лепестка
    20. Четырехлистрик
    21. Ромашка
    Ответ: """))
    control(quiz)


import sys

N = int(sys.stdin.readline())
A = list(map(int, sys.stdin.readline().split()))
parent = [None] * (N+1)
dp = [1] * (N+1)

maxlen = 0
seqend = 0
for n in range(N):
    for m in range(n):
        if not A[m] < A[n]:
            continue
        if dp[m] >= dp[n]:
            dp[n] = dp[m]+1
            parent[n] = m
            if dp[n] > maxlen:
                maxlen = dp[n]
                seqend = n

sequence = []
while seqend is not None:
    sequence.append(A[seqend])
    seqend = parent[seqend]
print(len(sequence))
print(' '.join(map(str, reversed(sequence))))

Baekjoon Online Judge/problem/14003/26815257 시간 초과.py


import streamlit as st
import time
import pandas as pd
import forecasting_wpi as fw
import altair as alt
from matplotlib import  pyplot as plt
from plotly import  graph_objs as go
import plotly.express as px

st.header('Wholesale Price Index Forecasting')
st.write("The new series of Wholesale Price Index(WPI) with base 2011-12 is effective from April 2017. Data for WPI(2011-12) has however been provided from April 2012 to March 2017 for the purpose of research and analysis only. Linking factor given for conversion of WPI(2011-12) indices to WPI(2004-05) series should be used from April 2017 onwards.")

temp_df = fw.getData()
col_values = fw.commodity(temp_df)
def showDataFrame(df):
    first_col.dataframe(df)

show_trend = st.button('Show Trend')
colNameSelected = st.selectbox("Please select Commodity",options=col_values)
first_col, second_col = st.beta_columns([1,1])

temp_df_selected = fw.filterData(colNameSelected,temp_df)
showDataFrame(temp_df_selected)

fig = px.line(temp_df_selected, x="TimeSeries", y="WPI", title='WPI Trend of '+colNameSelected)
second_col.plotly_chart(fig)

build_model = st.button('Forecast : Prophet')

def plotForecast(cmp_df):
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=cmp_df['TimeSeries'], y=cmp_df['y'],
                             mode='lines',
                             name='Actual'))
    fig.add_trace(go.Scatter(x=cmp_df['TimeSeries'], y=cmp_df['yhat'],
                             mode='lines+markers',
                             name='Forecast'))
    st.plotly_chart(fig)

if build_model:
    cmp_df = fw.modelBuildingStart(colNameSelected,temp_df)
    st.dataframe(cmp_df)
    plotForecast(cmp_df)
#if show_trend:
    # line_alt = alt.Chart(temp_df_selected).mark_line().encode(
    #     x='TimeSeries',
    #     y='WPI'
    # )
    # st.altair_chart(line_alt,use_container_width=True)

#
# st.write('Hello World')
# name = st.text_input("Enter you Name")
# home = st.sidebar.button("Home",)
# about = st.sidebar.button("About",)
# add_selectbox = st.sidebar.selectbox(
#     "How would you like to be contacted?",
#     ("Email", "Home phone", "Mobile phone")
# )
# if home:
#     print("Home clicked")
#     st.balloons()
# st.write(name)
# print(name)
# progress = st.progress(0)
#
#
# st.code('for i in range(8): foo()')
#
#


from typing import List

def rotate(matrix: List[List[int]]) -> None:
    N = len(matrix)
    for i in range(N>>1):
        temp_row = matrix[i][:]
        matrix[i] = matrix[N - 1 - i][:]
        matrix[N - 1 - i] = temp_row

if __name__ == "__main__":
    n, digit = divmod(10036, 10)


violations = {
    "g1": 10000     ,    "g2": 20000     ,    "g3": 30000,
    "b1": 50000     ,    "b2": 55000     ,    "b3": 60000,
    "y1": 100000     ,    "y2": 150000,
    "r1": 300000     ,    "r2": 400000
}
keys = list(violations.keys())
print("violations:",keys)
n = int(input("enter number of violations: "))
sum = 0
for i in range(n):
    code = input("code: ")
    sum += violations[code]
print("total penalties of violations:",sum)
# thanks for your timr ;)


import ui
import command as cmd
import model as md
from tkinter import *
from PIL import Image, ImageTk

class Application():
    def __init__(self):
        traffic_lights = [md.TrafficLight(x*30%23) for x in range(16)]
        city = md.City([md.Road(x*15, "Название улицы" + str(x), [md.Building("Здание" + str(x*10+i)) for i in range(5)], [traffic_lights[x], traffic_lights[x+1]]) for x in range(15)])
        routes = [md.Rout(city.roads[x:-x]) for x in range(1,6)]
        self.app_ui = ui.ApplicationWindow(add_road_command=cmd.AddRoadCommand(city),
                                           add_traffic_light_command=cmd.AddTrafficLightCommand(city),
                                           add_building_command=cmd.AddBuildingCommand(city),
                                           delete_building_command=cmd.DeleteBuildingCommand(city),
                                           delete_road_command=cmd.DeleteRoadCommand(city),
                                           delete_traffic_light_command=cmd.DeleteTrafficLightCommand(city),
                                           change_load_command=cmd.ChangeLoadCommand(city),
                                           change_roadname_command=cmd.ChangeRoadnameCommand(city),
                                           change_throughput_command=cmd.ChangeThroughputCommand(city),
                                           find_shortest_rout_command=cmd.FindShortestRoutCommand(city, routes),
                                           build_rout_command=cmd.BuildRoutCommand(city, routes),
                                           find_fastest_rout_command=cmd.FindFastestRoutCommand(city, routes))

    def run(self):
        self.app_ui.run()

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


import argparse

import cv2
import numpy as np
import tensorflow as tf

import lpips_tf

def load_image(fname):
    image = cv2.imread(fname)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    return image.astype(np.float32) / 255.0

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--model', choices=['net-lin', 'net'], default='net-lin', help='net-lin or net')
    parser.add_argument('--net', choices=['squeeze', 'alex', 'vgg'], default='alex', help='squeeze, alex, or vgg')
    parser.add_argument('--version', type=str, default='0.1')
    args = parser.parse_args()

    ex_ref = load_image('./PerceptualSimilarity/imgs/ex_ref.png')
    ex_p0 = load_image('./PerceptualSimilarity/imgs/ex_p0.png')
    ex_p1 = load_image('./PerceptualSimilarity/imgs/ex_p1.png')

    session = tf.Session()

    image0_ph = tf.placeholder(tf.float32)
    image1_ph = tf.placeholder(tf.float32)
    lpips_fn = session.make_callable(
        lpips_tf.lpips(image0_ph, image1_ph, model=args.model, net=args.net, version=args.version),
        [image0_ph, image1_ph])

    ex_d0 = lpips_fn(ex_ref, ex_p0)
    ex_d1 = lpips_fn(ex_ref, ex_p1)

    print('Distances: (%.3f, %.3f)' % (ex_d0, ex_d1))

if __name__ == '__main__':
    main()


# the regressor will be trained on previously trained and stroed supervised vae model decoder output

# 2019.1.16
# zinc data set
# regressor pretrained on the pretrained_vanilla_vae output and then fixed
# encoder take only x as input

import matplotlib
import matplotlib.pyplot as plt
import rdkit
from rdkit import Chem
from rdkit.Chem import Draw
import h5py
import pdb
import numpy as np
import argparse
import random
import sys, os
import torch
from torch.autograd import Variable
from torch.nn.parameter import Parameter
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.optim.lr_scheduler import ReduceLROnPlateau
from tqdm import tqdm

#prameters to be specified
#cmd_args.regressor_saved_dir = './regressor/regressor_pretrained_pretrained_vae_output'
#cmd_args.vanilla_vae_save_dir = './../ICML_2019/vanila_supervised_vae/zinc/vanilla_supervised_vae'
#cmd_args.training_data_dir = '/work/molecule_generation/sdvae/mol_vae_clean/zinc_data_experiments/data/data_278'
sys.path.append('%s/../' % os.path.dirname(os.path.realpath('__file__')))
from cmd_args import cmd_args
sys.path.append('%s/../util/' % os.path.dirname(os.path.realpath('__file__')))
import cfg_parser as parser
cmd_args.output_dim = 1
cmd_args.batch_size = 300
cmd_args.num_epochs= 300
cmd_args.output_dim = 1
cmd_args.kl_coeff = 1
seed = 19260817

sys.path.append('%s/../util/' % os.path.dirname(os.path.realpath('__file__')))
## define the model
from mol_util import rule_ranges, terminal_idxes, DECISION_DIM
from train_util import PerpCalculator
from train_util import raw_logit_to_smile_labels, run_job

class MolVAE(nn.Module):
    def __init__(self):
        super(MolVAE, self).__init__()
        self.latent_dim = cmd_args.latent_dim
        self.encoder = CNNEncoder(max_len=cmd_args.max_decode_steps, latent_dim=cmd_args.latent_dim)
        self.state_decoder = StateDecoder(max_len=cmd_args.max_decode_steps, latent_dim=cmd_args.latent_dim)
        self.perp_calc = PerpCalculator()

    def reparameterize(self, mu, logvar):
        if self.training:
            eps = mu.data.new(mu.size()).normal_(0, cmd_args.eps_std)
            if cmd_args.mode == 'gpu':
                eps = eps.cuda()
            eps = Variable(eps)

            return mu + eps * torch.exp(logvar * 0.5)
        else:
            return mu

    def forward(self, x_inputs, y_inputs, true_binary, rule_masks, t_y):
        z_mean, z_log_var = self.encoder(x_inputs)
        z = self.reparameterize(z_mean, z_log_var)
        raw_logits = self.state_decoder(z, y_inputs)
        perplexity = self.perp_calc(true_binary, rule_masks, raw_logits)
        kl_loss = -0.5 * torch.sum(1 + z_log_var - z_mean ** 2 - torch.exp(z_log_var), -1)

        return perplexity, cmd_args.kl_coeff * torch.mean(kl_loss)

from pytorch_initializer import weights_init
#q(z|x)
class CNNEncoder(nn.Module):
    def __init__(self, max_len, latent_dim):
        super(CNNEncoder, self).__init__()
        self.latent_dim = latent_dim
        self.max_len = max_len

        self.conv1 = nn.Conv1d(DECISION_DIM, 9, 9)
        self.conv2 = nn.Conv1d(9, 9, 9)
        self.conv3 = nn.Conv1d(9, 10, 11)

        self.last_conv_size = max_len - 9 + 1 - 9 + 1 - 11 + 1
        self.w1 = nn.Linear(self.last_conv_size * 10, 435)
        self.mean_w = nn.Linear(435, latent_dim)
        self.log_var_w = nn.Linear(435, latent_dim)
        weights_init(self)

    def forward(self, x_cpu):
        if cmd_args.mode == 'cpu':
            batch_input = Variable(torch.from_numpy(x_cpu))
        else:
            batch_input = Variable(torch.from_numpy(x_cpu).cuda())

        h1 = self.conv1(batch_input)
        h1 = F.relu(h1)
        h2 = self.conv2(h1)
        h2 = F.relu(h2)
        h3 = self.conv3(h2)
        h3 = F.relu(h3)

        # h3 = torch.transpose(h3, 1, 2).contiguous()
        flatten = h3.view(x_cpu.shape[0], -1)
        h = self.w1(flatten)
        h = F.relu(h)

        z_mean = self.mean_w(h)
        z_log_var = self.log_var_w(h)

        return (z_mean, z_log_var)

#decoder
class StateDecoder(nn.Module):
    def __init__(self, max_len, latent_dim):
        super(StateDecoder, self).__init__()
        self.latent_dim = latent_dim + cmd_args.output_dim
        self.max_len = max_len

        self.z_to_latent = nn.Linear(self.latent_dim, self.latent_dim)
        if cmd_args.rnn_type == 'gru':
            self.gru = nn.GRU(self.latent_dim, 501, cmd_args.output_dim)
        elif cmd_args.rnn_type == 'sru':
            self.gru = SRU(self.latent_dim, 501, cmd_args.output_dim)
        else:
            raise NotImplementedError

        self.decoded_logits = nn.Linear(501, DECISION_DIM)
        weights_init(self)

    def forward(self, z, y):

        if cmd_args.mode == 'cpu':
            y = torch.tensor(y).float()
        else:
            y = torch.tensor(y).cuda().float()

        assert len(z.size()) == 2 # assert the input is a matrix
        h = self.z_to_latent(torch.cat((z, y.view(y.shape[0],1)), 1))
        #h = self.z_to_latent(torch.cat((z, torch.tensor(y).cuda().float()), 1))
        h = F.relu(h)
        rep_h = h.expand(self.max_len, z.size()[0], z.size()[1] + cmd_args.output_dim) # repeat along time steps
        out, _ = self.gru(rep_h) # run multi-layer gru
        logits = self.decoded_logits(out)
        return logits

#1. Define regressor
from mol_util import DECISION_DIM
class Regressor(nn.Module):
    def __init__(self, max_len, latent_dim):
        super(Regressor, self).__init__()
        self.latent_dim = latent_dim
        self.max_len = max_len
        self.conv1 = nn.Conv1d(DECISION_DIM, 9, 9)
        self.conv2 = nn.Conv1d(9, 9, 9)
        self.conv3 = nn.Conv1d(9, 10, 11)
        self.last_conv_size = max_len - 9 + 1 - 9 + 1 - 11 + 1
        self.w1 = nn.Linear(self.last_conv_size * 10 , 435 )
        self.mean_w = nn.Linear(435, latent_dim)
        self.label_linear_1 = nn.Linear(latent_dim, cmd_args.output_dim)
        weights_init(self)

    def forward(self, x_cpu):
        if cmd_args.mode == 'cpu':
            batch_input = Variable(x_cpu)

        else:
            batch_input = Variable(x_cpu.cuda())

        h1 = self.conv1(batch_input)
        h1 = F.relu(h1)
        h2 = self.conv2(h1)
        h2 = F.relu(h2)
        h3 = self.conv3(h2)
        h3 = F.relu(h3)
        flatten = h3.view(x_cpu.shape[0], -1)
        h = self.w1(flatten)
        h = F.relu(h)
        ## apply a linear transformation followed by sigmoid on latent z
        z_mean = self.mean_w(h)
        z_mean = F.relu(z_mean)
        y = self.label_linear_1(z_mean)
        y = F.tanh(y)
        return y

## train the regressor only on the training data logits
sys.path.append('%s/../util/' % os.path.dirname(os.path.realpath('__file__')))
from train_util import get_batch_input_regressor
def train_regressor(phase, epoch, optimizer, model, regressor, sample_indexs, data_binary, data_property):
    total_loss = []
    pbar = tqdm(range(0, (len(sample_indexs) + (cmd_args.batch_size - 1) * (optimizer is None)) // cmd_args.batch_size), unit='batch')

    if phase == 'train' and optimizer is not None:
        regressor.train()
    else:
        regressor.eval()

    n_samples = 0
    for pos in pbar:
        selected_idx = sample_indexs[pos * cmd_args.batch_size : (pos + 1) * cmd_args.batch_size]
        x_inputs, y_inputs,v_x, t_y = get_batch_input_regressor(selected_idx, data_binary, data_property)  # no grad for evaluate mode.
        z_mean, z_log_var = model.encoder(x_inputs)
        #z = model.reparameterize(z_mean,  z_log_var)
        z = z_mean
        ## p(x|z, y')
        rex_logits_ = model.state_decoder(z, y_inputs)

        '''
        smiles, index, y_reconstructedx = raw_logit_to_smile_labels(rex_logits_.detach())
        if smiles ==[]:
            print('smiles is empty')
            pred_y = 0
            negative_reward  = 0
        else:
            true_y = t_y[index]
            rex_logits = rex_logits_[:,index, :]
            pred_y = regressor(rex_logits.permute(1,2,0))
            negative_reward = (pred_y.float().view(-1) - true_y).norm()
            minibatch_loss = negative_reward.data.cpu().numpy()
            #pbar.set_description('At epoch: %d  regressor loss: %0.5f' % (epoch, minibatch_loss))
            pbar.set_description('At epoch: %d  regressor loss: %0.5f  reg1: %0.5f' % (epoch, minibatch_loss, negative_reward))
       '''
        pred_y = regressor(rex_logits_.permute(1,2,0))
        true_y = t_y
        negative_reward = (pred_y.float().view(-1) - true_y).norm()
        minibatch_loss = negative_reward.data.cpu().numpy()
        #pbar.set_description('At epoch: %d  regressor loss: %0.5f' % (epoch, minibatch_loss))
        pbar.set_description('At epoch: %d  regressor loss: %0.5f  reg1: %0.5f' % (epoch, minibatch_loss, negative_reward))
        if optimizer is not None:
            assert len(selected_idx) == cmd_args.batch_size
            optimizer.zero_grad()
            negative_reward.backward()
            optimizer.step()

        total_loss.append( np.array([minibatch_loss]) * len(selected_idx))
        n_samples += len(selected_idx)

    total_loss = np.sum(np.array(total_loss), 0)

    return regressor, total_loss/n_samples, minibatch_loss

random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
cmd_args.num_epochs = 300
if not os.path.exists(cmd_args.regressor_saved_dir):
    os.makedirs(cmd_args.regressor_saved_dir)

sys.path.append('%s/../util/' % os.path.dirname(os.path.realpath('__file__')))
from train_util import Prepare_data
getting_data = Prepare_data(cmd_args)

train_binary_x, train_masks, valid_binary_x, valid_masks, train_y, valid_y = getting_data.load_data()
print('num_train: %d\tnum_valid: %d' % (train_y.shape[0], valid_binary_x.shape[0]))

ae = MolVAE()
if cmd_args.mode == 'gpu':
    ae = ae.cuda()
regressor = Regressor(cmd_args.max_decode_steps, cmd_args.latent_dim)
regressor.cuda()

optimizer_regressor = optim.Adam(regressor.parameters(), lr=cmd_args.learning_rate)
lr_scheduler = ReduceLROnPlateau(optimizer_regressor, 'min', factor=0.5, patience=5, verbose=True, min_lr=0.001)

# load the pretrained vae model
vae_pretrained_model = cmd_args.vanilla_vae_save_dir + '/epoch-best.model'
if vae_pretrained_model  is not None and vae_pretrained_model != '':
        if os.path.isfile(vae_pretrained_model):
            print('loading model from %s' % vae_pretrained_model)
            ae.load_state_dict(torch.load(vae_pretrained_model))

sample_idxes = list(range(train_binary_x.shape[0]))
best_valid_loss = None
for epoch in range(cmd_args.num_epochs):
    random.shuffle(sample_idxes)

    ## update the reggressor:
    regressor, regressor_loss, reg_1= train_regressor('train', epoch, optimizer_regressor, ae, regressor, sample_idxes,  train_binary_x, train_y)
    print('>>>>average regressor \033[92mtraining\033[0m of epoch %d: average loss %.5f, minibatch %.5f' % (epoch, regressor_loss, reg_1))

    if epoch % 1 == 0:
        _, valid_loss, _= train_regressor('valid', epoch,  None, ae,  regressor, list(range(valid_binary_x.shape[0])), valid_binary_x, valid_y)
        print('>>>>average regressor \033[92mtraining\033[0m of epoch %d: average loss %.5f, minibatch %.5f' % (epoch, regressor_loss, reg_1))
        lr_scheduler.step(valid_loss)
        torch.save(regressor.state_dict(), cmd_args.regressor_saved_dir + '/epoch-%d.model' % epoch)

        if best_valid_loss is None or valid_loss < best_valid_loss:
            best_valid_loss = valid_loss
            print('saving to best model since this is the best valid loss so far.----')
            torch.save(regressor.state_dict(), cmd_args.regressor_saved_dir + '/epoch-best.model')


from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.views.generic import CreateView
from django.views.generic import DetailView
from django.views.generic import ListView
from django.views.generic import UpdateView

from hackday.teams.forms import CreateTeamForm
from hackday.teams.forms import UpdateTeamForm
from hackday.teams.models import STATUS
from hackday.teams.models import Team
from hackday.teams.models import TeamCreateStatus

from hackday.assets.models import Attachment
from hackday.assets.models import ImageAttachment
from hackday.assets.models import Link
from hackday.assets.forms import AttachmentForm
from hackday.assets.forms import ImageAttachmentForm
from hackday.assets.forms import LinkAttachmentForm

class TeamListView(ListView):
    model = Team
    queryset = Team.objects.filter(status=STATUS.ACTIVE)

    def get_context_data(self, **kwargs):
        context = super(TeamListView, self).get_context_data(**kwargs)
        try:
            online = TeamCreateStatus.objects.all()[0].online
        except:
            online = True
        context["create_status"] = online
        return context

class TeamDetailView(DetailView):
    model = Team
    queryset = Team.objects.filter(status=STATUS.ACTIVE)

    def get_context_data(self, **kwargs):
        context = super(TeamDetailView, self).get_context_data(**kwargs)
        try:
            online = TeamCreateStatus.objects.all()[0].online
        except:
            online = True
        context["create_status"] = online
        return context

class TeamUpdateView(UpdateView):
    model = Team
    form_class = UpdateTeamForm
    queryset = Team.objects.filter(status=STATUS.ACTIVE)

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        """ If user isn't a team member (or team isn't active),
            redirect to team listing.
        """
        try:
            response = super(TeamUpdateView, self).dispatch(*args, **kwargs)
        except:
            return HttpResponseRedirect(reverse('teams-list'))
        if not self.object.is_member(self.request.user):
            return HttpResponseRedirect(reverse('teams-list'))
        return response

    def form_valid(self, form):
        """ In case the user forgets, add the captain as a team member.
        """
        team = form.save()
        team.add_captain_as_member()

        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': team.slug}))

class TeamCreateView(CreateView):
    model = Team
    form_class = CreateTeamForm

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        """ If team creation is disabled (via admin), redirect.
        """
        try:
            online = TeamCreateStatus.objects.all()[0].online
        except:
            online = True

        if online:
            return super(CreateView, self).dispatch(*args, **kwargs)
        else:
            return render(args[0], 'teams/create_offline.html');

    def form_valid(self, form):
        """ Because team doesn't exist in DB yet, and creator is required,
            we need to first save the form, add creator, and THEN save to DB
        """
        team = form.save(commit=False)
        team.status = STATUS.ACTIVE
        team.creator = self.request.user
        team.save()
        form.save_m2m()
        team.add_captain_as_member()

        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': team.slug}))

def delete(request, slug):
    try:
        team = Team.objects.get(slug=slug)
        if team.is_member(request.user):
            team.status = STATUS.DELETED
            team.save()
            return HttpResponseRedirect(reverse('teams-list'))
        else:
            return HttpResponseRedirect(reverse('teams-detail',
                kwargs={'slug': slug}))
    except:
        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': slug}))

def upload_attachment(request, slug):
    env = {}

    team = Team.objects.get(slug=slug)
    if not team.is_member(request.user):
        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': slug}))

    if request.method == 'POST':
        form = AttachmentForm(request.POST, request.FILES)
        if form.is_valid():
            attachment = Attachment(attached_file = form.cleaned_data['attached_file'],
                                   title = form.cleaned_data['title'],
                                   alt_text = form.cleaned_data['alt_text'])
            attachment.save()
            team.attachments.add(attachment)
            return HttpResponseRedirect(reverse('teams-detail',
                kwargs={'slug': slug}))
    else:
        form = AttachmentForm()

    env['form'] = form
    return render(request, 'teams/upload.html', env)

def remove_attachment(request, slug, attachment_id):
    team = Team.objects.get(slug=slug)
    if team.is_member(request.user):
        attachment = Attachment.objects.get(id=attachment_id)
        team.attachments.remove(attachment)

    return HttpResponseRedirect(reverse('teams-detail',
        kwargs={'slug': slug}))

def upload_image(request, slug):
    env = {}

    team = Team.objects.get(slug=slug)
    if not team.is_member(request.user):
        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': slug}))

    if request.method == 'POST':
        form = ImageAttachmentForm(request.POST, request.FILES)
        if form.is_valid():
            image = ImageAttachment(attached_file = form.cleaned_data['attached_file'],
                                    title = form.cleaned_data['title'],
                                    alt_text = form.cleaned_data['alt_text'])
            image.save()
            team.images.add(image)
            return HttpResponseRedirect(reverse('teams-detail',
                kwargs={'slug': slug}))
    else:
        form = ImageAttachmentForm()

    env['form'] = form
    return render(request, 'teams/upload.html', env)

def remove_image(request, slug, attachment_id):
    team = Team.objects.get(slug=slug)
    if team.is_member(request.user):
        image = ImageAttachment.objects.get(id=attachment_id)
        team.images.remove(image)

    return HttpResponseRedirect(reverse('teams-detail',
        kwargs={'slug': slug}))

def add_link(request, slug):
    env = {}

    team = Team.objects.get(slug=slug)
    if not team.is_member(request.user):
        return HttpResponseRedirect(reverse('teams-detail',
            kwargs={'slug': slug}))

    if request.method == 'POST':
        form = LinkAttachmentForm(request.POST)
        if form.is_valid():
            link = Link(url = form.cleaned_data['url'],
                        title = form.cleaned_data['title'],
                        text = form.cleaned_data['text'])
            link.save()
            team.links.add(link)
            return HttpResponseRedirect(reverse('teams-detail',
                kwargs={'slug': slug}))
    else:
        form = LinkAttachmentForm()

    env['form'] = form
    return render(request, 'teams/upload.html', env)

def remove_link(request, slug, attachment_id):
    team = Team.objects.get(slug=slug)
    if team.is_member(request.user):
        link = Link.objects.get(id=attachment_id)
        team.links.remove(link)

    return HttpResponseRedirect(reverse('teams-detail',
        kwargs={'slug': slug}))


"""
The purpose of this file is to get the robots.txt file some websites have.
This gives the user more information about the website if they wish to scrape it.

@author Travis Hill
"""
import urllib.request
import io

def getRobotsTxt(url):
    if url.endswith('/'):
        path = url
    else:
        path = url + "/"
    req = urllib.request.urlopen(path + "robots.txt", data=None)
    data = io.TextIOWrapper(req, encoding='utf-8')
    return data.read()


#exception handling
#search exception in python
import sys
import logging
#provides various functions and variables that are used to manipulate different parts od python runtime environment

def error_message_detail(error, error_detail:sys):
    _,_,exc_tb=error_detail.exc_info() #info function will give error details
    file_name=exc_tb.tb_frame.f_code.co_filename  #properties inside one another that is available in exception handling documentation
    #search in google custom exception handling
    error_message="Error occured in python script name [{0}] line number [{1}] error message [{2}]".format(
        file_name,exc_tb.tb_lineno,str(error)

    )
    return error_message

'''
explanation given in video: inheriting the parent exception
self is the variable of class. handy keyword allows you to access variables, attributes, and methods of a defined class in Python

'''
class CustomException(Exception):
    def __init__(self,error_message, error_detail:sys):#constructor
        super().__init__(error_message)  #what is happening here
        self.error_message=error_message_detail(error_message,error_detail=error_detail)

    def __str__(self):
        return self.error_message

if __name__=="__main__":
    try:
        a=1/0
    except Exception as e:
        logging.info("Divide by zero  ")
        raise CustomException(e, sys)


class WARCRecord:
    def __init__(self, warc_id: str, data_length: str, record_type: str, subject_uri: str,
                 creation_date: str, content_type: str, record_id: str) -> None:
        self.warc_id = warc_id
        self.data_length = int(data_length)
        self.record_type = record_type
        self.subject_uri = subject_uri
        self.creation_data = creation_date
        self.content_type = content_type
        self.record_id = record_id

    def print(self) -> None:
        print("Record: {{ warc-id: {}, data-length: {}, record-type: {}, subject-uri: {} }}"
                     .format(self.warc_id, self.data_length, self.record_type, self.subject_uri))


"""event.py - Event handling (keyboard, mouse, etc.) for the main window.
"""

import urllib
import gtk
import gtk.gdk

from mcomix.preferences import prefs
from mcomix import constants
from mcomix import portability
from mcomix import keybindings

class EventHandler:

    def __init__(self, window):
        self._window = window

        self._last_pointer_pos_x = 0
        self._last_pointer_pos_y = 0
        self._pressed_pointer_pos_x = 0
        self._pressed_pointer_pos_y = 0

        #: For scrolling "off the page".
        self._extra_scroll_events = 0

    def resize_event(self, widget, event):
        """Handle events from resizing and moving the main window."""
        if not self._window.is_fullscreen:
            prefs['window x'], prefs['window y'] = self._window.get_position()

        if (event.width != self._window.width or
            event.height != self._window.height):

            if not self._window.is_fullscreen:
                prefs['window width'] = event.width
                prefs['window height'] = event.height

            self._window.width = event.width
            self._window.height = event.height
            self._window.draw_image()

    def register_key_events(self):
        """ Registers keyboard events and their default binings, and hooks
        them up with their respective callback functions. """

        manager = keybindings.keybinding_manager()

        # Navigation keys that work in addition to the accelerators in ui.py
        manager.register('previous page',
            ['KP_Page_Up', 'BackSpace', '<Mod1>Left'],
            self._window.previous_page)
        manager.register('next page',
            ['KP_Page_Down', '<Mod1>Right'],
            self._window.next_page)

        # Numpad (without numlock) aligns the image depending on the key.
        manager.register('scroll left bottom',
            ['KP_1'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'left', 'vert':'bottom'})
        manager.register('scroll middle bottom',
            ['KP_2'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'middle', 'vert':'bottom'})
        manager.register('scroll right bottom',
            ['KP_3'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'right', 'vert':'bottom'})

        manager.register('scroll left middle',
            ['KP_4'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'left', 'vert':'middle'})
        manager.register('scroll middle',
            ['KP_5'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'middle', 'vert':'middle'})
        manager.register('scroll right middle',
            ['KP_6'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'right', 'vert':'middle'})

        manager.register('scroll left top',
            ['KP_7'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'left', 'vert':'top'})
        manager.register('scroll middle top',
            ['KP_8'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'middle', 'vert':'top'})
        manager.register('scroll right top',
            ['KP_9'],
            self._window.scroll_to_fixed,
            kwargs={'horiz':'right', 'vert':'top'})

        # Enter/exit fullscreen.
        manager.register('exit fullscreen',
            ['Escape'],
            self._window.actiongroup.get_action('fullscreen').set_active,
            args=(False,))
        manager.register('toggle fullscreen',
            ['F11'],
            self._window.actiongroup.get_action('fullscreen').activate)

        # Zooming commands for manual zoom mode
        manager.register('zoom in',
            ['plus', 'equal'],
            self._window.actiongroup.get_action('zoom_in').activate)
        manager.register('zoom out',
            ['minus'],
            self._window.actiongroup.get_action('zoom_out').activate)
        manager.register('zoom original',
            ['<Control>0', '<Control>KP_0'],
            self._window.actiongroup.get_action('zoom_original').activate)

        # Arrow keys scroll the image
        manager.register('scroll down',
            ['Down', 'KP_Down', 'j'],
            self._scroll_down)
        manager.register('scroll up',
            ['Up', 'KP_Up', 'k'],
            self._scroll_up)
        manager.register('scroll right',
            ['Right', 'KP_Right', 'l'],
            self._scroll_right)
        manager.register('scroll left',
            ['Left', 'KP_Left', 'h'],
            self._scroll_left)

        # Space key scrolls down a percentage of the window height or the
        # image height at a time. When at the bottom it flips to the next
        # page.
        #
        # It also has a "smart scrolling mode" in which we try to follow
        # the flow of the comic.
        #
        # If Shift is pressed we should backtrack instead.
        manager.register('smart scroll down',
            ['space'],
            self._smart_scroll_down)
        manager.register('smart scroll up',
            ['<Shift>space'],
            self._smart_scroll_up)

        # OSD Display
        manager.register('osd panel',
            ['Tab'],
            self._window.show_info_panel)

    def key_press_event(self, widget, event, *args):
        """Handle key press events on the main window."""

        # Dispatch keyboard input handling
        manager = keybindings.keybinding_manager()
        manager.execute((event.keyval, event.state))

        # ---------------------------------------------------------------
        # Register CTRL for scrolling only one page instead of two
        # pages in double page mode
        # ---------------------------------------------------------------
        if event.keyval in (gtk.keysyms.Control_L, gtk.keysyms.Control_R):
            self._window.imagehandler.force_single_step = True

        # ----------------------------------------------------------------
        # We kill the signals here for the Up, Down, Space and Enter keys,
        # or they will start fiddling with the thumbnail selector (bad).
        # ----------------------------------------------------------------
        if (event.keyval in (gtk.keysyms.Up, gtk.keysyms.Down,
          gtk.keysyms.space, gtk.keysyms.KP_Enter, gtk.keysyms.KP_Up,
          gtk.keysyms.KP_Down, gtk.keysyms.KP_Home, gtk.keysyms.KP_End,
          gtk.keysyms.KP_Page_Up, gtk.keysyms.KP_Page_Down) or
          (event.keyval == gtk.keysyms.Return and not
          'GDK_MOD1_MASK' in event.state.value_names)):

            self._window.emit_stop_by_name('key_press_event')
            return True

    def key_release_event(self, widget, event, *args):
        """ Handle release of keys for the main window. """

        # ---------------------------------------------------------------
        # Unregister CTRL for scrolling only one page in double page mode
        # ---------------------------------------------------------------
        if event.keyval in (gtk.keysyms.Control_L, gtk.keysyms.Control_R):
            self._window.imagehandler.force_single_step = False

    def scroll_wheel_event(self, widget, event, *args):
        """Handle scroll wheel events on the main layout area. The scroll
        wheel flips pages in best fit mode and scrolls the scrollbars
        otherwise.
        """
        if 'GDK_BUTTON2_MASK' in event.state.value_names:
            return

        if event.direction == gtk.gdk.SCROLL_UP:

            if prefs['zoom mode'] == constants.ZOOM_MODE_BEST:
                self._window.previous_page()

            elif prefs['zoom mode'] == constants.ZOOM_MODE_HEIGHT:

                if self._window.is_manga_mode:
                    self._scroll_with_flipping(prefs['number of pixels to scroll per mouse wheel event'], 0)
                else:
                    self._scroll_with_flipping(-prefs['number of pixels to scroll per mouse wheel event'], 0)

            else:
                self._scroll_with_flipping(0, -prefs['number of pixels to scroll per mouse wheel event'])

        elif event.direction == gtk.gdk.SCROLL_DOWN:

            if prefs['zoom mode'] == constants.ZOOM_MODE_BEST:
                self._window.next_page()

            elif prefs['zoom mode'] == constants.ZOOM_MODE_HEIGHT:

                if self._window.is_manga_mode:
                    self._scroll_with_flipping(-prefs['number of pixels to scroll per mouse wheel event'], 0)
                else:
                    self._scroll_with_flipping(prefs['number of pixels to scroll per mouse wheel event'], 0)
            else:
                self._scroll_with_flipping(0, prefs['number of pixels to scroll per mouse wheel event'])

        elif event.direction == gtk.gdk.SCROLL_RIGHT:
            self._window.next_page()

        elif event.direction == gtk.gdk.SCROLL_LEFT:
            self._window.previous_page()

    def mouse_press_event(self, widget, event):
        """Handle mouse click events on the main layout area."""

        if event.button == 1:
            self._pressed_pointer_pos_x = event.x_root
            self._pressed_pointer_pos_y = event.y_root
            self._last_pointer_pos_x = event.x_root
            self._last_pointer_pos_y = event.y_root

        elif event.button == 2:
            self._window.actiongroup.get_action('lens').set_active(True)

        elif event.button == 3 and not event.state & gtk.gdk.MOD1_MASK:
            self._window.cursor_handler.set_cursor_type(constants.NORMAL_CURSOR)
            self._window.popup.popup(None, None, None, event.button,
                event.time)

        elif event.button == 4:
            self._window.show_info_panel()

    def mouse_release_event(self, widget, event):
        """Handle mouse button release events on the main layout area."""

        self._window.cursor_handler.set_cursor_type(constants.NORMAL_CURSOR)

        if (event.button == 1):

            if event.x_root == self._pressed_pointer_pos_x and \
                event.y_root == self._pressed_pointer_pos_y and \
                not self._window.was_out_of_focus:
                self._window.next_page()

            else:
                self._window.was_out_of_focus = False

        elif event.button == 2:
            self._window.actiongroup.get_action('lens').set_active(False)

        elif event.button == 3 and event.state & gtk.gdk.MOD1_MASK:
            self._window.previous_page()

    def mouse_move_event(self, widget, event):
        """Handle mouse pointer movement events."""

        if not self._window.is_in_focus:
            self._window.was_out_of_focus = True
        else:
            self._window.was_out_of_focus = False

        event = _get_latest_event_of_same_type(event)

        if 'GDK_BUTTON1_MASK' in event.state.value_names:
            self._window.cursor_handler.set_cursor_type(constants.GRAB_CURSOR)
            self._window.scroll(self._last_pointer_pos_x - event.x_root,
                                self._last_pointer_pos_y - event.y_root)
            self._last_pointer_pos_x = event.x_root
            self._last_pointer_pos_y = event.y_root
            self._drag_timer = event.time

        else:
            self._window.cursor_handler.refresh()

    def drag_n_drop_event(self, widget, context, x, y, selection, drag_id,
      eventtime):
        """Handle drag-n-drop events on the main layout area."""
        # The drag source is inside MComix itself, so we ignore.

        if (context.get_source_widget() is not None):
            return

        uris = selection.get_uris()

        if not uris:
            return

        # Normalize URIs
        uris = [ portability.normalize_uri(uri) for uri in uris ]
        paths = [ urllib.url2pathname(uri).decode('utf-8') for uri in uris ]

        if len(paths) > 1:
            self._window.filehandler.open_file(paths)
        else:
            self._window.filehandler.open_file(paths[0])

    def _scroll_with_flipping(self, x, y):
        """Handle scrolling with the scroll wheel or the arrow keys, for which
        the pages might be flipped depending on the preferences.  Returns True
        if able to scroll without flipping and False if a new page was flipped
        to.
        """

        if self._window.scroll(x, y) or not prefs['flip with wheel']:
            self._extra_scroll_events = 0

            return True

        if y > 0 or (self._window.is_manga_mode and x < 0) or (
          not self._window.is_manga_mode and x > 0):
            forwards_scroll = True

        else:
            forwards_scroll = False

        if forwards_scroll:
            self._extra_scroll_events = max(1, self._extra_scroll_events + 1)

            if self._extra_scroll_events >= prefs['number of key presses before page turn']:
                self._extra_scroll_events = 0
                self._window.next_page()

                return False

            return True
        else:
            self._extra_scroll_events = min(-1, self._extra_scroll_events - 1)

            if self._extra_scroll_events <= -prefs['number of key presses before page turn']:
                self._extra_scroll_events = 0

                self._window.previous_page()

                return False

            return True

    def _scroll_down(self):
        """ In best fit mode, skip right to the  next page. In other modes,
        scroll first. """
        if not prefs['zoom mode'] == constants.ZOOM_MODE_BEST:
            self._scroll_with_flipping(0, prefs['number of pixels to scroll per key event'])
        else:
            self._window.next_page()

    def _scroll_up(self):
        """ In best fit mode, skip right to the  previous page. In other modes,
        scroll first. """
        if not prefs['zoom mode'] == constants.ZOOM_MODE_BEST:
            self._scroll_with_flipping(0, -prefs['number of pixels to scroll per key event'])
        else:
            self._window.previous_page()

    def _scroll_right(self):
        """ In best fit mode, skip right to the  next page. In other modes,
        scroll first. """
        if not prefs['zoom mode'] == constants.ZOOM_MODE_BEST:
            self._scroll_with_flipping(prefs['number of pixels to scroll per key event'], 0)
        else:
            self._window.next_page()

    def _scroll_left(self):
        """ In best fit mode, skip right to the  previous page. In other modes,
        scroll first. """
        if not prefs['zoom mode'] == constants.ZOOM_MODE_BEST:
            self._scroll_with_flipping(-prefs['number of pixels to scroll per key event'], 0)
        else:
            self._window.previous_page()

    def _smart_scroll_down(self):
        """ Smart scrolling. """

        x_step, y_step = self._window.get_visible_area_size()
        x_step = int(x_step * 0.9)
        y_step = int(y_step * 0.9)

        if self._window.is_manga_mode:
            x_step *= -1

        if not prefs["smart space scroll"]:
            if (prefs['zoom mode'] == constants.ZOOM_MODE_BEST or
                not self._window.scroll(0, y_step)):
                self._window.next_page()
            return

        if self._window.displayed_double():
            if self._window.is_on_first_page():

                if not self._window.scroll(x_step, 0, 'first'):

                    if not self._window.scroll(0, y_step):

                        if not self._window.scroll_to_fixed(
                          horiz='startsecond'):
                            self._window.next_page()
                        else:
                            self._window.scroll_to_fixed(
                                    vert='top')

                    else:

                        self._window.scroll_to_fixed(
                            horiz='startfirst')
            else:

                if not self._window.scroll(x_step, 0, 'second'):

                    if not self._window.scroll(0, y_step):
                        self._window.next_page()
                    else:
                        self._window.scroll_to_fixed(
                            horiz='startsecond')
        else:
            # When a double page is displayed, scroll left/right,
            # then top/bottom
            if not prefs['invert smart scroll']:
                if not self._window.scroll(x_step, 0):

                    if not self._window.scroll(0, y_step):
                        self._window.next_page()
                    else:
                        self._window.scroll_to_fixed(
                            horiz='startfirst')
            # Scroll top/bottom, then left/right
            else:
                if not self._window.scroll(0, y_step):
                    if not self._window.scroll(x_step, 0):
                        self._window.next_page()
                    else:
                        self._window.scroll_to_fixed(
                            horiz='startsecond', vert='top')

    def _smart_scroll_up(self):
        """ Reversed smart scrolling. """

        x_step, y_step = self._window.get_visible_area_size()
        x_step = int(x_step * 0.9)
        y_step = int(y_step * 0.9)

        if self._window.is_manga_mode:
            x_step *= -1

        if not prefs["smart space scroll"]:
            if (prefs['zoom mode'] == constants.ZOOM_MODE_BEST or
                not self._window.scroll(0, -y_step)):
                self._window.previous_page()
            return

        if self._window.displayed_double():
            if self._window.is_on_first_page():

                if not self._window.scroll(-x_step, 0, 'first'):

                    if not self._window.scroll(0, -y_step):
                        self._window.previous_page()
                    else:
                        self._window.scroll_to_fixed(
                            horiz='endfirst')

            else:
                if not self._window.scroll(-x_step, 0, 'second'):

                    if not self._window.scroll(0, -y_step):

                        if not self._window.scroll_to_fixed(
                          horiz='endfirst'):
                            self._window.previous_page()

                        else:
                            self._window.scroll_to_fixed(
                                vert='bottom')

                    else:
                        self._window.scroll_to_fixed(
                            horiz='endsecond')
        else:
            # When a double page is displayed, scroll left/right,
            # then top/bottom
            if not prefs['invert smart scroll']:
                if not self._window.scroll(-x_step, 0):

                    if not self._window.scroll(0, -y_step):
                        self._window.previous_page()
                    else:
                        self._window.scroll_to_fixed(horiz='endfirst')
            # Scroll top/bottom, then left/right
            else:
                if not self._window.scroll(0, -y_step):
                    if not self._window.scroll(-x_step, 0):
                        self._window.previous_page()
                    else:
                        self._window.scroll_to_fixed(
                            horiz='startfirst', vert='bottom')

def _get_latest_event_of_same_type(event):
    """Return the latest event in the event queue that is of the same type
    as <event>, or <event> itself if no such events are in the queue. All
    events of that type will be removed from the event queue.
    """
    events = []

    while gtk.gdk.events_pending():
        queued_event = gtk.gdk.event_get()

        if queued_event is not None:

            if queued_event.type == event.type:
                event = queued_event
            else:
                events.append(queued_event)

    for queued_event in events:
        queued_event.put()

    return event

# vim: expandtab:sw=4:ts=4


input_file = open('input.txt')
output_file = open('output.txt', 'w')
line = input_file.readline()
while line:
    line = line.replace('\n', '')
    #line = line.replace('\xe2\x80\x93', '-')
    #output_file.write("Input:\n{}\n".format(line))
    line = line.split(' ')
    result = {
        'author': '',
        'year': '',
        'title': '',
        'journal': '',
        'volume': '',
        'issue': '',
        'pages': ''
    }
    check = {
        'author': 0,
        'year': 0,
        'title': 0,
        'journal': 0,
        'volume': 0,
        'pages': 0
    }
    for i in xrange(len(line)):
        text = line[i]
        if check['author'] == 0:
            if text[0:-1].isdigit():
                check['author'] = 1
            elif line[i+1][-1] == ':' or (i+2 < len(line) and line[i+2][-1] == ':') and text[-1] == ',':
                result['author'] += text
                check['author'] = 1
            else:
                result['author'] += text
                if text[-1] == '.' and '.' not in result['author'][0:-1] and len(result['author']) > 2:
                    result['author'] = result['author'][:-1]
                    check['author'] = 1
                elif 'and' in result['author'] and result['author'][-1] ==',':
                    result['author'] = result['author'][:-1]
                    check['author'] = 1
                else:
                    result['author'] += ' '
        elif check['year'] == 0 and len(text[:-1]) == 4 and text[:-1].isdigit():
            result['year'] = text[:-1]
            check['year'] = 1
        elif check['title'] == 0:
            result['title'] += text
            if text[-1] == '.' or line[i+1] == 'vol.' or line[i+1] == 'pp.' or line[i+1] == 'In':
                result['title'] = result['title']
                check['title'] = 1
            else:
                result['title'] += ' '
        elif check['journal'] == 0 and line[i] != 'pp.' and line[i] != 'vol.':
            result['journal'] += text
            if text[-1] == '.' or line[i+1].isdigit() or line[i+1][0:-1].isdigit() or line[i+1] == 'pp.' or line[i+1] == 'vol.':
                result['journal'] = result['journal'][:-1]
                check['journal'] = 1
            else:
                result['journal'] += ' '
        elif check['volume'] == 0 and text != 'pp.':
            check['journal'] = 1
            if text == 'Vol' or text == 'vol.':
                i += 1
                result['volume'] = line[i]
                if not result['volume'].isdigit():
                    result['volume'] = result['volume'][:-1]
                check['volume'] = 1
                i += 1
                text = line[i]
                if line[i] == 'No.' or line[i] == 'no.':
                    i += 1
                    result['issue'] = line[i][0:-1]
            elif text.isdigit() and line[i+1][0] == '(':
                result['volume'] = text
                i += 1
                text = line[i]
                if text[0] == '(' and text[-1] == ',':
                    result['issue'] = text[1:-2]
                check['volume'] = 1
        elif check['pages'] == 0:
            check['volume'] = 1
            if text == 'pages' or text == 'pp.':
                i += 1
                text = line[i]
                result['pages'] = text[0:-1]
                check['pages'] = 1
            elif text[0] =='e':
                result['pages'] = text[0:-1]
                check['pages'] = 1
    if 'In' in result['journal'][0:2]:
        result['book-title'] = result['journal']
        result['book-title'] = result['book-title'].split(',')[0]
        result['journal'] = ''
    if len(result['title'].split(",")) > 1:
        result['publisher'] = result['title'].split(",")[1]
        if 'Communications' not in result['publisher']:
            result['publisher'] = ""
    if "Media" in result['journal']:
        result['publisher'] = result['journal']
        result['journal'] = ""
    result['title'] = result['title'].split(",")[0]
    result['title'] = result['title'].replace('"', '')
    output_file.write("Output:\n")
    for i in result:
        if result[i]:
            output_file.write("{}: {}\n".format(i, result[i]))
    output_file.write("\n")
    line = input_file.readline()