from random import choice, randint
from ortools.sat.python import cp_model
from itertools import product

AdjList = dict[int, list[int]]

def solve(
    width: int,
    height: int,
    left_adj: AdjList,
    right_adj: AdjList,
    up_adj: AdjList,
    down_adj: AdjList,
    weights: dict[int, int]
) -> list[list[int]]:
    tiles = left_adj.keys()

    model = cp_model.CpModel()
    has_tile = {}
    for row, col in product(range(height), range(width)):
        for tile in tiles:
            has_tile[row, col, tile] = model.NewBoolVar(f'has_tile{row, col, tile}')

    # One tile per position
    for row, col in product(range(height), range(width)):
        model.Add(
            sum(has_tile[row, col, tile] for tile in tiles) == 1
        )

    # Use all tiles
    for tile in tiles:
        model.Add(
            sum(
                has_tile[row, col, tile]
                for row, col in product(range(height), range(width))
            )   >= 1
        )

    # Adjacency constraints
    for row, col in product(range(height), range(width)):
        for tile in tiles:
            # left
            if col > 0:
                left_adj_satisfied = model.NewBoolVar('')
                model.AddImplication(has_tile[row, col, tile], left_adj_satisfied)

                model.AddBoolOr([
                    has_tile[row, col-1, adj_tile] for adj_tile in left_adj[tile]
                ]).OnlyEnforceIf(left_adj_satisfied)

            # right
            if col < width-1:
                right_adj_satisfied = model.NewBoolVar('')
                model.AddImplication(has_tile[row, col, tile], right_adj_satisfied)

                model.AddBoolOr([
                    has_tile[row, col+1, adj_tile] for adj_tile in right_adj[tile]
                ]).OnlyEnforceIf(right_adj_satisfied)

            # up
            if row > 0:
                up_adj_satisfied = model.NewBoolVar('')
                model.AddImplication(has_tile[row, col, tile], up_adj_satisfied)

                model.AddBoolOr([
                    has_tile[row-1, col, adj_tile] for adj_tile in up_adj[tile]
                ]).OnlyEnforceIf(up_adj_satisfied)

            # down
            if row < height-1:
                down_adj_satisfied = model.NewBoolVar('')
                model.AddImplication(has_tile[row, col, tile], down_adj_satisfied)

                model.AddBoolOr([
                    has_tile[row+1, col, adj_tile] for adj_tile in down_adj[tile]
                ]).OnlyEnforceIf(down_adj_satisfied)

    # random hinting for artistic value
    for row, col in product(range(height), range(width)):
        if randint(0, 10) == 0:
            model.AddHint(has_tile[row, col, choice(list(tiles))], 1)

    score = 0
    for tile in list(tiles)[1:]:
        times_used = sum(
            has_tile[row, col, tile]
            for row, col in product(range(height), range(width))
        )
        diff = model.NewIntVar(-width * height, width * height, '')
        abs_diff = model.NewIntVar(0, width * height, '')
        model.Add(diff == times_used - weights[tile])
        model.AddAbsEquality(abs_diff, diff)
        score += abs_diff

    model.Minimize(score)

    solver = cp_model.CpSolver()
    solver.parameters.max_time_in_seconds = 60
    code = solver.Solve(model)
    if code in [cp_model.FEASIBLE, cp_model.OPTIMAL]:
        print('Score:', solver.Value(score))
        output_grid = [[None] * width for _ in range(height)]
        for row, col in product(range(height), range(width)):
            for tile in tiles:
                if solver.Value(has_tile[row, col, tile]):
                    output_grid[row][col] = tile

        return output_grid

    elif code == cp_model.UNKNOWN:
        raise ValueError('Timed out before a solution was found.')

    raise ValueError('No solution!')


#method 1
def char_frequency(str1):
    dict = {}
    for n in str1:
        keys = dict.keys()
        print(n, " keys: " , keys)
        if n in keys:
            dict[n] += 1
        else:
            dict[n] = 1
    return dict

#method two with collections
s="abcv"
from collections import Counter
counts = Counter(s) #dictionary
# for i in s:
#   print(i,counts[i])
print(counts)

print(char_frequency("abac"))


"""
Test utils functions
"""
import numpy as np
from utils import *
import cvxopt

X = np.random.rand(10,3)

print(X)
Xnorm = normalize(X, -1,2)
print("normalized X:", Xnorm)
Xstandard = standardize(X)
print("standardized X: ", Xstandard)

Xint = np.random.randint(10, size=(10, 3))
print(Xint)
linear_kernel = linear_kernel()
print("linear kernel:", linear_kernel(Xint[0],Xint[1]))

poly_kernel = polynomial_kernel(power=2, coef=1.)
print("2nd order polynomia kernel:", poly_kernel(Xint[0],Xint[1]))

rbf_kernel = rbf_kernel(gamma=0.1)
print("rbf kernel:", rbf_kernel(Xint[0],Xint[1]))

Xint2 = np.random.randint(5, size=(2, 2))
print(Xint2)
print("covariance matrix: ", calculate_covariance_matrix(Xint2))

"""
CVXOPT
solving a linear program:
minimize c*X subject to A*x <= b
Here: minimize y = 2*x1 + x2
subject to:
-x1 + x2 <= 1
-x1 - x2 <= -2
-x2 <= 0
x1 - 2*x2 <= 4
"""
from cvxopt import matrix, solvers
# made up by 2 columns of coefficient with x1, x2....
A = matrix([[-1.0, -1.0, 0.0, 1.0], [1.0, -1.0, -1.0, -2.0]])
print("A: ", A)

b = matrix([ 1.0, -2.0, 0.0, 4.0 ])
print("b: ", b)

c = matrix([2.0, 1.0])
lin_sol = solvers.lp(c, A, b)
print("optimal solution of x: ", lin_sol['x'])
# print(lin_sol)
print("optimal solution of y: ", lin_sol['primal objective'])

"""
CVXOPT
solving a nonlinear/quadratic program:
minimize 1/2* xT * P * x + qT * x subject to G*x <= h and A*x = b
convex if and only if P is PSD
 P and q are required, the others are optional
Here: minimize y = 1/2*x1^2 + 3*x1 + 4*x2
subject to:
-x1 <= 0
-x2 <= 0
-x1-3*x2 <=-15
2*x1+5*y2 <= 100
3*x1 + 4*x2 <= 80
x1+x2 = 5

"""
# Define QP parameters (directly)
Q = matrix([[1.0, 0.0], [0.0, 0.0]])
p = matrix([3.0, 4.0])

G = matrix([[-1.0, 0.0, -1.0, 2.0, 3.0], [0.0, -1.0, -3.0, 5.0, 4.0]])
h = matrix([0.0, 0.0, -15.0, 100.0, 80.0])
A = matrix([1.0, 1.0], (1, 2))
b = matrix(5.0)

# Define QP parameters (with NumPy)
# P = matrix(np.diag([1,0]), tc='d')
# q = matrix(np.array([3.0, 4.0]), tc='d')
# G = matrix(np.array([[-1,0],[0,-1],[-1,-3],[2,5],[3,4]]), tc='d')
# h = matrix(np.array([0,0,-15,100,80]), tc='d')

quad_sol = solvers.qp(Q, p, G, h, A, b)

"""
minimize 1/2* xT * Q * x + pT * x subject to G*x <= h and A*x = b
Here: minimize y =2*x1^2 + x2^2 + x1*x2 + x1 + x2
subject to:
-x1 <= 0
-x2 <= 0
x1+x2 = 1
"""
Q = 2*matrix([[2, .5], [.5, 1]])
p = matrix([1.0, 1.0])
G = matrix([[-1.0, 0.0], [0.0, -1.0]])
h = matrix([0.0, 0.0])
A = matrix([1.0, 1.0], (1, 2))
b = matrix(1.0)
quad_sol2 = solvers.qp(Q, p, G, h, A, b)

print("optimal solution of x: ", quad_sol2['x'])
# print(quad_sol2)
print("optimal solution of y: ", quad_sol2['primal objective'])


import datetime
current_date = datetime.datetime.now()
year = current_date.year
print(year)
year_= str(year)

sum_ = 0
for i in year_:
	print(i)
	sum_ += int(i)

print(sum_)

text = "a1a1"

count_num = 0
count_let = 0
for num_ in text:
	if num_.isdigit():
	    count_num += 1
	elif num_.isalpha():
	    count_let +=1
print(count_num)
print(count_let)

count_num1 = 0

for i in text:
	if i.isdigit():
		count_num1 +=1
	else:
	    print("couldnt fine")
	    #continue
	    break
	print("Ive founde one more number")

sum_= 0

for nun_2 in range(1,21):
	if nun_2 == 3 and nun_2 == 13:
		continue

	sum_ += nun_2


from django.core.files.uploadedfile import InMemoryUploadedFile
import base64,re,sys, datetime
from PIL import Image
from io import BytesIO
from rest_framework import serializers

def base64ToImage(base64_image_data):
    try:
        buffer_plot = BytesIO()
        base64_data = re.sub('^data:image/.+;base64,', '', base64_image_data)
        binary_data = base64.b64decode(base64_data)
        img_data = BytesIO(binary_data)
        img = Image.open(img_data)
        try:
            img.save(buffer_plot, format='PNG', quality=100)
        except:
            img.save(buffer_plot, format='JPEG', quality=100)
        buffer_plot.seek(0)
        return InMemoryUploadedFile(buffer_plot, 'ImageField',f'''{datetime.datetime.now().strftime("%d%m%y%H%M%S%f")}.png''','image/png',sys.getsizeof(buffer_plot), None)
    except Exception as e:
        raise serializers.ValidationError({"image":f"{e}"})


'''
fish block
'''

pos_neg_fish = '''На {} положительно влияет {} атмосферного давления, а его {} может негативно повлиять на активность рыбы. '''

pos_fish = '''{} атмосферного давления благоприятно влияет на клев {}. '''

neg_fish = '''{} атмосферного давления может негативно повлиять на клев {}. '''

none_fish = '''На данный момент недостаточно изучено, как именно влияет изменения атмосферного давления на клев {}. '''

'''
desc block
'''

hard_low_desc = '''{} ожидается резкий спад атмосферного давления. '''

hard_low_desc_no = '''{} резких спадов атмосферного давления не ожидается. '''

hard_up_desc = '''{} прогнозируется резкий рост атмосферного давления. '''

hard_up_desc_no = '''За период {} резкого роста атмосферного давления не прогнозируется. '''

minmax_desc = '''Минимальное значение атмосферного давления в течение - {}, максимальное - {}. '''

ten_minmax_desc = '''{} прогнозируется минимальное значение атмосферного давления - {}, а {} ожидается максимальная - {}. '''

'''
utils
'''

from ..helper.date import get_dates_by_intervals

def hard_dates(pressures, dates, tag):
    subs = []
    for i in range(1, len(pressures)):
        subs.append(pressures[i] - pressures[i - 1])
    if tag == 'low':
        mask_subs = [1 if sub <= -3 else 0 for sub in subs]
    elif tag == 'up':
        mask_subs = [1 if sub >= 3 else 0 for sub in subs]
    if sum(mask_subs) == 0:
        return None
    intervals = []
    current = [-1, -1]
    max_sub = 0
    for i in range(len(mask_subs)):
        if mask_subs[i]:
            max_sub = max(max_sub, abs(subs[i]))
            if current[0] == -1:
                current[0] = i
            current[1] = i + 1
        else:
            if not current[0] == -1:
                intervals.append((subs[i], (current[0], current[1])))
            current[0] = -1
    if not current[0] == -1:
        intervals.append((max_sub, (current[0], current[1])))
    if len(intervals) == 0:
        return None
    top_interval = [max(intervals, key=lambda x: x[0])[1]]
    return get_dates_by_intervals(dates, top_interval)


'''
About dialog initialization
'''
from datetime import datetime
import os

from .constants import NAME, VERSION

from PyQt5.QtGui import QFont, QPixmap
from PyQt5.QtWidgets import (QDialog,
                             QLabel,
                             QVBoxLayout,
                             QHBoxLayout)

class AboutMenu(QDialog):
    def __init__(self):
        '''
        About dialog initialization
        '''
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setFixedSize(600, 200)
        name_font = QFont()
        name_font.setPointSize(16)
        name_font.setBold(True)

        version_font = QFont()
        version_font.setPointSize(11)

        copyright_font = QFont()
        copyright_font.setPointSize(8)
        copyright_font.setBold(True)

        daze_logo = QLabel(self)
        daze_logo_path = QPixmap(os.path.join(os.path.dirname(__file__),
                                              'icons',
                                              'daze_logo.png'))
        daze_logo.setPixmap(daze_logo_path)
        name_message = QLabel(self)
        name_message.setFont(name_font)
        version_message = QLabel(self)
        version_message.setFont(version_font)
        info_message = QLabel(self)
        copyright_message = QLabel(self)
        copyright_message.setFont(copyright_font)

        vbox = QVBoxLayout()
        vbox.addWidget(name_message)
        vbox.addWidget(version_message)
        vbox.addWidget(info_message)
        vbox.addWidget(copyright_message)

        hbox = QHBoxLayout()
        hbox.addLayout(vbox)
        hbox.addWidget(daze_logo)
        self.setLayout(hbox)

        name_msg = '{}'.format(NAME)

        version_msg = 'Version {}'.format(VERSION)

        info_msg = '''
            Daze is not responsible for illegal downloads of any content
            that violate the terms and services agreement of any kind.
            '''

        copyright_msg = ('Copyright (c) {} Shahbaz Khan. All Rights '
                         'Reserved'.format(datetime.today().year))

        name_message.setText(name_msg)
        version_message.setText(version_msg)
        info_message.setText(info_msg)
        copyright_message.setText(copyright_msg)


"""
PyTorch implementation of original Parapred architecture.
"""
from __future__ import print_function
from torch.autograd import Variable
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.utils.rnn import pad_packed_sequence, pack_padded_sequence

from constants import *

class AbSeqModel(nn.Module):
    def __init__(self):
        """
        Parapred's building blocks.
        """
        super(AbSeqModel, self).__init__()
        # kernel
        self.conv1 = nn.Conv1d(NUM_FEATURES, NUM_FEATURES, 3, padding=1)
        self.elu = nn.ELU()
        self.dropout1 = nn.Dropout(0.15)
        self.bidir_lstm = nn.LSTM(NUM_FEATURES, 256, bidirectional=True)
        self.dropout2 = nn.Dropout(0.3)
        self.fc = nn.Conv1d(512, 1, 1)

        for m in self.modules():
            self.weights_init(m)

    def weights_init(self, m):
        """
        Parameter initialisation for Parapred architecture. Xavier and orthogonal are used, depending on layer.
        :param m:
        :return:
        """
        if isinstance(m, nn.Conv1d):
            torch.nn.init.xavier_uniform(m.weight.data)
            m.bias.data.fill_(0.0)
        if isinstance(m, nn.LSTM):
            torch.nn.init.xavier_uniform(m.weight_ih_l0)
            torch.nn.init.orthogonal(m.weight_hh_l0)
            for names in m._all_weights:
                for name in filter(lambda n: "bias" in n, names):
                    bias = getattr(m, name)
                    n = bias.size(0)
                    start, end = n // 4, n // 2
                    bias.data[start:end].fill_(1.0)
            m.bias_ih_l0.data.fill_(0.0)

    def forward(self, input, unpacked_masks, masks, lengths):
        """
        Performing forward propagation
        :param input: antibody amino acid sequences
        :param unpacked_masks:
        :param masks:
        :param lengths:
        :return: binding probabilities for antibody amino acids.
        """
        initial = input
        x = input

        x = torch.transpose(x, 1, 2)
        x = self.conv1(x)
        x = torch.transpose(x, 1, 2)

        x = torch.mul(x, unpacked_masks)
        x = self.elu(x)

        x = x + initial

        x = self.dropout1(x)

        packed_input = pack_padded_sequence(x, lengths, batch_first=True)
        output, hidden = self.bidir_lstm(packed_input)
        x, _ = pad_packed_sequence(output, batch_first=True)
        print("after lstm", x.data, file=print_file)  # 32x32x512

        x = self.dropout2(x)

        x = torch.transpose(x, 1, 2)
        x = self.fc(x)
        x = torch.transpose(x, 1, 2)

        x = torch.mul(x, masks)
        return x


import gym
import torch as th
import numpy as np
import torch.nn as nn
import torch.nn.functional as F

lr = 0.001
gamma = 0.9
hidden = 32
env = gym.make('CartPole-v0')
device = "cpu"
env = env.unwrapped
n_action = env.action_space.n
n_state = env.observation_space.shape[0]

class actor(nn.Module):  # policy net
    def __init__(self):
        super(actor, self).__init__()
        self.fc1 = nn.Linear(n_state, hidden)
        self.fc2 = nn.Linear(hidden, n_action)
        self.softmax = nn.Softmax(dim=0)

    def forward(self, x):
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        prob = self.softmax(x)
        return prob

class critic(nn.Module):  # Q net
    def __init__(self):
        super(critic, self).__init__()
        self.fc1 = nn.Linear(n_state, hidden)
        self.fc2 = nn.Linear(hidden, 1)

    def forward(self, x):
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        return x

class AC():
    def __init__(self):
        self.actor = actor().to(device)
        self.critic = critic().to(device)

        self.Aoptimizer = th.optim.Adam(self.actor.parameters(), lr=lr)
        self.Coptimizer = th.optim.Adam(self.critic.parameters(), lr=lr)

    def choose_action(self, s):
        s = th.FloatTensor(s).to(device)
        a_prob = self.actor(s)
        rand = np.random.uniform()
        accumulation = 0
        action = 0
        for i in range(n_action):
            accumulation += a_prob[i]
            if accumulation >= rand:
                action = i
                break
        return action

    def actor_learn(self, s, a, td_error):
        s = th.FloatTensor(s).to(device)
        a_prob = self.actor(s)
        a_prob = a_prob[a]
        loss = -(th.log(a_prob) * td_error.detach())

        self.Aoptimizer.zero_grad()
        loss.backward()
        self.Aoptimizer.step()

    def critic_learn(self, transition):  # transition=[s,[r],[a],s_,[done]]
        s = th.FloatTensor(transition[0]).to(device)
        r = transition[1][0]
        s_ = th.FloatTensor(transition[3]).to(device)
        done = transition[4][0]

        v_eval = self.critic(s)
        v_target = self.critic(s_) * gamma + r

        td_error = v_eval - v_target.detach()
        loss = td_error ** 2

        self.Coptimizer.zero_grad()
        loss.backward()
        self.Coptimizer.step()
        return td_error

ac = AC()

for episode in range(10000):
    t = 0
    s = env.reset()
    total_reward = 0
    while (t < 300):
        a = ac.choose_action(s)
        s_, r, done, _ = env.step(a)
        total_reward += r
        transition = [s, [r], [a], s_, [done]]

        td_error = ac.critic_learn(transition)
        ac.actor_learn(s, a, td_error)
        if done:
            break
        s = s_
    if (episode % 10 == 0):
        print("Episode:" + format(episode) + ",score:" + format(total_reward))


from player import Player
from game import Game, Action
from math import sqrt
import numpy as np
from macros import *
from collections import defaultdict
import time
import random
import torch
from net import Net
# TODO: implement N(s, a), etc. as dictionaries to save on transpositions

def to_action(move, turn):
    if move == BOARD_SIZE * BOARD_SIZE:
        return Action(turn, PASS)
    return Action(turn, PLAY, move // BOARD_SIZE, move % BOARD_SIZE)

def from_action(action):
    if action.type == PASS:
        return BOARD_SIZE * BOARD_SIZE
    assert(action.type == PLAY)
    return action.x * BOARD_SIZE + action.y

# credit for general MCTS code goes to
# https://github.com/plkmo/AlphaZero_Connect4/blob/master/src/MCTS_c4.py
class UCTNode:
    def __init__(self, game, move, parent=None):
        self.game = game
        self.move = move
        self.is_expanded = False
        self.parent = parent
        self.children = {}
        self.child_priors = np.zeros([INPUT], dtype=np.float32)
        self.child_total_value = np.zeros([INPUT], dtype=np.float32)
        self.child_number_visits = np.zeros([INPUT], dtype=np.float32)
        self.action_idxes = self.game.action_idxs()

    @property
    def number_visits(self):
        return self.parent.child_number_visits[self.move]

    @number_visits.setter
    def number_visits(self, value):
        self.parent.child_number_visits[self.move] = value

    @property
    def total_value(self):
        return self.parent.child_total_value[self.move]

    @total_value.setter
    def total_value(self, value):
        self.parent.child_total_value[self.move] = value

    def child_Q(self):
        return self.child_total_value / (1 + self.child_number_visits)

    def child_U(self):
        return sqrt(self.number_visits) * (abs(self.child_priors) / (1 + self.child_number_visits))

    def best_child(self):
        # if no legal actions, we're in a terminal state and we should return
        if self.action_idxes:
            bestmove = self.child_Q() + self.child_U()
            bestmove = self.action_idxes[np.argmax(bestmove[self.action_idxes])]
        else:
            bestmove = None
        return bestmove

    def select_leaf(self):
        current = self
        while current.is_expanded:
            best_move = current.best_child()
            if best_move is None:
                return current
            current = current.maybe_add_child(best_move)
        return current

    def add_dirichlet_noise(self, action_idxs, child_priors):
        # # TODO: understand what is going on here
        valid_child_priors = child_priors[action_idxs]  # select only legal moves entries in child_priors array
        valid_child_priors = 0.75 * valid_child_priors + 0.25 * np.random.dirichlet(np.zeros([len(valid_child_priors)],
                                                                                dtype=np.float32) + 192)
        child_priors[action_idxs] = valid_child_priors
        return child_priors

    def expand(self, child_priors):
        self.is_expanded = True
        action_idxs = self.game.action_idxs()
        c_p = child_priors
        if not action_idxs:
            self.is_expanded = False
        self.action_idxes = action_idxs
        for i in range(len(child_priors)):
            if i not in action_idxs:
                c_p[i] = 0.00000000
        # for some reason the below line doesn't work, probably different python version
        # c_p[[i for i in range(len(child_priors)) if i not in action_idxs]] = 0.000000000  # mask all illegal actions
        if self.parent.parent is None:  # add dirichlet noise to child_priors in root node
            c_p = self.add_dirichlet_noise(action_idxs, c_p)
        self.child_priors = c_p

    def maybe_add_child(self, move):
        if move not in self.children:
            copy_game = Game.from_other(self.game)
            copy_game.move(to_action(move, copy_game.turn))
            self.children[move] = UCTNode(
                copy_game, move, parent=self)
        return self.children[move]

    def backup(self, value_estimate: float):
        current = self
        while current.parent is not None:
            current.number_visits += 1
            if current.game.turn == BLACK:  # same as current.parent.game.player = 0
                current.total_value += (-1 * value_estimate)  # value estimate +1 = O wins
            elif current.game.turn == WHITE:  # same as current.parent.game.player = 1
                current.total_value += (1 * value_estimate)
            current = current.parent

class DummyNode:
    def __init__(self):
        self.parent = None
        self.child_total_value = defaultdict(float)
        self.child_number_visits = defaultdict(float)

class MCTSPlayer(Player):
    def __init__(self, board_size, color, evaluator, playouts=50):
        super().__init__(board_size, color)
        self.evaluator = evaluator
        self.playouts = playouts

    def _mcts(self, game):
        root = UCTNode(game, move=None, parent=DummyNode())
        for _ in range(self.playouts):
            leaf = root.select_leaf()
            child_priors, value_estimate = self.evaluator(leaf.game)
            if leaf.game.done:
                # terminal game state, no need to expand
                leaf.backup(value_estimate)
                continue
            leaf.expand(child_priors)
            leaf.backup(value_estimate)
        return root

    def get_move(self, game):
        node = self._mcts(game)
        # return most visited move
        # print(node.child_number_visits)
        move_idx = np.random.choice(np.flatnonzero(node.child_number_visits == node.child_number_visits.max()))
        # parse move_idx into an action
        return to_action(move_idx, self.color)
        # if move_idx == self.board_size * self.board_size:
        #     return Action(self.turn, PASS)
        # return Action(self.turn, PLAY, move_idx // 9, move_idx % 9)

def simple_mcts_evaluation(game):
    priors = np.full((INPUT), 1 / INPUT)
    # priors = [1 / len(game.action_idxs())] * len(game.action_idxs())
    if game.done:
        if game.winner == BLACK:
            return priors, 1
        elif game.winner == WHITE:
            return priors, -1
        return priors, 0
    return priors, game.score() / (game.board_size * game.board_size + game.komi)


import os, requests
from pathlib import Path

rootPath = os.getcwd()
rndList = []

def Run():
    command = input("Enter command: [-install]")
    if command == "-install":
        Install()

def Install():
    #Create the folder structure
    print("Createing folders...")
    os.mkdir(rootPath+"/templates")
    os.mkdir(rootPath+"/static")
    os.mkdir(rootPath+"/static/data")
    os.mkdir(rootPath+"/static/images")
    os.mkdir(rootPath+"/static/js")
    os.mkdir(rootPath+"/static/storage")
    os.mkdir(rootPath+"/static/styles")
    os.mkdir(rootPath+"/static/userDatabase")
    os.mkdir(rootPath+"/static/data/__")
    os.mkdir(rootPath+"/static/data/__/thumbnails/")
    os.mkdir(rootPath+"/static/data/__/thumbnails/ahahah_low/")
    os.mkdir(rootPath+"/static/data/databases")
    os.mkdir(rootPath+"/static/data/default")
    os.mkdir(rootPath+"/static/data/dictionarys")
    os.mkdir(rootPath+"/static/data/analytics")
    os.mkdir(rootPath+"/static/images/icons")
    os.mkdir(rootPath+"/static/storage/specials")
    os.mkdir(rootPath+"/static/storage/specials/thumbnails")
    os.mkdir(rootPath+"/ffmpeg")
    os.mkdir(rootPath+"/input")
    os.mkdir(rootPath+"/output")
    print("Folders created")

    #Move files to destination folder
    print("Moving files to folders...")
    Path(rootPath+"/_data/home.html").rename(rootPath+"/templates/home.html")
    Path(rootPath+"/_data/login.html").rename(rootPath+"/templates/login.html")
    Path(rootPath+"/_data/impressum.html").rename(rootPath+"/templates/impressum.html")
    Path(rootPath+"/_data/videoPlayer.html").rename(rootPath+"/templates/videoPlayer.html")
    Path(rootPath+"/_data/loginStyle.css").rename(rootPath+"/static/styles/loginStyle.css")
    Path(rootPath+"/_data/homeStyle.css").rename(rootPath+"/static/styles/homeStyle.css")
    Path(rootPath+"/_data/videoPlayerStyle.css").rename(rootPath+"/static/styles/videoPlayerStyle.css")
    Path(rootPath+"/_data/Rhiledia.ttf").rename(rootPath+"/static/styles/Rhiledia.ttf")
    Path(rootPath+"/_data/Ayrton Pight.ttf").rename(rootPath+"/static/styles/Ayrton Pight.ttf")
    Path(rootPath+"/_data/yuruy.otf").rename(rootPath+"/static/styles/yuruy.oft")
    Path(rootPath+"/_data/videoPlayer.js").rename(rootPath+"/static/js/videoPlayer.js")
    Path(rootPath+"/_data/backward.svg").rename(rootPath+"/static/images/icons/backward.svg")
    Path(rootPath+"/_data/expand.svg").rename(rootPath+"/static/images/icons/expand.svg")
    Path(rootPath+"/_data/expandd.svg").rename(rootPath+"/static/images/icons/expandd.svg")
    Path(rootPath+"/_data/forward.svg").rename(rootPath+"/static/images/icons/forward.svg")
    Path(rootPath+"/_data/LeftArrow_black.png").rename(rootPath+"/static/images/icons/LeftArrow_black.png")
    Path(rootPath+"/_data/pause.svg").rename(rootPath+"/static/images/icons/pause.svg")
    Path(rootPath+"/_data/play.svg").rename(rootPath+"/static/images/icons/play.svg")
    Path(rootPath+"/_data/reduce.svg").rename(rootPath+"/static/images/icons/reduce.svg")
    Path(rootPath+"/_data/RightArrow_black.png").rename(rootPath+"/static/images/icons/RightArrow_black.png")
    Path(rootPath+"/_data/silence.svg").rename(rootPath+"/static/images/icons/silence.svg")
    Path(rootPath+"/_data/searchIcon.png").rename(rootPath+"/static/images/icons/searchIcon.png")
    Path(rootPath+"/_data/thumbs-up_small.png").rename(rootPath+"/static/images/icons/thumbs-up_small.png")
    Path(rootPath+"/_data/thumbs-down_small.png").rename(rootPath+"/static/images/icons/thumbs-down_small.png")
    Path(rootPath+"/_data/thumbs-up.png").rename(rootPath+"/static/images/icons/thumbs-up.png")
    Path(rootPath+"/_data/thumbs-down.png").rename(rootPath+"/static/images/icons/thumbs-down.png")
    Path(rootPath+"/_data/volume.svg").rename(rootPath+"/static/images/icons/volume.svg")
    Path(rootPath+"/_data/background.png").rename(rootPath+"/static/images/background.png")
    Path(rootPath+"/_data/Logo_01.png").rename(rootPath+"/static/images/Logo_01.png")
    Path(rootPath+"/_data/analytics.py").rename(rootPath+"/analytics.py")
    Path(rootPath+"/_data/database.py").rename(rootPath+"/database.py")
    Path(rootPath+"/_data/modules.py").rename(rootPath+"/modules.py")
    Path(rootPath+"/_data/server.py").rename(rootPath+"/server.py")
    Path(rootPath+"/_data/freeVoD.py").rename(rootPath+"/freeVoD.py")
    Path(rootPath+"/_data/converter.py").rename(rootPath+"/converter.py")
    Path(rootPath+"/_data/userDatabase.py").rename(rootPath+"/userDatabase.py")
    Path(rootPath+"/_data/ahahah_low.mp4").rename(rootPath+"/static/data/__/ahahah_low.mp4")
    Path(rootPath+"/_data/ahahah_low.png").rename(rootPath+"/static/data/__/thumbnails/ahahah_low/0.png")
    Path(rootPath+"/_data/categorieDictionary").rename(rootPath+"/static/data/dictionarys/categorieDictionary")
    Path(rootPath+"/_data/actorNameDictionary").rename(rootPath+"/static/data/dictionarys/actorNameDictionary")
    Path(rootPath+"/_data/keyWordDictionary").rename(rootPath+"/static/data/dictionarys/keyWordDictionary")
    print("Files moved to folders")

    #Create files
    print("creating database files...")
    file = open(rootPath+"/static/data/analytics/analytics.db", "wb")
    file.close()
    file = open(rootPath+"/static/data/analytics/categorieAnalytics.db", "wb")
    file.close()
    file = open(rootPath+"/static/data/analytics/keyWordList.db", "wb")
    file.close()
    file = open(rootPath+"/static/data/analytics/actorAnalytics.db", "wb")
    file = open(rootPath+"/static/data/databases/userDataBase.db", "wb")
    file.close()
    file = open(rootPath+"/static/data/databases/videoDatabase.db", "wb")
    file.close()
    print("database files created")

    print("Installing requirements: Flask, cv2, fake_headers...")
    os.system('pip install -r ./_data/requirements.txt')
    print("requirements: Flask, cv2, fake_headers installed")
    Path(rootPath+"/_data/requirements.txt").rename(rootPath+"/requirements.txt")
    fileList = os.listdir(rootPath+"/_data/")
    command = input("Enter download ffmpeg? ")
    if command == "yes":
        DownloadFFMPEG()
    if len(fileList) < 1:
        print("Installation complete\n Enter python njoyporn.py to start the server")

def DownloadFFMPEG():
    url = "http://www.gilltrick.com/static/Downloads/ffmpeg.exe"
    local_filename = os.getcwd()+"/ffmpeg/ffmpeg.exe"
    with requests.get(url, stream=True) as r:
        r.raise_for_status()
        with open(local_filename, 'wb') as f:
            for chunk in r.iter_content(chunk_size=8192):
                f.write(chunk)
    return local_filename

if __name__ == "__main__":
    Run()


import logging

logger = logging.getLogger(__name__)

CHAR_SHORT_MAX_LENGTH_DESCRIPTION = 'Exceeded maximum length of 50 characters.'
CHAR_LONG_MAX_LENGTH_DESCRIPTION = 'Exceeded maximum length of 255 characters.'

ERRORS_DICT = {
    20000: 'Invalid filter.',
    20001: 'Invalid filter type.',
    20002: 'Invalid page.',
    20003: 'Invalid slug.',
    20004: 'Invalid search.',
    20005: 'Invalid order.',
    20006: 'Invalid order values.',
    20007: 'Invalid query.',
    20008: 'Post not found.',
    20009: 'Already shared.',
    20010: 'Mood not processed.',
    20011: ('mood_type', 'Already log in a diary'),
    20012: 'Root not found',
    20013: 'Cannot comment under.',
    20014: 'Comment not found',
    20015: 'Something wrong.',
    20016: 'Support not found',
}