import cv2
import face_recognition
import put_chinese_text
import time

VIDEO_DIR = 'hamilton_clip.mp4'
resize_ratio = 0.5

input_video = cv2.VideoCapture(VIDEO_DIR)   # 读取视频文件
length = int(input_video.get(cv2.CAP_PROP_FRAME_COUNT)) #视频帧数

fourcc = cv2.VideoWriter_fourcc(*'mp4v')    # 视频编码器
output_video = cv2.VideoWriter('hamilton_clip_recognition_face.mp4', fourcc, 29.97, (640, 360)) # 打开一个视频写入文件

# encoding两张需要识别的人脸
lmm_image = face_recognition.load_image_file("lin-manuel-miranda.png")
lmm_face_encoding = face_recognition.face_encodings(lmm_image)[0]

al_image = face_recognition.load_image_file("alex-lacamoire.png")
al_face_encoding = face_recognition.face_encodings(al_image)[0]

# 已知人脸encodings
known_face_encodings = [
    lmm_face_encoding,
    al_face_encoding
]

known_face_names = [
    'lin',
    'alex'
]

frame_number = 0

while True:
    start_time = time.time()
    # 读取视频流的每一帧
    ret, frame = input_video.read()
    # 放缩每一帧，加速
    small_frame = cv2.resize(frame, (0, 0), fx=resize_ratio, fy=resize_ratio)

    frame_number += 1
    # 视频结束
    if not ret:
        break

    # BGR2RGB，face_recognition库需要此格式
    rgb_frame = small_frame[:, :, ::-1]
    # 获取当前帧所有人脸及其encodings
    face_locations = face_recognition.face_locations(rgb_frame, model='cnn')
    face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)

    face_names = []
    for encoding in face_encodings:
        # 为每一个encoding对比已知的encodings
        matches = face_recognition.compare_faces(known_face_encodings, encoding)
        name = 'unknown'
        # 找出结果为True所对应的名字
        if True in matches:
            matchIds = [i for (i, b) in enumerate(matches) if b]
            name = known_face_names[matchIds[0]]
        face_names.append(name)

    # 标记人脸和名字
    for (top, right, bottom, left), name in zip(face_locations, face_names):
        # 如果使用了放缩帧，从新计算原始坐标位置
        top, right, bottom, left = int(top / resize_ratio), int(right / resize_ratio), int(bottom / resize_ratio), int(left / resize_ratio)
        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
        top_text = top - 16 if top - 16 > 16 else top + 16
        cv2.rectangle(frame, (left, top_text), (right, top), (0, 0, 255), cv2.FILLED)
        frame = put_chinese_text.draw_text(frame, name, (left, top_text), (0, 0, 0))
    end_time = time.time()
    fps = '%.2f FPS'% (1 / (end_time - start_time))
    # cv2.putText(frame, fps, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2)
    cv2.putText(frame, fps, (0, 20), cv2.FONT_HERSHEY_DUPLEX, 0.7, (0, 255, 0), 1)
    # 将该帧写入文件
    output_video.write(frame)
    # 显示
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break

input_video.release()
cv2.destroyAllWindows()
if output_video is not None:
	output_video.release()


import sys, os, pickle
DIR = os.path.dirname(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
sys.path.append(DIR)
from Dataset.mnist import load_mnist
from functions import *
from PIL import Image

def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))
    pil_img.show()

def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=True, one_hot_label=False)
    return x_test, t_test

def init_network():
    with open(DIR + "/Dataset/sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)
    return network

def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3

    return softmax(a3)

if __name__ == "__main__":

    x, t = get_data()
    network = init_network()

    accuracy_cnt = 0
    for i in range(len(x)):
        y = predict(network, x[i])
        p = np.argmax(y) # 확률이 가장 높은 원소의 인덱스를 얻는다.
        if p == t[i]:
            accuracy_cnt += 1

    print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

    """ (x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
    # flatten parameter makes input images simple array
    # normalize parameter normalizes input image's pixels to between 0.0 and 1.0 (or it can be 0~255)

    print(x_train.shape)
    print(t_train.shape)
    print(x_test.shape)
    print(t_test.shape)

    img = x_train[0]
    label = t_train[0]
    print(label)

    print(img.shape)
    img = img.reshape(28, 28)
    print(img.shape)

    img_show(img) """


from django.forms import ModelForm
from django.utils.translation import gettext_lazy as _
from . import models

class LivreForm(ModelForm):
    class Meta:
        model = models.Livre
        fields = ('titre', 'auteur', 'date_parution', 'nombre_pages','resume')
        labels = {
            'titre' : _('Titre'),
            'auteur' : _('Auteur') ,
            'date_parution' : _('date de parution'),
            'nombre_pages' : _('nombres de pages'),
            'resume' : _('Résumé'),
        }
        localized_fields = ('date_parution',)

class CategorieForm(ModelForm):
    class Meta:
        model = models.Categorie
        fields = ('nom', 'description')
        labels = {
            'nom' : _('Nom de la catégorie'),
        }


#!/usr/bin/env python
#-*- coding:utf-8 -*-

import logging

from ..json_struct_patch import JsonStructPatch

def test_properties_diff():
    local = {'rsyslog': {'facility': 2}}
    template = { "rsyslog": {
                    "properties": {
                        "facility": {
                            "index": "not_analyzed",
                            "type": "string"
                        }}}}
    patch = JsonStructPatch(template)
    delta = patch.diff_template(local)
    logging.debug('delta == %s',(delta))
    assert delta == []

def test_nested_properties_diff():
    local = {'rsyslog': {'facility': {'local':1}}}
    template = { "rsyslog": {
                    "properties": {
                        "facility": {
                             "properties":{
                              "local":{
                            "index": "not_analyzed",
                            "type": "string"
                        }}}}}}
    patch = JsonStructPatch(template)
    delta = patch.diff_template(local)
    logging.debug('delta == %s',(delta))
    assert delta == []

def test_neg_properties_diff():
    local = {'rsyslog': {'facility':'sss', 'fromhost': 'openstack'}}
    template = { "rsyslog": {
                    "properties": {
                        "facility": {
                             "properties":{
                              "local":{
                            "index": "not_analyzed",
                            "type": "string"
                        }}}}}}
    patch = JsonStructPatch(template)
    delta = patch.diff_template(local)
    logging.debug('delta == %s',(delta))
    assert delta == [(".rsyslog.fromhost","not_in_template")]

def test_2array_simple_diff():
    local = {'CEE': {}, 'systemd': {}, 'rsyslog': {'facility':'ll','protocol-version':11}}
    template = {                 "CEE": {
                    "type": "object"
                }, "rsyslog":{
                     "properties": {
                        "facility": {
                            "index": "not_analyzed",
                            "type": "string"
                        }}},
                    "systemd": {
                    "properties": {
                        "k": {
                            "properties": {
                                "KERNEL_DEVICE": {
                                    "index": "not_analyzed",
                                    "type": "string"
                                }}}}}}
    patch = JsonStructPatch(template)
    delta = patch.diff_template(local)
    logging.debug('delta == %s',(delta))
    assert delta == [(".rsyslog.protocol-version","not_in_template")]

if __name__ == '__main__':
    import nose
    nose.runmodule()


import side_by_side
import convolution
import numpy as np
from PIL import Image
from sys import argv
import math

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

def canny_img(im_init):
    def gaussiano(im):
        gaussian = np.ones((5,5), dtype=np.float);
        gaussian[:,:] = [
            [1,4,7,4,1],
            [4,16,26,16,4],
            [7,26,41,26,7],
            [4,16,26,16,4],
            [1,4,7,4,1]]
        gaussian[:,:] *= 1./273;

        return convolution.convolution(im, gaussian)

    def edge_detection(im, kernel):
        robertsx = np.zeros((2,2), dtype=np.float)
        robertsx[:,:] = [[1,0],
                         [0,-1]]
        robertsy = np.zeros((2,2), dtype=np.float)
        robertsy[:,:] = [[0,1],
                         [-1,0]]

        prewittx = np.zeros((3,3), dtype=np.float)
        prewittx[:,:] = [[-1, 0, 1],
                         [-1, 0, 1],
                         [-1, 0, 1]]
        prewitty = np.zeros((3,3), dtype=np.float)
        prewitty[:,:] = [[1, 1, 1],
                         [0, 0, 0],
                         [-1, -1, -1]]

        sobelx = np.zeros((3,3), dtype=np.float)
        sobelx[:,:] = [[1, 0, -1],
                       [2, 0, -2],
                       [1, 0, -1]]
        sobely = np.zeros((3,3), dtype=np.float)
        sobely[:,:] = [[1, 2, 1],
                       [0, 0, 0],
                       [-1, -2, -1]]

        def border_detection(img, kernelx, kernely):
            imx = convolution.convolution(img, kernelx)
            imx = imx.astype(np.float)
            imy = convolution.convolution(img, kernely)
            imy = imy.astype(np.float)

            r = np.power(np.power(imx, 2)+np.power(imy, 2), 0.5) / np.sqrt(2.0)
            t = np.arctan(imy / (imx + 0.00001))
            return r, t

        if kernel == "roberts":
            return border_detection(im1, robertsx, robertsy)
        elif kernel == "prewitt":
            return border_detection(im1, prewittx, prewitty)
        elif kernel == "sobel":
            return border_detection(im1, sobelx, sobely)

    def supresion_de_no_maximos(jo, jm):
        jn = np.zeros(jm.shape, dtype=np.float)
        k1, k2 = jm.shape
        for i in range(1, k1-1):
            for j in range(1, k2-1):
                angulo = jo[i,j]
                if -np.pi / 8 < angulo <= np.pi / 8:
                    if jm[i,j] >= jm[i, j-1] and jm[i,j] >= jm[i, j+1]:
                        jn[i,j] = jm[i,j]
                elif np.pi / 8 < angulo <= 3 * np.pi / 8:
                    if jm[i,j] >= jm[i-1, j+1] and jm[i,j] >= jm[i+1, j-1]:
                        jn[i,j] = jm[i,j]
                elif -np.pi / 8 >= angulo > -3 * np.pi / 8:
                    if jm[i,j] >= jm[i-1, j-1] and jm[i,j] >= jm[i+1, j+1]:
                        jn[i,j] = jm[i,j]
                elif angulo > 3 * np.pi / 8 or angulo <= -3 * np.pi / 8:
                    if jm[i,j] >= jm[i-1, j] and jm[i,j] >= jm[i+1, j]:
                        jn[i,j] = jm[i,j]
        return jn / np.max(jn)

    U_MAX = 0.14
    U_MIN = 0.01
    def umbral_por_histeresis(im, jo):
        r = np.zeros(jm.shape, dtype=np.float)
        k1, k2 = jm.shape
        for i in range(1, k1-1):
            for j in range(1, k2-1):
                if im[i, j] >= U_MIN:
                    r[i, j] = im[i,j]
                if im[i, j] >= U_MAX:
                    angulo = jo[i,j]
                    if -np.pi / 8 < angulo <= np.pi / 8:
                        if im[i-1, j] >= U_MIN:
                            r[i-1, j] = U_MAX
                        if im[i+1, j] >= U_MIN:
                            r[i+1, j] = U_MAX
                    elif np.pi / 8 < angulo <= 3 * np.pi / 8:
                        if im[i-1, j-1] >= U_MIN:
                            r[i-1, j-1] = U_MAX
                        if im[i+1, j+1] >= U_MIN:
                            r[i+1, j+1] = U_MAX
                    elif -np.pi / 8 >= angulo > -3 * np.pi / 8:
                        if im[i-1, j+1] >= U_MIN:
                            r[i-1, j+1] = U_MAX
                        if im[i+1, j-1] >= U_MIN:
                            r[i+1, j-1] = U_MAX
                    elif angulo > 3 * np.pi / 8 or angulo <= -3 * np.pi / 8:
                        if im[i, j-1] >= U_MIN:
                            r[i, j-1] = U_MAX
                        if im[i, j+1] >= U_MIN:
                            r[i, j+1] = U_MAX
        idx = r >= U_MAX
        r[idx] = 1.0
        idx = r < U_MAX
        r[idx] = 0.0
        return r
    im_gauss = gaussiano(im_init)
    jm, jo = edge_detection(im_gauss, "sobel")
    return umbral_por_histeresis(supresion_de_no_maximos(jo, jm), jo)

im1 = np.asarray(Image.open(argv[1]).convert('L'))
im2 = canny_img(im1)

k1, k2 = im2.shape
ts = np.arange(-np.pi / 2, np.pi / 2, np.pi / 20)

max_mod = np.power(k1*k1 + k2*k2, 0.5)
min_mod = -max_mod
pasos_mod = (max_mod - min_mod) / 20

cuenta = {}
for angulo in ts:
    cuenta_angulo = {}
    for i in range(k1):
        for j in range(k2):
            if im2[i][j] == 0.0: continue
            d = int(i * np.sin(angulo) + j * np.cos(angulo))
            # d = int(pasos_mod * int(d / pasos_mod))
            if d not in cuenta_angulo.keys():
                cuenta_angulo[d] = 0
            else:
                cuenta_angulo[d] += 1
    cuenta[angulo] = cuenta_angulo

print(cuenta)
lineas_rectas = []
for angulo in ts:
    for modulo in cuenta[angulo]:
        if cuenta[angulo][modulo] > 50:
            lineas_rectas.append((angulo, modulo))
            print(cuenta[angulo][modulo])
print(lineas_rectas)

stacked_img = np.stack((im2,)*3, axis=-1)
print(stacked_img)

for angulo, modulo in lineas_rectas:
    if -0.001 < np.cos(angulo) < 0.001:
        print(i)
        for j in range(k2):
            stacked_img[abs(modulo),j,:] = [1.0, 0, 0]
        continue
    for i in range(k1):
        j = int((modulo - i * np.sin(angulo)) / (np.cos(angulo) + 0.0001))
        if 0 <= j < k2:
            stacked_img[i,j,:] = [1.0, 0, 0]

plt.imshow(stacked_img, cmap='gray') #, vmin=0, vmax=255)
plt.show()


from pathlib import Path
from typing import Any, Dict, List, Union

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import yaml
from torch import Tensor
from torchmetrics import Dice, JaccardIndex
from transformers import EvalPrediction

class ComputeMetrics(object):
    def __init__(self, resource: Union[Path, str, Dict[str, Any]]) -> None:
        config = resource
        if isinstance(resource, Path) or isinstance(resource, str):
            resource = Path(resource)

            with open(resource, "r") as file:
                config = yaml.safe_load(file)

        assert "compute_metrics" in config, f"wrong resource {resource} construction"

        self.thresholds = config["compute_metrics"]["thresholds"]
        self.dice = Dice(num_classes=1)
        self.iou = JaccardIndex(task="binary")

    def compute_group_area_by_relarea(self, label: float) -> int:
        for i, interval in enumerate(self.thresholds):
            if interval[0] <= label < interval[1]:
                return i
        return i

    def compute_group_area_by_target(self, label: Union[Tensor, np.ndarray]) -> int:
        object_area = label.sum()
        image_area = np.product(label.shape[-2:])

        relative_area = object_area / image_area

        for i, interval in enumerate(self.thresholds):
            if interval[0] <= relative_area < interval[1]:

                return i
        return i

    def __call__(self, eval_pred: EvalPrediction) -> Dict[str, float]:
        predictions, labels = eval_pred
        b, _, _, _ = predictions.shape

        area_groups = {i: {"dice": [], "iou": []} for i in range(len(self.thresholds))}

        for i in range(b):
            pred = Tensor(predictions[i : i + 1]).float()
            label = Tensor(labels[i : i + 1]).long()

            pred = F.softmax(pred, dim=1)

            group_area = self.compute_group_area_by_target(label)
            area_groups[group_area]["dice"].append(
                self.dice(pred[:, 1].flatten(), label.flatten())
            )

            pred = pred.argmax(dim=1)
            area_groups[group_area]["iou"].append(self.iou(pred, label))

        metrics_result = {}
        dice_all = []
        iou_all = []

        for gr in area_groups:
            dice_all += area_groups[gr]["dice"]
            iou_all += area_groups[gr]["iou"]
            metrics_result[f"dice_group_{gr}"] = np.mean(area_groups[gr]["dice"])
            metrics_result[f"iou_group_{gr}"] = np.mean(area_groups[gr]["iou"])

        metrics_result["dice"] = np.mean(dice_all)
        metrics_result["iou"] = np.mean(iou_all)

        return metrics_result


import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread("imagens/hospital2.jpg")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

corners = cv.goodFeaturesToTrack(gray, 10, 0.05, 0.25)

for item in corners:
    x, y = item[0]
    cv.circle(img, (x, y), 4, (0, 0, 255), -1)

fig = plt.figure(figsize=(10,8))
plt.imshow(img)
plt.show()


import logging
from celery import shared_task

logger = logging.getLogger('error')

@shared_task
def error_logger(err, exc_info=None):
    if exc_info:
        exc_type, exc_obj, exc_tb = exc_info
        logger.error(f'{exc_tb.tb_frame.f_code.co_filename} {exc_tb.tb_lineno} {str(err)}')
    else:
        logger.error(f'{str(err)}')


import discord
from discord.ext import commands, tasks

import requests
import json
import html
import random

# Commands for Trivia game
class triviaCommands(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def trivia(self, ctx):
        mention = ctx.author.mention

        # Gets the JSON string text response from opent database
        response = requests.get('https://opentdb.com/api.php?amount=1')
        triviaResponse = json.loads(response.text)
        triviaResponseInformation = triviaResponse['results'][0]

        question = triviaResponseInformation['question']
        question = html.unescape(question)
        questionType = triviaResponseInformation['type']
        questionCategory = triviaResponseInformation['category']
        questionDifficulty = triviaResponseInformation['difficulty']
        questionAnswer = triviaResponseInformation['correct_answer']
        questionAnswer = html.unescape(questionAnswer)

        questionInformation = ""

        # Displays different formats for the answers depending on if the question is multiple choice or true or false
        if questionType == 'multiple':
            questionType = 'Multiple Choice'
            questionsArray = []

            # Gets all the possible answers in an array and randomizes the array
            decodedCorrectAnswer = html.unescape(triviaResponseInformation['correct_answer'])
            questionsArray.append(decodedCorrectAnswer)
            for incorrectQuestions in triviaResponseInformation['incorrect_answers']:
                decodedIncorrectQuestions = html.unescape(incorrectQuestions)
                questionsArray.append(decodedIncorrectQuestions)
            random.shuffle(questionsArray)

            questionAlphabet = 97

            individualQuestionsString = ""
            for individualQuestions in questionsArray:
                individualQuestionsString += f'{chr(questionAlphabet)}) {individualQuestions}\n'
                questionAlphabet = questionAlphabet + 1

            questionInformation += f'{mention}\n\nType: {questionType}\nCategory: {questionCategory}\nDifficulty: {questionDifficulty}\nQuestion: {question}\n\nAnswers: \n{individualQuestionsString}\nPlease type your answer(a/b/c/d) in the chat:'
            embedVar = discord.Embed(title='Trivia', description=questionInformation, color=0xFFA500)
            await ctx.channel.send(embed=embedVar)

            # Ensures the author that initially started the trivia, is the one answering so other user messages aren't taken into account and they answer with 'a', 'b', 'c' or 'd'
            def check(m):
                return m.author == ctx.author and (m.content.lower() == 'a' or m.content.lower() == 'b' or m.content.lower() == 'c' or m.content.lower() == 'd')

            # Gets the users answer based off their letter input
            userAnswer = await self.bot.wait_for('message', check=check)
            answerValue = questionsArray[ord(userAnswer.content.lower())-97]

            # Checks if the users answer is correct
            if answerValue.lower() == questionAnswer.lower():
                embedVar = discord.Embed(description=f'You chose the correct answer {mention}', color=0xFFA500)
                await ctx.channel.send(embed=embedVar)
            else:
                embedVar = discord.Embed(description=f'You chose the incorrect answer, the correct answer was \'{questionAnswer}\' {mention}', color=0xFFA500)
                await ctx.channel.send(embed=embedVar)

        else:
            questionType = 'True or False'

            questionInformation += f'{mention}\n\nType:{questionType}\nCategory: {questionCategory}\nDifficulty: {questionDifficulty}\nQuestion: {question}\n\nAnswers: \na) True\nb) False\n\nPlease type your answer(a/b) in the chat:'
            embedVar = discord.Embed(title='Trivia', description=questionInformation, color=0xFFA500)
            await ctx.channel.send(embed=embedVar)

            # Ensures the author that initially started the trivia, is the one answering so other user messages aren't taken into account
            def check(m):
                return m.author == ctx.author and (m.content.lower() == 'a' or m.content.lower() == 'b')

            # Gets the users answer
            userAnswer = await self.bot.wait_for('message', check=check)

            # Converts the users alphabetical answer to True or False
            if userAnswer.content.lower() == 'a':
                userAnswer = "True"
            elif userAnswer.content.lower() == 'b':
                userAnswer = "False"

            # Checks if the users answers is correct
            if userAnswer.lower() == questionAnswer.lower():
                embedVar = discord.Embed(description=f'You chose the correct answer {mention}', color=0XFFA500)
                await ctx.channel.send(embed=embedVar)
            else:
                embedVar = discord.Embed(description=f'You chose the incorrect answer, the correct answer was \'{questionAnswer}\' {mention}', color=0xFFA500)
                await ctx.channel.send(embed=embedVar)

# Sets up the trivia bot command above
def setup(bot):
    bot.add_cog(triviaCommands(bot))


from PIL import Image, ImageEnhance, ImageOps
import PIL.ImageDraw as ImageDraw
import numpy as np
import random

class RandAugmentPolicy(object):
    """Randomly choose one of the best 25 Sub-policies on CIFAR10.
    Example:
    >>> policy = RandAugmentPolicy()
    >>> transformed = policy(image)
    Example as a PyTorch Transform:
    >>> transform=transforms.Compose([
    >>>     transforms.Resize(256),
    >>>     RandAugmentPolicy(),
    >>>     transforms.ToTensor()])
    """

    # I change fill color from (128, 128, 128) to (0, 0, 0)
    def __init__(self, fillcolor=(0, 0, 0), N=1, M=5):
        self.policies = [
            "invert",
            "autocontrast",
            "equalize",
            "rotate",
            "solarize",
            "color",
            "posterize",
            "contrast",
            "brightness",
            "sharpness",
            "shearX",
            "shearY",
            "translateX",
            "translateY",
            "cutout",
        ]
        self.N = N
        self.M = M

    def __call__(self, img):
        """Applies RandAugment on input image.

        Args:
            img: Input image

        Returns:
            np.ndarray: Augmented image based on N and M hyper-parameters chosen for RA.
        """

        choosen_policies = np.random.choice(self.policies, self.N)
        for policy in choosen_policies:
            subpolicy_obj = SubPolicy(operation=policy, magnitude=self.M)
            img = subpolicy_obj(img)

        return img
        # return self.policies[policy_idx](img)

    def __repr__(self):
        return f"RandAugment Policy with Cutout where N: {self.N} and M: {self.M}"

class SubPolicy(object):
    def __init__(self, operation, magnitude, fillcolor=(128, 128, 128), MAX_PARAM=10):
        ranges = {
            "shearX": np.linspace(0, 0.3, MAX_PARAM),
            "shearY": np.linspace(0, 0.3, MAX_PARAM),
            "translateX": np.linspace(0, 150 / 331, MAX_PARAM),
            "translateY": np.linspace(0, 150 / 331, MAX_PARAM),
            "rotate": np.linspace(0, 30, MAX_PARAM),
            "color": np.linspace(0.0, 0.9, MAX_PARAM),
            "posterize": np.round(np.linspace(8, 4, MAX_PARAM), 0).astype(np.int),
            "solarize": np.linspace(256, 0, MAX_PARAM),
            "contrast": np.linspace(0.0, 0.9, MAX_PARAM),
            "sharpness": np.linspace(0.0, 0.9, MAX_PARAM),
            "brightness": np.linspace(0.0, 0.9, MAX_PARAM),
            "autocontrast": [0] * MAX_PARAM,
            "equalize": [0] * MAX_PARAM,
            "invert": [0] * MAX_PARAM,
            "cutout": np.linspace(0.0, 0.8, MAX_PARAM),
        }

        # from https://stackoverflow.com/questions/5252170/specify-image-filling-color-when-rotating-in-python-with-pil-and-setting-expand
        def rotate_with_fill(img, magnitude):
            rot = img.convert("RGBA").rotate(magnitude)
            return Image.composite(
                rot, Image.new("RGBA", rot.size, (0,) * 4), rot
            ).convert(img.mode)

        def Cutout(img, v):  # [0, 60] => percentage: [0, 0.2]
            assert 0.0 <= v <= 0.8
            if v <= 0.0:
                return img

            v = v * img.size[0]

            return CutoutAbs(img, v)

        def CutoutAbs(img, v):  # [0, 60] => percentage: [0, 0.2]
            # assert 0 <= v <= 20
            if v < 0:
                return img
            w, h = img.size
            x0 = np.random.uniform(w)
            y0 = np.random.uniform(h)

            x0 = int(max(0, x0 - v / 2.0))
            y0 = int(max(0, y0 - v / 2.0))
            x1 = min(w, x0 + v)
            y1 = min(h, y0 + v)

            xy = (x0, y0, x1, y1)
            # color = (125, 123, 114)
            color = (0, 0, 0)
            img = img.copy()
            ImageDraw.Draw(img).rectangle(xy, color)
            return img

        func = {
            "shearX": lambda img, magnitude: img.transform(
                img.size,
                Image.AFFINE,
                (1, magnitude * random.choice([-1, 1]), 0, 0, 1, 0),
                Image.BICUBIC,
                fillcolor=fillcolor,
            ),
            "shearY": lambda img, magnitude: img.transform(
                img.size,
                Image.AFFINE,
                (1, 0, 0, magnitude * random.choice([-1, 1]), 1, 0),
                Image.BICUBIC,
                fillcolor=fillcolor,
            ),
            "translateX": lambda img, magnitude: img.transform(
                img.size,
                Image.AFFINE,
                (1, 0, magnitude * img.size[0] * random.choice([-1, 1]), 0, 1, 0),
                fillcolor=fillcolor,
            ),
            "translateY": lambda img, magnitude: img.transform(
                img.size,
                Image.AFFINE,
                (1, 0, 0, 0, 1, magnitude * img.size[1] * random.choice([-1, 1])),
                fillcolor=fillcolor,
            ),
            "rotate": lambda img, magnitude: rotate_with_fill(img, magnitude),
            # "rotate": lambda img, magnitude: img.rotate(magnitude * random.choice([-1, 1])),
            "color": lambda img, magnitude: ImageEnhance.Color(img).enhance(
                1 + magnitude * random.choice([-1, 1])
            ),
            "posterize": lambda img, magnitude: ImageOps.posterize(img, magnitude),
            "solarize": lambda img, magnitude: ImageOps.solarize(img, magnitude),
            "contrast": lambda img, magnitude: ImageEnhance.Contrast(img).enhance(
                1 + magnitude * random.choice([-1, 1])
            ),
            "sharpness": lambda img, magnitude: ImageEnhance.Sharpness(img).enhance(
                1 + magnitude * random.choice([-1, 1])
            ),
            "brightness": lambda img, magnitude: ImageEnhance.Brightness(img).enhance(
                1 + magnitude * random.choice([-1, 1])
            ),
            "autocontrast": lambda img, magnitude: ImageOps.autocontrast(img),
            "equalize": lambda img, magnitude: ImageOps.equalize(img),
            "invert": lambda img, magnitude: ImageOps.invert(img),
            "cutout": lambda img, magnitude: Cutout(img, magnitude),
        }

        self.operation = func[operation]
        self.magnitude = ranges[operation][magnitude]

    def __call__(self, img):
        # if random.random() < self.p1: img = self.operation1(img, self.magnitude1)
        img = self.operation(img, self.magnitude)
        return img

class SplitAugmentPolicy(object):
    def __init__(self, N=1, M=5, slices=4):
        self.policies = [
            "invert",
            "autocontrast",
            "equalize",
            "rotate",
            "solarize",
            "color",
            "posterize",
            "contrast",
            "brightness",
            "sharpness",
            "shearX",
            "shearY",
            "translateX",
            "translateY",
            "cutout",
        ]
        self.N = N
        self.M = M
        self.slices = slices
        # print(f"Split Augment Object initialized: N: {self.N}, M: {self.M} and slices: {self.slices}")

    def __call__(self, img):
        # policy_idx = random.randint(0, len(self.policies) - 1)
        w, h = img.size
        img = np.array(img)

        if self.slices == 4:
            img_1 = Image.fromarray(img[0:16, 0:16, :])
            img_2 = Image.fromarray(img[0:16, 16:, :])
            img_3 = Image.fromarray(img[16:, 0:16, :])
            img_4 = Image.fromarray(img[16:, 16:, :])

            imgess = [img_1, img_2, img_3, img_4]
        elif self.slices == 2:
            img_1 = Image.fromarray(img[:, 0:16, :])
            img_2 = Image.fromarray(img[:, 16:, :])

            imgess = [img_1, img_2]
        else:
            raise NotImplementedError

        for i, img in enumerate(imgess):
            choosen_policies = np.random.choice(self.policies, self.N)
            for policy in choosen_policies:
                subpolicy_obj = SubPolicy(operation=policy, magnitude=self.M)
                img = subpolicy_obj(img)
                imgess[i] = np.array(img)

        temp_img = np.zeros(shape=(w, h, 3))
        if self.slices == 4:
            temp_img[0:16, 0:16, :] = imgess[0]
            temp_img[0:16, 16:, :] = imgess[1]
            temp_img[16:, 0:16, :] = imgess[2]
            temp_img[16:, 16:, :] = imgess[3]
        elif self.slices == 2:
            temp_img[:, 0:16, :] = imgess[0]
            temp_img[:, 16:, :] = imgess[1]
        else:
            raise NotImplementedError

        temp_img = Image.fromarray(temp_img.astype(np.uint8))
        return temp_img

    def __repr__(self):
        return "SplitAugment CIFAR Policy with Cutout"


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Класс управления картой 2GIS.
"""

import jinja2

from . import double_gis_util

from ic.utils import extfunc

__version__ = (0, 1, 1, 1)

# Шаблон результирующего HTML документа
HTML_TEMPLATE = '''<!DOCTYPE html>

        <meta charset="utf-8">
        <title>{{ title }}</title>

        {{ map }}

'''

# Шаблон карты
MAP_TEMPLATE = '''

'''

class ic2GISMap(object):
    """
    Класс управления картой 2GIS.
    """
    _map_template = jinja2.Template(MAP_TEMPLATE)
    _html_template = jinja2.Template(HTML_TEMPLATE)

    def __init__(self, location=None,
                 width='2000px', height='1300px',
                 left='0%', top='0%',
                 position=None,
                 tiles='OpenStreetMap',
                 attr=None,
                 min_zoom=0,
                 max_zoom=18,
                 zoom_start=10,
                 min_lat=-90,
                 max_lat=90,
                 min_lon=-180,
                 max_lon=180,
                 max_bounds=False,
                 crs='EPSG3857',
                 control_scale=False,
                 prefer_canvas=False,
                 no_touch=False,
                 disable_3d=False,
                 png_enabled=False,
                 zoom_control=True,
                 **kwargs):
        """
        Конструктор. Создание карты.
        :param location: Точка геолокации (ширина, долгота) центра карты.
        :param width: Ширина карты.
        :param height: Высота карты.
        :param left:
        :param top:
        :param position:
        :param tiles: Карта набора плиток для использования.
        :param attr: Атрибуция плитки карты; требуется только при передаче пользовательского URL плитки.
        :param min_zoom: Минимально допустимый уровень масштабирования для создаваемого слоя листов.
        :param max_zoom: Максимально допустимый уровень масштабирования для создаваемого слоя листов.
        :param zoom_start: Начальный уровень масштабирования для карты.
        :param min_lat:
        :param max_lat:
        :param min_lon:
        :param max_lon:
        :param max_bounds:
        :param crs:
        :param control_scale: Независимо от того, чтобы добавить масштаб управления на карте.
        :param prefer_canvas:
        :param no_touch:
        :param disable_3d:
        :param png_enabled:
        :param zoom_control: Отображение управления масштабированием на карте.
        """
        if location is None:
            # If location is not passed we center and zoom out.
            self.location = [0, 0]
            zoom_start = 1
        else:
            self.location = double_gis_util.validate_location(location)

        # Размеры
        self.width = double_gis_util.parse_size(width)
        self.height = double_gis_util.parse_size(height)
        self.left = double_gis_util.parse_size(left)
        self.top = double_gis_util.parse_size(top)
        # self.position = position

        # Масштабирование
        self.zoom = zoom_start

        # Маркеры
        self.markers = list()

    def add_marker(self, marker):
        """
        Добавить маркер на карту.
        :param marker: Объект маркера.
        :return: True/False.
        """
        self.markers.append(marker)
        return True

    def render(self, **kwargs):
        """
        Генерирует HTML-представление элемента.
        :return: Сгенерированное HTML представление карты.
        """
        return self._map_template.render(location=self.location,
                                         zoom=self.zoom,
                                         markers=self.markers,
                                         **kwargs)

    def save(self, html_filename):
        """
        Сохранить карту в HTML файле.
        :param html_filename: Полное имя HTML файла.
        :return: True/False.
        """
        map_html = self.render()
        html = self._html_template.render(map=map_html,
                                          width=self.width,
                                          height=self.height)

        return extfunc.save_file_text(html_filename, html)

# Для поддержки рендеринга имена классов необходимо переопределить
Map = ic2GISMap


import requests
import json
import unicodedata
from bs4 import BeautifulSoup
import os
from dotenv import load_dotenv
import time

def find_env_file(folder):
    for filename in os.listdir(folder):
        if filename.endswith(".env"):
            return os.path.join(folder, filename)
    return None

def normalize_text(text):
    normalized_text = unicodedata.normalize('NFKD', text)
    return normalized_text.replace('“', "'").replace('”', "'")

def scrape_quotes(url, output_file):
    load_dotenv(find_env_file(os.getcwd()))
    page_num = 1

    while True:
        response = requests.get(url)
        content = response.text
        soup = BeautifulSoup(content, 'html.parser')

        target_script = None
        for script in soup.find_all('script'):
            if 'text' in script.text:
                target_script = script.text
                break

        if target_script is None:
            break

        start_index = target_script.find('[')
        end_index = target_script.find('];') + 1
        quotes_data = target_script[start_index:end_index]

        try:
            quotes = json.loads(quotes_data)
            for quote in quotes:
                quote['text'] = normalize_text(quote['text'])

        except json.JSONDecodeError as e:
            print("JSON parse invalid:", e)

        with open(output_file, "a", encoding='utf-8') as file:
            for quote in quotes:
                quote_data = {
                    "text": quote['text'],
                    "by": quote['author']['name'],
                    "tags": quote['tags']
                }
                json.dump(quote_data, file, ensure_ascii=False, indent=2)
                file.write("\n")

        next_page = soup.find('li', class_='next')
        if not next_page:
            break
        url = next_page.find('a')['href']
        url = f'http://quotes.toscrape.com{url}'
        page_num += 1
        time.sleep(2)

    print(f"Quotes from {page_num} pages have been saved in the output file.")

load_dotenv(find_env_file(os.getcwd()))
input_url = os.getenv("INPUT_URL")
output_file = os.getenv("OUTPUT_FILE")


import pandas as pd
import streamlit as st
from st_aggrid import AgGrid, GridOptionsBuilder
from st_aggrid.shared import GridUpdateMode

STREAMLIT_AGGRID_URL = "https://github.com/PablocFonseca/streamlit-aggrid"
st.set_page_config(
    layout="centered", page_icon="🖱" , page_title="Interactive table app"
)
st.title("🖱 Interactive table app" )
st.write(
    """Indiana Births and Infant Mortality."""
)

st.write("Go ahead, click on a row in the table below!")

def aggrid_interactive_table(df: pd.DataFrame):
    """Creates an st-aggrid interactive table based on a dataframe.

    Args:
        df (pd.DataFrame]): Source dataframe

    Returns:
        dict: The selected row
    """
    options = GridOptionsBuilder.from_dataframe(
        df, enableRowGroup=True, enableValue=True, enablePivot=True
    )

    options.configure_side_bar()

    options.configure_selection("single")
    selection = AgGrid(
        df,
        enable_enterprise_modules=True,
        gridOptions=options.build(),
        theme="light",
        update_mode=GridUpdateMode.MODEL_CHANGED,
        allow_unsafe_jscode=True,
    )

    return selection

##"https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv"

iris = pd.read_csv(

    "http://www.indybiosystems.com/datasets/ibid_5000.txt"
)

selection = aggrid_interactive_table(df=iris)

if selection:
    st.write("You selected:")
    st.json(selection["selected_rows"])

st.write("## Code")


from functools import partial, wraps

from usage_model import Redis

def init_redis(func=None, *, redis: Redis = None):
    if func is None:
        return partial(init_redis, redis=redis)

    @wraps(func)
    async def wrapper(*args, **kwargs):
        if not redis.is_connected:
            await redis.connect()
        try:
            result = func(*args, **kwargs)
        finally:
            if redis.is_connected:
                await redis.dis_connected()
        return result

    return wrapper


import os
import re
import shutil
import subprocess
import sys

import toml

MD_ANCHOR_LINKS = r"\[(.+)\]\(#.+\)"

def slugify(s):
    """
    From: http://blog.dolphm.com/slugify-a-string-in-python/

    Simplifies ugly strings into something URL-friendly.
    >>> print slugify("[Some] _ Article's Title--")
    some-articles-title
    """
    s = s.lower()
    for c in [' ', '-', '.', '/']:
        s = s.replace(c, '_')
    s = re.sub('\W', '', s)
    s = s.replace('_', ' ')
    s = re.sub('\s+', ' ', s)
    s = s.strip()
    return s.replace(' ', '-')

# Store errors to print them at the end.
errors = []

class Theme(object):
    def __init__(self, name, path):
        print("Loading %s" % name)
        self.name = name
        self.path = path

        try:
            with open(os.path.join(self.path, "theme.toml")) as f:
                self.metadata = toml.load(f)
        except Exception as e:
            error_message = f"Theme '{self.name}' encountered a TOML parsing issue: {str(e)}"
            errors.append(error_message)
            self.metadata = None
            return  # exit the constructor early

        with open(os.path.join(self.path, "README.md")) as f:
            self.readme = f.read()
            self.readme = self.readme.replace("{{", "{{/*").replace("}}", "*/}}").replace("{%", "{%/*").replace("%}", "*/%}")
            self.readme = re.sub(MD_ANCHOR_LINKS, r"\1", self.readme)
        self.repository = self.get_repository_url()
        self.initial_commit_date, self.last_commit_date = self.get_commit_dates()

    def get_repository_url(self):
        command = "git -C {} remote -v".format(self.path)
        (_, git_remotes) = subprocess.getstatusoutput(command)
        cleaned = (
            git_remotes
            .split("\n")[0]
            .split("\t")[1]
            .replace(" (fetch)", "")
        )
        if cleaned.startswith("git@"):
            cleaned = cleaned.replace("git@github.com:", "https://github.com/").replace(".git", "")
        return cleaned

    def get_commit_dates(self):
        command = 'git log --pretty=format:"%aI" {}'.format(self.path)
        (_, date) = subprocess.getstatusoutput(command)
        dates = date.split("\n")

        # last, first
        return dates[0], dates[len(dates) - 1]

    def to_zola_content(self):
        """
        Returns the page content for Gutenberg
        """
        return """
+++
title = "{title}"
description = "{description}"
template = "theme.html"
date = {updated}

[extra]
created = {created}
updated = {updated}
repository = "{repository}"
homepage = "{homepage}"
minimum_version = "{min_version}"
license = "{license}"
demo = "{demo}"

[extra.author]
name = "{author_name}"
homepage = "{author_homepage}"
+++

{readme}
        """.format(
            title=self.metadata["name"],
            description=self.metadata["description"],
            created=self.initial_commit_date,
            updated=self.last_commit_date,
            repository=self.repository,
            homepage=self.metadata.get("homepage", self.repository),
            min_version=self.metadata["min_version"],
            license=self.metadata["license"],
            author_name=self.metadata["author"]["name"],
            author_homepage=self.metadata["author"].get("homepage", ""),
            demo=self.metadata.get("demo", ""),
            readme=self.readme,
        )

    def to_zola_folder(self, container):
        """
        Creates the page folder containing the screenshot and the info in
        content/themes
        """
        page_dir = os.path.join(container, self.name)
        os.makedirs(page_dir)

        with open(os.path.join(page_dir, "index.md"), "w") as f:
            print("Writing theme info as zola content: {}".format(self.name))
            f.write(self.to_zola_content())

        shutil.copyfile(
            os.path.join(self.path, "screenshot.png"),
            os.path.join(page_dir, "screenshot.png"),
        )

def read_themes():
    base = "./"
    themes = []

    for item in sorted(os.listdir(base)):
        full_path = os.path.join(base, item)
        if item == "env" or item == "venv":
            continue
        # themes is the name i'm giving locally when building in this folder
        if item.startswith(".") or not os.path.isdir(full_path) or item == "themes":
            continue

        if not os.path.exists(os.path.join(full_path, "README.md")):
            error_message = f"Theme '{item}' is missing README.md."
            errors.append(error_message)
            continue

        if not os.path.exists(os.path.join(full_path, "screenshot.png")):
            error_message = f"Theme '{item}' is missing screenshot.png."
            errors.append(error_message)
            continue

        theme = Theme(item, full_path)

        # Check if metadata was successfully loaded.
        if theme.metadata is None:
            continue

        required_metadata = ['name']
        metadata_check = [required for required in required_metadata if required not in theme.metadata]
        if len(metadata_check) > 0:
            error_message = f"Theme '{theme.name}' is missing required metadata: {', '.join(metadata_check)}."
            errors.append(error_message)
            continue

        themes.append(theme)

    return themes

if __name__ == "__main__":
    if len(sys.argv) != 2:
        raise Exception("Missing destination folder as argument!")

    destination = sys.argv[1]
    all_themes = read_themes()

    # Delete everything first in this folder
    if os.path.exists(destination):
        shutil.rmtree(destination)
    os.makedirs(destination)

    with open(os.path.join(destination, "_index.md"), "w") as f:
        f.write("""
+++
template = "themes.html"
sort_by = "date"
+++
        """)

    for t in all_themes:
        t.to_zola_folder(destination)

    # Display errors.
    if errors:
        print("\n\n" + "="*60)
        print("ERROR SUMMARY:")
        print("-"*60)
        for error in errors:
            print(error)
            print("-"*60)
        print("="*60 + "\n")

    # Print summary of themes processed.
    print(f"\nThemes successfully processed: {len(all_themes)}")
    print(f"Themes with errors: {len(errors)}")


import collections
import datetime
import os
import random
import shutil
import sys
import time

import numpy as np
import torch
from PIL import Image

class AverageMeter(object):
    '''
    Taken from:
    https://github.com/keras-team/keras
    '''
    """Computes and stores the average and current value"""

    def __init__(self, name, fmt=':f'):
        self.name = name
        self.fmt = fmt
        self.reset()

    def reset(self):
        self.val = 0
        self.avg = 0
        self.sum = 0
        self.count = 0

    def update(self, val, n=1):
        self.val = val
        self.sum += val * n
        self.count += n
        self.avg = self.sum / self.count

    def __str__(self):
        fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})'
        return fmtstr.format(**self.__dict__)

    def return_avg(self):
        return self.avg

class Progbar(object):
    '''
    Taken from:
    https://github.com/keras-team/keras
    '''
    """Displays a progress bar.
    # Arguments
        target: Total number of steps expected, None if unknown.
        width: Progress bar width on screen.
        verbose: Verbosity mode, 0 (silent), 1 (verbose), 2 (semi-verbose)
        stateful_metrics: Iterable of string names of metrics that
            should *not* be averaged over time. Metrics in this list
            will be displayed as-is. All others will be averaged
            by the progbar before display.
        interval: Minimum visual progress update interval (in seconds).
    """

    def __init__(self, target, width=30, verbose=1, interval=0.05,
                 stateful_metrics=None):
        self.target = target
        self.width = width
        self.verbose = verbose
        self.interval = interval
        if stateful_metrics:
            self.stateful_metrics = set(stateful_metrics)
        else:
            self.stateful_metrics = set()

        self._dynamic_display = ((hasattr(sys.stdout, 'isatty') and
                                  sys.stdout.isatty()) or
                                 'ipykernel' in sys.modules)
        self._total_width = 0
        self._seen_so_far = 0
        self._values = collections.OrderedDict()
        self._start = time.time()
        self._last_update = 0

    def update(self, current, values=None):
        """Updates the progress bar.
        # Arguments
            current: Index of current step.
            values: List of tuples:
                `(name, value_for_last_step)`.
                If `name` is in `stateful_metrics`,
                `value_for_last_step` will be displayed as-is.
                Else, an average of the metric over time will be displayed.
        """
        values = values or []
        for k, v in values:
            if k not in self.stateful_metrics:
                if k not in self._values:
                    self._values[k] = [v * (current - self._seen_so_far),
                                       current - self._seen_so_far]
                else:
                    self._values[k][0] += v * (current - self._seen_so_far)
                    self._values[k][1] += (current - self._seen_so_far)
            else:
                # Stateful metrics output a numeric value.  This representation
                # means "take an average from a single value" but keeps the
                # numeric formatting.
                self._values[k] = [v, 1]
        self._seen_so_far = current

        now = time.time()
        info = ' - %.0fs' % (now - self._start)
        if self.verbose == 1:
            if (now - self._last_update < self.interval and
                    self.target is not None and current < self.target):
                return

            prev_total_width = self._total_width
            if self._dynamic_display:
                sys.stdout.write('\b' * prev_total_width)
                sys.stdout.write('\r')
            else:
                sys.stdout.write('\n')

            if self.target is not None:
                numdigits = int(np.floor(np.log10(self.target))) + 1
                barstr = '%%%dd/%d [' % (numdigits, self.target)
                bar = barstr % current
                prog = float(current) / self.target
                prog_width = int(self.width * prog)
                if prog_width > 0:
                    bar += ('=' * (prog_width - 1))
                    if current < self.target:
                        bar += '>'
                    else:
                        bar += '='
                bar += ('.' * (self.width - prog_width))
                bar += ']'
            else:
                bar = '%7d/Unknown' % current

            self._total_width = len(bar)
            sys.stdout.write(bar)

            if current:
                time_per_unit = (now - self._start) / current
            else:
                time_per_unit = 0
            if self.target is not None and current < self.target:
                eta = time_per_unit * (self.target - current)
                if eta > 3600:
                    eta_format = ('%d:%02d:%02d' %
                                  (eta // 3600, (eta % 3600) // 60, eta % 60))
                elif eta > 60:
                    eta_format = '%d:%02d' % (eta // 60, eta % 60)
                else:
                    eta_format = '%ds' % eta

                info = ' - ETA: %s' % eta_format
            else:
                if time_per_unit >= 1:
                    info += ' %.0fs/step' % time_per_unit
                elif time_per_unit >= 1e-3:
                    info += ' %.0fms/step' % (time_per_unit * 1e3)
                else:
                    info += ' %.0fus/step' % (time_per_unit * 1e6)

            for k in self._values:
                info += ' - %s:' % k
                if isinstance(self._values[k], list):
                    avg = np.mean(
                        self._values[k][0] / max(1, self._values[k][1]))
                    if abs(avg) > 1e-3:
                        info += ' %.4f' % avg
                    else:
                        info += ' %.4e' % avg
                else:
                    info += ' %s' % self._values[k]

            self._total_width += len(info)
            if prev_total_width > self._total_width:
                info += (' ' * (prev_total_width - self._total_width))

            if self.target is not None and current >= self.target:
                info += '\n'

            sys.stdout.write(info)
            sys.stdout.flush()

        elif self.verbose == 2:
            if self.target is None or current >= self.target:
                for k in self._values:
                    info += ' - %s:' % k
                    avg = np.mean(
                        self._values[k][0] / max(1, self._values[k][1]))
                    if avg > 1e-3:
                        info += ' %.4f' % avg
                    else:
                        info += ' %.4e' % avg
                info += '\n'

                sys.stdout.write(info)
                sys.stdout.flush()

        self._last_update = now

    def add(self, n, values=None):
        self.update(self._seen_so_far + n, values)

class Memory(object):
    def __init__(self, device, size=2000, weight=0.5):
        self.memory = np.zeros((size, 128))
        self.weighted_sum = np.zeros((size, 128))
        self.weighted_count = 0
        self.weight = weight
        self.device = device

    def initialize(self, net, train_loader):
        self.update_weighted_count()
        print('Saving representations to memory')
        bar = Progbar(len(train_loader), stateful_metrics=[])
        for step, batch in enumerate(train_loader):
            with torch.no_grad():
                images = batch['original'].to(self.device)
                index = batch['index']
                output = net(images=images, mode=0)
                self.weighted_sum[index, :] = output.cpu().numpy()
                self.memory[index, :] = self.weighted_sum[index, :]
                bar.update(step, values=[])

    def update(self, index, values):
        self.weighted_sum[index, :] = values + (1 - self.weight) * self.weighted_sum[index, :]
        self.memory[index, :] = self.weighted_sum[index, :]/self.weighted_count
        pass

    def update_weighted_count(self):
        self.weighted_count = 1 + (1 - self.weight) * self.weighted_count

    def return_random(self, size, index):
        if isinstance(index, torch.Tensor):
            index = index.tolist()
        #allowed = [x for x in range(2000) if x not in index]
        allowed = [x for x in range(index[0])] + [x for x in range(index[0] + 1, 2000)]
        index = random.sample(allowed, size)
        return self.memory[index, :]

    def return_representations(self, index):
        if isinstance(index, torch.Tensor):
            index = index.tolist()
        return torch.Tensor(self.memory[index, :])

class ModelCheckpoint():
    def __init__(self, mode, directory):
        self.directory = directory
        if mode == 'min':
            self.best = np.inf
            self.monitor_op = np.less
        elif mode == 'max':
            self.best = 0
            self.monitor_op = np.greater
        else:
            print('\nChose mode \'min\' or \'max\'')
            raise Exception('Mode should be either min or max')
        if os.path.isdir(self.directory):
            shutil.rmtree(self.directory)
            os.mkdir(self.directory)
        else:
            os.mkdir(self.directory)

    def save_model(self, model, current_value, epoch):
        if self.monitor_op(current_value, self.best):
            print('\nSave model, best value {:.3f}, epoch: {}'.format(current_value, epoch))
            self.best = current_value
            torch.save(model.state_dict(), os.path.join(self.directory, 'epoch_{}'.format(epoch)))

class NoiseContrastiveEstimator():
    def __init__(self, device):
        self.device = device

    def __call__(self, original_features, path_features, index, memory, negative_nb=1000):
        loss = 0
        for i in range(original_features.shape[0]):

            temp = 0.07
            cos = torch.nn.CosineSimilarity()
            criterion = torch.nn.CrossEntropyLoss()

            negative = memory.return_random(size=negative_nb, index=[index[i]])
            negative = torch.Tensor(negative).to(self.device).detach()

            image_to_modification_similarity = cos(original_features[None, i, :], path_features[None, i, :])/temp
            matrix_of_similarity = cos(path_features[None, i, :], negative) / temp

            similarities = torch.cat((image_to_modification_similarity, matrix_of_similarity))
            loss += criterion(similarities[None, :], torch.tensor([0]).to(self.device))
        return loss / original_features.shape[0]

def pil_loader(path):
    with open(path, 'rb') as f:
        img = Image.open(f)
        return img.convert('RGB')

class Logger:
    def __init__(self, file_name):
        self.file_name = file_name
        index = ['Epoch']
        with open('{}.csv'.format(self.file_name), 'w') as file:
            file.write('Epoch,Loss,Time\n')

    def update(self, epoch, loss):
        now = datetime.datetime.now()
        with open('{}.csv'.format(self.file_name), 'a') as file:
            file.write('{},{:.4f},{}\n'.format(epoch, loss, now))


__all__ = [
    "calc",
]

import copy
import json
import logging
from pathlib import Path
import pickle as pk
from typing import NoReturn, Optional, Tuple

import numpy as np

import torch
from torch import Tensor
from torch.utils.data import DataLoader

from . import _config as config
from . import dirs
from . import influence_utils
from .influence_utils import InfluenceMethod
from .influence_utils.nn_influence_utils import InfFuncTensors
from .losses import TORCH_DEVICE
from . import tracin_utils
from .types import CustomTensorDataset, LearnerParams
from . import utils

DEFAULT_R = 10
INF_RES_DIR = None

@influence_utils.log_time(res_type=InfluenceMethod.INF_FUNC)
def calc(block: utils.ClassifierBlock, tr_dl: DataLoader, te_x: Tensor,
         te_y: Tensor, ex_id: Optional[int] = None, use_precompute: bool = False):
    r"""
    :param block: Block of interest
    :param tr_dl: \p DataLoader used to train the learners
    :param te_x:
    :param te_y:
    :param ex_id:
    :param use_precompute:
    :return:
    """
    global INF_RES_DIR
    INF_RES_DIR = dirs.RES_DIR / config.DATASET.name.lower() / "inf_func" / block.name().lower()
    INF_RES_DIR.mkdir(exist_ok=True, parents=True)

    # Use the tensors to create a supervised training set. Supports optional test transform
    kw_args = {}
    if config.has_tfms():
        kw_args = {"transform": config.get_test_tfms()}
    ds = CustomTensorDataset([te_x, te_y], **kw_args)
    te_dl = DataLoader(ds, drop_last=False, shuffle=False, num_workers=utils.NUM_WORKERS,
                       batch_size=1)

    # Do not use the original training dataloader since it may require transforms or drop part of
    # the dataset.  Create temporary Dataloader that overcomes those issues
    assert isinstance(tr_dl.dataset, CustomTensorDataset), "Code supports certain dataset type"

    # Each learner will have different influence function values
    _calc_block_inf(block=block, tr_dl=tr_dl, te_dl=te_dl, ex_id=ex_id,
                    use_precompute=use_precompute)

def _calc_block_inf(block: utils.ClassifierBlock, tr_dl: DataLoader, te_dl: DataLoader,
                    ex_id: Optional[int],
                    use_precompute: bool) -> InfFuncTensors:
    r"""
    Encapsulates calculating the influence of blocks

    :param block: Block for which influence is calculated
    :param tr_dl: Train \p DataLoader
    :param te_dl: Test \p DataLoader
    :return: Tuple of the sorted estimated loss, backdoor IDs, and dataset IDs
    """
    block.eval()
    wd = config.get_learner_val(block.name(), LearnerParams.Attribute.WEIGHT_DECAY)

    bl_x, bl_y, bd_ids, ds_ids = _build_learner_tensors(block=block, train_dl=tr_dl)
    n_tr = bl_y.shape[0]
    batch_tr_dl, instance_tr_dl = _build_block_dataloaders(bl_x=bl_x, bl_y=bl_y)

    flds = [block.name(), "inf-fin"]
    prefix = "-".join(flds).lower()
    # noinspection PyTypeChecker
    filename = utils.construct_filename(prefix=prefix, out_dir=INF_RES_DIR, ex_id=ex_id,
                                        file_ext="pkl", add_ds_to_path=False)
    # if not filename.exists():
    msg = f"calculation of {InfluenceMethod.INF_FUNC.value} influence"
    logging.info(f"Starting {msg}")
    if True:
        precomputed_s_test = None
        if use_precompute:
            assert filename.exists(), "Precomputed s_test file does not exist"
            with open(filename, "rb") as f_in:
                precomputed_s_test = pk.load(f_in).s_test

        # Order of res: influences, train_inputs_collections, s_test
        res = influence_utils.compute_influences(model=block,
                                                 n_gpu=1 if torch.cuda.is_available() else 0,
                                                 device=TORCH_DEVICE,
                                                 f_loss=block.loss.calc_train_loss,
                                                 test_dl=te_dl,
                                                 batch_train_data_loader=batch_tr_dl,
                                                 instance_train_data_loader=instance_tr_dl,
                                                 weight_decay=wd,
                                                 s_test_damp=config.DAMP,
                                                 s_test_scale=config.SCALE,
                                                 s_test_num_samples=config.R_DEPTH,
                                                 s_test_iterations=config.T_REPEATS,
                                                 precomputed_s_test=precomputed_s_test)

        # Extract the result fields
        res.ds_ids, res.bd_ids = ds_ids.clone(), bd_ids.clone()
        with open(filename, "wb+") as f_out:
            pk.dump(res, f_out)
    logging.info(f"COMPLETED {msg}")

    with open(filename, "rb") as f_in:
        res = pk.load(f_in)  # type: InfFuncTensors
    flds = (
        (res.inf_base, InfluenceMethod.INF_FUNC),
        (res.inf_sim, InfluenceMethod.INF_FUNC_RENORM),
    )
    for influence_vals, method in flds:
        # Convert the estimated loss
        est_loss = -1 / n_tr * influence_vals

        est_loss_sorted, helpful = torch.sort(est_loss, dim=0, descending=True)
        tmp_bd_ids, tmp_ds_ids = res.bd_ids[helpful], res.ds_ids[helpful]

        tracin_utils.results.generate_epoch_stats(ep=None, subepoch=None, method=method,
                                                  block=block, inf_vals=est_loss_sorted,
                                                  bd_ids=tmp_bd_ids, ds_ids=tmp_ds_ids,
                                                  ex_id=ex_id, log_cutoff=True)

        if config.USE_WANDB:
            train_dl = tracin_utils.configure_train_dataloader(train_dl=tr_dl)
            tracin_utils.generate_wandb_results(block=block, inf_vals=est_loss_sorted.cpu(),
                                                ds_ids=tmp_ds_ids.cpu(), bd_ids=tmp_bd_ids.cpu(),
                                                method=method, train_dl=train_dl, ex_id=ex_id)

    return res

def _log_influence_results(block: utils.ClassifierBlock, est_loss: Tensor, helpful: Tensor,
                           ds_ids: Tensor, bl_y: Tensor) -> NoReturn:
    r"""
    :param block:
    :param est_loss: Estimated change in loss if training example is removed
    :param helpful: Training examples numbered from 0 to (# training examples - 1)
    :param ds_ids: Dataset ID numbers for the training examples used by the block
    :param bl_y: Labels for the training examples used by the block
    """
    b_name = block.name()
    influence_utils.check_duplicate_ds_ids(ds_ids=ds_ids)

    harmful = torch.flip(helpful, dims=[0])
    for i in range(2):
        if i == 0:
            name = "helpful"
        else:
            name = "harmful"
        top_ord = locals()[name][:5]
        top_ids = ds_ids[top_ord]
        logging.info(f"{b_name}: Top {name} IDs: {top_ids.tolist()}")
        logging.info(f"{b_name}: Top {name} Est. Change Loss: {est_loss[top_ord].tolist()}")
        logging.info(f"{b_name}: Top {name} Labels: {bl_y[top_ord].tolist()}")

def _build_inf_results_file(block: utils.ClassifierBlock, helpful: Tensor, influence_vals: Tensor,
                            est_loss_vals: Tensor, ds_ids: Tensor, bl_y: Tensor) -> NoReturn:
    r"""
    Constructs the influence results file

    :param block:
    :param helpful:
    :param influence_vals:
    :param est_loss_vals:
    :param ds_ids: Dataset ID numbers for the training examples used by the block
    :param bl_y: Labels for the training examples used by the block
    :return:
    """
    assert ds_ids.shape == helpful.shape, "Helpful tensor shape does not match the ID tensor"
    assert bl_y.shape == helpful.shape, "Helpful tensor shape does not match the y tensor"

    ord_ids, ord_y = ds_ids[helpful], bl_y[helpful]
    influence_utils.check_duplicate_ds_ids(ds_ids=ds_ids)

    ord_inf, ord_est_loss = influence_vals[helpful], est_loss_vals[helpful]
    inf_res = {"block_name": block.name(),
               "dataset": config.DATASET.name,
               "hvp_batch_size": config.HVP_BATCH_SIZE,
               "damp": config.DAMP,
               "scale": config.SCALE,
               "helpful-ids": ord_ids.tolist(),
               "helpful-ord-loss": ord_est_loss.tolist(),
               "helpful-y": ord_y.tolist(),
               "helpful-influence": ord_inf.tolist(),
               "test_id": config.TARG_IDX,
               "test-targ-cls": config.TARG_CLS,
               "test-pois-cls": config.POIS_CLS
               }

    res_path = _build_inf_res_filename(block)
    with open(res_path, "w+") as f_out:
        json.dump(inf_res, f_out)

def _build_inf_res_filename(block: utils.ClassifierBlock) -> Path:
    r""" Construct the filename for the results """
    prefix = f"inf-{block.name()}-t-id={config.TARG_IDX}"
    return utils.construct_filename(prefix, out_dir=dirs.RES_DIR, file_ext="json",
                                    add_timestamp=True)

def _build_learner_tensors(block: utils.ClassifierBlock,
                           train_dl: DataLoader) -> Tuple[Tensor, Tensor, Tensor, Tensor]:
    r"""
    Construct the X/y/IDs tensors based on any example filtering by the block
    :param block:
    :param train_dl:
    :return: Tuple of X, y, backdoor IDs, and dataset IDs tensors respectively
    """
    tmp_ds = copy.copy(train_dl.dataset)
    tmp_ds.transform = None
    cp_tr_dl = DataLoader(tmp_ds, batch_size=config.BATCH_SIZE,
                          drop_last=False, shuffle=False, num_workers=utils.NUM_WORKERS)

    verify_contents = True   # ToDo Revert to false to speed up final version

    all_x, all_y, all_bd_ids, all_ds_ids = [], [], [], []
    for batch_tensors in cp_tr_dl:
        batch = block.organize_batch(batch_tensors, process_mask=True,
                                     verify_contents=verify_contents)
        if batch.skip():
            continue

        all_x.append(batch.xs.cpu())
        all_y.append(batch.lbls.cpu())
        all_bd_ids.append(batch.bd_ids.cpu())
        all_ds_ids.append(batch.ds_ids.cpu())

    all_ds_ids, id_ordering = torch.sort(torch.cat(all_ds_ids, dim=0), dim=0)
    # Consolidate into tensors and sort by the image IDs
    n_tr = id_ordering.shape[0]  # Number of training examples
    # Strange count for number of training examples
    assert n_tr == id_ordering.numel(), "Weird size mismatch"

    filename = "_".join([block.name().lower(), "inf-func", block.start_time])
    # noinspection PyUnresolvedReferences
    np.savetxt(INF_RES_DIR / (filename + "_ord-id.csv"), all_ds_ids.numpy(), fmt='%d',
               delimiter=',')

    # Combine the subtensors and ensure the order aligns with all_ds_ids
    tr_x, tr_y = torch.cat(all_x, dim=0)[id_ordering], torch.cat(all_y, dim=0)[id_ordering]
    all_bd_ids = torch.cat(all_bd_ids, dim=0)[id_ordering]
    return tr_x, tr_y, all_bd_ids, all_ds_ids

def _build_block_dataloaders(bl_x: Tensor, bl_y: Tensor) -> Tuple[DataLoader, DataLoader]:
    r"""
    Constructs two separate dataloaders.  You may want different properties dataloader properties
    when estimating the Hessian vector product (HVP) and when estimating influence.  By specifying
    separate \p DataLoaders, those two roles are separated.

    :param bl_x: Block's X tensor
    :param bl_y: Blocks y (i.e. label) tensor
    :return: Tuple of the batch \p DataLoader (used for generating the HVP) and the instance
             \p DataLoader used when estimating influence.
    """
    # ToDo Determine whether to use transforms
    ds = CustomTensorDataset((bl_x, bl_y), transform=config.get_train_tfms())
    batch_tr_dl = DataLoader(ds, batch_size=config.HVP_BATCH_SIZE,
                             shuffle=True, drop_last=True, num_workers=utils.NUM_WORKERS)

    ds = CustomTensorDataset((bl_x, bl_y), transform=config.get_test_tfms())
    instance_tr_dl = DataLoader(ds, batch_size=1, shuffle=False, drop_last=False,
                                num_workers=utils.NUM_WORKERS)
    return batch_tr_dl, instance_tr_dl


import copy
import threading
import socketserver
import json
from typing import List
from mcsu_data import *

_BUFFER_SIZE = 1024
_CLIENTS_MAX = 8

class State:
    def __init__(self):
        self.userdata = DataGame(0, [])
        self.uid_free = []
        self.uid = 0
        self.lock = threading.Semaphore()

    def get_userdata(self):
        self.lock.acquire()
        mycopy: DataGame = copy.deepcopy(self.userdata)
        self.lock.release()
        return mycopy

    def set_userdata(self, player: DataPlayer):
        self.lock.acquire()

        found = False
        for i, curplayer in enumerate(self.userdata.players):
            if curplayer.uid == player.uid:
                self.userdata.players[i] = player
                found = True
                break
        if not found:
            self.userdata.players.append(player)

        self.lock.release()

    def next_turn(self):
        self.lock.acquire()
        self.uid = (self.uid + 1) % len(self.userdata.players)
        self.lock.release()

    def del_uid(self, uid: int):
        self.lock.acquire()
        for player in self.userdata.players:
            if uid == player.uid:
                self.uid_free.append(uid)

                # we can't remain in this turn anymore
                if self.userdata.turn == player.uid:
                    self.next_turn()

                del self.userdata.players[uid]
                break
        self.lock.release()

    def new_uid(self) -> int:
        self.lock.acquire()
        if len(self.uid_free) > 0:
            uid = self.uid_free.pop(0)
            self.lock.release()
            return uid

        uid = self.uid
        self.uid += 1
        self.lock.release()
        return uid

class McsuServer:
    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port
        self.state: State = State()
        self.turn: int = 0

    def run(self):
        class Handler(socketserver.ThreadingTCPServer):
            thisref = self
            def handle(self):
                this = Handler.thisref
                uid = -1

                # DC if too many clients
                if len(self.state) >= _CLIENTS_MAX:
                    print("Too many clients!")
                    return

                self.request.setblocking(True)
                while True:
                    data = self.receive()
                    if data is None:
                        if uid != -1: self.state.del_uid(uid)
                        print("No data")
                        break

                    command = data.get('_command')
                    if command is None:
                        if uid != -1: self.state.del_uid(uid)
                        print("No command")
                        break

                    elif command == 'register':
                        uid = self.state.new_uid()
                        units = data.get('units')
                        if not units is None:
                            data = DataPlayer(uid, units)
                            self.state.set_userdata(data)
                        data = DataRegister(uid)
                        self.send(data)

                    elif command == 'status':
                        if uid == -1:
                            print("No status uid")
                            break
                        data: DataGame = self.state.get_userdata()
                        self.send(data)

                    elif command == 'finish':
                        if uid == -1:
                            print("No finish uid")
                            break
                        self.state.next_turn()

                    elif command == 'quit':
                        if uid != -1:
                            print("No quit uid")
                            self.state.del_uid(uid)
                        self.state.del_uid(uid)
                        break

                    elif command == 'move':
                        if uid == -1:
                            print("No move uid")
                            break

                        # get commanded position
                        selected_unit = data.get('mover')
                        x = data.get('x')
                        y = data.get('y')
                        if selected_unit is None or x is None or y is None:
                            print("No selected unit/x/y")
                            break

                        state: DataGame = self.state.get_userdata()
                        need_to_break = False
                        for player in state.players:
                            if not uid == player.uid: continue

                            # find data unit from selected unit
                            for unit in player.units:
                                if unit.x == selected_unit.x and unit.y == selected_unit.y:
                                    # move it!
                                    unit.x = x
                                    unit.y = y
                            if need_to_break: break

                    elif command == 'attack':
                        pass

            def send(self, obj):
                myobj = obj if type(obj) is dict else obj.__dict__
                try:
                    message = json.dumps(myobj)
                except:
                    print('Failed to dumps')
                    return

                try:
                    self.request.sendall(message)
                except:
                    print('Failed to sendall')
                    return

            def receive(self):
                try:
                    self.message = self.request.recv(_BUFFER_SIZE)
                except:
                    print("Failed to receive")
                    return None

                # disconnected
                if len(self.message) == 0: return None

                try:
                    data: dict = json.loads(self.message)
                except:
                    print("Failed to loads")
                    return None
                return data

        with socketserver.ThreadingTCPServer((self.host, self.port), Handler) as server:
            server.serve_forever()

def main(args):
    server = McsuServer('0.0.0.0', 20000)
    server.run()
    return 0

if __name__ == '__main__':
    import sys
    exit(main(sys.argv))


import numpy as np
import time
import uuid

from models.Basic import Basic
from gurobipy import *

class FairIR(Basic):
    """Fair paper matcher via iterative relaxation.

    """

    def __init__(self, loads, loads_lb, coverages, weights, thresh=0.0):
        """Initialize.

        Args:
            loads - a list of integers specifying the maximum number of papers
                  for each reviewer.
            loads_lb - a list of ints specifying the minimum number of papers
                  for each reviewer.
            coverages - a list of integers specifying the number of reviews per
                 paper.
            weights - the affinity matrix (np.array) of papers to reviewers.
                   Rows correspond to reviewers and columns correspond to
                   papers.

            Returns:
                initialized makespan matcher.
        """
        self.n_rev = np.size(weights, axis=0)
        self.n_pap = np.size(weights, axis=1)
        self.loads = loads
        self.loads_lb = loads_lb
        self.coverages = coverages
        self.weights = weights
        self.id = uuid.uuid4()
        self.m = Model("%s : FairIR" % str(self.id))
        self.makespan = thresh
        self.solution = None

        self.m.setParam('OutputFlag', 0)

        self.load_ub_name = 'lib'
        self.load_lb_name = 'llb'
        self.cov_name = 'cov'
        self.ms_constr_prefix = 'ms'
        self.round_constr_prefix = 'round'

        # primal variables
        start = time.time()
        self.lp_vars = []
        for i in range(self.n_rev):
            self.lp_vars.append([])
            for j in range(self.n_pap):
                self.lp_vars[i].append(self.m.addVar(ub=1.0,
                                                     name=self.var_name(i, j)))
        self.m.update()
        print('#info FairIR:Time to add vars %s' % (time.time() - start))

        start = time.time()
        # set the objective
        obj = LinExpr()
        for i in range(self.n_rev):
            for j in range(self.n_pap):
                obj += self.weights[i][j] * self.lp_vars[i][j]
        self.m.setObjective(obj, GRB.MAXIMIZE)
        print('#info FairIR:Time to set obj %s' % (time.time() - start))

        start = time.time()
        # load upper bound constraints.
        for r, load in enumerate(self.loads):
            self.m.addConstr(sum(self.lp_vars[r]) <= load,
                             self.lub_constr_name(r))

        # load load bound constraints.
        if self.loads_lb is not None:
            for r, load in enumerate(self.loads_lb):
                self.m.addConstr(sum(self.lp_vars[r]) >= load,
                                 self.llb_constr_name(r))

        # coverage constraints.
        for p, cov in enumerate(self.coverages):
            self.m.addConstr(sum([self.lp_vars[i][p]
                                  for i in range(self.n_rev)]) == cov,
                             self.cov_constr_name(p))

        # makespan constraints.
        for p in range(self.n_pap):
            self.m.addConstr(sum([self.lp_vars[i][p] * self.weights[i][p]
                                  for i in range(self.n_rev)]) >= self.makespan,
                             self.ms_constr_name(p))
        self.m.update()
        print('#info FairIR:Time to add constr %s' % (time.time() - start))

    def ms_constr_name(self, p):
        """Name of the makespan constraint for paper p."""
        return '%s%s' % (self.ms_constr_prefix, p)

    def lub_constr_name(self, r):
        """Name of load upper bound constraint for reviewer r."""
        return '%s%s' % (self.load_ub_name, r)

    def llb_constr_name(self, r):
        """Name of load lower bound constraint for reviewer r."""
        return '%s%s' % (self.load_lb_name, r)

    def cov_constr_name(self, p):
        """Name of coverage constraint for paper p."""
        return '%s%s' % (self.cov_name, p)

    def change_makespan(self, new_makespan):
        """Change the current makespan to a new_makespan value.

        Args:
            new_makespan - the new makespan constraint.

        Returns:
            Nothing.
        """
        for c in self.m.getConstrs():
            if c.getAttr("ConstrName").startswith(self.ms_constr_prefix):
                self.m.remove(c)
                # self.m.update()

        for p in range(self.n_pap):
            self.m.addConstr(sum([self.lp_vars[i][p] * self.weights[i][p]
                                  for i in range(self.n_rev)]) >= new_makespan,
                             self.ms_constr_prefix + str(p))
        self.makespan = new_makespan
        self.m.update()

    def sol_as_mat(self):
        if self.m.status == GRB.OPTIMAL or self.m.status == GRB.SUBOPTIMAL:
            solution = np.zeros((self.n_rev, self.n_pap))
            for v in self.m.getVars():
                i, j = self.indices_of_var(v)
                solution[i, j] = v.x
            self.solution = solution
            return solution
        else:
            raise Exception(
                'You must have solved the model optimally or suboptimally '
                'before calling this function.')

    def integral_sol_found(self):
        """Return true if all lp variables are integral."""
        sol = self.sol_as_dict()
        return all(sol[self.var_name(i, j)] == 1.0 or
                   sol[self.var_name(i, j)] == 0.0
                   for i in range(self.n_rev) for j in range(self.n_pap))

    def fix_assignment(self, i, j, val):
        """Round the variable x_ij to val."""
        self.lp_vars[i][j].ub = val
        self.lp_vars[i][j].lb = val

    def find_ms(self):
        """Find an the highest possible makespan.

        Perform a binary search on the makespan value. Each time, solve the
        makespan LP without the integrality constraint. If we can find a
        fractional value to one of these LPs, then we can round it.

        Args:
            None

        Return:
            Highest feasible makespan value found.
        """
        mn = 0.0
        mx = np.max(self.weights) * np.max(self.coverages)
        ms = mx
        best = None
        self.change_makespan(ms)
        start = time.time()
        self.m.optimize()
        print('#info FairIR:Time to solve %s' % (time.time() - start))
        for i in range(10):
            print('#info FairIR:ITERATION %s ms %s' % (i, ms))
            if self.m.status == GRB.INFEASIBLE:
                mx = ms
                ms -= (ms - mn) / 2.0
            else:
                assert(best is None or ms > best)
                assert(self.m.status == GRB.OPTIMAL)
                best = ms
                mn = ms
                ms += (mx - ms) / 2.0
            self.change_makespan(ms)
            self.m.optimize()
        return best

    def solve(self):
        """Find a makespan and solve the ILP.

        Run a binary search to find an appropriate makespan and then solve the
        ILP. If solved optimally or suboptimally then save the solution.

        Args:
            mn - the minimum feasible makespan (optional).
            mx - the maximum possible makespan( optional).
            itr - the number of iterations of binary search for the makespan.
            log_file - the string path to the log file.

        Returns:
            The solution as a matrix.
        """
        if self.makespan <= 0:
            print('#info FairIR: searching for fairness threshold')
            ms = self.find_ms()
        else:
            print('#info FairIR: config fairness threshold: %s' % self.makespan)
            ms = self.makespan
        self.change_makespan(ms)
        self.round_fractional(np.ones((self.n_rev, self.n_pap)) * -1)

        sol = {}
        for v in self.m.getVars():
            sol[v.varName] = v.x

    def sol_as_dict(self):
        """Return the solution to the optimization as a dictionary.

        If the matching has not be solved optimally or suboptimally, then raise
        an exception.

        Args:
            None.

        Returns:
            A dictionary from var_name to value (either 0 or 1)
        """
        if self.m.status == GRB.OPTIMAL or self.m.status == GRB.SUBOPTIMAL:
            _sol = {}
            for v in self.m.getVars():
                _sol[v.varName] = v.x
            return _sol
        else:
            raise Exception(
                'You must have solved the model optimally or suboptimally '
                'before calling this function.\nSTATUS %s\tMAKESPAN %f' % (
                    self.m.status, self.makespan))

    def round_fractional(self, integral_assignments=None, count=0):
        """Round a fractional solution.

        This is the meat of the iterative relaxation approach.  First, if the
        solution to the relaxed LP is integral, then we're done--return the
        solution. Otherwise, here's what we do:
        1. if a variable is integral, lock it's value to that integer.
        2. find all papers with exactly 2 or 3 fractionally assigned revs and
           drop the makespan constraint on that reviewer.
        3. if no makespan constraints dropped, find a reviewer with exactly two
           fraction assignments and drop the load constraints on that reviewer.

        Args:
            integral_assignments - np.array of revs x paps (initially None).
            log_file - the log file if exists.
            count - (int) to keep track of the number of calls to this function.

        Returns:
            Nothing--has the side effect or storing an assignment matrix in this
            class.
        """
        if integral_assignments is None:
            integral_assignments = np.ones((self.n_rev, self.n_pap)) * -1

        self.m.optimize()

        if self.m.status != GRB.OPTIMAL and self.m.status != GRB.SUBOPTIMAL:
            assert False, '%s\t%s' % (self.m.status, self.makespan)

        if self.integral_sol_found():
            return
        else:
            frac_assign_p = {}
            frac_assign_r = {}
            sol = self.sol_as_dict()
            fractional_vars = []

            # Find fractional vars.
            for i in range(self.n_rev):
                for j in range(self.n_pap):
                    if j not in frac_assign_p:
                        frac_assign_p[j] = []
                    if i not in frac_assign_r:
                        frac_assign_r[i] = []

                    if sol[self.var_name(i, j)] == 0.0 and \
                                    integral_assignments[i][j] != 0.0:
                        self.fix_assignment(i, j, 0.0)
                        integral_assignments[i][j] = 0.0

                    elif sol[self.var_name(i, j)] == 1.0 and \
                                    integral_assignments[i][j] != 1.0:
                        self.fix_assignment(i, j, 1.0)
                        integral_assignments[i][j] = 1.0

                    elif sol[self.var_name(i, j)] != 1.0 and \
                                    sol[self.var_name(i, j)] != 0.0:
                        frac_assign_p[j].append(
                            (i, j, sol[self.var_name(i, j)]))
                        frac_assign_r[i].append(
                            (i, j, sol[self.var_name(i, j)]))
                        fractional_vars.append((i, j, sol[self.var_name(i, j)]))

                        integral_assignments[i][j] = sol[self.var_name(i, j)]

            # First try to elim a makespan constraint.
            removed = False
            for (paper, frac_vars) in frac_assign_p.items():
                if len(frac_vars) == 2 or len(frac_vars) == 3:
                    for c in self.m.getConstrs():
                        if c.ConstrName == self.ms_constr_name(paper):
                            self.m.remove(c)
                            removed = True

            # If necessary remove a load constraint.
            if not removed:
                for (rev, frac_vars) in frac_assign_r.items():
                    if len(frac_vars) == 2:
                        for c in self.m.getConstrs():
                            if c.ConstrName == self.lub_constr_name(rev) or \
                                    c.ConstrName == self.llb_constr_name(rev):
                                self.m.remove(c)
            self.m.update()
            return self.round_fractional(integral_assignments, count + 1)

if __name__ == "__main__":
    init_makespan = 0.7
    ws = np.array([
        np.array([0.9, 0.9, 0.5, 0.5]),
        np.array([0.9, 0.9, 0.6, 0.6]),
        np.array([0.1, 0.1, 0.2, 0.2]),
        np.array([0.2, 0.1, 0.2, 0.3])
    ])
    print(ws)
    a = np.array([2, 2, 2, 2])
    b = np.array([2, 2, 2, 2])
    x = FairIR(a, [0, 0, 0, 0], b, ws)
    s = time.time()
    x.solve()
    print(x.sol_as_mat())
    print(x.objective_val())
    print(time.time() - s)
    print("[done.]")


import gym

class GymSpec:
    def __init__(self, name, env_id):
        self.name = name
        self.env_id = env_id

GYM_ENVS = [
    GymSpec('gym_CartPole-v0', 'CartPole-v0'),
    GymSpec('gym_CartPolev-1', 'CartPole-v1'),
]

def gym_env_by_name(name):
    for cfg in GYM_ENVS:
        if cfg.name == name:
            return cfg
    raise Exception('Unknown Gym env')

def make_gym_env(env_name, cfg, **kwargs):
    mujoco_spec = gym_env_by_name(env_name)
    env = gym.make(mujoco_spec.env_id)
    return env


import requests
from django.shortcuts import redirect, render
from animal.models import Siliao,Zhongzhu,Peizhong,Renjian,Fenmian,Caijing,Xingweiy
from django.http import JsonResponse
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from animal.models import Site_Info, User
from django.contrib import auth
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
import os

# Create your views here.
def index(request):
    return render(request, "animal/index.html")
def xinxiyulan(request):
    return render(request, "animal/xinxiyulan.html")
def xiputu(request):
    return render(request, "animal/xiputu.html")
def shengchantishi(request):
    data1_list = Zhongzhu.objects.filter(Q(peizhong__contains='否')).count()
    data2_list = Zhongzhu.objects.filter(Q(zaizhu__contains='是')).count()
    data3_list = Zhongzhu.objects.filter(pinzhong__contains='种公猪',yimiao__contains='否').count()
    data4_list = Zhongzhu.objects.filter(pinzhong__contains='种母猪', yimiao__contains='否').count()
    return render(request, "animal/shengchantishi.html", {"data1_list": data1_list,"data2_list": data2_list,"data3_list": data3_list,"data4_list": data4_list})

def siliaokucun(request):
    data_list = Siliao.objects.all()
    return render(request, "animal/siliaokucun.html",{'data_list':data_list})
def xingweijilu(request):
    data1_list = Peizhong.objects.all()
    data2_list = Renjian.objects.all()
    data3_list = Fenmian.objects.all()
    data4_list = Caijing.objects.all()
    data5_list = Xingweiy.objects.all()
    return render(request, "animal/xingweijilu.html", {'data1_list': data1_list,'data2_list':data2_list,'data3_list':data3_list,'data4_list':data4_list,'data5_list':data5_list})

def peiadd(request):
    if request.method == "GET":
        return render(request,"animal/peiadd.html")
    bianhao = request.POST.get("bianhao")
    jiluneirong = request.POST.get("jiluneirong")
    Peizhong.objects.create(bianhao=bianhao,jiluneirong=jiluneirong)
    return redirect("/xingweijilu")
def peidelete(request):
    #删除饲料库存
    nid = request.GET.get('nid')
    Peizhong.objects.filter(id=nid).delete()
    return redirect("/xingweijilu")
def renadd(request):
    if request.method == "GET":
        return render(request,"animal/renadd.html")
    bianhao = request.POST.get("bianhao")
    jiluneirong = request.POST.get("jiluneirong")
    Renjian.objects.create(bianhao=bianhao,jiluneirong=jiluneirong)
    return redirect("/xingweijilu")
def rendelete(request):
    nid = request.GET.get('nid')
    Renjian.objects.filter(id=nid).delete()
    return redirect("/xingweijilu")
def fenadd(request):
    if request.method == "GET":
        return render(request,"animal/fenadd.html")
    bianhao = request.POST.get("bianhao")
    jiluneirong = request.POST.get("jiluneirong")
    Fenmian.objects.create(bianhao=bianhao,jiluneirong=jiluneirong)
    return redirect("/xingweijilu")
def fendelete(request):
    nid = request.GET.get('nid')
    Fenmian.objects.filter(id=nid).delete()
    return redirect("/xingweijilu")
def caiadd(request):
    if request.method == "GET":
        return render(request,"animal/caiadd.html")
    bianhao = request.POST.get("bianhao")
    jiluneirong = request.POST.get("jiluneirong")
    Caijing.objects.create(bianhao=bianhao,jiluneirong=jiluneirong)
    return redirect("/xingweijilu")
def caidelete(request):
    nid = request.GET.get('nid')
    Caijing.objects.filter(id=nid).delete()
    return redirect("/xingweijilu")
def yadd(request):
    if request.method == "GET":
        return render(request,"animal/yadd.html")
    bianhao = request.POST.get("bianhao")
    jiluneirong = request.POST.get("jiluneirong")
    Xingweiy.objects.create(bianhao=bianhao,jiluneirong=jiluneirong)
    return redirect("/xingweijilu")
def ydelete(request):
    nid = request.GET.get('nid')
    Xingweiy.objects.filter(id=nid).delete()
    return redirect("/xingweijilu")
def siliaoadd(request):
    if request.method == "GET":
        return render(request,"animal/siliaoadd.html")
    sname = request.POST.get("sname")
    kucun = request.POST.get("kucun")
    Siliao.objects.create(sname=sname,kucun=kucun)
    return redirect("/siliaokucun")
def sdelete(request):
    #删除饲料库存
    nid = request.GET.get('nid')
    Siliao.objects.filter(id=nid).delete()
    return redirect("/siliaokucun")
def edit(request,nid):
    if request.method =="GET":
        row_object = Siliao.objects.filter(id=nid).first()
        print(row_object.sname,row_object.kucun)
        return render(request,'animal/edit.html',{"row_object": row_object})
    #获取
    sname = request.POST.get("sname")
    Siliao.objects.filter(id=nid).update(sname=sname)
    kucun = request.POST.get("kucun")
    Siliao.objects.filter(id=nid).update(kucun=kucun)
    return redirect("/siliaokucun")
def chart_bar(request):
    data1_list = Zhongzhu.objects.filter(Q(zhushe__contains='1')).count()
    data2_list = Zhongzhu.objects.filter(Q(zhushe__contains='2')).count()
    data3_list = Zhongzhu.objects.filter(Q(zhushe__contains='3')).count()
    data4_list = Zhongzhu.objects.filter(Q(zhushe__contains='4')).count()
    data5_list = Zhongzhu.objects.filter(Q(zhushe__contains='5')).count()
    legend = ["数量"]
    series_list =[
        {
            "name": '数量',
            "type": 'bar',
            "data": [data1_list, data2_list, data3_list, data4_list, data5_list]
        }
    ]
    x_axis = ['一号猪舍','二号猪舍','三号猪舍','四号猪舍','五号猪舍']
    result ={
        "status":True,
        "data":{
            'legend':legend,
            'series_list':series_list,
            'x_axis':x_axis,
        }
    }
    return JsonResponse(result)
def chart_bing(request):
    data1_list = Zhongzhu.objects.filter(Q(pinzhong__contains='种公猪')).count()
    data2_list = Zhongzhu.objects.filter(Q(pinzhong__contains='种母猪')).count()
    data =[

        { "value": data1_list, "name": '种公猪' },
        { "value": data2_list, "name": '种母猪' },
    ]

    result ={
        "status":True,
        'data':data,

    }
    return JsonResponse(result)
def chart_zong(request):
    data_list = Zhongzhu.objects.all().count()
    data =[
        {
            "value": data_list,
            "name": '种猪数'
        }
    ]
    result ={
        "status":True,
        'data':data
    }
    return JsonResponse(result)
def chart_ku(request):
    data1_list = Siliao.objects.filter(sname='麸皮').values_list('kucun').first()
    data2_list = Siliao.objects.filter(sname='蛋白质类').values_list('kucun').first()
    data3_list = Siliao.objects.filter(sname='矿物质类').values_list('kucun').first()
    data4_list = Siliao.objects.filter(sname='维生素类').values_list('kucun').first()
    data5_list = Siliao.objects.filter(sname='大麦').values_list('kucun').first()
    data6_list = Siliao.objects.filter(sname='小麦').values_list('kucun').first()
    data7_list = Siliao.objects.filter(sname='玉米').values_list('kucun').first()
    data8_list = Siliao.objects.filter(sname='油脂').values_list('kucun').first()
    data =[
        {"value": data1_list, "name": '麸皮'},
        {"value": data2_list, "name": '蛋白质类'},
        {"value": data3_list, "name": '矿物质类'},
        {"value": data4_list, "name": '维生素类'},
        {"value": data5_list, "name": '大麦'},
        {"value": data6_list, "name": '小麦'},
        {"value": data7_list, "name": '玉米'},
        {"value": data8_list, "name": '油脂'}
    ]
    result ={
        "status":True,
        'data':data
    }
    return JsonResponse(result)

def chart_graph(request):

    data_list =[
        {
            "name":1,
            "category": '种公猪',
            "draggable": "true",
        }, {
            "name": 2,
            "category": '种母猪',
            "draggable": "true",
        }, {
            "name": 3,
            "category": '种公猪',
            "draggable": "true",
        }, {
            "name": 4,
            "category": '种母猪',
            "draggable": "true",
        }, {
            "name": 5,
            "category": '种公猪',
            "draggable": "true",
        }, {
            "name": 6,
            "category": '种公猪',
            "draggable": "true",
        }, {
            "name": 7,
            "category": '种母猪',
            "draggable": "true",
        },
    ]
    links =[
        {
            "source": '1',
            "target": '5',
            "value": '父系',

        }, {
            "source": '2',
            "target": '5',
            "value": '母系',
        }, {
            "source": '3',
            "target": '7',
            "value": '父系',
        }, {
            "source": '4',
            "target": '7',
            "value": '母系',
        }, {
            "source": '5',
            "target": '6',
            "value": '父系',
        }, {
            "source": '7',
            "target": '6',
            "value": '母系',
        },
    ]
    result ={
        "status":True,
        'data':{
            'data_list':data_list,
            'links':links,

        }

    }
    return JsonResponse(result)