import random
from datetime import datetime, timedelta
import db
from words import WORDS, TARGETS

MAX_TIME = 60 * 60 # 1 hour

class Wordle:
    def __init__(self):
        self.games: dict[int, Game] = {}

    def restart(self, uid: int) -> bool:
        old = uid in self.games
        db.add_score(uid, 6, False)
        self.games[uid] = Game()
        return old

    def guess(self, uid: int, word: str) -> str:
        caps = word.lower()
        if caps not in WORDS and caps not in TARGETS:
            return f"{word} is not a valid word"

        if uid not in self.games:
            self.games[uid] = Game()

        start = self.games[uid].get_starttime()
        if (datetime.now() - start).seconds > MAX_TIME:
            self.games[uid] = Game()

        self.games[uid].guess(caps)
        return str(self.games[uid])

    def get_guesses(self, uid: int) -> str:
        if uid in self.games:
            guesses = self.games[uid].get_guesses()
            return "\n".join(guesses)
        else:
            return "Invalid word"

    def check_gameover(self, uid: int):
        if uid in self.games and self.games[uid].is_gameover():
            db.add_score(uid, self.games[uid].num_guesses(), self.games[uid].did_win())
            del self.games[uid]

class Game:
    def __init__(self):
        self.start = datetime.now()
        self.word = random.choice(TARGETS)
        print(self.word)
        self.guesses = []
        self.emoji = []
        self.letters = {}
        self.won = False
        for c in self.word:
            if c not in self.letters:
                self.letters[c] = 1
            else:
                self.letters[c] += 1

    def __str__(self) -> str:
        output = ""
        gameover = self.is_gameover()
        if gameover:
            n = f"{self.num_guesses()}" if self.won else "X"
            output += f"{self.word} {n}/6\n\n"
        for e in self.emoji:
            output += e + '\n'

        if gameover:
            if self.won:
                output += "Well done!"
            else:
                output += "Better luck next time!"
        return output

    def is_gameover(self) -> bool:
        return len(self.guesses) == 6 or self.won

    def did_win(self) -> bool:
        return self.won

    def get_guesses(self) -> list[str]:
        return self.guesses

    def num_guesses(self) -> int:
        return len(self.guesses)

    def get_starttime(self) -> datetime:
        return self.start

    def guess(self, guess: str):
        self.guesses.append(guess)

        if guess == self.word:
            self.emoji.append(":green_square:" * 5)
            self.won = True
            return

        emoji = ""
        for i in range(5):
            e = self.get_emoji(guess, i)
            emoji += e
        self.emoji.append(emoji)

    def get_num_letters(self, c: str):
        if c not in self.letters:
            return 0
        else:
            return self.letters[c]

    def get_emoji(self, word: str, idx: int) -> str:
        letter = word[idx]
        target = self.word[idx]
        n = self.get_num_letters(letter)

        if letter == target:
            return ":green_square:"

        if n == 0:
            return ":black_large_square:"

        indices = [i for i in range(5) if letter == word[i]]
        if len(indices) == n:
            return ":yellow_square:"

        for i in range(n):
            j = indices[i]
            if j == idx:
                return ":yellow_square:"

        return ":black_large_square:"


from eagle import tools
from eagle import api, fields, models
from psycopg2.extensions import AsIs

class EducationGroupTeacherReport(models.Model):
    _name = 'education.group.teacher.report'
    _description = 'Teacher Groups Repor'
    _auto = False
    _rec_name = 'teacher_id'

    center_id = fields.Many2one(
        comodel_name='res.partner', string='Education Center')
    course_id = fields.Many2one(
        comodel_name='education.course', string='Education Course')
    group_id = fields.Many2one(
        comodel_name='education.group', string='Education Group')
    subject_id = fields.Many2one(
        comodel_name='education.subject', string='Education Subject')
    teacher_id = fields.Many2one(
        comodel_name='hr.employee', string='Teacher')
    classroom_id = fields.Many2one(
        comodel_name='education.classroom', string='Classroom')
    academic_year_id = fields.Many2one(
        comodel_name='education.academic_year', string='Academic Year')

    _depends = {
        'education.schedule': [
            'subject_id', 'classroom_id', 'teacher_id', 'academic_year_id'
        ],
        'education.group': [
            'center_id', 'course_id'
        ],
    }

    def _select(self):
        select_str = """
            SELECT
                row_number() OVER () as id,
                grp.center_id AS center_id,
                grp.course_id AS course_id,
                grp.id AS group_id,
                sch.subject_id AS subject_id,
                sch.classroom_id AS classroom_id,
                sch.teacher_id AS teacher_id,
                sch.academic_year_id AS academic_year_id
        """
        return select_str

    def _from(self):
        from_str = """
                FROM edu_schedule_group sch_group
                JOIN education_schedule sch ON sch_group.schedule_id = sch.id
                JOIN education_group grp ON sch_group.group_id = grp.id
        """
        return from_str

    def _group_by(self):
        group_by_str = """
                GROUP BY grp.center_id, grp.course_id, grp.id, sch.subject_id,
                sch.classroom_id, sch.teacher_id, sch.academic_year_id
        """
        return group_by_str

    @api.model_cr
    def init(self):
        # self._table = education_group_teacher_report
        tools.drop_view_if_exists(self.env.cr, self._table)
        self.env.cr.execute(
            """CREATE or REPLACE VIEW %s as
                (
                %s %s %s
            )""", (
                AsIs(self._table), AsIs(self._select()), AsIs(self._from()),
                AsIs(self._group_by()),))


import requests
import json
import logging
import time

logging.basicConfig(
    filename="server.log",
    filemode='a',
    level=logging.INFO,
    format='{levelname} {asctime} {name} : {message}',
    style='{'
)
log = logging.getLogger(__name__)

def main(url):
    while True:
        try:
            r = requests.get(url)
            data = json.loads(r.content)
            for key in data.keys():
                logging.info("Ключ: %s, Значення: %s", key, data[key])
        except requests.exceptions.ConnectionError as err:
            logging.error("Server is not available (" + str(err) + ")")
        if '--once' in sys.argv:
            break
        time.sleep(60)

if __name__ == '__main__':
    main("http://localhost:8000/health")


from django.contrib.auth.models import User
from rest_framework import generics
from .serializers import (
    PostCreateSerializer, PostListSerializer, PostReactSerializer, CommentCreateSerializer,
    CommentSerializer, CommentPreviewSerializer
)
from account.serializers import UserMentionsSerializer
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated, AllowAny
from .models import Content
from rest_framework import status
from rest_framework.parsers import FileUploadParser
from rest_framework.decorators import api_view, authentication_classes, permission_classes

class Post(generics.ListCreateAPIView):
    authentication_classes = [TokenAuthentication, ]
    permission_classes = [IsAuthenticated, ]
    parser_class = (FileUploadParser,)

    def get(self, request, *args, **kwargs):
        query_set = Content.objects.order_by('-posted')
        serializer = PostListSerializer(query_set, many=True, context={'request':request})
        return Response(data=serializer.data, status=200)

    def post(self, request, *args, **kwargs):
        print(request.data)
        serializer = PostCreateSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            post = serializer.save(author=request.user)
            post_json = PostListSerializer(post, context={'request': request}).data
            data = {'message':'post succesfully created'}
            return Response(data=post_json, status=200)

        return Response({'message':'Ooops!! Something went wrong...'}, status=400)

class UserFeed(generics.ListCreateAPIView):
    authentication_classes = [TokenAuthentication, ]
    permission_classes = [IsAuthenticated, ]

    def get(self, request, *args, **kwargs):
        query_set = Content.objects.filter(author=request.user)
        serializer = PostListSerializer(query_set, many=True, context={'request':request})
        return Response(data=serializer.data, status=200)

        return Response({'message':'Ooops!! Something went wrong...'}, status=400)

class PostDetail(generics.ListCreateAPIView):
    authentication_classes = [TokenAuthentication, ]
    permission_classes = [IsAuthenticated, ]
    parser_class = (FileUploadParser,)

    def get(self, request, *args, **kwargs):
        query_set = Content.objects.get(id=request.query_params['post_id'])
        serializer = PostListSerializer(query_set, context={'request':request})
        return Response(data=serializer.data, status=200)

@api_view(['POST', ])
@authentication_classes([TokenAuthentication, ])
@permission_classes([AllowAny, ])
def post_react(request):
    serializer = PostReactSerializer(data = request.data)
    if serializer.is_valid(raise_exception=True):
        data = serializer.validated_data
        post_id = data['post_id']
        action = data['action']
        react = data['react']
        user = request.user
        post = Content.objects.get(id=post_id)
        # exists = post.likes.filter(username=user.username).exists()

        if react == 'like':
            exists = post.likes.filter(username=user.username).exists()
            if exists:
                if action == 'unlike':
                    post.likes.remove(user)
            elif action == 'like':
                post.likes.add(user)
        else:
            exists = post.loves.filter(username=user.username).exists()
            if exists:
                if action == 'unlike':
                    post.likes.remove(user)
            elif action == 'like':
                post.loves.add(user)
        return Response({'success':True}, status=200)
    return Response({'success':False}, status=400)

class Comment(generics.ListCreateAPIView):
    authentication_classes = [TokenAuthentication, ]
    permission_classes = [IsAuthenticated, ]

    def post(self, request, *args, **kwargs):
        serializer = CommentCreateSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            post = Content.objects.get(id=request.data['post_id'])
            comment = serializer.save(author=request.user, post=post)
            response = {'id':comment.id, 'success':True}
            return Response(response, status=status.HTTP_201_CREATED)

    def get(self, request, *args, **kwargs):
        post = Content.objects.get(id=request.query_params['post_id'])
        if request.query_params['all'] == 'true':
            serializer = CommentSerializer(post.comments.all(), many=True)
        else:
            if request.query_params['specific'] == 'true':
                serializer = CommentSerializer(
                    post.comments.get(id=request.query_params['comment_id']))
            else:
                serializer = CommentPreviewSerializer(post.comments.last(), many=False)

        return Response(serializer.data, status=status.HTTP_200_OK)

class UserMentions(generics.ListAPIView):
    authentication_classes = [TokenAuthentication, ]
    permission_classes = [IsAuthenticated, ]

    def get(self, request, *args, **kwargs):
        if request.query_params['queryExists'] == 'true':
            username = request.query_params['username']
            users = User.objects.filter(username__contains=username).exclude(username=request.user.username)[:10]
        else:
            users = User.objects.all().exclude(username=request.user.username)[:10]
        serializer = UserMentionsSerializer(users, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

# def echo_post(request):
#     post_id = request.POST['post_id']
#     post = Content.objects.get(id=post_id)
#     print(request.POST)
#     form = ContentForm(request.POST or None, request.FILES or None)
#     if form.is_valid():
#         obj = form.save(commit=False)
#         print(obj, obj.parent)
#         obj.parent = post
#         obj.author = request.user
#         print(obj, obj.parent)
#         obj.save()
#         return JsonResponse({"success":True})
#     return JsonResponse({"success":False})


import os

import numpy
import numpy as np
import matplotlib.pyplot as plt
import random
from config import CFG
from l1CSP import L1CSP
from sklearn.model_selection import StratifiedKFold

plt.rcParams['font.sans-serif'] = ['SimHei']  # 画图
plt.rcParams['axes.unicode_minus'] = False

FeatureL = 3        #要提取的特征数 L*2
control = 0         #control0提取一维特征，control1提取二维的8n*300特征

def readfile(path):
    names = os.listdir(path)
    x = []
    y = []
    for i, name in enumerate(names):
        x.append(np.load(path + name))
        y.append(np.load(path + name)['y'])
    index = x[-1].files[:-1]
    return x, y, index

def CSP(data, label):

    #瑞利熵求解
    channel = np.size(data, 1)
    trials = np.size(data, 0)
    n_class = len(set(label.flatten()))

    cov_mat = np.zeros((trials, channel, channel), dtype=np.float32)
    for i in range(trials):
        e = data[i, :, :]
        cov = e.dot(e.transpose())
        cov_mat[i] = cov / cov.trace()

    labeled_cov = {}
    for i in range(n_class):
        labeled_cov[i] = np.mean(cov_mat[np.where(label == i)[0]], axis=0)

    cov_total1 = np.linalg.inv(labeled_cov[1]).dot(labeled_cov[0])
    Dt1, Ut1 = np.linalg.eig(cov_total1)
    dtindex1 = np.argsort(np.abs(Dt1))[::-1]
    Ut1 = Ut1[:, dtindex1]
    M1 = Ut1.T[0:FeatureL, :]

    cov_total2 = np.linalg.inv(labeled_cov[0]).dot(labeled_cov[1])
    Dt2, Ut2 = np.linalg.eig(cov_total2)
    dtindex2 = np.argsort(np.abs(Dt2))[::-1]
    Ut2 = Ut2[:, dtindex2]
    M2 = Ut2.T[0:FeatureL, :]
    CSPMatrix = np.concatenate((M1, M2), axis=0)

    '''#RD正则化
    labeled_mean = {}
    for i in range(n_class):
        labeled_mean[i] = np.mean(data[np.where(label == i)[0]], axis=0)
    channel_cov = labeled_mean[0].dot(labeled_mean[1].T)
    RD1 = np.diag(np.sum(np.abs(channel_cov), axis=1) / channel)
    RD1 = RD1 / RD1.max()
    RD2 = np.diag(np.sum(np.abs(channel_cov), axis=0) / channel)
    RD2 = RD2 / RD2.max()
    '''
    '''#白化求解
    cov_mean_total = labeled_cov[0] + labeled_cov[1]
    Dt,Ut = np.linalg.eig(cov_mean_total)
    dtindex = np.argsort(np.abs(Dt))[::-1]
    Dt = Dt[dtindex]
    Ut = Ut[:, dtindex]
    P = np.dot(np.diag(np.sqrt(1 / Dt)), Ut.transpose())
    transCov1 = P.dot(labeled_cov[0]).dot(P.transpose())

    D1, U1 = np.linalg.eig(transCov1)
    d1index = np.argsort(np.abs(D1))[::-1]
    U1 = U1[:, d1index]
    CSPMatrix = U1.T.dot(P)
    D1 = np.diag(D1[d1index])
    '''
    '''L1CSP 直接优化
    x1 = data[np.where(label == 0)[0]].transpose(1, 0, 2).reshape(data.shape[1], -1)
    x2 = data[np.where(label == 1)[0]].transpose(1, 0, 2).reshape(data.shape[1], -1)
    csp = L1CSP(500, [10, 1, 0.5, 0.2, 1e-1, 0.05, 0.02, 1e-2, 1e-3], 1e-4)
    m1 = csp(x1, x2, FeatureL)
    m2 = csp(x2, x1, FeatureL)
    CSPMatrix = np.concatenate((m1, m2), axis=0)
    '''
    '''L1CSP bootstrap优化
    x1 = data[np.where(label == 0)[0]]
    x2 = data[np.where(label == 1)[0]]
    m1 = []
    m2 = []
    csp = L1CSP(500, [0.05, 0.02, 1e-2, 1e-3, 0.2, 1e-1, 1, 2, 5, 10, 100, 400], 0.1)
    for i in range(5):
        index1 = np.random.choice(np.arange(x1.shape[0]), size=int(x1.shape[0] / 10), replace=False)
        index2 = np.random.choice(np.arange(x2.shape[0]), size=int(x2.shape[0] / 10), replace=False)
        xx1 = x1[index1].transpose(1, 0, 2).reshape(x1.shape[1], -1)
        xx2 = x2[index2].transpose(1, 0, 2).reshape(x2.shape[1], -1)
        m1.append(csp(xx1, xx2, FeatureL))
        m2.append(csp(xx2, xx1, FeatureL))
    mm1 = np.mean(np.array(m1), axis=0)
    mm2 = np.mean(np.array(m2), axis=0)
    CSPMatrix = np.concatenate((mm1, mm2), axis=0)
    '''
    return CSPMatrix

def FeatureExtra(CspMat, data):
    global control
    trials = np.size(data, 0)
    Filter = np.r_[CspMat[:FeatureL], CspMat[-FeatureL:]]
    if control==1:
        samples = np.size(data, 2)
        feature = np.zeros([trials, 2 * FeatureL, samples])
        for t in range(trials):
            project = Filter.dot(data[t])
            feature[t, :, :] = np.log(np.abs(project))
        return feature

    feature = np.zeros([trials, 2 * FeatureL])
    #L2
    for t in range(trials):
        project = Filter.dot(data[t])
        variances = np.var(project, 1)
        for f in range(len(variances)):
            feature[t, f] = np.log(variances[f] / np.sum(variances))
    return feature
    '''
    #L1
    for t in range(trials):
        project = Filter.dot(data[t])
        for f in range(project.shape[0]):
            feature[t, f] = np.linalg.norm(project[f], ord=1)
    return feature
    '''

if not os.path.exists(CFG.CANET.TRAIN.DATASET):
    os.makedirs(CFG.CANET.TRAIN.DATASET)
if not os.path.exists(CFG.SVM.DATASET):
    os.makedirs(CFG.SVM.DATASET)

cspMatrix = []      #训练集特征提取
#cspMatrix = np.load('cspmatrix.npz')['cspma']
rawx, ylabel, wave_list = readfile(CFG.DATA_WAVED_TRAIN)
for i in range(len(ylabel)):
    val_x = {}
    val_y = ylabel[i]
    train_x = {}
    train_y = np.concatenate((np.array(ylabel)[np.delete(np.arange(len(ylabel)), i), :]))
    Feature_t = []
    Feature_v = []
    for k, j in enumerate(wave_list):
        val_x[j] = rawx[i][j]
        train_index = np.delete(np.arange(len(ylabel)), i)
        train_x[j] = rawx[train_index[0]][j]
        for p in range(1, len(train_index)):
            temp = rawx[train_index[p]][j].copy()
            train_x[j] = np.concatenate((train_x[j], temp), axis=0)
        CSPM = CSP(train_x[j], train_y)
        cspMatrix.append(CSPM)
        #CSPM = cspMatrix[i*4+k]
        Feature_t.append(FeatureExtra(CSPM, train_x[j]))
        Feature_v.append(FeatureExtra(CSPM, val_x[j]))

        '''
        train_xxl = np.where(train_y == 0)[0]
        train_xxr = np.where(train_y == 1)[0]
        plt.plot(Feature_t[k][train_xxl][:, 0], Feature_t[k][train_xxl][:, 3], 'x', label="L", color='blue')
        plt.plot(Feature_t[k][train_xxr][:, 0], Feature_t[k][train_xxr][:, 3], 'o', label="r", color='green')
        plt.show()

        train_xl = np.where(val_y == 0)[0]
        train_xr = np.where(val_y == 1)[0]
        plt.plot(Feature_v[k][train_xl][:, 0], Feature_v[k][train_xl][:, 3], 'x', label="L", color='coral')
        plt.plot(Feature_v[k][train_xr][:, 0], Feature_v[k][train_xr][:, 3], 'o', label="r", color='yellow')
        plt.show()
        '''

    featrue_t = np.array(Feature_t)
    featrue_v = np.array(Feature_v)
    if control == 0:
        feature_t = featrue_t.transpose((1, 0, 2)).reshape(-1, featrue_t.shape[0] * featrue_t.shape[2])
        feature_v = featrue_v.transpose((1, 0, 2)).reshape(-1, featrue_v.shape[0] * featrue_v.shape[2])
        tmu = np.mean(feature_t, axis=0)
        tsigma = np.mean(feature_t, axis=0)
        feature_t = (feature_t - tmu) / tsigma
        vmu = np.mean(feature_v, axis=0)
        vsigma = np.mean(feature_v, axis=0)
        feature_v = (feature_v - vmu) / vsigma
        np.savez(CFG.SVM.DATASET + "fold" + str(i) + ".npz", train_x=feature_t, train_y=train_y, val_x=feature_v,
                     val_y=val_y)
    else:
        feature_t = featrue_t.transpose((1, 0, 2, 3)).reshape((featrue_t.shape[1], featrue_t.shape[0] * featrue_t.shape[2], featrue_t.shape[3]))
        feature_v = featrue_v.transpose((1, 0, 2, 3)).reshape((featrue_v.shape[1], featrue_v.shape[0] * featrue_v.shape[2], featrue_v.shape[3]))
        np.savez(CFG.CANET.TRAIN.DATASET + "fold"+str(i)+".npz", train_x=feature_t, train_y=train_y, val_x=feature_v, val_y=val_y)
np.savez("cspmatrix.npz", cspma=np.array(cspMatrix))
print('over')

'''测试数据特征提取
if not os.path.exists(CFG.CANET.TRAIN.DATATEST):
    os.makedirs(CFG.CANET.TRAIN.DATATEST)
if not os.path.exists(CFG.DATA_TEST):
    os.makedirs(CFG.DATA_TEST)

cspMatrix = np.load('cspmatrix.npz')['cspma']
path = CFG.DATA_WAVED_TEST
names = os.listdir(path)
for i, name in enumerate(names):
    x = np.load(path+name)
    index = x.files
    Fold = []
    for p in range(4):
        Feature = []
        xout ={}
        for k, j in enumerate(index):
            xout[j] = x[j]
            #mean = np.mean(xout[j], axis=2, keepdims=True)
            #xout[j] = xout[j] - np.mean(xout[j], axis=2, keepdims=True)
            #for p in range(len(xout[j])):
            #    xout[j][p] = xout[j][p] / np.sqrt(xout[j][p].dot(xout[j][p].T).trace())
            Feature.append(FeatureExtra(cspMatrix[p*4 + k], xout[j]))
        featrue = np.array(Feature)
        if control == 0:
            feature = featrue.transpose((1, 0, 2)).reshape(-1, featrue.shape[0] * featrue.shape[2])
            mu = np.mean(feature, axis=0)
            sigma = np.mean(feature, axis=0)
            feature = (feature - mu) / sigma
        else:
            feature = featrue.transpose((1, 0, 2, 3)).reshape(
                (featrue.shape[1], featrue.shape[0] * featrue.shape[2], featrue.shape[3]))
        Fold.append(feature)
    if control == 0:
        np.savez(CFG.DATA_TEST + "n"+str(i+5)+".npz", fold=Fold)
    else:
        np.savez(CFG.CANET.TRAIN.DATATEST + "n" + str(i + 5) + ".npz", fold=Fold)
'''


import pygame

class InterDimensionalRift(pygame.sprite.Sprite):
    def __init__(self, possible_images):
        super().__init__()
        self.possible_images = possible_images
        self.current_image_number = 0
        self.image = self.possible_images[self.current_image_number].copy()
        self.rect = self.image.get_rect()
        self.is_closed = False
        self.horizontal_speed = 3

    def update(self):
        if not self.is_closed:
            if self.image.get_alpha() == 0:
                self.current_image_number += 1
                if self.current_image_number > len(self.possible_images) - 1:
                    self.current_image_number = 0
                self.image = self.possible_images[self.current_image_number].copy()

                old_x = self.rect.x
                old_y = self.rect.y
                self.rect = self.image.get_rect()
                self.rect.x = old_x
                self.rect.y = old_y
            else:
                self.image.set_alpha(self.image.get_alpha() - 1)
                pygame.time.delay(3)

    def handle_player_collision(self, player):
        if not self.is_closed and not player.is_jumping and not player.sprite_grounded_on == self:
            if player.rect.x >= (self.rect.x - self.rect.width) and player.move_right:
                player.rect.x = self.rect.x - self.rect.width + 20
                player.stop()
            if player.rect.x <= (self.rect.x + self.rect.width) and player.move_left:
                player.rect.x = self.rect.x + self.rect.width - 15
                player.stop()
        elif player.is_jumping and player.rect.y >= (self.rect.y - self.rect.height):
            player.rect.y = self.rect.y - self.rect.height + 20
            player.stop()
            player.is_grounded = True
            player.sprite_grounded_on = self
            player.sprite_grounded_on_multiplier = 1
        elif self.is_closed and not player.is_jumping and not player.sprite_grounded_on == self:
            if player.rect.x >= (self.rect.x - self.rect.width) and player.move_right:
                self.rect.x += self.horizontal_speed
            if player.rect.x >= self.rect.x and player.move_left:
                self.rect.x -= self.horizontal_speed

    def close(self):
        self.is_closed = True
        self.image.set_alpha(255)


from django.shortcuts import render_to_response
from django.core.context_processors import csrf

def tire(request):
    if request.POST:
            if request.POST["motosikletkg"] and request.POST["yolcukg"]:
                motosiklet_kg = request.POST["motosikletkg"]
                yolcu_kg = request.POST["yolcukg"]

                toplam_kg = int(motosiklet_kg) + int(yolcu_kg)

                if int(toplam_kg) > 200 and int(toplam_kg) < 300:
                    on_lastik = "25-27"
                    arka_lastik = "32-34"
                elif int(toplam_kg) > 300 and int(toplam_kg) < 400:
                    on_lastik = "27-29"
                    arka_lastik = "34-37"
                elif int(toplam_kg) > 400:
                    on_lastik = "28-30"
                    arka_lastik = "36-38"
                else:
                    on_lastik = "Hesaplanamadi"
                    arka_lastik = "Hesaplanamadi"

            c = {"request": request,
                 "onlastik": on_lastik,
                 "arkalastik": arka_lastik}

            c.update(csrf(request))

            return render_to_response("tire/tire-pressure-calculator.html", c)

    c = {"request": request}
    c.update(csrf(request))

    return render_to_response("tire/tire-pressure-calculator.html", c)


# 14503 로봇 청소기
from collections import deque
import sys
input = sys.stdin.readline

def bfs(r,c,d):
    ans = 0
    visited = [[False]*m for _ in range(n)]
    q = deque()
    q.append((r,c))

    while q:
        x,y = q.popleft()
        if not visited[x][y]:
            ans+=1
        visited[x][y] = True   # 현재 위치 청소
        cnt = 0   # 네방향 이동 가능 여부
        for i in range(4):
            d = (d-1) % 4
            nx, ny = dx[d]+x, dy[d]+y
            if not visited[nx][ny] and arr[nx][ny] == 0:
                q.append((nx,ny))
                break
            else:
                cnt += 1
            # 네 방향 모두 청소되어 있는 경우
            if cnt == 4:
                # 뒤쪽 방향이 벽인 경우
                if arr[x+dx[(d-2)%4]][y+dy[(d-2)%4]] == 1:
                    return print(ans)
                q.append((x+dx[(d-2)%4],y+dy[(d-2)%4]))
    return print(ans)

n,m = map(int,input().split())
r,c,d = map(int, input().split())
arr = [list(map(int,input().split())) for _ in range(n)]
dx,dy = (-1,0,1,0), (0,1,0,-1)   # 북:0 동:1 남:2 서:3   cnt = (cnt-1) % 4

bfs(r,c,d)


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

import vtk

#Genera la imagen en un archivo.
def plotToFile(fName, renWin, renderer, width, height,fileFormat):
  w2i = vtk.vtkWindowToImageFilter()
  writer = vtk.vtkJPEGWriter()
  w2i.SetInput(renWin)
  w2i.Update()
  writer.SetInputConnection(w2i.GetOutputPort())
  writer.SetFileName(fName)
  renWin.Render()
  w2i.Update()
  writer.Write()


import time
import random
import requests
import pandas as pd
from requests_oauthlib import OAuth1
key_words=["Object Detection","YOLO","Machine Learning"]
auth = OAuth1("R3HqOpqIo6AcKjDYKD1tpsBzQ", "hw1X2Hv7IlND6eKewSFbFa7SgQ70OpEHKKr7wzvtFDPlFuffVe",f"AAAAAAAAAAAAAAAAAAAAAPnOhgEAAAAAtGmcPuNuqE%2FTStZkA1wcHCmpY%2Bw%3Dn9KHHdFYQJEyBy5sDYNchbCDqiFV5JBRNTtKPPNWpAE9aJ8uyY")
def bearer_oauth(r):
    r.headers["Authorization"]="Bearer {}".format(f"AAAAAAAAAAAAAAAAAAAAAPnOhgEAAAAAtGmcPuNuqE%2FTStZkA1wcHCmpY%2Bw%3Dn9KHHdFYQJEyBy5sDYNchbCDqiFV5JBRNTtKPPNWpAE9aJ8uyY")
    r.headers["User-Agent"]="Mozilla/5.0"

    return r
query_params={'query': 'Python',
             'tweet.fields': 'author_id',
             'expansions':'author_id',
             'max_results': '100',
             'user.fields':'created_at,entities,description,id,location,name,pinned_tweet_id,profile_image_url,protected,public_metrics,url,username,verified,withheld'
             }
url = "https://api.twitter.com/2/tweets/search/recent"#API url
query_params_two=query_params.copy() # next page header
id_had_lst=[]# looped user
user_info_lst=[]# result
key_word_num=0
next=False # flip page
pageNum=0
while key_word_num<len(key_words):

    query_params['query']= key_words[key_word_num]
    query_params_two['query']= key_words[key_word_num]
    print("now we are in",query_params['query'])
    time.sleep(random.random()*10)
    if next:# the second page of now searching key word
        r = requests.get(url,auth=bearer_oauth,params=query_params_two)
    else:# the first page of the now searching key word

        r = requests.get(url,auth=bearer_oauth,params=query_params)
    js = r.json()
    print(js)
    for one_user in js["includes"]["users"]:
        if one_user["id"] in id_had_lst: #pass the already looped users
            continue
        id_had_lst.append(one_user["id"])
        user_info_lst.append(one_user)
    print("Done one page!")
    if "next_token" not in js["meta"]: #if we have data in next page
        key_word_num+=1
        next=False
        print("finish the {} key word".format(key_word_num))
        continue
    else:
        pageNum+=1
        if pageNum>9:
            key_word_num+=1
            pageNum=0
            next=False
            print("finish the {} key word".format(key_word_num))
            continue
        query_params_two["next_token"] = js["meta"]["next_token"]
        next=True
        continue
pd.DataFrame(user_info_lst).to_csv(r"twitter.csv")


from flask import Flask,request
from flask_cors import CORS
import json
import helperFunctionsAPI as hp

app = Flask(__name__)
CORS(app)

@app.route('/search', methods=['GET'])
def searchResult():
    song_input = request.args.get('song_name')
    artist_input = request.args.get('artist_name')
    album_input = request.args.get('album_name')

    response = hp.getDataFromQuery(song_input, artist_input, album_input)
    return json.dumps(response)

@app.route('/recommend', methods=['GET'])
def generateRecommend():
    featureVector = json.loads(request.args.get("query"))["featureVector"]
    recommendations = hp.getRecommendations(featureVector,"fromProfile",50,"")
    return json.dumps(recommendations)

@app.route('/getmp3url', methods=['GET'])
def getMP3URL():
    response = {}
    artist = request.args.get('artist')
    songInput = request.args.get('input')
    songId = request.args.get('songid')

    response["url"] = hp.getMP3URL(songInput, artist)
    response["data"] = hp.getInformationFromID(songId)

    return json.dumps(response)

@app.route('/recommendByTrack', methods=['GET'])
def recommendByTrack():
    songId = request.args.get("input")
    response = hp.getRecommendations([], "fromTrackID", 15, songId)
    return json.dumps(response)

if __name__ == "__main__":
    app.run(host='0.0.0.0')


from django.shortcuts import render, reverse, HttpResponse, redirect
from django.contrib import messages
from django.conf import settings

# Create your views here.
import stripe

def donate(request):
    return render(request, 'payment_donate.html')

def charge(request):
    get_amount = request.GET['amount']
    if get_amount == '':
        # messages.error(request, 'Please insert a value.')
        return redirect(reverse('donate'))
    else:
        amount = int(get_amount) * 100
        if amount == 0:
            messages.error(request, 'Please insert a value more than 0.')
            # return redirect(reverse('donate'), error_message='Please insert a value more than 0.')
            return redirect(reverse('donate'))

    stripe.api_key = settings.STRIPE_SECRET_KEY

    session = stripe.checkout.Session.create(payment_method_types=['card'],
        line_items=[
            {
                'name' : 'Donation',
                'description' : 'A simple donation to support BuggyReporter',
                'amount' : amount ,
                'currency' : 'sgd',
                'quantity' : 1
            }
        ],
        success_url= request.build_absolute_uri(reverse('success')),
        cancel_url=request.build_absolute_uri(reverse('cancel'))
    )
    return render(request, 'payment_charge_donate.html', {
        'CHECKOUT_SESSION_ID': session.id,
        'publishable_key': settings.STRIPE_PUBLISHABLE_KEY
    })

def success(request):
    messages.success(request, "You have successfully made a donation.")
    return redirect(reverse('index'))
    # return HttpResponse("
We have gotten your money
")

def cancel(request):
    messages.error(request, "You have cancelled a donation.")
    return redirect(reverse('donate'))

    # return HttpResponse("
No, don't go!
")


import datetime

DEFAULT_DATE_FORMAT = '%d/%m/%Y'
KNOWN_DATE_FORMATS = [DEFAULT_DATE_FORMAT, '%d-%b-%Y', '%Y-%b-%d', '%b-%d-%Y', '%Y/%m/%d', '%m/%d/%Y']

def string_to_date(string):
    for date_format in KNOWN_DATE_FORMATS:
        try:
            return datetime.datetime.strptime(string, date_format)
        except:
            pass
    return None

def date_to_string(date, date_format = DEFAULT_DATE_FORMAT):
    return date.strftime(date_format) if date else date

def previous_business_date(date = None, count_back = 1):
    if date is None:
        date = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)

    delta = datetime.timedelta(days = 1)
    count_down = count_back
    while count_down > 0:
        new_date = date - delta

        if new_date.weekday() >= 5: #If Saturday or Sunday
            date = new_date
            continue

        count_down -= 1
        if count_down == 0:
            return new_date

    return date

def get_today():
    time_now = datetime.datetime.now()
    hour_now = time_now.hour
    time_now = time_now.replace(hour=0, minute=0, second=0, microsecond=0)

    #If weekend (i.e. Sat or Sun)
    if time_now.weekday() > 4:
        while time_now.weekday() > 4:
            time_now -= datetime.timedelta(days = 1)
        return time_now

    #The daily paper import finishes at 2AM UTC of that day. Therefore,
    #if hour < 2AM then we have to show the previous date.
    #There could be a minor difference if daylight saving is present, but it does not
    #really affect result that much (user may have incorrect result for one hour at most).
    if hour_now < 2:
        time_now = time_now.replace(hour=0, minute=0, second=0, microsecond=0)
        return previous_business_date(time_now, count_back = 1)
    else: #Otherwise, we show paper of the current date
        return previous_business_date(count_back = 0)


from collections import Counter

class Database:
    def insert(self, movies_data_list, movies_kw_data):
        self.MOVIES_DATA = movies_data_list
        self.MOVIES_KW_DATA = movies_kw_data

    def get_data(self, query):

        for operator in ["AND", "OR", "NOT"]:
            if operator in query:
                query1, query2 = query.split(operator)
                res1, res2 = self.__fetch(query1), self.__fetch(query2)
                break

        if "AND" in query:
            res_indices = list(set(res1) & set(res2))
            res_indices.sort(key=Counter(res1 + res2).get, reverse=True)
        elif "OR" in query:
            res_indices = list(set(res1 + res2))
            res_indices.sort(key=Counter(res1 + res2).get, reverse=True)
        elif "NOT" in query:
            res_indices = list(set(res1) - set(res2))
            res_indices.sort(key=Counter(res1).get, reverse=True)
        else:
            temp = self.__fetch(query)
            res_indices = list(set(temp))
            res_indices.sort(key=Counter(temp).get, reverse=True)

        res = []
        for index in res_indices:
            res.append(self.MOVIES_DATA[index])
        return res

    def __fetch(self, query):
        query = query.split()
        res_indices = []

        for word in query:
            if word in self.MOVIES_KW_DATA:
                res_indices += self.MOVIES_KW_DATA[word]

        return res_indices


# ***********************************************************************
# Import libraries
# ***********************************************************************

import sys
import os
import dill
import pickle as pk
import numpy as np
import pandas as pd
import scipy as sp

sys.path.append( os.path.abspath( '../' ) )

from mfd.ecoMfd import EcoMfdConst as EcoMfd

from utl.utils import getLogger

# ***********************************************************************
# Some definitions
# ***********************************************************************

DIAG_FLAG = True
SREL_FLAG = True

# ***********************************************************************
# Class MfdMod: Model object that builds a manifold based model
# ***********************************************************************

class MfdMod:

    def __init__(   self,
                    dfFile,
                    minTrnDate,
                    maxTrnDate,
                    maxOosDate,
                    velNames,
                    stepSize     = None,
                    optType      = 'SLSQP',
                    maxOptItrs   = 100,
                    optGTol      = 1.0e-4,
                    optFTol      = 1.0e-8,
                    factor       = 4.0e-5,
                    regCoef      = None,
                    minMerit     = 0.0,
                    minTrend     = 0.0,
                    maxBias      = 1.0,
                    varFiltFlag  = False,
                    validFlag    = False,
                    selParams    = None,
                    smoothCount  = None,
                    srcTerm      = None,
                    atnFct       = 1.0,
                    mode         = 'intraday',
                    logFileName  = None,
                    verbose      = 1          ):

        self.dfFile      = dfFile
        self.minTrnDate  = minTrnDate
        self.maxTrnDate  = maxTrnDate
        self.maxOosDate  = maxOosDate
        self.stepSize    = stepSize
        self.optType     = optType
        self.maxOptItrs  = maxOptItrs
        self.optGTol     = optGTol
        self.optFTol     = optFTol
        self.minMerit    = minMerit
        self.minTrend    = minTrend
        self.maxBias     = maxBias
        self.varFiltFlag = varFiltFlag
        self.validFlag   = validFlag
        self.srcTerm     = srcTerm
        self.mode        = mode
        self.ecoMfd      = None
        self.trmFuncDict = {}
        self.logFileName = logFileName
        self.verbose     = verbose
        self.logger      = getLogger( logFileName, verbose, 'mod' )
        self.converged   = False

        if regCoef is None:
            self.regCoef    = 0.0
            self.optRegFlag = True
        else:
            self.regCoef    = regCoef
            self.optRegFlag = False

        self.factor   = factor

        assert atnFct >= 0, 'atnFct should be positive!'
        assert atnFct <= 1.0, 'atnFct should be less than or equal to 1.0!'

        self.atnFct = atnFct

        if selParams is None:
            self.velNames = velNames
        else:
            self.velNames = self.selVels( velNames, selParams )

        self.varNames = self.getVarNames()

        if smoothCount is not None :
            for velName in self.velNames:
                self.trmFuncDict[ velName ] = lambda x : x.rolling( int( smoothCount ),
                                                                    win_type = 'blackman',
                                                                    center   = True ).mean()

    def getVarNames( self ):

        varNames = []

        for velName in self.velNames:

            tmpList = velName.split( '_' )

            if tmpList[-1] == 'Diff':
                varName = '_'.join( tmpList[:-1] )
            else:
                varName = velName + '_Cumul'

            varNames.append( varName )

        return varNames

    def selVels( self, candVelNames, selParams ):

        assert isinstance( selParams, dict ), \
            'selParams should be of dict type!'

        assert 'inVelNames' in selParams.keys(), \
            'inVarNames should be set in selParams!'

        assert 'maxNumVars' in selParams.keys(), \
            'maxNumVars should be set in selParams!'

        assert 'minImprov' in selParams.keys(), \
            'minImprov should be set in selParams!'

        assert 'strategy' in selParams.keys(), \
            'strategy should be set in selParams!'

        inVelNames = selParams[ 'inVelNames' ]
        maxNumVars = selParams[ 'maxNumVars' ]
        minImprov  = selParams[ 'minImprov' ]
        strategy   = selParams[ 'strategy' ]

        assert set( inVelNames ).issubset( set( candVelNames ) ),\
            'inVelNames should be a subset of candVelNames!'

        assert maxNumVars <= len( candVelNames ), \
            'maxNumVars should be less than or equal to number of candVelNames!'

        assert maxNumVars >= len( inVelNames ), \
            'maxNumVars should be greater than or equal to number of inVelNames!'

        if strategy == 'forward':
            velNames = self.selVelsFwd( candVelNames, selParams )
        else:
            assert False, 'Unknown strategy %s!' % strategy

        return velNames

    def selVelsFwd( self, candVelNames, selParams ):

        inVelNames = selParams[ 'inVelNames' ]
        maxNumVars = selParams[ 'maxNumVars' ]
        minImprov  = selParams[ 'minImprov' ]
        strategy   = selParams[ 'strategy' ]

        if maxNumVars == len( inVelNames ):
            return inVelNames

        sortDict   = {}
        for velName in candVelNames:

            if velName in inVelNames:
                continue

            self.velNames = inVelNames + [ velName ]
            self.varNames = self.getVarNames()

            sFlag  = self.setMfd()

            if not sFlag:
                continue

            sortDict[ velName ] = self.ecoMfd.getError()

        sVelNames = sortDict.keys()

        assert len( sVelNames ) > 0, 'Unsuccessful variable selection!'

        sVelNames = sorted( sVelNames, key = lambda y : sortDict[y] )
        velNames  = inVelNames.copy()
        error     = np.inf
        cnt       = 0

        for velName in sVelNames:

            self.velNames = velNames + [ velName ]
            self.varNames = self.getVarNames()

            sFlag  = self.setMfd()

            if not sFlag:
                continue

            newError = self.ecoMfd.getError()

            if error - newError >= minImprov:
                velNames.append( velName )
                error = newError
                cnt += 1
                self.logger.info( 'Added %s ; error = %0.4f', velName, error )
            else:
                self.logger.info( '%s was not added!', velName )

            if cnt == maxNumVars:
                break

        assert len( velNames ) > 0, 'Unsuccessful variable selection!'

        self.logger.info( 'Selected:', velNames )
        self.logger.info( list( set( velNames ) - set( inVelNames ) ), 'were added!' )

        return velNames

    def build( self ):

        self.logger.info( 'Building a manifold...' )

        sFlag  = self.setMfd()

        self.echoMod()

        if not sFlag:
            self.converged = sFlag
            return False

        if self.varFiltFlag:
            dropFlag = self.filtVars()
            if dropFlag:
                sFlag = self.setMfd()

                self.echoMod()

                if not sFlag:
                    self.converged = sFlag
                    return False

        if self.optRegFlag:
            self.regCoef = self.optReg()
            sFlag = self.setMfd()

            self.echoMod()

            if not sFlag:
                self.converged = sFlag
                return False

        if self.validFlag:
            sFlag = self.validate()

            if not sFlag:
                self.converged = sFlag
                return False

        ecoMfd = self.ecoMfd
        merit  = ecoMfd.getMerit()
        merit  = min( merit, ecoMfd.getOosMerit() )
        trend  = ecoMfd.getOosTrendCnt()
        nDims  = ecoMfd.nDims
        bias   = 0

        for varId in range( nDims ):
            bias = max( bias, ecoMfd.getRelBias( varId ) )

        if merit < self.minMerit:
            self.logger.warning( 'Merit does not meet criteria!' )
            sFlag = False

        if trend < self.minTrend:
            self.logger.warning( 'Trend does not need criteria!' )
            sFlag = False

        if bias > self.maxBias:
            self.logger.warning( 'Bias does not meet criteria' )
            sFlag = False

        if not sFlag:
            self.converged = sFlag
            return False

        self.converged = True

        return True

    def setMfd( self ):

        self.ecoMfd = EcoMfd( varNames     = self.varNames,
                              velNames     = self.velNames,
                              dateName     = 'Date',
                              dfFile       = self.dfFile,
                              minTrnDate   = self.minTrnDate,
                              maxTrnDate   = self.maxTrnDate,
                              maxOosDate   = self.maxOosDate,
                              trmFuncDict  = self.trmFuncDict,
                              optType      = self.optType,
                              maxOptItrs   = self.maxOptItrs,
                              optGTol      = self.optGTol,
                              optFTol      = self.optFTol,
                              stepSize     = self.stepSize,
                              factor       = self.factor,
                              regCoef      = self.regCoef,
                              regL1Wt      = 0.0,
                              nPca         = None,
                              diagFlag     = DIAG_FLAG,
                              srelFlag     = SREL_FLAG,
                              endBcFlag    = True,
                              srcTerm      = self.srcTerm,
                              atnFct       = self.atnFct,
                              mode         = self.mode,
                              logFileName  = self.logFileName,
                              verbose      = self.verbose        )

        sFlag = self.ecoMfd.setParams()

        if not sFlag:
            self.logger.warning( 'Did not converge!' )

        return sFlag

    def save( self, outModFile ):

        with open( outModFile, 'wb' ) as fHd:
            dill.dump( self, fHd, pk.HIGHEST_PROTOCOL )

    def echoMod( self ):

        ecoMfd  = self.ecoMfd
        nDims   = ecoMfd.nDims

        self.logger.info( 'Manifold Error    : %0.6f', ecoMfd.getError() )
        self.logger.info( 'Manifold oos Error: %0.6f', ecoMfd.getOosError() )
        self.logger.info( 'Manifold oos velocity trend match: %0.6f', ecoMfd.getOosTrendCnt( 'vel' ) )

        self.logger.info( '\n' + str( ecoMfd.getTimeDf() ) )

    def filtVars( self ):

        if not self.varFiltFlag:
            return

        ecoMfd      = self.ecoMfd
        varNames    = self.varNames
        velNames    = self.velNames
        newVarNames = []
        newVelNames = []
        dropFlag    = False
        for varId in range( ecoMfd.nDims ):

            varName = varNames[varId]
            velName = velNames[varId]
            merit   = ecoMfd.getMerit( [ varName ] )
            bias    = ecoMfd.getRelBias( varId )

            if merit < self.minMerit:
                dropFlag = True
                continue

            if bias > self.maxBias:
                dropFlag = True
                continue

            newVarNames.append( varName )
            newVelNames.append( velName )

        self.varNames = newVarNames
        self.velNames = newVelNames

        return dropFlag

    def crossVal( self,
                  minYrs,
                  incYrs,
                  regCoef = 0.0   ):

        minDt     = pd.to_datetime( self.minTrnDate )
        maxDt     = pd.to_datetime( self.maxTrnDate )
        maxOosDt  = pd.to_datetime( self.maxOosDate )

        if 2 * incYrs > ( maxDt.year - minDt.year ):
            self.logger.warning( 'Increment is too small! No cross validation done!' )
            return None

        if 3 * incYrs > ( maxOosDt.year - minDt.year ):
            self.logger.warning( 'Increment is too small! No cross validation done!' )
            return None

        maxDt    = minDt + pd.DateOffset( years = int( minYrs ) )

        maxMaxDt = pd.to_datetime( self.maxOosDate ) -\
                   pd.DateOffset( years = incYrs )
        maxMaxDt = min( maxMaxDt, pd.to_datetime( self.maxTrnDate ) )

        maxTrnDates = []
        while maxDt <= maxMaxDt:
            maxTrnDates.append( maxDt.strftime( '%Y-%m-%d' ) )
            maxDt = maxDt + pd.DateOffset( years = int( incYrs ) )

        ecoMfds = []
        for maxTrnDate in maxTrnDates:

            maxOosDt   = pd.to_datetime( maxTrnDate ) +\
                         pd.DateOffset( years = incYrs )

            maxOosDate = maxOosDt.strftime( '%Y-%m-%d' )

            ecoMfd     = EcoMfd( varNames     = self.varNames,
                                 velNames     = self.velNames,
                                 dateName     = 'Date',
                                 dfFile       = self.dfFile,
                                 minTrnDate   = self.minTrnDate,
                                 maxTrnDate   = maxTrnDate,
                                 maxOosDate   = maxOosDate,
                                 trmFuncDict  = self.trmFuncDict,
                                 optType      = self.optType,
                                 maxOptItrs   = self.maxOptItrs,
                                 optGTol      = self.optGTol,
                                 optFTol      = self.optFTol,
                                 stepSize     = self.stepSize,
                                 factor       = self.factor,
                                 regCoef      = regCoef,
                                 regL1Wt      = 0.0,
                                 nPca         = None,
                                 diagFlag     = DIAG_FLAG,
                                 srelFlag     = SREL_FLAG,
                                 endBcFlag    = True,
                                 srcTerm      = self.srcTerm,
                                 atnFct       = self.atnFct,
                                 mode         = self.mode,
                                 logFileName  = self.logFileName,
                                 verbose      = self.verbose        )

            ecoMfds.append( ecoMfd )

        return ecoMfds

    def optReg( self ):

        if not self.optRegFlag:
            return

        self.logger.info( 'Running optimization for regularization coefficient!' )

        options    = {    'disp'       : False,
                          'gtol'       : 1e-05,
                          'eps'        : 1e-03,
                          'return_all' : False,
                          'maxiter'    : 200,
                          'norm'       : np.inf         }

        res  = sp.optimize.minimize( self.optRegFunc,
                                     x0      = 0.0,
                                     method  = 'CG',
                                     options = options   )
        self.logger.info( res )
        self.logger.info( res[ 'x' ] )

        return res[ 'x' ]

    def optRegFunc( self, regCoef ):

        minDt   = pd.to_datetime( self.minTrnDate )
        maxDt   = pd.to_datetime( self.maxTrnDate )
        minYrs  = int( ( maxDt.year - minDt.year ) / 2.0 )
        incYrs  = 1.0
        val     = 0.0

        ecoMfds = self.crossVal( minYrs  = minYrs,
                                 incYrs  = incYrs,
                                 regCoef = regCoef )

        for ecoMfd in ecoMfds:
            val += ecoMfd.getOosMerit()

        fct = len( ecoMfds )
        if fct > 0:
            fct = 1.0 / fct

        val *= fct

        return val

    def validate( self ):

        validFlag = True

        oosMeritAvg = self.optRegFunc( self.regCoef )

        self.logger.info( 'Average OOS merit:', oosMeritAvg )

        validFlag = validFlag & (oosMeritAvg >= self.minMerit)

        return validFlag


from typing import Optional, List

import instructions

class Argument:
    label: str = None
    immediate: int = None
    offset: int = None

    @classmethod
    def from_label(cls, label: str, offset: int = 0):
        argument = Argument()
        argument.label = label
        argument.offset = offset
        return argument

    @classmethod
    def from_immediate(cls, immediate: int):
        argument = Argument()
        argument.immediate = immediate
        return argument

    def is_label(self) -> bool:
        return self.label is not None

    def __repr__(self) -> str:
        if self.is_label():
            suffix = ''
            if self.offset != 0:
                sign = '+' if self.offset > 0 else '-'
                suffix = f'{sign}{self.offset}'
            return f'{self.label}{suffix}'
        else:
            return str(self.immediate)

    def __eq__(self, other):
        return self.label == other.label and self.immediate == other.immediate and self.offset == other.offset

class AsmLine:
    is_data: bool = False
    mnemonic: str = None
    argument: Argument = None
    address: int = None
    label: str = None

    def is_relative_branch(self) -> bool:
        return self.mnemonic in ['BR', 'BRZ', 'BRN']

    def is_non_relative_branch(self) -> bool:
        return self.mnemonic in [
            'LDAM',
            'LDBM',
            'STAM',
            'LDAC',
            'LDBC',
            'LDAP',
            'LDAI',
            'LDBI',
            'STAI',
            'BRB',
        ]

    @classmethod
    def from_instruction(cls, mnemonic: str, argument: Argument):
        asm_line = AsmLine()
        asm_line.mnemonic = mnemonic
        asm_line.argument = argument
        return asm_line

    @classmethod
    def from_data(cls, argument: Argument):
        asm_line = AsmLine()
        asm_line.argument = argument
        asm_line.is_data = True
        return asm_line

    def __repr__(self) -> str:
        prefix = ''

        if self.label is not None:
            prefix = f'{self.label} '

        if self.is_data:
            asm_line_str = f'DATA {self.argument}'
        else:
            asm_line_str = f'{self.mnemonic} {self.argument}'

        return f'{prefix}{asm_line_str}'

    def __eq__(self, other):
        return self.is_data == other.is_data and \
               self.mnemonic == other.mnemonic and \
               self.argument == other.argument and \
               self.address == other.address and \
               self.label == other.label

    def __copy__(self):
        result = Argument()
        result.is_data = self.is_data
        result.mnemonic = self.mnemonic
        result.argument = self.argument
        result.address = self.address
        result.label = self.label

        return result

    def to_int(self) -> int:
        if self.is_data:
            return self.argument.immediate
        else:
            opcode = instructions.MNEMONICS.index(self.mnemonic)
            argument = 0 if self.argument is None else self.argument.immediate
            instruction = (opcode << 4) + argument
            return instruction

    def is_prefix(self) -> bool:
        return self.mnemonic == 'PFIX'

def asm_lines_to_machine_code(asm_lines: List[AsmLine]) -> List[int]:
    return [asm_line.to_int() for asm_line in asm_lines]


from num2words import num2words
from .name_patterns import number_patterns
import random

def digits(num):
    return len(str(num))

def reverse(num):
    return str(num)[::-1]

def even(num):
    return 'Yes' if num % 2 == 0 else 'No'

def odd(num):
    return 'Yes' if num % 2 != 0 else 'No'

def prime(num):
    c = 0
    for i in range(1,num+1):
        if num % i == 0:
            c+=1
    return 'Yes' if c == 2 else 'No'

def armstrong(num):
    num_str = str(num)
    num_digits = len(num_str)
    sum_of_powers = sum(int(digit) ** num_digits for digit in num_str)
    return 'Yes' if num == sum_of_powers else 'No'

# print(armstrong(100))

def magic(num):
    # Convert the number to a string
    num_str = str(num)

    # Calculate the sum of digits
    digit_sum = sum(int(digit) for digit in num_str)

    # Check if the digit sum is equal to the product of digits
    return 'Yes' if digit_sum * digit_sum == num else 'No'

def perfect(num):
    if num <= 0:
        return False
    divisors = [divisor for divisor in range(1, num) if num % divisor == 0]
    divisors_sum = sum(divisors)
    return 'Yes' if num == divisors_sum else 'No'

# def sum(num):
#     return sum(divisor for divisor in range(1, num) if num % divisor == 0)

def collatz(num):
    sequence = [num]
    while num != 1:
        if num % 2 == 0:
            num = numr // 2
        else:
            num = num * 3 + 1
        sequence.append(num)
    return sequence

def binary(num):
    return bin(num)[2:]

def octal(num):
    return oct(num)[2:]

def hexadecimal(num):
    return hex(numr)[2:]

def word(num):
    word = num2words(num)
    return word.replace('-',' ').title()

def factorial(num):
    if num == 0:
        return 1
    else:
        return num * factorial(num - 1)

def palindrome(num):
    return 'Yes' if str(num) == str(num)[::-1] else 'No'

def fibonacci(num):
    if num < 0:
        return False

    a, b = 0, 1
    while b < num:
        a, b = b, a + b

    return 'Yes' if b == num else 'No'

def prime_factorization(num):
    factors = []
    for i in range(2,num+1):
        if num % i == 0:
            factors.append(i)
    factors.remove(num)
    return factors

def table(num):
    try:
        table_string = ''
        table_patterns = (
        f"Here is the {num}th math table:",
        f"I have the {num}th math table for you:",
        f"Let's look at the {num}th math table:",
        f"The {num}th math table is as follows:",
        f"Here's the table for {num}:",
        f"Behold the {num}th math table:",
        f"Prepare to witness the {num}th math table:",
        f"Unlocking the secrets of the {num}th math table:",
        f"The {num}th math table holds valuable information:",
        f"Exploring the depths of the {num}th math table:",
        f"Unveiling the mysteries of the {num}th math table:",
        f"Discovering the patterns in the {num}th math table:",
        f"Behold, the majestic {num}th math table:",
        f"Embark on a journey through the {num}th math table:",
        f"Prepare to be amazed by the {num}th math table:",
        f"Let's delve into the {num}th math table:",
        f"The {num}th math table awaits your attention:",
        f"Unlocking the power of the {num}th math table:",
        f"Behold the beauty of the {num}th math table:",
        f"Delving into the wonders of the {num}th math table:"    )
        for i in range(1,11):
            table_string+= f"
{num} X {i} = {num*i}

"
        return random.choice(table_patterns)+'

'+table_string
    except:
        return 'Please provide number to generate math table'

def even_numbers(from_,to_):
    even_numbers_list = []
    for i in range(from_,to_+1):
        if i % 2 == 0:
            even_numbers_list.append(str(i))
    return random.choice(number_patterns).replace('{number_category}', 'Even').replace('{start}', str(from_)).replace('{end}', str(to_)) +'
    '+', '.join(even_numbers_list)+''

def odd_numbers(from_,to_):
    even_numbers_list = []
    for i in range(from_,to_+1):
        if i % 2 != 0:
            even_numbers_list.append(str(i))
    return random.choice(number_patterns).replace('{number_category}', 'Odd').replace('{start}', str(from_)).replace('{end}', str(to_)) +'
    '+', '.join(even_numbers_list)+''

def prime_numbers(from_,to_):
    prime_numbers_list = []
    for num in range(from_,to_+1):
        c = 0
        for i in range(1,num+1):
            if num % i == 0 :
                c += 1
        prime_numbers_list.append(str(num)) if c == 2 else 0
    return random.choice(number_patterns).replace('{number_category}', 'Prime').replace('{start}', str(from_)).replace('{end}', str(to_)) +'
    '+', '.join(prime_numbers_list)+''

def fibonacci_numbers(from_,to_):
    fibonacci_numbers = [0, 1]
    while fibonacci_numbers[-1] < to_:
        next_number = fibonacci_numbers[-1] + fibonacci_numbers[-2]
        fibonacci_numbers.append(next_number)
    fibonacci_numbers = [str(num) for num in fibonacci_numbers if from_ <= num <= to_]
    return random.choice(number_patterns).replace('{number_category}', 'Fibonacci').replace('{start}', str(from_)).replace('{end}', str(to_)) +'
    '+', '.join(fibonacci_numbers)+''

def explain_number(num):
    num = int(num)
    value = f"""

{num}

        {' '*4}The given number is {num}({word(num)}). It is {'an Even' if even(num) == 'Yes' else 'not an Even'} number. It is {'an Odd' if odd(num) == 'Yes' else 'not an Odd'} number. It is {'a Prime' if prime(num) == 'Yes' else 'not a Prime'} number. It is {'a Perfect' if perfect(num) == 'Yes' else 'not a Perfect'} number. It is {'Armstrong' if armstrong(num) == 'Yes' else 'not an Armstrong'} number. It is {'a Magic' if magic(num) == 'Yes' else 'not a Magic'} number. It is {'a Fibonacci' if fibonacci(num) == 'Yes' else 'not a'} Fibonacci number.

        No of digits : {digits(num)}

        Even Number : {even(int(num))}

        Odd Number : {odd(int(num))}

        Prime Number : {prime(int(num))}

        Perfect Number : {perfect(int(num))}

        Armstrong Number : {armstrong(int(num))}

        Magic Number : {magic(int(num))}

        Fibonacci Number : {fibonacci(int(num))}

"""
    return value


import pytest
from flask import Flask, json
from extensions import flask_app
from helpers import get_model_from_pickle

@pytest.fixture
def client():
    flask_app.config['TESTING'] = True
    with flask_app.test_client() as client:
        yield client

def test_get_movies_mocked_one(client, mocker):
    mocker.patch('helpers.get_model_from_pickle', return_value = None)
    mocker.patch('app.recommend_top_20_movies_for_user', return_value = "harry+potter,star+wars")
    response = client.get('/recommend/2')
    assert(response.status == '200 OK')
    assert(response.text == "harry+potter,star+wars")

def test_get_movies_mocked_two(client, mocker):
    mocker.patch('helpers.get_model_from_pickle', return_value = None)
    mocker.patch('app.recommend_top_20_movies_for_user', return_value = "harry+potter,star+wars")
    response = client.get('/recommend/-2')
    assert(response.status == '400 BAD REQUEST')

def test_get_movies_mocked_three(client, mocker):
    mocker.patch('helpers.get_model_from_pickle', return_value = None)
    mocker.patch('app.recommend_top_20_movies_for_user', return_value = "harry+potter,star+wars")
    response = client.get('/recommend/badinput')
    assert(response.status == '400 BAD REQUEST')

def test_get_movies_bad_unmocked_one(client, mocker):
    mocker.patch('helpers.get_model_from_pickle', return_value = get_model_from_pickle("svd_model"))
    response = client.get('/recommend/-2')
    assert(response.status == '400 BAD REQUEST')

def test_get_movies_unmocked(client, mocker):
    mocker.patch('app.get_model', return_value = get_model_from_pickle("svd_model"))
    response = client.get('/recommend/2')
    assert(response.status == '200 OK')
    res = "thrill+ride+the+science+of+fun+1997,vincent+1982,chaotic+ana+2007,for+the+birds+2000,a+very+social+secretary+2005,keeping+the+promise+1997,sweepers+1999,the+madagascar+penguins+in+a+christmas+caper+2005,the+true+meaning+of+christmas+specials+2002,asfalto+2000,the+bleeding+2009,mascara+1999,the+manzanar+fishing+club+2012,paths+of+hate+2011,season+for+assassins+1975,children+2006,so+much+so+fast+2006,home+alone+2+lost+in+new+york+1992"
    assert(response.text == res)

def test_get_movies_bad_two_unmocked(client, mocker):
    mocker.patch('app.get_model', return_value = get_model_from_pickle("svd_model"))
    response = client.get('/recommend/invalid')
    assert(response.status == '400 BAD REQUEST')


import json
from . import configutil
import os
import errno

def openJSON(filepath):
    """ open a json file and return a JSON object """
    with open(filepath) as data_file:
        data = json.load(data_file)
    return data

def save(data):
    """ save some data into the output file """
    with open(configutil.getOutputFilePath(),"w") as file:
        file.write(data)

def mkdir(path):
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            raise


import datetime
import uuid

from pony import orm

def define_discordserver(db):
    class DiscordServer(db.Entity):
        id = orm.PrimaryKey(uuid.UUID, default=uuid.uuid4)
        state = orm.Required(int, min=1,
                             max=4)  # 1 = waiting for approval, 2 = public, 3 = expired, 4 = requeued (eg channel change)
        invite_code = orm.Required(str, unique=True)
        server_id = orm.Required(int, unique=True, size=64)
        name = orm.Required(str, max_len=32)
        description = orm.Optional(str, max_len=100)
        invitee_id = orm.Required(int, size=64)
        submitted_at = orm.Required(datetime.datetime)
        category_channel_name = orm.Required(str)
        genre_category_name = orm.Optional(str)
        last_checked = orm.Required(datetime.datetime)
        # deprecated
        index_message_id = orm.Optional(int, size=64)


from manager_settings import *

import os
import pygit2
import time
import subprocess
import shutil
import multiprocessing

class BuildManager(object):
    def __init__(self, build_dir):
        if not os.path.exists(build_dir):
            os.mkdir(build_dir)

        try:
            self.repo = pygit2.Repository(TUNGSTEN_CLONE_DIR)
        except Exception:
            self.repo = pygit2.clone_repository(TUNGSTEN_REPO, TUNGSTEN_CLONE_DIR)

        self.builds = {}
        for path in os.listdir(build_dir):
            success_dir = os.path.join(build_dir, path, "build.success")
            tungsten = os.path.join(build_dir, path, "build", "release", "tungsten")
            if os.path.exists(success_dir):
                # confirm this is a commit
                if self.repo.get(path) is None:
                    continue

                self.builds[path] = {"exec": tungsten, "success": True}

    def get_latest_commits(self, num):
        latest = self.repo.lookup_branch("origin/master", pygit2.GIT_BRANCH_REMOTE).target
        count = 1
        for commit in self.repo.walk(latest, pygit2.GIT_SORT_TOPOLOGICAL):
            yield commit.oid.hex
            count += 1
            if count > num:
                return

    def get_latest_commit(self):
        self.fetch()
        return self.repo.lookup_branch("origin/master", pygit2.GIT_BRANCH_REMOTE).target.hex

    def get_latest_built_commit(self):
        for commit in self.get_latest_commits(10):
            ex = self.get_exec(commit)
            if ex:
                return ex

    def get_exec(self, commit):
        if commit not in self.builds:
            return None
        if not self.builds[commit].get('success'):
            return None
        return self.builds[commit]['exec']

    def fetch(self):
        t = self.repo.remotes['origin'].fetch()
        while (t.received_objects < t.total_objects):
            time.sleep(1)

    def build(self, commit=None, force=False):
        self.fetch()

        if commit is None: # build latest
            commit = self.get_latest_commit()

        git_commit = self.repo.get(commit)
        if git_commit is None:
            raise ValueError("Not a valid commit")
        if git_commit.type != pygit2.GIT_OBJ_COMMIT:
            raise ValueError("Object is not a commit!")

        self.repo.reset(commit, pygit2.GIT_RESET_HARD)

        build_root = os.path.join(TUNGSTEN_BUILD_DIR, commit)
        lock_dir = os.path.join(build_root, "build.lock")
        success_dir = os.path.join(build_root, "build.success")
        fail_dir = os.path.join(build_root, "build.fail")

        if os.path.exists(fail_dir):
            if not force:
                raise Exception("Build failed already, will not build again")
        if os.path.exists(success_dir):
            if not force:
                return

        if os.path.exists(build_root):
            shutil.rmtree(build_root)

        os.mkdir(build_root)
        os.mkdir(lock_dir)

        if not os.path.exists(build_root):
            raise Exception("Failed to make build_root %r" % build_root)

        print(build_root)
        p = subprocess.Popen([os.path.join(TUNGSTEN_CLONE_DIR, "setup_builds.sh")], shell=True, cwd=build_root)
        if p.wait() != 0:
            os.mkdir(fail_dir)
            os.rmdir(lock_dir)
            self.builds[commit] = {"success": False}
            raise Exception("Failed to setup_builds")

        p = subprocess.Popen(["make", "-j", str(multiprocessing.cpu_count())], cwd=os.path.join(build_root, "build", "release"))
        if p.wait() != 0:
            os.mkdir(fail_dir)
            os.rmdir(lock_dir)
            self.builds[commit] = {"success": False}
            raise Exception("Failed to build")

        if not os.path.exists(os.path.join(build_root, "build", "release", "tungsten")):
            os.mkdir(fail_dir)
            os.rmdir(lock_dir)
            self.builds[commit] = {"success": False}
            raise Exception("Failed to build")

        self.builds[commit] = {"exec": os.path.join(build_root, "build", "release", "tungsten"),
                "success": True}

        os.mkdir(success_dir)
        os.rmdir(lock_dir)


"""core functions."""

from pathlib import Path
from random import choices

import numpy as np
import pandas as pd

from wt.io import glob_str, yamlr, yamlw

def __batch_prepare_card_uuids_and_versions(path):
    import uuid
    cards = []
    p = Path(path)
    files = p.glob(glob_str)
    for file in files:
        with open(file, 'r+') as fid:
            doc = yamlr.load(fid)
            doc['version'] = 1
            doc['uuid'] = str(uuid.uuid4())
            cards.append(doc.copy())
            fid.seek(0)
            fid.truncate()
            yamlw.dump(doc, fid)
    return cards

def prep_cards(database, classes, types=None):
    """Prepares the set of valid cards for a search on classes and types.

    Parameters
    ----------
    database: `pd.DataFrame`
        card database
    classes : iterable
        iterable of class(es) to draw valid cards for
    types : iterable, optional
        types to further filter by; card can be any of the specified types

    Returns
    -------
    `pandas.DataFrame`
        filtered dataframe of valid cards

    """
    # begin all valid sets with all generic cards
    class_masks = [database['class'] == 'generic']

    # for each class specified, create a mask on the database of cards which have that class
    for class_ in classes:
        class_masks.append(database['class'] == class_)

    # concatonate the masks and accept values where any mask passes
    class_mask = pd.concat(class_masks, axis=1).any(axis=1)
    total_mask = class_mask

    # if some card types are specified, repeat class masking for types
    if types:
        types_masks = []
        for type_ in types:
            types_masks.append(database[database['types'].apply(lambda x: type_ in x)])
        type_mask = pd.concat(types_masks, axis=1).any(axis=1)

        # finally, find the mask which satisfies both the class and type masks simultaneously
        total_mask = pd.concat((class_mask, type_mask), axis=1)
        total_mask = total_mask.replace(np.NaN, False).all(axis=1)

    return database[total_mask]  # return cards satisfying this mask

def draw_cards(valid_cards, n=1):
    """Draw card(s).

    Parameters
    ----------
    valid_cards: `pd.DataFrame`
        card database
    n: `int`
        number of cards to draw

    Returns
    -------
    iterable of `dict`s
        iterable containing a dict for each card

    """
    uuids = valid_cards.uuid.values
    weights = valid_cards.draw_chance.values
    id_ = choices(uuids, weights, k=n)
    outmask = valid_cards.uuid.isin(id_)
    chosen_cards = valid_cards[outmask]
    dictionaries = chosen_cards.to_dict(orient='records')
    return dictionaries

def prep_and_draw_cards(database, classes, types=None, n=1):
    """Prepares valid cards and draws a card for the user.

    This is a macro that calls the preparation and draw functions, it is a convenience function
    for when the valid cards for a particular case are not already cached.

    Parameters
    ----------
    valid_cards: `pd.DataFrame`
        card database
    classes : iterable
        iterable of class(es) to draw valid cards for
    types : iterable, optional
        types to further filter by; card can be any of the specified types
    n: `int`
        number of cards to draw

    Returns
    -------
    iterable of `dict`s
        iterable containing a dict for each card

    """
    valid_cards = prep_cards(database, classes, types)
    return draw_cards(valid_cards, n)