from google.appengine.ext import db

from book import Book

import urllib

class Library:

  @staticmethod
  def add_book(self, b_name, b_quantity):

    b = Book(name= b_name, quantity= int(b_quantity))

    urllib.unquote(b.name)

    self.response.write("> Voce cadastrou o livro: " + b.name  + " com "+ str(b.quantity))

    b.put()

  @staticmethod
  def get_books(self):
    books = db.GqlQuery("SELECT * FROM Book")

    self.response.write("LIVRO    |   QUANTIDADE
")

    for b in books:
      self.response.write("- "+b.name +" ----- " + str(b.quantity) + "
")

    self.response.write("
")

  @staticmethod
  def lend_book(self, book_name):
    books = db.GqlQuery("SELECT * FROM Book WHERE name = :1", book_name)

    for b in books:
      b.quantity = int( int(b.quantity) -1 )
      b.put()
      self.response.write("> A quantidade do livro " + b.name +  " eh: " + str(b.quantity))

  @staticmethod
  def return_book(self, book_name):
    books = db.GqlQuery("SELECT * FROM Book WHERE name = :1", book_name)

    for b in books:
      b.quantity = int( int(b.quantity) +1 )
      b.put()
      self.response.write("> A quantidade do livro " + b.name + " eh: " +  str(b.quantity))

  @staticmethod
  def delete_book(self, book_name):

    books = db.GqlQuery("SELECT * FROM Book WHERE name = :1", book_name)
    for b in books:
      b.delete()

    self.response.write("> Voce apagou o livro " + book_name +"do banco!")

  @staticmethod
  def delete_all(self):

    books= db.GqlQuery("SELECT * FROM Book")
    for b in books:
      b.delete()

    self.response.write("> Voce apagou o banco!
")


'''
Created on Feb 19, 2017

@author: jjordening
'''

import cv2
import numpy as np

def minValImage(arr, channel=0):
    """
    Determines the minimum value of arr in a channel
    """
    return np.min(np.min(np.min(arr[:, :, :, channel], axis=1), axis=1), axis=0)

def maxValImage(arr, channel=0):
    """
    Determines the maximium value of arr in a channel
    """
    return np.max(np.max(np.max(arr[:, :, :, channel], axis=0), axis=0), axis=0)

def addGrayLayer(image):
    """
    Adds a gray layer as a fourth channel to an image

    Input:
        image

    Output:
        an array of images with the channels RGBGray
    """
    gray = cv2.cvtColor(image, cv2.CV_HLS2GRAY)
    return np.concatenate((image, gray.reshape((image.shape[0], image.shape[1], 1))), axis=2)

def addGradientLayer(image, sobel_kernel=3, magThresh=(0, 255), dirThresh=(0, np.pi/2)):
    """
    Adds a gray layer as a fourth channel to an image

    Input:
        image

    Output:
        an array of images with the channels RGBGray
    """
    sobelx = cv2.Sobel(image[:, :, 1], cv2.CV_64F, 1, 0, ksize=sobel_kernel)
    sobely = cv2.Sobel(image[:, :, 1], cv2.CV_64F, 0, 1, ksize=sobel_kernel)
    # Calculate the gradient magnitude
    gradMag = np.sqrt(sobelx**2 + sobely**2)
    absGradDir = np.arctan2(np.absolute(sobely), np.absolute(sobelx))
    # Rescale to 8 bit
    scaleFactor = np.max(gradMag)/255
    gradMag = (gradMag/scaleFactor).astype(np.uint8)
    # Create a binary image of ones where thresholds are met, zeros otherwise
    binaryOutput = np.zeros_like(gradMag)
    binaryOutput[(gradMag >= magThresh[0]) & (gradMag <= magThresh[1]) &
                 (absGradDir >= dirThresh[0]) & (absGradDir <= dirThresh[1])] = 1
    # Return the binary image
    return np.concatenate((image, binaryOutput.reshape((image.shape[0], image.shape[1], 1))) , axis=2)

def applyNormalisation(image):
    """
        Applies a normalisation to an image with the channels RGBGray.
        It applies a CLAHE normalisation to the gray layer and then normalises the
        values such, that they have a mean of 0 and a deviation of 1

        Input:
            image

        Output:
            an array of images with the channels RGBGray
    """
    #clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
    #image[:,:,3] = clahe.apply(image[:,:,3])
    return image / 255.

def convertRGBToHSV(img):
    temp = np.zeros(img.shape)
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            r = img[i, j, 0]
            g = img[i, j, 1]
            b = img[i, j, 2]
            maximum = np.max([r, g, b])
            minimum = np.min([r, g, b])
            if maximum == minimum:
                temp[i, j, 0] = 0
            elif maximum == r:
                temp[i, j, 0] = 1./6.*(g - b)/(maximum - minimum)
            elif maximum == g:
                temp[i, j, 0] = 1./6.*(2 + (b - r)/(maximum - minimum))
            else:
                temp[i, j, 0] = 1./6.*(4+(r - g) / (maximum - minimum))
            if temp[i, j, 0] < 0 :
                temp[i, j, 0] += 1.
            temp[i, j, 1] = 0 if maximum == 0 else (maximum-minimum)/maximum
            temp[i, j, 2] = maximum
    return temp

def convertHSVToRGB(img):
    temp = np.zeros(img.shape)
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            f = img[i, j, 0]*6.
            hi = int(f)
            f -= hi
            p = img[i, j, 2]*(1. - img[i, j, 1])
            q = img[i, j, 2]*(1. - f*img[i, j, 1])
            t = img[i, j, 2]*(1. - (1.-f)*img[i, j, 1])
            if hi == 0 or hi == 6:
                temp[i, j] = [img[i, j, 2], t, p]
            elif hi == 1:
                temp[i, j] = [q, img[i, j, 2], p]
            elif hi == 2:
                temp[i, j] = [p, img[i, j, 2], t]
            elif hi == 3:
                temp[i, j] = [p, q, img[i, j, 2]]
            elif hi == 4:
                temp[i, j] = [t, p, img[i, j, 2]]
            else:
                temp[i, j] = [img[i, j, 2], p, q]
    return temp

def augmentImageAndLabel(image, label, depth=None):
    image = lightImage(image)
    shiftHor = np.random.randint(-30,31)
    shiftVer = np.random.randint(-30,31)
    image = shiftImg(image, shiftHor, shiftVer)
    image = blurImage(image)
    label = shiftImg(label, shiftHor, shiftVer)
    np.clip(image, 0, 255, image)
    if depth is not None:
        depth = shiftImg(depth, shiftHor, shiftVer)
        return image, label, depth
    return image, label

def augmentImage(image, label):
    #rot = int(np.random.rand()**2*90 -45)
    rot = int(np.random.rand()**2*60 - 30)
    image = rotateImage(image, rot)
    # Add a part of the rotated angle, as it is counted counter-clockwise.
    # If you turn counter-clockwise, this looks like the car would be more left
    # and needs to drive to the right -> add some angle
    # divide it by the maximum of the steering angle in deg ->25
    label[0] -= 3*rot/(30)
    label[1] -= .2*rot/20
    #label[2] += .1*rot/10
    shiftHor = np.random.randint(-40,41)
    shiftVer = np.random.randint(-5,6)
    image = shiftImg(image, shiftHor, shiftVer)
    #label[0] *= (1-shiftVer/100)
    label[0] += 2.5*shiftHor/(40)
    label[1] -= .3*shiftHor/40
    #label[2] += .1*shiftHor/40steering
    label[0] = min(max(label[0], -5),5)
    label[1] = min(max(label[1], -1),1)
    label[2] = min(max(label[2], -1),1)
    #image = lightImage(blurImage(image))
    return image, label

def blurImage(img):
    # Blur image with random kernel
    kernel_size = np.random.randint(1, 5)
    if kernel_size % 2 != 1:
        kernel_size += 1
    return cv2.GaussianBlur(img, (kernel_size, kernel_size), 0)

def lightImage(img):
    # HSV brightness transform
    img = cv2.cvtColor(img,cv2.COLOR_RGB2HSV)
    brightness = np.random.uniform(0.8,1.1)
    img[:,:,2] = img[:,:,2]*brightness
    np.clip(img, 0, 255, img)
    return cv2.cvtColor(img,cv2.COLOR_HSV2RGB)

def preprocessImage(image):
    """
    This function represents the default preprocessing for
    an image to prepare them for the network
    """
    #image = cv2.resize(image, (320, 160))[::-1]
    #image = image[image.shape[0]*1//5:image.shape[0]*7//8,:,:]
    #image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
    #image = cv2.convertScaleAbs(image, alpha=(1))
    #image = addGradientLayer(image, 7, (100,255), (0, np.pi/2))
    image = applyNormalisation(image)
    return image

def preprocessImages(arr):
    """
    This function represents the default preprocessing for
    images to prepare them for the network
    """
    return np.array([preprocessImage(image) for image in arr])

def perspectiveTransform(img, M):
    h, w = img.shape[:2]
    return cv2.warpPerspective(img, M, (w,h), flags=cv2.INTER_LINEAR)

def shiftImg(arr, horizontal, vertical):
    if len(arr.shape) == 2:
        if(horizontal > 0):
            arr = np.concatenate((arr[horizontal:,:],np.zeros((horizontal,arr.shape[1]))), axis=0)
        elif(horizontal < 0):
            arr = np.concatenate((np.zeros((np.abs(horizontal),arr.shape[1])), arr[:horizontal,:]), axis=0)
        if(vertical > 0):
            arr = np.concatenate((arr[:,vertical:],np.zeros((arr.shape[0],vertical))), axis=1)
        elif(vertical < 0):
            arr = np.concatenate((np.zeros((arr.shape[0], np.abs(vertical))), arr[:,:vertical]), axis=1)

    else:
        if(horizontal > 0):
            arr = np.concatenate((arr[horizontal:], np.zeros((horizontal, arr.shape[1], arr.shape[2]))), axis=0)
        elif(horizontal < 0):
            arr = np.concatenate((np.zeros((np.abs(horizontal), arr.shape[1], arr.shape[2])), arr[:horizontal]), axis=0)
        if(vertical > 0):
            arr = np.concatenate((arr[:, vertical:], np.zeros((arr.shape[0], vertical, arr.shape[2]))), axis=1)
        elif(vertical < 0):
            arr = np.concatenate((np.zeros((arr.shape[0], np.abs(vertical), arr.shape[2])), arr[:,:vertical]), axis=1)
    return arr

"""def shiftImg(arr, horizontal, vertical):

        This function shifts an image horizontally and vertically
        Input:
            horizontal - amplitude of shift in pixels (positive to the right
            negative to the left)
            vertical - aplitude of the ishift in pixels (positive downwards
            negative upwards)

    M = np.float32([[1,0,1*horizontal],[0,1,vertical]])
    return cv2.warpAffine(arr,M,(arr.shape[1], arr.shape[0]))"""

def mirrorImage(img):
    """
        This function mirrors the handed image around the y-axis
    """
    return img[:,::-1]

def rotateImage(img, angle):
    """
        Rotates image around the point in the middle of the bottom of the picture by
        angle degrees.
    """
    rotation = cv2.getRotationMatrix2D((img.shape[0], img.shape[1]//2), angle, 1)
    return cv2.warpAffine(img, rotation, (img.shape[1], img.shape[0]))

def rotateImages(arr, angles):
    """
        Rotates multiple images by the given angles.
    """
    arr = [rotateImage(img, angle) for img, angle in zip(arr, angles)]
    return arr


'''
Created on Jun 3, 2014

@author: CKenley
'''
from django.test import TestCase, Client
from core.models import Purchase_order, Sell_order

class CoreViewsTestCase(TestCase):

    def setUp(self):
        self.client = Client()
        Purchase_order.objects.create(
                                      id=1,
                                      amount=1,
                                      price=99.99,
                                      order_type="MB",
                                      user_id=1
                                      )

    def test_index(self):
        resp = self.client.get('/bitcoinwizard/')
        self.assertEqual(resp.status_code, 200)


import os
import sys
import argparse

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Recursively get the size of folders.')
    parser.add_argument('path', metavar='-p', default="cwd",
                        help='use this path instead of the current path')
    args = parser.parse_args()
    path = args.path[1]
    if path == "cwd":
        path = os.getcwd()


import json
from block import Block
from settings import MAP_PATH

class Map_Loader(object):
    def __init__(self):
        with open(MAP_PATH, encoding='utf-8') as data_file:
            data = json.load(data_file)
            self.blocks = data["blocks"]
            self.maps = data["maps"]
            self.title = None
        self.level = -1

    def next_map(self):
        if len(self.maps) - 1 > self.level:
            self.level += 1
            self.title = self.maps[self.level]["title"]
            return self.level
        return None

    def get_blocks(self):
        return [Block(block["x"], block["y"], *self.blocks[block["kind"]]) for block in self.maps[self.level]["blocks"]]


from marvinbot.utils import localized_date, get_message, trim_markdown
from marvinbot.handlers import CommonFilters, CommandHandler, MessageHandler, CallbackQueryHandler
from marvinbot.plugins import Plugin
from marvinbot.net import download_file

from telegram import MessageEntity, InlineKeyboardMarkup, InlineKeyboardButton
from telegram import ChatAction

import re
import logging
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials

from mp3_tagger import MP3File, VERSION_BOTH

log = logging.getLogger(__name__)

class SpotifyPlugin(Plugin):
    AUTH_BASE_URL = 'https://accounts.spotify.com/api/token'
    API_BASE_URL = 'https://api.spotify.com/v1/'

    def __init__(self):
        super(SpotifyPlugin, self).__init__('spotify')
        self.spotify = None
        self.url_pattern = None

    def get_default_config(self):
        return {
            'short_name': self.name,
            'enabled': True,
            'client_id': "",
            'client_secret': "",
            'url_pattern': r"https://open\.spotify\.com/(?P<type>track|album|artist)/(?P<id>[a-zA-Z0-9]+)"
        }

    def configure(self, config):
        log.info("Initializing Spotify Plugin")
        client_id = config.get("client_id")
        del config["client_id"]
        client_secret = config.get("client_secret")
        del config["client_secret"]
        self.url_pattern = re.compile(config.get("url_pattern"), flags=re.IGNORECASE)
        client_credentials_manager = SpotifyClientCredentials(client_id=client_id, client_secret=client_secret)
        self.spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

    def setup_handlers(self, adapter):
        self.add_handler(CommandHandler('spotify', self.on_spotify_command, command_description='Allows the user to '
                                                                                'search for songs on '
                                                                                'Spotify.')
                         #  .add_argument('--artists', help='Search for artists', action='store_true')
                         #  .add_argument('--albums', help='Search for albums', action='store_true')
                         #  .add_argument('--playlists', help='Search for playlists', action='store_true')
                         # .add_argument('--skip', help='Results to skip', default='0')
                         .add_argument('--count', help='Number of results', default='1')
                         .add_argument('terms', nargs='*', help='Search terms'))
        self.add_handler(MessageHandler(CommonFilters.entity(MessageEntity.URL), self.on_url))
        self.add_handler(CallbackQueryHandler('spotify:fetch-preview', self.on_button), priority=1)

    def on_spotify_command(self, update, **kwargs):
        message = get_message(update)
        query = (" ".join(kwargs.get('terms'))).strip()
        if query == '':
            return

        artists = kwargs.get('artists')
        albums = kwargs.get('albums')
        playlists = kwargs.get('playlists')
        n = int(kwargs.get('count', 1))
        n = n if n >= 1 else 1
        s = int(kwargs.get('skip', 0))
        s = s if s >= 0 else 0

        if artists:
            query_type = 'artist'
        elif albums:
            query_type = 'album'
        elif playlists:
            query_type = 'playlist'
        else:
            query_type = 'track'

        data = self.spotify.search(q=query, type=query_type)

        responses = []
        if query_type == 'track':
            for item in data["tracks"]["items"][s:s + n]:
                artists = ", ".join(
                    map(lambda a: "[{}]({})".format(trim_markdown(a["name"]),
                                                    a["external_urls"]["spotify"]), item["artists"]))
                track = "[{}]({})".format(trim_markdown(item["name"]), item["external_urls"]["spotify"])
                album = "[{}]({})".format(trim_markdown(item["album"]["name"]),
                                          item["album"]["external_urls"]["spotify"])
                response = "🎼 {track}\n🎙 {artists}\n💽 {album}".format(track=track, album=album, artists=artists)
                responses.append(response)
        else:
            self.adapter.bot.sendMessage(chat_id=message.chat_id, text="Not yet implemented")
            return

        if not responses:
            self.adapter.bot.sendMessage(chat_id=message.chat_id, text="No results")
            return

        track_id = data["tracks"]["items"][s]["id"]

        callback_data = "{name}:{action}:{track_id}".format(name=self.name, action="fetch-preview", track_id=track_id)

        url = "https://open.spotify.com/track/{}".format(track_id)
        listen_on_spotify = InlineKeyboardButton(text="Listen on Spotify", url=url)
        if data["tracks"]["items"][s]["preview_url"]:
            preview_button = InlineKeyboardButton(text="Preview", callback_data=callback_data)
            keyboard = [[preview_button, listen_on_spotify]]
        else:
            keyboard = [[listen_on_spotify]]
        reply_markup = InlineKeyboardMarkup(keyboard)
        self.adapter.bot.sendMessage(chat_id=message.chat_id,
                                     text="\n\n".join(responses),
                                     parse_mode="Markdown",
                                     disable_web_page_preview=True,
                                     reply_markup=reply_markup)

    def on_url(self, update):
        message = get_message(update)

        urls = map(lambda url: message.text[url.offset:url.offset + url.length],
                   filter(lambda entity: entity.type == MessageEntity.URL, message.entities))

        for url in urls:
            m = self.url_pattern.match(url)
            if not m:
                continue
            if m.group("type") == "track":
                track_id = m.group("id")
                preview_url, filename, track_name, artists = self.get_track_preview(track_id)

                if preview_url is None or len(preview_url) == 0:
                    log.info("Not fetching %s - %s. Reason: preview_url is empty", artists, track_name)
                    continue
                log.info("Fetching %s - %s", artists, track_name)
                self.fetch_and_send(message.chat_id, preview_url, filename, track_name, artists)
            if m.group("type") == "album":
                album_id = m.group("id")
                data = self.spotify.album(album_id)
                artists = ", ".join(
                    map(lambda artist: "[{}]({})".format(trim_markdown(artist["name"]),
                                                         artist["external_urls"]["spotify"]), data["artists"]))
                album = "[{}]({})".format(trim_markdown(data["name"]), data["external_urls"]["spotify"])
                release_date = data.get("release_date")
                responses = []
                responses.append(
                    "💽 {album}\n🎙 {artists}\n📅 {release_date}\n".format(release_date=release_date, album=album,
                                                                           artists=artists))
                for item in data["tracks"]["items"]:
                    responses.append(
                        "🎼 [{name}]({url})".format(name=item["name"], url=item["external_urls"]["spotify"]))
                self.adapter.bot.sendMessage(
                    chat_id=message.chat_id,
                    text='\n'.join(responses),
                    disable_web_page_preview=True,
                    parse_mode="Markdown")

    def on_button(self, update):
        query = update.callback_query
        data = query.data.split(":")
        track_id = data[2]
        query.answer('Fetching...')
        url = "https://open.spotify.com/track/{}".format(track_id)
        listen_on_spotify = InlineKeyboardButton(text="Listen on Spotify", url=url)
        keyboard = [[listen_on_spotify]]
        query.message.edit_reply_markup(reply_markup=InlineKeyboardMarkup(keyboard))
        preview_url, filename, track_name, artists = self.get_track_preview(track_id)
        self.fetch_and_send(query.message.chat_id, preview_url, filename, track_name, artists)

    def get_track_preview(self, track_id):
        track = self.spotify.track(track_id)
        preview_url = track["preview_url"]
        track_name = track["name"]
        artists = ", ".join(
            map(lambda a: trim_markdown(a["name"]), track["artists"]))
        filename = "{} - {}.mp3".format(artists, track_name)
        return preview_url, filename, track_name, artists

    def fetch_and_send(self, chat_id, url, target_filename, track_name, artists):
        def on_done(filename):
            self.adapter.bot.sendChatAction(chat_id=chat_id, action=ChatAction.UPLOAD_AUDIO)
            mp3 = MP3File(filename)
            mp3.song = track_name
            mp3.artist = artists
            mp3.set_version(VERSION_BOTH)
            mp3.save()
            with open(filename, 'rb') as fp:
                self.adapter.bot.sendAudio(chat_id=chat_id, audio=fp, timeout=60)

        download_file(url=url, on_done=on_done, target_filename=target_filename)


from flask import Flask, render_template, request, redirect
from flask_socketio import SocketIO
import EntityCreationForm, ClassCreationForm, RaceCreationForm, ItemCreationForm

import pymysql

connection = pymysql.connect(host="localhost",user="root",passwd="",database="nat20")
connection.autocommit(True)

cursor = connection.cursor()

app = Flask(__name__)
app.config['SECRET_KEY'] = 'UEsYH1aeEkYaK2KUldAVvg#'
socketio = SocketIO(app)

@app.route('/', methods=['GET', 'POST'])
def main_page():
    if request.method == 'POST':
        if(request.form.get("Create Entity")):
            return redirect("/createEntity")
        elif(request.form.get("Create Class")):
            return redirect("/createClass")
        elif(request.form.get("Create Race")):
            return redirect("/createRace")
        elif(request.form.get("Create Item")):
            return redirect("/createItem")
        elif(request.form.get("Create Tile")):
            pass
            #return redirect("/createTile")
        elif(request.form.get("Save")):
            pass

    return render_template('adventurepackcreator.html', title='Adventure Pack Creator')

@app.route('/createEntity', methods=['GET', 'POST'])
def handle_entity_creation():
    form = EntityCreationForm.EntityCreationForm()
    if("cancel" in request.form):
        return redirect("/")

    if(form.validate_on_submit()):
        #Do stuff
        return redirect("/")

    return render_template('createEntity.html', title='Entity Creator', form=form)

@app.route('/createClass', methods=['GET', 'POST'])
def handle_class_creation():
    form = ClassCreationForm.ClassCreationForm()
    if("cancel" in request.form):
        return redirect("/")

    if(form.validate_on_submit()):
        query = "INSERT INTO classes(name, description, castingStat) VALUES (\"%s\", \"%s\", \"%s\")" % (form.className.data, form.classDescription.data, dict(form.castAttribute.choices).get(form.castAttribute.data))
        cursor.execute(query)
        return redirect("/")

    return render_template("classCreator.html", title='Class Creator', form=form)

@app.route('/createRace', methods=['GET', 'POST'])
def handle_race_creation():
    form = RaceCreationForm.RaceCreationForm()
    if("cancel" in request.form):
        return redirect("/")

    if(form.validate_on_submit()):
        query = "INSERT INTO races(name, strength, dexterity, endurance, charisma, sorcery, willpower) VALUES(\"%s\", %d, %d, %d, %d, %d, %d)" % (form.raceName.data, form.strengthBonus.data, form.dexterityBonus.data, form.enduranceBonus.data, form.charismaBonus.data, form.sorceryBonus.data, form.willpowerBonus.data)
        cursor.execute(query)
        return redirect("/")

    return render_template("raceCreator.html", title='Race Creator', form=form)

@app.route('/createItem', methods=['GET', 'POST'])
def handle_item_creation():
    form = ItemCreationForm.ItemCreationForm()
    if("cancel" in request.form):
        return redirect("/")

    if(form.validate_on_submit()):
        val = "item"
        otherVal = 5

        if form.itemType.data == "spell":
            val = "magic"
        elif form.itemType.data == "weapon":
            val = "weapon"
        elif form.itemType.data == "item":
            otherVal = 0
            if form.itemUsable.data:
                val = "potion"

        query = "INSERT INTO items(name, type, value, modifier, itemRange) VALUES (\"%s\", \"%s\", %d, %d, %d)" % (form.itemName.data, val, 10, 10, otherVal)
        cursor.execute(query)
        return redirect("/")

    return render_template("itemCreator.html", title='Item Creator', form=form)

if __name__ == '__main__':
    socketio.run(app, debug=True)

connection.close()


from ..layers import Layer
from ..utils.naming import inc_name_count
from ..utils.list import ListModel

def _add(event):
    """When a layer is added, set its name."""
    layers = event.source
    layer = event.item
    layer.name = layers._coerce_name(layer.name, layer)
    layer.events.name.connect(lambda e: layers._update_name(e))
    layers.unselect_all(ignore=layer)

class LayerList(ListModel):
    """List-like layer collection with built-in reordering and callback hooks.

    Parameters
    ----------
    iterable : iterable
        Iterable of napari.layer.Layer

    Attributes
    ----------
    events : vispy.util.event.EmitterGroup
        Event hooks:
            * added(item, index): whenever an item is added
            * removed(item): whenever an item is removed
            * reordered(): whenever the list is reordered
    """

    def __init__(self, iterable=()):
        super().__init__(
            basetype=Layer,
            iterable=iterable,
            lookup={str: lambda q, e: q == e.name},
        )

        self.events.added.connect(_add)

    def __newlike__(self, iterable):
        return ListModel(self._basetype, iterable, self._lookup)

    def _coerce_name(self, name, layer=None):
        """Coerce a name into a unique equivalent.

        Parameters
        ----------
        name : str
            Original name.
        layer : napari.layers.Layer, optional
            Layer for which name is generated.

        Returns
        -------
        new_name : str
            Coerced, unique name.
        """
        for l in self:
            if l is layer:
                continue
            if l.name == name:
                name = inc_name_count(name)

        return name

    def _update_name(self, event):
        """Coerce name of the layer in `event.layer`."""
        layer = event.source
        layer.name = self._coerce_name(layer.name, layer)

    def move_selected(self, index, insert):
        """Reorder list by moving the item at index and inserting it
        at the insert index. If additional items are selected these will
        get inserted at the insert index too. This allows for rearranging
        the list based on dragging and dropping a selection of items, where
        index is the index of the primary item being dragged, and insert is
        the index of the drop location, and the selection indicates if
        multiple items are being dragged. If the moved layer is not selected
        select it.

        Parameters
        ----------
        index : int
            Index of primary item to be moved
        insert : int
            Index that item(s) will be inserted at
        """
        total = len(self)
        indices = list(range(total))
        if not self[index].selected:
            self.unselect_all()
            self[index].selected = True
        selected = [i for i in range(total) if self[i].selected]

        # remove all indices to be moved
        for i in selected:
            indices.remove(i)
        # adjust offset based on selected indices to move
        offset = sum([i < insert and i != index for i in selected])
        # insert indices to be moved at correct start
        for insert_idx, elem_idx in enumerate(selected, start=insert - offset):
            indices.insert(insert_idx, elem_idx)
        # reorder list
        self[:] = self[tuple(indices)]

    def unselect_all(self, ignore=None):
        """Unselects all layers expect any specified in ignore.

        Parameters
        ----------
        ignore : Layer | None
            Layer that should not be unselected if specified.
        """
        for layer in self:
            if layer.selected and layer != ignore:
                layer.selected = False

    def select_all(self):
        """Selects all layers."""
        for layer in self:
            if not layer.selected:
                layer.selected = True

    def remove_selected(self):
        """Removes selected items from list."""
        to_delete = []
        for i in range(len(self)):
            if self[i].selected:
                to_delete.append(i)
        to_delete.reverse()
        for i in to_delete:
            self.pop(i)
        if len(to_delete) > 0:
            first_to_delete = to_delete[-1]
            if first_to_delete == 0 and len(self) > 0:
                self[0].selected = True
            elif first_to_delete > 0:
                self[first_to_delete - 1].selected = True

    def select_next(self, shift=False):
        """Selects next item from list.
        """
        selected = []
        for i in range(len(self)):
            if self[i].selected:
                selected.append(i)
        if len(selected) > 0:
            if selected[-1] == len(self) - 1:
                if shift is False:
                    self.unselect_all(ignore=self[selected[-1]])
            elif selected[-1] < len(self) - 1:
                if shift is False:
                    self.unselect_all(ignore=self[selected[-1] + 1])
                self[selected[-1] + 1].selected = True
        elif len(self) > 0:
            self[-1].selected = True

    def select_previous(self, shift=False):
        """Selects previous item from list.
        """
        selected = []
        for i in range(len(self)):
            if self[i].selected:
                selected.append(i)
        if len(selected) > 0:
            if selected[0] == 0:
                if shift is False:
                    self.unselect_all(ignore=self[0])
            elif selected[0] > 0:
                if shift is False:
                    self.unselect_all(ignore=self[selected[0] - 1])
                self[selected[0] - 1].selected = True
        elif len(self) > 0:
            self[0].selected = True

    def toggle_selected_visibility(self):
        """Toggle visibility of selected layers"""
        for layer in self:
            if layer.selected:
                layer.visible = not layer.visible


"""Contains the superclass for a game."""
from __future__ import annotations

import copy
import logging
import random
from abc import ABC, abstractmethod

from agent.data import gameplay_action
from agent.environment import agent_actions
from agent.environment import card
from agent.environment import environment_objects
from agent.environment import position
from agent.environment import rotation
from agent.environment import state_delta
from agent.environment import terrain
from agent.environment import util as environment_util
from typing import TYPE_CHECKING

from agent.simulation.planner import get_neighbor_move_position

if TYPE_CHECKING:
    from typing import List, Tuple, Set
    from agent.config import game_args
    from agent.environment import agent

class Game(ABC):
    def __init__(self,
                 args: game_args.GameArgs,
                 leader_actions: List[List[gameplay_action.GameplayAction]] = None,
                 expected_sets: List[Tuple[List[card.Card], List[card.Card]]] = None,
                 auto_end_turn: bool = True,
                 verbose: bool = False,
                 check_valid_state: bool = True):
        """Abstract class for games.

        Args:
            args: Arguments for configuring the game.
            leader_actions: Pre-specified actions the leader should take (e.g., when interleaving with sent follower
                actions).
            expected_sets: Sets of cards that should be made (in order) during the game.
            auto_end_turn: Whether turns should be automatically ended when players run out of moves.
            verbose: Whether to log actions taken in the game to the console.
            check_valid_state: Whether to check that expected sets are made.
        """
        self._args: game_args.GameArgs = args
        self._verbose = verbose
        self._check_valid_state = check_valid_state

        # Initialize the environment information as null for now
        self._hexes: List[Tuple[terrain.Terrain, position.Position]] = []
        self._obstacle_positions: Set[position.Position] = set()
        self._objects: List[environment_objects.EnvironmentObject] = []
        self._env_width: int = environment_util.ENVIRONMENT_WIDTH
        self._env_depth: int = environment_util.ENVIRONMENT_DEPTH
        self._current_state_delta: state_delta.StateDelta = None
        self._obstacle_positions: List[position.Position] = []

        # Initialize the game playing logistics
        self._current_turn_index: int = 0
        self._turns_left: int = self._args.get_initial_number_of_turns()
        self._is_leader_turn: bool = True
        self._num_moves_left: int = self._args.get_leader_moves_per_turn()
        self._score: int = 0

        self._instruction_buffer: List[str] = list()

        self._keep_track_of_turns: bool = args.keep_track_of_turns()
        self._auto_end_turn: bool = auto_end_turn

        # Expected sets
        self._expected_sets: List[Tuple[List[card.Card], List[card.Card]]] = copy.deepcopy(expected_sets)
        self._expected_states: List[List[card.Card]] = None
        self._current_state_index: int = 0
        self._current_set_index: int = 0 if expected_sets is not None else None

        # Whether the game is currently in a valid state (i.e., expected cards values)
        self._valid_state: bool = True

        self._leader_actions: List[List[gameplay_action.GameplayAction]] = leader_actions

        self._move_id = 0
        self._num_completed_instructions = 0
        self._turn_id = 0

    @abstractmethod
    def _execute_follower(self, action: agent_actions.AgentAction) -> None:
        pass

    @abstractmethod
    def _execute_leader(self, action: agent_actions.AgentAction) -> None:
        pass

    @abstractmethod
    def _add_cards(self, new_cards: List[card.Card]) -> None:
        pass

    @abstractmethod
    def send_command(self, command: str) -> None:
        pass

    def add_instruction(self, instruction: str):
        """Adds an instruction to the queue."""
        self._instruction_buffer.append(instruction)
        self._move_id += 1
        if self._verbose:
            logging.info('Added instruction: ' + str(instruction))
            logging.info('There are now ' + str(len(self._instruction_buffer)) + ' instructions.')

    def get_instruction_index(self):
        """Gets the current instruction index."""
        return self._num_completed_instructions

    def _execute_leader_actions(self) -> None:
        if self._leader_actions is None:
            raise ValueError('Cannot execute leader actions when none are provided')
        if self._current_turn_index < len(self._leader_actions):
            for action in self._leader_actions[self._current_turn_index]:
                # Stop executing leader actions.
                if not self._valid_state:
                    return

                if isinstance(action, gameplay_action.MovementAction):
                    self.execute_leader_action(action.get_action())
                    if not self._valid_state:
                        break
                elif isinstance(action, gameplay_action.InstructionAction):
                    self.send_command(action.get_instruction())
                    self._instruction_buffer.append(action.get_instruction())
                    if self._verbose:
                        logging.info('Adding instruction ' + str(action.get_instruction()))
            self._current_turn_index += 1
        else:
            if self._verbose:
                logging.info('Not more leader actions to execute')

        if self._verbose:
            logging.info('Done with executing leader actions, so ending the turn')
        self.end_turn()

    def _set_obstacles(self) -> None:
        for hex_terrain, hex_position in self._hexes:
            if hex_terrain in terrain.OBSTACLE_TERRAINS:
                self._obstacle_positions.append(hex_position)
        for obj in self._objects:
            assert obj.get_type() != environment_objects.ObjectType.CARD
            self._obstacle_positions.append(obj.get_position())

    def _check_for_new_set(self, prev_state_delta: state_delta.StateDelta, action: agent_actions.AgentAction,
                           character: environment_objects.ObjectType) -> None:
        """ Checks whether a set was made after the provided state with the action taken."""
        self._current_state_delta = self.get_most_recent_game_info(prev_state_delta, action, character, False)

        # Then check to see if a set was made
        if self._expected_sets is not None:
            new_set: List[card.Card] = state_delta.set_made(prev_state_delta.cards, self._current_state_delta.cards)
            if new_set:
                # Check that this was the expected set
                new_cards: List[card.Card] = []
                if self._current_set_index >= len(self._expected_sets):
                    was_expected_set = False
                else:
                    expected_set: List[card.Card] = self._expected_sets[self._current_set_index][0]
                    new_cards: List[card.Card] = self._expected_sets[self._current_set_index][1]
                    was_expected_set = state_delta.card_states_equal(expected_set, new_set)

                if was_expected_set:
                    self._add_cards(new_cards)
                    self._current_state_delta.cards.extend(new_cards)
                    self._current_set_index += 1
                else:
                    if self._check_valid_state:
                        self._valid_state = False

                    if self._args.generate_new_cards():
                        # Now, generate random new cards...
                        new_generated_cards: List[card.Card] = list()

                        while not state_delta.set_exists(self._current_state_delta.cards + new_generated_cards):
                            # Generate new cards.
                            new_generated_cards = list()
                            for _ in range(3):
                                new_generated_cards.append(card.generate_random_card_properties())

                        # Place the cards
                        updated_generated_cards: List[card.Card] = list()
                        non_obstacle_positions: Set[position.Position] = set()
                        for x in range(environment_util.ENVIRONMENT_DEPTH):
                            for y in range(environment_util.ENVIRONMENT_WIDTH):
                                if position.Position(x, y) not in self._obstacle_positions:
                                    non_obstacle_positions.add(position.Position(x, y))

                        for new_card in new_generated_cards:
                            # Possible locations are all places in the map except those with obstacles, and where other
                            # cards are now.
                            possible_locations: Set[position.Position] = \
                                non_obstacle_positions \
                                - set([current_card.get_position() for current_card in self._current_state_delta.cards])

                            chosen_location: position.Position = random.choice(list(possible_locations))
                            new_card.update_position(chosen_location)

                            # Add the card here now so that it won't place later cards on top of it (unlikely,
                            # but possible)
                            self._current_state_delta.cards.append(new_card)
                            updated_generated_cards.append(new_card)
                        self._add_cards(updated_generated_cards)

    @abstractmethod
    def get_score(self) -> int:
        pass

    @abstractmethod
    def get_game_info(self, force_update: bool = False) -> state_delta.StateDelta:
        pass

    @abstractmethod
    def get_most_recent_game_info(self,
                                  prev_state_delta: state_delta.StateDelta,
                                  action: agent_actions.AgentAction,
                                  character: environment_objects.ObjectType,
                                  need_new_set_cards: bool = False) -> state_delta.StateDelta:
        pass

    def get_hexes(self) -> List[Tuple[terrain.Terrain, position.Position]]:
        return self._hexes

    def get_objects(self) -> List[environment_objects.EnvironmentObject]:
        return self._objects

    def is_leader_turn(self) -> bool:
        return self._is_leader_turn

    def get_num_moves_left(self) -> int:
        return self._num_moves_left

    def valid_state(self) -> bool:
        return self._valid_state

    def get_obstacle_positions(self) -> List[position.Position]:
        return self._obstacle_positions

    def get_remaining_leader_actions(self) -> List[List[gameplay_action.GameplayAction]]:
        """Gets the leader actions remaining in the prespecified leader actions."""
        if self._current_turn_index < len(self._leader_actions):
            return self._leader_actions[self._current_turn_index:]
        return []

    def instruction_buffer_size(self) -> int:
        return len(self._instruction_buffer)

    def get_current_instruction(self) -> str:
        return self._instruction_buffer[0]

    def get_env_width(self) -> int:
        return self._env_width

    def get_env_depth(self) -> int:
        return self._env_depth

    def get_turns_left(self) -> int:
        return self._turns_left

    def get_move_id(self):
        return self._move_id

    def get_turn_index(self):
        return self._turn_id

    def finish_all_leader_actions(self) -> None:
        """Finishes all specified leader actions at once."""
        self._is_leader_turn = True
        while self._current_turn_index < len(self._leader_actions):
            for action in self._leader_actions[self._current_turn_index]:
                if isinstance(action, gameplay_action.MovementAction):
                    self.execute_leader_action(action.get_action())
                if not self._valid_state:
                    return
            self._current_turn_index += 1

    def end_turn(self) -> None:
        """Ends the current player's turn."""
        self._turn_id += 1
        if self._is_leader_turn:
            if self._verbose:
                logging.info('Ending leader turn')
            # If it was the leader's turn, change to the follower's turn.
            self._is_leader_turn = False
            self._num_moves_left = self._args.get_follower_moves_per_turn()

            # But if there aren't any instructions left now, return to the leader's turn.
            if not self._instruction_buffer and \
                    (not self._auto_end_turn or
                     (self._leader_actions is not None and self._current_turn_index < len(self._leader_actions))) and \
                    self._auto_end_turn:
                if self._verbose:
                    logging.info('Automatically ending follower turn because there are no instructions left!')
                self.end_turn()
        else:
            if self._verbose:
                logging.info('Ending follower turn')
            # Only decrease number of turns when the follower has finished.
            self._turns_left -= 1
            self._is_leader_turn = True
            self._num_moves_left = self._args.get_leader_moves_per_turn()

            if self._leader_actions is not None:
                self._execute_leader_actions()

    def reset_state(self,
                    leader_actions: List[List[gameplay_action.GameplayAction]],
                    state: state_delta.StateDelta,
                    num_steps_remaining: int,
                    expected_sets: List[Tuple[List[card.Card], List[card.Card]]],
                    num_instructions: int = 1,
                    expected_states: List[List[card.Card]] = None) -> None:
        """Resets the game state to a specified state."""
        # Reset the internal values in the simulator

        self._expected_states = expected_states
        self._current_state_index: int = 0
        self._current_state_delta = copy.deepcopy(state)

        # The current turn index is wrt. the set of leader actions to take, so reset to zero
        self._current_turn_index: int = 0

        # Reset the number of turns remaining in the game.
        self._turns_left: int = self._args.get_initial_number_of_turns()
        self._instruction_buffer = ['[placeholder]' for _ in range(num_instructions)]

        # Assuming that it's not starting with the leader turn.
        # End turn if it's the leader's turn.
        if self._is_leader_turn:
            self.end_turn()
        self._is_leader_turn: bool = False
        self._num_moves_left: int = num_steps_remaining

        # Set, but do not execute, the leader actions.
        self._leader_actions: List[List[gameplay_action.GameplayAction]] = leader_actions
        self._expected_sets = copy.deepcopy(expected_sets)
        self._current_set_index = 0

        self._valid_state = True

    def _check_if_state_expected(self, card_list: List[card.Card]):
        card_set_same = \
            self._current_state_index < len(self._expected_states) and \
            state_delta.card_states_equal(self._expected_states[self._current_state_index], card_list)
        if not card_set_same:
            # Compare with the next one -- maybe it triggered a card or made a set.
            self._current_state_index += 1

            next_card_set_same = \
                self._current_state_index < len(self._expected_states) \
                and state_delta.card_states_equal(self._expected_states[self._current_state_index], card_list)
            if not next_card_set_same:
                self._valid_state = False

    def execute_follower_action(self, action: agent_actions.AgentAction) -> state_delta.StateDelta:
        if self._verbose:
            logging.info('Executing follower action ' + str(action))
        if action != agent_actions.AgentAction.STOP and len(self._current_state_delta.cards) != 21:
            raise ValueError('There are not 21 cards in the current state!')
        assert isinstance(action, agent_actions.AgentAction)
        if self.is_leader_turn() and self._keep_track_of_turns:
            raise ValueError('Can\'t execute agent action when it\'s the leader\'s turn.')
        if not self._instruction_buffer and self._leader_actions is not None:
            raise ValueError('Should not be able to execute actions when there are '
                             + str(len(self._instruction_buffer))
                             + ' instructions available')

        prev_state_delta: state_delta.StateDelta = copy.deepcopy(self._current_state_delta)

        # Internal execute MUST set the current state delta.
        self._execute_follower(action)

        resulting_state: state_delta.StateDelta = prev_state_delta

        if action != agent_actions.AgentAction.START and action != agent_actions.AgentAction.STOP:
            self._move_id += 1
            self._check_for_new_set(prev_state_delta, action, environment_objects.ObjectType.FOLLOWER)
            resulting_state = copy.deepcopy(self._current_state_delta)

            if self._expected_states:
                # Check that it's in the current state.
                self._check_if_state_expected(resulting_state.cards)

            self._num_moves_left -= 1

            if self._num_moves_left == 0 and self._valid_state and self._auto_end_turn:
                if self._verbose:
                    logging.info('Ending turn because there are no steps left.')
                self.end_turn()
        elif action == agent_actions.AgentAction.STOP:
            self._instruction_buffer = self._instruction_buffer[1:]
            self._num_completed_instructions += 1
            if self._verbose:
                logging.info(str(len(self._instruction_buffer)) + ' in buffer')
            if not self._instruction_buffer and self._auto_end_turn:
                if self._verbose:
                    logging.info('Ending follower turn because there are no instructions left.')
                self.end_turn()

        del prev_state_delta
        return resulting_state

    def execute_leader_action(self, action: agent_actions.AgentAction) -> None:
        if self._verbose:
            logging.info('Executing leader action ' + str(action))
        if len(self._current_state_delta.cards) != 21:
            raise ValueError('There are not 21 cards in the current state!')
        assert isinstance(action, agent_actions.AgentAction)
        if not self.is_leader_turn() and self._keep_track_of_turns:
            raise ValueError('Can\'t execute leader action when it\'s the agent\'s turn.')

        self._move_id += 1

        prev_state_delta: state_delta.StateDelta = copy.deepcopy(self._current_state_delta)

        self._execute_leader(action)

        self._check_for_new_set(prev_state_delta, action, environment_objects.ObjectType.LEADER)

        if self._expected_states:
            self._check_if_state_expected(self._current_state_delta.cards)

        self._num_moves_left -= 1

        if self._num_moves_left == 0 and self._leader_actions is None and self._auto_end_turn:
            self.end_turn()

        del prev_state_delta

    def get_possible_actions(self, player: agent.Agent) -> List[agent_actions.AgentAction]:
        possible_actions: List[agent_actions.AgentAction] = [agent_actions.AgentAction.STOP,
                                                             agent_actions.AgentAction.RR,
                                                             agent_actions.AgentAction.RL]

        player_position: position.Position = player.get_position()
        player_rotation: rotation.Rotation = player.get_rotation()

        facing_position, behind_position = get_neighbor_move_position(player_position, player_rotation)

        if facing_position not in self.get_obstacle_positions() \
                and facing_position.x >= 0 and facing_position.y >= 0 \
                and facing_position.x < environment_util.ENVIRONMENT_WIDTH \
                and facing_position.y < environment_util.ENVIRONMENT_DEPTH:
            possible_actions.append(agent_actions.AgentAction.MF)

        if behind_position not in self.get_obstacle_positions() \
                and behind_position.x >= 0 and behind_position.y >= 0 \
                and behind_position.x < environment_util.ENVIRONMENT_WIDTH \
                and behind_position.y < environment_util.ENVIRONMENT_DEPTH:
            possible_actions.append(agent_actions.AgentAction.MB)

        return possible_actions


from collections import defaultdict, deque
from typing import List

class Solution:
    def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
        """
        rooms = [[1],[2],[3],[]] return True
        """
        roomMap = defaultdict(list)
        n = len(rooms)
        for i in range(n):
            for j in range(len(rooms[i])):
                roomMap[i].append(rooms[i][j])
        count = 0
        queue = deque()
        visited = [False for _ in range(n)]
        queue.append(0)
        while len(queue):
            current = queue.popleft()
            if visited[current]:
                continue
            visited[current]=True
            count+=1
            if count>=n:
                return True
            keys = roomMap[current]
            if len(keys)>0:
                for e in keys:
                    queue.append(e)
        return count>=n

if __name__ == '__main__':
    rooms = [[1], [2], [3], []]
    rooms1 = [[1, 3], [3, 0, 1], [2], [0]]
    print(Solution().canVisitAllRooms(rooms))
    print(Solution().canVisitAllRooms(rooms1))


import json

class RelationActionListLazy(In.core.lazy.HTMLObjectLazy):
	'''list of comments'''

	def __init__(self, data = None, items = None, **args):

		super().__init__(data, items, **args)

		# always set new id
		self.id = 'RelationActionListLazy'

		context = IN.context
		if context.request.ajax_lazy:

			db = IN.db
			connection = db.connection

			nabar_id = context.nabar.id

			if not nabar_id:
				return

			query = IN.db.select({
				'table' : ['relation.relation', 'r'],
				'columns' : ['r.id', 'rr.from_entity_id', 'r.type'],
				'join' : [
					#['inner join', 'relation.relation_member', 'rm', [
					#	['r.id = rm.relation_id']
					#]],
					['inner join', 'relation.relation_request', 'rr', [
						['r.id = rr.relation_id']
					]]
				],
				'where' : [
					['r.relation_status', IN.relater.RELATION_STATUS_REQUESTED],
					['r.status', '>=', 1],
					['rr.to_entity_type', 'Nabar'],
					['rr.to_entity_id', nabar_id]
				],
				'order' : {'rr.created' : 'desc'}
			})

			cursor = query.execute()

			__form_load = IN.former.load

			if cursor.rowcount > 0:

				for row in cursor:

					from_entity_id = row['from_entity_id']

					form = __form_load('RelationActionDirect', args = {
						'from_entity_type' : 'Nabar',
						'from_entity_id' : nabar_id,	# viewer
						'to_entity_type' : 'Nabar',
						'to_entity_id' : from_entity_id,# page
						'relation_type' : row['type']
					})

					self.add(form)

					#remaining = total - limit
					#if remaining > 0 and  last_id > 0:
						#self.add('TextDiv', {
							#'id' : '_'.join(('more-commens', parent_entity_type, str(parent_entity_id), str(self.parent_id))),
							#'value' : str(remaining) + ' more comments',
							#'css' : ['ajax i-text-center pointer i-panel-box i-panel-box-primary'],
							#'attributes' : {
								#'data-href' : ''.join(('/comment/more/!Content/', str(parent_entity_id), '/', str(last_id), '/', str(self.parent_id)))
							#},
							#'weight' : -1
						#})

@IN.register('RelationActionListLazy', type = 'Themer')
class RelationActionListLazyThemer(In.core.lazy.HTMLObjectLazyThemer):
	'''lazy themer'''

	def theme_attributes(self, obj, format, view_mode, args):

		obj.lazy_args['type'] = obj.__type__

		json_args = ''
		try:
			json_args = json.dumps(obj.lazy_args, skipkeys = True, ensure_ascii = False)
		except Exception as e:
			print(9999999999, obj.lazy_args, obj.__type__)
			raise e

		obj.attributes['data-args'] = json_args
		return super().theme_attributes(obj, format, view_mode, args)


import pygame
from random import *

WINDOW_SIZE = WINDOW_WIDTH, WINDOW_HEIGHT = 750, 750
FPS = 30
SPEED = 25

class Tetris:
    def __init__(self):
        self.size = 50
        self.x_pos = WINDOW_WIDTH // 2
        self.y_pos = 0
        self.flag = True
        self.map = []
        self.b = []
        self.figures = ['s', 'z', 'l', 't', 'j', 'o', 'i']

    def render(self, screen):
        if self.flag == True:
            self.what_figure = self.get_figure()
            self.flag = False
        if self.what_figure == 's':
            self.draw_s(screen)
        elif self.what_figure == 'z':
            self.draw_z(screen)
        elif self.what_figure == 'l':
            self.draw_l(screen)
        elif self.what_figure == 't':
            self.draw_t(screen)
        elif self.what_figure == 'j':
            self.draw_j(screen)
        elif self.what_figure == 'o':
            self.draw_o(screen)
        elif self.what_figure == 'i':
            self.draw_i(screen)

    def new_coords(self):
        self.x_pos = WINDOW_WIDTH // 2
        self.y_pos = 0
        self.flag = True

    def get_figure(self):
        self.a = choice(self.figures)
        return self.a

    def get_size(self):
        return self.size

    def get_position(self):
        return self.x_pos, self.y_pos

    def set_position(self, position):
        self.x_pos, self.y_pos = position

    def is_free_left(self, x):
        if x >= SPEED:
            return True

    def is_free_right(self, x):
        if x <= WINDOW_WIDTH - self.size - SPEED:
            return True

    def is_free_down(self, y):
        if y <= WINDOW_HEIGHT - self.size - 7:
            return True

    def is_free_down_low(self, y):
        if y <= WINDOW_HEIGHT - self.size - 2:
            return True

    def draw_s(self, screen):
        pygame.draw.polygon(screen, pygame.Color('red'),
                            [(self.x_pos, self.y_pos),
                             (self.x_pos + self.size * 2, self.y_pos),
                             (self.x_pos + self.size * 2, self.size + self.y_pos),
                             (self.x_pos + self.size, self.size + self.y_pos),
                             (self.x_pos + self.size, self.size * 2 + self.y_pos),
                             (self.x_pos - self.size, self.size * 2 + self.y_pos),
                             (self.x_pos - self.size, self.size + self.y_pos),
                             (self.x_pos, self.size + self.y_pos)])

    def draw_z(self, screen):
        pygame.draw.polygon(screen, pygame.Color('orange'),
                            [(self.x_pos - self.size, self.y_pos),
                             (self.x_pos + self.size, self.y_pos),
                             (self.x_pos + self.size, self.size + self.y_pos),
                             (self.x_pos + self.size * 2, self.size + self.y_pos),
                             (self.x_pos + self.size * 2, self.size * 2 + self.y_pos),
                             (self.x_pos, self.size * 2 + self.y_pos),
                             (self.x_pos, self.size + self.y_pos),
                             (self.x_pos - self.size, self.size + self.y_pos)])

    def draw_j(self, screen):
        pygame.draw.polygon(screen, pygame.Color('pink'),
                            [(self.x_pos, self.y_pos),
                             (self.x_pos + self.size, self.y_pos),
                             (self.x_pos + self.size * 2, self.y_pos),
                             (self.x_pos + self.size * 2, self.size + self.y_pos),
                             (self.x_pos + self.size, self.size + self.y_pos),
                             (self.x_pos + self.size, self.size * 3 + self.y_pos),
                             (self.x_pos, self.size * 3 + self.y_pos)])

    def draw_t(self, screen):
        pygame.draw.polygon(screen, pygame.Color('blue'),
                            [(self.x_pos - self.size, self.y_pos),
                             (self.x_pos + self.size * 2, self.y_pos),
                             (self.x_pos + self.size * 2, self.size + self.y_pos),
                             (self.x_pos + self.size * 2, self.size + self.y_pos),
                             (self.x_pos + self.size, self.size + self.y_pos),
                             (self.x_pos + self.size, self.size * 2 + self.y_pos),
                             (self.x_pos, self.size * 2 + self.y_pos),
                             (self.x_pos, self.size + self.y_pos),
                             (self.x_pos - self.size, self.size + self.y_pos)])

    def draw_l(self, screen):
        pygame.draw.polygon(screen, pygame.Color('yellow'),
                            [(self.x_pos, self.y_pos),
                             (self.x_pos - self.size * 2, self.y_pos),
                             (self.x_pos - self.size * 2, self.size + self.y_pos),
                             (self.x_pos - self.size, self.size + self.y_pos),
                             (self.x_pos - self.size, self.size * 3 + self.y_pos),
                             (self.x_pos, self.size * 3 + self.y_pos)])

    def draw_o(self, screen):
        pygame.draw.rect(screen, pygame.Color('green'),
                         (self.x_pos - self.size, self.y_pos,
                          self.size * 2, self.size * 2), 0)

    def draw_i(self, screen):
        pygame.draw.rect(screen, pygame.Color('purple'),
                         (self.x_pos - self.size, self.y_pos,
                          self.size, self.size * 4), 0)

class Move:
    def __init__(self, tetris):
        self.tetris = tetris

    def render(self, screen):
        self.tetris.render(screen)

    def update_figure(self):
        self.next_x, self.next_y = self.tetris.get_position()
        if pygame.key.get_pressed()[pygame.K_LEFT]:
            if self.tetris.is_free_left(self.next_x):
                    self.next_x -= SPEED
        if pygame.key.get_pressed()[pygame.K_RIGHT]:
            if self.tetris.is_free_right(self.next_x):
                self.next_x += SPEED
        if pygame.key.get_pressed()[pygame.K_DOWN]:
            if self.tetris.is_free_down(self.next_y):
                self.next_y += 10
            else:
                self.next_y += WINDOW_WIDTH - self.tetris.get_size() - self.next_y
        if self.tetris.is_free_down_low(self.next_y):
            self.next_y += 4
        else:
            self.next_y += WINDOW_WIDTH - self.tetris.get_size() - self.next_y
        self.tetris.set_position((self.next_x, self.next_y))
        if self.next_y == WINDOW_WIDTH - self.tetris.get_size():
            self.tetris.new_coords()

def main():
    pygame.init()
    screen = pygame.display.set_mode(WINDOW_SIZE)
    clock = pygame.time.Clock()
    tetris = Tetris()
    move = Move(tetris)
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
        move.update_figure()
        screen.fill(pygame.Color('gray'))
        move.render(screen)
        move.update_figure()
        pygame.display.flip()
        clock.tick(FPS)
    pygame.quit()

if __name__ == "__main__":
    main()


# coding=utf-8
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.http import HttpResponse
from django.template import loader, Context
import os
# 工具函数导入
from webapi.tools import random_str, pack, tokenActive, log
import time
import chardet
import subprocess
import urllib2, qcloud_cos
import requests
from Conline.settings import STATIC_URL, BASE_DIR
import binascii
# model导入
from webapi.models import Section, User, EditSection, Record

# 日志导入
from webapi.tools import Debuglog

# 定义section文件地址
sectionfiledir = BASE_DIR + os.sep + 'static' + os.sep + 'sectionfile' + os.sep

# 获取章节列表
@csrf_exempt
def getSectionList(request):
    try:
        model = []
        user = tokenActive(request.COOKIES)
        if isinstance(user, User) and request.body == '':
            sectionlist = list(Section.objects.all().filter(creator=user.userid))
        else:
            body = eval(request.body)
            sectionlist = list(Section.objects.all().filter(father=body['courseid']).order_by('creattime'))
            # 记录用户查看课程的记录
            if isinstance(user, User):
                record = Record(userid=user.userid, courseid=body['courseid'], time=int(1000 * time.time()))
                record.save()
        if len(sectionlist) > 0:
            for section in sectionlist:
                model.append({
                    'sectionid': section.sectionid,
                    'title': section.title,
                    'creator': section.creator,
                    'type': section.type,
                    'creattime': section.creattime
                })
        return pack(data=model)
    except Exception as e:
        return pack(msg=e)

# 获取章节内容详情
@csrf_exempt
def getSectionDetail(request):
    try:
        body = eval(request.body)
        section = list(Section.objects.all().filter(sectionid=body['sectionid']))
        if len(section) == 0:
            raise Exception('课程id错误')
        section = section[0]
        model = {
            'sectionid': section.sectionid,
            'title': section.title,
            'creator': section.creator,
            'type': section.type,
            'content': section.content,
            'fileurl': section.fileurl,
            'father': section.father,
            'creattime': section.creattime
        }
        return pack(data=model)
    except Exception as e:
        return pack(msg=e)

# 创建章节内容
@csrf_exempt
def creatSection(request):
    try:
        body = request.POST.dict()
        if 'courseid' not in body:
            t = loader.get_template('upload.html')
            return HttpResponse(t.render())
        user = tokenActive({'token': body['token']})
        if not isinstance(user, User):
            return pack(code=user)
        # 如果是学生，那么不让创建
        if user.type == 0:
            return pack(msg='学生无法创建课程')
        # 获取当前时间戳
        now = int(1000 * time.time())
        id = random_str()
        section = EditSection(sectionid=id, creattime=now, creator=user.userid, type=body['type'], title=body['title'],
                          father=body['courseid'], operator=0)
        # 获取上传的文件，如果没有文件，则默认为None
        file = request.FILES.get("file", None)
        if not file:
            pack(msg="no files for upload!")

        # 文字文件和视频文件分别处理
        if body['type'] == '1':
            appid = 1252409052
            secret_id = u'AKIDQkspaAxYEZItIV7K2axCF6yuhHIDfVr0'
            secret_key = u'CG8nkZJtJXaS7au1vdJsGtOp4JQQFsRp'
            region_info = u"tj"
            cos_client = qcloud_cos.CosClient(appid, secret_id, secret_key, region=region_info)
            creatSectionFile(file=file, section=section)
            request = qcloud_cos.UploadFileRequest(u'conlinestatic1', u'/sectionfile/'+section.fileurl, u''+sectionfiledir+section.fileurl)
            res = cos_client.upload_file(request)
            if res['code'] != 0:
                raise Exception('上传失败')
            request = qcloud_cos.UpdateFileRequest(u'conlinestatic1', u'/sectionfile/'+section.fileurl)
            request.set_content_disposition(u'inline; filename=' + section.fileurl)
            cos_client.update_file(request)
            os.remove(sectionfiledir+section.fileurl)
        elif body['type'] == '0':
            filetype = '.' + str(file).split('.')[1]
            # 如果是txt或者md那么存到数据库
            if filetype == '.txt' or filetype == '.md':
                filecontent = file.read()
                # 获取编码方式
                encodetype = chardet.detect(filecontent)['encoding']
                section.content = filecontent.decode(encodetype)
            # 如果是pdf那么创建文件
            elif filetype == '.pdf':
                creatSectionFile(file=file, section=section)
            # 如果是doc那么先转pdf再保存文件
            elif filetype == '.doc':
                creatSectionFile(file=file, section=section)
                desfile = random_str() + '.pdf'
                log('des: ' + desfile)
                log('sre' + section.fileurl)
                office = subprocess.Popen(['sh', '/home/ubuntu/office.sh'])
                office.wait()
                write = subprocess.Popen(['python3', '/home/ubuntu/DocumentConverter.py', sectionfiledir + section.fileurl, sectionfiledir + desfile], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
                write.wait()
                if write.stderr.read() != '':
                    log('error: ' + write.stderr.read())
                    raise Exception('上传出错')
                section.fileurl = desfile
            else:
                raise Exception('文件类型错误')
        section.save()

        return pack()
    except Exception as e:
        return pack(msg=e)

# 删除章节
@csrf_exempt
def deletesection(request):
    try:
        body = eval(request.body)
        user = tokenActive(request.COOKIES)
        if not isinstance(user, User):
            return pack(code=user)
        if user.type == 0:
            raise Exception('学生无法删除')
        section = Section.objects.all().filter(creator=user.userid).filter(sectionid=body['sectionid'])
        # for sec in list(section):
        #     if sec.fileurl is not None:
        #         os.remove(sectionfiledir + sec.fileurl)
        section.delete()
        return pack()

    except Exception as e:
        return pack(msg=e)

# 编辑章节
@csrf_exempt
def editSection(request):
    try:
        body = eval(request.body)
        user = tokenActive(request.COOKIES)
        if not isinstance(user, User):
            return pack(code=user)
        if user.type == 0:
            raise Exception('学生无法编辑')
        section = list(Section.objects.filter(creator=user.userid).filter(sectionid=body['sectionid']))[0]
        section.title = body['title']
        section.save()
        return pack()
    except Exception as e:
        return pack(msg=e)

# 写入章节文件
def creatSectionFile(file=None, section=Section()):
    # 获取扩展名
    filetype = '.' + str(file).split('.')[1]
    # 保存fileurl
    section.fileurl = random_str() + filetype
    # 打开特定的文件进行二进制的写操作
    destination = open(sectionfiledir + section.fileurl, 'wb+')
    # 分块写入文件
    for chunk in file.chunks():
        destination.write(chunk)
    destination.close()

def moban(request):
    try:
        body = eval(request.body)

    except Exception as e:
        return pack(msg=e)


from datetime import date
import re
import sys

from django.shortcuts import render
from django.http import JsonResponse
from django.utils.safestring import SafeString
from .lib.dwd import  Forecast, Plz, Monattage

# Create your view
def index(request):
    return render(request, 'wetter/index.html')

def daten(request, geo, monattag):
    if "ort" in request.GET:
        ort = re.split("\ \d", request.GET['ort'])[0]
    else:
        ort = ""

    p1 = geo.split(",")
    try:
        fc = Forecast(p1[0], p1[1], 100, monattag, 3)
        fc.get_aggregates()
        jstr = SafeString(fc.make_history())
        jstr = jstr.replace("None", "null")
        jstr = jstr.replace("'", '"')
        heute = date.today()
        stations = [(x.stationsname, x.bundesland, x.stationshoehe, x.distance)
                    for x in fc.stations]
        if len(set([x[1] for x in stations])) == 1:
            bundesland = "/" + stations[0][1]
        else:
            bundesland = ""

        return render(
            request, 'wetter/daten.html', {
                "aggr": fc.aggregates,
                "geoBreite": p1[0],
                "geoLaenge": p1[1],
                "monattag": str(fc.tag) + ". " + fc.get_month(fc.monat) + "",
                "monattatstr": str(fc.tag),
                "ort": ort,
                "bundesland": bundesland,
                "history": SafeString(jstr),
                "stationen": stations,
                "heutetag": heute.day,
                "heutemonat": fc.get_month(heute.month)[0:3],
                "heutejahr": heute.year
            })
    except:
        msg = "Entschuldigung, das hat leider nicht geklappt. \
        Wahrscheinlich gab es eine Problem mit der Bereitsstellung der Daten. \
        Versuche es bitte mit einen anderen Ort. "
        e = sys.exc_info()[0]

        return render(request, "wetter/index.html", {"error": msg,"err_info":e})

def plz(request):
    plz = Plz()
    data = plz.query(request.GET['query'])
    return JsonResponse(data, safe=False)

def monattage(request):
    monattage = Monattage()
    data = monattage.query(request.GET['query'])
    return JsonResponse(data, safe=False)


import preprocess
import numpy as np
import pandas as pd
from sklearn.metrics import log_loss
from sklearn.ensemble import GradientBoostingClassifier

#test phase
X_train,X_test,Y_train,Y_test = preprocess.load_data()
"""
#test test everywhere yay

model = GradientBoostingClassifier()

model.fit(X_train,Y_train)
y_predict = model.predict_proba(X_test)

print log_loss(Y_test,y_predict)
"""

#deploy
#loading data using numerai example
np.random.seed(0)
training_data = pd.read_csv('numerai_training_data.csv', header=0)
prediction_data = pd.read_csv('numerai_tournament_data.csv', header=0)
Y = training_data['target']
X = training_data.drop('target', axis=1)
t_id = prediction_data['t_id']
x_prediction = prediction_data.drop('t_id', axis=1)

model = GradientBoostingClassifier()
model.fit(X,Y)
y_prediction = model.predict_proba(x_prediction)
results = y_prediction[:, 1]
results_df = pd.DataFrame(data={'probability':results})
joined = pd.DataFrame(t_id).join(results_df)

print("Writing predictions from Oracle Lamp to CSV File...")
# Save the predictions out to a CSV file
joined.to_csv("predictions-gbm.csv", index=False)


"""A decoder that uses beam search. Can only be used for inference, not
training.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from collections import namedtuple

import tensorflow as tf
from seq2seq.inference import beam_search
from seq2seq.decoders.decoder_base import DecoderBase, DecoderStepOutput

class BeamDecoderOutput(
    namedtuple("DecoderOutput", [
        "logits", "predicted_ids", "log_probs", "scores", "beam_parent_ids",
        "original_outputs"
    ])):
  """Structure for the output of a beam search decoder. This class is used
  to define the output at each step as well as the final output of the decoder.
  If used as the final output, a time dimension `T` is inserted after the
  beam_size dimension.

  Args:
    logits: Logits at the current time step of shape `[beam_size, vocab_size]`
    predicted_ids: Chosen softmax predictions at the current time step.
      An int32 tensor of shape `[beam_size]`.
    log_probs: Total log probabilities of all beams at the current time step.
      A float32 tensor of shaep `[beam_size]`.
    scores: Total scores of all beams at the current time step. This differs
      from log probabilities in that the score may add additional processing
      such as length normalization. A float32 tensor of shape `[beam_size]`.
    beam_parent_ids: The indices of the beams that are being continued.
      An int32 tensor of shape `[beam_size]`.
  """
  pass

class BeamSearchDecoder(DecoderBase):
  """The BeamSearchDecoder wraps another decoder to perform beam search instead
  of greedy selection. This decoder must be used with batch size of 1, which
  will result in an effective batch size of `beam_width`.

  Args:
    decoder: A instance of `DecoderBase` to be used with beam search.
    config: A `BeamSearchConfig` that defines beam search decoding parameters.
  """

  def __init__(self, decoder, config):
    super(BeamSearchDecoder, self).__init__(
        decoder.cell, decoder.input_fn, decoder.max_decode_length,
        decoder.prediction_fn, decoder.name)
    self.decoder = decoder
    self.config = config

  def __call__(self, *args, **kwargs):
    with self.decoder.variable_scope():
      return self._build(*args, **kwargs)

  @staticmethod
  def _wrap_loop_state(value, loop_state):
    """Wraps the loop state to also include to beam decoder state.
    """
    if loop_state is None:
      return value
    else:
      return (value, loop_state)

  @staticmethod
  def _unwrap_loop_state(loop_state):
    """Unwraps the loop state to return (beam_decoder_state, original_state)
    """
    if isinstance(loop_state, tuple) and isinstance(loop_state[0],
                                                    beam_search.BeamState):
      return loop_state
    else:
      return loop_state, None

  def pack_outputs(self, outputs_ta, final_loop_state):
    """Transposes outputs from time-major to batch-major.
    """
    logits = outputs_ta.logits.stack()
    predicted_ids = outputs_ta.predicted_ids.stack()
    log_probs = outputs_ta.log_probs.stack()
    scores = outputs_ta.scores.stack()
    beam_parent_ids = outputs_ta.beam_parent_ids.stack()

    _, original_final_loop_state = self._unwrap_loop_state(final_loop_state)
    orignal_output = self.decoder.pack_outputs(
        outputs_ta.original_outputs, original_final_loop_state)

    # We're using a batch size of 1, so we add an extra dimension to
    # convert tensors to [1, beam_width, ...] shape. This way Tensorflow
    # doesn't confuse batch_size with beam_width
    orignal_output = orignal_output.__class__(
        *[tf.expand_dims(_, 1) for _ in orignal_output]
    )

    return BeamDecoderOutput(
        logits=tf.expand_dims(logits, 1),
        predicted_ids=tf.expand_dims(predicted_ids, 1),
        log_probs=tf.expand_dims(log_probs, 1),
        scores=tf.expand_dims(scores, 1),
        beam_parent_ids=tf.expand_dims(beam_parent_ids, 1),
        original_outputs=orignal_output)

  def compute_output(self, cell_output):
    raise ValueError("""Beam Search decoder does not support this method.""")

  def output_shapes(self):
    return BeamDecoderOutput(
        logits=tf.zeros([self.decoder.vocab_size]),
        predicted_ids=tf.zeros([], dtype=tf.int64),
        log_probs=tf.zeros([], dtype=tf.float32),
        scores=tf.zeros([], dtype=tf.float32),
        beam_parent_ids=tf.zeros([], dtype=tf.int32),
        original_outputs=self.decoder.output_shapes())

  def create_next_input(self, time_, initial_call, output):
    if initial_call:
      next_input, elements_finished = self.decoder.create_next_input(
          time_, initial_call, output.original_outputs)
      # The first time we tile the initial input [beam_width] time
      next_input_beam = tf.tile(next_input, [self.config.beam_width, 1])
      elements_finished_beam = tf.tile(
          elements_finished, [self.config.beam_width])
      return next_input_beam, elements_finished_beam

    # Shuffle the original output according to our beam search result
    original_values_shuffled = []
    for value in output.original_outputs:
      value_shuffled = beam_search.nest_map(
          value,
          lambda x: tf.gather(x, output.beam_parent_ids))
      original_values_shuffled.append(value_shuffled)
    original_outputs_shuffled = output.original_outputs.__class__(
        *original_values_shuffled)
    original_outputs_shuffled = original_outputs_shuffled._replace(
        predicted_ids=output.predicted_ids)

    next_input, elements_finished = self.decoder.create_next_input(
        time_, initial_call, original_outputs_shuffled)
    return next_input, elements_finished

  def step(self, time_, cell_output, cell_state, loop_state):
    initial_call = (cell_output is None)

    if initial_call:
      cell_output = tf.zeros([self.config.beam_width, self.cell.output_size])

      # We start out with all beams being equal, so we tile the cell state
      # [beam_width] times
      next_cell_state = beam_search.nest_map(
          cell_state, lambda x: tf.tile(x, [self.config.beam_width, 1]))

      # Call the original decoder
      original_outputs = self.decoder.step(
          time_, None, cell_state, loop_state)

      # Create an initial Beam State
      beam_state = beam_search.create_initial_beam_state(
          config=self.config,
          max_time=self.decoder.max_decode_length)

      next_loop_state = self._wrap_loop_state(
          beam_state, original_outputs.next_loop_state)

      outputs = self.output_shapes()

    else:
      prev_beam_state, original_loop_state = self._unwrap_loop_state(loop_state)

      # Call the original decoder
      original_outputs = self.decoder.step(
          time_, cell_output, cell_state, original_loop_state)

      # Perform a step of beam search
      beam_state = beam_search.beam_search_step(
          logits=original_outputs.outputs.logits,
          beam_state=prev_beam_state,
          config=self.config)
      beam_state.predicted_ids.set_shape([None, self.decoder.max_decode_length])
      next_loop_state = self._wrap_loop_state(
          beam_state, original_outputs.next_loop_state)

      outputs = BeamDecoderOutput(
          logits=tf.zeros([self.config.beam_width, self.config.vocab_size]),
          predicted_ids=tf.to_int64(beam_state.predicted_ids[:, time_ - 1]),
          log_probs=beam_state.log_probs,
          scores=beam_state.scores,
          beam_parent_ids=beam_state.beam_parent_ids,
          original_outputs=original_outputs.outputs)

      # Cell states are shuffled around by beam search
      next_cell_state = beam_search.nest_map(
          original_outputs.next_cell_state,
          lambda x: tf.gather(x, beam_state.beam_parent_ids))

    # The final step output
    step_output = DecoderStepOutput(
        outputs=outputs,
        next_cell_state=next_cell_state,
        next_loop_state=next_loop_state)

    return step_output


# -*- coding: utf-8 -*-
from odoo import models, fields, api
from datetime import datetime, date

class Pointing(models.Model):
    _name = 'btp_pointing.pointing'

    @api.one
    @api.depends('construction_site_id.name', 'date')
    def _compute_name(self):
        if self.construction_site_id and self.date:
            self.name = "Pointages " + (self.construction_site_id.name).lower() + " du " + datetime.strptime(self.date,
                                                                                '%Y-%m-%d').strftime(
                '%d-%m-%Y')

    name = fields.Char(string="Nom", compute='_compute_name', store=True)
    date = fields.Date(string='Date', required=True, default=date.today())
    construction_site_id = fields.Many2one('construction_site.construction_site', string='Chantier', required=True)
    stage_ids = fields.One2many('btp_pointing.pointing.stage', 'pointing_id',
                                string="Étapes de pointages")

    _sql_constraints = [
        ('name_uniq', 'unique(name)',
         "Le nom doit être unique.\n Veuillez corriger pour continuer!"),
    ]


from django.shortcuts import render, redirect, reverse
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
import os
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.conf import settings
import numpy as np
from PIL import Image
import json
import math
import requests
from django.conf import settings

# Create your views here.
@login_required
def home(request):
    return render(request, 'doctors/home.html')

@login_required
def appointments(request):
    return redirect('calendar')

@login_required
def predict(request):
    if request.method == 'GET':
        return render(request, 'doctors/predict.html')
    else:
        print('entered else')
        print("file recieved")
        form = request.FILES
        print(form['file'])

        file_object = request.FILES["file"]
        file_name = str(file_object)
        print(f'[INFO] File Name: {file_name}')
        path = os.path.join('doctors/static/doctors/', file_name)
        with open(path, 'wb+') as f:
            for chunk in file_object.chunks():
                f.write(chunk)
        #images = os.listdir("path/to/images") #Can use glob as well
        url = 'https://skin-cancer-sample.herokuapp.com/'
        img = np.asarray(Image.open(path).resize((256,256)))
        # img.save(settings.MEDIA_URL + 'cancer_images/', file_name)
        #print(img)
        class NumpyEncoder(json.JSONEncoder):
            def default(self, obj):
                if isinstance(obj, np.ndarray):
                    return obj.tolist()
                return json.JSONEncoder.default(self, obj)
        json_dump = json.dumps({"image":img}, cls = NumpyEncoder)
        #print(json_dump)
        send_request = requests.post(url, json_dump)
        print(send_request)
        result = send_request.json()['results']
        print(result)
        index = np.argmax(result)
        print(result[0][index])

        cancers = {
            0: 'Actinic kerastose',
            1: 'Basal cell carcinoma',
            2: 'Benign keratosis-like lesions',
            3: 'Dermatofibroma',
            4: 'Melanocytic nevi',
            5: 'Melanoma',
            6: 'Vascular lessions'
        }
        path = 'doctors/' + file_name
        context = {
        "detected": cancers[index],
        "percentage": math.trunc(result[0][index]*100),
        "address": "Hyderabad, India",
        'images': path
        }

        return render(request, 'doctors/predict_res.html',context)