import pandas as pd
import numpy as np
import os

PATH = 'data/movielens/'
TRAINFILE = PATH + 'train.csv'
TESTFILE = PATH + 'test.csv'
VALIDFILE = PATH + 'val.csv'
MAPFILE=PATH+'item2id.map'

def get_item():
    train = pd.read_csv(TRAINFILE, sep='\t')
    valid = pd.read_csv(VALIDFILE, sep='\t')
    test = pd.read_csv(TESTFILE, sep='\t')
    data = pd.concat([train, valid, test])
    return data.item.unique()

def load_data(f, max_len):
    if os.path.exists(MAPFILE):
        item2idmap = {}
        with open(MAPFILE,'r') as fi:
            lines=fi.readlines()
            for line in lines:
                k, v = line.strip().split('\t')
                item2idmap[int(k)] = int(v)
    else:
        items = get_item()
        item2idmap = dict(zip(items, range(items.size)))
        with open(MAPFILE, 'w') as fo:
            for k, v in item2idmap.items():
                fo.write(str(k) + '\t' + str(v) + '\n')
    n_items = len(item2idmap)
    data = pd.read_csv(f, sep='\t')
    data['item'] = data['item'].map(item2idmap)
    data = data.sort_values(by=['Time']).groupby('user')['item'].apply(list).to_dict()
    new_x = []
    new_y = []
    for k, v in data.items():
        if len(v) < max_len + 1:
            continue
        x = v[:max_len]
        y = [0] * n_items
        y[v[max_len]] = 1
        new_x.append(x)
        new_y.append(y)
    return new_x, new_y, n_items

def load_train(max_len):
    return load_data(TRAINFILE, max_len)

def load_valid(max_len):
    return load_data(VALIDFILE, max_len)

def load_test(max_len):
    return load_data(TESTFILE, max_len)

def cal_eval(top_k_index,labels):
    users = np.shape(top_k_index)[0]
    top_k = np.shape(top_k_index)[1]
    hits, ndcg, mrr = 0, 0.0, 0.0
    for i in range(users):
        cur_user = top_k_index[i]
        for j in range(top_k):
            if labels[i] == cur_user[j]:
                hits += 1
                mrr += 1 / (1 + j)
                dcg = 1 / np.log2(1 + 1 + j)
                idcg = 1 / np.log2(1 + 1)
                ndcg += dcg / idcg
                break
    return hits / users,ndcg / users,mrr / users

if __name__=="__main__":
    load_train(16)


import urllib2
import json

headers = {'Content-Type': 'application/json; charset=utf-8'}

XXX_HOST = "http://xxx.xxx.com/xxx-app/"

# post请求，json格式数据

def post_json(url, header, request_data):
    req = urllib2.Request(url, request_data, header)
    page = urllib2.urlopen(req)
    res = page.read()
    page.close()
    return res

YYY_HOST = "http://yyy.yyy.com/yyy-app/"

# get请求

def get_(param1, param2):
    url = YYY_HOST + "yyyy/yyyy?param1=" + \
        str(param1) + "&param2=" + str(param2) + "&param3=VIP"
    req = urllib2.Request(url)
    page = urllib2.urlopen(req, timeout=5000)
    res = page.read()
    page.close()
    return json.loads(res)["data"]


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.core.management.base import BaseCommand, CommandError
from cards.search import searchservice
from cards.models import Card, BaseCard
from cards.models import PhysicalCard
import json

from django.utils import dateparse

import codecs

import sys

from elasticsearch import Elasticsearch, exceptions

from kitchen.text.converters import getwriter

class Command(BaseCommand):

    def add_arguments(self, parser):
        parser.add_argument('--full', dest='full', action='store_true',
                            help='Rebuild the entire index, not just data that has changed.')

    def handle(self, *args, **options):
        # check the card index
        self.checkCardIndex()

        self.checkCardnameIndex()

        # first, let's get the most recent doc change in ES:
        lmt_q = {
            "query": {"match_all": {}},
            "size": 1,
            "sort": [
                {
                    "_update_datetime": {
                        "order": "desc"
                    }
                }
            ]
        }
        lmt_res = searchservice.search(index='card', body=lmt_q)
        last_time = None
        try:
            sys.stdout.write("timestamp: {}\n".format(json.dumps(lmt_res['hits']['hits'][0]['_source']['_update_datetime'])))
            last_time = dateparse.parse_datetime(lmt_res['hits']['hits'][0]['_source']['_update_datetime'])
        except KeyError:
            # no doc, I guess
            pass
        sys.stdout.write("'card' index last updated {}\n".format(last_time))

        pcs = None

        if not last_time or options['full']:
            sys.stdout.write("Re-indexing entire card database...\n")
            pcs = PhysicalCard.objects.all()
            #pcs = PhysicalCard.objects.filter(pk__gte=15200, pk__lt=15800)
        else:
            cards = Card.objects.filter(updated_at__gte=last_time)
            bc_ids = {}
            for card in cards:
                bc_ids[card.basecard_id] = True
            basecards = BaseCard.objects.filter(updated_at__gte=last_time)
            pc_ids = {}
            for basecard in basecards:
                #sys.stderr.write("bc -> pc {}\n".format(basecard.physicalcard_id))
                pc_ids[basecard.physicalcard_id] = True
            basecards = BaseCard.objects.filter(id__in=[bc_id for bc_id in bc_ids])
            for basecard in basecards:
                pc_ids[basecard.physicalcard_id] = True
            pcs = PhysicalCard.objects.filter(id__in=[pc_id for pc_id in pc_ids])

        total_count = pcs.count()
        counter = 0
        sys.stdout.write("Cards to index: {}\n".format(total_count))
        for pc in pcs:
            searchservice.index_physicalcard(pc)
            counter += 1
            if counter % 100 == 0:
                sys.stdout.write("{:>6} : {:>4.0%} complete\n".format(counter, float(counter) / float(total_count)))
        sys.stdout.write("Complete!\n")

    def checkCardIndex(self):
        index_name = 'card'
        try:
            val = searchservice._es.indices.get_settings(index_name)
        except exceptions.NotFoundError:
            sys.stdout.write("'{}' index does not exist. Creating it...\n".format(index_name))
            searchservice._es.indices.create(index=index_name,
                                             body={})
        return True

    def checkCardnameIndex(self):
        index_name = 'cardname'
        cur_mappings = None
        try:
            cur_mappings = searchservice._es.indices.get_mapping(index_name)
        except exceptions.NotFoundError:
            sys.stdout.write("'{}' index does not exist. Creating it...\n".format(index_name))
            with open('elasticsearch/cardname_settings.json', 'r') as cnsjson_fh:
                cns = json.load(cnsjson_fh)
                sys.stdout.write("Creating '{}' index with:\n{}\n".format(index_name, json.dumps(cns, indent=2)))
                searchservice._es.indices.create(index=index_name,
                                                 body=cns)
        if cur_mappings:
            # we need to validate that there is an ngram field on the "name" property. If there isn't, we should bail.
            # cur_settings['cardname']['settings']['index']
            # BOOKMARK - check to see if there is an ngram mappings on "name"
            try:
                ngram = cur_mappings[index_name]['mappings']['cardname']['properties']['name']['fields']['ngram']
                slug = cur_mappings[index_name]['mappings']['cardname']['properties']['slug']
                lmvid = cur_mappings[index_name]['mappings']['cardname']['properties']['latest_multiverseid']
            except KeyError as ke:
                sys.stdout.write("{} index does not have an 'ngram' field on 'name'.\n".format(index_name))
                sys.stdout.write("{} index Mappings:\n{}\n".format(index_name, json.dumps(cur_mappings, indent=2)))
                sys.stdout.write("Aborting.\n")
                # You may need to drop the old index and start over.
                sys.stdout.write("Try this to get the index started...\n")
                sys.stdout.write("curl -X DELETE '{}:{}/{}?pretty'\n".format(searchservice._host, searchservice._port, index_name))
                sys.stdout.write(
                    "curl -X PUT '{}:{}/{}?pretty' -H 'Content-Type: application/json' -d @elasticsearch/cardname_settings.json\n".format(
                        searchservice._host,
                        searchservice._port,
                        index_name))
                raise ke
        return True


class Solution:
    def findWinners(self, matches):
        ans = [[],[]]
        games = {}
        for game in matches:
            if not (game[0] in games): games[game[0]] = 0
            if game[1] in games:
                games[game[1]] += 1
                continue
            else: games[game[1]] = 1
        for key in dict(sorted(games.items())):
            if games[key] > 1:
                continue
            elif games[key] == 1: ans[1].append(key)
            else: ans[0].append(key)
        return ans

if __name__ == "__main__":
    test = Solution()
    print(test.findWinners([[1,3],[2,3],[3,6],[5,6],[5,7],[4,5],[4,8],[4,9],[10,4],[10,9]]))
    pass


from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.decorators import login_required
from django.http import (HttpRequest, HttpResponse, HttpResponseNotFound,
                         HttpResponseRedirect)
from django.shortcuts import redirect, render
from django.urls import reverse_lazy
from django.views.decorators.cache import cache_page

from core import constants as const
from core.db_queries import Query

INDEX_URL     = reverse_lazy('questions:index')
QUESTIONS_URL = reverse_lazy('questions:questions')
FINISH_URL    = reverse_lazy('questions:finish_test')

# @cache_page(timeout=20, key_prefix='index')  # 10 minutes
def index(request: HttpRequest):
    """Обработчик для главной страницы.
    """
    context = {
        'title'           : const.TITLE,
        'card_header'     : const.INDEX_CARD_HEADER,
        'index_page_text' : const.INDEX_PAGE_TEXT,
        'maximum_grade'   : Query.get_maximum_grade(),
    }
    return render(request, 'index.html', context)

# @cache_page(timeout=60, key_prefix='rating')  # 1 minute
def rating(request: HttpRequest):
    """Показывает рейтинг пользователей.
    """
    context = {
        'title'   : const.TITLE,
        'header'  : const.ALL_RESULTS_CARD_HEADER,
        'results' : Query.get_users_rating()
    }
    return render(request, 'questions/results.html', context)

@login_required
def my_results(request: HttpRequest):
    """Показывает все результаты текущего пользователя.
    """
    user: AbstractBaseUser = request.user
    context = {
        'title'   : const.TITLE,
        'header'  : const.MY_RESULTS_CARD_HEADER,
        'results' : Query.get_user_results(user)
    }
    return render(request, 'questions/results.html', context)

def get_question(
    request: HttpRequest
):
    """Выводит очередной вопрос и учитывает ответы.
    Если предыдущий тест был случайно прерван, продолжит предыдущий тест.
    """
    user: AbstractBaseUser = request.user
    if user.is_anonymous:
        return redirect(INDEX_URL)

    question = Query.get_next_question(user=user)
    if question is None:
        return redirect(FINISH_URL)

    context = {
        'title'       : const.TITLE,
        'question'    : question,
        'button_type' : ('radio', 'checkbox')[question.many_answers]
    }

    return render(request, 'questions/question.html', context)

@login_required
def add_answer(
    request: HttpRequest,
    question_pk: int
):
    """Учитывает переданные пользователем ответы.
    """
    question = Query.get_current_question(
        question_pk=question_pk
    )
    if question is None:
        return HttpResponseNotFound('
Page not found
')

    context = {
        'title'       : const.TITLE,
        'question'    : question,
        'button_type' : ('radio', 'checkbox')[question.many_answers]

    }
    choice = request.POST.getlist('answer')

    if not choice:
        context['error_message'] = const.ERR_NO_ANSWERS
        return render(request, 'questions/question.html', context)

    if not Query.update_result(
        user        =request.user,
        question_pk =question_pk,
        choice      =choice
    ):
        context['error_message'] = const.ERR_FALSE_ANSWERS
        return render(request, 'questions/question.html', context)

    return redirect(QUESTIONS_URL)

def to_finish_test(
    request: HttpRequest
) -> HttpResponse | HttpResponseRedirect:
    """Завершает тест.
    Если пользователь не проходил тестов, либо пытается завершить без
    отмеченных ответов, перекидывает на главную страницу.
    Начатый тест будет продолжен в дальнейшем.
    """
    user: AbstractBaseUser = request.user
    if user.is_anonymous:
        return redirect(INDEX_URL)

    closed, current_result = Query.close_last_result(user)

    if not closed:
        return redirect(INDEX_URL)

    context = {
        'title'  : const.TITLE,
        'header' : const.FINISH_CARD_HEADER,
        'result' : current_result
    }
    return render(request, 'questions/finish.html', context)


import os
import torch
import torchvision
import random
import pandas as pd
import numpy as np
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image

import cv2

import torch.nn.functional as F
import torchvision.transforms as transforms
import torchvision.models as models
from torch.utils.data import Dataset, random_split, DataLoader
from torchvision.datasets import ImageFolder
from torchvision import models
from torch import optim
from torchsummary import summary

from math import atan2, degrees

class CatPicture():

    def __init__(self, filename):

        self.which_p = 1
        self.which_d = 1
        self.wear_list = [0, 0, 0]

        self.ori_filename = filename

        tmp_idx = filename.rfind(".")
        self.short_filename = filename[:tmp_idx]

        def resize_img(im):
            old_size = im.shape[:2]  # old_size is in (height, width) format
            ratio = float(img_size) / max(old_size)
            new_size = tuple([int(x * ratio) for x in old_size])
            # new_size should be in (width, height) format
            im = cv2.resize(im, (new_size[1], new_size[0]))
            delta_w = img_size - new_size[1]
            delta_h = img_size - new_size[0]
            top, bottom = delta_h // 2, delta_h - (delta_h // 2)
            left, right = delta_w // 2, delta_w - (delta_w // 2)
            new_im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT,
                                        value=[0, 0, 0])
            return new_im, ratio, top, left

        class CatDataset(Dataset):

            def __init__(self, images, labels, transform):

                self.imgs = images
                self.labels = labels
                self.transform = transform

            def __len__(self):

                return len(self.imgs)  # return DataSet 長度

            def __getitem__(self, idx):

                image = self.imgs[idx]
                image = image[..., ::-1].copy()
                image = self.transform(image)
                label = np.array(self.labels[idx])

                return image, label  # return 模型訓練所需的資訊

        def Catface_dataloader(img):

            test_inputs = []
            test_inputs.append(img)
            test_labels = [0 for i in range(4)]

            test_dataloader = DataLoader(CatDataset(test_inputs, test_labels, test_transformer),
                                         batch_size=1, shuffle=False)
            return test_dataloader

        def Lmks_dataloader(img):

            test_inputs = []
            test_inputs.append(img)
            test_labels = [0 for i in range(18)]
            test_dataloader = DataLoader(CatDataset(test_inputs, test_labels, test_transformer),
                                         batch_size=1, shuffle=False)
            return test_dataloader

        class CatFaceModule(nn.Module):

            def __init__(self):
                super(CatFaceModule, self).__init__()
                v = torch.hub.load('pytorch/vision:v0.6.0',
                                   'mobilenet_v2', pretrained=True)
                v.classifier[1] = nn.Linear(v.last_channel, 4)
                self.layer1 = v

            def forward(self, x):
                out = self.layer1(x)
                return out

        class LmksModule(nn.Module):
            def __init__(self):
                super(LmksModule, self).__init__()
                v = torch.hub.load('pytorch/vision:v0.6.0',
                                   'mobilenet_v2', pretrained=True)
                v.classifier[1] = nn.Linear(v.last_channel, 18)
                self.layer1 = v

            def forward(self, x):
                out = self.layer1(x)
                return out

        # main program

        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        img_size = 224
        normalize = transforms.Normalize(
            mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])

        test_transformer = transforms.Compose([
            transforms.ToTensor(),
            normalize
        ])

        # the path of models
        cat_face_model_path = "mobilenet_RMSELoss500.ph"
        lmks_model_path = "mobilenet_RMSELoss100_36.ph"

        # load the models
        cat_model = CatFaceModule().to(device)
        cat_model.load_state_dict(torch.load(cat_face_model_path))
        cat_model.eval()

        lmks_model = LmksModule().to(device)
        lmks_model.load_state_dict(torch.load(lmks_model_path))
        lmks_model.eval()

        # the path of the image you want to test
        img_path = filename
        # read the image
        img = cv2.imread(img_path)
        ori_img = img.copy()
        result_img = img.copy()
        img, ratio, top, left = resize_img(img)
        # plt.figure()
        # plt.imshow(img)
        predicted = []

        # catface predicted
        catface_dataloader = Catface_dataloader(img)
        for i, (x, label) in enumerate(catface_dataloader):
            with torch.no_grad():
                x, label = x.to(device), label.to(device)
                output = cat_model(x)
                # loss = criterion(output, label.long())
                predicted = output.data[0].reshape((-1, 2))

        # the position of the cat face box
        pre_bb = predicted.cpu().numpy()
        # print(pre_bb)

        # the positoin of the cat face box when it at the origin image
        ori_bb = ((pre_bb - np.array([left, top])) / ratio).astype(np.int)
        # print(ori_bb)

        # cut the face image
        center = np.mean(ori_bb, axis=0)
        face_size = max(np.abs(ori_bb[1] - ori_bb[0]))
        new_bb = np.array([
            center - face_size * 0.6,
            center + face_size * 0.6
        ]).astype(np.int)
        new_bb = np.clip(new_bb, 0, 99999)
        face_img = ori_img[new_bb[0][1]:new_bb[1]
                           [1], new_bb[0][0]:new_bb[1][0]]
        # plt.figure()
        # plt.imshow(face_img)

        face_img, face_ratio, face_top, face_left = resize_img(face_img)

        # landmark prediction
        lmks_dataloader = Lmks_dataloader(face_img)
        for i, (x, label) in enumerate(lmks_dataloader):
            with torch.no_grad():
                x, label = x.to(device), label.to(device)
                output = lmks_model(x)
                # loss = criterion(output, label.long()) # 計算測試資料的準確度
                predicted = output.data[0].reshape((-1, 2))

        pred_lmks = predicted.cpu().numpy()
        # print(pred_lmks)

        new_lmks = (
            (pred_lmks - np.array([face_left, face_top])) / face_ratio).astype(np.int)
        self.ori_lmks = new_lmks + new_bb[0]

        ori_img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2RGB)

        # initial cat
        self.ori_pic = result_img

        tmp_filename = self.short_filename + "_000.jpg"
        cv2.imwrite(tmp_filename, result_img)

        # main end

    def angle_between(self, p1, p2):
        xDiff = p2[0] - p1[0]
        yDiff = p2[1] - p1[1]
        return degrees(atan2(yDiff, xDiff))

    def overlay_transparent(self, background_img, img_to_overlay_t, x, y, overlay_size=None):
        bg_img = background_img.copy()
        # convert 3 channels to 4 channels
        if bg_img.shape[2] == 3:
            bg_img = cv2.cvtColor(bg_img, cv2.COLOR_BGR2BGRA)

        if overlay_size is not None:
            img_to_overlay_t = cv2.resize(
                img_to_overlay_t.copy(), overlay_size)

        b, g, r, a = cv2.split(img_to_overlay_t)

        for i in range(len(a)):
            for j in range(len(a[0])):
                if a[i][j] < 200:
                    a[i][j] = 0

        #mask = cv2.medianBlur(a, 5)
        mask = a

        h, w, _ = img_to_overlay_t.shape
        roi = bg_img[int(y - h / 2):int(y + h / 2),
                     int(x - w / 2):int(x + w / 2)]

        img1_bg = cv2.bitwise_and(roi.copy(), roi.copy(),
                                  mask=cv2.bitwise_not(mask))
        img2_fg = cv2.bitwise_and(
            img_to_overlay_t, img_to_overlay_t, mask=mask)

        bg_img[int(y - h / 2):int(y + h / 2), int(x - w / 2)               :int(x + w / 2)] = cv2.add(img1_bg, img2_fg)

        # convert 4 channels to 4 channels
        bg_img = cv2.cvtColor(bg_img, cv2.COLOR_BGRA2BGR)

        return bg_img

    def setWearList(self, which_pattern):
        self.wear_list[self.which_d] = which_pattern

    def CreateBasePic(self):
        tmp_list = self.wear_list[:]
        tmp_list[self.which_d] = 0
        base_filepath = self.short_filename + "_" + \
            str(tmp_list[0]) + str(tmp_list[1]) + str(tmp_list[2]) + ".jpg"
        if os.path.isfile(base_filepath):
            return
        self.WearHat(tmp_list[0], 0, 0)
        self.WearBow(tmp_list[0], tmp_list[1], 0)
        self.WearGlasses(tmp_list[0], tmp_list[1], tmp_list[2])

    def WearDecorate(self):
        self.CreateBasePic()
        if self.which_d == 0:
            self.WearHat(self.wear_list[0],
                         self.wear_list[1], self.wear_list[2])
        elif self.which_d == 1:
            self.WearBow(self.wear_list[0],
                         self.wear_list[1], self.wear_list[2])
        else:
            self.WearGlasses(self.wear_list[0],
                             self.wear_list[1], self.wear_list[2])
        new_name = self.short_filename + "_" + \
            str(self.wear_list[0]) + str(self.wear_list[1]
                                         ) + str(self.wear_list[2]) + ".jpg"
        return new_name

    def WearHat(self, h_n, b_n, g_n):
        if h_n == 0:
            return
        # add hat
        hat_name = "hat" + str(h_n) + ".png"
        hat = cv2.imread(hat_name, cv2.IMREAD_UNCHANGED)
        hat_center = np.mean([self.ori_lmks[5], self.ori_lmks[6]], axis=0)
        hat_size = np.linalg.norm(self.ori_lmks[5] - self.ori_lmks[6]) * 3
        angle = -self.angle_between(self.ori_lmks[5], self.ori_lmks[6])
        M = cv2.getRotationMatrix2D(
            (hat.shape[1] / 2, hat.shape[0] / 2), angle, 1)
        rotated_hat = cv2.warpAffine(hat, M, (hat.shape[1], hat.shape[0]))

        base_name = self.short_filename + "_" + \
            "0" + str(b_n) + str(g_n) + ".jpg"
        new_name = self.short_filename + "_" + \
            str(h_n) + str(b_n) + str(g_n) + ".jpg"
        base_pic = cv2.imread(base_name)

        try:
            cat = self.overlay_transparent(base_pic, rotated_hat, hat_center[0], hat_center[1], overlay_size=(
                int(hat_size), int(hat.shape[0] * hat_size / hat.shape[1])))
        except:
            print('failed overlay image')

        cv2.imwrite(new_name, cat)

    def WearBow(self, h_n, b_n, g_n):
        if b_n == 0:
            return
        # add bow
        bow_name = "bow" + str(b_n) + ".png"
        bow = cv2.imread(bow_name, cv2.IMREAD_UNCHANGED)
        bow_center = np.mean([self.ori_lmks[3], self.ori_lmks[5]], axis=0)
        bow_size = np.linalg.norm(self.ori_lmks[3] - self.ori_lmks[5]) * 1.5
        angle = -self.angle_between(self.ori_lmks[3], self.ori_lmks[5])
        M = cv2.getRotationMatrix2D(
            (bow.shape[1] / 2, bow.shape[0] / 2), angle, 1)
        rotated_bow = cv2.warpAffine(bow, M, (bow.shape[1], bow.shape[0]))

        base_name = self.short_filename + "_" + \
            str(h_n) + "0" + str(g_n) + ".jpg"
        new_name = self.short_filename + "_" + \
            str(h_n) + str(b_n) + str(g_n) + ".jpg"
        base_pic = cv2.imread(base_name)

        cat = self.overlay_transparent(base_pic, rotated_bow, bow_center[0], bow_center[1], overlay_size=(
            int(bow_size), int(bow.shape[0] * bow_size / bow.shape[1])))

        cv2.imwrite(new_name, cat)

    def WearGlasses(self, h_n, b_n, g_n):
        # add glasses
        if g_n == 0:
            return
        glasses_name = "glasses" + str(g_n) + ".png"
        glasses = cv2.imread(glasses_name, cv2.IMREAD_UNCHANGED)
        glasses_center = np.mean([self.ori_lmks[0], self.ori_lmks[1]], axis=0)
        glasses_size = np.linalg.norm(
            self.ori_lmks[0] - self.ori_lmks[1]) * 2.5
        angle = -self.angle_between(self.ori_lmks[0], self.ori_lmks[1])
        M = cv2.getRotationMatrix2D(
            (glasses.shape[1] / 2, glasses.shape[0] / 2), angle, 1)
        rotated_glasses = cv2.warpAffine(
            glasses, M, (glasses.shape[1], glasses.shape[0]))

        base_name = self.short_filename + "_" + \
            str(h_n) + str(b_n) + "0" + ".jpg"
        new_name = self.short_filename + "_" + \
            str(h_n) + str(b_n) + str(g_n) + ".jpg"
        base_pic = cv2.imread(base_name)

        cat = self.overlay_transparent(base_pic, rotated_glasses, glasses_center[0], glasses_center[1], overlay_size=(
            int(glasses_size), int(glasses.shape[0] * glasses_size / glasses.shape[1])))

        cv2.imwrite(new_name, cat)


def solution(relation):
    column = len(relation[0])
    row = len(relation)
    candidateKey = []
    for case in range(1, 2**column):
        minimality = True
        uniqueness = True
        hashmap = {}
        for key in candidateKey:
            if key & case == key:
                minimality = False
                break
        if minimality == False:
            continue
        for r in range(row):
            tmpStr = ''
            curCols = []
            for k in range(column):
                if case & (1 << k):
                    curCols.append(k)
            for c in curCols:
                tmpStr += relation[r][c]
            if tmpStr in hashmap:
                uniqueness = False
                break
            hashmap[tmpStr] = True
        if uniqueness:
            candidateKey.append(case)

    answer = len(candidateKey)
    return answer

print(solution([
    ["100", "ryan", "music", "2"],
    ["200", "apeach", "math", "2"],
    ["300", "tube", "computer", "3"],
    ["400", "con", "computer", "4"],
    ["500", "muzi", "music", "3"],
    ["600", "apeach", "music", "2"]]))


import json

from flask import request, jsonify
from flask_restful import Resource
from werkzeug.exceptions import BadRequest

from managers.brand import BrandManager
from models import RoleType
from models.products import *
from schemas.request.brand import CreateBrandRequestSchema, EditBrandRequestSchema
from schemas.response.brand import (
    CreateBrandResponseSchema,
    BrandNameOnlyResponseSchema,
)
from utils.decorators import validate_schema, token_required, permission_required

from dotenv import load_dotenv

load_dotenv()

import cloudinary
import cloudinary.uploader
import cloudinary.api

config = cloudinary.config(secure=True)

class Brand(Resource):
    @validate_schema(CreateBrandRequestSchema)
    @permission_required(RoleType.admin)
    def post(self):
        # uploaded_files = request.files.get('file', '')
        # print(uploaded_files)
        # a = request
        # print(a)
        #
        # upload_result = cloudinary.uploader.upload(uploaded_files)

        # return jsonify(upload_result)

        brand = BrandManager.create(request.get_json())
        schema = CreateBrandResponseSchema()
        return schema.dumps(brand)

    @staticmethod
    def get():
        brand_name = request.args.get("brand")
        schema = CreateBrandResponseSchema()
        if not brand_name:
            brands = BrandManager.get_all()
            brand_name_schema = BrandNameOnlyResponseSchema()
            return brand_name_schema.dumps(brands, many=True)

        if brand_name == "all":
            brands = BrandManager.get_all()
            return schema.dumps(brands, many=True)

        elif brand_name:
            brands = BrandManager.get_by_name(brand_name)
            return schema.dumps(brands)

        raise BadRequest("You should use query parameters, check the documentation!")

class BrandUpdate(Resource):
    @staticmethod
    @permission_required(RoleType.admin)
    def get(id_):
        brand = BrandManager.get_by_id(id_)
        schema = CreateBrandResponseSchema()
        return schema.dumps(brand)

    @staticmethod
    @permission_required(RoleType.admin)
    @validate_schema(EditBrandRequestSchema)
    def put(id_):
        brand = BrandManager.edit_brand(id_, request.get_json())
        schema = CreateBrandResponseSchema()
        return schema.dumps(brand)

    @staticmethod
    @permission_required(RoleType.admin)
    def delete(id_):
        result = BrandManager.delete(id_)
        return json.dumps(result)


import logging

from sklearn.metrics import accuracy_score

from pytorch_tabular import TabularModel
from pytorch_tabular.config import DataConfig, OptimizerConfig, TrainerConfig
from ml.solvers.base_solver import Solver

class PytorchTabularSolver(Solver):
    def init_model(self):
        super(PytorchTabularSolver, self).init_model()

        data_config = DataConfig(
            target=['Y'],
            # target should always be a list. Multi-targets are only supported for regression. Multi-Task Classification is not implemented
            continuous_cols=list(self.val_loader.df_data[0].select_dtypes(include=['int64']).columns),
            categorical_cols=list(self.val_loader.df_data[0].select_dtypes(include=['object', 'uint8']).columns),
            validation_split=0.0)
        trainer_config = TrainerConfig(**self.config.trainer.params.dict())  # index of the GPU to use. 0, means CPU
        optimizer_config = OptimizerConfig()

        self.model = TabularModel(data_config=data_config,
                                  model_config=self.model,
                                  optimizer_config=optimizer_config,
                                  trainer_config=trainer_config)

    def load_model(self):
        try:
            self.model = TabularModel.load_from_checkpoint(self.result_dir)
        except FileNotFoundError as e:
            logging.info('No saved model found: no model is loaded.')

    def train(self):
        """
        Training the tree based networks.
        Save the model if it has better performance than the previous ones.
        """
        self.model.fit(train=self.train_loader.df,
                       validation=self.val_loader.df)
        # save model
        self.model.save_model(self.result_dir)

        self.eval()

        self.save_acc()

    def eval(self):
        """
        Evaluate the model.
        """
        preds = self.model.predict(self.val_loader.df_data[0]).prediction.to_numpy()
        gt = self.val_loader.data[1]

        self.accuracy = accuracy_score(preds, gt)
        print(self.accuracy)

        if self.config.env.save_preds:
            self.save_preds(preds)


#file a transaction
#any changes to the users balanace should be reflected in the account file

import datetime

def transaction_options(accounts_path, line_number):

    stay_logged_in = True
    while stay_logged_in == True:
        ask = input('Would you like to make a transaction, return to the homepage, or logout (T/H/L)? ').upper()
        if ask == 'T':
            transaction(accounts_path, line_number)
        elif ask == 'H':
            return homepage()
        elif ask == 'L':
            return logout()
        else:
            print ('Invalid input')

def transaction(accounts_path, line_number):

    person_involved = input('First input the other entity involved in the transaction: ')
    transaction_amount = ''
    continue_transaction = True

    while continue_transaction == True:
        money = input("Next tell us the money transferred, if you spent money add a '-' in front of the amount: ")
        money_list = []
        money_list[:0] = money
        if money_list[0] == '-':
            money_list[0] = '0'
        for num in money_list:
            if num.isnumeric() == False:
                print ('money only contains numbers')
                continue

        #if the hyphen was changed to a 0, change it back
        if money_list[0] == '0':
            money_list[0] = '-'
        #convert the list back into a string
        for num in money_list:
            transaction_amount += num
        continue_transaction = False

    #ask the user for the date of the transaction
    #syntax check for the date
    #write the other entity, amount of money, and date into the transaction history file

    enter_date = True
    while enter_date == True:
        date_of_transaction = input('Lastly, tell us the date this transaction occurred, use the format yyyy-mm-dd: ')
        format = '%Y-%m-%d'
        try:
            datetime.datetime.strptime(date_of_transaction, format)
        except ValueError:
            print ('This is the incorrect date format, please try again')
            continue
        break

    #get the account number so we can open their transaction history
    with open(accounts_path, 'r') as accounts_file:
        #list of all the lines in the accounts file where each item is 1 line from the file
        accounts_list = accounts_file.readlines()
        #split the string at index line_number into a list of separate values
        split_line = accounts_list[line_number].split(', ')
        #if the 2nd element in the split_line list matches the inputted password, the user has successfully logged in
        account_number = split_line[0]

    #this needs to print on a newline
    with open (f'{account_number}.txt', 'a') as transaction_history:
        transaction_history.write(f'{person_involved}, {transaction_amount}, {date_of_transaction}\n')

    #open the file
    #find the line where the account number matches
    #change the balance value
    #re write the whole file

    # with open(accounts_path, 'r') as accounts_file:
    #     #list of all the lines in the accounts file where each item is 1 line from the file
    #     accounts_list = accounts_file.readlines()
    #     #split the string at index line_number into a list of separate values
    #     split_line = accounts_list[line_number].split(', ')
    #     #if the 2nd element in the split_line list matches the inputted password, the user has successfully logged in
    #     account_number = split_line[4]

def homepage():
    print ('Returning to the homepage')
    return True

def logout():
    print ('Logging you out now, returning to login screen')
    return False