height = input("Input height (in cm): ")
weight = input("Input weight (in kg): ")

height = float(height)
height = height / 100
weightint = float(weight)
height2 = height ** 2
bmi = weightint / height2

underweight = 18.5
normalweight = 24.9
preadipositas = 29.9
moderateadipositas = 34.9
strongadipositas = 39.9
user_score = ""

if bmi < underweight:
    user_score = "Underweight"
elif ((bmi > underweight) and (bmi < normalweight)):
    user_score = "Normalweight"
elif ((bmi < preadipositas) and (bmi > normalweight)):
    user_score = "Overweight"
elif ((bmi > normalweight) and (bmi < preadipositas)):
    user_score = "Pre-adipositas"
elif ((bmi > preadipositas) and (bmi < moderateadipositas)):
    user_score = "Moderate adipositas"
elif ((bmi > moderateadipositas) and (bmi < strongadipositas)):
    user_score = "Strong adipositas"
elif ((bmi > strongadipositas)):
    user_score = "Extreme adipositas"
print(f"Your height is {height} m. Your weight is {weight} kg. Your calculated BMI is {round(bmi, 2)} - {user_score}.")


#!/usr/bin/env python

##################################################
## DEPENDENCIES
import sys
import os
import os.path
try:
    import builtins as builtin
except ImportError:
    import __builtin__ as builtin
from os.path import getmtime, exists
import time
import types
from Cheetah.Version import MinCompatibleVersion as RequiredCheetahVersion
from Cheetah.Version import MinCompatibleVersionTuple as RequiredCheetahVersionTuple
from Cheetah.Template import Template
from Cheetah.DummyTransaction import *
from Cheetah.NameMapper import NotFound, valueForName, valueFromSearchList, valueFromFrameOrSearchList
from Cheetah.CacheRegion import CacheRegion
import Cheetah.Filters as Filters
import Cheetah.ErrorCatchers as ErrorCatchers

##################################################
## MODULE CONSTANTS
VFFSL=valueFromFrameOrSearchList
VFSL=valueFromSearchList
VFN=valueForName
currentTime=time.time
__CHEETAH_version__ = '2.4.4'
__CHEETAH_versionTuple__ = (2, 4, 4, 'development', 0)
__CHEETAH_genTime__ = 1458422848.980832
__CHEETAH_genTimestamp__ = 'Sat Mar 19 16:27:28 2016'
__CHEETAH_src__ = '/home/jeb/Repositories/rosmod/gui/templates/rapidxml_utils_hpp.tmpl'
__CHEETAH_srcLastModified__ = 'Tue Mar  8 10:57:08 2016'
__CHEETAH_docstring__ = 'Autogenerated by Cheetah: The Python-Powered Template Engine'

if __CHEETAH_versionTuple__ < RequiredCheetahVersionTuple:
    raise AssertionError(
      'This template was compiled with Cheetah version'
      ' %s. Templates compiled before version %s must be recompiled.'%(
         __CHEETAH_version__, RequiredCheetahVersion))

##################################################
## CLASSES

class rapidxml_utils_hpp(Template):

    ##################################################
    ## CHEETAH GENERATED METHODS

    def __init__(self, *args, **KWs):

        super(rapidxml_utils_hpp, self).__init__(*args, **KWs)
        if not self._CHEETAH__instanceInitialized:
            cheetahKWArgs = {}
            allowedKWs = 'searchList namespaces filter filtersLib errorCatcher'.split()
            for k,v in KWs.items():
                if k in allowedKWs: cheetahKWArgs[k] = v
            self._initCheetahInstance(**cheetahKWArgs)

    def respond(self, trans=None):

        ## CHEETAH: main method generated for this template
        if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
            trans = self.transaction # is None unless self.awake() was called
        if not trans:
            trans = DummyTransaction()
            _dummyTrans = True
        else: _dummyTrans = False
        write = trans.response().write
        SL = self._CHEETAH__searchList
        _filter = self._CHEETAH__currentFilter

        ########################################
        ## START - generated method body

        write(u'''#ifndef RAPIDXML_UTILS_HPP_INCLUDED\r
#define RAPIDXML_UTILS_HPP_INCLUDED\r
\r
// Copyright (C) 2006, 2009 Marcin Kalicinski\r
// Version 1.13\r
// Revision $DateTime: 2009/05/13 01:46:17 $\r
//! \\file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful\r
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.\r
\r
#include "rapidxml.hpp"\r
#include <vector>\r
#include <string>\r
#include <fstream>\r
#include <stdexcept>\r
\r
namespace rapidxml\r
{\r
\r
    //! Represents data loaded from a file\r
    template<class Ch = char>\r
    class file\r
    {\r
        \r
    public:\r
        \r
        //! Loads file into the memory. Data will be automatically destroyed by the destructor.\r
        //! \\param filename Filename to load.\r
        file(const char *filename)\r
        {\r
            using namespace std;\r
\r
            // Open stream\r
            basic_ifstream<Ch> stream(filename, ios::binary);\r
            if (!stream)\r
                throw runtime_error(string("cannot open file ") + filename);\r
            stream.unsetf(ios::skipws);\r
            \r
            // Determine stream size\r
            stream.seekg(0, ios::end);\r
            size_t size = stream.tellg();\r
            stream.seekg(0);   \r
            \r
            // Load data and add terminating 0\r
            m_data.resize(size + 1);\r
            stream.read(&m_data.front(), static_cast<streamsize>(size));\r
            m_data[size] = 0;\r
        }\r
\r
        //! Loads file into the memory. Data will be automatically destroyed by the destructor\r
        //! \\param stream Stream to load from\r
        file(std::basic_istream<Ch> &stream)\r
        {\r
            using namespace std;\r
\r
            // Load data and add terminating 0\r
            stream.unsetf(ios::skipws);\r
            m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());\r
            if (stream.fail() || stream.bad())\r
                throw runtime_error("error reading stream");\r
            m_data.push_back(0);\r
        }\r
        \r
        //! Gets file data.\r
        //! \\return Pointer to data of file.\r
        Ch *data()\r
        {\r
            return &m_data.front();\r
        }\r
\r
        //! Gets file data.\r
        //! \\return Pointer to data of file.\r
        const Ch *data() const\r
        {\r
            return &m_data.front();\r
        }\r
\r
        //! Gets file data size.\r
        //! \\return Size of file data, in characters.\r
        std::size_t size() const\r
        {\r
            return m_data.size();\r
        }\r
\r
    private:\r
\r
        std::vector<Ch> m_data;   // File data\r
\r
    };\r
\r
    //! Counts children of node. Time complexity is O(n).\r
    //! \\return Number of children of node\r
    template<class Ch>\r
    inline std::size_t count_children(xml_node<Ch> *node)\r
    {\r
        xml_node<Ch> *child = node->first_node();\r
        std::size_t count = 0;\r
        while (child)\r
        {\r
            ++count;\r
            child = child->next_sibling();\r
        }\r
        return count;\r
    }\r
\r
    //! Counts attributes of node. Time complexity is O(n).\r
    //! \\return Number of attributes of node\r
    template<class Ch>\r
    inline std::size_t count_attributes(xml_node<Ch> *node)\r
    {\r
        xml_attribute<Ch> *attr = node->first_attribute();\r
        std::size_t count = 0;\r
        while (attr)\r
        {\r
            ++count;\r
            attr = attr->next_attribute();\r
        }\r
        return count;\r
    }\r
\r
}\r
\r
#endif\r
''')

        ########################################
        ## END - generated method body

        return _dummyTrans and trans.response().getvalue() or ""

    ##################################################
    ## CHEETAH GENERATED ATTRIBUTES

    _CHEETAH__instanceInitialized = False

    _CHEETAH_version = __CHEETAH_version__

    _CHEETAH_versionTuple = __CHEETAH_versionTuple__

    _CHEETAH_genTime = __CHEETAH_genTime__

    _CHEETAH_genTimestamp = __CHEETAH_genTimestamp__

    _CHEETAH_src = __CHEETAH_src__

    _CHEETAH_srcLastModified = __CHEETAH_srcLastModified__

    _mainCheetahMethod_for_rapidxml_utils_hpp= 'respond'

## END CLASS DEFINITION

if not hasattr(rapidxml_utils_hpp, '_initCheetahAttributes'):
    templateAPIClass = getattr(rapidxml_utils_hpp, '_CHEETAH_templateClass', Template)
    templateAPIClass._addCheetahPlumbingCodeToClass(rapidxml_utils_hpp)

# CHEETAH was developed by Tavis Rudd and Mike Orr
# with code, advice and input from many other volunteers.
# For more information visit http://www.CheetahTemplate.org/

##################################################
## if run from command line:
if __name__ == '__main__':
    from Cheetah.TemplateCmdLineIface import CmdLineIface
    CmdLineIface(templateObj=rapidxml_utils_hpp()).run()


import asyncio
import requests
import time
import docker

status_api_url = 'http://status-state-api:8080/docker-ps'
r = requests.get(url = status_api_url)
status_state_list = r.json()

async def update_containers():
    client = docker.from_env()
    containers = client.containers.list(True)
    for list_item in containers:
        if list_item.attrs['Id'] in status_state_list:
            print("Container with Id " + list_item.attrs['Id'] + " is in status_state_list")
            if list_item.attrs['State']['Status'] == "exited":
                print("Restarting container with Id " + list_item.attrs['Id'])
                list_item.restart()
        else:
            print("Deleting container " + list_item.attrs['Id'])
            list_item.stop()
            list_item.remove()
            print("Container " + list_item.attrs['Id'] + " deleted")

async def do_stuff_periodically(interval, periodic_function):
    while True:
        await asyncio.gather(
            asyncio.sleep(interval),
            periodic_function(),
        )

asyncio.run(do_stuff_periodically(30, update_containers))


def LIS(arr):
    n = len(arr)
    i, j, max_len = 0, 0, 0

    lst = [1]*(n)

    for i in range(1, n):
        for j in range(i):
            if (arr[i] > arr[j] and lst[i] < lst[j] + 1):
                lst[i] = lst[j] + 1

    for i in range(n):
        if max_len < lst[i]:
            max_len = lst[i]

    return max_len

# DRIVER CODE
arr = [23, 12, 67, 22, 34, 54, 12, 57, 21, 47, 26, 28, 83]
print("Length is", LIS(arr))


from parser import ParserError

from tracardi.service.plugin.domain.register import Plugin, Spec, MetaData, Documentation, PortDoc, Form, FormGroup, \
    FormField, FormComponent
from tracardi.service.plugin.runner import ActionRunner
from tracardi.service.plugin.domain.result import Result
from .model.config import Config
from datetime import datetime
from dateutil import parser

def validate(config: dict):
    return Config(**config)

class TimeDiffCalculator(ActionRunner):

    config: Config

    async def set_up(self, init):
        self.config = validate(init)

    @staticmethod
    def parse_date(date):
        try:
            if isinstance(date, str):
                if date == 'now':
                    date = datetime.utcnow()
                else:
                    date = parser.parse(date)
            elif not isinstance(date, datetime):
                raise ValueError("Date can be either string or datetime object")
            return date
        except ParserError:
            raise ValueError("Could not parse data `{}`".format(date))

    async def run(self, payload: dict, in_edge=None) -> Result:

        dot = self._get_dot_accessor(payload)

        ref_date = self.parse_date(dot[self.config.reference_date])
        now_date = self.parse_date(dot[self.config.now])

        diff_secs = (now_date - ref_date).total_seconds()

        return Result(port="time_difference", value={
            "seconds": diff_secs,
            "minutes": diff_secs / 60,
            "hours": diff_secs / (60 * 60),
            "days": diff_secs / (60 * 60 * 24),
            "weeks": diff_secs / (60 * 60 * 24 * 7)
        })

def register() -> Plugin:
    return Plugin(
        start=False,
        spec=Spec(
            module='tracardi.process_engine.action.v1.time.time_difference.plugin',
            className='TimeDiffCalculator',
            inputs=["payload"],
            outputs=["time_difference"],
            version='0.6.0.1',
            license="MIT",
            author="Dawid Kruk",
            init={
                "reference_date": None,
                "now": "now"
            },
            form=Form(
                groups=[
                    FormGroup(
                        name="Time delta",
                        description="Calculates the time difference between two dates.",
                        fields=[
                            FormField(
                                id="reference_date",
                                name="Reference date",
                                description="Please type path to the start date.",
                                component=FormComponent(type="dotPath", props={
                                    "label": "Source"
                                }),
                                required=True
                            ),
                            FormField(
                                id="now",
                                name="Second date",
                                description="Please type path, date or 'now'. This is the end date.",
                                component=FormComponent(type="dotPath", props={"label": "Source"}),
                                required=True
                            )
                        ]
                    )
                ]
            )
        ),
        metadata=MetaData(
            name='Time difference',
            desc='Returns time difference between two dates.',
            type='flowNode',
            icon='time',
            group=["Time"],
            purpose=['collection', 'segmentation'],
            documentation=Documentation(
                inputs={
                    "payload": PortDoc(desc="This port payload object.")
                },
                outputs={
                    "time_difference": PortDoc(desc="This port returns time difference in several time "
                                                    "units.")
                }
            )
        )
    )


import json
import pandas as pd
import numpy as np

if __name__ == "__main__":
    f = open("data/AllSongs.json", "r")
    rows = []
    for row in f:
        r = json.loads(row)
        rows.append(r)
    f.close()

    rows.reverse()

    df = pd.DataFrame(rows)
    df = df.drop(columns=['ip_addr_decrypted'])
    df = df.rename(columns={'master_metadata_track_name':'track_name', 'master_metadata_album_artist_name':'artist_name', 'master_metadata_album_album_name':'album_name'})
    df['offline'] = df['offline'].fillna(False)
    df['shuffle'] = df['shuffle'].fillna(False)
    df['skipped'] = df['skipped'].fillna(False)
    df.to_csv('processed_data.csv')


#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import simplejson as json
import time
from gSheetUtil import GSheetUtil
from readPagesUtil import ReadPagesUtil

# get values for specific title from readPageUtil.py in mapper formatter
# 'key':'value'
def valuesToUpdate():
    rp = ReadPagesUtil();
    return rp.loadPageTableFII()

def getFundDetail(dfRow):
    #print(dfRow[1])
    dfFundPage = ReadPagesUtil().loadFundDetailByCod(dfRow[1])[0].fillna("")
    print(dfFundPage)
    # create class and initialize with this values
    fundDetail = {}
    fundDetail["cod"] = dfRow[1]
    fundDetail["name"] = dfRow[0]
    fundDetail["ticker"] = dfFundPage[1][1]
    fundDetail["cnpj"] = dfFundPage[1][2]
    #fundDetail["page"] = dfFundPage[1][4]
    ##############################
    return fundDetail

def insertFundDetailInGSheet(fundDetail, index):
    for ticker in fundDetail['ticker'].split():
        gsu.renewAccessToken()
        worksheet.update_acell(f'A{index}', fundDetail['name'])
        worksheet.update_acell(f'B{index}', fundDetail['cod'])
        worksheet.update_acell(f'C{index}', ticker)
        worksheet.update_acell(f'D{index}', fundDetail['cnpj'])
        index += 1
    time.sleep(10)

# update defined cells with actual values
def updateFunds(gsu, valuesFromPage, worksheet):
    #loop in dataToUpdate
    #if dataToUpdate key == valuesToUpdate key -> update valuesToUpdate.value on dataToUpdate.value
    index = 1
    dic = []
    for row in valuesFromPage.iterrows():
        fundDetail = getFundDetail(row[1])
        #insertFundDetailInGSheet(fundDetail)
        dic.append(fundDetail)
        print(dic)

if __name__ == '__main__':
    gsu = GSheetUtil()
    worksheet = gsu.getSheet().worksheet("FII")
    #print(tdJson)
    updateFunds(gsu, valuesToUpdate(), worksheet)


import json
import os
from typing import AnyStr
import warnings

def set_ignore_warnings():
    warnings.simplefilter("ignore")
    # set os environ variable for multiprocesses
    os.environ["PYTHONWARNINGS"] = "ignore"

def extract_inputs_from_title(fpath: AnyStr):
    """Get inputs from file with key field title and department

    Args:
        fpath (AnyStr): file path

    Returns:
        List[AnyStr]: inputs for model
    """
    inputs = []
    with open(fpath, 'r', encoding='utf8') as fobj:
        for line in fobj:
            jobj = json.loads(line)
            inputs.append(jobj['title'] + " ".join(jobj['department'].split()))
    return inputs


import random

def play():
    diceList = [-1]
    while True:
        diceList = diceList + [random.randint(1,6)]
        if (diceList[-1] == 6) and (diceList[-2] == diceList[-1]):
            for i in range(1, len(diceList)):
                print("{} ".format(diceList[i]), end="")
            return len(diceList) - 1

throwsDice = []
sum = 0
for i in range(0,20):
    sum = sum + play()
    print("")

print("The mean of 20 times games of throws is: {}".format(sum/24))


def printTable(table):
    longestStringInRow = []
    longestStringLen = 0
    for row in table:
        for item in row:
            if (len(item) > longestStringLen):
                longestStringLen = len(item)
        longestStringInRow.append(longestStringLen)
        longestStringLen = 0
    rowIndex = 0
    itemIndex = 0
    countedItems = 0
    totalItems = len(table) * len(table[0])
    while (countedItems < totalItems):
        justifyLen = longestStringInRow[rowIndex] - len(table[rowIndex][itemIndex])
        if (rowIndex < len(table) - 1):
            print((" " * justifyLen) + table[rowIndex][itemIndex].rjust(justifyLen) + " ", end="")
            rowIndex += 1
        else:
            print((" " * justifyLen) + table[rowIndex][itemIndex].rjust(justifyLen))
            rowIndex = 0
            itemIndex += 1
        countedItems += 1

def main():
    tableData = [['apples', 'oranges', 'cherries', 'banana'],
['Alice', 'Bob', 'Carol', 'David'],
['dogs', 'cats', 'moose', 'goose']]
    printTable(tableData)

main()


from itertools import combinations

def Check(data,S):
    count = 0
    for i in range(1,len(data)+1):
        result = list(combinations(data,i))
        for j in range(len(result)):
            sum1 = sum(result[j])
            if sum1 == S:
                count += 1
    return count

def Input():
    N, S = map(int,input().split())
    data = list(map(int,input().split()))
    return N,S,data

N,S,data = Input()
print(Check(data,S))


'''
cache_mode:
0:使用cache缓存必要参数
1:使用cache缓存必要参数，对cache进行8bit量化节省显存，带来小许延时增长
2:不使用cache，耗时约为mode0的2倍，但是显存不受输入图像分辨率限制，tile_mode填得够大，1.5G显存可超任意比例
'''
import os
import sys

import numpy as np
import torch
from torch import nn as nn
from torch.nn import functional as F

root_path = os.path.abspath('.')
sys.path.append(root_path)

def q(inp, cache_mode):
    maxx = inp.max()
    minn = inp.min()
    delta = maxx - minn
    if (cache_mode == 2):
        return ((inp - minn) / delta * 255).round().byte().cpu(), delta, minn, inp.device  # 大概3倍延时#太慢了，屏蔽该模式
    elif (cache_mode == 1):
        return ((inp - minn) / delta * 255).round().byte(), delta, minn, inp.device  # 不用CPU转移

def dq(inp, if_half, cache_mode, delta, minn, device):
    if (cache_mode == 2):
        if (if_half == True):
            return inp.to(device).half() / 255 * delta + minn
        else:
            return inp.to(device).float() / 255 * delta + minn
    elif (cache_mode == 1):
        if (if_half == True):
            return inp.half() / 255 * delta + minn  # 不用CPU转移
        else:
            return inp.float() / 255 * delta + minn

class SEBlock(nn.Module):
    def __init__(self, in_channels, reduction=8, bias=False):
        super(SEBlock, self).__init__()
        print(in_channels)
        print(in_channels // reduction)
        self.conv1 = nn.Conv2d(in_channels, in_channels // reduction, 1, 1, 0, bias=bias)
        self.conv2 = nn.Conv2d(in_channels // reduction, in_channels, 1, 1, 0, bias=bias)

    def forward(self, x):
        if ("Half" in x.type()):  # torch.HalfTensor/torch.cuda.HalfTensor
            x0 = torch.mean(x.float(), dim=(2, 3), keepdim=True).half()
        else:
            x0 = torch.mean(x, dim=(2, 3), keepdim=True)
        x0 = self.conv1(x0)
        x0 = F.relu(x0, inplace=True)
        x0 = self.conv2(x0)
        x0 = torch.sigmoid(x0)
        x = torch.mul(x, x0)
        return x

    def forward_mean(self, x, x0):
        x0 = self.conv1(x0)
        x0 = F.relu(x0, inplace=True)
        x0 = self.conv2(x0)
        x0 = torch.sigmoid(x0)
        x = torch.mul(x, x0)
        return x

class UNetConv(nn.Module):
    def __init__(self, in_channels, mid_channels, out_channels, se):
        super(UNetConv, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_channels, mid_channels, 3, 1, 0),
            nn.LeakyReLU(0.1, inplace=True),
            nn.Conv2d(mid_channels, out_channels, 3, 1, 0),
            nn.LeakyReLU(0.1, inplace=True),
        )
        if se:
            self.seblock = SEBlock(out_channels, reduction=8, bias=True)
        else:
            self.seblock = None

    def forward(self, x):
        z = self.conv(x)
        if self.seblock is not None:
            z = self.seblock(z)
        return z

class UNet1(nn.Module):
    def __init__(self, in_channels, out_channels, deconv):
        super(UNet1, self).__init__()
        self.conv1 = UNetConv(in_channels, 32, 64, se=False)
        self.conv1_down = nn.Conv2d(64, 64, 2, 2, 0)
        self.conv2 = UNetConv(64, 128, 64, se=True)
        self.conv2_up = nn.ConvTranspose2d(64, 64, 2, 2, 0)
        self.conv3 = nn.Conv2d(64, 64, 3, 1, 0)

        if deconv:
            #self.conv_bottom = nn.ConvTranspose2d(64, out_channels, 4, 2, 3)
            self.conv_bottom = nn.ConvTranspose2d(64, out_channels, 4, 2, 3)
        else:
            self.conv_bottom = nn.Conv2d(64, out_channels, 3, 1, 0)

        for m in self.modules():
            if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d)):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, 0, 0.01)
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)

    def forward(self, x):
        x1 = self.conv1(x)
        x2 = self.conv1_down(x1)
        x1 = F.pad(x1, (-4, -4, -4, -4))
        x2 = F.leaky_relu(x2, 0.1, inplace=True)
        x2 = self.conv2(x2)
        x2 = self.conv2_up(x2)
        x2 = F.leaky_relu(x2, 0.1, inplace=True)
        x3 = self.conv3(x1 + x2)
        x3 = F.leaky_relu(x3, 0.1, inplace=True)
        z = self.conv_bottom(x3)
        return z

    def forward_a(self, x):
        x1 = self.conv1(x)
        x2 = self.conv1_down(x1)
        x1 = F.pad(x1, (-4, -4, -4, -4))
        x2 = F.leaky_relu(x2, 0.1, inplace=True)
        x2 = self.conv2.conv(x2)
        return x1, x2

    def forward_b(self, x1, x2):
        x2 = self.conv2_up(x2)
        x2 = F.leaky_relu(x2, 0.1, inplace=True)
        x3 = self.conv3(x1 + x2)
        x3 = F.leaky_relu(x3, 0.1, inplace=True)
        z = self.conv_bottom(x3)
        return z

class UNet2(nn.Module):
    def __init__(self, in_channels, out_channels, deconv):
        super(UNet2, self).__init__()

        self.conv1 = UNetConv(in_channels, 32, 64, se=False)
        self.conv1_down = nn.Conv2d(64, 64, 2, 2, 0)
        self.conv2 = UNetConv(64, 64, 128, se=True)
        self.conv2_down = nn.Conv2d(128, 128, 2, 2, 0)
        self.conv3 = UNetConv(128, 256, 128, se=True)
        self.conv3_up = nn.ConvTranspose2d(128, 128, 2, 2, 0)
        self.conv4 = UNetConv(128, 64, 64, se=True)
        self.conv4_up = nn.ConvTranspose2d(64, 64, 2, 2, 0)
        self.conv5 = nn.Conv2d(64, 64, 3, 1, 0)

        if deconv:
            self.conv_bottom = nn.ConvTranspose2d(64, out_channels, 4, 2, 3)
        else:
            self.conv_bottom = nn.Conv2d(64, out_channels, 3, 1, 0)

        for m in self.modules():
            if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d)):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, nn.Linear):
                nn.init.normal_(m.weight, 0, 0.01)
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)

    def forward(self, x, alpha=1):
        x1 = self.conv1(x)
        x2 = self.conv1_down(x1)
        x1 = F.pad(x1, (-16, -16, -16, -16))
        x2 = F.leaky_relu(x2, 0.1, inplace=True)
        x2 = self.conv2(x2)
        x3 = self.conv2_down(x2)
        x2 = F.pad(x2, (-4, -4, -4, -4))
        x3 = F.leaky_relu(x3, 0.1, inplace=True)
        x3 = self.conv3(x3)
        x3 = self.conv3_up(x3)
        x3 = F.leaky_relu(x3, 0.1, inplace=True)
        x4 = self.conv4(x2 + x3)
        x4 *= alpha
        x4 = self.conv4_up(x4)
        x4 = F.leaky_relu(x4, 0.1, inplace=True)
        x5 = self.conv5(x1 + x4)
        x5 = F.leaky_relu(x5, 0.1, inplace=True)
        z = self.conv_bottom(x5)
        return z

    def forward_a(self, x):  # conv234结尾有se
        x1 = self.conv1(x)
        x2 = self.conv1_down(x1)
        x1 = F.pad(x1, (-16, -16, -16, -16))
        x2 = F.leaky_relu(x2, 0.1, inplace=True)
        x2 = self.conv2.conv(x2)
        return x1, x2

    def forward_b(self, x2):  # conv234结尾有se
        x3 = self.conv2_down(x2)
        x2 = F.pad(x2, (-4, -4, -4, -4))
        x3 = F.leaky_relu(x3, 0.1, inplace=True)
        x3 = self.conv3.conv(x3)
        return x2, x3

    def forward_c(self, x2, x3):  # conv234结尾有se
        x3 = self.conv3_up(x3)
        x3 = F.leaky_relu(x3, 0.1, inplace=True)
        x4 = self.conv4.conv(x2 + x3)
        return x4

    def forward_d(self, x1, x4):  # conv234结尾有se
        x4 = self.conv4_up(x4)
        x4 = F.leaky_relu(x4, 0.1, inplace=True)
        x5 = self.conv5(x1 + x4)
        x5 = F.leaky_relu(x5, 0.1, inplace=True)

        z = self.conv_bottom(x5)
        return z

class UpCunet2x(nn.Module):
    def __init__(self, in_channels=3, out_channels=3):
        super(UpCunet2x, self).__init__()
        self.unet1 = UNet1(in_channels, out_channels, deconv=True)
        self.unet2 = UNet2(in_channels, out_channels, deconv=False)

    def forward(self, x, tile_mode, cache_mode, alpha, pro):
        n, c, h0, w0 = x.shape
        if ("Half" in x.type()):
            if_half = True
        else:
            if_half = False
        if (tile_mode == 0):  # 不tile
            #将奇数变为下一个最近的偶数
            ph = ((h0 - 1) // 2 + 1) * 2
            pw = ((w0 - 1) // 2 + 1) * 2
            #填充h w 维度 （h前填充，h后填充，w前填充，w后填充）
            x = F.pad(x, (18, 18 + pw - w0, 18, 18 + ph - h0), 'reflect')  # 需要保证被2整除
            x = self.unet1.forward(x)
            x0 = self.unet2.forward(x, alpha)
            x = F.pad(x, (-20, -20, -20, -20))
            x = torch.add(x0, x)
            if (w0 != pw or h0 != ph): x = x[:, :, :h0 * 2, :w0 * 2]
            if (pro):
                return ((x - 0.15) * (255 / 0.7)).round().clamp_(0, 255).byte()
            else:
                return (x * 255).round().clamp_(0, 255).byte()
        elif (tile_mode == 1):  # 对长边减半
            if (w0 >= h0):
                crop_size_w = ((w0 - 1) // 4 * 4 + 4) // 2  # 减半后能被2整除，所以要先被4整除
                crop_size_h = (h0 - 1) // 2 * 2 + 2  # 能被2整除
            else:
                crop_size_h = ((h0 - 1) // 4 * 4 + 4) // 2  # 减半后能被2整除，所以要先被4整除
                crop_size_w = (w0 - 1) // 2 * 2 + 2  # 能被2整除
            crop_size = (crop_size_h, crop_size_w)
        elif (tile_mode >= 2):
            tile_mode=min(h0, w0) // 128
            #tile_mode = min(min(h0, w0) // 128, int(tile_mode))  # 最小短边为128*128
            t2 = tile_mode * 2
            crop_size = (((h0 - 1) // t2 * t2 + t2) // tile_mode, ((w0 - 1) // t2 * t2 + t2) // tile_mode)
        else:
            print("tile_mode config error")
            os._exit(233)

        ph = ((h0 - 1) // crop_size[0] + 1) * crop_size[0]
        pw = ((w0 - 1) // crop_size[1] + 1) * crop_size[1]
        x = F.pad(x, (18, 18 + pw - w0, 18, 18 + ph - h0), 'reflect')
        n, c, h, w = x.shape
        if (if_half):
            se_mean0 = torch.zeros((n, 64, 1, 1), device=x.device, dtype=torch.float16)
        else:
            se_mean0 = torch.zeros((n, 64, 1, 1), device=x.device, dtype=torch.float32)
        n_patch = 0
        tmp_list = []
        i_length=(h - 36)//crop_size[0]
        j_length=(w - 36) //crop_size[1]
        for i in range(i_length):
            tmp_list.append([])
            for j in range(j_length):
                print(f"i:{i},j:{j}")
                x_crop = x[:, :, i*crop_size[0]:(i +1)* crop_size[0] + 36, j*(crop_size[1]):(j+1)* crop_size[1] + 36]
                n, c1, h1, w1 = x_crop.shape
                tmp0, x_crop = self.unet1.forward_a(x_crop)
                if (if_half):  # torch.HalfTensor/torch.cuda.HalfTensor
                    tmp_se_mean = torch.mean(x_crop.float(), dim=(2, 3), keepdim=True).half()
                else:
                    tmp_se_mean = torch.mean(x_crop, dim=(2, 3), keepdim=True)
                se_mean0 += tmp_se_mean
                n_patch += 1
                #tmp_dict[i][j] = (tmp0, x_crop)
                tmp_list[i].append([])
                # tmp_list[i][j].append(tmp0)
                # tmp_list[i][j].append(x_crop)
                tmp_list[i][j] = [tmp0, x_crop]

        se_mean0 /= n_patch
        if (if_half):
            se_mean1 = torch.zeros((n, 128, 1, 1), device=x.device, dtype=torch.float16)
        else:
            se_mean1 = torch.zeros((n, 128, 1, 1), device=x.device, dtype=torch.float32)

        print(f"{'-'*10}")

        for i in range(i_length):
            for j in range(j_length):
                print(f"i:{i},j:{j}")
                tmp0, x_crop =  tmp_list[i][j][0],tmp_list[i][j][1]
                x_crop = self.unet1.conv2.seblock.forward_mean(x_crop, se_mean0)
                opt_unet1 = self.unet1.forward_b(tmp0, x_crop)
                tmp_x1, tmp_x2 = self.unet2.forward_a(opt_unet1)
                opt_unet1 = F.pad(opt_unet1, (-20, -20, -20, -20))
                if (cache_mode): opt_unet1, tmp_x1 = q(opt_unet1, cache_mode), q(tmp_x1, cache_mode)
                if (if_half):  # torch.HalfTensor/torch.cuda.HalfTensor
                    tmp_se_mean = torch.mean(tmp_x2.float(), dim=(2, 3), keepdim=True).half()
                else:
                    tmp_se_mean = torch.mean(tmp_x2, dim=(2, 3), keepdim=True)
                if (cache_mode): tmp_x2 = q(tmp_x2, cache_mode)
                se_mean1 += tmp_se_mean
                tmp_list[i][j] = [opt_unet1, tmp_x1, tmp_x2]

        se_mean1 /= n_patch
        if (if_half):
            se_mean0 = torch.zeros((n, 128, 1, 1), device=x.device, dtype=torch.float16)
        else:
            se_mean0 = torch.zeros((n, 128, 1, 1), device=x.device, dtype=torch.float32)

        print(f"{'-' * 10}")
        for i in range(i_length):
            for j in range(j_length):
                print(f"i:{i},j:{j}")
                opt_unet1, tmp_x1, tmp_x2 = tmp_list[i][j][0],tmp_list[i][j][1],tmp_list[i][j][2]
                if (cache_mode): tmp_x2 = dq(tmp_x2[0], if_half, cache_mode, tmp_x2[1], tmp_x2[2], tmp_x2[3])
                tmp_x2 = self.unet2.conv2.seblock.forward_mean(tmp_x2, se_mean1)
                tmp_x2, tmp_x3 = self.unet2.forward_b(tmp_x2)
                if (cache_mode): tmp_x2 = q(tmp_x2, cache_mode)
                if (if_half):  # torch.HalfTensor/torch.cuda.HalfTensor
                    tmp_se_mean = torch.mean(tmp_x3.float(), dim=(2, 3), keepdim=True).half()
                else:
                    tmp_se_mean = torch.mean(tmp_x3, dim=(2, 3), keepdim=True)
                if (cache_mode): tmp_x3 = q(tmp_x3, cache_mode)
                se_mean0 += tmp_se_mean
                tmp_list[i][j] = [opt_unet1, tmp_x1, tmp_x2, tmp_x3]
        se_mean0 /= n_patch
        if (if_half):
            se_mean1 = torch.zeros((n, 64, 1, 1), device=x.device, dtype=torch.float16)
        else:
            se_mean1 = torch.zeros((n, 64, 1, 1), device=x.device, dtype=torch.float32)
        print(f"{'-' * 10}")
        for i in range(i_length):
            for j in range(j_length):
                print(f"i:{i},j:{j}")
                opt_unet1, tmp_x1, tmp_x2, tmp_x3 = tmp_list[i][j][0],tmp_list[i][j][1],tmp_list[i][j][2],tmp_list[i][j][3]
                if (cache_mode): tmp_x3 = dq(tmp_x3[0], if_half, cache_mode, tmp_x3[1], tmp_x3[2], tmp_x3[3])
                tmp_x3 = self.unet2.conv3.seblock.forward_mean(tmp_x3, se_mean0)
                if (cache_mode): tmp_x2 = dq(tmp_x2[0], if_half, cache_mode, tmp_x2[1], tmp_x2[2], tmp_x2[3])
                tmp_x4 = self.unet2.forward_c(tmp_x2, tmp_x3) * alpha
                if (if_half):  # torch.HalfTensor/torch.cuda.HalfTensor
                    tmp_se_mean = torch.mean(tmp_x4.float(), dim=(2, 3), keepdim=True).half()
                else:
                    tmp_se_mean = torch.mean(tmp_x4, dim=(2, 3), keepdim=True)
                if (cache_mode): tmp_x4 = q(tmp_x4, cache_mode)
                se_mean1 += tmp_se_mean
                tmp_list[i][j] = [opt_unet1, tmp_x1, tmp_x4]
        se_mean1 /= n_patch
        res = torch.zeros((n, c, h * 2 - 72, w * 2 - 72), dtype=torch.uint8, device=x.device)
        print(f"{'-' * 10}")
        for i in range((h - 36) // crop_size[0]):
            for j in range((w - 36) // crop_size[1]):
                print(f"i:{i},j:{j}")
                x, tmp_x1, tmp_x4 = tmp_list[i][j][0],tmp_list[i][j][1],tmp_list[i][j][2]
                if (cache_mode): tmp_x4 = dq(tmp_x4[0], if_half, cache_mode, tmp_x4[1], tmp_x4[2], tmp_x4[3])
                tmp_x4 = self.unet2.conv4.seblock.forward_mean(tmp_x4, se_mean1)
                if (cache_mode): tmp_x1 = dq(tmp_x1[0], if_half, cache_mode, tmp_x1[1], tmp_x1[2], tmp_x1[3])
                x0 = self.unet2.forward_d(tmp_x1, tmp_x4)
                if (cache_mode): x = dq(x[0], if_half, cache_mode, x[1], x[2], x[3])
                #del tmp_list[i][j]
                x = torch.add(x0, x)  # x0是unet2的最终输出
                if (pro):
                    res[:, :, i*crop_size[0] * 2:i*crop_size[0] * 2 + h1 * 2 - 72, j*crop_size[1] * 2:j *crop_size[1]* 2 + w1 * 2 - 72] = (
                            (x - 0.15) * (255 / 0.7)).round().clamp_(0, 255).byte()
                else:
                    res[:, :, i*crop_size[0] * 2:i*crop_size[0] * 2 + h1 * 2 - 72, j*crop_size[1] * 2:j*crop_size[1] * 2 + w1 * 2 - 72] = (x * 255).round().clamp_(0,
                                                                                255).byte()
        del tmp_list
        # torch.cuda.empty_cache()
        if (w0 != pw or h0 != ph): res = res[:, :, :h0 * 2, :w0 * 2]
        return res

class RealWaifuUpScaler(object):
    def __init__(self, scale, weight_path, half, device):
        weight = torch.load(weight_path, map_location="cpu")
        self.pro = "pro" in weight
        if (self.pro): del weight["pro"]
        #
        self.model = eval("UpCunet%sx" % scale)()
        if (half == True):
            self.model = self.model.half().to(device)
        else:
            self.model = self.model.to(device)
        self.model.load_state_dict(weight, strict=True)
        self.model.eval()
        self.half = half
        self.device = device

    def np2tensor(self, np_frame):
        if (self.pro):
            # half半精度
            if (self.half == False):
                return torch.from_numpy(np.transpose(np_frame, (2, 0, 1))).unsqueeze(0).to(self.device).float() / (
                        255 / 0.7) + 0.15
            else:
                return torch.from_numpy(np.transpose(np_frame, (2, 0, 1))).unsqueeze(0).to(self.device).half() / (
                        255 / 0.7) + 0.15
        else:
            if (self.half == False):
                return torch.from_numpy(np.transpose(np_frame, (2, 0, 1))).unsqueeze(0).to(self.device).float() / 255
            else:
                return torch.from_numpy(np.transpose(np_frame, (2, 0, 1))).unsqueeze(0).to(self.device).half() / 255

    def tensor2np(self, tensor):
        return (np.transpose(tensor.squeeze().cpu().numpy(), (1, 2, 0)))

    def __call__(self, frame, tile_mode, cache_mode, alpha):
        with torch.no_grad():
            # numpy转为tensor 将HWC转为HCW
            tensor = self.np2tensor(frame)
            if (cache_mode == 3):
                result = self.tensor2np(self.model.forward_gap_sync(tensor, tile_mode, alpha, self.pro))
            elif (cache_mode == 2):
                result = self.tensor2np(self.model.forward_fast_rough(tensor, tile_mode, alpha, self.pro))
            else:
                result = self.tensor2np(self.model(tensor, tile_mode, cache_mode, alpha, self.pro))
        return result

if __name__ == "__main__":
    ###########inference_img
    import time, cv2, sys
    from time import time as ttime
    """
    mode: 在其中填写video或者image决定超视频还是超图像；
scale: 超分倍率；
model_path: 填写模型参数路径(目前3倍4倍超分只有3个模型，2倍有4个不同降噪强度模型和1个保守模型)；
device: 显卡设备号。如果有多卡超图片，建议手工将输入任务平分到不同文件夹，填写不同的卡号；
超图像，需要填写输入输出文件夹；超视频，需要指定输入输出视频的路径。
cache_mode:根据个人N卡显存大小调节缓存模式.mode2/3可超任意大小分辨率（瓶颈不在显存）图像
0: 默认使用cache缓存必要参数
1: 使用cache缓存必要参数，对缓存进行8bit量化节省显存，带来15%延时增长，肉眼完全无法感知的有损模式
tile: 数字越大显存需求越低，相对地可能会小幅降低推理速度 {0, 1, x, auto}
0: 直接使用整张图像进行推理，大显存用户或者低分辨率需求可使用
1: 对长边平分切成两块推理
x: 宽高分别平分切成x块推理
auto: 当输入图片文件夹图片分辨率不同时，填写auto自动调节不同图片tile模式，未来将支持该模式。

alpha: 该值越大AI修复程度、痕迹越小，越模糊；alpha越小处理越烈，越锐化，色偏（对比度、饱和度增强）越大；默认为1不调整，推荐调整区间(0.7,1.3)；
half: 半精度推理，>=20系显卡直接写True开着就好

tile 0
cache_mode 1

    """
    tile_mode=3
    cache_mode=0
    alpha=1
    scale=2
    weight_name = "weights_pro/pro-no-denoise-up2x.pth".split("/")[-1].split(".")[0]
    # cpu下 half需要为False
    upscaler2x = RealWaifuUpScaler(scale, "weights_pro/pro-no-denoise-up2x.pth", half=False, device="cpu:0")
    frame = cv2.imread("inputs/test3.jpeg")[:, :, [2, 1, 0]]

    result = upscaler2x(frame, tile_mode=tile_mode, cache_mode=cache_mode, alpha=alpha)[:, :, ::-1]
    cv2.imwrite("output/pt_2x_3.png", result)

    # input_dir = "%s/inputs" % root_path
    # output_dir = "%s/output-dir-all-test" % root_path
    # os.makedirs(output_dir, exist_ok=True)
    # for name in os.listdir(input_dir):
    #     print(name)
    #     tmp = name.split(".")
    #     inp_path = os.path.join(input_dir, name)
    #     suffix = tmp[-1]
    #     prefix = ".".join(tmp[:-1])
    #     tmp_path = os.path.join(root_path, "tmp", "%s.%s" % (int(time.time() * 1000000), suffix))
    #     print(inp_path, tmp_path)
    #     # 支持中文路径
    #     # os.link(inp_path, tmp_path)#win用硬链接
    #     os.symlink(inp_path, tmp_path)  # linux用软链接
    #     # 加载图片为矩阵 H W C（BGR） (2, 1, 0指的是指读取rgb)
    #     frame = cv2.imread(tmp_path)[:, :, [2, 1, 0]]
    #     t0 = ttime()
    #     # 调用upscaler2x __call__
    #     result = upscaler2x(frame, tile_mode=tile_mode, cache_mode=cache_mode, alpha=alpha)[:, :, ::-1]
    #     t1 = ttime()
    #     print(prefix, "done", t1 - t0, "tile_mode=%s" % tile_mode, cache_mode)
    #     tmp_opt_path = os.path.join(root_path, "tmp", "%s.%s" % (int(time.time() * 1000000), suffix))
    #     cv2.imwrite(tmp_opt_path, result)
    #     n = 0
    #     while (1):
    #         if (n == 0):
    #             suffix = "_%sx_tile%s_cache%s_alpha%s_%s.png" % (
    #                 scale, tile_mode, cache_mode, alpha, weight_name)
    #         else:
    #             suffix = "_%sx_tile%s_cache%s_alpha%s_%s_%s.png" % (
    #                 scale, tile_mode, cache_mode, alpha, weight_name, n)
    #         if (os.path.exists(os.path.join(output_dir, prefix + suffix)) == False):
    #             break
    #         else:
    #             n += 1
    #     final_opt_path = os.path.join(output_dir, prefix + suffix)
    #     os.rename(tmp_opt_path, final_opt_path)
    #     os.remove(tmp_path)

    # for weight_path, scale in [("weights_v3/up2x-latest-denoise3x.pth", 2), ("weights_v3/up3x-latest-denoise3x.pth", 3),
    #                            ("weights_v3/up4x-latest-denoise3x.pth", 4), ("weights_pro/pro-denoise3x-up2x.pth", 2),
    #                            ("weights_pro/pro-denoise3x-up3x.pth", 3), ]:
    #
    #
    #     for tile_mode in [0, 5]:
    #         for cache_mode in [0, 1, 2, 3]:
    #             for alpha in [1]:
    #                 weight_name = weight_path.split("/")[-1].split(".")[0]
    #                 #cpu下 half需要为False
    #                 upscaler2x = RealWaifuUpScaler(scale, weight_path, half=False, device="cpu:0")
    #                 input_dir = "%s/inputs" % root_path
    #                 output_dir = "%s/output-dir-all-test" % root_path
    #                 os.makedirs(output_dir, exist_ok=True)
    #                 for name in os.listdir(input_dir):
    #                     print(name)
    #                     tmp = name.split(".")
    #                     inp_path = os.path.join(input_dir, name)
    #                     suffix = tmp[-1]
    #                     prefix = ".".join(tmp[:-1])
    #                     tmp_path = os.path.join(root_path, "tmp", "%s.%s" % (int(time.time() * 1000000), suffix))
    #                     print(inp_path, tmp_path)
    #                     # 支持中文路径
    #                     # os.link(inp_path, tmp_path)#win用硬链接
    #                     os.symlink(inp_path, tmp_path)  # linux用软链接
    #                     # 加载图片为矩阵 H W C（BGR） (2, 1, 0指的是指读取rgb)
    #                     frame = cv2.imread(tmp_path)[:, :, [2, 1, 0]]
    #                     t0 = ttime()
    #                     # 调用upscaler2x __call__
    #                     result = upscaler2x(frame, tile_mode=tile_mode, cache_mode=cache_mode, alpha=alpha)[:, :, ::-1]
    #                     t1 = ttime()
    #                     print(prefix, "done", t1 - t0, "tile_mode=%s" % tile_mode, cache_mode)
    #                     tmp_opt_path = os.path.join(root_path, "tmp", "%s.%s" % (int(time.time() * 1000000), suffix))
    #                     cv2.imwrite(tmp_opt_path, result)
    #                     n = 0
    #                     while (1):
    #                         if (n == 0):
    #                             suffix = "_%sx_tile%s_cache%s_alpha%s_%s.png" % (
    #                                 scale, tile_mode, cache_mode, alpha, weight_name)
    #                         else:
    #                             suffix = "_%sx_tile%s_cache%s_alpha%s_%s_%s.png" % (
    #                                 scale, tile_mode, cache_mode, alpha, weight_name, n)
    #                         if (os.path.exists(os.path.join(output_dir, prefix + suffix)) == False):
    #                             break
    #                         else:
    #                             n += 1
    #                     final_opt_path = os.path.join(output_dir, prefix + suffix)
    #                     os.rename(tmp_opt_path, final_opt_path)
    #                     os.remove(tmp_path)


import logging

import boto3
from sqlalchemy import func

from config import OLD_BUCKET, NEW_BUCKET, URL_ENDPOINT, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
from db import Images

class S3Utils:
    @staticmethod
    def get_s3_resource():
        #Here we could **kwargs
        return boto3.resource('s3', aws_access_key_id=AWS_ACCESS_KEY_ID,
                              aws_secret_access_key=AWS_SECRET_ACCESS_KEY, endpoint_url=URL_ENDPOINT)

    @staticmethod
    def transfer_s3_to_s3(s3session, old_key, new_key, new_bucket_name=NEW_BUCKET, bucket_to_copy=OLD_BUCKET):
        try:
            copy_source = {
                'Bucket': bucket_to_copy,
                'Key': old_key
            }
            s3session.meta.client.copy(copy_source, new_bucket_name, new_key)
            return True
        except Exception as e:
            logging.error(e)
            return False

class MariaUtils:
    @staticmethod
    def get_not_processed_key(session, limit=5):
        while session.query(Images).filter(Images.new_key == None).count() > 0:
            for i in session.query(Images).filter(Images.new_key == None).order_by(func.rand()).limit(limit).all():
                yield i

    @staticmethod
    def update_element(session, pic, new_key):
        try:
            pic.new_key = new_key
            session.add(pic)
            session.commit()
        except:
            session.rollback()


from collections import namedtuple
import functools
import cherrypy

Crumb = namedtuple("Crumb", ["url", "name"])

class Controller(object):

    def __init__(self, lookup):
        self._lookup = lookup

    def _set_data(self, entity, data):
        for k in data:
            setattr(entity, k, data[k])

    def _get_data(self, prefix, fields, post):
        data = dict((k.split(".", 1)[1], post[k]) for k in post if k.startswith('%s.' % prefix))
        return dict((k, data[k]) for k in data if k in fields)

    def render(self, template, crumbs=[], **variables):
        tmpl = self._lookup.get_template(template)
        variables['flash'] = cherrypy.session.pop('flash', None)
        variables['breadcrumbs'] = crumbs
        return tmpl.render(**variables)

def auth(groups=[]):
    # http://stackoverflow.com/questions/3302844/writing-a-cherrypy-decorator-for-authorization
    if not cherrypy.session.has_key('user.id'):
        raise cherrypy.HTTPRedirect('/login')

    if not groups:
        return

    if not cherrypy.session.get('user.group', None) in groups:
        cherrypy.session['flash'] = 'You are not authorized to access this section.'
        raise cherrypy.HTTPRedirect('/index')


"""
组合

1 2 3 4, k=3

123
124
134
234
"""

def combination(elements, k):
    if k < 0:
        raise ValueError(k)
    if k == 0:
        return []
    res = []
    k -= 1
    for i in range(len(elements)):
        if k == 0:
            res.append([elements[i]])
            continue
        tmp = combination(elements[i + 1:], k)
        for x in tmp:
            res.append([elements[i]] + x)
    return res

print(combination('1234', 2))


import unittest
from second_max_number.core.utils import *

class MyTestCase(unittest.TestCase):
    def test_something(self):
        actual_input=second_max([2,3,5,4])
        expected_output=4
        self.assertEqual(actual_input, expected_output)

if __name__ == '__main__':
    unittest.main()


# python=3.9.15, requests=2.28.1
# coding:utf-8
import os
import requests
import json
import time
import datetime
import logging
import urllib3
import random
from utils import SMSBot

urllib3.disable_warnings()
random.seed(1234)
logging.basicConfig(format='%(asctime)s  %(message)s', filename=os.path.join(__file__, '../log/book_court.log'),
                    level=logging.INFO)

class HuangLongCourtBooker:
    def __init__(self, venue, item, weekend_free_time='10:00', weekday_free_time='20:00'):
        self.base_url = "https://field.hulasports.com/api/orderlists/get/book"
        # self.base_url = "https://field.hulasports.com/api/venues/59cc96c142fa6b6703843bbf"
        self.headers = {
            'Host': 'field.hulasports.com',
            'Content-Type': 'application/json',
            'Content-Length': '208',
            'Accept': '*/*',
            'Accept-Language': 'en-ca',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, '
                          'like Gecko) Mobile/15E217 MicroMessenger/6.8.0(0x16080000) NetType/WIFI Language/en '
                          'Branch/Br_trunk MiniProgramEnv/Mac',
            'Referer': 'https://servicewechat.com/wx6ecc186775895db1/111/page-frame.html',
            'appId': 'wx6ecc186775895db1',  # small program id
            'memberId': '61ce7fe9b7ef552966c2b707',  # my personal account id
            'If-None-Match': 'W / "29c5-M36aWhykYp0pomdtDwAcjEf7xTY"',
        }
        self.data = {
            "orderDateNum": 1669392000000,
            "_venue": "59cc96c142fa6b6703843bbf",
            "_item": "5a393753d5fcfb9d3ec54265",
            "passBaseOn": "start",
            "showLine": "row",
            "showPassTime": False,
            "_org": "59cb5c718e1e92a702eca340",
            "delayMins": 0
        }
        self.offset = 10
        self.weekend_free_time = weekend_free_time
        self.weekday_free_time = weekday_free_time
        self.venue = venue
        self.item = item

    def validate_data(self):
        try:
            response = requests.post(self.base_url, headers=self.headers, data=json.dumps(self.data), verify=False)
            if response.status_code == 200:
                logging.info(response.text)
        except Exception as e:
            logging.error(e)

    def analyze_data(self):
        start_date = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        end_date = start_date + datetime.timedelta(days=7)
        rst = '有空闲场地啦! '
        while start_date <= end_date:
            try:
                cur_unix = int(time.mktime(start_date.timetuple()) * 1000)
                free_spot = self.weekend_free_time if start_date.weekday() in (
                    5, 6) else self.weekday_free_time  # Sat/Sun = 5/6
                self.data = {
                    "orderDateNum": cur_unix,
                    "_venue": self.venue,
                    "_item": self.item,
                    "passBaseOn": "start",
                    "showLine": "row",
                    "showPassTime": False,
                    "_org": "59cb5c718e1e92a702eca340",
                    "delayMins": 0
                }
                response = requests.post(self.base_url, headers=self.headers, data=json.dumps(self.data), verify=False)
                datas = json.loads(response.text)
                # print(datas['data']['booking_array'])
                row_num = len(datas['data']['booking_array'])
                col_num = len(datas['data']['booking_array'][0]['booking_infos'])

                for i in range(row_num):
                    for j in range(col_num):
                        content = datas['data']['booking_array'][i]['booking_infos'][j]
                        if content['state']['state'] == '可预订' and content['showStartTime'] >= free_spot:
                            rst += '{0}({1}) {2} {3} 如需预约请回复: {4}\n'.format(start_date.strftime('%Y-%m-%d'),
                                                                                start_date.strftime('%A')[:3],
                                                                                content['showTime'],
                                                                                content['fieldName'],
                                                                                random.randint(1111, 9999)
                                                                           )
            except Exception as e:
                logging.error(e)

            start_date = start_date + datetime.timedelta(days=1)

        logging.info(rst)
        return rst

if __name__ == '__main__':
    smsbot = SMSBot()
    receivers = '18560155097, 19121922357, 19357660781'
    logging.info('Start scrape court info')

    # squash booker
    s = HuangLongCourtBooker(venue='59cc96c142fa6b6703843bbf', item='5a393753d5fcfb9d3ec54265')
    rst = s.analyze_data()
    if len(rst) > 10:
        smsbot.send_sms(receiver=receivers, body='【Shakewin】' + rst)
    # tennis booker
    t = HuangLongCourtBooker(venue='59cdec566f1d65ba08316176', item='59cc95ca42fa6b6703843bba')
    rst = t.analyze_data()
    if len(rst) > 10:
        smsbot.send_sms(receiver=receivers, body='【Shakewin】' + rst)


from dataclasses import dataclass
from sqlalchemy import(
    Column,
    Integer,
    String
)

from  src.constants import Base

@dataclass
class HallOfFame(Base):
	__tablename__ = 'hall_of_fame'
	id = Column(Integer, primary_key = True)
	player_id = Column(String(50))


from __future__ import division
from jinja2.runtime import LoopContext, TemplateReference, Macro, Markup, TemplateRuntimeError, missing, concat, escape, markup_join, unicode_join, to_string, identity, TemplateNotFound
def run(environment):
    name = '/source\\core\\__south.html'

    def root(context, environment=environment):
        l_asset = context.resolve('asset')
        l_page = context.resolve('page')
        if 0: yield None
        yield u'<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>\n<script>window.jQuery || document.write(\'<script src="%s"><\\/script>\')</script>\n\n<!-- Core Scripts -->\n<script src="%s"></script>\n<script src="%s"></script>\n<script src="%s"></script>\n<script src="%s"></script>\n\n<!-- Base Scripts -->\n<script src="%s"></script>\n\n\n\n\n\n' % (
            context.call(environment.getattr(l_asset, 'script'), 'jquery', 'core'),
            context.call(environment.getattr(l_asset, 'script'), 'modernizr', 'core'),
            context.call(environment.getattr(l_asset, 'script'), 'underscore', 'core'),
            context.call(environment.getattr(l_asset, 'script'), 'backbone', 'core'),
            context.call(environment.getattr(l_asset, 'script'), 'lawnchair', 'core'),
            context.call(environment.getattr(l_asset, 'script'), 'base', 'apptools'),
        )
        if environment.getattr(l_page, 'analytics'):
            if 0: yield None
            yield u'\n<script>\n\t'
            template = environment.get_template('snippets/google_analytics.js', '/source\\core\\__south.html')
            for event in template.root_render_func(template.new_context(context.parent, True, locals())):
                yield event
            yield u'\n</script>\n'

    blocks = {}
    debug_info = '2=11&5=12&6=13&7=14&8=15&11=16&17=18&19=21'
    return locals()


from buildNetwork import buildNetwork
from getRefCiteSim import getRefs, getCites, getSimls
from drawGraph_v2 import drawGraph
import pickle

#arnumber = 260747
#print getRefs(arnumber)

### build reference network
MAX_ITERS = 20
MAX_NODES = 5
g_ref = buildNetwork(MAX_ITERS, MAX_NODES, 'refs')
#arnumber = 7120028
arnumber = 7037476

#g_ref.createRefGraph(arnumber)
outfile = "refs_{0}_{1}_{2}.p".format(arnumber, MAX_ITERS, MAX_NODES)
#g_ref.saveData(outfile)

infile = outfile
plt = drawGraph(infile, arnumber, [], 'refs')
plt.draw()

### build citation network
MAX_ITERS = 10
MAX_NODES = 10
g_ref = buildNetwork(MAX_ITERS, MAX_NODES, 'cites')
arnumber = 7037476
community_nodes = pickle.load(open('seed_community.p', 'rb'))
#g_ref.createCiteGraph(arnumber, community_nodes)
outfile = "cites_{0}_{1}_{2}.p".format(arnumber, MAX_ITERS, MAX_NODES)
#g_ref.saveData(outfile)

#infile = outfile
#plt = drawGraph(infile, arnumber, community_nodes, 'cites')
#plt.draw()


# Contest Code:COOK116B
# Problem Code:GIFTSRC

from sys import stdin, stdout
try:
    T = int(stdin.readline())
except:
    T = 0

for _ in range(T):
    n = int(stdin.readline())
    moves = list(map(str, stdin.readline().rstrip()))

    repeat = False
    x_axis = ['L', 'R']
    y_axis = ['U', 'D']
    prev_move = 0
    x = 0
    y = 0

    for i in range(n):
        repeat = False

        if(prev_move in x_axis and moves[i] in x_axis) or(prev_move in y_axis and moves[i] in y_axis):
            repeat = True

        if not repeat:
            if moves[i] == 'L':
                x -= 1
            elif moves[i] == 'R':
                x += 1
            elif moves[i] == 'U':
                y += 1
            elif moves[i] == 'D':
                y -= 1
        prev_move = moves[i]
    print(x, y)


#! /usr/bin/env python
from decimal import Decimal
import json
import sys
import re

# The sales tax charged when buying the wine at auction.
SALES_TAX_RATE = 0.09
# The commission charged when selling the wine after the auction.
SALE_COMMISSION = 0.15
# The target profit for any wine purchased at auction.
TARGET_PROFIT = 0.1

def format_cents(cents):
    return '$%.2f' % (float(cents) / 100)

if not len(sys.argv) == 3:
    raise Exception('Usage: python wine.py auctions.json sales.json')

auctions = json.load(open(sys.argv[1]))
sales = json.load(open(sys.argv[2]))

biddable_auctions = []
for auction in auctions:
    matched_sales = []
    # Get the list of matching sales.
    for sale in sales:
        if (auction.get('vintage') == int(sale['year']) and
                sale['winery'] in auction['title'] and
                sale['grape'] in auction['title'] and
                sale['name'] in auction['title'] and
                auction['size'] == 750):
            matched_sales.append(sale)
    # If there were matching sales, we can determine if bidding on the auction would be a good idea.
    if len(matched_sales) > 0:
        # Price per bottle at the current auction price.
        current_price_per_bottle = auction['current_bid'] / auction['quantity']
        auction['current_price_per_bottle'] = current_price_per_bottle

        # Market price per bottle for each sale.
        sale_prices = [int(Decimal(re.sub(r'[^\d.]', '', sale['sold'])) * 100) for sale in matched_sales]
        auction['sale_prices'] = sale_prices
        # print '\tSale prices: %s' % sale_prices
        max_sale_price_per_bottle = max(sale_prices)
        auction['max_sale_price_per_bottle'] = max_sale_price_per_bottle

        # Break even bid is based on the maximum sale price.
        revenue_per_bottle = max_sale_price_per_bottle * (1 - SALE_COMMISSION)
        auction['revenue_per_bottle'] = revenue_per_bottle
        profitable_price_per_bottle = revenue_per_bottle / (1 + TARGET_PROFIT)
        auction['profitable_price_per_bottle'] = profitable_price_per_bottle
        max_bid_per_bottle = profitable_price_per_bottle / (1 + SALES_TAX_RATE)
        auction['max_bid_per_bottle'] = max_bid_per_bottle
        auction['max_bid'] = max_bid_per_bottle * auction['quantity']

        if max_bid_per_bottle > current_price_per_bottle:
            min_profit = (revenue_per_bottle - profitable_price_per_bottle) * auction['quantity']
            auction['min_profit'] = min_profit
            max_profit = (revenue_per_bottle - current_price_per_bottle * (1 + SALES_TAX_RATE)) * auction['quantity']
            auction['max_profit'] = max_profit
            # If there's a potential for sufficient profit, add this to the list of biddable auctions.
            biddable_auctions.append(auction)

print(json.dumps(biddable_auctions, indent=4, sort_keys=True))


from keras.layers import Input
import sys
import os

_root_dir = os.path.dirname(
    os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
_deepxplore_dir = os.path.join(_root_dir, 'deep_xplore')
_deepxplore_mnist_dir = os.path.join(_deepxplore_dir, 'MNIST')

sys.path.append(_deepxplore_dir)
sys.path.append(_deepxplore_mnist_dir)

from Model1 import Model1
from Model2 import Model2
from Model3 import Model3

def model_load(downloaded_path):
    """
    Load list of three models and keras.layers.Input()
    :param downloaded_path:
    :return: List containing three models and keras.layers.Input()
    """
    input_shape = (28, 28, 1)

    # define input tensor as a placeholder
    input_tensor = Input(shape=input_shape)

    # load multiple models sharing same input tensor
    train = not os.path.isfile(os.path.join(_deepxplore_mnist_dir, 'Model1.h5'))
    model1 = Model1(input_tensor=input_tensor, train=train)

    train = not os.path.isfile(os.path.join(_deepxplore_mnist_dir, 'Model2.h5'))
    model2 = Model2(input_tensor=input_tensor, train=train)

    train = not os.path.isfile(os.path.join(_deepxplore_mnist_dir, 'Model3.h5'))
    model3 = Model3(input_tensor=input_tensor, train=train)

    return model1, model2, model3, input_tensor


import telebot
from telebot import types
import random
import matplotlib.pyplot as plt
from io import BytesIO

name_event = None
participant_numbers = 1
Max_participants = 10
name_game = None
Max_points = 1
player_name = None
points = 1
chat_id = None
gstatus = None
ev_status = None

messages = [
    "Je n'ai pas compris ce que vous voulez dire.",
    "Pouvez-vous reformuler votre demande ?",
    "Je suis dÃ©solÃ©, je ne comprends pas.",
    "Je ne sais pas comment vous aider.",
    "Je n'arrive pas Ã  comprendre ce que vous voulez dire.",
]

bot = telebot.TeleBot("AAFAPmWaytjJjPM-LTjuHDtxF8k0ND9NRYQ")
counter = {}

users = {"player_name": player_name, "scores": points}
game = {
    "game_name": name_game,
    "participant_numbers": participant_numbers,
    "Max_participants": Max_participants,
    "points_max": Max_points,
}
games = [game]
events = {
    "name_event": name_event,
    "participant_numbers": participant_numbers,
    "Max_participants": Max_participants,
    "games": games,
    "IDDECHAT": chat_id,
    "players": users,
}

# Here you can define your command handlers and message handlers
# For example:

@bot.message_handler(commands=["start"])
def start(message):
    bot.send_message(
        message.chat.id,
        "Bonjour, je suis votre bot Organisateur. \n Les Commandes disponibles sont: \n -/creer un Ã©vÃ¨nement et ses participants ( jeu inclus) \n -/ajouter une activitÃ© ou jeu secondaire \n -/inclure un participant \n -/arreter le jeu secondaire \n -/stopper l'activitÃ© principale \n /donner des points, \n /afficher le resultat du jeu \n /tutoriel ",
    )
    bot.send_message(message.chat.id, "Entrez le nom de votre activitÃ©:")

# -------------------------------------------------------- la c'est mon message acceuillant--------------------------------------------------------#

@bot.message_handler(commands=["creer"])
def create_event(message):
    chat_id = message.chat.id
    user_id = message.from_user.id

    # Check if user is an admin of the group
    chat_member = bot.get_chat_member(chat_id, user_id)
    if not chat_member.status == "administrator":
        bot.send_message(
            chat_id, "Vous n'avez pas les droits d'accÃ©der Ã  cette commande."
        )
        return

    # Get the event name from the command
    args = message.text.split()[1:]
    if len(args) < 1:
        bot.send_message(chat_id, "Usage: /creer <nom de l'Ã©vÃ©nement>")
        return
    name_event = args[0]

    # Check if the event already exists
    if not events.get(chat_id):
        events[chat_id] = {}
    if events[chat_id].get(name_event):
        bot.send_message(chat_id, f"L'Ã©vÃ©nement {name_event} existe dÃ©jÃ .")
        return

    # Ask for the maximum number of participants for the event
    msg = bot.send_message(
        chat_id, "Combien de participants maximum peut accueillir cet Ã©vÃ©nement ?"
    )
    bot.register_next_step_handler(msg, get_max_participants, name_event=name_event)

# -------------------------------------------------------- la commande creer evenement faite------------------------------------------------------------#
def get_max_participants(message, name_event):
    chat_id = message.chat.id
    user_id = message.from_user.id

    # Get the maximum number of participants from the user input
    try:
        Max_participants = int(message.text)
    except ValueError:
        bot.send_message(chat_id, "Veuillez entrer un nombre valide.")
        return

    # Check if the event already exists
    if not events.get(chat_id):
        events[chat_id] = {}
    if events[chat_id].get(name_event):
        bot.send_message(chat_id, f"L'Ã©vÃ©nement {name_event} existe dÃ©jÃ .")
        return

    # Create a new event dictionary
    event = {}
    event["name_event"] = name_event
    event["participant_numbers"] = 0
    event["Max_participants"] = Max_participants
    event["games"] = {}
    event["IDDECHAT"] = chat_id

    # Add the new event to the events dictionary for this group
    events[chat_id][name_event] = event

    # Confirm that the event was created successfully
    bot.send_message(chat_id, f"L'Ã©vÃ©nement {name_event} a Ã©tÃ© crÃ©Ã© avec succÃ¨s.")

# -------------------------------------------------------- la commande de limite maximale de joueur evenement faite------------------------------------------------------------#

@bot.message_handler(func=lambda message: True)
def pas_compris(message):
    if message.from_user.id not in counter:
        message_text = random.choice(messages)
        bot.send_message(message.chat.id, message_text)
        counter[message.from_user.id] = {"message": message_text, "count": 1}
    else:
        counter[message.from_user.id]["count"] += 1
    if counter[message.from_user.id]["count"] == 5:
        message_text = "en depit de votre manque de communication je ne puis vous aider plus que cela adieux, cretin"
        bot.send_message(message.chat.id, message_text)
    else:
        message_text = random.choice(
            [m for m in messages if m != counter[message.from_user.id]["message"]]
        )
        bot.send_message(message.chat.id, message_text)
        counter[message.from_user.id] = message_text

@bot.message_handler(commands=["ajouter"])
def add_game(message):
    chat_id = message.chat.id
    user_id = message.from_user.id

    # Check if user is an admin of the group
    chat_member = bot.get_chat_member(chat_id, user_id)
    if not chat_member.status == "administrator":
        bot.send_message(
            chat_id, "Vous n'avez pas les droits d'accÃ©der Ã  cette commande."
        )
        return

    # Get the event name and game name from the command
    args = message.text.split()[1:]
    if len(args) < 2:
        bot.send_message(chat_id, "Usage: /add_game <nom de l'Ã©vÃ©nement> <nom du jeu>")
        return
    name_event = args[0]
    name_game = args[1]

    # Check if the event exists
    if not events.get(chat_id) or not events[chat_id].get(name_event):
        bot.send_message(chat_id, f"L'Ã©vÃ©nement {name_game} n'existe pas.")
        return

    # Check if the game already exists
    if events[chat_id][name_event].get("games") and events[chat_id][name_event][
        "games"
    ].get(name_game):
        bot.send_message(
            chat_id, f"Le jeu {name_game} existe dÃ©jÃ  dans l'Ã©vÃ©nement {name_event}."
        )
        return

    # Get the max points for the game
    msg = bot.send_message(
        chat_id, f"Quel est le nombre maximum de points pour le jeu {name_game} ?"
    )
    bot.register_next_step_handler(
        msg, get_Max_points_add_game, name_event=name_event, name_game=name_game
    )

def get_Max_points_add_game(message, name_event, name_game):
    chat_id = message.chat.id
    user_id = message.from_user.id

    # Get the max points for the game from the user input
    try:
        Max_points = int(message.text)
    except ValueError:
        bot.send_message(chat_id, "Veuillez entrer un nombre valide.")
        return

    # Add the new game to the event dictionary
    if not events[chat_id][name_event].get("games"):
        events[chat_id][name_event]["games"] = {}
    events[chat_id][name_event]["games"][name_game] = {"points_max": Max_points}

    # Confirm that the game was added successfully
    bot.send_message(
        chat_id,
        f"Le jeu {name_game} a Ã©tÃ© ajoutÃ© Ã  l'Ã©vÃ©nement {name_event} avec succÃ¨s.",
    )

@bot.message_handler(commands=["inclure"])
def add_player(message):
    chat_id = message.chat.id
    user_id = message.from_user.id

    # Get the event name, game name, and player name from the command
    args = message.text.split()[1:]
    if len(args) < 3:
        bot.send_message(
            chat_id,
            "Usage: /add_player <nom de l'Ã©vÃ©nement> <nom du jeu> <nom du joueur>",
        )
        return
    name_event = args[0]
    name_game = args[1]
    player_name = args[2]

    # Check if the event exists
    if not events.get(chat_id) or not events[chat_id].get(name_event):
        bot.send_message(chat_id, f"L'Ã©vÃ©nement {name_event} n'existe pas.")
        return

    # Check if the game exists
    if not events[chat_id][name_event].get("games") or not events[chat_id][name_event][
        "games"
    ].get(name_game):
        bot.send_message(
            chat_id, f"Le jeu {name_game} n'existe pas dans l'Ã©vÃ©nement {name_event}."
        )
        return

    # Check if the player already exists in the game
    if (
        events[chat_id][name_event]["games"][name_game].get("players")
        and player_name in events[chat_id][name_event]["games"][name_game]["players"]
    ):
        bot.send_message(
            chat_id,
            f"Le joueur {player_name} est dÃ©jÃ  inscrit dans le jeu {name_game}.",
        )
        return

    # Add the player to the game
    if not events[chat_id][name_event]["games"][name_game].get("players"):
        events[chat_id][name_event]["games"][name_game]["players"] = []
    events[chat_id][name_event]["games"][name_game]["players"].append(player_name)

    # Reply with success message
    bot.send_message(
        chat_id,
        f"Le joueur {player_name} a Ã©tÃ© ajoutÃ© au jeu {name_game} de l'Ã©vÃ©nement {name_event}.",
    )

# -------------------------------------------------------- fonction pour ajouter un joueur -------------------------------------------------------#
@bot.message_handler(commands=["donner"])
def add_points(message):
    chat_id = message.chat.id
    user_id = message.from_user.id

    args = message.text.split()[1:]
    if len(args) < 4:
        bot.send_message(
            chat_id,
            "Usage: /add_points <nom de l'Ã©vÃ©nement> <nom du jeu> <nom du joueur> <nombre de points>",
        )
        return
    name_event = args[0]
    name_game = args[1]
    player_name = args[2]
    points = int(args[3])

    if not events.get(chat_id) or not events[chat_id].get(name_event):
        bot.send_message(chat_id, f"L'Ã©vÃ©nement {name_event} n'existe pas.")
        return

    if not events[chat_id][name_event].get("games") or not events[chat_id][name_event][
        "games"
    ].get(name_game):
        bot.send_message(
            chat_id, f"Le jeu {name_game} n'existe pas dans l'Ã©vÃ©nement {name_game}."
        )
        return

    if (
        not events[chat_id][name_event]["games"][name_game].get("players")
        or player_name not in events[chat_id][name_event]["games"][name_game]["players"]
    ):
        bot.send_message(
            chat_id,
            f"Le joueur {player_name} n'existe pas dans le jeu {name_game} de l'Ã©vÃ©nement {name_event}.",
        )
        return

    if not events[chat_id][name_event]["games"][name_game].get("scores"):
        events[chat_id][name_event]["games"][name_game]["scores"] = {}
    if not events[chat_id][name_event]["games"][name_game]["scores"].get(player_name):
        events[chat_id][name_event]["games"][name_game]["scores"][player_name] = 0
    events[chat_id][name_event]["games"][name_game]["scores"][player_name] += points

    bot.send_message(
        chat_id,
        f"{points} points ont Ã©tÃ© ajoutÃ©s au score de {player_name} dans le jeu {name_game} de l'Ã©vÃ©nement {name_event}.",
    )

@bot.message_handler(commands=["arreter"])
def stop_game(message):
    chat_id = message.chat.id
    user_id = message.from_user.id

    args = message.text.split()[1:]
    if len(args) < 2:
        bot.send_message(chat_id, "Usage: /stop_game <nom de l'Ã©vÃ©nement> <nom du jeu>")
        return
    name_event = args[0]
    name_game = args[1]

    if not events.get(chat_id) or not events[chat_id].get(name_event):
        bot.send_message(chat_id, f"L'Ã©vÃ©nement {name_event} n'existe pas.")
        return

    if not events[chat_id][name_event].get("games") or not events[chat_id][name_event][
        "games"
    ].get(name_game):
        bot.send_message(
            chat_id, f"Le jeu {name_game} n'existe pas dans l'Ã©vÃ©nement {name_event}."
        )
        return

    del events[chat_id][name_event]["games"][name_game]
    bot.send_message(
        chat_id, f"Le jeu {name_game} a Ã©tÃ© supprimÃ© de l'Ã©vÃ©nement {name_event}."
    )

@bot.message_handler(commands=["stopper"])
def stop_event(message):
    chat_id = message.chat.id
    user_id = message.from_user.id

    args = message.text.split()[1:]
    if len(args) < 1:
        bot.send_message(chat_id, "Usage: /stop_event <nom de l'Ã©vÃ©nement>")
        return
    name_event = args[0]

    if not events.get(chat_id) or not events[chat_id].get(name_event):
        bot.send_message(chat_id, f"L'Ã©vÃ©nement {name_event} n'existe pas.")
        return

    del events[chat_id][name_event]
    bot.send_message(chat_id, f"l'Ã©vÃ©nement {name_event} a Ã©tÃ© supprimÃ©.")

def get_name_event_from_message(message):
    # Extract the name of the event from the message text
    name_event = message.text.split()[1]
    return name_event

def get_name_game_from_message(message):
    # Extract the name of the event from the message text
    name_game = message.text.split()[1]
    return name_game

def get_player_name_from_message(message):
    # Extract the name of the event from the message text
    player_name = message.text.split()[1]
    return player_name

def auto_delete_game(message):
    chat_id = message.chat.id
    name_event = get_name_event_from_message(message)
    name_game = get_name_game_from_message(message)
    player_name = get_player_name_from_message(message)

    # Check if the player has reached the maximum number of points
    max_points = get_Max_points_add_game(chat_id, name_event, name_game)
    if (
        events[chat_id][name_event]["games"][name_game]["players"][name_game]
        >= max_points
    ):
        # Delete the game
        del events[chat_id][name_event]["games"][name_game]
        bot.reply_to(
            message,
            f"Le joueur {player_name} a atteint la limite de points et le jeu {name_game} a Ã©tÃ© supprimÃ©.",
        )
    else:
        bot.reply_to(
            message,
            f"Le joueur {player_name} a maintenant {events[chat_id][name_event]['games'][name_game]['players'][player_name]} points dans le jeu {name_event}.",
        )

def see_result(message):
    chat_id = message.chat.id
    name_event = get_name_event_from_message(message)
    name_game = get_name_game_from_message(message)

    # Check if the game exists
    if not events[chat_id][name_event]["games"].get(name_game):
        return []

    # Get the maximum number of points
    max_points = get_Max_points_add_game(chat_id, name_event, name_game)

    # Get the results for each player
    results = []
    for player in events[chat_id][name_event]["games"][name_game]["players"]:
        points = events[chat_id][name_event]["games"][name_game]["players"][player]
        result = (player, points)
        results.append(result)

    # Sort the results by score
    results.sort(key=lambda x: x[1], reverse=True)

    # Add a message for the winner
    if results and results[0][1] >= max_points:
        winner = results[0][0]
        results.insert(
            0,
            (
                f"ðŸ‘‘ {winner}",
                events[chat_id][name_event]["games"][name_game]["players"][winner],
            ),
        )

    # Create the bar chart
    fig, ax = plt.subplots()
    y_pos = range(len(results))
    scores = [result[1] for result in results]
    labels = [result[0] for result in results]
    ax.barh(y_pos, scores)
    ax.set_yticks(y_pos)
    ax.set_yticklabels(labels)
    ax.invert_yaxis()
    ax.set_xlabel("Score")
    ax.set_title(f"RÃ©sultats pour {name_game}")

    # Save the bar chart to a BytesIO object
    buffer = BytesIO()
    fig.savefig(buffer, format="png")
    buffer.seek(0)

    # Construct the message with the bar chart and the results
    message = f"RÃ©sultats pour {name_game} :\n"
    for i, result in enumerate(results):
        message += f"{i+1}. {result[0]} : {result[1]} points\n"
    message += "\n"

    bot.send_photo(chat_id, photo=buffer, caption=message)

bot.polling()


"""Interface to support the following user stories:

- What reagents and how many number of times does it take to gain one level with
    - One skill level
    - All recipes from level X to Y
- What is the price of:
    - One recipe
    - All recipes from level X to Y

as configuration it takes:
    path to profession.json (a list of recipes for this profession)
        +invalid recipe IDs
        +required array of (recipe IDs , skill level)
    an instance of Reagent costs

"""

from typing import Dict, List, Optional
from gold_amount import GoldAmount
from nexushub_api import NexusHubApi, Reagent
from recipes import Recipe
import json

class Profession:
    name: str
    recipes: List[Recipe]
    required_recipes: Dict[int,int] # skill_level: recipe.id
    recipe_path: List[Recipe]

    def __init__(self, name: str, nexus_hub_api: NexusHubApi, recipe_json_path: str, broken_recipes: List[int]=[], required_recipes: Dict[int, int]=[]) -> None:
        self.name = name
        self.nexus_hub_api = nexus_hub_api
        self.required_recipes = required_recipes
        self.broken_recipes = broken_recipes
        with open(recipe_json_path) as f:
            self.recipes = [recipe for recipe in (Recipe.from_json(recipe_data, nexus_hub_api) for recipe_data in json.load(f)) if recipe]
        self.recipe_path = []
        for i in range(1,450):
            result = self.cheapest_way_to_level_at(i)
            if result is None:
                print("Failed to find a suitable recipe for level " + str(i))
                continue
            self.recipe_path.append(result)

    def print_recipe_path(self, target: int):
        print_combined_recipe(self.recipe_path[:target])

    def cheapest_way_to_max(self) -> List[Recipe]:
        return self.cheapest_way_to(450)

    def cheapest_way_to(self, target: int) -> List[Recipe]:
        return self.recipe_path[:target]

    def cheapest_way_to_level_at(self, skill_level) -> Recipe:
        if skill_level in self.required_recipes:
            recipe_id = self.required_recipes[skill_level]
            return self.recipe_by_id(recipe_id)
        possible_recipes = self.possible_recipes(skill_level)
        if len(possible_recipes) == 0:
            return None
        return min(possible_recipes, key=lambda recipe: recipe.cost_for_skillup(skill_level))

    def recipe_by_id(self, recipe_id):
        for recipe in self.recipes:
            if recipe.id == recipe_id:
                return recipe
        return None

    def possible_recipes(self, skill_level) -> List[Recipe]:
        possible_recipes: List[Recipe] = []
        for recipe in self.recipes:
            if not recipe.can_use(skill_level):
                continue
            if not recipe.can_receive_skillup(skill_level):
                continue
            if recipe.id in self.broken_recipes:
                continue
            possible_recipes.append(recipe)
        return possible_recipes

    def reagents_for_level(self, skill_level: int, recipe: Recipe) -> List[int]:
        multiplier = recipe.expected_times_per_skillup(skill_level)
        return {reagent: recipe.quantity(reagent.id) * multiplier for reagent in recipe.reagents}

    def total_cost_to_max(self):
        return self.total_cost_to(450)

    def total_cost_to(self, target: int):
        total_cost = GoldAmount.from_copper(0)
        for skill_level, recipe in enumerate(self.recipe_path, 1):
            if skill_level == target:
                break
            skill_level = skill_level + 1
            total_cost += recipe.price * recipe.expected_times_per_skillup(skill_level)
        return total_cost

    def reagents_required_to_max(self):
        return self.reagents_required_to(450)

    def reagents_required_to(self, target: int) -> Dict[Reagent,int]:
        reagents: Dict[Reagent, int] = {}
        for skill_level, recipe in enumerate(self.recipe_path, 1):
            if skill_level == target:
                break
            reagents = merge_dict(reagents, recipe.reagents)
        return reagents

def merge_dict(dict1, dict2):
    return {k: dict1.get(k, 0) + dict2.get(k, 0) for k in set(dict1) | set(dict2)}

def print_combined_recipe(recipe_path):
    start = None
    prev = None
    result = []
    for i, x in enumerate(recipe_path, 1):
        if x != prev:
            if start is not None:
                result.append((start, i-1, prev, i-start))
            start = i
            prev = x
    if start is not None:
        result.append((start, len(recipe_path)-1, prev, len(recipe_path)-start-1))
    total = GoldAmount.from_copper(0)
    for arr in result:
        start = arr[0]
        end = arr[1]
        recipe = arr[2]
        quantity = arr[3]
        print(f"[{start:3}-{end+1:3}] {recipe.name[:35]:35} (x{quantity:2}). Cost = {recipe.price * quantity}")
        total  += recipe.price * quantity
    print("="*10)
    print(f"Total cost = {total}")

class Enchanting(Profession):
    def __init__(self, nexus_hub_api: NexusHubApi):
        broken_recipes = [
            42613,
            28022,
            45765,
            7421,
        ]

        required_recipes = {
            1: 7421, # Runed Copper Rod
            100: 7795, # Runed Silver Rod
            155: 13628, # Runed Golden Rod
            200: 13702, # Runed Truesilver Rod
            299: 20051, # Runed Arcanite Rod
            300: 32664, # Runed Fel Iron Rod
            350: 32665, # Runed Adamantite Rod
        }
        super().__init__(
            name="enchanting",
            nexus_hub_api=nexus_hub_api,
            recipe_json_path="data/enchanting.json",
            broken_recipes=broken_recipes,
            required_recipes=required_recipes,
        )

class Engineering(Profession):
    def __init__(self, nexus_hub_api: NexusHubApi):
        super().__init__(
            name="engineering",
            nexus_hub_api=nexus_hub_api,
            recipe_json_path="data/engineering.json",
        )

        print(self.recipes)


# This example assumes the following globals:
# data_manager (NimDotNet.DataManager)
# instrument (NimDotNet.NimControl)
# acquisition (NimDotNet.AcquisitionManager)
# profiles (NimDotNet.UserProfileManager)

global data_manager
global instrument
global acquisition
global profiles

# load all associated data from the specified file
file_to_load = 'C:/Data/DEFAULT_USER/NimPythonTraining/Example2/Example2_2017-04-25_19h33m36s614ms.tif'
data_manager.LoadData(file_to_load)

# lets see what we loaded
for f in data_manager.Files:
	print(f)


import pandas as pd
import numpy as np

from os import getcwd, chdir
#!/usr/bin/env python
chdir("C:\\Users\\Daniel\\Documents\\pandas")
getcwd()

pd.set_option('display.max_rows', 500)
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 100)

import os
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = 'C:/Anaconda3/Library/plugins/platforms'

movie = pd.read_csv("./data/movie.csv")
movie.head()

index = movie.index; index
columns = movie.columns; columns
data = movie.values; data
movie.info()
type(index)
type(columns)
type(data)

movie.dtypes
movie.get_dtype_counts()
movie['director_name']
movie.director_name

director = movie['director_name']
director.name
director.to_frame()

s_attr_methods = set(dir(pd.DataFrame))
len(s_attr_methods)

movie = pd.read_csv('./data/movie.csv')
director =movie['director_name']
actor_1_fb_likes = movie['actor_1_facebook_likes']

director.head()
actor_1_fb_likes.head()
actor_1_fb_likes.value_counts()

director.size
director.shape
len(director)

director.count()

actor_1_fb_likes.count()
actor_1_fb_likes.min(), actor_1_fb_likes.max(), actor_1_fb_likes.mean(), actor_1_fb_likes.median()

from sklearn import linear_model
reg = linear_model.LinearRegression()
reg.fit([[0,0], [1,1], [2,2]], [0, 1, 2])
reg.coef_