__author__ = 'Ryan'
from bs4 import *
import pandas as pd
import requests
import pickle
import datetime
import math
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import os
import time
import random
from urllib.request import urlretrieve
import sys
import shutil

class FG_Scrape:
    def __init__(self):
        self.addr = '/projections/'
        self.zips_ros_b = 'http://www.fangraphs.com/projections.aspx?pos=all&stats=bat&type=rzips&team=0&lg=all&players=0'
        self.zips_ros_p = 'http://www.fangraphs.com/projections.aspx?pos=all&stats=pit&type=rzips&team=0&lg=all&players=0'
        self.steamer_ros_b = 'http://www.fangraphs.com/projections.aspx?pos=all&stats=bat&type=steamerr&team=0&lg=all&players=0'
        self.steamer_ros_p = 'http://www.fangraphs.com/projections.aspx?pos=all&stats=pit&type=steamerr&team=0&lg=all&players=0'
        self.steamer_b = 'http://www.fangraphs.com/projections.aspx?pos=all&stats=bat&type=steamer&team=0&lg=all&players=0'
        self.steamer_p = 'http://www.fangraphs.com/projections.aspx?pos=all&stats=pit&type=steamer&team=0&lg=all&players=0'
        self.dc_ros_p = 'http://www.fangraphs.com/projections.aspx?pos=all&stats=bat&type=rfangraphsdc&team=0&lg=all&players=0'
        self.dc_ros_b = 'http://www.fangraphs.com/projections.aspx?pos=all&stats=pit&type=rfangraphsdc&team=0&lg=all&players=0'
        # self.link_list = [self.zips_ros_b, self.zips_ros_p, self.steamer_ros_b, self.steamer_ros_p]#, self.dc_ros_p, self.dc_ros_b]
        self.link_list = [self.steamer_b, self.steamer_p]
        self.name_list = ['zips_ros_b', 'zips_ros_p', 'steamer_ros_b', 'steamer_ros_p']  # , 'dc_ros_p', 'dc_ros_b']
        chromedriver = 'D:\downloads/chromedriver'
        os.environ['webdriver.chrome.driver'] = chromedriver
        self.driver = webdriver.Chrome(chromedriver)
        self.dl_path = 'C:\\Users\Ryan\Downloads'
        self.dest_path = 'C:\\Users\Ryan\PycharmProjects\\NCB_Stats\projections'

    def scrape(self):
        for l, n in zip(self.link_list, self.name_list):
            self.driver.get(url=l)
            time.sleep(5)
            print('link up')
            link = self.driver.find_element_by_id('ProjectionBoard1_cmdCSV').click()
            time.sleep(5)
            print('clicked')
            d = os.curdir
            for filename in os.listdir(self.dl_path):
                print(filename)
                if filename == 'FanGraphs Leaderboard.csv':
                    print('rename')
                    src_path = os.path.join(self.dl_path, filename)
                    dest_path = os.path.join(self.dest_path, n + '.csv')
                    os.rename(src_path, dest_path)
                    print('rename done')
                    # shutil.copy(filename, self.addr)

    def clear_old(self):
        for filename in os.listdir(self.dl_path):
            if 'FanGraphs Leaderboard' in filename:
                os.remove(filename)
        for filename in os.listdir(self.dest_path):
            os.remove(filename)

    def run_scrape(self):
        self.clear_old()
        self.scrape()

def main():
    scrape = FG_Scrape()
    scrape.run_scrape()

main()


#itertools-用于操作迭代对象的函数
import itertools

#无限迭代器
natuals = itertools.count(1)
for n in natuals:
	print(n)

#无限循环序列
cs = itertools.cycle('ABC')
for c in cs:
	print(c)

#循环元素，可限定次数
ns = itertools.repeat('A', 3)
for n in ns:
	print(n)

#截取有序序列
natuals = itertools.count(1)
ns = itertools.takewhile(lambda x:x<=10,natuals)
list(ns)

#串联迭代对象
for c in itertools.chain('ABC','XYZ'):
	print(c)

#把迭代器中相邻的重复元素挑出来放在一起
for key,group in itertools.groupby('AAABBCCAA',lambda c:c.upper()):
	print(key,list(group))

#计算圆周率
def pi(N):
	#setp 1:创建一个奇数数列
	natuals = itertools.count(1,2)
	#setp 2:取该序列的前N项
	ns = itertools.takewhile(lambda x:x<=(2*N-1),natuals)
	#setp 3:添加正负符号并用4除 4/1 -4/3 4/5
	#setp 4:求和
	res = 0
	for k,v in enumerate(list(ns)):
	    res += 4/v if k%2==0 else -4/v
	return res

print(pi(10))
print(pi(100))
print(pi(1000))
print(pi(10000))
assert 3.04 < pi(10) < 3.05
assert 3.13 < pi(100) < 3.14
assert 3.140 < pi(1000) < 3.141
assert 3.1414 < pi(10000) < 3.1415
print('ok')


import pytest

from unittest.mock import create_autospec

from django_swagger_utils.drf_server.exceptions import NotFound

from essentials_kit_management.interactors.presenters import \
    FormPresenterInterface
from essentials_kit_management.interactors.storages import \
    FormStorageInterface

from essentials_kit_management.interactors.get_user_ordered_details_interactor \
    import GetUserOrderedDetailsInteractor

from essentials_kit_management.interactors.storages.dtos import (
    GetUserOrderDto
)

def test_get_user_ordered_details_interactor_with_valid_details(
        get_user_brand_dtos,
        get_user_items_dtos,
        get_user_order_dtos,
        get_expected_get_user_order_dtos
    ):

    # Arrange
    user_id = 1
    form_id = 1
    expected_dict = {}
    form_presenter = create_autospec(FormPresenterInterface)
    form_storage = create_autospec(FormStorageInterface)
    interactor = GetUserOrderedDetailsInteractor(form_storage=form_storage,
                                                 form_presenter=form_presenter)

    form_storage.get_order_dtos.return_value = get_user_order_dtos
    form_storage.get_user_brand_dtos.return_value = get_user_brand_dtos
    form_storage.get_user_item_dtos.return_value = get_user_items_dtos

    # Act
    actual_dict = interactor.get_user_ordered_details(user_id=user_id,
                                                      form_id=form_id)

    # Assert
    form_storage.is_valid_form_id(form_id=form_id)
    form_storage.get_order_dtos.assert_called_once_with(user_id=user_id,
                                                        form_id=form_id)
    form_storage.get_user_brand_dtos.assert_called_once()
    form_storage.get_user_item_dtos.assert_called_once()
    form_presenter.get_user_ordered_details_response(
         order_detail_dtos=get_expected_get_user_order_dtos)


# -*- coding: utf-8 -*-
"""
This is a Landlab wrapper for A Wickert's gFlex flexure model (Wickert et al.,
submitted to Geoscientific Model Development). The most up-to-date version of
his code can be found at github.com/awickert/gFlex.

This Landlab wrapper will use a snapshot of that code, which YOU need to
install on your own machine.
A stable snapshot of gFlex is hosted on PyPI, which is the recommended version
to install.
If you have pip (the Python package install tool), simply run
'pip install gFlex' from a command prompt.
Alternatively, you can download and unpack the code (from github, or with PyPI,
pypi.python.org/pypi/gFlex/), then run 'python setup.py install'.

Created on Thu Feb 19 18:47:11 2015

@author: daniel.hobley (SiccarPoint @Github)

...following AW's run_in_script_2D.py.
"""
from __future__ import print_function

import numpy as np
import inspect
from landlab import RasterModelGrid, Component
from landlab import ModelParameterDictionary
from landlab import FieldError

try:
    import gflex
except ImportError:
    import warnings, sys

    warnings.warn("gFlex not installed.")
    print("""
To use the gFlex component you must have gFlex installed on your machine.
For installation instructions see gFlex on GitHub:

  https://github.com/awickert/gFlex
          """.strip(), file=sys.stderr)

class gFlex(Component):
    """
    This is the Landlab component controlling the gFlex code.

    Note that gFlex maintains its own internal version if the grid, but this
    should not affect performance.
    """
    _name = 'gFlex'

    _input_var_names = set(['surface_load__stress',
                        ])

    _output_var_names = set(['lithosphere__vertical_displacement',
                             'topographic__elevation',
                        ])

    _var_units = {'earth_material_load__magnitude_of_stress' : 'Pa',
                  'earth_material_load__x_positions' : 'm',
                  'earth_material_load__y_positions' : 'm',
                  'earth_material_load__force' : 'N',
                  'lithosphere__elastic_thickness' : 'm',
                  'lithosphere__vertical_displacement' : 'm',
                  }

    _var_mapping = {'earth_material_load__magnitude_of_stress' : 'node',
                  'earth_material_load__x_positions' : 'node',
                  'earth_material_load__y_positions' : 'node',
                  'earth_material_load__force' : 'node',
                  'lithosphere__elastic_thickness' : 'node',
                  'lithosphere__vertical_displacement' : 'node',
                  }

    _var_defs = {'earth_material_load__magnitude_of_stress' : 'Magnitude of stress exerted by surface load',
                  'earth_material_load__x_positions' : 'x position of any surface load',
                  'earth_material_load__y_positions' : 'y position of any surface load',
                  'earth_material_load__force' : 'Force exerted by surface load',
                  'lithosphere__elastic_thickness' : 'Elastic thickness of the lithosphere',
                  'lithosphere__vertical_displacement' : 'Vertical deflection of the surface and of the lithospheric plate',
                  }

    def __init__(self, grid, params):
        self.initialize(grid, params)

    def initialize(self, grid, params):
        """
        grid must be a landlab RasterModelGrid to use gFlex.

        params may be a dictionary of input parameters, or a standard Landlab
        input text file.

        gFlex requires:
        * E, Young's modulus
        * nu, Poisson's ratio
        * rho_m, the mantle density
        * rho_fill, the infill material density
        * Te, the elastic thickness. Can be scalar or an nnodes-long array.
            If you want an array, supply a grid field name where the data can
            be found.
        * BC_W, BC_E, BC_S, BC_N, strings describing the boundary conditions.
            Choose from ('Dirichlet0', '0Moment0Shear', 'Periodic').

        gFlex can take as options:
        * g, the gravitational acceleration (defaults to 9.81)

        gFlex takes as input fields:
        * surface_load__stress

        gFlex modifies/returns:
        * topographic__elevation (if it exists already)
        * lithosphere__vertical_displacement

        """
        assert RasterModelGrid in inspect.getmro(grid.__class__)
        BC_options = ('Dirichlet0', '0Moment0Shear', '0Slope0Shear', 'Periodic')

        if type(params) == str:
            input_dict = ModelParameterDictionary(params)
        else:
            assert type(params) == dict
            input_dict = params

        #instantiate the module:
        self.flex = gflex.F2D()
        flex = self.flex

        #set up the grid variables:
        self._grid = grid
        flex.dx = grid.dx
        flex.dy = grid.dy

        #we assume these properties are fixed in this relatively
        #straightforward implementation, but they can still be set if you want:
        try:
            flex.Method = input_dict['Method']
        except KeyError:
            flex.Method = 'FD'
        try:
            flex.PlateSolutionType = input_dict['PlateSolutionType']
        except KeyError:
            flex.PlateSolutionType = 'vWC1994'
        try:
            flex.Solver = input_dict['Solver']
        except KeyError:
            flex.Solver = 'direct'
        try:
            quiet = input_dict['Quiet']
        except KeyError:
            flex.Quiet = True
        else:
            flex.Quiet = bool(quiet)

        flex.E = float(input_dict['E'])
        flex.nu = float(input_dict['nu'])
        flex.rho_m = float(input_dict['rho_m'])
        flex.rho_fill = float(input_dict['rho_fill'])
        try:
            flex.g = input_dict['g']
        except KeyError:
            flex.g = 9.81
        flex.BC_W = input_dict['BC_W']
        flex.BC_E = input_dict['BC_E']
        flex.BC_S = input_dict['BC_S']
        flex.BC_N = input_dict['BC_N']
        for i in (flex.BC_E, flex.BC_W, flex.BC_N, flex.BC_S):
            assert i in BC_options

        Te_in = input_dict['Te']
        try:
            flex.Te = float(Te_in)
        except ValueError:
            flex.Te = grid.at_node[Te_in].view().reshape((grid.number_of_node_rows, grid.number_of_node_columns))
            self._input_var_names.add(Te_in)
            self._output_var_names.add(Te_in)

        #set up the link between surface load stresses in the gFlex component and the LL grid field:
        flex.qs = grid.at_node['surface_load__stress'].view().reshape((grid.number_of_node_rows, grid.number_of_node_columns))

        #create a holder for the "pre-flexure" state of the grid, to allow updating of elevs:
        self.pre_flex = np.zeros(grid.number_of_nodes, dtype=float)

    def flex_lithosphere(self, **kwds):
        """
        Executes (& finalizes, from the perspective of gFlex) the core method
        of gFlex. Note that flexure of the lithosphere proceeds to steady state
        in a single timestep.
        """
        #note kwds is redundant at the moment, but could be used subsequently for dynamic control over params
        self.flex.qs = self._grid.at_node['surface_load__stress'].view().reshape((self._grid.number_of_node_rows, self._grid.number_of_node_columns))
        self.flex.initialize()
        self.flex.run()
        self.flex.finalize()

        self._grid.at_node['lithosphere__vertical_displacement'] = self.flex.w.view().ravel()

        try:
            self._grid.at_node['topographic__elevation']
            #a topo exists...
        except FieldError:
            pass
        else:
            topo_diff = self._grid.at_node['lithosphere__vertical_displacement'] - self.pre_flex
            self._grid.at_node['topographic__elevation'] += topo_diff
            self.pre_flex += topo_diff


# Spiral is 1001 x 1001, so starts at 1001^2
# Start at top number then add n - (999 + 1) 4 times
# Then add n - (997 + 1) 4 times
# continue until - 1

def main():
    square_dim = 1001
    total = square_dim ** 2
    current_num = total
    i = square_dim - 2
    while i > 0:
        for j in range(4):
            current_num -= (i + 1)
            total += current_num
        i -= 2
    print(total)

if __name__ == '__main__':
    main()


import autodisc as ad

class LeniaClassifierStatisticsV2(ad.core.SystemStatistic):

    def __init__(self):

        super().__init__()

        self.data['classifier_animal'] = []
        self.data['classifier_diverging'] = []
        self.data['classifier_stable_fixpoint_solution'] = []
        self.data['classifier_moving'] = []

        self.is_lenia_animal_classifier = ad.systems.lenia.IsLeniaAnimalClassifierV2()
        self.is_diverging_classifier = ad.classifier.static.IsDivergingClassifier()
        self.stable_fix_point_solution_classifier = ad.classifier.static.StableFixPointSolutionClassifier()
        self.is_moving_classifier = ad.classifier.static.IsMovingClassifier()

    def reset(self):
        # set all statistics to zero
        for key in self.data.keys():
            self.data[key] = []

    def calc_after_run(self, system, all_obs):
        '''Calculates the final statistics for lenia observations after a run is completed'''

        # collect statistics from system which might be needed for the classifiers
        statistics_data = dict()
        for stat in system.statistics:
            statistics_data = {**stat.data, **statistics_data}

        self.is_lenia_animal_classifier.config.r = system.run_parameters['R']
        self.data['classifier_animal'] = self.is_lenia_animal_classifier.calc(all_obs, statistics_data)

        self.data['classifier_diverging'] = self.is_diverging_classifier.calc(all_obs, statistics_data)

        self.data['classifier_stable_fixpoint_solution'] = self.stable_fix_point_solution_classifier.calc(all_obs, statistics_data)

        self.data['classifier_moving'] = self.is_moving_classifier.calc(all_obs, statistics_data)


from django.test import TestCase
from productos.models import Product
from django.urls import reverse
from django.core.management import call_command

class VerProductosTestCase(TestCase):
    def setUp(self):
        Product.objects.create(original_code='qwerewetret', product_code='sahsakjhaksjh', name='capot',
                               description='blanco', car_brand='honda', car_model='civic',
                               car_year='2020', public_price='200', card_price='250', master_price='100',
                               wholesale_price='150', dozen_price='190')

    def test_url_correct(self):
        response = self.client.get(reverse('shop:ver_catalogo'))
        self.assertEqual(response.status_code, 200)

    def test_view(self):
        response = self.client.get(reverse('shop:ver_catalogo'))
        self.assertContains(response, 'capot')


from Lab_7.Task3.poly3d import *
from tkinter import *
from tkinter import ttk

class Gui:
    CANVAS_WIDTH = 500
    CANVAS_HEIGHT = 500

    def __init__(self):
        self.window = Tk()
        self.figure = None
        self.proection = None   # проецирование = 0 (ортографическое), 1 (изометрическое), 2 (перспективное)
        self.xyz = None         # проецирование = 0 (на yz), 1 (на xz), 2 (на xy) ДЛЯ ОРТОГРАФИЧЕСКИХ

        self.window.title("MECHMAT SILA")
        self.window.resizable(False, False)
        # canvas
        self.canvas = Canvas(self.window, width=self.CANVAS_WIDTH, height=self.CANVAS_HEIGHT, background='white')
        self.canvas.grid(row=0, column=0)
        # mouse clicks
        self.canvas.bind("<ButtonRelease-1>", self.left_button_release)

        # clear button
        self.clear_button = ttk.Button(self.window, text='Clear', command=self.clear_window)
        self.clear_button.grid(row=15, column=2)

        self.OPTIONS_figure = [
            "",
            "Тетраэдр",
            "Гексаэдр",
            "Октаэдр",
            "Икосаэдр",
            "Додекаэдр",
            "Функция",
            'Фигура вращения'
        ]
        self.label1 = ttk.Label(self.window, text='Фигура:                ')
        self.label1.grid(row=1, column=1)
        self.what_figure = StringVar(self.window)
        self.what_figure.set(self.OPTIONS_figure[2])
        self.option_menu1 = ttk.OptionMenu(self.window, self.what_figure, *self.OPTIONS_figure)
        self.option_menu1.grid(row=2, column=1)

        self.OPTIONS_proection = [
            "",
            "Ортографическая",
            "Изометрическая",
            "Перспективная"
        ]
        self.label2 = ttk.Label(self.window, text='Проекция:                     ')
        self.label2.grid(row=1, column=2)
        self.what_proection = StringVar(self.window)
        self.what_proection.set(self.OPTIONS_proection[1])
        self.option_menu2 = ttk.OptionMenu(self.window, self.what_proection, *self.OPTIONS_proection)
        self.option_menu2.grid(row=2, column=2)

        self.OPTIONS_xyz = [
            "",
            "xy",
            "xz",
            "yz"
        ]
        self.label3 = ttk.Label(self.window, text='Проецирование на: ')
        self.label3.grid(row=1, column=3)
        self.what_xyz = StringVar(self.window)
        self.what_xyz.set(self.OPTIONS_xyz[1])
        self.option_menu3 = ttk.OptionMenu(self.window, self.what_xyz, *self.OPTIONS_xyz)
        self.option_menu3.grid(row=2, column=3)

        # ПОВОРОТ
        ttk.Label(self.window, text="Angle: ").grid(row=3, column=2)
        self.angle_input = Entry(self.window, width=7)
        self.angle_input.insert(0, "180")
        self.angle_input.grid(row=4, column=2)

        self.OPTIONS_rotate = [
            "",
            "оси X",
            "оси Y",
            "оси Z"
        ]
        self.label4 = ttk.Label(self.window, text='Поворот относительно: ')
        self.label4.grid(row=3, column=3)
        self.what_rotate = StringVar(self.window)
        self.what_rotate.set(self.OPTIONS_rotate[1])
        self.option_menu4 = ttk.OptionMenu(self.window, self.what_rotate, *self.OPTIONS_rotate)
        self.option_menu4.grid(row=4, column=3)

        self.rotate_button = ttk.Button(self.window, text='Rotate', command=self.rotate_action)
        self.rotate_button.grid(row=3, column=1)
        self.rotate_button2 = ttk.Button(self.window, text='Rotate line', command=self.rotate_line_action)
        self.rotate_button2.grid(row=4, column=1)

        self.label5 = ttk.Label(self.window, text='p1: ')
        self.label5.grid(row=3, column=4)
        self.p1_x = Entry(self.window, width=5)
        self.p1_x.grid(row=3, column=5)
        self.p1_x.insert(0, "0")
        self.p1_y = Entry(self.window, width=5)
        self.p1_y.grid(row=3, column=6)
        self.p1_y.insert(0, "0")
        self.p1_z = Entry(self.window, width=5)
        self.p1_z.grid(row=3, column=7)
        self.p1_z.insert(0, "0")

        self.label6 = ttk.Label(self.window, text='p2: ')
        self.label6.grid(row=4, column=4)
        self.p2_x = Entry(self.window, width=5)
        self.p2_x.grid(row=4, column=5)
        self.p2_x.insert(0, "0")
        self.p2_y = Entry(self.window, width=5)
        self.p2_y.grid(row=4, column=6)
        self.p2_y.insert(0, "0")
        self.p2_z = Entry(self.window, width=5)
        self.p2_z.grid(row=4, column=7)
        self.p2_z.insert(0, "0")

        # ОТРАЖЕНИЕ
        self.reflection_button = ttk.Button(self.window, text='Отражение', command=self.reflection_action)
        self.reflection_button.grid(row=6, column=1)
        self.OPTIONS_xyz_reflection = [
            "",
            "xy",
            "xz",
            "yz"
        ]
        self.label3 = ttk.Label(self.window, text='Отражение относительно: ')
        self.label3.grid(row=6, column=3)
        self.what_xyz_reflection = StringVar(self.window)
        self.what_xyz_reflection.set(self.OPTIONS_xyz_reflection[1])
        self.option_menu5 = ttk.OptionMenu(self.window, self.what_xyz_reflection, *self.OPTIONS_xyz_reflection)
        self.option_menu5.grid(row=7, column=3)

        # СДВИГ
        self.reflection_button = ttk.Button(self.window, text='Сдвиг', command=self.shift_action)
        self.reflection_button.grid(row=8, column=1)

        ttk.Label(self.window, text="Shift: ").grid(row=8, column=3)

        self.label7 = ttk.Label(self.window, text='X: ')
        self.label7.grid(row=8, column=4)
        self.shift_x = Entry(self.window, width=5)
        self.shift_x.grid(row=8, column=5)

        self.label8 = ttk.Label(self.window, text='Y: ')
        self.label8.grid(row=8, column=6)
        self.shift_y = Entry(self.window, width=5)
        self.shift_y.grid(row=8, column=7)

        self.label9 = ttk.Label(self.window, text='Z: ')
        self.label9.grid(row=8, column=8)
        self.shift_z = Entry(self.window, width=5)
        self.shift_z.grid(row=8, column=9)

        # МАСШТАБИРОВАНИЕ
        self.scale_button = ttk.Button(self.window, text='Scale', command=self.scale_action)
        self.scale_button.grid(row=9, column=1)

        ttk.Label(self.window, text="Scale: ").grid(row=9, column=3)
        # self.scale_input = Entry(self.window, width=7)
        # self.scale_input.insert(0, "1")
        # self.scale_input.grid(row=9, column=2)

        self.label10 = ttk.Label(self.window, text='X: ')
        self.label10.grid(row=9, column=4)
        self.scale_x = Entry(self.window, width=5)
        self.scale_x.grid(row=9, column=5)

        self.label11 = ttk.Label(self.window, text='Y: ')
        self.label11.grid(row=9, column=6)
        self.scale_y = Entry(self.window, width=5)
        self.scale_y.grid(row=9, column=7)

        self.label12 = ttk.Label(self.window, text='Z: ')
        self.label12.grid(row=9, column=8)
        self.scale_z = Entry(self.window, width=5)
        self.scale_z.grid(row=9, column=9)

        # ttk.Label(self.window, text="Scale: ").grid(row=10, column=3)
        #
        # self.label10 = ttk.Label(self.window, text='X: ')
        # self.label10.grid(row=10, column=4)
        # self.scale_x = Entry(self.window, width=5)
        # self.scale_x.grid(row=10, column=5)
        #
        # self.label11 = ttk.Label(self.window, text='Y: ')
        # self.label11.grid(row=10, column=6)
        # self.scale_y = Entry(self.window, width=5)
        # self.scale_y.grid(row=10, column=7)
        #
        # self.label12 = ttk.Label(self.window, text='Z: ')
        # self.label12.grid(row=10, column=8)
        # self.scale_z = Entry(self.window, width=5)
        # self.scale_z.grid(row=10, column=9)

        self.set_default_values()
        self.window.mainloop()

    def set_default_values(self):
        """
        Установка значений по умолчанию во всех элементах интерфейса.
        Функция вызывается при первом запуске.
        """
        self.what_figure.set(self.OPTIONS_figure[1])
        self.what_xyz.set(self.OPTIONS_xyz[1])
        self.what_proection.set(self.OPTIONS_proection[1])
        self.angle_input.delete(0, END)
        self.angle_input.insert(0, "45")
        self.what_rotate.set(self.OPTIONS_rotate[1])
        self.what_xyz_reflection.set(self.OPTIONS_xyz_reflection[1])

        self.shift_x.delete(0, END)
        self.shift_x.insert(0, "0")
        self.shift_y.delete(0, END)
        self.shift_y.insert(0, "0")
        self.shift_z.delete(0, END)
        self.shift_z.insert(0, "0")

        self.scale_x.delete(0, END)
        self.scale_x.insert(0, "1")
        self.scale_y.delete(0, END)
        self.scale_y.insert(0, "1")
        self.scale_z.delete(0, END)
        self.scale_z.insert(0, "1")

        # self.p1_x.delete(0, END)
        # self.p1_x.insert(0, "0")
        # self.p1_y.delete(0, END)
        # self.p1_y.insert(0, "0")
        # self.p1_z.delete(0, END)
        # self.p1_z.insert(0, "0")
        #
        # self.p2_x.delete(0, END)
        # self.p2_x.insert(0, "0")
        # self.p2_y.delete(0, END)
        # self.p2_y.insert(0, "0")
        # self.p2_z.delete(0, END)
        # self.p2_z.insert(0, "0")

    def rotate_action(self):
        """
        Поворот
        """
        angle = float(self.angle_input.get())
        key = 0
        if self.what_rotate.get() == "оси X":
            key = 0
        elif self.what_rotate.get() == "оси Y":
            key = 1
        elif self.what_rotate.get() == "оси Z":
            key = 2

        self.figure.rotation(angle=angle, key=key)
        self.plot_figure()

    def rotate_line_action(self):
        """
        Поворот относительно линии
        """
        angle = float(self.angle_input.get())

        p1 = P(x=float(self.p1_x.get()), y=float(self.p1_y.get()), z=float(self.p1_z.get()))
        p2 = P(x=float(self.p2_x.get()), y=float(self.p2_y.get()), z=float(self.p2_z.get()))

        self.figure.rotationL(p1=p1, p2=p2, angle=angle)
        self.plot_figure()

    def reflection_action(self):
        """
        Отражение
        """
        key = 0
        if self.what_xyz_reflection.get() == 'xy':
            key = 0
        elif self.what_xyz_reflection.get() == 'xz':
            key = 1
        elif self.what_xyz_reflection.get() == 'yz':
            key = 2
        print(key)
        self.figure.reflection(key=key)
        self.plot_figure()

    def scale_action(self):
        """
        Масштабирование
        """
        # scale = float(self.scale_input.get())
        # self.figure.scaleC(xscale=scale, yscale=scale, zscale=scale)
        # self.plot_figure()

        self.figure = self.figure.scaleC(xscale=float(self.scale_x.get()),
                                         yscale=float(self.scale_y.get()),
                                         zscale=float(self.scale_z.get()))
        self.plot_figure()

    def shift_action(self):
        """
        Сдвиг
        """
        self.figure = self.figure.shift(xshift=float(self.shift_x.get()),
                                        yshift=float(self.shift_y.get()),
                                        zshift=float(self.shift_z.get()))
        self.plot_figure()

    def clear_window(self):
        """
        Отчистка окна
        """
        self.canvas.delete("all")

    def plot_figure(self):
        """
        Отрисовка изменённой фигуры
        """
        self.clear_window()
        # self.figure.setcenter(self.CANVAS_WIDTH / 2, self.CANVAS_WIDTH / 2, self.CANVAS_WIDTH / 2)
        pnts, edgs = self.figure.projection(tp=self.proection, key=self.xyz)

        for e in edgs:
            p1 = pnts[e[0]]
            p2 = pnts[e[1]]
            height = self.CANVAS_HEIGHT / 2
            width = self.CANVAS_WIDTH / 2
            if self.xyz == 0:
                self.canvas.create_line(p1.y, p1.z, p2.y, p2.z)
            elif self.xyz == 1:
                self.canvas.create_line(p1.x, p1.z, p2.x, p2.z)
            elif self.xyz == 2:
                self.canvas.create_line(width + p1.x, height - p1.y, width + p2.x, height - p2.y)

    def left_button_release(self, event):
        """
        Установка фигуры по левому нажатию мыши
        """
        self.figure = Tetrahedron()
        if self.what_figure.get() == "Тетраэдр":
            self.figure = Tetrahedron()
        elif self.what_figure.get() == "Гексаэдр":
            self.figure = Hexahedron()
        elif self.what_figure.get() == "Октаэдр":
            self.figure = Octahedron()
        elif self.what_figure.get() == "Икосаэдр":
            self.figure = Icosahedron()
        elif self.what_figure.get() == "Додекаэдр":
            self.figure = Dodecahedron()
        elif self.what_figure.get() == "Функция":
                self.figure = Func(f=lambda x, y: np.sin((x + y) * 3), x0=0, x1=1, y0=0, y1=1, step=0.1)
                # np.sin((x + y) * 3)
                # (x + y)
        elif self.what_figure.get() == "Фигура вращения":
            self.figure = RotationFigure([[0, 100, 0], [0, 100, 100]], partitions=4, key=2) # [[0, 100, 40], [20, 60, 70], [0, 30, 50], [0, 10, 50]]

        tp = 0
        if self.what_proection.get() == 'Перспективная':
            tp = 2
        elif self.what_proection.get() == 'Изометрическая':
            tp = 1
        elif self.what_proection.get() == 'Ортографическая':
            tp = 0

        key = 2
        if self.what_xyz.get() == 'yz':
            key = 0
        elif self.what_xyz.get() == 'xz':
            key = 1
        elif self.what_xyz.get() == 'xy':
            key = 2

        self.proection = tp
        self.xyz = key
        #self.figure.setcenter(250, 250, 0)  # .rotationXYZ(20, 60, 60)
        self.plot_figure()

if __name__ == '__main__':
    Gui()


import os
import cv2
import numpy as np
import requests
import pyfakewebcam
from signal import signal, SIGINT
from sys import exit

# setup access to the *real* webcam
cap = cv2.VideoCapture('/dev/video0')
height, width = 720, 1280
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FPS, 30)

# In case the real webcam does not support the requested mode.
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))

# The scale factor for image sent to bodypix
sf = 0.5

# setup the fake camera
fake = pyfakewebcam.FakeWebcam('/dev/video2', width, height)

# declare global variables
background = None
foreground = None
f_mask = None
inv_f_mask = None

def load_images():
    global background
    global foreground
    global f_mask
    global inv_f_mask

    # load the virtual background
    background = cv2.imread("background.jpg")
    background = cv2.resize(background, (width, height))

    foreground = cv2.imread("foreground.jpg")
    foreground = cv2.resize(foreground, (width, height))

    f_mask = cv2.imread("foreground-mask.png")
    f_mask = cv2.normalize(f_mask, None, alpha=0, beta=1,
                        norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)
    f_mask = cv2.resize(f_mask, (width, height))
    f_mask = cv2.cvtColor(f_mask, cv2.COLOR_BGR2GRAY)
    inv_f_mask = 1 - f_mask

def handler(signal_received, frame):
    load_images()
    print('Reloaded the background and foreground images')

def get_mask(frame, bodypix_url='http://127.0.0.1:9000'):
    frame = cv2.resize(frame, (0, 0), fx=sf, fy=sf)
    _, data = cv2.imencode(".png", frame)
    r = requests.post(
        url=bodypix_url,
        data=data.tobytes(),
        headers={'Content-Type': 'application/octet-stream'})
    mask = np.frombuffer(r.content, dtype=np.uint8)
    mask = mask.reshape((frame.shape[0], frame.shape[1]))
    mask = cv2.resize(mask, (0, 0), fx=1/sf, fy=1/sf,
                      interpolation=cv2.INTER_NEAREST)
    mask = cv2.dilate(mask, np.ones((20,20), np.uint8) , iterations=1)
    mask = cv2.blur(mask.astype(float), (30,30))
    return mask

def shift_image(img, dx, dy):
    img = np.roll(img, dy, axis=0)
    img = np.roll(img, dx, axis=1)
    if dy>0:
        img[:dy, :] = 0
    elif dy<0:
        img[dy:, :] = 0
    if dx>0:
        img[:, :dx] = 0
    elif dx<0:
        img[:, dx:] = 0
    return img

def get_frame(cap, background):
    _, frame = cap.read()
    # fetch the mask with retries (the app needs to warmup and we're lazy)
    # e v e n t u a l l y c o n s i s t e n t
    mask = None
    while mask is None:
        try:
            mask = get_mask(frame)
        except:
            print("mask request failed, retrying")

    # composite the foreground and background
    for c in range(frame.shape[2]):
        frame[:,:,c] = frame[:,:,c] * mask + background[:,:,c] * (1 - mask)

    for c in range(frame.shape[2]):
        frame[:,:,c] = frame[:,:,c] * inv_f_mask + foreground[:,:,c] * f_mask

    return frame

if __name__ == '__main__':
    load_images()
    signal(SIGINT, handler)
    print('Running...')
    print('Please press CTRL-\ to exit.')
    print('Please CTRL-C to reload the background and foreground images')
    # frames forever
    while True:
        frame = get_frame(cap, background)
        # fake webcam expects RGB
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        fake.schedule_frame(frame)


import copy
import importlib
import itertools

import six
import yaml

from ioc.schema.dependency import Dependency
from ioc.schema.exc import InvalidDeclaration
from ioc.schema.adapters import SymbolDependencyAdapter
from ioc.schema.adapters import LiteralDependencyAdapter
from ioc.schema.adapters import NestedDependencyAdapter
from ioc.schema.adapters import DependencyCollectionAdapter
from ioc.schema.base import Schema

class SchemaParser(object):
    """Parses the dependency configuration schema."""

    def __init__(self, provider=None, override=False):
        self.provider = provider or importlib.import_module('ioc.provider')
        self.override = override

    def load(self, dependencies):
        """Inspect the dependency configuration and validate the declared
        items.
        """
        schema = Schema(self.provider, override=self.override)

        # Check that each dependency has at least a name.
        names = set()
        for dep in dependencies:
            name = dep.get('name')
            if name is None:
                raise InvalidDeclaration(dep, "No name specified")

            if not isinstance(name, six.string_types):
                raise InvalidDeclaration(dep, "Invalid name specified: %s" % repr(name))
            if name in names:
                raise InvalidDeclaration(dep, "Duplicate name: %s" % name)

            names.add(name)

        # For each dependency, try to load them as either a Simple, Literal
        # or NestedDependency.
        adapters = [
            NestedDependencyAdapter(),
            SymbolDependencyAdapter(),
            LiteralDependencyAdapter(),
            DependencyCollectionAdapter(),
        ]

        for dep in dependencies:
            cleaned_dep = None
            for adapter in adapters:
                cleaned_dep, errors = adapter.load(copy.deepcopy(dep))
                if not errors:
                    break

                cleaned_dep = None

            # If there is still no dependency loaded at this point, this
            # means the declaration was invalid.
            if cleaned_dep is None:
                raise InvalidDeclaration(dep, "Invalid dependency declaration")

            assert issubclass(type(cleaned_dep), Dependency),\
                "load() must return a Dependency implementation, got %s" %\
                repr(cleaned_dep)
            schema.add(cleaned_dep)

        return schema


import pandas as pd
import numpy as np
from tkinter import *
from tkinter import filedialog

def browsefunc():
    root = Tk()
    root.withdraw()
    root.update()
    filename = filedialog.askopenfilename(filetypes=[('csv', '*.csv'), ('xlsx', '*xlsx')])
    root.destroy()

    return filename

def check_col_names(df):
    relev_col = ("naam", "omschrijving")
    for c in df.columns:
        cLow = c.lower()
        if cLow in relev_col:
            df.rename(columns = {c : cLow}, inplace = True)

    if 'naam' and 'omschrijving' in df.columns:
        return df
    else:
        print("\nYour columns are not labelled as \"omschrijving\" for courses and \"naam\" for the student names. Please rename them and/or check the format of your file to work with this program.")
        exit()

def course_choice1(df, group):
    print("\nNow you choose the first course you want to check. Press any key apart from enter and then enter to see a list of all courses.")
    df = check_col_names(df)
    if input():
        uni_courses = np.unique(df['omschrijving'])
        for i, c in enumerate(uni_courses):
            print(f"{i+1}: {c}")
        print("\nEnter the number corresponding with the first course you want to check.")
        choice = input()
        choice = int(choice) - 1
        course1 = uni_courses[choice]
        print(f"\nYour first course is: {course1} \nIs that correct? Enter y for yes and n for no.")

        studentsList1 = np.where(df['omschrijving']== course1, df["naam"], "None")
        studentsList1 = studentsList1[studentsList1 != "None"]
        print("\nStudents taking this course:", studentsList1)

        print("\nStudents being in the selected group and taking the course:")

        for i, _ in enumerate(studentsList1):
            studentsList1[i] = studentsList1[i].split(",")
            studentsList1[i] = studentsList1[i][0].split()
            studentsList1[i] = studentsList1[i][-1]

        studentsList2 = group["Last Name"]
        true = 0
        false = 0
        for i in studentsList2:
            if i in studentsList1:
                print(i)
                true +=1
            else:
                false += 1
        print(f"\nOverlaps?\n true: {true}\n false: {false}")
        decider(df, group)
    else:
        print("\nOooops. Something went wrong. Let's do this again!")
        starter()

def starter():
    welcome_msg = "Hi! You are about to compare a course participant list with a student group list.\nFirst you are going to select your group file (a group per CSV file, just \"save as\" and select CSV in case you have received a xlsx file).\nThen you will select the enrolments file which can stay as xlsx (select the type of file you are looking for on the bottom right)"
    print(welcome_msg)
    group = browsefunc()
    if group:
        print("\nSuccess!\nNow the enrolments.")
    enrolments= browsefunc()
    if enrolments:
        print("\nSuccess!")

    group = pd.read_csv(group, sep=";")
    enrolments =pd.read_excel(enrolments)

    course_choice1(enrolments, group)

def decider(enrolments, group):
    print("\nDone.\nWhat do you want to do next? \nPress 1 for another comparison using the same enrolments and group file. \nPress 2 for another comparison using the same enrolments but a different group file. \nPress 3 to restart or 4 to exit.")
    decision = input()
    if decision == "1":
        course_choice1(enrolments, group)
    elif decision == "2":
        print("\nNow choose a new group file.")
        group = browsefunc()
        group = pd.read_csv(group, sep=";")
        course_choice1(enrolments, group)
    elif decision == "3":
        starter()
    elif decision == "4":
        exit
    else:
        print("\nWhoops! Something went wrong. Let us try again!")
        decider(enrolments, group)

starter()


#
#  This monkey-patches M2Crypto's RSA and DSA support to allow us
#  to create keys directly from a given set of parameters.
#  It's based on the following patch from the M2Crypt bugtracker:
#
#      https://bugzilla.osafoundation.org/show_bug.cgi?id=12981
#
#  We use ctypes to avoid recompiling the M2Crypto binaries.

import ctypes
from M2Crypto import RSA, DSA, m2, __m2crypto

_m2lib = ctypes.CDLL(__m2crypto.__file__)

_m2lib.BN_free.argtypes = (ctypes.c_void_p,)
_m2lib.BN_mpi2bn.argtypes = (ctypes.c_char_p, ctypes.c_int, ctypes.c_void_p,)
_m2lib.BN_mpi2bn.restype = ctypes.c_void_p

class _RSA(ctypes.Structure):
    """OpenSSL struct representing a RSA key (struct rsa_st)."""
    _fields_ = [("pad", ctypes.c_int),
                ("version", ctypes.c_long),
                ("RSA_METHOD", ctypes.c_void_p),
                ("ENGINE", ctypes.c_void_p),
                ("n", ctypes.c_void_p),
                ("e", ctypes.c_void_p),
                ("d", ctypes.c_void_p)]
                # There are many more fields, but we don't need them.

class _DSA(ctypes.Structure):
    """OpenSSL struct representing a DSA key (struct dsa_st)."""
    _fields_ = [("pad", ctypes.c_int),
                ("version", ctypes.c_long),
                ("write_params", ctypes.c_int),
                ("p", ctypes.c_void_p),
                ("q", ctypes.c_void_p),
                ("g", ctypes.c_void_p),
                ("pub_key", ctypes.c_void_p),
                ("priv_key", ctypes.c_void_p)]
                # There are many more fields, but we don't need them.

def maybe_provide(obj):
    """Decorator to provide default implemenation of a function."""
    def decorator(func):
        if not hasattr(obj, func.__name__):
            setattr(obj, func.__name__, func)
        return func
    return decorator

@maybe_provide(m2)
def rsa_set_d(rsa, value):
    """Set the private-key component "d" of a RSA object."""
    bn = _m2lib.BN_mpi2bn(value, len(value), None)
    if not bn:
        raise RSA.RSAError("invalid private key data")
    rsa_p = ctypes.cast(ctypes.c_void_p(int(rsa)), ctypes.POINTER(_RSA))
    if rsa_p.contents.d:
        _m2lib.BN_free(rsa_p.contents.d)
    rsa_p.contents.d = bn

@maybe_provide(m2)
def dsa_set_pub(dsa, value):
    """Set the public-key component of a DSA object."""
    bn = _m2lib.BN_mpi2bn(value, len(value), None)
    if not bn:
        raise DSA.DSAError("invalid public key data")
    dsa_p = ctypes.cast(ctypes.c_void_p(int(dsa)), ctypes.POINTER(_DSA))
    if dsa_p.contents.pub_key:
        _m2lib.BN_free(dsa_p.contents.pub_key)
    dsa_p.contents.pub_key = bn

@maybe_provide(m2)
def dsa_set_priv(dsa, value):
    """Set the private-key component of a DSA object."""
    bn = _m2lib.BN_mpi2bn(value, len(value), None)
    if not bn:
        raise DSA.DSAError("invalid private key data")
    dsa_p = ctypes.cast(ctypes.c_void_p(int(dsa)), ctypes.POINTER(_DSA))
    if dsa_p.contents.priv_key:
        _m2lib.BN_free(dsa_p.contents.priv_key)
    dsa_p.contents.priv_key = bn

@maybe_provide(RSA)
def new_key(parameters):
    """Create a RSA object from the given parameters."""
    e, n, d = parameters
    rsa = m2.rsa_new()
    m2.rsa_set_e(rsa, e)
    m2.rsa_set_n(rsa, n)
    m2.rsa_set_d(rsa, d)
    return RSA.RSA(rsa, 1)

# Calling sign() on a public key will segfault M2Crypto.
# Stub it out so that it raises an error instead.
if "sign" not in RSA.RSA_pub.__dict__:
    RSA.RSA_pub.sign = RSA.RSA_pub.private_encrypt

@maybe_provide(DSA)
def load_pub_key_params(p, q, g, pub):
    """Create a DSA_pub object from parameters and key."""
    dsa = m2.dsa_new()
    m2.dsa_set_p(dsa, p)
    m2.dsa_set_q(dsa, q)
    m2.dsa_set_g(dsa, g)
    m2.dsa_set_pub(dsa, pub)
    return DSA.DSA_pub(dsa, 1)

@maybe_provide(DSA)
def load_key_params(p, q, g, pub, priv):
    """Create a DSA object from parameters and key."""
    dsa = m2.dsa_new()
    m2.dsa_set_p(dsa, p)
    m2.dsa_set_q(dsa, q)
    m2.dsa_set_g(dsa, g)
    m2.dsa_set_pub(dsa, pub)
    m2.dsa_set_priv(dsa, priv)
    return DSA.DSA(dsa, 1)


# -*- coding: utf-8 -*-
"""
Created on Tue Mar 28 12:53:21 2017

@author: joans

A view is a pair (fragment number, side), with two fragments and two sides
(exterior, interior)
    Fragment  Side  View
    1         E     1
    1         I     2
    2         E     3
    2         I     4

Captures are pairs of led light source and exposure time :
    LED       Exp time   Capture
    visible 1      0.5         1
    visible 1        1         2
    visible 2      0.5         3
    visible 2        1         4
    ir 1           0.5         5
    ir 1             1         6
    ir 2           0.5         7
    ir 2             1         8

sampling = 1 => no sampling, 2 = 1/4 size etc

crop_size is the final number of rows and cols for training and testing.
In num_channels computation, 3 for RGB, and the product is because we concatenate images from
several captures from the same view
"""
import os
import numpy as np

class Params_data():
    """ Dataset """
    path_dataset = '/datatmp/kidney_stones/'
    path_groundtruth = os.path.join(path_dataset,'groundtruth.xls')
    views = [1,2,3,4]
    captures = [2,] # [2,6,8]
    class_level = 1
    num_classes = 8

    """ for precomputed samples """
    num_data_augmentations = 100
    """ must be >= than max_batches*batch_size/number of samples """
    path_precomputed_samples = '/datatmp/precomputed_samples_sampling_3/'
    #path_precomputed_samples = '/datatmp/precomputed_samples_sampling_2/'
    #path_precomputed_samples = '/datatmp/precomputed_samples_sampling_1/'

    """ Data augmentation """
    data_augmentation_train = True
    data_augmentation_test = False
    mixer_probability = 0.8

    sampling = 3
    crop_size = 200
    # offset = 0.2 # relative to crop size, only for sample_rotate_crop() in Image_transform
    max_brightness_change = 5
    max_contrast_change = 0.02 # abans 0.05

    """ computations """
    num_views = len(views)
    num_captures = len(captures)
    image_shape = (crop_size, crop_size, 3*num_captures)

    """ Checkings for the dataset of kidney stones"""
    for v in views:
        assert v in range(1,5)
    for cap in captures:
        assert cap in range(1,9)
    assert class_level in [1,2]
    assert (class_level==1 and num_classes==8) \
           or (class_level==2 and num_classes==12)

class Params_net():
    Types_of_non_linearity = ['sigmoid', 'relu', 'elu', 'tanh']
    Shapes_of_network = ['shallow', 'deep', 'deep with strides',
                         'more shallow', 'resnet', 'densenet']
    Types_sharing_features = ['all', 'every each other', 'any']

    share_features = 'every each other'

    shape_network = 'resnet'
    assert shape_network in Shapes_of_network

    assert Params_data.image_shape[0]==200
    if shape_network=='deep':
        kernels = 14*[3]
        depth =   2*[64]+10*[128]+2*[256]
        stridesxy = 14*[1]
        do_maxpooling = 7*[True,False]

    elif shape_network=='deep with strides':
        """ better strides>1 than maxpooling ? """
        kernels = 11*[3]
        depth =   2*[96]+7*[48]+2*[128]
        stridesxy = 3*[2,2,1]+[2,2]
        do_maxpooling = 11*[False]

    elif shape_network=='shallow':
        kernels =   7*[3]
        depth =     2*[64]+3*[128]+2*[256]
        stridesxy = 7*[1]
        do_maxpooling = 7*[True]

    elif shape_network=='more shallow':
        kernels =   4*[3]
        depth =     [48,64,128,256]
        stridesxy = 4*[2]
        do_maxpooling = 4*[True]

    elif shape_network=='resnet':
        kernels =   3
        depth =     64
        stridesxy = None
        do_maxpooling = None

    elif shape_network=='densenet':
        kernels =   3
        depth =     48
        stridesxy = None
        do_maxpooling = None

    """ parameters of convolutional layers, in features and classifier """
    non_linearity = 'elu'

    """ parameters of fully connected layers in classifier"""
    number_of_fc_layers = 3
    assert number_of_fc_layers in [1,2,3,4]
    fc_constant_bias = 1.0E-01

    """ parameters for regularization: weight normalization and dropout """
    lambda_features = 1e-03
    lambda_classification = 1e-02
    keep_prob_cnn = 1.0
    keep_prob_classification_layers = 0.4

    """ If True we concatenate the features coming from each branch and then
    input them to a unique classifier block made of fc layers and ended by
    a softmax to produce a unique vector of probabilities.
    If False we concatenate them also and then we generate several
    permutations (n! at most, n=number of branches or views) each entering
    one branch of a classifier as before, only that they all share
    weights. This produces several probs that are averaged. Also, there is one
    xentropy per classifier block (with gt) and potentially n over 2 xentropies
    between pairs of blocks """
    early_fusion_features = False

    if not early_fusion_features:
        """ If True there will be 4 permutations from the concatenated features:
        e1i1e2i2, e2i2e1i1, e1i2e2i1, e2i1e1i2. If False just the two first ones. """
        mix_fragments = False

    """ batch normalization """
    do_batch_normalization = False

    if shape_network not in ['resnet', 'densenet']:
        assert len(kernels) == len(depth)
        assert len(kernels) == len(stridesxy)
        assert len(kernels) == len(do_maxpooling)

    assert non_linearity in Types_of_non_linearity
    assert share_features in Types_sharing_features
    assert shape_network in Shapes_of_network

class Params_training():
    Types_of_optimizer = ['GradientDescent', 'Adagrad', 'RMSPROP', 'Adam']

    num_folds = 4
    batch_size = 48
    max_batches = 6000
    balanced_batches = False

    randomize = True
    if not randomize:
        numpy_seed = 1
        tensorflow_seed = 1234

    initial_learning_rate = 1e-04
    final_learning_rate = 1e-05
    # power_learning_rate = 1
    optimizer = 'Adam'

    show_every_batches = 1
    assess_every_batches = 25
    """ asses the test set and saves the results """
    save_model = True
    """ saves the weights at the last batch for each fold """

    gpu_device = '1'
    results_dir = 'experiments/'

    if balanced_batches:
        num_threads = 4
        """ check bacthes are balanced if num_treads large """
        max_num_samples_in_queue = 10*batch_size
    else:
        num_threads = 5
        max_num_samples_in_queue = 10*batch_size

    noisy_labels = False
    if noisy_labels:
        period_permutation = 80
        """ permute labels in a batch every this number of batches """

    soft_labels = False
    if soft_labels:
        scheme_soft_labels = 1

        if scheme_soft_labels==0:
            prob_real = 1.0
            confusion_matrix = np.ones((8,8)) - np.eye(8)
            """
            aixo es equivalent al training de sempre, amb groundtruth numeric, la
            classe real amb prob 1 i la resta prob zero.
            """
        elif scheme_soft_labels==1:
            prob_real = 0.7
            confusion_matrix = np.ones((8,8)) - np.eye(8)
            """
            aixo es repartir proporcionalment entre totes les classes la probabilitat
            1.0 - probabilitat de la real que es menor que 1.0
            """
        elif scheme_soft_labels==2:
            prob_real = 0.90
            confusion_matrix = np.array([
                [0, 1, 0, 0, 0, 0, 0, 0,],
                [1, 0, 1, 0, 0, 0, 0, 0,],
                [1, 1, 0, 0, 0, 0, 0, 0,],
                [0, 0, 1, 0, 1, 0, 0, 0,],
                [0, 1, 1, 1, 0, 0, 0, 0,],
                [0, 1, 0, 0, 1, 0, 1, 0,],
                [0, 1, 1, 0, 0, 0, 0, 1,],
                [1, 1, 0, 0, 0, 0, 1, 0,],
            ]) # binary matrix of shape num_classes x num_classes
            """
            aqui repartim 1 - prob. real entre algunes classes nomes, aquelles amb
            les que es confon mes cadascuna
            """
        elif scheme_soft_labels==3:
            prob_real = 0.6
            confusion_matrix = np.array([
                [0, 1, 1, 0, 0, 0, 1, 1,],
                [1, 0, 1, 1, 0, 0, 0, 1,],
                [1, 1, 0, 1, 1, 0, 0, 0,],
                [0, 1, 1, 0, 1, 1, 0, 0,],
                [0, 0, 1, 1, 0, 1, 1, 0,],
                [0, 0, 0, 1, 1, 0, 1, 1,],
                [1, 0, 0, 0, 1, 1, 0, 1,],
                [1, 1, 0, 0, 0, 1, 1, 0,],
            ])
            """
            faig una mena de matriu 4-diagonal i circular, que vol dir que
            la confusio es dona amb les 2 seguents i 2 anteriors classes
            aixo inclou el que passa en el cas anterior, mes o menys
            """
        else:
            assert False

        r,c = confusion_matrix.shape
        assert r==c # is square
        num_classes = r
        assert np.all([x in [0,1] for x in confusion_matrix.flatten()]) # is binary
        assert np.sum(confusion_matrix,axis=1).all() >= 0 # not one or more confusions per class
        assert np.sum(confusion_matrix,axis=1).all() < num_classes # less than num_classes confusions
        assert np.all(np.diag(confusion_matrix)==0) # can not confuse with itself

    if balanced_batches:
        assert batch_size % Params_data.num_classes == 0


from re import L
import requests
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from lxml import etree
import os
from time import sleep
import xlrd
import win32api
import win32con
import xlsxwriter as xw
from openpyxl import load_workbook
# #实现无可视化界面
# from selenium.webdriver.chrome.options import Options
# #实现规避检测
# from selenium.webdriver import ChromeOptions
# #实现无可视化界面的操作
# chrome_options = Options()
# chrome_options.add_argument('--headless')
# chrome_options.add_argument('--disable-gpu')
# #实现规避检测
# option = ChromeOptions()
# option.add_experimental_option('excludeSwitches', ['enable-automation'])
# #如何实现让selenium规避被检测到的风险
# brs = webdriver.Chrome(executable_path='./selenium/chromedriver',chrome_options=chrome_options,options=option)
def Load_ExcelDone(list,n=0):
    data=xlrd.open_workbook('./paper/paper.xlsx')
    table=data.sheets()[0]
    nrows=table.nrows
    for i in range(nrows):
        try:list.append(int(float(table.row_values(i)[n])))
        except:
            continue
    print(list)

def add_information_excel(filename,paper,list_done):
    workbook=load_workbook(filename+'.xlsx')
    wb=workbook.active
    for p in paper:
        column_n='A'+str(p.n)
        column_name='B'+str(p.n)
        column_wos='C'+str(p.n)
        column_url='D'+str(p.n)
        wb[column_n]=p.n
        wb[column_name]=p.name
        wb[column_wos]=p.wos
        wb[column_url]=p.url
    workbook.save(filename+'.xlsx')

def savepage_pywin32():
    win32api.keybd_event(17, 0, 0, 0)           # 按下ctrl
    win32api.keybd_event(83, 0, 0, 0)           # 按下s
    win32api.keybd_event(83, 0, win32con.KEYEVENTF_KEYUP, 0)    # 释放s
    win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)    # 释放ctrl
    sleep(1)
    win32api.keybd_event(13, 0, 0, 0)           # 按下enter
    win32api.keybd_event(13, 0, win32con.KEYEVENTF_KEYUP, 0)    # 释放enter

def search(kw):
    #seach in sci
    search_input=brs.find_element_by_xpath('//input[@data-ta="search-criteria-input"]')
    try:
        wind=brs.find_element_by_id('pendo-close-guide-8fdced48')
        wind.click()                     #find serch box
        search_input.click()
        search_input.clear()
        search_input.send_keys(kw)
        search_input.send_keys(Keys.ENTER)                                          #input keywords
        butn=brs.find_element_by_xpath('//span[@class="mat-button-wrapper"]')   #find search button
        butn.click()
    except:
        search_input.click()
        search_input.clear()
        search_input.send_keys(kw)
        search_input.send_keys(Keys.ENTER)                                          #input keywords
        butn=brs.find_element_by_xpath('//span[@class="mat-button-wrapper"]')   #find search button
        butn.click()                                                            #click serch button and serch

def getsource(url,broser):
    broser.get(url)
    page_text=broser.page_source
    print('page_souce load successful')
    return page_text

def SaveHtml(HTML,Filename):
    if not os.path.exists('./paper/HTML'):
        os.makedirs('./paper/HTML')
    Filename=Filename+'.html'
    with open('./paper/HTML/'+Filename,'wb',encoding='utf-8') as fp:
        fp.write(HTML)
    return 'save successful'

def closewind(s):
    brs.find_element_by_id(s).click

def getpaper_wos_url(source):
    tree=etree.HTML(source)
    download=tree.xpath('//app-records-list//a[@data-ta="summary-record-title-link"]/@href')[0]
    Download='https://www.webofscience.com'+download
    return Download

def load_BasicExcel(lists,number,n=7):
    data=xlrd.open_workbook('./paper/gao.xlsx')
    table=data.sheets()[0]
    nrows=table.nrows
    if nrows>number:
        nrows=number
    for i in range(nrows):
        if i<=1:
            continue
        elif table.row_values(i)[n]==table.row_values(i-1)[n]:
            continue
        else :
            s=paper(i,table.row_values(i)[n],0,0)
            lists.append(s)

def getHTML(url,headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36'}):
    c=requests.get(url=url,headers=headers).content
    return c

def getfulltext_url(page):
    tree=etree.HTML(page)
    c=tree.xpath('//app-full-record-links//a/@href')[0]
    return c

class paper:
    def __init__(self,n,name,wos,url):
        self.n=n
        self.name=name
        self.wos=wos
        self.url=url

brs = webdriver.Chrome(executable_path='./selenium/chromedriver')
url='https://www.webofscience.com/wos/woscc/basic-search'
#create list
Paper_list=[]           #save paper (url,name,i,)
Paper_list_result=[]
# url_fulltest_list=[]    #save url
Paper_list_failed=[]    #save paper_url_failed
Paper_list_success_n=[]
Load_ExcelDone(Paper_list_success_n)
Paper_list_done=Paper_list_success_n
load_BasicExcel(Paper_list,50) # load data

#Seach and find paper_url
for kw in Paper_list:
    if kw.n not in Paper_list_success_n:
        try:
            brs.get(url)
            sleep(6)
            search(kw.name)
            sleep(2)
            wos=getpaper_wos_url(brs.page_source)
            sleep(3)
            brs.get(wos)
            sleep(2)
            url_fulltest=getfulltext_url(brs.page_source)
            # #save page by ctrl+s - enter
            # brs.get(url_fulltest)
            # sleep(6)
            # savepage_pywin32()
            # sleep(20)
            #save in list
            kw.wos=wos
            kw.url=url_fulltest
            Paper_list_result.append(kw)
            # url_fulltest_list.append(kw.url)

            #save name of success
            # Paper_list_success.append(kw.name)
            Paper_list_success_n.append(kw.n)
            print(kw.n,'load susccessful')
        except:
            #save name of failed
            print(kw.n,'load failed')
            Paper_list_failed.append(kw)

brs.quit()

add_information_excel('./paper/paper',Paper_list_result,Paper_list_done)
add_information_excel('./paper/paper_failed',Paper_list_failed,[])


import argparse
import os
import sys
import csv
import json
import datetime
import dateutil.parser as date_parser
import codecs

# Parse Arguements
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--file', help='CSV input file', required=True)
args = parser.parse_args()
file=args.file

# Preflight Checks
if not os.path.exists(file):
    sys.exit("Cannot find "+file)

# Helper functions
def check_in_list(item, list):
    if item in list:
        list.remove(item)
        return True
    else:
        print("Error, not in list")
        return False

def choose_csv_column(hacker_tracker_field, csv_columns_left):
    output = ""
    while output == "":
        print("\nColumns left: "+str(csv_columns_left))
        user_input = str(input("Which column is "+hacker_tracker_field+"? ") or "")
        if check_in_list(user_input, csv_columns_left):
            output = user_input
            return (output, csv_columns_left)

def convert_to_isotime(text):
    date = date_parser.parse(text)
    return date.isoformat()

def set_endtime(iso_start_time, duration):
    print(duration)
    date_time_start = datetime.datetime.strptime(iso_start_time, '%Y-%m-%dT%H:%M:%S')
    end_time = date_time_start + datetime.timedelta(minutes=int(duration))
    return end_time.isoformat()

def get_speaker_id(speakers_list, speaker_handle, speaker_id, conference_code):
    # return speaker id if we already have it
    for speaker in speakers_list:
        if speaker['name'] == speaker_handle:
            return speakers_list, speaker['id']

    # Else just make a new one
    # Most of this is blank. Because Skytalks
    speaker_id += 1
    new_speaker_json = {}
    new_speaker_json.update({"name": speaker_handle})
    new_speaker_json.update({ "updated_at": datetime.datetime.now().isoformat()})
    new_speaker_json.update({"description": ""})
    new_speaker_json.update({"title": ""})
    new_speaker_json.update({"id": speaker_id})
    new_speaker_json.update({"twitter": ""})
    new_speaker_json.update({"conference": conference_code})
    new_speaker_json.update({"link": ""})
    speakers_list.append(new_speaker_json)
    return speakers_list, speaker_id

# Lets chew in the CSV
csv_columns=[]
list_of_events=[]
with open(file) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            for item in row:
                csv_columns.append(item)
            print(f'Column names are {", ".join(csv_columns)}')
            line_count += 1
        else:
            event_json={}
            for i in range(0,len(csv_columns)):
                event_json.update({csv_columns[i]: row[i]})
            list_of_events.append(event_json)
            line_count += 1

# Alrighty then. Now to line up with the inputs hacker tracker needs
csv_columns_left = csv_columns
print("Set global values")
conference_code = str(input("Conference Code [DC27]: ") or "DC27")
event_type = int(input("Event Type [9]: ") or "9")
#Uncomment if it's just one location
#location = str(input("Location [Bally’s Las Vegas - Jubilee Tower 2nd floor]: ") or "Bally’s Las Vegas - Jubilee Tower 2nd floor")

print('\n\n')
print("Choose which CSV column headers to set to which Hacker Tracker Option")
start_date, csv_columns_left = choose_csv_column("start_date", csv_columns_left)
duration, csv_columns_left = choose_csv_column("duration (in minutes)", csv_columns_left)
title, csv_columns_left = choose_csv_column("title", csv_columns_left)
speakers, csv_columns_left = choose_csv_column("speakers", csv_columns_left)
description, csv_columns_left = choose_csv_column("description", csv_columns_left)
location, csv_columns_left = choose_csv_column("location", csv_columns_left)
'''
# Hardcoded Skytalks Values
conference_code = "DC27"
event_type = "9"
location = "Bally’s Las Vegas - Jubilee Tower 2nd floor"
start_date = "Day-Time"
duration = "Duration"
title = "Talk Title"
speakers = "Speaker(s)"
description = "Talk Description"
'''
# And finally, let's make some JSON
schedule = []
speakers_list = []
id = 1337
current_speaker_id = 7331
for event in list_of_events:
    # Check for empty keys caused by newlines
    print(event)
    if event[title] == "":
        pass
    else:
        hacker_tracker_event_json = {}
        hacker_tracker_event_json.update({"start_date": str(convert_to_isotime(event[start_date]))})
        hacker_tracker_event_json.update({"id": id})
        hacker_tracker_event_json.update({"description": event[description]})
        hacker_tracker_event_json.update({"location": event[location]})
        # Uncomment if just one location
        #hacker_tracker_event_json.update({"location": location})
        hacker_tracker_event_json.update({"link": ""})
        # hacker_tracker_event_json.update({"speakers": event[speakers].splitlines()})
        this_event_speakers=[]
        for speaker in event[speakers].split(", "):
            speakers_list, speaker_to_append = get_speaker_id(speakers_list, speaker, current_speaker_id, conference_code)
            this_event_speakers.append(speaker_to_append)
            if current_speaker_id < speaker_to_append:
                current_speaker_id = speaker_to_append
        hacker_tracker_event_json.update({"speakers": this_event_speakers})
        hacker_tracker_event_json.update({"end_date": str(set_endtime(convert_to_isotime(event[start_date]), event[duration]))})
        hacker_tracker_event_json.update({"conference": conference_code})
        hacker_tracker_event_json.update({"event_type": int(event_type)})
        hacker_tracker_event_json.update({"includes": ""})
        hacker_tracker_event_json.update({"title": event[title]})
        hacker_tracker_event_json.update({"updated_at": datetime.datetime.now().isoformat()})

        schedule.append(hacker_tracker_event_json)
        id += 1

hacker_tracker_schedule_json = {}
hacker_tracker_schedule_json.update({"Schedule": schedule})
print(json.dumps(hacker_tracker_schedule_json, indent=2, ensure_ascii=False))

hacker_tracker_speakers_json = {}
hacker_tracker_speakers_json.update({"speakers": speakers_list})
print(json.dumps(hacker_tracker_speakers_json, indent=2, ensure_ascii=False))

# Let's write this sucker to a file
with codecs.open('events.json', 'w', 'utf-8') as events_file:
    events_file.write(json.dumps(hacker_tracker_schedule_json, indent=2, ensure_ascii=False))
with codecs.open('speakers.json', 'w', 'utf-8') as speakers_file:
    speakers_file.write(json.dumps(hacker_tracker_speakers_json, indent=2, ensure_ascii=False))


from django.urls import path

from . import views

app_name = 'slots'
urlpatterns = [
    path('', views.index_view, name='index'),

    path('login/', views.login_view, name='login'),
    path('logout/', views.logout_view, name='logout'),
    path('signup/', views.signup_view, name='signup'),

    path('shops/', views.ShopsView.as_view(), name='shops'),
    path('shops/<int:pk>/', views.ShopView.as_view(), name='view-shop'),
    path('shops/<int:shop>/<str:method>/<int:slot>/',
        views.slot_manage_view,
        name='manage-slot'
    ),
    path('shops/<int:shop>/modify/', views.modify_view, name='modify'),

    path('me/', views.user_view, name='user'),
    path('me/slots/', views.SlotsView.as_view(), name='slots'),
    path('me/settings/', views.user_settings_view, name='settings'),
]


__author__ = 'spaweska'

"""
Question:
    Write a method which can calculate square value of number

Hints:
Using the ** operator
"""

def sqr(number: str) -> float:
    try:
        number = float(number)
        print(float(number ** 2))
    except ValueError:
        print("Something went wrong")

num = input("Enter number: ")
sqr(num)


# coding: utf8

import numpy as np
from gurobipy import *
import random
import time
import matplotlib.pyplot as plt
import timeit

EPSILON = 0.01
PRECISION = 10

def init_data(n, p):
    weight_max = 100
    objects = []
    for i in range(p):
        obj = ["object_" + str(i), random.randint(1,weight_max)]
        for j in range(n):
            crt = random.random()
            obj.append(crt)
        objects.append(obj)
    return objects

def getIdeal(objects, n):
    ideal = [max([row[i] for row in objects]) for i in range(2,n+2)]
    return ideal

def computeTchebycheffNorm(ideal, objects, epsilon, p):
    temp = [[abs(row[i+2] - ideal[i]) for i in range(len(ideal))] for row in objects]
    result = [max(temp[i]) + epsilon * sum(temp[i]) + 0.000001 for i in range(p) ]
    return result

def defineModel(objects, tcheb, p):
    model = Model()

    X = [model.addVar(vtype=GRB.BINARY, name="x%d"% i) for i in range (p)]
    model.update()

    objective = quicksum([xi*1/si for xi, si in zip(X, tcheb)])
    model.setObjective(objective, GRB.MAXIMIZE)

    weights_sum = quicksum([xi*wi[1] for xi, wi in zip(X, objects)])
    max_weight = 0.5*sum([wi[1] for wi in objects])
    model.addConstr(weights_sum, GRB.LESS_EQUAL, max_weight, name="weightsSum<=maxWeight")

    model.update()
    model.setParam('OutputFlag', False )
    model.write("KS.lp")
    return model

def solveModel(model):
    t1 = time.time()
    model.optimize()
    t2 = time.time()
    model.write("KS.sol")
    #print "X = ", [v.x for v in model.getVars()]
    return t2 - t1

def main():

    n_steps = range(5,51,5)
    p_steps = range(25,1001,25)
    time_tab = np.zeros([len(p_steps),len(n_steps)])

    results = np.zeros((len(p_steps), len(n_steps)))

    for i,p in enumerate(p_steps):
        for j,n in enumerate(n_steps):
            objects = init_data(n, p)
            ideal = getIdeal(objects, n)
            tcheb = computeTchebycheffNorm(ideal, objects, EPSILON, p)
            model = defineModel(objects, tcheb, p)
            results[i][j] = timeit.timeit(model.optimize, number = PRECISION)/PRECISION

    print("tableau de moyennes des temps (10 executions) selon p et n")
    print(results)
    #plt.plot(n_steps, results[-1])
    plt.plot(p_steps, results[:,-1])
    plt.ylabel('time (s)')
    plt.xlabel('values of p')
    plt.title('time for n = 25')
    plt.grid(True)

main()


import numpy as np
import skfuzzy as fuzz

# Tao cac bien trong tap mo
#   * Quality and service on subjective ranges [0, 10]
#   * Tip has a range of [0, 25] in units of percentage points
x_qual = np.arange(0, 11, 1)
x_serv = np.arange(0, 11, 1)
x_tip = np.arange(0, 26, 1)

# Thiet ke 9 so mo
qual_lo = fuzz.trimf(x_qual, [0, 0, 5])
qual_md = fuzz.trimf(x_qual, [0, 5, 10])
qual_hi = fuzz.trimf(x_qual, [5, 10, 10])
serv_lo = fuzz.trimf(x_serv, [0, 0, 5])
serv_md = fuzz.trimf(x_serv, [0, 5, 10])
serv_hi = fuzz.trimf(x_serv, [5, 10, 10])
tip_lo = fuzz.trimf(x_tip, [0, 0, 13])
tip_md = fuzz.trimf(x_tip, [0, 13, 25])
tip_hi = fuzz.trimf(x_tip, [13, 25, 25])

# Cac ham mo hoa
qual_level_lo = fuzz.interp_membership(x_qual, qual_lo, 9.)
qual_level_hi = fuzz.interp_membership(x_qual, qual_hi, 9.)
serv_level_lo = fuzz.interp_membership(x_serv, serv_lo, 9.)
serv_level_md = fuzz.interp_membership(x_serv, serv_md, 9.)
serv_level_hi = fuzz.interp_membership(x_serv, serv_hi, 9.)
qual_level_md = fuzz.interp_membership(x_qual, qual_md, 9.)
# Cac luat mo
# Luat 1
active_rule1 = np.fmin(qual_level_lo, serv_level_lo)
# Luat 2
tip_activation_lo = np.fmin(active_rule1, tip_lo)
tip_activation_md = np.fmin(serv_level_md, tip_md)
# Luat 3
# Neu quality la high va service la high thi tip la high
active_rule3 = np.fmax(qual_level_hi, serv_level_hi)
tip_activation_hi = np.fmin(active_rule3, tip_hi)

# Khu mo
aggregated = np.fmax(tip_activation_lo,
                     np.fmax(tip_activation_md, tip_activation_hi))
tip = fuzz.defuzz(x_tip, aggregated, 'bisector')
tip2 = fuzz.defuzz(x_tip, aggregated, 'centroid')
print(tip, tip2)


import re
from nonebot import on_command, export, logger
from nonebot.typing import T_State
from nonebot.adapters.cqhttp.bot import Bot
from nonebot.adapters.cqhttp.event import MessageEvent, GroupMessageEvent, PrivateMessageEvent
from nonebot.adapters.cqhttp.permission import GROUP, PRIVATE_FRIEND
from nonebot.adapters.cqhttp import MessageSegment, Message
from omega_miya.utils.Omega_plugin_utils import init_export, init_permission_state
from .utils import pic_2_base64, get_saucenao_identify_result, get_ascii2d_identify_result

# Custom plugin usage text
__plugin_name__ = '识图'
__plugin_usage__ = r'''【识图助手】
使用SauceNAO/ascii2d识别各类图片、插画
群组/私聊可用

**Permission**
Friend Private
Command & Lv.50
or AuthNode

**AuthNode**
basic

**Usage**
/识图'''

# 声明本插件可配置的权限节点
__plugin_auth_node__ = [
    'basic'
]

# Init plugin export
init_export(export(), __plugin_name__, __plugin_usage__, __plugin_auth_node__)

# 注册事件响应器
search_image = on_command(
    '识图',
    aliases={'搜图'},
    # 使用run_preprocessor拦截权限管理, 在default_state初始化所需权限
    state=init_permission_state(
        name='search_image',
        command=True,
        level=50,
        auth_node='basic'),
    permission=GROUP | PRIVATE_FRIEND,
    priority=20,
    block=True)

# 修改默认参数处理
@search_image.args_parser
async def parse(bot: Bot, event: MessageEvent, state: T_State):
    args = str(event.get_message()).strip().split()
    if not args:
        await search_image.reject('你似乎没有发送有效的消息呢QAQ, 请重新发送:')
    state[state["_current_key"]] = args[0]
    if state[state["_current_key"]] == '取消':
        await search_image.finish('操作已取消')

@search_image.handle()
async def handle_first_receive(bot: Bot, event: MessageEvent, state: T_State):
    if event.reply:
        img_url = str(event.reply.message).strip()
        if re.match(r'^(\[CQ:image,file=[abcdef\d]{32}\.image,url=.+?])$', img_url):
            state['image_url'] = img_url

    args = str(event.get_plaintext()).strip().lower().split()
    if args:
        await search_image.finish('该命令不支持参数QAQ')

@search_image.got('image_url', prompt='请发送你想要识别的图片:')
async def handle_draw(bot: Bot, event: MessageEvent, state: T_State):
    if isinstance(event, GroupMessageEvent):
        group_id = event.group_id
    else:
        group_id = 'Private event'

    image_url = state['image_url']
    if not re.match(r'^(\[CQ:image,file=[abcdef\d]{32}\.image,url=.+?])$', image_url):
        await search_image.reject('你发送的似乎不是图片呢, 请重新发送, 取消命令请发送【取消】:')

    # 提取图片url
    image_url = re.sub(r'^(\[CQ:image,file=[abcdef\d]{32}\.image,url=)', '', image_url)
    image_url = re.sub(r'(])$', '', image_url)

    try:
        has_error = False
        await search_image.send('获取识别结果中, 请稍后~')
        identify_result = []
        identify_saucenao_result = await get_saucenao_identify_result(url=image_url)
        if identify_saucenao_result.success():
            identify_result.extend(identify_saucenao_result.result)
        else:
            has_error = True

        # saucenao 没有结果时再使用 ascii2d 进行搜索
        if not identify_result:
            identify_ascii2d_result = await get_ascii2d_identify_result(url=image_url)
            # 合并搜索结果
            if identify_ascii2d_result.success():
                identify_result.extend(identify_ascii2d_result.result)
            else:
                has_error = True
        if identify_result:
            for item in identify_result:
                try:
                    if type(item['ext_urls']) == list:
                        ext_urls = ''
                        for urls in item['ext_urls']:
                            ext_urls += f'{urls}\n'
                        ext_urls = ext_urls.strip()
                    else:
                        ext_urls = item['ext_urls']
                        ext_urls = ext_urls.strip()
                    img_b64 = await pic_2_base64(item['thumbnail'])
                    if not img_b64.success():
                        msg = f"识别结果: {item['index_name']}\n\n相似度: {item['similarity']}\n资源链接: {ext_urls}"
                        await search_image.send(msg)
                    else:
                        img_seg = MessageSegment.image(img_b64.result)
                        msg = f"识别结果: {item['index_name']}\n\n相似度: {item['similarity']}\n资源链接: {ext_urls}\n{img_seg}"
                        await search_image.send(Message(msg))
                except Exception as e:
                    logger.warning(f'处理和发送识别结果时发生了错误: {repr(e)}')
                    continue
            logger.info(f"{group_id} / {event.user_id} 使用searchimage成功搜索了一张图片")
            return
        elif not identify_result and has_error:
            await search_image.send('识图过程中获取信息失败QAQ, 请重试一下吧')
            logger.info(f"{group_id} / {event.user_id} 使用了searchimage, 但在识图过程中获取信息失败")
            return
        else:
            await search_image.send('没有找到相似度足够高的图片QAQ')
            logger.info(f"{group_id} / {event.user_id} 使用了searchimage, 但没有找到相似的图片")
            return
    except Exception as e:
        await search_image.send('识图失败, 发生了意外的错误QAQ, 请稍后重试')
        logger.error(f"{group_id} / {event.user_id} 使用命令searchimage时发生了错误: {repr(e)}")
        return


from flask_restful import Resource, reqparse
from db import query, connectToHost
import base64
import pymysql
from flask_jwt_extended import jwt_required

def convertToBlob(value):
    return base64.b64decode(value.encode('utf-8'))

"""
Using the resource in this module, admin can insert an image with select_status = 1.
The admin has to send just the request_no and the image.
All the other papers corresponding to the request_no get deleted
whether they have a select_status of 1 or not.
The entries in the requests table are deleted for a request_no, admin uploaded image is insered into requests.
Then active_exams and submissions table entries are deleted which have the request_no sent.
"""

class AdminQpRequest(Resource):

    @jwt_required
    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument('r_id', type=int, help="r_id cannot be left blank!")
        data = parser.parse_args()
        #create query string
        qstr = f""" SELECT * FROM requests where r_id = { data['r_id'] };"""
        try:
            return query(qstr)
        except:
            return {
                "message" : "There was an error connecting to the requests table while retrieving."
            }, 500

    @jwt_required
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('b_id', type=int, required=True, help="b_id cannot be left blank!")
        parser.add_argument('sem_no', type=int, required=True, help="sem_no cannot be left blank!")
        parser.add_argument('exam_type', type=str, required=True, help="exam_type cannot be left blank!")
        parser.add_argument('subtype', type=str, required=True, help="request_no cannot be left blank!")
        parser.add_argument('s_code', type=str, required=True, help="s_code cannot be left blank!")
        parser.add_argument('year', type=int, required=True, help="year cannot be left blank!")
        parser.add_argument('image', type=str, required=True, help="image cannot be left blank!")

        #parser.add_argument('select_status', type=int, required=False, default = 0)

        data = parser.parse_args()

        # a transaction is made, so not using query function from db module
        # we use connectToHost function from db module and commit explicitly
        # the query function from db module commits for each query which is not desirable in
        # a transaction sequence as follows.
        # here we execute several queries then commit.
        try:
            connection = connectToHost()

            #start connection, create cursor and execute query from cursor
            connection.begin()
            cursor = connection.cursor()

            #obtain request_no from the details provided, store in req_no

            qstr = f"""
            select DISTINCT request_no
            from timetable t
            inner join details d on (t.d_id = d.d_id)
            WHERE b_id = '{data['b_id']}' AND
            sem_no = '{data['sem_no']}' AND
            exam_type = '{data['exam_type']}' AND
            subtype = '{data['subtype']}' AND
            year = '{data['year']}' AND
            s_code = '{data['s_code']}'
            LIMIT 1;
            """

            cursor.execute(qstr)
            cursor.execute(qstr)
            result = cursor.fetchall()
            req_no = list(result[0].values())[0]

            # delete all the other entries in requests table
            # with the same request_no, whether selected or not
            qstr = f"""
            delete from requests
            where request_no = {req_no};
            """

            cursor.execute(qstr)

            #creating a tuple of values to be inserted because a formatted string is used
            #here its useful to avoid SQL syntax errors while inserting BLOB value into table
            vals_tuple = (req_no, convertToBlob(data['image']), 1 ) #set select status to 1
            #convertToBlob is used to convert base64 string to BLOB data

            qstr = f""" INSERT INTO requests (request_no, image, select_status)
                        values (%s, %s, %s); """

            cursor.execute(qstr, vals_tuple)

            # delete the corresponding entry from active_exams if paper is uploaded.
            qstr = f""" DELETE FROM active_exams
            WHERE request_no = { req_no }; """
            cursor.execute(qstr)

            # for deleting user info from submissions table
            qstr = f""" DELETE FROM User.submissions
            WHERE request_no = { req_no };
            """
            cursor.execute(qstr)

            connection.commit() #commit the changes made

            #close the cursor and connection
            cursor.close()
            connection.close()
        except IndexError:
            """
            this is to handle tuple index error
            which is raised if no data could be retrieved and stored
            where data is retrieved in this way
            result = cursor.fetchall()
            req_no = list(result[0].values())[0]
            """
            return {
                "message" : "Required data not present."
            }, 400
        except (pymysql.err.InternalError, pymysql.err.ProgrammingError, pymysql.err.IntegrityError) as e:
            return {
                "message" : "MySQL error: " + str(e)
            }, 500
        except Exception as e:
            return {
                "message" : "There was an error connecting to the requests table while inserting." + str(e)
            }, 500

        return {
            "message" : "Succesfully inserted"
        }, 200


"""You are planning to organise a flash mob dance. You have exactly s stripes. You can color any stripe in exactly one of the colours: red or yellow. You want all the participants to position themselves in a solid rectangle with n rows and m columns.

If a dancer is in the ith row and jth column you want to give them exactly i red stripes and exactly j yellow ones (1-based).

You need to give all the stripes to all the dancers.

Find the maximum number of dancers can participate, or return -1 if it is impossible to give all the stripes to the dancers.

Example

For s = 9, the output should be danceStripes(s) = 3.

You can color 3 stripes in red, and 6 stripes in yellow. The rectangle should be of the size (1, 3). The first dancer would have 1 red and 1 yellow, the second dancer - 1 red and 2 yellow, and the third dancer - 1 red and 3 yellow.

For s = 10, the output should be danceStripes(s) = -1.

It is not possible to distribute this number of stripes according to the requirements.

Input/Output

[execution time limit] 4 seconds (py)

[input] integer s

The total number of stripes (each of which can be coloured either red or yellow).

Guaranteed constraints:
1 ≤ s ≤ 10^9.

[output] integer

A maximum number of dancers."""

### Does 2^31 - 1 in about 0.01 seconds

def danceStripes(s):
    #https://oeis.org/A052146 -> Maximum number we can start before there are too many stripes
    column = int((pow(8 * s + 1, 0.5) - 3) / 2) + 1
    stripes = column + column * (column + 1) / 2
    row = 1
    dancers = -1
    while column >= row:
        if stripes < s:
            row += 1
            stripes += row * column + column * (column + 1) / 2
        else:
            if stripes == s:
                dancers = max(column * row, dancers)
            stripes -= row * column + row * (row + 1) / 2
            column -= 1
    return dancers


import os
import os.path
import shutil
import logging
import yaml
from piecrust import (
        RESOURCES_DIR, THEME_DIR, THEME_CONFIG_PATH, THEME_INFO_PATH)
from piecrust.commands.base import ChefCommand

logger = logging.getLogger(__name__)

class ThemesCommand(ChefCommand):
    def __init__(self):
        super(ThemesCommand, self).__init__()
        self.name = 'themes'
        self.description = "Manage the themes for the current website."

    def setupParser(self, parser, app):
        if app.root_dir is None:
            return

        subparsers = parser.add_subparsers()
        p = subparsers.add_parser(
                'create',
                help="Create a new theme for the current website.")
        p.add_argument(
                '--from-default',
                action='store_true',
                help=("Create a new theme by copying the default PieCrust "
                      "theme into the theme directory"))
        p.add_argument(
                'theme_name',
                help=("The name of the theme"))
        p.set_defaults(sub_func=self._createTheme)

        p = subparsers.add_parser(
                'override',
                help="Copies a theme to the website for customization.")
        p.set_defaults(sub_func=self._overrideTheme)

    def checkedRun(self, ctx):
        ctx.args.sub_func(ctx)

    def _createTheme(self, ctx):
        theme_dir = os.path.join(ctx.app.root_dir, THEME_DIR)
        if os.path.exists(theme_dir):
            logger.warning("A theme already exists, and will be overwritten. "
                           "Are you sure? [Y/n]")
            ans = input()
            if len(ans) > 0 and ans.lower() not in ['y', 'yes']:
                return 1

            shutil.rmtree(theme_dir)

        try:
            if ctx.args.from_default:
                def reporting_copy2(src, dst):
                    rel_dst = os.path.relpath(dst, ctx.app.root_dir)
                    logger.info(rel_dst)
                    shutil.copy2(src, dst)

                default_theme_dir = os.path.join(RESOURCES_DIR, 'theme')
                shutil.copytree(default_theme_dir, theme_dir,
                                copy_function=reporting_copy2)
                return 0

            logger.info("Creating theme directory.")
            os.makedirs(theme_dir)

            logger.info("Creating theme_config.yml")
            config_path = os.path.join(theme_dir, THEME_CONFIG_PATH)
            with open(config_path, 'w', encoding='utf8') as fp:
                fp.write('')

            logger.info("Creating theme_info.yml")
            info_path = os.path.join(theme_dir, THEME_INFO_PATH)
            with open(info_path, 'w', encoding='utf8') as fp:
                yaml.dump(
                        {
                            'name': ctx.args.theme_name or 'My New Theme',
                            'description': "A new PieCrust theme.",
                            'authors': ['Your Name Here <email or twitter>'],
                            'url': 'http://www.example.org'},
                        fp,
                        default_flow_style=False)
            return 0
        except:
            logger.error("Error occured, deleting theme directory.")
            shutil.rmtree(theme_dir)
            raise

    def _overrideTheme(self, ctx):
        app_dir = ctx.app.root_dir
        theme_dir = ctx.app.theme_dir
        if not theme_dir:
            logger.error("There is not theme currently applied to override.")
            return 1

        copies = []
        for dirpath, dirnames, filenames in os.walk(theme_dir):
            rel_dirpath = os.path.relpath(dirpath, theme_dir)
            for name in filenames:
                if (dirpath == theme_dir and
                        name in [THEME_CONFIG_PATH, THEME_INFO_PATH]):
                    continue
                src_path = os.path.join(dirpath, name)
                dst_path = os.path.join(app_dir, rel_dirpath, name)
                copies.append((src_path, dst_path))

        conflicts = []
        for c in copies:
            if os.path.exists(c[1]):
                conflicts.append(c[1])
        if conflicts:
            logger.warning("Some website files will be overwritten:")
            for c in conflicts:
                logger.warning(os.path.relpath(c, app_dir))
            logger.warning("Are you sure? [Y/n]")
            ans = input()
            if len(ans) > 0 and ans.lower() not in ['y', 'yes']:
                return 1

        for c in copies:
            logger.info(os.path.relpath(c[1], app_dir))
            if not os.path.exists(os.path.dirname(c[1])):
                os.makedirs(os.path.dirname(c[1]))
            shutil.copy2(c[0], c[1])


# -*- coding: cp1252 -*-
# Et program for å trekke tilfeldige lodd

from random import *
from graphics import *

options = open("options.cfg", "r+")
valg = options.readlines()
valg = [eval(x) for x in valg]
options.close()
# valg = [xmax, ymax, årefra, åretil, bøker, loddperbok, laveste, fem?]
# vil inkl. en ekstra linje i filen

class Bok:

    def __init__(self, win):
        self.trukket = []
        self.fra = 1
        self.til = valg[4] + 1 # antall bøker
        self.win = win
        self.rekke = -1
        self.fil = open("trekt_bok.txt","a")

        self.head = Text(Point(0.1, 1), "Loddbøker")
        self.head.setStyle("bold")
        self.head.setTextColor(color_rgb(21,71,9))
        self.head.setSize(26)
        self.head.draw(win)

        self.boktekst = Text(Point(0.2, 0.8), " Bok: ")
        self.loddtekst = Text(Point(0.2, 0.7), "Lodd: ")
        self.boktekst.setSize(36)
        self.loddtekst.setSize(36)
        self.boktekst.draw(win)
        self.loddtekst.draw(win)

        self.displaytekst = Text(Point(0.5, 0.5), "")
        self.displaytekst.setSize(50)
        self.displaytekst.draw(win)

        self.entry = Entry(Point(0.1, 0.1), 15)
        self.entry.setFill("light grey")
        self.entry.setTextColor("dark grey")
        self.entry.draw(win)

    def __del__(self):
        self.fil.close()

    def trekk(self):
        self.displaytekst.setText("")
        lodd = [randrange(self.fra, self.til), randrange(1,valg[5])]

        # Er loddet gyldig? Nei -> finn gyldig
        if len(self.trukket) >= 500*(self.til - self.fra):
                return False
        while lodd in self.trukket:
            lodd = [randrange(self.fra, self.til), randrange(1,valg[5])]

        # Nå har vi funnet gyldig lodd
        self.trukket.append(lodd)
        self.fil.write("bok: %d, lodd: %d\n" % (lodd[0], lodd[1]))
        return lodd

    def forrige(self):
        self.displaytekst.setText("")
        self.rekke -= 1
        try:
            return self.trukket[self.rekke]
        except:
            self.rekke += 1
            return False

    def neste(self):
        self.displaytekst.setText("")
        self.rekke += 1
        try:
            return self.trukket[self.rekke]
        except:
            self.rekke -= 1
            return False

    def oppdater(self, a):
        if type(a) == type("a"):
            self.loddtekst.setText("Feil!")
            self.boktekst.undraw()

        self.boktekst.setText(" Bok: %2d" % a[0])
        self.loddtekst.setText("Lodd: %3d" % a[1])

    def navn(self):
        navn = self.entry.getText()
        self.displaytekst.setText(navn)
        self.entry.setText("")

class Are:

    def __init__(self, win):
        self.win = win
        self.fra = valg[2]
        self.til = valg[3] + 1
        self.trukket = []
        self.fil = open("trekt_are.txt", "a")

        self.head = Text(Point(0.1, 1), "ÅRESALG")
        self.head.setStyle("bold")
        self.head.setTextColor(color_rgb(21,71,9))
        self.head.setSize(26)
        self.head.draw(win)

##        self.vinnernr = Text(Point(0.3, 0.87), "")
##        self.vinnernr.setSize(30)
##        self.vinnernr.draw(win)

        if valg[7]: # fem lodd/åre
            self.text1 = Text(Point(0.37, 0.51), "")
            self.text1.setSize(27)
            self.text1.setStyle("bold")
            self.text1.setTextColor(color_rgb(21,71,9))
            self.text1.draw(win)

        else:
            self.text1 = Text(Point(0.35, 0.56), "")
            self.text1.setSize(26)
            self.text1.setStyle("bold")
            self.text1.setTextColor(color_rgb(21,71,9))
            self.text1.draw(win)

        self.text2 = Text(Point(0.35, 0.44), "")
        self.text2.setSize(26)
        self.text2.setStyle("bold")
        self.text2.setTextColor(color_rgb(21,71,9))
        self.text2.draw(win)

        self.hovedtall = Text(Point(0.48, 0.8), "")
        self.hovedtall.setSize(100)
        self.hovedtall.setFace("times roman")
        self.hovedtall.draw(win)

        self.logo = Image(Point(0.98, 0.86), "HML_logo_Farge2.gif")
        self.logo.draw(win)

        # for å gå tilbake til tidligere lodd
        self.rekke = -1

    def __del__(self):
        self.fil.close()

##    def activate_vinnernr(self):
##        self.vinnernr.setText("vinnernr: ")

    def undraw(self):
        self.head.undraw()
        self.text1.undraw()
        self.text2.undraw()
        self.hovedtall.undraw()

    def trekk(self):
        self.rekke = -1
        lodd = randrange(self.fra, self.til)

        if valg[6]: # 1 -> 10, tror det er denne
            if not lodd % 10:
                lower = lodd - 9
                higher = lodd
            lower = lodd - lodd % 10 + 1
            higher = lodd - lodd % 10 + 10
        else: # 0 - 9
            lower = lodd - lodd % 10
            higher = lodd - lodd % 10 + 9

        while lodd in self.trukket:
            lodd = randrange(self.fra, self.til)
            # 20 % lavere for hver åre som er trukket
            for i in trukket:
                if lower < i < higher:
                    if 0.8 < random:
                        lodd = trukket[0] # da kjører vi på nytt

            if len(self.trukket) == (self.til - self.fra):
                # tom for lodd
                return False

        self.trukket.append(lodd)
        self.fil.write("Åre: %d\n" % (lodd))
        return lodd

    def forrige(self):
        self.rekke -= 1
        try:
            return self.trukket[self.rekke]
        except:
            self.rekke += 1
            return False

    def neste(self):
        self.rekke += 1
        try:
            return self.trukket[self.rekke]
        except:
            self.rekke -= 1
            return False

    def oppdater(self, a):
        # a = 5463, 124, ...
        if type(a) == type("a"):
            self.hovedtall.setText(a)
            return True

        if valg[7]: # fem lodd/åre
            if valg[6]: # 1 -> 5
                if a%10:
                    b = a%10
                else:
                    b = a%10+5
                if a%10 < 6:
                    tall1 = range(a-b+1, a+6-b)
                else:
                    tall1 = range(a-b+6, a-b+11)
                #tall2 = range(a-b+6, a-b+11)
            else: # 0 -> 4
                b = a%10
                if a%10 < 5:
                    tall1 = range(a-b, a-b+5)
                else:
                    tall1 = range(a-b+5, a-b+10)
                #tall2 = range(a-b+5, a-b+10)

            tall1 = ["%5s" % str(x) for x in tall1]
            #tall2 = ["%5s" % str(x) for x in tall2]

            self.text1.setText("   ".join(tall1))
            #self.text2.setText("   ".join(tall2))

        else: # 10 lodd/åre
            if not valg[6]: # 1 -> 10
                if a%10:
                    b = a%10
                else:
                    b = a%10+10
                tall1 = range(a-b+1, a+6-b)
                tall2 = range(a-b+6, a-b+11)
            else: # 0 -> 9
                b = a%10
                tall1 = range(a-b, a-b+5)
                tall2 = range(a-b+5, a-b+10)

            tall1 = ["%5s" % str(x) for x in tall1]
            tall2 = ["%5s" % str(x) for x in tall2]

            self.text1.setText("   ".join(tall1))
            self.text2.setText("   ".join(tall2))

        self.hovedtall.setText(str(a))

    def reset(self):
        self.trukket = []

def main():
    # print "Velkommen til lodd."
    xmax = valg[0]
    ymax = valg[1]
    win = GraphWin("Lodd", xmax, ymax)
    win.setCoords(0.0, 0.0, 1.1, 1.05)

    are = Image(Point(0.5, 0.5), "are-medium.gif")
    are.draw(win)

    buttons = draw_partial_screen(win)

    lodd = Are(win)

    while True:
        mus = checkmouse(win, buttons)
        if mus == 1:
            # nytt lodd
##            lodd.activate_vinnernr()
            vinner = lodd.trekk()
            if vinner: lodd.oppdater(vinner)
            else:
                lodd.oppdater("TOMT")
        elif mus == 2:
            # Forrige lodd
            vinner = lodd.forrige()
            if vinner: lodd.oppdater(vinner)
        elif mus == 3:
            vinner = lodd.neste()
            if vinner: lodd.oppdater(vinner)
        elif mus == 4:
            are.undraw()
            lodd.undraw()
            loddbok(win, buttons)
        elif mus == 5:
            win.close()
            return 0

def loddbok(win, buttons):
    lodd = Bok(win)
    g = True

    while g:
        mus = checkmouse(win, buttons)
        if mus == 1:
            vinner = lodd.trekk()
            if vinner: lodd.oppdater(vinner)
            else:
                lodd.oppdater("TOMT")
        elif mus == 2:
            vinner = lodd.forrige()
            if vinner: lodd.oppdater(vinner)
        elif mus == 3:
            vinner = lodd.neste()
            if vinner: lodd.oppdater(vinner)
        elif mus == 4:
            win.close()
            main()
        elif mus == 5:
            win.close()
            return 0
        else:
            lodd.navn()

def draw_partial_screen(win):

    fyll = Rectangle(Point(0.0, 0.0), Point(1.1, 0.06))
    fyll.setFill("light grey")
    fyll.setWidth(0)
    fyll.draw(win)

    buttons = [False]*5
    button_text = [False]*5
    labels = ["Nytt lodd", "Forrige lodd", "Neste lodd", "Modus", "Avslutt"]
    for i in range(5):
        buttons[i] = Rectangle(Point(0.09+0.2*i,0.0), Point(0.25 + 0.2*i, 0.05))
        buttons[i].setWidth(0)
        buttons[i].setOutline("light gray")
        buttons[i].draw(win)

        button_text[i] = Text(Point(0.17 + 0.2*i, 0.025), labels[i])
        button_text[i].setTextColor("dark grey")
        button_text[i].setSize(18)
        button_text[i].draw(win)

    return buttons

def checkmouse(win, buttons):
    p = win.getMouse()
    p = [p.getX(), p.getY()]
    b = []
    for i in buttons:
        b.append([i.getP1(), i.getP2()])
    b = [[[x[0].getX(), x[0].getY()], [x[1].getX(), x[1].getY()]] for x in b]

    i = 1
    for each in b:
        if (each[0][0] < p[0] < each[1][0]) and \
                (each[0][1] < p[1] < each[1][1]):
            return i
        i += 1
    return False

main()


import sys, os.path

import Version

def httpHeaders(type = "text/html; charset='utf-8'"):
    h = "Content-Type: %s\n" % type
    return h + "\n"

def htmlHead(params = { }):
    h = """<?xml version=\"1.0\"?>
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"""
    h += ""
    h += """
<title>amaroK juKebox """ + Version.Version + """</title>"""
    if params.has_key('style'):
        for s in params['style']:
            h += "<link rel='stylesheet' type='text/css' href='%s' />" % s
    if params.has_key('markup'):
        for s in params['markup']:
            h += s
    h += ""
    h += ""
    return h

def htmlTail():
    h = "
"
    h += "
Controls
"
    h += "<address>Home (amaroK juKebox " + Version.Version + ")</address>"
    h += ""
    h += ""
    return h