from sanic import Sanic
from sanic import Blueprint
import time, json as jsonbase, re,logging, sys
from logging import StreamHandler
from sanic.response import json
from controller.config import HOST_URL,DB_CONFIG_PRE
from controller.utils.db_conection.oracle_db.query import create_pools,get_items
from controller.utils.httputils.httputils import ClientRequest
from controller.utils.shilian import call_api,save_xujiadan
conf_format =  ' [ %(asctime)-15s ]  - %(name)s -   %(levelname)s -  %(pathname)s[line : %(lineno)d] - FUNNAME : [%(funcName)s]  -  MESSAGE : %(message)s  	'
app = Sanic(__name__)
url_prefix = '/api/common'
bp = Blueprint(__name__)
bp.url_prefix = url_prefix

logging.basicConfig(
    level=logging.INFO,
    format=conf_format)
logger = logging.getLogger(__name__)

httputils = ClientRequest()
request_method = {"POST": httputils.post, "GET": httputils.get}

# API detail
@bp.route('/<name:[A-Za-z0-9/._]+>', methods=["OPTIONS"])
async def detail(request, name):
    result = await get_items(app.pool, 'tp_api', {"name": name})
    return json({"status":0,"data":result})

# API unified call method
@bp.route('/<name:[A-Za-z0-9/._]+>', methods=["POST"])
async def detail(request, name):
    '''
    :param request: request info
    :param name: request api name
    :return: api response info
    '''

    result = await get_items(app.pool, 'tp_api', {"name": name})
    print('世聯估價',"------------------------"+name,result)
    if result:
        params = request.json
        result = result[0]
        x = len(result.get('params'))
        result.get('params').update(params)
        y = len(result.get('params'))
        if x > y:
            return json({"status": 1, "data": "", "msg": "传入参数有误"})
        try:

            print(result.get("name")[0:2], 'result.get("name")[0:2]')
            if result.get("name")[0:2]=="sl":
                url=result.get("url")
                if result.get("name")=="sl_loupan" and x==2:
                    url=url+'/{}/{}'.format(params.get("city_id"), params.get("name"))
                if result.get("name")=="sl_gujia" and x==5:
                    url=url+'/{}/{}/{}/{}/{}'.format(params.get("cid"),params.get("bid"),params.get("hid"),params.get("area"),params.get("case_id"))
                if result.get("name")=="sl_loudong" and x==1:
                    url=url+'/{}'.format(params.get("cid"))
                if result.get("name")=="sl_fanghao" and x==1:
                    url=url+'/{}'.format(params.get("bid"))
                print('------------main',url)
                data=await call_api(url,method="get")
                return json(data)
            else:
                result = await request_method[result['http_method']](HOST_URL+result.get("url"), data=jsonbase.dumps(params), headers={"Content-Type": "application/json"})
        except Exception as e:
            return json({"status": 1, "msg": f"访问出错:{e}", "data": None})
        if result and result.headers['Content-Type'] in ["text/html","text/html; charset=utf-8"] :
            pattern = re.compile('.*?<center><h1>(.*?)<.*?')
            html_page =  await result.text()
            print(type(html_page), html_page)
            match = re.findall(pattern,html_page)
            if match:
                return json({"status":1, "msg":match[0],"data":None})
            pattern = re.compile('.*?<b>InterfaceError(.*?)<.*?')
            match = re.findall(pattern, html_page)
            if match:
                return json({"status": 1, "msg": match[0], "data": None})

            return json({"status": 1, "msg": html_page, "data": None})
        elif result and result.headers['Content-Type'] in ["application/json", "text/plain; charset=utf-8"]:
            temp_v = await result.text()
            print(await result.text())
            logger.info(await result.text(),'------------------======',result.headers['Content-Type'],  result)
            response_data = await result.json()
            return json({"status": 0, "msg":"获取成功","data":response_data})

        else:
            return json({"status": 0, "msg": f"不支持的返回数据类型,:{result.headers['Content-Type']}", "data": None})
    else:

        return json({"status":1,"data":None, "msg":"该接口不存在"})

@app.listener('before_server_start')
async def register_db(app, loop):
    '''
    :param app: sanic main start
    :param loop: uvloop
    :return: None
    '''
    app.pool = await create_pools(loop, **DB_CONFIG_PRE)
    print(app.pool)

# async def is_xunjiadan(case_id):
#     result = await sl_get_price(case_id)
#     if not result:
#         return False
#     if result.get("ReturnCode") not in (16, 17, 18):
#         await is_xunjiadan(case_id)
#     # if result.get("ReturnCode") == 18:
#     #     return False
#     return True

app.blueprint(bp)
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9881, debug=True)
    print('xxxx')


# -*- encoding: utf-8 -*-
import requests
import os.path
import json
import sys

def uploadImage(smms_auth,filename,proxies_s):

    headers = {
        "Authorization": smms_auth
    }
    proxies=None
    if proxies_s is None:
        proxies=None
    else:
        proxies={
            'http':proxies_s,
            'https':proxies_s
        }
    files={'smfile':(os.path.basename(filename),open(filename,'rb'))}

    with requests.session().request("POST", "https://sm.ms/api/v2/upload",
                                    headers=headers,proxies=proxies,
                                    files=files) as resp:
        print(resp.text)

def main(smms_auth,filename,proxies_s):
    uploadImage(smms_auth,filename,proxies_s)

if __name__ == '__main__':
    if len(sys.argv) <=2: sys.exit(0)
    if len(sys.argv) == 4:
        main(sys.argv[1],sys.argv[2],sys.argv[3])
    else:
        main(sys.argv[1],sys.argv[2],None)


from src.Account.Account import Account
from src.Vault.VaultMenu import VaultMenu
from src.Session import SESSIONS

def main():
    while True:
        if len(SESSIONS)==0:
            vault = VaultMenu()
            vault.init()
        else:
            account=Account()
            print(account.display())

main()


import math
import matplotlib.pyplot as plt

def r1 (t):
    return 2.0 + math.cos(3.0*t)

def r2(t):
    return 2.0 - math.exp(t)

A = []
B = []
C = []
res = []
i = -10.0
while (i < 4.0):
    A.append (r1(i))
    B.append (r2(i))
    C.append (i)
    i = i+0.001
    if ( abs((r1(i) - r2(i))) < 0.001 ):
        res.append(r1(i))

print("los puntos de interseccion son: ", res)
plt.plot(C,A, color='red')
plt.plot(C,B, color='blue')
plt.show()


import numpy as np

def rolling_window(input_array, size_kernel, stride, print_dims = True):
    """Function to get rolling windows.

    Arguments:
        input_array {numpy.array} -- Input, by default it only works with depth equals to 1.
                                      It will be treated as a (height, width) image. If the input have (height, width, channel)
                                      dimensions, it will be rescaled to two-dimension (height, width)
        size_kernel {int} -- size of kernel to be applied. Usually 3,5,7. It means that a kernel of (size_kernel, size_kernel) will be applied
                             to the image.
        stride {int or tuple} -- horizontal and vertical displacement

    Keyword Arguments:
        print_dims {bool} -- [description] (default: {True})

    Returns:
        [list] -- A list with the resulting numpy.arrays
    """
    # Check right input dimension
    assert(len(input_array.shape) in set([1,2])), "input_array must have dimension 2 or 3. Yours have dimension {}".format(len(input_array))

    if input_array.shape == 3:
        input_array = input_array[:,:,0]

    # Stride: horizontal and vertical displacement
    if isinstance(stride,int):
        sh, sw = stride, stride
    elif isinstance(stride,tuple):
        sh, sw = stride

    # Input dimension (height, width)
    n_ah, n_aw = input_array.shape

    # Filter dimension (or window)
    n_k  = size_kernel

    dim_out_h = int(np.floor( (n_ah - n_k) / sh + 1 ))
    dim_out_w = int(np.floor( (n_aw - n_k) / sw + 1 ))

    # List to save output arrays
    list_tensor = []

    # Initialize row position
    start_row = 0
    for i in range(dim_out_h):
        start_col = 0
        for j in range(dim_out_w):
            sub_array = []
            # Get one window
            sub_array.append(input_array[start_row:(start_row+n_k), start_col:(start_col+n_k)])
            sub_array.append(start_row)
            sub_array.append(start_col)
            # Append sub_array
            list_tensor.append(sub_array)
            start_col += sw
        start_row += sh

    if print_dims:
        print("- Input tensor dimensions -- ", input_array.shape)
        print("- Kernel dimensions -- ", (n_k, n_k))
        print("- Stride (h,w) -- ", (sh, sw))
        print("- Total windows -- ", len(list_tensor))

    return list_tensor


# -*- coding: utf-8 -*-
from django.db import models
from intelligent_home.components.device_management.models import Device, Module
from homepage import Homepage

class WidgetManager(models.Manager):

    def create(self, homepage, device, module, size, bar):
        widget = Widget(
            homepage=homepage,
            device=device,
            module=module,
            size=size,
            bar=bar,
            priority=homepage.get_next_available_widget_priority(bar)
        )
        widget.save()
        return widget

class Widget(models.Model):

    # Choices
    DEFAULT_SIZE = 'big'
    SIZE_CHOICES = (
        ('big', 'Duży'),
        ('medium', 'Średni'),
        ('small', 'Mały'),
    )

    DEFAULT_BAR = 'left'
    BAR_CHOICES = (
        ('left', 'Po lewej'),
        ('right', 'Po prawej'),
    )

    # Attributes
    size = models.CharField(max_length=6, choices=SIZE_CHOICES, default=DEFAULT_SIZE)
    bar = models.CharField(max_length=5, choices=BAR_CHOICES, default=DEFAULT_BAR)
    priority = models.PositiveIntegerField()

    # Relations
    homepage = models.ForeignKey(Homepage)
    device = models.ForeignKey(Device, blank=True, null=True)
    module = models.ForeignKey(Module, blank=True, null=True)

    # Manager
    objects = WidgetManager()

    # Meta
    class Meta:
        app_label = 'homepage'

    # Model utilities
    def move_up(self):
        if self.priority == 1:
            return False

        self.priority -= 1
        self.save()

        for widget in self.homepage.widget_set.filter(bar=self.bar).order_by('priority'):
            if widget.pk != self.pk and widget.priority == self.priority:
                widget.priority += 1
                widget.save()

        return True

    def move_down(self):
        if self.priority == self.homepage.widget_set.filter(bar=self.bar).order_by('-priority').first().priority:
            return False

        self.priority += 1
        self.save()

        for widget in self.homepage.widget_set.filter(bar=self.bar).order_by('priority'):
            if widget.pk != self.pk and widget.priority == self.priority:
                widget.priority -= 1
                widget.save()

        return True


# subsribe to matches

import asyncio
from datetime import datetime
import sys
from copra.websocket import Channel, Client

# class Tick:
#     def __init__(self, tick_dict):
#         self.product_id = tick_dict['product_id']
#         self.best_bid = float(tick_dict['best_bid'])
#         self.best_ask = float(tick_dict['best_ask'])
#         self.price = float(tick_dict['price'])
#         self.side = tick_dict['side']
#         self.size = float(tick_dict['last_size'])
#         self.time = datetime.strptime(tick_dict['time'], '%Y-%m-%dT%H:%M:%S.%fZ')

#     @property
#     def spread(self):
#         return self.best_ask - self.best_bid

#     def __repr__(self):
#         rep  = "{}\t\t\t\t{}\n".format(self.product_id, self.time)
#         rep += "=============================================================\n"
#         rep += "   Price: ${:.2f}\tSize:{:.8f}\tSide:{: >5}\n".format(self.price, self.size, self.side)
#         rep += "Best ask: ${:.2f}\tBest bid: ${:.2f}\tSpread: ${:.2f}\n".format(self.best_ask, self.best_bid, self.spread)
#         rep += "=============================================================\n"
#         return rep

class Match(Client):
    def on_message(self, message):
        for f in message:
            print(f, " : ", message[f])
        print("=============================================================\n")

product_id = sys.argv[1]
loop = asyncio.get_event_loop()
channel = Channel('heartbeat', product_id)
matcher = Match(loop, channel)
try:
    loop.run_forever()
except KeyboardInterrupt:
    loop.run_until_complete(matcher.close())
    loop.close()


# -*- coding: utf-8 -*-
"""User models."""
import datetime
from uuid import uuid4

from flask_login import current_user

from xgaming.utils import RedisJsonModel

class Wallet(RedisJsonModel):
    """
    0: real
    1: bonus
    """

    def __init__(self, *args, **kwargs):
        fields = {
            'guid': uuid4().hex,
            'key': 'guid',
            'amount': 0.0,
            'type': 0,
            'reference': u'',
            'created_date': datetime.datetime.now()
        }
        fields.update(kwargs)
        super(Wallet, self).__init__(self, connection='REDIS_WALLET', **fields)

    def wb(self):
        return 'real_wallet_balance' if self['type'] is 0 else 'bonus_wallet_balance'

    def withdraw(self):

        if self.get('amount', 0) > 0.0:
            self['amount'] = - self['amount']

        if current_user[self.wb()] + self['amount'] < 0:
            return False

        if (self.save()):
            pipe = current_user.storage.pipeline()
            pipe.execute_command('JSON.ARRAPPEND', '{}'.format(current_user['email']), 'transactions',
                                 '"{}"'.format(self['guid']))
            pipe.execute_command('JSON.NUMINCRBY', '{}'.format(current_user['email']), '{}'.format(self.wb()),
                                 int(self['amount']))
            pipe.execute()
        return self

    def deposit(self):
        if self.get('amount', 0) <= 0.0:
            return True

        if (self.save()):
            pipe = current_user.storage.pipeline()
            pipe.execute_command('JSON.ARRAPPEND', '{}'.format(current_user['email']), 'transactions',
                                 '"{}"'.format(self['guid']))
            pipe.execute_command('JSON.NUMINCRBY', '{}'.format(current_user['email']), '{}'.format(self.wb()),
                                 int(self['amount']))
            pipe.execute()
        return self


import os, sys, argparse, pprint
from pyteaser import SummarizeUrl

pp = pprint.PrettyPrinter(indent=4)

parser = argparse.ArgumentParser()
parser.add_argument('-u', action='store', dest='url_list', help='path to url list')
results = parser.parse_args()
urls = results.url_list

if os.path.isfile(urls):
    with open(urls) as f:
        l = f.readlines()
        for url in l:
            summaries = SummarizeUrl(url)
            pp.pprint('*'*40)
            pp.pprint(summaries)


import sys
import os
import multiprocessing
import progressbar
import colorama

import ffmpeg
import meta
import my_youtube
import ffmpegrunner
import title

def usage_and_exit():
    print("""mux en/ru audio files into a Goswami Maharaj's video while adding proper title
usage: mux "yyyy-mm-dd goswamimj.mp4"
(or drag and drop the file onto me)""")
    exit()

def orig_titled(orig_mp4_filename):
    """Prepare all files in original language: m4a, mp4, mp3"""
    lang = meta.get_lang(orig_mp4_filename)

    # first we cut m4a and mp4 version sequentially because these are
    # IO-bound tasks on the single drive, so running them in parallel
    # doesn't make much sense.
    _cut_orig_m4a(orig_mp4_filename, lang, line=0)
    cut_video_filename = meta.get_work_filename(orig_mp4_filename, ' ' + lang + ' titled.mkv')
    _cut_orig_mp4_titled(orig_mp4_filename, cut_video_filename, lang, line=1)

    # And now we run two long-running tasks (uploading to youtube
    # and encoding mp3) in parallel

    p_upload_orig_mp4 = multiprocessing.Process(
        target=_upload_orig_mp4,
        kwargs={'orig_mp4_filename': orig_mp4_filename, 'cut_video_filename': cut_video_filename, 'lang': lang, 'line': 2})
    p_upload_orig_mp4.start()

    p_encode_orig_mp3 = multiprocessing.Process(
        target=_encode_orig_mp3,
        kwargs={'orig_mp4_filename': orig_mp4_filename, 'lang': lang, 'line': 3})
    p_encode_orig_mp3.start()

    p_upload_orig_mp4.join()
    p_encode_orig_mp3.join()

def _cut_orig_mp4_titled(orig_mp4_filename, cut_mp4_filename, lang, line):
    title.make_mp4_with_title(orig_mp4_filename, lang, cut_mp4_filename)

def _upload_orig_mp4(orig_mp4_filename, cut_video_filename, lang, line):
    def run(callback):
        title = meta.get_youtube_title(orig_mp4_filename, lang)
        description = meta.get_youtube_description_orig(orig_mp4_filename, lang)
        youtube_id = my_youtube.upload(
            cut_video_filename,
            title=title,
            description=description,
            lang=lang,
            update=callback)
        meta.update_yaml(orig_mp4_filename, 'youtube_id_orig', youtube_id)
    run_with_progressbar(line, run, 'upload')

def run_with_progressbar(line, run, name):
    colorama.init()
    bar = None

    def callback(curr_value, max_value):
        nonlocal bar, line
        cursor_down(line)
        if bar is None:
            bar = progressbar.ProgressBar(
                widgets=[name, ': ', progressbar.Bar(), ' ', progressbar.ETA()],
                max_value=max_value)
        bar.update(curr_value)
        cursor_up(line)

    run(callback)

    cursor_down(line)
    bar.finish()
    cursor_up(line + 1)

def _cut_orig_m4a(orig_mp4_filename, lang, line):
    cmd = ['ffmpeg', '-y',
           '-i', orig_mp4_filename]
    cmd += ffmpeg.meta_args(orig_mp4_filename, lang)
    cmd += ffmpeg.ss_args(orig_mp4_filename)
    cmd += ffmpeg.to_args(orig_mp4_filename)
    cmd += ['-c:a', 'copy', '-vn',
            meta.get_work_filename(orig_mp4_filename, ' ' + lang + '.m4a')]
    _run_ffmpeg_at_line(cmd, line, 'm4a')

def cursor_down(line):
    print('\x1b[%dB' % line, end='')

def cursor_up(line):
    print('\x1b[%dA' % line, end='')

def _run_ffmpeg_at_line(cmd, line, name):
    def run(callback):
        ffmpegrunner.run(cmd, callback)
    run_with_progressbar(line, run, name)

def _encode_orig_mp3(orig_mp4_filename, lang, line):
    cmd = ['ffmpeg', '-y',
           '-i', orig_mp4_filename,
           '-ac', '1',
           '-codec:a', 'mp3', '-b:a', '96k']
    cmd += ffmpeg.ss_args(orig_mp4_filename)
    cmd += ffmpeg.to_args(orig_mp4_filename)
    cmd += ffmpeg.meta_args(orig_mp4_filename, lang)
    cmd += [meta.get_work_filename(orig_mp4_filename, ' ' + lang + '.mp3')]
    _run_ffmpeg_at_line(cmd, line, 'mp3')

def main():
    try:
        orig_mp4_filename = sys.argv[1]
        if not os.path.isfile(orig_mp4_filename):
            print('file "%s" not found' % orig_mp4_filename)
            print('')
            usage_and_exit()
        orig_titled(orig_mp4_filename)
    except (IndexError, KeyboardInterrupt):
        usage_and_exit()

if __name__ == '__main__':
    main()


"""
https://leetcode.com/problems/product-of-array-except-self/

Given an array nums of n integers where n > 1,  return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].

Example:

Input:  [1,2,3,4]
Output: [24,12,8,6]
Constraint: It's guaranteed that the product of the elements of any prefix or suffix of the array (including the whole array) fits in a 32 bit integer.

Note: Please solve it without division and in O(n).

Follow up:
Could you solve it with constant space complexity? (The output array does not count as extra space for the purpose of space complexity analysis.)

Accepted
630,538
Submissions
1,037,576

"""

class Solution:

    #     ## O(N) solution but uses extra space
    #     def productExceptSelf(self, nums: List[int]) -> List[int]:

    #         """
    #         The idea is to build to two extra arrays such as left and right
    #         left[i]  = product of all elements left to the index i
    #         right[i] = product of all elements right to the index i

    #         """

    #         n=len(nums)
    #         left=[1]*n  ##Product of all number left of index i
    #         right=[1]*n

    #         for i in range(1,n):
    #             left[i]=left[i-1]*nums[i-1]

    #         for i in range(n-2,-1,-1):
    #             right[i]=right[i+1]*nums[i+1]

    #         result=[]

    #         for i in range(n):
    #             result.append(left[i]*right[i])

    #         return result

    ## O(N) solution but uses extra space
    def productExceptSelf(self, nums: List[int]) -> List[int]:

        """
        The idea is not to build to  extra arrays such as left ,right as above. Insted use the answer array

        """

        n = len(nums)
        result = [1] * n

        for i in range(1, n):
            result[i] = result[i - 1] * nums[i - 1]

        print(result)

        ## Instead of keepi track if right array, use a variable right to keep track of the right values.

        right = 1
        for i in range(n - 1, -1, -1):
            result[i] = result[i] * right
            right = right * nums[i]

        return result


# authors: Izzy Charlton and Lucklita Theng
# import needed libraries
import pygame
from random import randint

# initaite PyGame
pygame.init()

# setting colors for later use and the display window for the game
brown = (51, 21, 0)
white = (55, 255, 255)
green = (76, 153, 0)
blue = (0, 50, 128)

# creating a window for the game
display_surface = pygame.display.set_mode((500,500))

# create Character class which includes
# constructor and methods for Aarnie and the insects
class Character:

# constructor for characters
	def __init__(self, x, y, image, size):
		self.x = x
		self.y = y
		self.image = image
		self.size = size

# method to draw and scale the characters onto the screen
	def drawCharacter(self):
		self.image = pygame.image.load(self.image)
		self.image = pygame.transform.scale(self.image, (self.size, self.size))
# attach a rectangle object to the character image
# which allows tracking and movement of characters on screen
		self.imagerect = self.image.get_rect()
		self.imagerect.center = (self.x, self.y)
		display_surface.blit(self.image, self.imagerect)

# method to update the rectangle object within the character image
# according to the changes on the image
	def updateRect(self):
		self.imagerect.center = (self.x, self.y)
		display_surface.blit(self.image, self.imagerect)

# method to get the x-coordinate of the character
	def getX(self):
		return self.x

# method to get the y-coordinate of the character
	def getY(self):
		return self.y

# method to set a new x-coordinate for the character
	def setX(self, n):
		self.x = n

# method to set a new y-coordinate for the character
	def setY(self, n):
		self.y = n

# method to set a new image for the character
	def setImage(self, image):
		self.image = image

# method to get the radius of the size of the character
# to use for calculating distance between two objects
# needed for the collision check method between characters
	def getRadius(self):
		radius = (self.size**(1/2)) // 2
		return radius

# create class Game which includes several objects and methods
class Game:

# constructor of the Game class,
# primarily includes features of the game display
	def __init__(self, x, y, caption, color):
		self.x = x
		self.y = y
		self.caption = caption
		self.color = color

# set method to change color of the window
	def setColor(self, n):
		self.color = n

# method to draw a window for the game
	def drawWin(self):
		pygame.display.set_mode((self.x, self.y))
		pygame.display.set_caption(self.caption)
		display_surface.fill(self.color)

# method to display text inside the window of the game
# includes setting the font, size, color and location of the text
	def displayText(self, string, color, size, x, y):
		font = pygame.font.Font("freesansbold.ttf", size)
		text = font.render(string, True, color)
		textbox = text.get_rect()
		textbox.center = (x, y)
		display_surface.blit(text, textbox)

# method to display a winning screen when the player wins the game,
# which is when Aarnie reaches the top of the screen
	def showWin(self):
		self.color = white
		self.drawWin()
		self.displayText("You win! You freed Aarnie!", brown, 32, 250, 120)
		self.displayText("Press SPACE to start again", green, 25, 250, 180)
# creating Aarnie as an object within the class Character
# to be shown on the winning screen
		aarnie = Character(60, 400, "aarnie.png", 700)
		aarnie.drawCharacter()

# method to display a game-over screen when the player loses the Game
# which is when Aarnie collides with one of the bugs
	def showGameover(self):
		self.color = brown
		self.drawWin()
		self.displayText("Game Over", white, 32, 250, 150)
		self.displayText("Press SPACE to start again!", white, 25, 250, 250)
# creating the insect to appear in the game-over screen
		bug = Character(240, 370, "insect.png", 500)
		bug.drawCharacter()

# method to initiate level 1 of the game
	def level1(self):

# creating aarnie as a character to be played in the game
		aarnie = Character(300, 400, "seedshell.png", 300)
		aarnie.drawCharacter()
		pygame.display.update()
# keeps track of the number of clicks,
# and create condition for clicking to occur
		clickCount = 0
		cracked = False
# get the mouse click and its position so the user can use it to click
# on the seedshell to crack Aarnie free
		click = pygame.mouse.get_pressed()
		mouse = pygame.mouse.get_pos()

# initiating a while loop so user can click until seedshell cracks
		while cracked is False:
			for event in pygame.event.get():

# detecting the mouse click, and keeps track of clicks
				if event.type == pygame.MOUSEBUTTONDOWN:
					clickCount += 1
# sets condition for when the seed will crack (set to 7 clicks by default)
					if clickCount >= 7:
# draws a window for the text to show that seed has cracked, and Aarnie is free
						self.drawWin()
						self.displayText("Yay! Aarnie's free!", white, 25, 250, 250)
						self.displayText("Press SPACE to continue.", white, 25, 250, 150)
						aarnie.setImage("aarnie.png")
						aarnie.drawCharacter()
						pygame.display.update()

# sets condition for user to hit spacebar to continue

				if event.type == pygame.KEYDOWN and clickCount >= 7:
						if event.key == pygame.K_SPACE:
							cracked = True
							self.drawWin()
# sets condition for user to quit by clicking
# upper left window quit button
				if event.type == pygame.QUIT:
					pygame.quit()
					quit()

# method for level 2 of the game
	def level2(self):
# create a list of bugs
		bugs = []
		for i in range(4):
			bug = Character(50, 100*(i+1), "insect.png", 200)
			bugs.append(bug)
			bug.drawCharacter()
		return bugs

# method to animate the bugs
	def moveBugs(self, bugs):
# loop to move the bugs by updating the x coordinates
# and using the random integer function from the random library
# for varying speed of the bugs across the screen
		for bug in bugs:
			if bug.getX() < 450:
				ranspeed = randint(2,8)
				bug.setX(bug.getX()+ ranspeed)
			else:
				bug.setX(0)
			bug.updateRect()
		return bugs

# method to get the distance between Aarnie and bugs
# needed for collision check
	def getDist(self, player, bug):
		# the formula of the Euclidean function ((p1 - q1)^2 + (p2 - q2)^2)^(1/2)
		distance = ((player.getX()- bug.getX())**2+(player.getY()-bug.getY())**2)**(1/2)
		return distance

# writing the main function of the game,
# here lies the general structure of the game
def main():
# creating a window
	game = Game(500, 500, "Aarnie's Adventure", blue)
	game.drawWin()

	game.displayText("Aarnie's Adventure", white, 32, 250, 100)
	game.displayText("Keep clicking to free Aarnie!", white, 27, 250, 170)

# calling the function to initiate level one from the class Game
	game.level1()

# setting the condition for level 2 to run
	level2 = True
# calling level 2 objects, Aarnie and the bugs
	bugs = game.level2()
	aarnie = Character(250, 480, "aarnie.png", 350)
	aarnie.drawCharacter()
	aarnie.updateRect()
	pygame.display.update()

# creating a loop for level 2 to run
# and for user to have controls to move Aarnie
	while level2 is True:
		game.setColor(green)
		game.drawWin()
		game.displayText("Help Aarnie escape to the top!", white, 20, 250, 40)
		game.displayText("Press UP, DOWN, LEFT, RIGHT to move Aarnie.", white, 15, 250, 60)
		aarnie.updateRect()
		bugs = game.moveBugs(bugs)

# creating controls for user to move Aarnie up, down, left and right
# to avoid colliding with the bugs
# within the visible parameters of the screen
		for event in pygame.event.get():
			if event.type == pygame.KEYDOWN:
				if event.key == pygame.K_UP and aarnie.getY() > 10:
					aarnie.setY(aarnie.getY() - 30)

				if event.key == pygame.K_DOWN and aarnie.getY() < 500 :
					aarnie.setY(aarnie.getY() + 30)

				if event.key == pygame.K_LEFT and aarnie.getX() > 0 :
					aarnie.setX(aarnie.getX() - 30)

				if event.key == pygame.K_RIGHT and aarnie.getX() < 400 :
					aarnie.setX(aarnie.getX() + 30)
# allowing the user to quit by closing the window
			if event.type == pygame.QUIT:
				pygame.quit()
				quit()
		pygame.display.update()
# creating the winning condition for the game
# when Aarnie y-coordinate reaches beyond 70 on the screen (at the top)
		if aarnie.getY() < 70:
			while True:
# display winning window
				game.showWin()
				pygame.display.update()
# creates option for user to play again or they can close the window to end game
				for event in pygame.event.get():
					if event.type == pygame.KEYDOWN:
						if event.key == pygame.K_SPACE:
							main()
					if event.type == pygame.QUIT:
						pygame.quit()
						quit()

# for loop to check for collision between bugs and Aarnie
		for bug in bugs:
			distance = game.getDist(aarnie, bug)
			apart = aarnie.getRadius()+bug.getRadius()
			print(distance, apart)
			if distance <= apart + 20:
				level2 = False

# if there is a collision, the game-over window appears on the screen
	while True:
		game.showGameover()
		pygame.display.update()
# creates option for user to play again or they can close the window to end game
		for event in pygame.event.get():
			if event.type == pygame.KEYDOWN:
				if event.key == pygame.K_SPACE:
					main()
			if event.type == pygame.QUIT:
				pygame.quit()
				quit()

# running the main function
main()

# quitting pygame library once the main function runs and quitting the game
pygame.quit()
quit()

# CITATIONS:

# Kellen Dorchen helped with understanding classes and objects of the code
# as well as understanding what a "clean code" means in general
# Jackie Chan helped clearing up the clutter of tabs and spaces inconsistency

# Sources that help us understand PyGame:
# "Introduction to PyGame", pythonprogramming.net
# "Changing Class Members in Python", geeksforgeeks.org
# "Using Pygame to move your game character around", opensource.com
# "Properties vs. Getters and Setters", python-course.eu
# "How to Calculate Euclidean Distance", Sciencing.com
# "Rect Collision Response", pygame.org


from numpy import array
import numpy as np

def gaussElimin(a, b):
  n = len(b)
#Elimination Phase
  for k in range(0, n-1):
    for i in range(k+1, n):
      if a[i, k] != 0.0:
        lam = a[i, k] / a[k, k]
        a[i, k+1:n] = a[i, k+1:n] - lam * a[k, k+1:n]
        b[i] = b[i] - lam * b[k]
#Back substitution
  for k in range(n-1, -1, -1):
    b[k] = (b[k] - np.dot(a[k, k+1:n], b[k+1:n])) / a[k, k]
  return b

##module gaussElimin
a = array([[4.0, -2.0, 1.0], \
           [-2.0, 4.0, -2.0],\
           [1.0, -2.0, 4.0]])
b = array([11.0, -16.0, 17.0])
x = gaussElimin(a, b)
print(x)
input('press return')


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
import time
import csv
from selenium.webdriver.chrome.options import Options
# from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

prefs = {"download.default_directory" : '/var/www/seleniumtest/archive/'}

options = Options()
options.add_argument("--start-maximized")
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
options.add_argument("--remote-debugging-port=9222")
options.add_experimental_option("prefs",prefs)
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_argument("--silent")

browser = webdriver.Chrome('/var/www/chromedriver', options=options)

browser.get('https://www.mca.gov.in/MinistryV2/eir_archive.html')
# browser.find_element_by_class_name("rules").click()
time.sleep(5)
total_file = browser.find_element_by_id("example_info").text
total_count = total_file.split(' ')[5]
total_page = (int(total_count)//6)+1
for i in range(total_page):

	excelfiles = browser.find_elements_by_class_name("descinner")
	action = ActionChains(browser);
	for excelfile in excelfiles:
		excelfile.click()
		time.sleep(2)

		print(excelfile.text)
	i+=1;
	pagination = browser.find_element_by_id("example_next")
	browser.execute_script("arguments[0].click();", pagination)
	time.sleep(10)


from math import cos, sin, radians, floor
from server.cords.scale_cords import scale_coords

def rotate(x: list, y: list, angle: float = 0):
    if len(x) != len(y):
        raise ValueError('x should be as long as y')

    angle = radians(angle)

    for i in range(len(x)):
        x[i] = floor(x[i] * cos(angle) - y[i] * sin(angle))
        y[i] = floor(x[i] * sin(angle) + y[i] * cos(angle))

    x = scale_coords(x)
    y = scale_coords(y)

    return x, y


#!/usr/bin/python3
'''use requests to fetch content from json'''
import requests
import sys

if __name__ == "__main__":
    hurl = 'http://0.0.0.0:5000/search_user'
    try:
        if len(sys.argv) == 1:
            print("No result")
        else:
            result = requests.post(hurl, data={'q': sys.argv[1]}).json()
            if not bool(result):
                print("No result")
            else:
                print("[{}] {}".format(result['id'], result['name']))
    except:
        print("Not a valid JSON")


try:
  from hashlib import md5
except ImportError:
  from md5 import md5
import bisect
from binascii import crc32

def md5_key(key):
    big_hash = md5( str(key) ).hexdigest()
    return int(big_hash[:4], 16)

class ConsistentHashRing:
  def __init__(self, nodes, replica_count=100, hash_type=None):
    self.ring = []
    self.nodes = set()
    self.replica_count = replica_count
    self.hash_type = hash_type

    for node in nodes:
      self.add_node(node)

    # Precompute hash function
    if self.hash_type in (None, 'md5'):
        self.hash_function = md5_key
    elif self.hash_type == 'crc32':
        # The md5 is dropped into the range of 0xffff. Let's
        # make sure crc is too
        self.hash_function = lambda key : (crc32(key) & 0xffff)
    else:
        raise Exception('Unsupported hash type: %s' % self.hash_type)

  def compute_ring_position(self, key):
    return self.hash_function(key)

  def add_node(self, node):
    self.nodes.add(node)
    for i in range(self.replica_count):
      replica_key = "%s:%d" % (node, i)
      position = self.compute_ring_position(replica_key)
      entry = (position, node)
      bisect.insort(self.ring, entry)

  def remove_node(self, node):
    self.nodes.discard(node)
    self.ring = [entry for entry in self.ring if entry[1] != node]

  def get_node(self, key):
    assert self.ring
    node = None
    node_iter = self.get_nodes(key)
    node = node_iter.next()
    node_iter.close()
    return node

  def get_nodes(self, key):
    assert self.ring
    nodes = set()
    position = self.compute_ring_position(key)
    search_entry = (position, None)
    index = bisect.bisect_left(self.ring, search_entry) % len(self.ring)
    last_index = (index - 1) % len(self.ring)
    while len(nodes) < len(self.nodes) and index != last_index:
      next_entry = self.ring[index]
      (position, next_node) = next_entry
      if next_node not in nodes:
        nodes.add(next_node)
        yield next_node

      index = (index + 1) % len(self.ring)


from django.urls import path
from .views import *
from django.contrib.auth.models import User

urlpatterns = [
	path('', vista_horarios),
	path('base/', vista_base, name = "vista_base"),
    path('horarios/', vista_horarios, name = "vista_horarios"),
    path('usuario/', vista_usuario, name = "vista_usuario"),
    path('ejercicio/', vista_ejercicio, name = "vista_ejercicio"),
    path('recepcionista/', vista_recepcionista, name = "vista_recepcionista"),
    path('gym/', vista_gym, name = "vista_gym"),
    path('agregar_usuario/', vista_agregar_usuario, name = "vista_agregar_usuaario"),
    path('agregar_ejercicio/', vista_agregar_ejercicio, name = "vista_agregar_ejercicio"),
    path('ver_ejercicio/<int:id_prod>/', vista_ver_ejercicio, name = "vista_ver_ejercicio"),
    path('ver_usuario/<int:id_prod>/', vista_ver_usuario, name = "vista_ver_usuario"),
    path('ver_recepcionista/<int:id_prod>/', vista_ver_recepcionista, name = "vista_ver_recepcionista"),
    path('ver_gym/<int:id_prod>/', vista_ver_gym, name = "vista_ver_gym"),
    path('ver_horarios/<int:id_prod>/', vista_ver_horarios, name = "vista_ver_horarios"),

    path('login/', vista_login, name = "vista_login"),
    path('register/', vista_register, name = "vista_register"),
]


# -*- coding: utf-8 -*- #
# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Integration tests for creating/using/deleting snapshots."""

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import contextlib

from googlecloudsdk.calliope import base
from tests.lib import e2e_utils
from tests.lib import test_case
from tests.lib.surface.compute import e2e_test_base
from tests.lib.surface.compute import utils

class _SnapshotsTestBase(e2e_test_base.BaseTest):

  def GetResourceName(self):
    return next(e2e_utils.GetResourceNameGenerator(
        prefix='gcloud-compute-test-snapshot', sequence_start=1))

  @contextlib.contextmanager
  def _CreateDisk(self):
    disk_name = self.GetResourceName()
    try:
      self.Run('compute disks create {0} --image-family {1} '
               '--image-project debian-cloud --zone {2}'
               .format(disk_name, utils.DEBIAN_IMAGE_FAMILY, self.zone))
      yield disk_name
    finally:
      self.Run('compute disks delete {0} --zone {1} --quiet'
               .format(disk_name, self.zone))

  @contextlib.contextmanager
  def _CreateSnapshot(self, disk_name, use_storage_location=False,
                      guest_flush=False):
    snapshot_name = self.GetResourceName()
    extra_flags = ''
    if guest_flush:
      extra_flags = '--guest-flush'
    try:
      if use_storage_location:
        self.Run('compute disks snapshot {0} --snapshot-names {1} --zone {2} '
                 '--storage-location {3} {4}'.format(
                     disk_name, snapshot_name, self.zone,
                     self.storage_location, extra_flags))
      else:
        self.Run('compute disks snapshot {0} --snapshot-names {1} --zone {2} '
                 '{3}'.format(
                     disk_name, snapshot_name, self.zone, extra_flags))
      yield snapshot_name
    finally:
      self.Run('compute snapshots delete {0} --quiet'.format(snapshot_name))

  @contextlib.contextmanager
  def _CreateDiskFromSnapshot(self, snapshot_name):
    disk_name = self.GetResourceName()
    try:
      self.Run('compute disks create {0} --source-snapshot {1} --zone {2}'
               .format(disk_name, snapshot_name, self.zone))
      yield disk_name
    finally:
      self.Run('compute disks delete {0} --zone {1} --quiet'
               .format(disk_name, self.zone))

  @contextlib.contextmanager
  def _CreateInstance(self, extra_flags=''):
    instance_name = self.GetResourceName()
    try:
      self.Run('compute instances create {0} --zone {1} {2}'
               .format(instance_name, self.zone, extra_flags))
      yield instance_name
    finally:
      self.Run('compute instances delete {0} --zone {1} --quiet'.format(
          instance_name, self.zone))

class SnapshotsTestGA(_SnapshotsTestBase):

  def testSnapshots(self):
    with self._CreateDisk() as disk_name, \
         self._CreateSnapshot(disk_name) as snapshot_name, \
         self._CreateDiskFromSnapshot(snapshot_name) as disk_name2, \
         self._CreateInstance('--disk name={},boot=yes'
                              .format(disk_name2)) as instance_name:
      # Check snapshot properties
      self.Run('compute snapshots describe {0}'.format(snapshot_name))
      self.AssertNewOutputContains('name: {0}'.format(snapshot_name),
                                   reset=False)
      self.AssertNewOutputContains('status: READY')

      # Check disk from snapshot properties
      self.Run('compute disks describe {0} --zone {1}'
               .format(disk_name2, self.zone))
      self.AssertNewOutputContains('global/snapshots/{0}'
                                   .format(snapshot_name),
                                   reset=False)
      self.AssertNewOutputContains('name: {0}'.format(disk_name2))

      # Check instance properties
      self.Run('compute instances describe {0} --zone {1}'
               .format(instance_name, self.zone))
      self.AssertNewOutputContains('zones/{0}/disks/{1}'
                                   .format(self.zone, disk_name2),
                                   reset=False)
      self.AssertNewOutputContains('status: RUNNING')
    # Check resources were cleaned up.
    self.Run('compute snapshots list')
    self.AssertNewOutputNotContains(snapshot_name)
    self.Run('compute disks list')
    self.AssertNewOutputNotContains(disk_name, reset=False)
    self.AssertNewOutputNotContains(disk_name2)

  def testWindowsVssSnapshot(self):
    extra_flags = '--image-project windows-cloud --image-family windows-2012-r2'
    with self._CreateInstance(extra_flags) as instance_name:
      # Create Windows Instance and wait for it to boot
      message = 'Instance setup finished.'
      booted = self.WaitForBoot(instance_name, message, retries=10,
                                polling_interval=60)
      self.assertTrue(booted, msg='Timed out waiting for Windows to boot.')
      # Snapshot Instance with VSS
      with self._CreateSnapshot(
          instance_name, guest_flush=True) as snapshot_name:
        # Check that snapshot exists
        self.Run('compute snapshots describe {0}'.format(snapshot_name))
        self.AssertNewOutputContains('name: {0}'.format(snapshot_name),
                                     reset=False)
        self.AssertNewOutputContains('status: READY')

class SnapshotsTestAlpha(_SnapshotsTestBase):

  def SetUp(self):
    self.track = base.ReleaseTrack.ALPHA
    self.storage_location = 'us-west1'

  def testStorageLocation(self):
    with self._CreateDisk() as disk_name, \
         self._CreateSnapshot(
             disk_name, use_storage_location=True) as snapshot_name:
      self.Run('compute snapshots describe {0}'.format(snapshot_name))
      self.AssertNewOutputContains('name: {0}'.format(snapshot_name),
                                   reset=False)
      self.AssertNewOutputContains("""storageLocations:
                                     - {0}""".format(self.storage_location),
                                   reset=False, normalize_space=True)
      self.AssertNewOutputContains('status: READY')

class SnapshotsLabelsTest(_SnapshotsTestBase):

  def SetUp(self):
    self.track = base.ReleaseTrack.GA

  def GetResourceName(self):
    return next(e2e_utils.GetResourceNameGenerator(
        prefix='gcloud-compute-test-snapshot-labels'))

  def testAddRemoveLabels(self):
    with self._CreateDisk() as disk_name, \
         self._CreateSnapshot(disk_name) as snapshot_name:
      add_labels = (('x', 'y'), ('abc', 'xyz'))
      self.Run('compute snapshots add-labels {0} --labels {1}'
               .format(snapshot_name,
                       ','.join(['{0}={1}'.format(pair[0], pair[1])
                                 for pair in add_labels])))
      self.Run('compute snapshots describe {0}'.format(snapshot_name))
      self.AssertNewOutputContainsAll(['abc: xyz', 'x: y'])

      remove_labels = ('abc',)
      self.Run('compute snapshots remove-labels {0} --labels {1}'
               .format(snapshot_name,
                       ','.join(['{0}'.format(k)
                                 for k in remove_labels])))
      self.Run('compute snapshots describe {0}'
               .format(snapshot_name))
      self.AssertNewOutputContains('x: y', reset=False)
      self.AssertNewOutputNotContains('abc: xyz')

      self.Run('compute snapshots remove-labels {0} --all '
               .format(snapshot_name))
      self.Run('compute snapshots describe {0}'.format(snapshot_name))
      self.AssertNewOutputNotContains('labels:')

  def testUpdateLabels(self):
    with self._CreateDisk() as disk_name, \
         self._CreateSnapshot(disk_name) as snapshot_name:
      add_labels = (('x', 'y'), ('abc', 'xyz'))
      self.Run('compute snapshots update {0} --update-labels {1}'
               .format(snapshot_name,
                       ','.join(['{0}={1}'.format(pair[0], pair[1])
                                 for pair in add_labels])))
      self.Run('compute snapshots describe {0}'.format(snapshot_name))
      self.AssertNewOutputContainsAll(['abc: xyz', 'x: y'])

      update_labels = (('x', 'a'), ('abc', 'xyz'), ('t123', 't7890'))
      remove_labels = ('abc',)
      self.Run(
          'compute snapshots update {0} --update-labels {1} --remove-labels {2}'
          .format(snapshot_name,
                  ','.join(['{0}={1}'.format(pair[0], pair[1])
                            for pair in update_labels]),
                  ','.join(['{0}'.format(k)
                            for k in remove_labels])))

      self.Run('compute snapshots describe {0}'.format(snapshot_name))
      self.AssertNewOutputContains('t123: t7890', reset=False)
      self.AssertNewOutputContains('x: a', reset=False)
      self.AssertNewOutputNotContains('abc: xyz')

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


"""
Three numbers sum problem.

We have an array of distinct integers, and integer representing the target_sum.
We need to find each unique combination of 3 integers that sum up to the target sum.
Those should be returned as an array for each combo, gathered in a parent array. So
the output should be two dimensional arrays with the combinations. Triplets should be
ordered ascending.
If no triplets are available, [] should be returned.

Approach 1, Brute force:
Use 3 nested loops to iterate over the array to find if 3 numbers sum up to target_sum.
Time complexity O(N^3) - cubic.

Approach 2:
Use a dict, to store each combo of 2 distinct ints as a key, where the value is always the
target_sum.

After dict is filled, we iterate over the array, trying to find is z = target_sum - (x + y) is
within the numbers
"""

numbers = [12, 3, 1, 2, -6, 5, -8, 6]

def three_numbers_sum(array, target_sum):
    x_y_sum_dict = {}
    x_y_z_sum_dict = {}
    tracked_idx = 0

    while tracked_idx < len(array):
        processed_number = numbers[tracked_idx]

        for idx, n in enumerate(array):
            if idx <= tracked_idx:
                continue
            x_y_sum_dict[processed_number, n] = target_sum
        tracked_idx += 1

    for x_y, target_sum in x_y_sum_dict.items():
        z = target_sum - sum(x_y)
        if z in numbers and z not in x_y:
            x_y_z_key = list(x_y + (z,))
            x_y_z_key.sort()
            x_y_z_sum_dict[tuple(x_y_z_key)] = target_sum

    return sorted([list(x_y_z) for x_y_z in x_y_z_sum_dict.keys()])

print(three_numbers_sum(numbers, 0))

# Algo expert solution:
# O(n^2) time | O(n) space
def threeNumberSum(array, targetSum):
    array.sort()
    triplets = []
    for i in range(len(array) - 2):
        left = i + 1
        right = len(array) - 1
        while left < right:
            currentSum = array[i] + array[left] + array[right]
            if currentSum == targetSum:
                triplets.append([array[i], array[left], array[right]])
                left += 1
                right -= 1
            elif currentSum < targetSum:
                left += 1
            elif currentSum > targetSum:
                right -= 1
        return triplets


#!/usr/bin/env python
# -*- coding: utf_8 -*-
"""
    fork from the github proj named "SwitecX25", original code is  c++, change to python
     notice that , don't put this program under multi-thread, and avoid motor lost steps
        2017.7.31 zrd
"""

import RPi.GPIO as GPIO
import time
import wiringpi as w_gpio
import math
import threading
import random

# // This table defines the acceleration curve.
# // 1st value is the speed step, 2nd value is delay in microseconds
# // 1st value in each row must be > 1st value in subsequent row
# // 1st value in last row should be == maxVel, must be <= maxVel
# 1st param is the steps from 0 ~ 810, means 0-20 steps ,use speed 3000 micro sec
# 20 - 50 steps use speed 1500 micro sec
# test show that, when speed below 1000, the motor lost steps __chark

# RESET_STEP_MICROSEC = 800
# RESET_STEP_MICROSEC = 8000
RESET_STEP_MICROSEC = 500
# defaultAccelTable = [
#     [20, 6750],
#     [50, 3300],
#     [100, 2200],
#     [150,  1800],
#     [300,  1350]
# ]
defaultAccelTable = [
    [20, 3000],
    [50, 1500],
    [100, 1000],
    [150,  800],
    [300,  600]
]

# 二维数组的行数
DEFAULT_ACCEL_TABLE_SIZE = 5

# // experimentation suggests that 400uS is about the step limit
# // with my hand-made needles made by cutting up aluminium from
# // floppy disk sliders.  A lighter needle will go faster.

# // State  3 2 1 0   Value

#            R   L
# // 0      1 0 0 1   0x9
# // 1      0 0 0 1   0x1
# // 2      0 1 1 1   0x7
# // 3      0 1 1 0   0x6
# // 4      1 1 1 0   0xE
# // 5      1 0 0 0   0x8
stateMap = [0x9, 0x1, 0x7, 0x6, 0xE, 0x8]

#            R   L
# // 0      0 1 1 0   0x6
# // 1      0 1 0 0   0x8
# // 2      0 0 0 1   0x9
# // 3      1 0 0 1   0x9
# // 4      1 0 0 0   0x8
# // 5      0 0 1 0   0x8

# stateMap = [0x6, 0x4, 0x1, 0x9, 0x8, 0x2]

class SwitecX25(object):

    def __init__(self):
        # multi threading things
        # super(SwitecX25, self).__init__()
        # self.__running = threading.Event()
        # self.__running.set()
        # io connect to switec motor
        # self.pins = [6, 13, 26, 19]
        # self.pins = [26, 19, 6, 13]
        self.pins = [13, 6, 26, 19]
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(6, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(13, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(26, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(19, GPIO.OUT, initial=GPIO.LOW)

        self.pinCount = 4
        self.stateCount = 6
        # 6 steps
        self.currentState = 0
        # step we are currently at
        self.currentStep = 0
        # target we are moving to
        self.targetStep = 0

        self.steps = 945
        # total steps available, switec total rotation 315 degree,we use 270 degree __chark

        self.time0 = None                     # time when we entered this state
        self.microDelay = None               # microsecs until next state
        self.vel = 0                        # steps travelled under acceleration
        self.dir = 0                        # direction -1,0,1
        self.stopped = True                 # true if stopped
        self.accelTable = defaultAccelTable

        # python另外增加的变量

        # 从c++不太好处理的两个变量
        # unsigned short (*accelTable)[2] # accel table can be modified.
        self.maxVel = 300           # fastest vel allowed

    def writeio(self):
        mask = stateMap[self.currentState]
        for i in range(self.pinCount):
            if mask & 0x01 == True:
                j = GPIO.HIGH
            else:
                j = GPIO.LOW
            GPIO.output(self.pins[i], j)
            mask >>= 1

    def stepup(self):
        if self.currentStep < self.steps:
            self.currentStep += 1
            self.currentState = (self.currentState + 1) % self.stateCount
            self.writeio()

    def stepdown(self):
        if self.currentStep > 0:
            self.currentStep -= 1
            self.currentState = (self.currentState + 5) % self.stateCount
            self.writeio()

    def zero(self):
        self.currentStep = self.steps - 1
        # time0_s = time.clock()
        # time1_s = w_gpio.micros()
        # w_gpio.delayMicroseconds(500)
        # time.sleep(RESET_STEP_MICROSEC/1000000)
        for i in range(self.steps):
            self.stepdown()
            time.sleep(RESET_STEP_MICROSEC/1000000)
        # time0_e = time.clock()
        # time1_e = w_gpio.micros()
        # print("%d" % ((time0_e-time0_s)*1000000))
        # print(time1_e - time1_s)
        self.currentStep = 0
        self.targetStep = 0
        self.vel = 0
        self.dir = 0

# // This function determines the speed and accel
# // characteristics of the motor.  Ultimately it
# // steps the motor once (up or down) and computes
# // the delay until the next step.  Because it gets
# // called once per step per motor, the calcuations
# // here need to be as light-weight as possible, so
# // we are avoiding floating-point arithmetic.
# //
# // To model acceleration we maintain vel, which indirectly represents
# // velocity as the number of motor steps travelled under acceleration
# // since starting.  This value is used to look up the corresponding
# // delay in accelTable.  So from a standing start, vel is incremented
# // once each step until it reaches maxVel.  Under deceleration
# // vel is decremented once each step until it reaches zero.

    def advance(self):
        if self.currentStep == self.targetStep and self.vel == 0:
            self.stopped = True
            self.dir = 0
            # self.time0 = time.time()
            # self.time0 = time.clock()
            self.time0 = time.process_time()
            return
        if self.vel == 0:
            if self.currentStep < self.targetStep:
                self.dir = 1
            else:
                self.dir = -1
            self.vel = 1
        if self.dir > 0:
            self.stepup()
        else:
            self.stepdown()

        if self.dir > 0:
            delta = self.targetStep - self.currentStep
        else:
            delta = self.currentStep - self.targetStep

        if delta > 0:
            # case 1 : moving towards target (maybe under accel or decel)
            if delta < self.vel:            # time to declerate
                self.vel -= 1
            elif self.vel < self.maxVel:    # accelerating
                self.vel += 1
            else:
                pass                        # at full speed - stay there
        # case 2 : at or moving away from target (slow down!)
        else:
            self.vel -= 1

        # vel now defines delay
        i = 0
        while self.accelTable[i][0] < self.vel:
            i += 1
        self.microDelay = self.accelTable[i][1]
        # self.time0 = time.time()
        # self.time0 = time.clock()
        self.time0 = time.process_time()

    def setposition(self, pos):
        if pos >= self.steps:
            pos = self.steps - 1
        self.targetStep = pos
        if self.stopped:
            self.stopped = False
            # self.time0 = time.time()
            # self.time0 = time.clock()
            self.time0 = time.process_time()
            self.microDelay = 0

    def update(self):
        if not self.stopped:
            # delta = (time.time() - self.time0)*1000000
            # delta = (time.clock() - self.time0) * 1000000
            delta = (time.process_time() - self.time0) * 1000000
            if delta >= self.microDelay:
                self.advance()

    def updateblocking(self):
        while not self.stopped:
            # delta = time.time() - self.time0
            # delta = (time.clock() - self.time0) * 1000000
            delta = (time.process_time() - self.time0) * 1000000
            if delta >= self.microDelay:
                self.advance()

    def stop(self):
        self.__running.clear()

    def run(self):
        while self.__running.is_set():
            if not self.stopped:
                # delta = (time.time() - self.time0)*1000000
                # delta = (time.clock() - self.time0) * 1000000
                delta = (time.process_time() - self.time0) * 1000000
                if delta >= self.microDelay:
                    self.advance()
        return

def main():
    thread_1 = SwitecX25()
    thread_1.zero()
    # thread_1.setposition(405)

    # flag = 1
    # thread_1.start()
    # while True:
    #     pass

    # meter_float = random.uniform(0, 810)
    # print("current position:%d" % meter_float)
    # thread_1.setposition(meter_float)

    # start = time.clock()
    start = time.process_time()
    flag = 1
    zero_flag = 0
    i = 0
    # motor1 = SwitecX25()
    try:
        while True:
            if zero_flag == 0:
                # thread_1.update()
                thread_1.updateblocking()
                # end = time.clock()
                end = time.process_time()
                if (end - start) > 1 and flag == 1:
                    print("end:%f, start:%f" % (end, start))
                    # start = time.clock()
                    start = time.process_time()
                    # meter_float = random.randint(0, 810)
                    # meter_pos = (i + 1) * 81
                    meter_pos = int(round(270 * 3 * i  / 3 ))  # psi 0 ~ 5076 psi
                    print("pos:%d" %  meter_pos)
                    thread_1.setposition(meter_pos)
                    i += 1
                    if i == 4:
                        i = 0
            else:
                thread_1.setposition(0)
                thread_1.updateblocking()
    finally:
        thread_1.stop()
        GPIO.cleanup()

if __name__ == "__main__":
    main()

# psi:500, pos:80
# psi:1000, pos:160
# psi:1500, pos:239
# psi:2000, pos:319
# psi:2500, pos:399
# psi:3000, pos:479
# psi:3500, pos:559
# psi:4000, pos:638
# psi:4500, pos:718
# psi:5000, pos:798


from rest_framework import generics, status
from api.permissions import IsOwnerOrReadOnly
from rest_framework.response import Response
from rest_framework import filters

from restaurants.serializers import (RestaurantsSerializer,
                                     CategorySerializer)
from rest_framework.generics import (ListCreateAPIView,
                                     ListAPIView,
                                     RetrieveUpdateDestroyAPIView)

from rest_framework.generics import get_object_or_404
from api.models import Restaurant

class GetAllRestaurantsView(ListCreateAPIView):
    """
    Class to GET the list of all Restaurants or POST a new Restaurant
    """
    serializer_class = RestaurantsSerializer
    queryset = Restaurant.objects.all()
    permission_classes = [IsOwnerOrReadOnly]

    def post(self, request):
        serializer = RestaurantsSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({"Status 201": "Restaurant created succesfully"}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class GetPostUpdateDeleteRestaurantView(RetrieveUpdateDestroyAPIView):
    """
    Class to GET - PUT - DELETE: Restaurant by id
    """
    serializer_class = RestaurantsSerializer

    def get_object(self, pk):
        restaurant = get_object_or_404(Restaurant, pk=pk)
        return restaurant

    def get(self, request, pk):
        restaurant = self.get_object(pk)
        serializer = RestaurantsSerializer(restaurant)
        return Response(serializer.data)

    def put(self, request, pk):
        restaurant = self.get_object(pk)
        serializer = RestaurantsSerializer(restaurant, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({"Status 201": "Restaurant updated succesfully"}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        restaurant = self.get_object(pk)
        restaurant.delete()
        return Response({"Status 204": "Restaurant deleted succesfully"}, status=status.HTTP_204_NO_CONTENT)

class GetRestaurantByCategoryView(ListAPIView):
    """
    Class to GET all the Restaurants by category
    """
    serializer_class = RestaurantsSerializer

    def get_queryset(self):
        category = self.kwargs.get("category").title()
        return Restaurant.objects.filter(category=category)

class GetRestaurantByUserIDView(generics.ListAPIView):
    """
    Class to Get the all the Restaurants by owner
    """
    serializer_class = RestaurantsSerializer

    def get_queryset(self, *args, **kwargs):
        kwargs = self.kwargs  # --> a dictionary with the url's parameter {'author_id': '2'}
        kw_id = kwargs.get('user_id')  # --> returns the value of key='author_id'
        return Restaurant.objects.filter(restaurant_owner=kw_id)

class CategoriesView(ListAPIView):
    """
    Class to GET the categories of the Restaurants
    """
    serializer_class = CategorySerializer
    queryset = Restaurant.objects.all()

    def get_queryset(self):
        categories = Restaurant.objects.values("category").distinct()

        return categories

class SearchRestaurant(generics.ListAPIView):
    """
    Class to Search Restaurants
    """

    serializer_class = RestaurantsSerializer
    queryset = Restaurant.objects.all()
    filter_backends = (filters.SearchFilter,)
    search_fields = ('name', 'category', 'city', 'country')


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

#%%

#%%

# %load_ext autoreload
# %autoreload 2

import os
from os import listdir
from os.path import join, basename
import numpy as np
import tifffile
import multiprocessing as mp
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
import tensorflow as tf
from mdl_adapter_layers import mdl_adapter_layers
from SaveModelDescript import SaveModelDescript
from change_InputShape import change_InputShape
from callback_PredWriter import callback_PredWriter
from datetime import datetime
import time
import cv2

# import matplotlib
# from RegularizeModel import RegularizeModel
# from ModelEditor import ModelEditor
# from get_CompileParams import get_CompileParams
# from callback_ConfMat import callback_ConfMat
# import pathlib
# import pandas as pd
# from Dataset_from_Dataframe import Dataset_from_Dataframe
# from Dataset_from_Cache import Dataset_from_Cache
# import pickle

# os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
# os.environ["CUDA_VISIBLE_DEVICES"]="0"

#%% Defining paths, loading dataframes and identifying classes

MasterPath = os.path.abspath("/gpfs0/home/jokhun/Pro 1/Cellular biosensor")
# MasterPath = os.path.abspath('//deptnas.nus.edu.sg/BIE/MBELab/jokhun/Pro 1/Cellular biosensor')
# MasterPath = os.path.abspath('/hpctmp/biejds/Pro 1/Cellular biosensor')
# MasterPath = os.path.abspath('/MBELab/jokhun/Pro 1/Cellular biosensor')

model_name = 'DICFea1Scra1412'

ImgPath = join (MasterPath,'6. Data/Projected_Fea1')

file_list = listdir(ImgPath)
Ch1_img_paths = []
Ch2_img_paths = []
Ch3_img_paths = []
Ch4_img_paths = []
Ch5_img_paths = []
for file_name in file_list:
    if 'DIC' in file_name:
        Ch1_img_paths.append(join(ImgPath,file_name))
    # if 'Lysosome' in file_name:
    #     Ch2_img_paths.append(join(ImgPath,file_name))
    # if 'ER' in file_name:
    #     Ch3_img_paths.append(join(ImgPath,file_name))
    # if 'MT' in file_name:
    #     Ch4_img_paths.append(join(ImgPath,file_name))
    # if 'Nuc' in file_name:
    #     Ch5_img_paths.append(join(ImgPath,file_name))

Ch1_img_paths.sort()
Ch2_img_paths.sort()
Ch3_img_paths.sort()
Ch4_img_paths.sort()
Ch5_img_paths.sort()

# sample_id = np.random.choice([i for i in range(len(Ch1_img_paths))], size=8, replace = False)
# Ch1_img_paths = [Ch1_img_paths[i] for i in sample_id]
# Ch2_img_paths = [Ch2_img_paths[i] for i in sample_id]
# Ch3_img_paths = [Ch3_img_paths[i] for i in sample_id]
# Ch4_img_paths = [Ch4_img_paths[i] for i in sample_id]
# Ch5_img_paths = [Ch5_img_paths[i] for i in sample_id]

#%% function to load images

numOfCrops_per_dim = 2
def load_img (path, numOfCrops_per_dim=numOfCrops_per_dim):
    raw = tifffile.imread(path)

    img_size = raw.shape[0]
    extra_pix = img_size % numOfCrops_per_dim
    extra_pix_0 = extra_pix//2
    extra_pix_1 = extra_pix - extra_pix_0
    raw = raw [extra_pix_0:img_size-extra_pix_1,extra_pix_0:img_size-extra_pix_1]

    crops=np.array([img for crop_ls in (np.split(split_0,numOfCrops_per_dim,-1) for split_0 in np.split(raw,numOfCrops_per_dim,0)) for img in crop_ls])
    return crops
    # return cv2.resize(tifffile.imread(path), (1412,1412), interpolation = cv2.INTER_AREA)

#%% Loading images

if __name__=='__main__':
    with mp.Pool() as pool:
        Ch1_img = np.concatenate(pool.map(load_img,Ch1_img_paths),axis=0) if len(Ch1_img_paths)>0 else []
        Ch2_img = np.concatenate(pool.map(load_img,Ch2_img_paths),axis=0) if len(Ch2_img_paths)>0 else []
        Ch3_img = np.concatenate(pool.map(load_img,Ch3_img_paths),axis=0) if len(Ch3_img_paths)>0 else []
        Ch4_img = np.concatenate(pool.map(load_img,Ch4_img_paths),axis=0) if len(Ch4_img_paths)>0 else []
        Ch5_img = np.concatenate(pool.map(load_img,Ch5_img_paths),axis=0) if len(Ch5_img_paths)>0 else []

#%% Repeating the paths to be consistent with image splitting

Ch1_img_paths = [path for path in Ch1_img_paths for rep in range(numOfCrops_per_dim*numOfCrops_per_dim)]
Ch2_img_paths = [path for path in Ch2_img_paths for rep in range(numOfCrops_per_dim*numOfCrops_per_dim)]
Ch3_img_paths = [path for path in Ch3_img_paths for rep in range(numOfCrops_per_dim*numOfCrops_per_dim)]
Ch4_img_paths = [path for path in Ch4_img_paths for rep in range(numOfCrops_per_dim*numOfCrops_per_dim)]
Ch5_img_paths = [path for path in Ch5_img_paths for rep in range(numOfCrops_per_dim*numOfCrops_per_dim)]

#%% Randomize the dataset

def randomizer (arr_ls, rng, randomizer_state):
    for arr in arr_ls:
        rng.__setstate__(randomizer_state)
        rng.shuffle(arr)
    return

rng = np.random.default_rng(seed=0)
randomizer_state = rng.__getstate__()

randomizer ([Ch1_img_paths, Ch2_img_paths, Ch3_img_paths, Ch4_img_paths, Ch5_img_paths], rng, randomizer_state)
randomizer ([Ch1_img, Ch2_img, Ch3_img, Ch4_img, Ch5_img], rng, randomizer_state)

#%%

X = np.expand_dims(Ch1_img,-1)
# X = np.stack((Ch1_img,Ch2_img,Ch3_img,Ch4_img,Ch5_img),axis=3)
First_ClassDelimiter = '_'
Second_ClassDelimiter = '_'
Y = [basename(path) for path in Ch1_img_paths]
Y = [y[y.find(First_ClassDelimiter)+1:] for y in Y]
Y = [y[:y.find(Second_ClassDelimiter)] for y in Y]

Ts_size = int(0.0 * X.shape[0])
Val_size = int(0.15 * X.shape[0])
Tr_size = X.shape[0] - (Ts_size + Val_size)
print(f'Train, val and test sample sizes: {Tr_size}, {Val_size}, {Ts_size}')

Ts_X = X[0:Ts_size]
Val_X = X[Ts_size:Ts_size + Val_size]
Tr_X = X[Ts_size + Val_size:Ts_size + Val_size + Tr_size]

Ts_img_paths = Ch1_img_paths[0:Ts_size]
Val_img_paths = Ch1_img_paths[Ts_size:Ts_size + Val_size]
Tr_img_paths = Ch1_img_paths[Ts_size + Val_size:Ts_size + Val_size + Tr_size]

#%% Encoding labels

ResponseEncoder = LabelEncoder()
ResponseEncoder.fit(Y)

class_names = ResponseEncoder.classes_
NumOfClasses = len(class_names)
print('Number of classes in the data: '+str(NumOfClasses))
print(class_names)

Ts_Y = ResponseEncoder.transform(Y[0:Ts_size])
Val_Y = ResponseEncoder.transform(Y[Ts_size:Ts_size + Val_size])
Tr_Y = ResponseEncoder.transform(Y[Ts_size + Val_size:Ts_size + Val_size + Tr_size])

#%%

batch_size = 8
print('batch size:',batch_size)
shuffle_buffer_size = np.max([batch_size,NumOfClasses])*2

def idx2img(batch_idx,batch_y,ImageSet):
    def fetch (batch_idx,ImageSet=ImageSet):
        batch_x = ImageSet[batch_idx]
        return batch_x # np.concatenate((batch_x,batch_x,batch_x),axis=3)
    batch_x=tf.numpy_function(fetch, [batch_idx], tf.uint8)
    batch_x.set_shape((None,*ImageSet.shape[1:])) # ((None,*ImageSet.shape[1:3],3))
    return batch_x,batch_y
def idx2img_Tr(batch_idx,batch_y,ImageSet=Tr_X):
    return idx2img(batch_idx,batch_y,ImageSet)
def idx2img_Val(batch_idx,batch_y,ImageSet=Val_X):
    return idx2img(batch_idx,batch_y,ImageSet)
def idx2img_Ts(batch_idx,batch_y,ImageSet=Ts_X):
    return idx2img(batch_idx,batch_y,ImageSet)

dataset_Tr = tf.data.Dataset.from_tensor_slices((np.array(range(len(Tr_X))), Tr_Y)).shuffle(buffer_size=shuffle_buffer_size)\
    .batch(batch_size=batch_size).map(idx2img_Tr, num_parallel_calls=tf.data.experimental.AUTOTUNE, deterministic=False)\
        .prefetch(tf.data.experimental.AUTOTUNE)

dataset_Val = tf.data.Dataset.from_tensor_slices((np.array(range(len(Val_X))), Val_Y)).shuffle(buffer_size=shuffle_buffer_size)\
    .batch(batch_size=batch_size).map(idx2img_Val, num_parallel_calls=tf.data.experimental.AUTOTUNE, deterministic=False)\
        .prefetch(tf.data.experimental.AUTOTUNE)

dataset_Ts = tf.data.Dataset.from_tensor_slices((np.array(range(len(Ts_X))), Ts_Y)).shuffle(buffer_size=shuffle_buffer_size)\
    .batch(batch_size=batch_size).map(idx2img_Ts, num_parallel_calls=tf.data.experimental.AUTOTUNE, deterministic=False)\
        .prefetch(tf.data.experimental.AUTOTUNE)

#%% function to change the input size of the core model

def change_InputShape (model, new_InputShape):

    model._layers[0]._batch_input_shape = (None,*new_InputShape)

    # rebuild model architecture by exporting and importing via json
    new_model = tf.keras.models.model_from_json(model.to_json())

    # copy weights from old model to new one
    success=[]
    failure=[]
    for l,layer in enumerate(new_model.layers):
        try:
            layer.set_weights(model.get_layer(name=layer.name).get_weights())
            success.append((l,layer.name))
        except:
            failure.append((l,layer.name))
    print(f'Weights successfully transferred to {len(success)} layers')
    print(f'Failed to transfer weights to {len(failure)} layers')
    print(failure)

    return new_model

#%% Building the model

original_img_shape = dataset_Tr.element_spec[0].shape.as_list()[1:]  #Tr_X[0].shape #(w, h, No._of_Ch)
Final_img_shape = (original_img_shape)

ModelName = model_name+'_Xception'
core_model = tf.keras.applications.Xception(input_shape=[*Final_img_shape[:2],3], include_top=False, weights="imagenet")
ref_core_model = "tf.keras.applications.Xception(input_shape=[*Final_img_shape[:2],3], include_top=False, weights=None)"
core_preprocess_layers = tf.keras.applications.xception.preprocess_input

AddTopAndBottomLayers = True

regularizer_Bottom = tf.keras.regularizers.l1_l2(l1=0, l2=0.001)
if AddTopAndBottomLayers:

    core_model = change_InputShape (core_model,Final_img_shape)

    In = tf.keras.Input(shape=original_img_shape, name="Preprocess_Input")
    adapter_layers = mdl_adapter_layers (Output_ImgShape=Final_img_shape)
    Out = core_preprocess_layers(adapter_layers.Int_Rescaler(name='Ch_rescale_0_255', Saturation=[0.001,0.005])(\
            adapter_layers.Im_Rotater(name='random_rotate')(\
                adapter_layers.Im_Flipper(name='random_flip_HnV')(\
                    adapter_layers.Im_Resizer(name='resize')(In)))))

    mdl_preprocess = tf.keras.Model(inputs=In, outputs=Out, name='mdl_preprocess')

    In = tf.keras.Input(shape=core_model.output_shape[1:4], name="Features")
    GlbMaxPool = tf.keras.layers.GlobalMaxPool2D(name="GlbMaxPool")
    GlbAvgPool = tf.keras.layers.GlobalAveragePooling2D(name="GlbAvgPool")
    MaxAvgConcat = tf.keras.layers.Concatenate(axis=-1, name="MaxAvgConcat")
    Dropout1 = tf.keras.layers.Dropout(0.25, name="Feature_Dropout")
    Dense1 = tf.keras.layers.Dense(units=core_model.output_shape[-1], activation='relu', kernel_regularizer=regularizer_Bottom, name="dense1")
    Dropout2 = tf.keras.layers.Dropout(0.25, name="Dropout2")
    predictions = tf.keras.layers.Dense(units=NumOfClasses, activation=None, kernel_regularizer=regularizer_Bottom, name="predictions")
    Out=predictions(Dropout2(Dense1(Dropout1(MaxAvgConcat([GlbMaxPool(In),GlbAvgPool(In)])))))
    mdl_prediction = tf.keras.Model(inputs=In, outputs=Out, name='mdl_prediction')

    In = tf.keras.Input(shape=original_img_shape, name="Input_images")
    Out = mdl_prediction(core_model(mdl_preprocess(In)))
    model = tf.keras.Model(inputs=In, outputs=Out, name=ModelName)
    print ('Bottom and Top layers added!')

#%% Saving model description

SaveModelDescription = True

if SaveModelDescription:
    Model_Path = join(MasterPath,model.name)
    SaveModelDescript(model, save_dir=Model_Path,\
        save_filename=model.name)
    print ('Model descriptions saved!')

#%% Editing the core model

# Edit_Core_Model = False
# # SaveEditedModelDescription = True
# # ModelKey = ModelKeys[0]

# if Edit_Core_Model:
#     model = models[ModelKey]
#     New_Layers={'drop1':tf.keras.layers.Dropout(rate=0.1, name='drop1'),
#                 'drop2':tf.keras.layers.Dropout(rate=0.2, name='drop2'),
#                 'drop3':tf.keras.layers.Dropout(rate=0.3, name='drop3'),
#                 'drop4':tf.keras.layers.Dropout(rate=0.4, name='drop4'),
#                 'drop5':tf.keras.layers.Dropout(rate=0.5, name='drop5'),
#                }

#     IncomingLinks_2Axe=[-18, -12, -14, -8, -5, -1]

#     IncomingLinks_2Forge=[(New_Layers['drop1'], model.layers[-19]),
#                           (model.layers[-18], New_Layers['drop1']),
#                           (model.layers[-12], New_Layers['drop1']),
#                           (New_Layers['drop2'], model.layers[-15]),
#                           (model.layers[-14], New_Layers['drop2']),
#                           (New_Layers['drop3'], model.layers[-9]),
#                           (model.layers[-8], New_Layers['drop3']),
#                           (New_Layers['drop4'], model.layers[-6]),
#                           (model.layers[-5], New_Layers['drop4']),
#                           (New_Layers['drop5'], model.layers[-2]),
#                           (model.layers[-1], New_Layers['drop5']),
#                          ]

#     model_inputs=None
#     model_outputs=None

#     model = ModelEditor(model, New_Layers=New_Layers, IncomingLinks_2Axe=IncomingLinks_2Axe,
#                                 IncomingLinks_2Forge=IncomingLinks_2Forge,
#                                 model_inputs=model_inputs, model_outputs=model_outputs)
#     models[ModelKey] = model

#     # Save edited model description
#     if SaveEditedModelDescription:
#         Model_Path = os.path.join(MasterPath,str(ModelKey))
#         SaveModelDescript(model, save_dir=Model_Path,
#                           save_filename=str(ModelKey+'_edited'))
#         print ('Model descriptions saved!')

#%% Adding Regularization to all regularizable layers

# RegularizeTheModel = False
# if RegularizeTheModel:
#     regularizer = tf.keras.regularizers.l1_l2(l1=0, l2=0.001)
#     for ModelKey in ModelKeys:
#         models[ModelKey]=RegularizeModel(models[ModelKey], regularizer, keep_weights=True)
# else: print ('No alteration in regularization!')

#%% Summary of models

determine_initial_accuracies = False

TrainEval=[]
ValEval=[]
TestEval=[]
if determine_initial_accuracies:

    model.compile(optimizer='adam',\
        loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\
            metrics=['accuracy'])
    print ('Model compiled!')

    print ('Initial Train Loss and Accuracy')
    Eval=model.evaluate(dataset_Tr, verbose=0)
    TrainEval.append(Eval)
    print (TrainEval)

    print ('\nInitial Val Loss and Accuracy')
    Eval=model.evaluate(dataset_Val, verbose=0)
    ValEval.append(Eval)
    print (ValEval)

    print ('\nInitial Test Loss and Accuracy')
    Eval=model.evaluate(dataset_Ts, verbose=0)
    TestEval.append(Eval)
    print (TestEval)

#%% Training config

def train_model (model, Dataset_Tr, Dataset_Val, initial_epoch=0, final_epoch=5, Model_Path=None, class_names=None):
    if Model_Path==None or Model_Path==[]:
        Model_Path=model.name

    sess_DateTime = str(datetime.now().strftime("%Y%m%d-%H%M%S"))
    MdlChkpt_Path = os.path.join(Model_Path,"MdlChkpt",(sess_DateTime+"_e{epoch:03d}_Acc{accuracy:.2f}_ValAcc{val_accuracy:.2f}.ckpt"))
    MdlChkpt_cb = tf.keras.callbacks.ModelCheckpoint(
        MdlChkpt_Path, monitor='val_accuracy', verbose=0, save_best_only=True, save_weights_only=True,
        mode='auto', save_freq="epoch"
    )
    TensorBoard_Path = os.path.join(Model_Path,"logs",(model.name+'_'+sess_DateTime))
    TensorBoard_cb = tf.keras.callbacks.TensorBoard(
        log_dir = TensorBoard_Path, histogram_freq=0, write_graph=False, write_images=False, update_freq="epoch",
        profile_batch=0, embeddings_freq=0, embeddings_metadata=None
    )

    EarlyStop_cb = tf.keras.callbacks.EarlyStopping(monitor='val_loss', \
        min_delta=0, patience=75, verbose=2, mode='auto',\
            baseline=None, restore_best_weights=True)

    # ConfMat_Path = os.path.join(Model_Path,"logs",(model.name+'_'+sess_DateTime))
    # log_confusion_matrix=callback_ConfMat(model, Dataset_Val, class_names=class_names, logdir=ConfMat_Path, freq=10)
    # # Define the per-epoch callback.
    # ConfMat_cb = tf.keras.callbacks.LambdaCallback(on_epoch_end=log_confusion_matrix)

    PredLog_Path = os.path.join(Model_Path,"logs",(model.name+'_'+sess_DateTime))
    pred_writer = callback_PredWriter(model, Dataset_Val, class_names=class_names, logdir=PredLog_Path, freq=5) #freq in epochs
    # Define the per-epoch callback.
    PredWriter_cb = tf.keras.callbacks.LambdaCallback(on_epoch_end=pred_writer)

    history = model.fit(Dataset_Tr, initial_epoch=initial_epoch, epochs=final_epoch, \
        verbose=1, callbacks=[EarlyStop_cb, TensorBoard_cb, MdlChkpt_cb, PredWriter_cb], # ,ConfMat_cb
        validation_data=Dataset_Val, validation_freq=1)

    return history

#%%

FreshTrainHistory = True
if FreshTrainHistory:
    history={}

#%% Selecting the layers to be trained

FineTune_Core_Onwards = 0  # 0 to set the entire model as trainable and None to copletely freeze training of the core model
learning_rate = 1e-3 # 1e-3, 1e-7
CoreModel_layer = -2

Change_Classifier_DropoutRate = False
New_DropoutRate = 0.8

print ('Total params:',f'{np.sum([np.prod(a.shape) for a in model.weights]):,}')
print ('Trainable params:',f'{np.sum([np.prod(a.shape) for a in model.trainable_weights]):,}')
print ('Non-trainable params:',f'{np.sum([np.prod(a.shape) for a in model.non_trainable_weights]):,}')
core_model = model.layers[CoreModel_layer]
core_model.trainable = True
if FineTune_Core_Onwards == None:
    FineTune_Core_Onwards = len(core_model.layers)
Num_CoreTrainableLayers=0
i_track=-1
for layer in core_model.layers[:FineTune_Core_Onwards]:
    i_track+=1
    if i_track > 1:
        layer.trainable = False
if FineTune_Core_Onwards != len(core_model.layers):
    ref_mdl = eval(ref_core_model)
    for layer in core_model.layers[FineTune_Core_Onwards:]:
        i_track+=1
        layer.trainable = ref_mdl.layers[i_track].trainable
        Num_CoreTrainableLayers+=1
    del ref_mdl
print ('Appropriate layers after',FineTune_Core_Onwards,'of',core_model.name,'have been set as trainable!')

if Change_Classifier_DropoutRate:
    model.layers[-1].layers[-2].rate = New_DropoutRate
    model.layers[-1].layers[-4].rate = New_DropoutRate
    print ('The dropout rates of the dropout layers in the classifier has been altered to', New_DropoutRate)

model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate),\
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),\
        metrics=['accuracy'])
print (model.name,'has been recompiled!')
print ('Total params:',f'{np.sum([np.prod(a.shape) for a in model.weights]):,}')
print ('Trainable params:',f'{np.sum([np.prod(a.shape) for a in model.trainable_weights]):,}')
print ('Non-trainable params:',f'{np.sum([np.prod(a.shape) for a in model.non_trainable_weights]):,}')

#%% Training

Epochs2TrainFor= 100

his_log=sorted(list(history.keys()))
if len(his_log)>0:
    his_log = history[his_log[-1]]
    initial_epoch = his_log.epoch[-1] + 1
else: initial_epoch = 0
final_epoch = initial_epoch + Epochs2TrainFor

ModelStart=time.perf_counter()
print('\nTraining!')
Model_Path = os.path.join(MasterPath,model.name)
sess_DateTime = str(datetime.now().strftime("%Y%m%d-%H%M%S"))
history[model.name+'_'+sess_DateTime+'_'+str(Num_CoreTrainableLayers)]=train_model (
    model, dataset_Tr, dataset_Val, initial_epoch=initial_epoch, final_epoch=final_epoch,
    Model_Path=Model_Path, class_names=class_names)

print('\n'+model.name+' trained! Training time = '+ str((time.perf_counter()-ModelStart)/60) + ' min!')

#%% Summary of Models

determine_accuracies = False

if determine_accuracies:
    print ('Train Loss and Accuracy')
    Eval=model.evaluate(dataset_Tr, verbose=0)
    TrainEval.append(Eval)
    for Eval in TrainEval:
        print (Eval)

    print ('\nVal Loss and Accuracy')
    Eval=model.evaluate(dataset_Val, verbose=0)
    ValEval.append(Eval)
    for Eval in ValEval:
        print (Eval)

    print ('\nTest Loss and Accuracy')
    Eval=model.evaluate(dataset_Ts, verbose=0)
    TestEval.append(Eval)
    for Eval in TestEval:
        print (Eval)

#%% Saving the latest version of the model

SaveLatestVersions = True
if SaveLatestVersions:

    In = tf.keras.Input(shape=Final_img_shape, name="core_input_saving")
    Out = mdl_prediction(core_model(In))
    model_saving = tf.keras.Model(inputs=In, outputs=Out, name='model_saving')
    sess = datetime.now().strftime("%Y%m%d-%H%M%S")
    Save_Path = os.path.join(MasterPath,model.name,("LastModel_"+sess))
    model_saving.save(Save_Path)
    # tf.keras.models.save_model(models[ModelKey], Save_Path, \
    #     overwrite=False, include_optimizer=True)
    # Save_Path = os.path.join(MasterPath,str(ModelKey),("history_"+sess+'.pkl'))
    # with open(Save_Path,"wb") as history_file:
    #     pickle.dump(history,history_file)
    print('\nThe latest version of the model has been saved!')

#%%


import random
import sys

rand = random.randint(1,10)
print(rand)
guesses = []
tries = 0

while len(guesses) < 3:

	userNum = -1
	while ((userNum <= 0) or (userNum >=  11)):
		userNum = int( input("Enter in your guess (1-10): "))
		if (userNum <= 0) or (userNum >= 11):
			print("Guess is out of range between 1 to 10!")
	guesses.append(userNum)
	if (userNum == rand):
		print("That is the right number! You win!")
		print("Your guesses: ")
		print(guesses)
		sys.exit(0)
	else:
		print("Wrong number, try again! You have {} guesses left".format(2-tries))
		tries = tries + 1

print("I'm sorry, you did not guess the right number! You Lost.")
print("Your guesses: ")
print(guesses)


# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------

"""
Hummingbird main (converters) API.
"""
from copy import deepcopy
import numpy as np

from onnxconverter_common.registration import get_converter

from ._container import PyTorchBackendModel
from .exceptions import MissingConverter, MissingBackend
from ._parse import parse_sklearn_api_model
from .supported import backend_map
from ._utils import torch_installed, lightgbm_installed, xgboost_installed
from . import constants

# Invoke the registration of all our converters.
from . import operator_converters  # noqa

# Set up the converter dispatcher.
from .supported import xgb_operator_list  # noqa
from .supported import lgbm_operator_list  # noqa

def _supported_backend_check(backend):
    """
    Function used to check whether the specified backend is supported or not.
    """
    if not backend.lower() in backend_map:
        raise MissingBackend("Backend: {}".format(backend))

def _convert_sklearn(model, test_input=None, extra_config={}):
    """
    This function converts the specified *scikit-learn* (API) model into its [PyTorch] counterpart.
    The supported operators can be found at `hummingbird.supported`.
    [PyTorch]: https://pytorch.org/

    Args:
        model: A scikit-learn model
        test_input: some input data used to trace the model execution
        extra_config: Extra configurations to be used by the individual operator converters.
                      The set of supported extra configurations can be found at `hummingbird.supported_configurations`

    Examples:
        >>> pytorch_model = _convert_sklearn(sklearn_model)

    Returns:
        A model implemented in *PyTorch*, which is equivalent to the input *scikit-learn* model
    """
    assert model is not None
    assert torch_installed(), "To use Hummingbird you need to install torch."

    # Parse scikit-learn model as our internal data structure (i.e., Topology)
    # We modify the scikit learn model during optimizations.
    model = deepcopy(model)
    topology = parse_sklearn_api_model(model)

    # Convert the Topology object into a PyTorch model.
    hb_model = _convert_topology(topology, extra_config=extra_config)
    return hb_model

def _convert_lightgbm(model, test_input=None, extra_config={}):
    """
    This function is used to generate a [PyTorch] model from a given input [LightGBM] model.
    [LightGBM]: https://lightgbm.readthedocs.io/
    [PyTorch]: https://pytorch.org/

    Args:
        model: A LightGBM model (trained using the scikit-learn API)
        test_input: Some input data that will be used to trace the model execution
        extra_config: Extra configurations to be used by the individual operator converters.
                      The set of supported extra configurations can be found at `hummingbird.supported_configurations`

    Examples:
        >>> pytorch_model = _convert_lightgbm(lgbm_model)

    Returns:
        A *PyTorch* model which is equivalent to the input *LightGBM* model
    """
    assert lightgbm_installed(), "To convert LightGBM models you need to instal LightGBM."

    return _convert_sklearn(model, test_input, extra_config)

def _convert_xgboost(model, test_input, extra_config={}):
    """
    This function is used to generate a [PyTorch] model from a given input [XGBoost] model.
    [PyTorch]: https://pytorch.org/
    [XGBoost]: https://xgboost.readthedocs.io/

    Args:
        model: A XGBoost model (trained using the scikit-learn API)
        test_input: Some input data used to trace the model execution
        extra_config: Extra configurations to be used by the individual operator converters.
                      The set of supported extra configurations can be found at `hummingbird.supported_configurations`

    Examples:
        >>> pytorch_model = _convert_xgboost(xgb_model, [], extra_config={"n_features":200})

    Returns:
        A *PyTorch* model which is equivalent to the input *XGBoost* model
    """
    assert xgboost_installed(), "To convert XGboost models you need to instal XGBoost."

    # XGBoostRegressor and Classifier have different APIs for extracting the number of features.
    # In the former case we need to infer them from the test_input.
    if constants.N_FEATURES not in extra_config:
        if "_features_count" in dir(model):
            extra_config[constants.N_FEATURES] = model._features_count
        elif test_input is not None:
            if type(test_input) is np.ndarray and len(test_input.shape) == 2:
                extra_config[constants.N_FEATURES] = test_input.shape[1]
            else:
                raise RuntimeError(
                    "XGBoost converter is not able to infer the number of input features.\
                        Apparently test_input is not an ndarray. \
                        Please fill an issue at https://github.com/microsoft/hummingbird/."
                )
        else:
            raise RuntimeError(
                "XGBoost converter is not able to infer the number of input features.\
                    Please pass some test_input to the converter."
            )
    return _convert_sklearn(model, test_input, extra_config)

def _convert_topology(topology, device=None, extra_config={}):
    """
    This function is used to convert a `onnxconverter_common.topology.Topology` object into a *PyTorch* model.

    Args:
        topology: The `onnxconverter_common.topology.Topology` object that will be converted into Pytorch
        device: Which device the translated model will be run on
        extra_config: Extra configurations to be used by individual operator converters

    Returns:
        A *PyTorch* model
    """
    assert topology is not None, "Cannot convert a Topology object of type None."

    operator_map = {}

    for operator in topology.topological_operator_iterator():
        try:
            converter = get_converter(operator.type)
            operator_map[operator.full_name] = converter(operator, device, extra_config)
        except ValueError:
            raise MissingConverter(
                "Unable to find converter for {} type {} with extra config: {}.".format(
                    operator.type, type(getattr(operator, "raw_model", None)), extra_config
                )
            )
        except Exception as e:
            raise e

    pytorch_model = PyTorchBackendModel(
        topology.raw_model.input_names, topology.raw_model.output_names, operator_map, topology, extra_config
    ).eval()

    if device is not None:
        pytorch_model = pytorch_model.to(device)
    return pytorch_model

def convert(model, backend, test_input=None, extra_config={}):
    """
    This function converts the specified input *model* into an implementation targeting *backend*.
    *Convert* supports [Sklearn], [LightGBM] and [XGBoost] models.
    For *LightGBM* and *XGBoost currently only the Sklarn API is supported.
    The detailed list of models and backends can be found at `hummingbird.supported`.
    [Sklearn]: https://scikit-learn.org/
    [LightGBM]: https://lightgbm.readthedocs.io/
    [XGBoost]: https://xgboost.readthedocs.io/

    Args:
        model: An input model
        backend: The target for the conversion
        test_input: some input data used to trace the model execution
        extra_config: Extra configurations to be used by the individual operator converters.
                      The set of supported extra configurations can be found at `hummingbird.supported_configurations`

    Examples:
        >>> pytorch_model = convert(sklearn_model,`pytorch`)

    Returns:
        A model implemented in *backend*, which is equivalent to the input model
    """
    _supported_backend_check(backend)

    if type(model) in xgb_operator_list:
        return _convert_xgboost(model, test_input, extra_config)

    if type(model) in lgbm_operator_list:
        return _convert_lightgbm(model, test_input, extra_config)

    return _convert_sklearn(model, test_input, extra_config)


import json
import os.path
import random
random.seed(205)
from outils import *
import stemmer

srcFolder = 'vacancies/'
dstFolder = 'dataset/'
allSkillsFileName = 'skills'
datasetFileName = 'dataset'

vacanciesNames = [srcFolder+item for item in os.listdir(srcFolder)]

jsons = [load_json_vacancy(name) for name in vacanciesNames]

skills = set()
dataset = list()

for vac in jsons:
    skills.update(vac['skills'])
skills = list(skills)

for vac in jsons:
    content = vac['company'] + ' ' + vac['title'] + ' ' + vac['content']
    content = stemmer.stemmize(content)

    existing_skills = vac['skills']
    target = [1.0 if skill in existing_skills else 0.0 for skill in skills]
    dataset.append({'target': target, 'content': content})

save_json_file(allSkillsFileName, list(skills))
save_json_file(datasetFileName, dataset)


"""Read and show meshio objects"""
import meshio
from vtkplotter import datadir, show, Actor, Text, printc

mesh = meshio.read(datadir+'shuttle.obj')

# vtkplotter understands meshio format:
printc(mesh, c='y')
show(mesh, Text(__doc__))

# or explicitly convert it to an Actor object:
a = Actor(mesh).lineWidth(1).color('tomato')
show(a)