########################################################################
# $HeadURL$
########################################################################
__RCSID__ = "$Id$"

from DIRAC                                                          import S_OK, S_ERROR, gConfig, gMonitor, gLogger, rootPath
from DIRAC.Core.Base.AgentModule                                    import AgentModule
from DIRAC.Core.Utilities.List                                      import sortList, breakListIntoChunks
from DIRAC.DataManagementSystem.Client.ReplicaManager               import ReplicaManager
from DIRAC.RequestManagementSystem.Client.RequestClient             import RequestClient
from DIRAC.DataManagementSystem.Client.StorageUsageClient           import StorageUsageClient
from DIRAC.Resources.Catalog.FileCatalogClient                      import FileCatalogClient
from DIRAC.TransformationSystem.Client.TransformationClient         import TransformationClient
from DIRAC.WorkloadManagementSystem.Client.WMSClient                import WMSClient
from datetime                                                       import datetime, timedelta
import re, os

AGENT_NAME = 'Transformation/TransformationCleaningAgent'

class TransformationCleaningAgent( AgentModule ):

  #############################################################################
  def initialize( self ):
    """Sets defaults """
    self.replicaManager = ReplicaManager()
    self.transClient = TransformationClient()
    self.wmsClient = WMSClient()
    self.requestClient = RequestClient()
    self.metadataClient = FileCatalogClient()
    self.storageUsageClient = StorageUsageClient()

    # This sets the Default Proxy to used as that defined under
    # /Operations/Shifter/DataManager
    # the shifterProxy option in the Configuration can be used to change this default.
    self.am_setOption( 'shifterProxy', 'DataManager' )

    self.transformationTypes = sortList( self.am_getOption( 'TransformationTypes', ['MCSimulation', 'DataReconstruction', 'DataStripping', 'MCStripping', 'Merge', 'Replication'] ) )
    gLogger.info( "Will consider the following transformation types: %s" % str( self.transformationTypes ) )
    self.directoryLocations = sortList( self.am_getOption( 'DirectoryLocations', ['TransformationDB', 'StorageUsage', 'MetadataCatalog'] ) )
    gLogger.info( "Will search for directories in the following locations: %s" % str( self.directoryLocations ) )
    self.transfidmeta = self.am_getOption( 'TransfIDMeta', "TransformationID" )
    gLogger.info( "Will use %s as metadata tag name for TransformationID" % self.transfidmeta )
    self.archiveAfter = self.am_getOption( 'ArchiveAfter', 7 ) # days
    gLogger.info( "Will archive Completed transformations after %d days" % self.archiveAfter )
    self.activeStorages = sortList( self.am_getOption( 'ActiveSEs', [] ) )
    gLogger.info( "Will check the following storage elements: %s" % str( self.activeStorages ) )
    self.logSE = self.am_getOption( 'TransformationLogSE', 'LogSE' )
    gLogger.info( "Will remove logs found on storage element: %s" % self.logSE )
    return S_OK()

  #############################################################################
  def execute( self ):
    """ The TransformationCleaningAgent execution method.
    """
    self.enableFlag = self.am_getOption( 'EnableFlag', 'True' )
    if not self.enableFlag == 'True':
      self.log.info( 'TransformationCleaningAgent is disabled by configuration option %s/EnableFlag' % ( self.section ) )
      return S_OK( 'Disabled via CS flag' )

    # Obtain the transformations in Cleaning status and remove any mention of the jobs/files
    res = self.transClient.getTransformations( {'Status':'Cleaning', 'Type':self.transformationTypes} )
    if res['OK']:
      for transDict in res['Value']:
        # If transformation is of type `Replication` or `Removal`, there is nothing to clean.
        # We just archive
        if transDict[ 'Type' ] in [ 'Replication', 'Removal' ]:
          self.archiveTransformation( transDict['TransformationID'] )
        else:
          self.cleanTransformation( transDict['TransformationID'] )

    # Obtain the transformations in RemovingFiles status and (wait for it) removes the output files
    res = self.transClient.getTransformations( {'Status':'RemovingFiles', 'Type':self.transformationTypes} )
    if res['OK']:
      for transDict in res['Value']:
        self.removeTransformationOutput( transDict['TransformationID'] )

    # Obtain the transformations in Completed status and archive if inactive for X days
    olderThanTime = datetime.utcnow() - timedelta( days = self.archiveAfter )
    res = self.transClient.getTransformations( {'Status':'Completed', 'Type':self.transformationTypes}, older = olderThanTime )
    if res['OK']:
      for transDict in res['Value']:
        self.archiveTransformation( transDict['TransformationID'] )

    return S_OK()

  #############################################################################
  #
  # Get the transformation directories for checking
  #

  def getTransformationDirectories( self, transID ):
    """ Get the directories for the supplied transformation from the transformation system """
    directories = []
    if 'TransformationDB' in self.directoryLocations:
      res = self.transClient.getTransformationParameters( transID, ['OutputDirectories'] )
      if not res['OK']:
        gLogger.error( "Failed to obtain transformation directories", res['Message'] )
        return res
      transDirectories = res['Value'].splitlines()
      directories = self.__addDirs( transID, transDirectories, directories )

    if 'StorageUsage' in self.directoryLocations:
      res = self.storageUsageClient.getStorageDirectories( '', '', transID, [] )
      if not res['OK']:
        gLogger.error( "Failed to obtain storage usage directories", res['Message'] )
        return res
      transDirectories = res['Value']
      directories = self.__addDirs( transID, transDirectories, directories )

    if 'MetadataCatalog' in self.directoryLocations:
      res = self.metadataClient.findDirectoriesByMetadata( {self.transfidmeta:transID} )
      if not res['OK']:
        gLogger.error( "Failed to obtain metadata catalog directories", res['Message'] )
        return res
      transDirectories = res['Value']
      directories = self.__addDirs( transID, transDirectories, directories )
    if not directories:
      gLogger.info( "No output directories found" )
    directories = sortList( directories )
    return S_OK( directories )

  def __addDirs( self, transID, newDirs, existingDirs ):
    for dir in newDirs:
      transStr = str( transID ).zfill( 8 )
      if re.search( transStr, str(dir) ):
        if not dir in existingDirs:
          existingDirs.append( dir )
    return existingDirs

  #############################################################################
  #
  # These are the methods for performing the cleaning of catalogs and storage
  #

  def cleanStorageContents( self, directory ):
    for storageElement in self.activeStorages:
      res = self.__removeStorageDirectory( directory, storageElement )
      if not res['OK']:
        return res
    return S_OK()

  def __removeStorageDirectory( self, directory, storageElement ):
    gLogger.info( 'Removing the contents of %s at %s' % ( directory, storageElement ) )
    res = self.replicaManager.getPfnForLfn( [directory], storageElement )
    if not res['OK']:
      gLogger.error( "Failed to get PFN for directory", res['Message'] )
      return res
    for directory, error in res['Value']['Failed'].items():
      gLogger.error( 'Failed to obtain directory PFN from LFN', '%s %s' % ( directory, error ) )
    if res['Value']['Failed']:
      return S_ERROR( 'Failed to obtain directory PFN from LFNs' )
    storageDirectory = res['Value']['Successful'].values()[0]
    res = self.replicaManager.getStorageFileExists( storageDirectory, storageElement, singleFile = True )
    if not res['OK']:
      gLogger.error( "Failed to obtain existance of directory", res['Message'] )
      return res
    exists = res['Value']
    if not exists:
      gLogger.info( "The directory %s does not exist at %s " % ( directory, storageElement ) )
      return S_OK()
    res = self.replicaManager.removeStorageDirectory( storageDirectory, storageElement, recursive = True, singleDirectory = True )
    if not res['OK']:
      gLogger.error( "Failed to remove storage directory", res['Message'] )
      return res
    gLogger.info( "Successfully removed %d files from %s at %s" % ( res['Value']['FilesRemoved'], directory, storageElement ) )
    return S_OK()

  def cleanCatalogContents( self, directory ):
    res = self.__getCatalogDirectoryContents( [directory] )
    if not res['OK']:
      return res
    filesFound = res['Value']
    if not filesFound:
      return S_OK()
    gLogger.info( "Attempting to remove %d possible remnants from the catalog and storage" % len( filesFound ) )
    res = self.replicaManager.removeFile( filesFound )
    if not res['OK']:
      return res
    for lfn, reason in res['Value']['Failed'].items():
      gLogger.error( "Failed to remove file found in the catalog", "%s %s" % ( lfn, reason ) )
    if res['Value']['Failed']:
      return S_ERROR( "Failed to remove all files found in the catalog" )
    return S_OK()

  def __getCatalogDirectoryContents( self, directories ):
    gLogger.info( 'Obtaining the catalog contents for %d directories:' % len( directories ) )
    for directory in directories:
      gLogger.info( directory )
    activeDirs = directories
    allFiles = {}
    while len( activeDirs ) > 0:
      currentDir = activeDirs[0]
      res = self.replicaManager.getCatalogListDirectory( currentDir, singleFile = True )
      activeDirs.remove( currentDir )
      if not res['OK'] and res['Message'].endswith( 'The supplied path does not exist' ):
        gLogger.info( "The supplied directory %s does not exist" % currentDir )
      elif not res['OK']:
        gLogger.error( 'Failed to get directory contents', '%s %s' % ( currentDir, res['Message'] ) )
      else:
        dirContents = res['Value']
        activeDirs.extend( dirContents['SubDirs'] )
        allFiles.update( dirContents['Files'] )
    gLogger.info( "Found %d files" % len( allFiles ) )
    return S_OK( allFiles.keys() )

  def cleanTransformationLogFiles( self, directory ):
    gLogger.info( "Removing log files found in the directory %s" % directory )
    res = self.replicaManager.removeStorageDirectory( directory, self.logSE, singleDirectory = True )
    if not res['OK']:
      gLogger.error( "Failed to remove log files", res['Message'] )
      return res
    gLogger.info( "Successfully removed transformation log directory" )
    return S_OK()

  #############################################################################
  #
  # These are the functional methods for archiving and cleaning transformations
  #

  def removeTransformationOutput( self, transID ):
    """ This just removes any mention of the output data from the catalog and storage """
    gLogger.info( "Removing output data for transformation %s" % transID )
    res = self.getTransformationDirectories( transID )
    if not res['OK']:
      gLogger.error( 'Problem obtaining directories for transformation %s with result "%s"' % ( transID, res ) )
      return S_OK()
    directories = res['Value']
    for directory in directories:
      if not re.search( '/LOG/', directory ):
        res = self.cleanCatalogContents( directory )
        if not res['OK']:
          return res
        res = self.cleanStorageContents( directory )
        if not res['OK']:
          return res
    gLogger.info( "Removed directories in the catalog and storage for transformation" )
    # Clean ALL the possible remnants found in the metadata catalog
    res = self.cleanMetadataCatalogFiles( transID, directories )
    if not res['OK']:
      return res
    gLogger.info( "Successfully removed output of transformation %d" % transID )
    # Change the status of the transformation to RemovedFiles
    res = self.transClient.setTransformationParameter( transID, 'Status', 'RemovedFiles' )
    if not res['OK']:
      gLogger.error( "Failed to update status of transformation %s to RemovedFiles" % ( transID ), res['Message'] )
      return res
    gLogger.info( "Updated status of transformation %s to RemovedFiles" % ( transID ) )
    return S_OK()

  def archiveTransformation( self, transID ):
    """ This just removes job from the jobDB and the transformation DB """
    gLogger.info( "Archiving transformation %s" % transID )
    # Clean the jobs in the WMS and any failover requests found
    res = self.cleanTransformationTasks( transID )
    if not res['OK']:
      return res
    # Clean the transformation DB of the files and job information
    res = self.transClient.cleanTransformation( transID )
    if not res['OK']:
      return res
    gLogger.info( "Successfully archived transformation %d" % transID )
    # Change the status of the transformation to archived
    res = self.transClient.setTransformationParameter( transID, 'Status', 'Archived' )
    if not res['OK']:
      gLogger.error( "Failed to update status of transformation %s to Archived" % ( transID ), res['Message'] )
      return res
    gLogger.info( "Updated status of transformation %s to Archived" % ( transID ) )
    return S_OK()

  def cleanTransformation( self, transID ):
    """ This removes any mention of the supplied transformation
    """
    gLogger.info( "Cleaning transformation %s" % transID )
    res = self.getTransformationDirectories( transID )
    if not res['OK']:
      gLogger.error( 'Problem obtaining directories for transformation %s with result "%s"' % ( transID, res ) )
      return S_OK()
    directories = res['Value']
    # Clean the jobs in the WMS and any failover requests found
    res = self.cleanTransformationTasks( transID )
    if not res['OK']:
      return res
    # Clean the log files for the jobs
    for directory in directories:
      if re.search( '/LOG/', directory ):
        res = self.cleanTransformationLogFiles( directory )
        if not res['OK']:
          return res
      res = self.cleanCatalogContents( directory )
      if not res['OK']:
        return res
      res = self.cleanStorageContents( directory )
      if not res['OK']:
        return res
    # Clean ALL the possible remnants found in the BK
    res = self.cleanMetadataCatalogFiles( transID, directories )
    if not res['OK']:
      return res
    # Clean the transformation DB of the files and job information
    res = self.transClient.cleanTransformation( transID )
    if not res['OK']:
      return res
    gLogger.info( "Successfully cleaned transformation %d" % transID )
    # Change the status of the transformation to deleted
    res = self.transClient.setTransformationParameter( transID, 'Status', 'Deleted' )
    if not res['OK']:
      gLogger.error( "Failed to update status of transformation %s to Deleted" % ( transID ), res['Message'] )
      return res
    gLogger.info( "Updated status of transformation %s to Deleted" % ( transID ) )
    return S_OK()

  def cleanMetadataCatalogFiles( self, transID, directories ):
    res = self.metadataClient.findFilesByMetadata( {self.transfidmeta:transID} )
    if not res['OK']:
      return res
    fileToRemove = res['Value']
    if not len(fileToRemove):
      gLogger.info('No files found for transID %s'%transID)
      return S_OK()
    res = self.replicaManager.removeFile( fileToRemove )
    if not res['OK']:
      return res
    for lfn, reason in res['Value']['Failed'].items():
      gLogger.error( "Failed to remove file found in metadata catalog", "%s %s" % ( lfn, reason ) )
    if res['Value']['Failed']:
      return S_ERROR( "Failed to remove all files found in the metadata catalog" )
    gLogger.info( "Successfully removed all files found in the BK" )
    return S_OK()

  #############################################################################
  #
  # These are the methods for removing the jobs from the WMS and transformation DB
  #

  def cleanTransformationTasks( self, transID ):
    res = self.__getTransformationExternalIDs( transID )
    if not res['OK']:
      return res
    externalIDs = res['Value']
    if externalIDs:
      res = self.transClient.getTransformationParameters( transID, ['Type'] )
      if not res['OK']:
        gLogger.error( "Failed to determine transformation type" )
        return res
      transType = res['Value']
      if transType in [ 'Replication', 'Removal' ]:
        res = self.__removeRequests( externalIDs )
      else:
        res = self.__removeWMSTasks( externalIDs )
      if not res['OK']:
        return res
    return S_OK()

  def __getTransformationExternalIDs( self, transID ):
    res = self.transClient.getTransformationTasks( condDict = {'TransformationID':transID} )
    if not res['OK']:
      gLogger.error( "Failed to get externalIDs for transformation %d" % transID, res['Message'] )
      return res
    externalIDs = []
    for taskDict in res['Value']:
      externalIDs.append( taskDict['ExternalID'] )
    gLogger.info( "Found %d tasks for transformation" % len( externalIDs ) )
    return S_OK( externalIDs )

  def __removeRequests( self, requestIDs ):
    gLogger.error( "Not removing requests but should do" )
    return S_OK()

  def __removeWMSTasks( self, jobIDs ):
    allRemove = True
    for jobList in breakListIntoChunks( jobIDs, 500 ):

      res = self.wmsClient.killJob( jobList )
      if res['OK']:
        gLogger.info( "Successfully killed %d jobs from WMS" % len( jobList ) )
      elif ( res.has_key( 'InvalidJobIDs' ) ) and ( not res.has_key( 'NonauthorizedJobIDs' ) ) and ( not res.has_key( 'FailedJobIDs' ) ):
        gLogger.info( "Found %s jobs which did not exist in the WMS" % len( res['InvalidJobIDs'] ) )
      elif res.has_key( 'NonauthorizedJobIDs' ):
        gLogger.error( "Failed to kill %s jobs because not authorized" % len( res['NonauthorizedJobIDs'] ) )
        allRemove = False
      elif res.has_key( 'FailedJobIDs' ):
        gLogger.error( "Failed to kill %s jobs" % len( res['FailedJobIDs'] ) )
        allRemove = False

      res = self.wmsClient.deleteJob( jobList )
      if res['OK']:
        gLogger.info( "Successfully removed %d jobs from WMS" % len( jobList ) )
      elif ( res.has_key( 'InvalidJobIDs' ) ) and ( not res.has_key( 'NonauthorizedJobIDs' ) ) and ( not res.has_key( 'FailedJobIDs' ) ):
        gLogger.info( "Found %s jobs which did not exist in the WMS" % len( res['InvalidJobIDs'] ) )
      elif res.has_key( 'NonauthorizedJobIDs' ):
        gLogger.error( "Failed to remove %s jobs because not authorized" % len( res['NonauthorizedJobIDs'] ) )
        allRemove = False
      elif res.has_key( 'FailedJobIDs' ):
        gLogger.error( "Failed to remove %s jobs" % len( res['FailedJobIDs'] ) )
        allRemove = False

    if not allRemove:
      return S_ERROR( "Failed to remove all remnants from WMS" )
    gLogger.info( "Successfully removed all tasks from the WMS" )
    res = self.requestClient.getRequestForJobs( jobIDs )
    if not res['OK']:
      gLogger.error( "Failed to get requestID for jobs.", res['Message'] )
      return res
    failoverRequests = res['Value']
    gLogger.info( "Found %d jobs with associated failover requests" % len( failoverRequests ) )
    if not failoverRequests:
      return S_OK()
    failed = 0
    for jobID, requestName in failoverRequests.items():
      res = self.requestClient.deleteRequest( requestName )
      if not res['OK']:
        gLogger.error( "Failed to remove request from RequestDB", res['Message'] )
        failed += 1
      else:
        gLogger.verbose( "Removed request %s associated to job %d." % ( requestName, jobID ) )
    if failed:
      gLogger.info( "Successfully removed %s requests" % ( len( failoverRequests ) - failed ) )
      gLogger.info( "Failed to remove %s requests" % failed )
      return S_ERROR( "Failed to remove all the request from RequestDB" )
    gLogger.info( "Successfully removed all the associated failover requests" )
    return S_OK()


from django.http.response import HttpResponse
from django.shortcuts import redirect, render
from .models import *
from accounts.models import *
from customer.models import Order,Orderdish

# Create your views here.

def dashboard(request,id):
  request.session["owner_id"]=id
  owner=Owner.objects.get(id=id)
  resturant=None
  dishes=None
  order=False
  recieved_order=None
  panding_order=None
  if Resturant.objects.all().filter(owner=owner):
    resturant=Resturant.objects.get(owner=owner)

  if Dish.objects.all().filter(owner=owner):
    dishes=Dish.objects.all().filter(owner=owner)

  if resturant:
    orders_list=Order.objects.filter(restaurant_id=resturant.id,complete=True)
    recieved_order=[]
    panding_order=[]
    # print(orders_list)
    for order in orders_list:
      dishess=Orderdish.objects.filter(order=order)
      # print(dishess)
      if dishess:
        d=[]
        total_bill=0
        for dish in dishess:
          quantity=dish.quantity
          name=dish.dish.name
          price=dish.dish.price
          obj=Info1(name,price,quantity)
          d.append(obj)
          total_bill=total_bill+quantity*price

        obj=Info2(d,order.id,total_bill)

        if order.status=="placed":
          recieved_order.append(obj)

        elif order.status=="panding":
          panding_order.append(obj)
    # print(recieved_order)
    # print(panding_order)

  if recieved_order or panding_order:
    order=True

  return render(request,'dashboard.html',{
    'name':owner.name,
    'id':id,
    'resturant':resturant,
    'dishes':dishes,
    'recieved_order':recieved_order,
    'panding_order':panding_order,
    'order':order
    })

def add_resturant(request,owner_id):
  if request.method=="POST":
    owner=Owner.objects.get(id=owner_id)
    name=request.POST["name"]
    address=request.POST["address"]
    latitude=request.POST["latitude"]
    longitude=request.POST["longitude"]
    opening_time=request.POST["opening_time"]
    closing_time=request.POST["closing_time"]
    bill_limit=request.POST["bill_limit"]

    Resturant.objects.create(
      owner=owner,
      name=name,
      address=address,
      latitude=latitude,
      longitude=longitude,
      opening_time=opening_time,
      closing_time=closing_time,
      bill_limit=bill_limit
    )

    return redirect("dashboard",id=owner_id)

  return render(request,'add_resturant.html')

def resturant_details(request,id):
  owner=Owner.objects.get(id=id)
  resturant=Resturant.objects.get(id=id)
  if request.method=="POST":
    name=request.POST["name"]
    address=request.POST["address"]
    latitude=request.POST["latitude"]
    longitude=request.POST["longitude"]
    opening_time=request.POST["opening_time"]
    closing_time=request.POST["closing_time"]
    bill_limit=request.POST["bill_limit"]

    Resturant.objects.all().filter(owner=owner).update(
      owner=owner,
      name=name,
      address=address,
      latitude=latitude,
      longitude=longitude,
      opening_time=opening_time,
      closing_time=closing_time,
      bill_limit=bill_limit
      )
    return redirect("dashboard",id=id)

  return render(request,'resturant_details.html',{
    'resturant':resturant
  })

def add_dish(request,owner_id):
  owner=Owner.objects.get(id=owner_id)

  if request.method=="POST":
    name=request.POST["name"]
    price=request.POST["price"]

    Dish.objects.create(
      owner=owner,
      name=name,
      price=price
    )
    owner_id=request.session["owner_id"]
    return redirect("dashboard",id=owner_id)

  return render(request,'add_dish.html')

def edit_dish(request,dish_id):
  if request.method=="POST":
    name=request.POST["name"]
    price=request.POST["price"]

    Dish.objects.all().filter(id=dish_id).update(
      name=name,
      price=price
    )

    owner_id=request.session["owner_id"]
    return redirect("dashboard",id=owner_id)

  dish=Dish.objects.get(id=dish_id)
  return render(request,'edit_dish.html',{
    'dish':dish
  })

def remove_dish(request,dish_id):
  instance=Dish.objects.get(id=dish_id)
  instance.delete()

  owner_id=request.session["owner_id"]
  return redirect("dashboard",id=owner_id)

class Info1:
  def __init__(self,name,price,quantity):
    self.name=name
    self.price=price
    self.quantity=quantity

class Info2:
  def __init__(self,dishes,id,bill):
    self.dishes=dishes
    self.id=id
    self.bill=bill

def accept_order(request,order_id):
  Order.objects.filter(id=order_id).update(
    status="panding"
  )

  owner_id=request.session["owner_id"]

  return redirect("dashboard",owner_id)

def reject_order(request,order_id):
  Order.objects.filter(id=order_id).update(
    status="rejected"
  )

  owner_id=request.session["owner_id"]

  return redirect("dashboard",owner_id)

def complete_order(request,order_id):
  Order.objects.filter(id=order_id).update(
    status="completed"
  )

  owner_id=request.session["owner_id"]

  return redirect("dashboard",owner_id)


from bokeh.models import BoxSelectTool, BoxZoomTool, LassoSelectTool, HoverTool, Quad
from bokeh.plotting import figure, output_file, show, gridplot, ColumnDataSource
from bokeh.models.widgets import Dropdown, Panel, Tabs, CheckboxButtonGroup, RadioGroup
from bokeh.io import output_file, show, vform

#PROJECT OVERVIEW:
#Create an interactive map of West Hall showing hallway culture via gender distribution, sleeping habit, etc.
#(If we hear back from STAR, we'll also have data on how people move from year to year, which will be awesome to implement)

#PROGRESS:
#currently outputs to an html file which has 2 tabs - one for WH1 and one for WH2
#rooms are currently blue squares, some with click and hover functionality, which is being modified and will be implemented in all once we figure out how to do it properly
#Also have buttons that are currently disfunctional but are planned to be able to display different color coordinations for each room.
#Will be initializing Room objects from a .csv file in this folder, but have not implemented yet.

# output to static HTML file
output_file("bokehlinetest.html")

class Room(object):
	def __init__(self, roomNum, roommates, gender, bedtime, top, bottom, left, right):
		self.roomNum = roomNum
		self.roommates = roommates
		self.gender = gender
		self.bedtime = bedtime
		self.top = top
		self.bottom = bottom
		self.left = left
		self.right = right

	def __str__(self):
		return 'Room Number: %s; Current Inhabitants: %s; Gender: %s; Average Bedtime: %s' %(self.roomNum, self.roommates, self.gender, self.bedtime)

# This was our previous Way of setting data (now we'll be using a csv file and pulling data from there to initialize each Room object)
'''
#setting dictionary values for things on the first floor
source1 = ColumnDataSource(
        data=dict(
			roomates = ['Uma and Lauren', 'Margo and Nicole'],
			gender = ['female', 'female'],
			top=[2, 2],
			bottom=[1, 1],
			left=[1, 3],
			right=[2, 4],
		)
	)
'''

#setting what goes in the hover box (currently dysfunctional)
hover = HoverTool(
        tooltips=[
        	("index", "@index"),
			("roomates", "@roomates"),
			("gender", "@gender")
			]
		)

TOOLS = "box_zoom,box_select,resize,reset,hover,tap"

p1 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall First Floor")
rooms1 = p1.quad('top','bottom', 'left', 'right',

					#visual choices for when the room isn't selected, doesn't really work.
					#also maybe not necessary to click to select rooms, but could
					#be useful framework for changing color based on which button is selected
					nonselection_fill_alpha=0.01,
					nonselection_fill_color=None,
					nonselection_line_color="firebrick",
					nonselection_line_alpha=1.0,

					#visual choices for when the room is selected, actually works
					selection_color="blue",
					selection_fill_alpha=.5,

					#source for all of the room data
					source=source1
					)

p1.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6],
          y1=[1, 6, 6, 6], color="#F4A582", line_width=3, legend="West Hall")
p1.select_one(BoxZoomTool).overlay.line_color = "olive"
p1.select_one(BoxZoomTool).overlay.line_width = 8
p1.select_one(BoxZoomTool).overlay.line_dash = "solid"
p1.select_one(BoxZoomTool).overlay.fill_color = None
tab1 =  Panel(child=p1, title="WH1")

p2 = figure(plot_width=400, plot_height=400, tools=TOOLS,title="West Hall Second Floor")

rooms2 = p2.quad(top=[2],bottom=[1], left=[1], right=[2],

					nonselection_fill_alpha=0.01,
					nonselection_fill_color=None,
					nonselection_line_color="firebrick",
					nonselection_line_alpha=1.0,

					selection_color="blue",
					selection_fill_alpha=.5)

p2.segment(x0=[1, 1, 1, 6], y0=[1, 6, 1, 1], x1=[6, 6, 1, 6],
          y1=[1, 6, 6, 6], color="#F4A582", line_width=3, legend="West Hall")

p2.select_one(BoxZoomTool).overlay.line_color = "olive"
p2.select_one(BoxZoomTool).overlay.line_width = 8
p2.select_one(BoxZoomTool).overlay.line_dash = "solid"
p2.select_one(BoxZoomTool).overlay.fill_color = None
tab2 = Panel(child=p2, title="WH2")

radio_group = RadioGroup(
        labels=["Gender", "Bedtime", "Some other shit"], active=0)

#dropdown_choices = [("Item 1", "item_1"), ("Item 2", "item_2"), ("Item 3", "item_3")]
#dropdown = Dropdown(label="Dropdown button", type="warning", menu=dropdown_choices)

tabs = Tabs(tabs=[ tab1, tab2 ])
layout = vform(dropdown, radio_group, tabs)

# show the results
show(tabs)
show(layout)
#show(vform(checkbox_button_group))


# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: build/bdist.linux-x86_64/egg/xpython/byteop/byteop25.py
# Compiled at: 2020-05-07 19:39:58
"""Bytecode Interpreter operations for Python 2.5

Note: this is subclassed so later versions may use operations from here.
"""
from __future__ import print_function, division
import operator, types, six, sys
from xdis import PYTHON_VERSION, IS_PYPY
from xpython.pyobj import Function, traceback_from_frame
from xpython.buildclass import build_class
COMPREHENSION_FN_NAMES = frozenset(('<setcomp>', '<dictcomp>', '<genexpr>'))

class ByteOp25(object):

    def __init__(self, vm):
        self.vm = vm
        self.version = vm.version
        self.is_pypy = vm.is_pypy

    def build_container(self, count, container_fn):
        elts = self.vm.popn(count)
        self.vm.push(container_fn(elts))

    def call_function_with_args_resolved(self, func, posargs, namedargs):
        if hasattr(func, 'im_func'):
            if func.im_self is not None:
                posargs.insert(0, func.im_self)
            if not isinstance(posargs[0], func.im_class):
                raise TypeError('unbound method %s() must be called with %s instance as first argument (got %s instance instead)' % (
                 func.im_func.func_name,
                 func.im_class.__name__,
                 type(posargs[0]).__name__))
            func = func.im_func
        if isinstance(func, types.BuiltinFunctionType):
            if func == globals:
                self.vm.push(self.vm.frame.f_globals)
                return
            if func == locals:
                self.vm.push(self.vm.frame.f_globals)
                return
            if self.version != PYTHON_VERSION and PYTHON_VERSION >= 3.4 and func == __build_class__:
                retval = build_class(*posargs, **namedargs)
                self.vm.push(retval)
                return
        if isinstance(func, types.FunctionType):
            if func in self.vm.fn2native:
                func = self.vm.fn2native[func]
        retval = func(*posargs, **namedargs)
        self.vm.push(retval)
        return

    def call_function(self, argc, args, kwargs):
        namedargs = {}
        lenKw, lenPos = divmod(argc, 256)
        for i in range(lenKw):
            key, val = self.vm.popn(2)
            namedargs[key] = val

        namedargs.update(kwargs)
        posargs = self.vm.popn(lenPos)
        posargs.extend(args)
        func = self.vm.pop()
        self.call_function_with_args_resolved(func, posargs, namedargs)

    def lookup_name(self, name):
        """Returns the value in the current frame associated for name"""
        frame = self.vm.frame
        if name in frame.f_locals:
            val = frame.f_locals[name]
        elif name in frame.f_globals:
            val = frame.f_globals[name]
        elif name in frame.f_builtins:
            val = frame.f_builtins[name]
        else:
            raise NameError("name '%s' is not defined" % name)
        return val

    def print_item(self, item, to=None):
        if to is None:
            to = sys.stdout
        if hasattr(to, 'softspace') and to.softspace:
            print(' ', end='', file=to)
            to.softspace = 0
        print(item, end='', file=to)
        if hasattr(to, 'softspace'):
            if isinstance(item, str):
                if not item or not item[(-1)].isspace() or item[(-1)] == ' ':
                    to.softspace = 1
            else:
                to.softspace = 1
        return

    def print_newline(self, to=None):
        if to is None:
            to = sys.stdout
        print('', file=to)
        if hasattr(to, 'softspace'):
            to.softspace = 0
        return

    def NOP(self):
        """Do nothing code. Used as a placeholder by the bytecode optimizer."""
        pass

    def POP_TOP(self):
        """Removes the top-of-stack (TOS) item."""
        self.vm.pop()

    def ROT_TWO(self):
        """Swaps the two top-most stack items."""
        a, b = self.vm.popn(2)
        self.vm.push(b, a)

    def ROT_THREE(self):
        """Lifts second and third stack item one position up, moves top down to position three."""
        a, b, c = self.vm.popn(3)
        self.vm.push(c, a, b)

    def ROT_FOUR(self):
        """Lifts second, third and forth stack item one position up, moves top down to position four."""
        a, b, c, d = self.vm.popn(4)
        self.vm.push(d, a, b, c)

    def DUP_TOP(self):
        """Duplicates the reference on top of the stack."""
        self.vm.push(self.vm.top())

    def GET_ITER(self):
        """Implements TOS = iter(TOS)."""
        self.vm.push(iter(self.vm.pop()))

    def STORE_SUBSCR(self):
        """Implements TOS1[TOS] = TOS2."""
        val, obj, subscr = self.vm.popn(3)
        obj[subscr] = val

    def DELETE_SUBSCR(self):
        """Implements del TOS1[TOS]."""
        obj, subscr = self.vm.popn(2)
        del obj[subscr]

    def PRINT_EXPR(self):
        print(self.vm.pop())

    def PRINT_ITEM(self):
        item = self.vm.pop()
        self.print_item(item)

    def PRINT_ITEM_TO(self):
        to = self.vm.pop()
        item = self.vm.pop()
        self.print_item(item, to)

    def PRINT_NEWLINE(self):
        self.print_newline()

    def PRINT_NEWLINE_TO(self):
        to = self.vm.pop()
        self.print_newline(to)

    def BREAK_LOOP(self):
        """Terminates a loop due to a break statement."""
        return 'break'

    def CONTINUE_LOOP(self, dest):
        """
        Continues a loop due to a continue statement. target is the
        address to jump to (which should be a FOR_ITER instruction).
        """
        self.vm.return_value = dest
        return 'continue'

    def LIST_APPEND(self, count):
        """Calls list.append(TOS1, TOS). Used to implement list
        comprehensions.
        """
        val = self.vm.pop()
        the_list = self.vm.peek(count)
        the_list.append(val)

    def LOAD_LOCALS(self):
        """
        Pushes a reference to the locals of the current scope on the
        stack. This is used in the code for a class definition: After the
        class body is evaluated, the locals are passed to the class
        definition."""
        self.vm.push(self.vm.frame.f_locals)

    def RETURN_VALUE(self):
        """Returns with TOS to the caller of the function.
        """
        self.vm.return_value = self.vm.pop()
        if self.vm.frame.generator:
            self.vm.frame.generator.finished = True
        return 'return'

    def YIELD_VALUE(self):
        """
        Pops TOS and yields it from a generator.
        """
        self.vm.return_value = self.vm.pop()
        return 'yield'

    def IMPORT_STAR(self):
        """Loads all symbols not starting with '_' directly from the module
        TOS to the local namespace. The module is popped after loading all
        names. This opcode implements from module import *.
        """
        mod = self.vm.pop()
        for attr in dir(mod):
            if attr[0] != '_':
                self.vm.frame.f_locals[attr] = getattr(mod, attr)

    def EXEC_STMT(self):
        """
        Implements exec TOS2,TOS1,TOS. The compiler fills missing
        optional parameters with None.
        """
        stmt, globs, locs = self.vm.popn(3)
        six.exec_(stmt, globs, locs)

    def POP_BLOCK(self):
        """
        Removes one block from the block stack. Per frame, there is a
        stack of blocks, denoting nested loops, try statements, and
        such."""
        self.vm.pop_block()

    def END_FINALLY(self):
        """
        Terminates a "finally" clause. The interpreter recalls whether the
        exception has to be re-raised, or whether the function
        returns, and continues with the outer-next block.
        """
        v = self.vm.pop()
        if isinstance(v, str):
            why = v
            if why in ('return', 'continue'):
                self.vm.return_value = self.vm.pop()
            if why == 'silenced':
                block = self.vm.pop_block()
                assert block.type == 'except-handler'
                self.vm.unwind_block(block)
                why = None
        elif v is None:
            why = None
        elif issubclass(v, BaseException):
            exctype = v
            val = self.vm.pop()
            tb = self.vm.pop()
            self.vm.last_exception = (exctype, val, tb)
            if self.version >= 3.5:
                block = self.vm.top_block()
                while len(self.vm.frame.stack) > block.level:
                    self.vm.pop()

                self.vm.push(tb, val, exctype)
            why = 'reraise'
        else:
            raise self.VMError('Confused END_FINALLY')
        return why

    def BUILD_CLASS(self):
        """
        Creates a new class object. TOS is the methods dictionary, TOS1 the
        tuple of the names of the base classes, and TOS2 the class name.
        """
        name, bases, methods = self.vm.popn(3)
        try:
            klass = type(name, bases, methods)
        except TypeError:
            klass = type(name, tuple([object] + list(bases)), methods)

        self.vm.push(klass)

    def STORE_NAME(self, name):
        """Implements name = TOS. namei is the index of name in the attribute
        co_names of the code object. The compiler tries to use STORE_LOCAL or
        STORE_GLOBAL if possible."""
        self.vm.frame.f_locals[name] = self.vm.pop()

    def DELETE_NAME(self, name):
        """Implements del name, where namei is the index into co_names attribute of the code object."""
        del self.vm.frame.f_locals[name]

    def UNPACK_SEQUENCE(self, count):
        """Unpacks TOS into count individual values, which are put onto the
        stack right-to-left.
        """
        seq = self.vm.pop()
        for x in reversed(seq):
            self.vm.push(x)

    def DUP_TOPX(self, count):
        """
        Duplicate count items, keeping them in the same order. Due to
        implementation limits, count should be between 1 and 5 inclusive.
        """
        items = self.vm.popn(count)
        for i in [1, 2]:
            self.vm.push(*items)

    def STORE_ATTR(self, name):
        """Implements TOS.name = TOS1, where namei is the index of name in co_names."""
        val, obj = self.vm.popn(2)
        setattr(obj, name, val)

    def DELETE_ATTR(self, name):
        """Implements del TOS.name, using namei as index into co_names."""
        obj = self.vm.pop()
        delattr(obj, name)

    def STORE_GLOBAL(self, name):
        """Works as STORE_NAME, but stores the name as a global."""
        f = self.vm.frame
        f.f_globals[name] = self.vm.pop()

    def LOAD_CONST(self, const):
        """Pushes co_consts[consti] onto the stack."""
        self.vm.push(const)

    def LOAD_NAME(self, name):
        """Pushes the value associated with co_names[namei] onto the stack."""
        self.vm.push(self.lookup_name(name))

    def BUILD_TUPLE(self, count):
        """Creates a tuple consuming count items from the stack, and pushes
        the resulting tuple onto the stack.
        """
        self.build_container(count, tuple)

    def BUILD_LIST(self, count):
        """Works as BUILD_TUPLE, but creates a list."""
        elts = self.vm.popn(count)
        self.vm.push(elts)

    def BUILD_SET(self, count):
        """Works as BUILD_TUPLE, but creates a set. New in version 2.7"""
        elts = self.vm.popn(count)
        self.vm.push(set(elts))

    def BUILD_MAP(self, size):
        """
        Pushes a new dictionary object onto the stack. The dictionary is
        pre-sized to hold count entries.
        """
        self.vm.push({})

    def LOAD_ATTR(self, name):
        """Replaces TOS with getattr(TOS, co_names[namei]).

        Note: name = co_names[namei] set in parse_byte_and_args()
        """
        obj = self.vm.pop()
        val = getattr(obj, name)
        self.vm.push(val)

    COMPARE_OPERATORS = [
     operator.lt,
     operator.le,
     operator.eq,
     operator.ne,
     operator.gt,
     operator.ge,
     lambda x, y: x in y,
     lambda x, y: x not in y,
     lambda x, y: x is y,
     lambda x, y: x is not y,
     lambda x, y: issubclass(x, Exception) and issubclass(x, y)]

    def COMPARE_OP(self, opname):
        """Performs a Boolean operation. The operation name can be found in cmp_op[opname]."""
        x, y = self.vm.popn(2)
        self.vm.push(self.COMPARE_OPERATORS[opname](x, y))

    def IMPORT_NAME(self, name):
        """
        Imports the module co_names[namei]. TOS and TOS1 are popped and
        provide the fromlist and level arguments of __import__().  The
        module object is pushed onto the stack.  The current namespace
        is not affected: for a proper import statement, a subsequent
        STORE_FAST instruction modifies the namespace.

        Note: name = co_names[namei] set in parse_byte_and_args()
        """
        level, fromlist = self.vm.popn(2)
        frame = self.vm.frame
        self.vm.push(__import__(name, frame.f_globals, frame.f_locals, fromlist, level))

    def IMPORT_FROM(self, name):
        """
        Loads the attribute co_names[namei] from the module found in TOS.
        The resulting object is pushed onto the stack, to be
        subsequently stored by a STORE_FAST instruction.

        Note: name = co_names[namei] set in parse_byte_and_args()
        """
        mod = self.vm.top()
        if not hasattr(mod, name):
            value = ImportError("cannot import name '%s' from '%s' (%s)" % (
             name, mod.__name__, mod.__file__))
            self.vm.last_exception = (
             ImportError, value, None)
            self.last_traceback = traceback_from_frame(self.vm.frame)
            return 'exception'
        else:
            self.vm.push(getattr(mod, name))
            return

    def JUMP_FORWARD(self, jump_offset):
        """Increments bytecode counter by jump.

        Note: jump = delta + f.f_lasti set in parse_byte_and_args()
        """
        self.vm.jump(jump_offset)

    def JUMP_IF_TRUE(self, jump_offset):
        """
        If TOS is true, increment the bytecode counter by delta. TOS is
        left on the stack.

        Note: jump = delta + f.f_lasti set in parse_byte_and_args()
        """
        val = self.vm.top()
        if val:
            self.vm.jump(jump_offset)

    def JUMP_IF_FALSE(self, jump_offset):
        """
        If TOS is false, increment the bytecode counter by delta. TOS is
        not changed.

        Note: jump = delta + f.f_lasti set in parse_byte_and_args()
        """
        val = self.vm.top()
        if not val:
            self.vm.jump(jump_offset)

    def JUMP_ABSOLUTE(self, target):
        """Set bytecode counter to target."""
        self.vm.jump(target)

    def FOR_ITER(self, jump_offset):
        """
        TOS is an iterator. Call its next() method. If this yields a new
        value, push it on the stack (leaving the iterator below
        it). If the iterator indicates it is exhausted TOS is popped,
        and the bytecode counter is incremented by delta.

        Note: jump = delta + f.f_lasti set in parse_byte_and_args()
        """
        iterobj = self.vm.top()
        try:
            v = next(iterobj)
            self.vm.push(v)
        except StopIteration:
            self.vm.pop()
            self.vm.jump(jump_offset)

    def LOAD_GLOBAL(self, name):
        """
        Loads the global named co_names[namei] onto the stack.

        Note: name = co_names[namei] set in parse_byte_and_args()
        """
        f = self.vm.frame
        if name in f.f_globals:
            val = f.f_globals[name]
        elif name in f.f_builtins:
            val = f.f_builtins[name]
        else:
            raise NameError("global name '%s' is not defined" % name)
        self.vm.push(val)

    def SETUP_LOOP(self, jump_offset):
        """
        Pushes a block for a loop onto the block stack. The block spans
        from the current instruction with a size of delta bytes.

        Note: jump = delta + f.f_lasti set in parse_byte_and_args()
        """
        self.vm.push_block('loop', jump_offset)

    def SETUP_EXCEPT(self, jump_offset):
        """
        Pushes a try block from a try-except clause onto the block
        stack. delta points to the first except block.

        Note: jump = delta + f.f_lasti set in parse_byte_and_args()
        """
        self.vm.push_block('setup-except', jump_offset)

    def SETUP_FINALLY(self, jump_offset):
        """
        Pushes a try block from a try-except clause onto the block
        stack. delta points to the finally block.

        Note: jump = delta + f.f_lasti set in parse_byte_and_args()
        """
        self.vm.push_block('finally', jump_offset)

    def STORE_MAP(self):
        """
        Store a key and value pair in a dictionary. Pops the key and value while leaving the dictionary on the stack.
        """
        the_map, val, key = self.vm.popn(3)
        the_map[key] = val
        self.vm.push(the_map)

    def LOAD_FAST(self, name):
        """
        Pushes a reference to the local co_varnames[var_num] onto the stack.
        """
        if name in self.vm.frame.f_locals:
            val = self.vm.frame.f_locals[name]
        else:
            raise UnboundLocalError("local variable '%s' referenced before assignment" % name)
        self.vm.push(val)

    def STORE_FAST(self, var_num):
        """Stores TOS into the local co_varnames[var_num]."""
        self.vm.frame.f_locals[var_num] = self.vm.pop()

    def DELETE_FAST(self, var_num):
        """Deletes local co_varnames[var_num]."""
        del self.vm.frame.f_locals[var_num]

    def LOAD_CLOSURE(self, i):
        """
        Pushes a reference to the cell contained in slot i of the cell and
        free variable storage. The name of the variable is co_cellvars[i] if i is less
        than the length of co_cellvars. Otherwise it is co_freevars[i -len(co_cellvars)].
        """
        self.vm.push(self.vm.frame.cells[i])

    def LOAD_DEREF(self, i):
        """
        Loads the cell contained in slot i of the cell and free variable
        storage. Pushes a reference to the object the cell contains on the
        stack.
        """
        self.vm.push(self.vm.frame.cells[i].get())

    def STORE_DEREF(self, name):
        """
        Stores TOS into the cell contained in slot i of the cell and free variable storage.
        """
        self.vm.frame.cells[name].set(self.vm.pop())

    def SETUP_WITH(self, dest):
        ctxmgr = self.vm.pop()
        self.vm.push(ctxmgr.__exit__)
        ctxmgr_obj = ctxmgr.__enter__()
        if self.version < 3.0:
            self.vm.push_block('with', dest)
        else:
            self.vm.push_block('finally', dest)
        self.vm.push(ctxmgr_obj)

    def WITH_CLEANUP(self):
        """Cleans up the stack when a "with" statement block exits. On top of
        the stack are 1 3 values indicating how/why the finally clause
        was entered:

        * TOP = None
        * (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval
        * TOP = WHY_*; no retval below it
        * (TOP, SECOND, THIRD) = exc_info()

        Under them is EXIT, the context manager s __exit__() bound method.

        In the last case, EXIT(TOP, SECOND, THIRD) is called,
        otherwise EXIT(None, None, None).

        EXIT is removed from the stack, leaving the values above it in
        the same order. In addition, if the stack represents an
        exception, and the function call returns a  true  value, this
        information is  zapped , to prevent END_FINALLY from
        re-raising the exception. (But non-local gotos should still be
        resumed.)

        All of the following opcodes expect arguments. An argument is
        two bytes, with the more significant byte last.
        """
        v = w = None
        u = self.vm.top()
        if u is None:
            exit_func = self.vm.pop(1)
        elif isinstance(u, str):
            if u in ('return', 'continue'):
                exit_func = self.vm.pop(2)
            else:
                exit_func = self.vm.pop(1)
            u = None
        elif issubclass(u, BaseException):
            w, v, u = self.vm.popn(3)
            exit_func = self.vm.pop()
            self.vm.push(w, v, u)
        else:
            raise self.VMError('Confused WITH_CLEANUP')
        exit_ret = exit_func(u, v, w)
        err = u is not None and bool(exit_ret)
        if err:
            self.vm.popn(3)
            self.vm.push(None)
        return

    def MAKE_FUNCTION(self, argc):
        """
        Pushes a new function object on the stack. TOS is the code
        associated with the function. The function object is defined to have
        argc default parameters, which are found below TOS.
        """
        code = self.vm.pop()
        defaults = self.vm.popn(argc)
        globs = self.vm.frame.f_globals
        fn = Function(name=None, code=code, globs=globs, argdefs=defaults, closure=None, vm=self.vm)
        if argc == 0 and code.co_name in COMPREHENSION_FN_NAMES:
            fn.has_dot_zero = True
        self.vm.push(fn)
        return

    def MAKE_CLOSURE(self, argc):
        """
        Creates a new function object, sets its func_closure slot, and
        pushes it on the stack. TOS is the code associated with the
        function. If the code object has N free variables, the next N
        items on the stack are the cells for these variables. The
        function also has argc default parameters, where are found
        before the cells.
        """
        if self.version >= 3.3:
            name = self.vm.pop()
        else:
            name = None
        closure, code = self.vm.popn(2)
        defaults = self.vm.popn(argc)
        globs = self.vm.frame.f_globals
        fn = Function(name, code, globs, defaults, closure, self.vm)
        self.vm.push(fn)
        return

    def BUILD_SLICE(self, count):
        """
        Pushes a slice object on the stack. argc must be 2 or 3. If it is
        2, slice(TOS1, TOS) is pushed; if it is 3, slice(TOS2, TOS1,
        TOS) is pushed. See the slice() built-in function for more
        information.
        """
        if count == 2:
            x, y = self.vm.popn(2)
            self.vm.push(slice(x, y))
        elif count == 3:
            x, y, z = self.vm.popn(3)
            self.vm.push(slice(x, y, z))
        else:
            raise self.VMError('Strange BUILD_SLICE count: %r' % count)

    def RAISE_VARARGS(self, argc):
        """
        Raises an exception. argc indicates the number of parameters to the
        raise statement, ranging from 0 to 3. The handler will find
        the traceback as TOS2, the parameter as TOS1, and the
        exception as TOS.
        """
        exctype = val = tb = None
        if argc == 0:
            exctype, val, tb = self.vm.last_exception
        elif argc == 1:
            exctype = self.vm.pop()
        elif argc == 2:
            val = self.vm.pop()
            exctype = self.vm.pop()
        elif argc == 3:
            tb = self.vm.pop()
            val = self.vm.pop()
            exctype = self.vm.pop()
        if isinstance(exctype, BaseException):
            val = exctype
            exctype = type(val)
        self.vm.last_exception = (exctype, val, tb)
        self.last_traceback = traceback_from_frame(self.vm.frame)
        if tb:
            return 'reraise'
        else:
            return 'exception'
            return

    def CALL_FUNCTION(self, argc):
        """
        Calls a callable object.
        The low byte of argc indicates the number of positional
        arguments, the high byte the number of keyword arguments.

        The stack contains keyword arguments on top (if any), then the
        positional arguments below that (if any), then the callable
        object to call below that.

        Each keyword argument is represented with two values on the
        stack: the argument s name, and its value, with the argument's
        value above the name on the stack. The positional arguments
        are pushed in the order that they are passed in to the
        callable object, with the right-most positional argument on
        top. CALL_FUNCTION pops all arguments and the callable object
        off the stack, calls the callable object with those arguments,
        and pushes the return value returned by the callable object.
        """
        return self.call_function(argc, [], {})

    def CALL_FUNCTION_VAR(self, argc):
        """
        Calls a function. argc is interpreted as in
        CALL_FUNCTION. The top element on the stack contains the
        variable argument list, followed by keyword and positional
        arguments.
        """
        args = self.vm.pop()
        return self.call_function(argc, args, {})

    def CALL_FUNCTION_KW(self, argc):
        """Calls a function. argc is interpreted as in CALL_FUNCTION.
        The top element on the stack contains the keyword arguments
        dictionary, followed by explicit keyword and positional
        arguments.
        """
        kwargs = self.vm.pop()
        return self.call_function(argc, [], kwargs)

    def CALL_FUNCTION_VAR_KW(self, argc):
        """
        Calls a function. argc is interpreted as in
        CALL_FUNCTION. The top element on the stack contains the keyword
        arguments dictionary, followed by the variable-arguments tuple,
        followed by explicit keyword and positional arguments.
        """
        args, kwargs = self.vm.popn(2)
        return self.call_function(argc, args, kwargs)


import os
import time
import RPi.GPIO as GPIO

class RPiControl:
	'Control anything connected to relay/RPi GPIO pins (BCM mode)'

	os.system('modprobe w1-gpio')
	os.system('modprobe w1-therm')
	#set up GPIO using BCM numbering
	GPIO.setmode(GPIO.BCM)
	#GPIO.setwarnings(False)

	# intialise class
	def __init__(self, pin, sensor, temp):

		self.pin = pin  # input the pin number control relay
		self.sensor = sensor # Temp sensor file location
		self.temp = temp #input the incubation temperature

	def set_pin(self):
		GPIO.setup(self.pin, GPIO.OUT) ## Setup GPIO Pin  to OUT
		#'/sys/bus/w1/devices/28-00042b6579ff/w1_slave'

	def temp_raw(self):
		temp_sensor = self.sensor ##Setup sensor file location
		f = open(temp_sensor, 'r')
		lines = f.readlines()
		f.close()
		return lines

	def read_temp(self):
		lines = self.temp_raw()
		while lines[0].strip()[-3:] != 'YES':
			time.sleep(0.2)
			lines = self.temp_raw();
		temp_output = lines[1].find('t=')
		if temp_output != -1:
			temp_string = lines[1].strip()[temp_output+2:]
			temp_c = float(temp_string) / 1000.0
		return temp_c

	def read_temp_json(self):
		temperature = str(self.read_temp())
		temperature = {'value':temperature}
		return temperature

	def temp_control(self):
		#while (True): # need to run this in background thread. a loop command
		print (self.read_temp())
		time.sleep(1)
		if self.read_temp() < self.temp :
			GPIO.output(self.pin,False) ## Turn on GPIO pin 7
			status  = {'value':'heating'}
		elif self.read_temp() >= self.temp:
			GPIO.output(self.pin,True) ## Turn off GPIO pin 7
			status = {'value':'cooling'}
		return status


import speech_recognition as speech
import os, sys, webbrowser, pyaudio, pyttsx3, time, datetime, requests, json, random, wikipedia

undestand = ['Я не понял вашего запроса.', 'Извините, но я вас не понял.', 'Давайте еще раз.', 'Я не раслышал.', 'Упс, что-то пошло не так.', 'А теперь еще раз, пожалуйста.']
answer = ['Я вас слушаю', 'Да?', 'Я тут.']
thanks = ['Всегда пожалуйста.', 'Рад помочь.', 'Обращайтесь.']
montharr = ['Января', 'Февраля', 'Марта', 'Апреля', 'Мая', 'Июня', 'Июля', 'Августа', 'Сентября', 'Октября', 'Ноября', 'Декабря']
weekarr = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье']
name = 'алекс'

engine = pyttsx3.init()

def talk(words):
	print('Ответ: '+words)
	engine.say(words)
	engine.runAndWait()

talk('Приветствую вас.')

def command():
	record = speech.Recognizer()

	with speech.Microphone() as source:
		print('Говорите...')
		record.pause_threshold = 1
		record.adjust_for_ambient_noise(source, duration=1)
		audio = record.listen(source)

	try:
		task = record.recognize_google(audio, language="ru-RU").lower()

	except speech.UnknownValueError:
		talk(random.choice(undestand))
		task = command()

	return task

def makeSomething(task):

	print('Вы сказали: ' + task)

	if name == task:
		talk(random.choice(answer))

	if ((name and ('спасибо') or ('спасибки') or ('благодарю'))) in task:
		talk(random.choice(answer))

	elif ((name and 'дата') or (name and 'дату')) in task:
		today = datetime.datetime.today()
		week = today.weekday()
		talk('Сегодня ' + str(today.day) + ' ' + montharr[today.month] + ' ' + str(today.year) + ' года. ' + weekarr[week])

	elif ((name and 'что такое') or (name and 'как понять')) in task:

		try:
			text = task.split(' ')
			wikipedia.set_lang('ru')
			word = wikipedia.page(text[-1:])
			word = word.content
			word = word.split('''

''')
			talk(word[0])

		except:
			talk('Я не смог найти объяснений этому слову.')

	elif ((name and 'поиск') or (name and 'найди') or (name and 'поищи')) in task:
		task = task.split(' ')
		webbrowser.open('https://www.google.com/search?q='+task[-2:])

	elif ((name and 'как тебя зовут') or (name and 'скажи свое имя') or (name and 'представься')) in task:
		talk('Я бот созданный на языке python, зовут меня Алекс')

	elif ((name and 'погода') or (name and 'погоде') or (name and 'погоды')) in task:
		today = datetime.date.today()
		talk('Погода в Махачкале:')
		response = requests.get('https://api.openweathermap.org/data/2.5/find?q=Махачкала&units=metric&appid=32b1a63f8fda519a08fc67f99d97590a')
		if json.loads(response.text)['cod'] == '200':
			weather = json.loads(response.text)['list'][0]
			text = '''Температура: '''+str(weather['main']['temp'])+''' градусов цельсия. Атмосферное давление: '''+str(weather['main']['pressure'])+''' мм рт. ст. Влажность: '''+str(weather['main']['humidity'])+'''%. Скорость ветра: '''+str(weather['wind']['speed'])+' м/с'
			talk(text)
		else:
			talk('Произошла ошибка! Проверьте свой запрос, возможно вы допустили ошибку.')

	elif name and 'погода' or 'погоде' or 'погоды' in task:
		pass

	else:
		talk(random.choice(undestand))

	talk = 0

while True:
	doTask = command()
	makeSomething(doTask)


import acm
import FOrderFlowController
import FOrderFlowPlayer
import FUxCore

class OrderFlowPlayerDialog (FUxCore.LayoutDialog):
    def __init__(self, orderFlow, initialOrderBooks):
        self.orderFlow = orderFlow
        self.initialOrderBooks = initialOrderBooks
        self.orderFlowPlayer = FOrderFlowPlayer.OrderFlowPlayer(orderFlow, self)
        self.fuxDlg = None
        self.bindings = acm.FUxDataBindings()
        self.nameCtrl = self.bindings.AddBinder( 'nameCtrl', acm.GetDomain('string'), None )
        self.nextEventCtrl = self.bindings.AddBinder( 'nextEventCtrl', acm.GetDomain('string'), None )
        self.startTimeCtrl = self.bindings.AddBinder( 'startTimeCtrl', acm.GetDomain('datetime'), None )
        self.ignoreBeforeCtrl = self.bindings.AddBinder( 'ignoreBeforeCtrl', acm.GetDomain('datetime'), None )
        self.speedCtrl = self.bindings.AddBinder( 'speedCtrl', acm.GetDomain('double'), None )
        self.startBtn = None
        self.stopBtn = None
        self.resetBtn = None

    def HandleApply(self):
        return 1

    def HandleDestroy(self):
        self.orderFlowPlayer.Play(False)

    def HandleCreate( self, dlg, layout):
        self.fuxDlg = dlg
        self.fuxDlg.Caption('Order Flow Player' )
        self.bindings.AddLayout(layout)

        self.startBtn = layout.GetControl('start')
        self.stopBtn = layout.GetControl('stop')
        self.resetBtn = layout.GetControl('reset')

        self.startBtn.AddCallback( 'Activate', onStartOrderFlow, self )
        self.stopBtn.AddCallback( 'Activate', onStopOrderFlow, self )
        self.resetBtn.AddCallback( 'Activate', onResetOrderFlow, self )

        self.nameCtrl.SetValue(self.orderFlow.Name(), False)
        self.startTimeCtrl.SetValue(self.orderFlow.StartTime(), False)
        self.speedCtrl.SetValue(self.orderFlow.Speed(), False)

        self.nameCtrl.Editable(False)
        self.nextEventCtrl.Editable(False)

        self.orderFlowPlayer.InitLayout(dlg, layout)
        self.orderFlowPlayer.AddOrderBooks(self.initialOrderBooks)
        self.bindings.AddDependent( self )
        self.UpdateControls()

    def ServerUpdate(self, sender, aspectSymbol, parameter):
        if parameter == self.startTimeCtrl:
            self.orderFlow.StartTime(self.startTimeCtrl.GetValue())
        elif parameter == self.ignoreBeforeCtrl:
            self.orderFlowPlayer.NextEvent(self.ignoreBeforeCtrl.GetValue())
        elif parameter == self.speedCtrl:
            self.orderFlow.Speed(self.speedCtrl.GetValue())
        self.UpdateControls()

    def UpdateControls(self):
        self.startTimeCtrl.Enabled(not self.orderFlow.IsStarted())
        self.ignoreBeforeCtrl.Enabled(not self.orderFlow.IsStarted())
        self.speedCtrl.Enabled(not self.orderFlow.IsStarted())
        self.startBtn.Enabled(not self.orderFlow.IsStarted())
        self.stopBtn.Enabled(self.orderFlow.IsStarted())
        self.resetBtn.Enabled(not self.orderFlow.IsStarted())
        self.orderFlowPlayer.UpdateControls()
        self.UpdateNextEvent()

    def UpdateNextEvent(self):
        text = ''
        nextEvent = self.orderFlow.NextEvent()
        if nextEvent != None:
            text = nextEvent.AsString()
        elif self.orderFlow.IsStarted():
            text = 'Done'

        self.nextEventCtrl.SetValue(text, False)

    def CreateLayout(self):
        b = acm.FUxLayoutBuilder()
        b.BeginVertBox('None')

        b.  BeginVertBox('EtchedIn', 'Order Flow')
        self.nameCtrl.BuildLayoutPart(b, 'File')
        self.nextEventCtrl.BuildLayoutPart(b, 'Next Event')
        self.startTimeCtrl.BuildLayoutPart(b, 'Start Time')
        self.ignoreBeforeCtrl.BuildLayoutPart(b, 'Ignore Events Before')
        self.speedCtrl.BuildLayoutPart(b, 'Speed')
        b.  EndBox()

        self.orderFlowPlayer.BuildLayoutPart(b)

        b.  BeginHorzBox('None')
        b.    AddSpace(5)
        b.    AddFill()
        b.    AddButton('start', '&&Start')
        b.    AddButton('stop', 'S&&top')
        b.    AddButton('reset', '&&Reset')
        b.  EndBox()

        b.EndBox()
        return b

    def Play(self, play):
        self.orderFlowPlayer.Play(play)
        self.UpdateNextEvent()
        self.UpdateControls()

    def Reset(self):
        self.orderFlowPlayer.Reset()
        self.UpdateNextEvent()
        self.UpdateControls()

    def OnOrderFlowEvent(self, orderFlowEvent):
        self.UpdateNextEvent()

def onStartOrderFlow(self, cd):
    self.Play(True)

def onStopOrderFlow(self, cd):
    self.Play(False)

def onResetOrderFlow(self, cd):
    self.Reset()

def selectStartedOrderFlow(shell):
    orderFlows = acm.FArray()
    all = acm.FOrderFlow.InstancesKindOf()

    for of in all:
        if of.IsStarted() and of.Name() != None:
            orderFlows.Add(of)

    if orderFlows.IsEmpty():
        return None

    question = 'You have one or more Order Flows running. Do you want to open a running Order Flow?'
    if 'Button1' == acm.UX().Dialogs().MessageBoxYesNo(shell, 'Question', question):
        if orderFlows.Size() == 1:
            return orderFlows.First()
        return acm.UX().Dialogs().SelectObject(shell, 'Open', 'Order Flow', orderFlows, None)
    return None

def openOrderFlow(shell, orderFlow, orderBooks):
    customDlg = OrderFlowPlayerDialog(orderFlow, orderBooks)
    acm.UX().Dialogs().ShowCustomDialog(shell, customDlg.CreateLayout(), customDlg )

def onConvertToNewFormat(invokationInfo):
    shell = invokationInfo.Parameter('shell')
    fileSelection = acm.FFileSelection()
    fileSelection.FileFilter(FOrderFlowPlayer.fileFilter)
    fileSelection.PickExistingFile(True)

    if acm.UX().Dialogs().BrowseForFile(shell, fileSelection):
        try:
            FOrderFlowController.convertToNewFormat(fileSelection.SelectedFile().StringKey())
            acm.UX().Dialogs().MessageBoxInformation(shell, 'Order Flow converted!')
        except Exception as e:
            FOrderFlowPlayer.showErrorDialog(shell, 'Failed to convert Order Flow: ' + str(e))

def onShowDlg(invokationInfo):
    shell = invokationInfo.Parameter('shell')
    orderBooks = invokationInfo.ExtensionObject().ActiveSheet().Selection().SelectedOrderBooks()
    orderFlow = selectStartedOrderFlow(shell)

    if orderFlow != None:
        openOrderFlow(shell, orderFlow, orderBooks)
    else:
        fileSelection = acm.FFileSelection()
        fileSelection.FileFilter(FOrderFlowPlayer.fileFilter)
        fileSelection.PickExistingFile(True)

        if acm.UX().Dialogs().BrowseForFile(shell, fileSelection):
            selectedFile = fileSelection.SelectedFile().StringKey()
            success = False

            try:
                serializer = acm.FXmlSerializer()
                orderFlow = FOrderFlowController.importOrderFlow(selectedFile)
                if orderFlow != None:
                    openOrderFlow(shell, orderFlow, orderBooks)
                    success = True
            except:
                pass

            if not success:
                result = FOrderFlowPlayer.showErrorDialog(shell, 'The selected file does not contain a valid Order Flow')
                if 'Button1' == result:
                    onShowDlg(invokationInfo)


from scene import *
from sound import load_effect, play_effect
from random import randint, random
import json
import os
import console
from math import sin
from functools import partial

IMAGE_WIDTH = 101
IMAGE_HEIGHT = 171
IMAGE_Y_OFFSET = -30
BLOCK_HEIGHT = 40
BLOCK_DEPTH = 80
DEAD_ZONE_MIN = -0.02
DEAD_ZONE_MAX =  0.02
PLAYER_CONTROL_SPEED = 2000
PLAYER_BOUNCE_VELOCITY = 1700
PLAYER_INITIAL_BOUNCE = 1700
MAX_CLOUD_DIST = 505
DIFFICULTY_Q = 100000.0
GAME_GRAVITY = 2000
GAME_WAITING = 0
GAME_PLAYING = 1
GAME_DEAD = 2

if os.path.isfile("names.json"): # if there is a file with names...
	text_file = open("names.json") # only open it in normal mode
else: # if not...
	text_file = open("names.json", "w+") # make one

if os.stat("names.json").st_size > 0:
	for line in text_file:
		if line.istitle():
			player_name = line
		else:
			player_name = console.input_alert('What is your name? ').title()
			text_file = open("names.json", "w")
			text_file.write(player_name)
			text_file.close()
else:
	player_name = console.input_alert('What is your name? ').title()
	text_file = open("names.json", "w")
	text_file.write(player_name)
	text_file.close()

# to reduce latency, preload effects in
load_effect('Boing_1')
load_effect('Crashing')

class Player(object):
	def __init__(self):
		self.bounds = Rect()
		self.velocity = 0

	def draw(self):
		tint(1,1,1)
		image('Alien', self.bounds.x, self.bounds.y + IMAGE_Y_OFFSET)

class GroundBlock(object):
	def __init__(self):
		self.bounds = Rect()

	def draw(self):
		tint(1,1,1)
		image('PC_Grass_Block', self.bounds.x, self.bounds.y)

class Cloud (object):
	def __init__(self):
		self.shapes = []

		num_circles = randint(4, 5)
		for i in xrange(num_circles):
			x = i * 20 - ((num_circles/2)*30)
			y = (random()-0.5) * 30
			rad = randint(50, 100)
			self.shapes.append([x, y, rad])

		self.width = num_circles * 30 + 30
		self.bounds = Rect(0, 0, self.width, 60)

	def is_colliding(self, pos):
		startp = self.bounds.x - self.width/2
		endp = self.bounds.x + self.width/2
		if ((pos.x < endp) and (pos.x > startp) and
		(pos.y < (self.bounds.y + 30)) and
		(pos.y > (self.bounds.y + 10))):
			return True
		return False

	def draw(self):
		push_matrix()
		translate(self.bounds.x, self.bounds.y)
		no_stroke()
		fill(0.90, 0.90, 0.90)
		for i in self.shapes:
			ellipse(i[0], i[1] - 5, i[2], i[2])

		fill(1.00, 1.00, 1.00)
		for i in self.shapes:
			ellipse(i[0], i[1] + 5, i[2], i[2])

		pop_matrix()

class Enemy (object):
	def __init__(self, scene):
		self.scene = scene
		self.hit = False
		self.x = randint(20, 768-20)
		self.initial_x = self.x
		self.y = 1024
		self.removed = False
		self.size = 64
		self.color = Color(1, 0, 1)
		self.speed = 1.0 / self.size * 100

	def update(self, dt):
		self.y -= self.speed
		self.x = self.initial_x + sin(self.y / 100)
		if self.y < -64:
			self.removed = True
		else:
			pass

	def draw(self):
		tint(self.color.r, self.color.g, self.color.b, 1.0)
		image('Ghost', self.x - self.size/2, self.y - self.size/2, self.size, self.size)
		tint(1, 1, 1)

		global enemy_bounds
		s = self.size
		enemy_bounds = Rect(self.x - s/2 * 0.9, self.y - s/2 * 0.8, s * 0.9, s * 0.8)

class MyScene (Scene):
	def create_ground(self):
		for x in range((int(self.bounds.w) / IMAGE_WIDTH) + 1):
			block = GroundBlock()
			block.bounds = Rect(x * IMAGE_WIDTH, 0, IMAGE_WIDTH, IMAGE_HEIGHT)
			self.scenery.append(block)

	def generate_clouds(self):
		y = self.cloud_height
		while self.cloud_height < self.bounds.h * 2:
			q = min(self.climb, DIFFICULTY_Q)
			min_dist = int(MAX_CLOUD_DIST * q / DIFFICULTY_Q)
			max_dist = int(MAX_CLOUD_DIST / 2 + min_dist / 2)
			self.cloud_height += randint(min_dist, max_dist)
			cloud = Cloud()
			cloud.bounds.x = random() * (self.bounds.w - 150)
			cloud.bounds.y = self.cloud_height
			self.scenery.append(cloud)

	def cull_scenery(self):
		for sprite in self.scenery:
			if sprite.bounds.top() < 0:
				self.scenery.remove(sprite)

	def control_player(self):
		tilt = gravity().x
		if(tilt < DEAD_ZONE_MIN) or (tilt > DEAD_ZONE_MAX):
			move = self.dt * tilt * PLAYER_CONTROL_SPEED
			self.player.bounds.x += move
			if(self.player.bounds.x < 0):
				self.player.bounds.x = 0
			elif(self.player.bounds.x > self.bounds.w - self.player.bounds.w):
				self.player.bounds.x = self.bounds.w - self.player.bounds.w

	def lower_scenery(self, y):
		self.climb += y
		self.cloud_height -= y
		for sprite in self.scenery:
			sprite.bounds.y -= y

	def run_gravity(self):
		global enemy_bounds
		player_y_move = self.dt * self.player.velocity
		scenery_y_move = 0
		old_velocity = self.player.velocity
		self.player.velocity -= self.dt * GAME_GRAVITY
		if(old_velocity > 0) and (self.player.velocity <= 0):
			self.player_apex_frame = True
		self.player.bounds.y += player_y_move
		if(self.player.bounds.y >= self.player_max_y):
			scenery_y_move = self.player.bounds.y - self.player_max_y
			self.player.bounds.y = self.player_max_y
			self.lower_scenery(scenery_y_move)
		elif(self.player.bounds.top() < 0):
			self.game_state = GAME_DEAD
			play_effect('Crashing')
		elif((self.player.bounds).intersects(enemy_bounds)):
			self.game_state = GAME_DEAD
			play_effect('Powerup_1')

	def collision_detect(self):
		bounce = False
		if(self.player.velocity < 0):
			p = Point(self.player.bounds.x + self.player.bounds.w/2, self.player.bounds.y)
			for sprite in self.scenery:
				if hasattr(sprite, 'is_colliding'):
					collision = sprite.is_colliding(p)
				else:
					collision = p in sprite.bounds
				if collision:
					self.player.velocity = PLAYER_BOUNCE_VELOCITY
					play_effect('Boing_1')
					break

	def game_loop(self):
		if self.game_state == GAME_PLAYING:
			self.run_gravity()
			self.collision_detect()
			self.control_player()
			if self.player_apex_frame:
				self.cull_scenery()
				self.generate_clouds()
				self.player_apex_frame = False

	def shadow_text(self, s, x, y): # text for end of game and score keeping
		tint(0,0,0)
		text(s, 'AppleSDGothicNeo-Bold', 48, x + 2, y - 2)
		tint(0.00, 0.50, 1.00)
		text(s, 'AppleSDGothicNeo-Bold', 48, x, y)

	def score_text(self, s, x, y): # text for a new player high score
		tint(0,0,0)
		text(s, 'AppleSDGothicNeo-Bold', 48, x + 2, y - 2)
		tint(1.00, 1.00, 0.40)
		text(s, 'AppleSDGothicNeo-Bold', 48, x, y)

	def high_score(self, name, score):
		file_name = 'highscores.json'
		high_scores = {}

		try:
			with open(file_name) as in_file:
				high_scores = json.load(in_file)
		except IOError:
			pass

		curr_high_score = high_scores.get(name, score - 1)
		if score >= curr_high_score:
				high_scores[name] = score
				self.score_text('NEW HIGH SCORE!', self.bounds.w / 2, self.bounds.h * 0.75)
				with open(file_name, 'w') as out_file:
					json.dump(high_scores, out_file)

	def draw_text(self):
		if(self.game_state == GAME_WAITING):
			self.shadow_text('Tap Screen to Start', self.bounds.w / 2, self.bounds.h * 0.6)
			self.shadow_text('Tilt Screen to Steer', self.bounds.w / 2, self.bounds.h * 0.4)
		elif(self.game_state == GAME_PLAYING):
			self.shadow_text('Score : ' + str(int(self.climb / 10)), self.bounds.w / 2, self.bounds.h * 0.95)
		if(self.game_state == GAME_DEAD):
			self.shadow_text('Score : ' + str(int(self.climb / 10)), self.bounds.w / 2, self.bounds.h * 0.95)
			self.shadow_text('Game Over', self.bounds.w / 2, self.bounds.h * 0.6)
			self.shadow_text('Tap to Play Again', self.bounds.w / 2, self.bounds.h * 0.4)
			self.high_score(player_name, int(self.climb / 10))

	def setup(self):
		self.game_state = GAME_WAITING
		self.bullets = []
		self.scenery = []
		self.climb = 0
		self.create_ground()
		self.cloud_height = 200
		self.generate_clouds()
		self.player = Player()
		self.player_apex_frame = False
		self.player.bounds = Rect(self.bounds.w / 2 - IMAGE_WIDTH / 2, BLOCK_HEIGHT + BLOCK_DEPTH / 2, IMAGE_WIDTH, IMAGE_HEIGHT)
		self.player_max_y = self.bounds.h * 0.6
		self.enemies = []
		self.spawn()

	def spawn(self):
		self.enemies.append(Enemy(self))
		self.delay(random() + 1.9, self.spawn)

	def draw(self):
		self.game_loop()
		background(0.40, 0.80, 1.00)
		for sprite in self.scenery:
			sprite.draw()
		self.player.draw()
		self.draw_text()

		global enemy_bounds
		for enemy in self.enemies:
			enemy.update(self.dt)
			enemy.draw()
			enemy_rect = enemy_bounds

	def touch_began(self, touch):
		if self.game_state == GAME_WAITING:
			self.game_state = GAME_PLAYING
			self.player.velocity = PLAYER_INITIAL_BOUNCE
		elif self.game_state == GAME_DEAD:
			self.setup()

run(MyScene())


import tensorflow as tf

"""manage variable with scope"""

with tf.variable_scope("home"):
    v = tf.get_variable("father", [1], initializer=tf.constant_initializer(1.0))
    print(v.name)

"""if tf.variable_scope use parameter 'reuse' and set to True ,
   we can get same variable from one variable scope """
with tf.variable_scope("home", reuse=True):
    v1 = tf.get_variable("father", [1])
    print(v1 == v)


import numpy as np
import sys
import json
import IPython
from scipy.stats import multivariate_normal

def em(data, k):
    """
    Run EM algorithm
    @param data The dataset
    @param k The number of mixture
    @return A dictionary of `weight`, `prob`, `mean`, `cov`
    """
    n = len(data[0])
    m = len(data)
    for i in range(m):
        data[i] = np.array(data[i])
    prob = [1/k] * k
    mean = [np.array([j] * n).transpose() for j in range(k)]
    cov = [np.eye(n) for j in range(k)]

    for _ in range(30):
        dist = [
            multivariate_normal(mean[j], cov[j])
            for j in range(k)
        ]
        w = [
            np.array([prob[j] * dist[j].pdf(x) for j in range(k)])
            for x in data
        ]
        w = [x / x.sum() for x in w]

        prob = [
            sum(w[i][j] for i in range(m)) / m
            for j in range(k)
        ]
        mean = [
            sum(data[i] * w[i][j] for i in range(m)) / prob[j] / m
            for j in range(k)
        ]
        cov = [
            sum(w[i][j] * np.matrix(data[i] - mean[j]).transpose().dot(np.matrix(data[i] - mean[j])) for i in range(m)) / prob[j] / m
            for j in range(k)
        ]

        print('mean', mean)
        print('prob', prob)
        print()

    return {
        'weight': w,
        'prob': prob,
        'mean': mean,
        'cov': cov
    }

def main():
    data = json.load(sys.stdin)
    k = 2
    ret = em(data, k)
    print('prob', ret['prob'])
    for j in range(k):
        print('mean #{}'.format(j), ret['mean'][j])
        print('cov #{}'.format(j))
        print(ret['cov'][j])
main()


import openpyxl

workbook = openpyxl.load_workbook("vers02.xlsx")

workbook.active=0
worksheet=workbook.active

i = 0
for cell in worksheet['C']:
    i += 1

    try:
        cell.value = (cell.value).replace("вес", "")
        cell.value = (cell.value).strip()

        a = str(cell)
        a = a.replace(">", "")
        a = a.split(".")
        b = a[1]
        print(b)
        worksheet[f'{b}'] = cell.value
        workbook.save('vers02.xlsx')
    except AttributeError:
        print("пустая ячейка")
        worksheet[f'{b}'] = cell.value
        workbook.save('vers02.xlsx')


from matplotlib import pyplot as plt
import numpy as np

from .abs_agent_trainer import AbsAgentTrainer
from ..value import ZeroBaselineProvider
from ..i_environment import IEnvironment

class TrainingProcess(object):
    def __init__(self, agent_trainer: AbsAgentTrainer):
        self.agent_trainer = agent_trainer
        self.baseline_provider = ZeroBaselineProvider()
        self.env: IEnvironment = None

        self.to_plot = False

    def set_baseline_provider(self, baseline_provider):
        self.baseline_provider = baseline_provider
        return self

    def set_env(self, env: IEnvironment):
        self.env = env
        return self

    def plot(self):
        self.to_plot = True
        return self

    def train(self, n_trajectories: int, n_episodes: int):
        losses = []
        trajectory_sizes = []
        decisivenesses = []
        try:
            for episode in range(n_episodes):
                average_trajectory_size = 0.0
                for _ in range(n_trajectories):
                    average_trajectory_size += len(
                        self.trainer.collect_trajectory(self.env)
                    )
                decisivenesses.append(self.trainer.decisiveness())
                self.baseline_provider.update()

                losses.append(self.trainer.train(self.baseline_provider))
                trajectory_sizes.append(average_trajectory_size / n_trajectories)
                print("{}\t-> {:0.2f}".format(episode, trajectory_sizes[-1]))

        except KeyboardInterrupt:
            pass

        if self.to_plot:
            xs = [x for x in range(len(trajectory_sizes))]
            a, b = np.polyfit(xs, trajectory_sizes, 1)

            fig, axes = plt.subplots(nrows=1, ncols=3)
            axes[0].plot(losses)
            axes[1].plot(xs, trajectory_sizes, "g")
            axes[1].plot(xs, [a * x + b for x in xs], "r")
            axes[2].plot(decisivenesses)
            axes[2].set_ylim([0.0, 1.0])

            fig.tight_layout()
            plt.show()

        return (losses, trajectory_sizes, decisivenesses)


import numpy as np
import pandas as pd
import json
from os.path import join
from random import shuffle

LIKE = 1
DISLIKE = -1
UNKNOWN = 0

class User:
    def __init__(self, idx, movie_ratings=[], entity_ratings=[], split_ratio=0.75):
        """
        A simulated user. Provided movie and entity ratings, can dynamically shuffle and
        generate training/test sets of answers.
        :param idx: The index of the user.
        :param movie_ratings: (Optional) A list of (movie_idx, rating) pairs.
        :param entity_ratings: (Optional) A list of (entity_idx, rating) pairs.
        :param split_ratio: (Optional, default 0.75) the ratio between training/test set sizes.
        """

        self.idx = idx
        self.movie_ratings = movie_ratings
        self.entity_ratings = entity_ratings
        self.split_ratio = split_ratio

        self.m_answers = None
        self.e_answers = None
        self.m_test_answers = None
        self.e_test_answers = None

    def shuffle(self):
        """
        Shuffles the user's ratings and generates new training and test answer sets.
        """
        self._reset()

        # Shuffle the ratings
        shuffle(self.movie_ratings)
        shuffle(self.entity_ratings)

        # Split into training and test answers
        m_answers, m_test_answers = split(self.movie_ratings, split_ratio=self.split_ratio)
        e_answers, e_test_answers = split(self.entity_ratings, split_ratio=self.split_ratio)

        self.m_answers = {m: r for m, r in m_answers}
        self.e_answers = {e: r for e, r in e_answers}
        self.m_test_answers = {m: r for m, r in m_test_answers}
        self.e_test_answers = {e: r for e, r in e_test_answers}

    def ask_movie(self, m, evaluation=False):
        answers = self.m_test_answers if evaluation else self.m_answers
        return answers[m] if m in answers else UNKNOWN

    def ask_entity(self, e, evaluation=False):
        answers = self.e_test_answers if evaluation else self.e_answers
        return answers[e] if e in answers else UNKNOWN

    def _reset(self):
        self.m_answers = {}
        self.e_answers = {}
        self.m_test_answers = {}
        self.e_test_answers = {}

class DataSet:
    def __init__(self, user_set, n_users, n_movies, n_entities):
        self.user_set = user_set
        self.n_users = n_users
        self.n_movies = n_movies
        self.n_entities = n_entities

    def split_users(self, split_ratio=0.75):
        return split(self.user_set, split_ratio=split_ratio)

    @staticmethod
    def shuffle(user_set):
        shuffle(user_set)  # Shuffle the order of users
        [u.shuffle() for u in user_set]  # Shuffle ratings for each user, generate new learning and test sets
        return user_set

def get_label_map(entities):
    # Map URIs to labels
    label_map = {}
    for uri, name, labels in entities:
        labels = labels.split('|')
        if uri not in label_map:
            label_map[uri] = labels

    return label_map

def get_top_entities(ratings, top_n):
    count_map = {}
    for uid, uri, r in ratings:
        if uri not in count_map:
            count_map[uri] = 0
        count_map[uri] += 1

    sorted_entities = sorted(count_map.items(), key=lambda x: x[1], reverse=True)
    sorted_entities = [uri for uri, count in sorted_entities]
    return sorted_entities if top_n is None else sorted_entities[:top_n]

def split(lst, split_ratio=0.75):
    split_index = int(len(lst) * split_ratio)
    lst1 = lst[:split_index]
    lst2 = lst[split_index:]

    return lst1, lst2

def generate_dataset(mindreader_dir='../data/mindreader', top_n=100):
    """
    Lorem ipsum
    :param mindreader_dir:
    :param top_n:
    :return:
    """
    with open(join(mindreader_dir, 'ratings_clean.json')) as fp:
        all_ratings = json.load(fp)
    with open(join(mindreader_dir, 'entities_clean.json')) as fp:
        entities = json.load(fp)

    # Filter out "don't know" ratings
    # TODO: See if we can use them for something
    all_ratings = [(uid, uri, r) for uid, uri, r in all_ratings if not r == 0]

    label_map = get_label_map(entities)

    # Split into movie and entity ratings
    movie_ratings = [(uid, uri, r) for uid, uri, r in all_ratings if 'Movie' in label_map[uri]]
    entity_ratings = [(uid, uri, r) for uid, uri, r in all_ratings if 'Movie' not in label_map[uri]]

    # Take the top-N
    top_movies = get_top_entities(movie_ratings, top_n=top_n)
    top_entities = get_top_entities(entity_ratings, top_n=top_n)

    # Filter out non-top entity/movie ratings
    movie_ratings = [(uid, uri, r) for uid, uri, r in all_ratings if uri in top_movies]
    entity_ratings = [(uid, uri, r) for uid, uri, r in all_ratings if uri in top_entities]

    # Map UIDs and URIs to indices
    uid_idx_map = {}
    m_uri_idx_map = {}
    e_uri_idx_map = {}
    u, m, e = 0, 0, 0

    for uid, uri, r in movie_ratings:
        if uid not in uid_idx_map:
            uid_idx_map[uid] = u
            u += 1
        if uri not in m_uri_idx_map:
            m_uri_idx_map[uri] = m
            m += 1
    for uid, uri, r in entity_ratings:
        if uid not in uid_idx_map:
            uid_idx_map[uid] = u
            u += 1
        if uri not in e_uri_idx_map:
            e_uri_idx_map[uri] = e
            e += 1

    # Create indexed rating triples
    movie_ratings = [
        (uid_idx_map[uid], m_uri_idx_map[uri], r)
        for uid, uri, r
        in movie_ratings
    ]

    entity_ratings = [
        (uid_idx_map[uid], e_uri_idx_map[uri] + m, r)  # Add movie idx to convert to same index space
        for uid, uri, r
        in entity_ratings
    ]

    # Create the users
    user_set = [User(idx) for idx in range(u)]

    # Assign ratings to users
    for u_idx, m_idx, r in movie_ratings:
        user_set[u_idx].movie_ratings.append((m_idx, r))
    for u_idx, e_idx, r in entity_ratings:
        user_set[u_idx].entity_ratings.append((e_idx, r))

    # Return the data set
    return DataSet(user_set, u, m, e)


import mechanize
import cookielib
import sys
import re
from Tkinter import *

#self defined find function
def find(text, pattern, start):
    """Return the index of the first occurence of pattern in text starting
    at start. Retun -1 if not found

    find(str, str, int) -> int
    """
    pattern_len = len(pattern)
    text_len = len(text)
    i = start
    while i < text_len:
        if pattern == text[i:i+pattern_len]:
            return i
        i += 1
    return -1

#controls found by name
##control=br.form.find_control("controlname")

#searching:
def search():
    """Searches for an item in teh gw2spidy database fromk input, returns prices of item along with viability for flipping.

    search()-> str"""
    while True:
        #Makes a browser object
        br=mechanize.Browser()

        #Sets cookies
        cj =cookielib.LWPCookieJar()
        br.set_cookiejar(cj)

        #Sets the browser options
        br.set_handle_equiv(True)
        br.set_handle_gzip(True)
        br.set_handle_redirect(True)
        br.set_handle_referer(True)
        br.set_handle_robots(False)

        #sets refresh rate for pages
        br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)

        #Debug messages on
        br.set_debug_http(True)
        br.set_debug_redirects(True)
        br.set_debug_responses(True)

        #Spoof a user agent
        ##br.addheader = [('User-agent', 'Mozilla/5.0 (X11; U; Linus i686; en-US; rv:1.9.0.1)Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]

        #Opening a site
        r= br.open('http://gw2spidy.com')
        html = r.read()

        #print the source
        ##print html

        #print the title
        #print br.title()

        #print response headers
        #print r.info()

        #show available forms for entering
##        for f in br.forms():
##            print "Form name:", f.name
##            pass

        #select the first form (has index of zero)
        br.form=list(br.forms())[0]

        #iterating through the controls in the form
        #for control in br.form.controls:
         #   print control
          #  print "type=%s, name=%s valu=%s" % (control.type, control.name, br[control.name])
        query=form.get()
        br.form=list(br.forms())[0]
        control.value=query
        response= br.submit()
        res=response.read()
        w=open('scrape_current.txt', 'w')
        w.write(res)
        w.close()
        findprice()
        return False

def findprice():
    f=open('scrape_current.txt', 'rU')
    source=f.read()
    source=str(source)
    f.close()

##################################################################################

    #sell
    sell_index=source.find('Sell Price', 0)
    sell_end_index=source.find('	', sell_index)
    sellprice=source[sell_index:sell_end_index]

    #Worth at least 1 gold
    if find(sellprice, 'gold', 0) != -1:
        gold_sell_index=sellprice.find('money-fragment',0)
        gold_sell_end=sellprice.find('>g<',gold_sell_index)
        gold_sell=sellprice[gold_sell_index:gold_sell_end]
        gold_sell=gold_sell.replace("gw2money", '')
        gold_sell=re.sub("\D", '', gold_sell)
        silv_sell_index=sellprice.find('money-fragment',gold_sell_end)
        silv_sell_end=sellprice.find('>s<',silv_sell_index)
        silv_sell=sellprice[silv_sell_index:silv_sell_end]
        silv_sell=silv_sell.replace("gw2money", '')
        silv_sell=re.sub("\D", '', silv_sell)
        if len(silv_sell)==0:
            silv_sell='0'
        cop_sell_index=sellprice.find('money-fragment',silv_sell_end)
        cop_sell_end=sellprice.find('>c<',cop_sell_index)
        cop_sell=sellprice[cop_sell_index:cop_sell_end]
        cop_sell=cop_sell.replace("gw2money", '')
        cop_sell=re.sub("\D", '', cop_sell)
        if len(cop_sell)==0:
            cop_sell='0'

    #Worth at least 1 silver
    elif find(sellprice, 'gold', 0) == -1 and find(sellprice, 'silver', 0) != -1:
        silv_sell_index=sellprice.find('money-fragment',0)
        silv_sell_end=sellprice.find('>s<',silv_sell_index)
        silv_sell=sellprice[silv_sell_index:silv_sell_end]
        silv_sell=silv_sell.replace("gw2money", '')
        silv_sell=re.sub("\D", '', silv_sell)
        cop_sell_index=sellprice.find('money-fragment',silv_sell_end)
        cop_sell_end=sellprice.find('>c<',cop_sell_index)
        cop_sell=sellprice[cop_sell_index:cop_sell_end]
        cop_sell=cop_sell.replace("gw2money", '')
        cop_sell=re.sub("\D", '', cop_sell)
        if len(cop_sell) == 0:
            cop_sell = '0'
        gold_sell='0'

    #Worth less than 1 silver
    else:
        cop_sell_index=sellprice.find('money-fragment',0)
        cop_sell_end=sellprice.find('>c<',cop_sell_index)
        cop_sell=sellprice[cop_sell_index:cop_sell_end]
        cop_sell=cop_sell.replace("gw2money", '')
        cop_sell=re.sub("\D", '', cop_sell)
        silv_sell='0'
        gold_sell='0'

#############################################################################################

    #buy
    buy_index=source.find('Buy Price', sell_end_index)
    buy_end_index=source.find('	', buy_index)
    buyprice=source[buy_index:buy_end_index]

    #gold
    if find(buyprice, 'gold', 0) != -1:
        gold_buy_index=buyprice.find('money-fragment',0)
        gold_buy_end=buyprice.find('>g<',gold_buy_index)
        gold_buy=buyprice[gold_buy_index:gold_buy_end]
        gold_buy=gold_buy.replace("gw2money", '')
        gold_buy=re.sub("\D", '', gold_buy)
        silv_buy_index=buyprice.find('money-fragment',gold_buy_end)
        silv_buy_end=buyprice.find('>s<',silv_buy_index)
        silv_buy=buyprice[silv_buy_index:silv_buy_end]
        silv_buy=silv_buy.replace("gw2money", '')
        silv_buy=re.sub("\D", '', silv_buy)
        if len(silv_buy) == 0:
            silv_buy ='0'
        cop_buy_index=buyprice.find('money-fragment',silv_buy_end)
        cop_buy_end=buyprice.find('>c<',cop_buy_index)
        cop_buy=buyprice[cop_buy_index:cop_buy_end]
        cop_buy=cop_buy.replace("gw2money", '')
        cop_buy=re.sub("\D", '', cop_buy)
        if len(cop_buy) == 0:
            cop_buy='0'

    #silver
    elif find(buyprice, 'silver', 0) != -1:
        silv_buy_index=buyprice.find('money-fragment',0)
        silv_buy_end=buyprice.find('>s<',silv_buy_index)
        silv_buy=buyprice[silv_buy_index:silv_buy_end]
        silv_buy=silv_buy.replace("gw2money", '')
        silv_buy=re.sub("\D", '', silv_buy)
        cop_buy_index=buyprice.find('money-fragment',silv_buy_end)
        cop_buy_end=buyprice.find('>c<',cop_buy_index)
        cop_buy=buyprice[cop_buy_index:cop_buy_end]
        cop_buy=cop_buy.replace("gw2money", '')
        cop_buy=re.sub("\D", '', cop_buy)
        if len(cop_buy) ==0:
            cop_buy='0'
        gold_buy='0'

    #copper
    else:
        cop_buy_index=buyprice.find('money-fragment',0)
        cop_buy_end=buyprice.find('>c<',cop_buy_index)
        cop_buy=buyprice[cop_buy_index:cop_buy_end]
        if len(cop_buy) != 0:
            cop_buy=cop_buy.replace("gw2money", '')
            cop_buy=re.sub("\D", '', cop_buy)
        else:
            cop_buy = '0'
        silv_buy='0'
        gold_buy='0'

    print ("Buy: "+gold_buy + 'gold, '+ silv_buy+ 'silver, ' + cop_buy+'copper.')
    print ("Sell: "+gold_sell + 'gold ' + silv_sell + 'silver ' + cop_sell+'copper.')

    profit = (((int(gold_sell)*10000)+(int(silv_sell)*100)+int(cop_sell))*.85)-((int(gold_buy)*10000)+(int(silv_buy)*100)+int(cop_buy))
    profit= round(profit)
    profit = int(profit)
    if profit > 0 :
        profit=str(profit)
        if len(profit) < 3:
            prof=("Profit: " + profit + 'c')
            result.config(text=prof)
            pass
        elif len(profit) == 3:
            prof=("Profit: " + profit[0] + 's' + profit [1:] + 'c')
            result.config(text=prof)
            pass
        elif len(profit) == 4:
            prof=("Profit: " + profit[0]+ profit[1] + 's' + profit [2:] + 'c')
            result.config(text=prof)
            pass
        elif len(profit) == 5:
            prof=("Profit: " + profit[0] + 'g' + profit[1]+ profit[2] + 's' + profit[3:] + 'c')
            result.config(text=prof)
            pass
        elif len(profit) == 6:
            prof=("Profit: " + profit[0]+ profit[1] + 'g' + profit[2] + profit[3] + 's' + profit[4:] +'c')
            result.config(text=prof)
            pass

    else:
        prof= "Item flipping not viable."
        result.config(text=prof)
    return True

##    return buyprice, sellprice

root = Tk()

root.title('Guild Wars 2 - Item Flipping')

label=Label(root, text='Enter item: ')
label.pack(side=LEFT)

form=Entry(root, width=20)
form.pack(side=LEFT)

calc=Button(root, bg="white", text="Check!", command=search)
calc.pack(side=LEFT)

result=Label(root, text='')
result.pack(side=LEFT)
root.mainloop()


from django.urls import path
from . import views

urlpatterns = [

    path('register', views.register , name= "register"),
    path('login', views.login, name ="login"),
    path('logout', views.logout, name ="logout"),
    path('otpauth', views.getotp, name= "getotp"),
    path('otpcheck', views.otpcheck, name="otpcheck"),
    path('snippet', views.snippet_detail, name="snippet")
]


"""
AUTHOR:  zeng_xiao_yu
GITHUB:  https://github.com/zengxiaolou
EMAIL:   zengevent@gmail.com
TIME:    2020/7/15-17:31
"""
from elasticsearch import Elasticsearch
es = Elasticsearch(hosts=["192.168.44.163:9200"])

data = {
    "doc": {
        "aa": 3
    }

}

# res = es.index("test1", data)
res = es.update("test1", "mGvaUXMBXRTZYmk_mjaJ", data)

print(res)


import argparse
import os
from dftfs import Storage

def main(arguments):
    storage = allocate_application(arguments)

    # Put data into a file
    path = input("Give the path where you want to store your message : ")
    #Check if path already exists
    while storage.exists(path):
        path = input("The path already exists, please give another path : ")
    msg = input("Give the message you want to store : ")
    print("Storing the message in \""+path+"\" ...")
    storage.put(path, msg)
    print("The message has been stored in \""+path+"\".")

    # Retrieve data
    print("Retrieving the message from \""+path+"\" ...")
    retrieved = storage.get(path)
    print("The message you stored is : "+retrieved+".")

    print("---------------------------")
    print("As a reminder from the report, log/log_crash.txt contains a mapping of the master knowledge.")
    print("We can map the worker to a file. The PID of this worker is displayed after launching init.sh")
    print("---------------------------")
    pid1 = input("Give the PID the first worker containing the message (assuming a valid PID) : ")
    pid2 = input("Give the PID the second worker containing the message (assuming a valid PID) : ")
    pid3 = input("Give the PID the third worker containing the message (assuming a valid PID) : ")
    print("Killing "+pid1+" "+pid2+" "+pid3+".")
    cmd = "kill "+str(pid1)+" "+str(pid2)+" "+str(pid3)
    os.system(cmd)

def allocate_application(arguments):
    application = Storage(port=arguments.port)

    return application

def parse_arguments():
    parser = argparse.ArgumentParser("DFTFS")
    parser.add_argument("--port", type=int, default=8000,
                        help="Sets the address of the master node.")

    arguments, _ = parser.parse_known_args()

    return arguments

if __name__ == "__main__":
    arguments = parse_arguments()
    main(arguments)


import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='3'
import cv2
from keras.models import load_model
import glob
note = ""

def etape4():
    model = load_model('/home/jabrane/Downloads/pfa/project/recognition/model_02/model_02.h5')

    images = []
    nn = []
    for filename in glob.glob('/home/jabrane/Downloads/pfa/project/noteFinal/note_0*.png'):
        nn.append(filename)
    nn.sort()

    for fichier in nn:
        img = cv2.imread(fichier, 0)
        images.append(img)

    for file in os.listdir('/home/jabrane/Downloads/pfa/project/noteFinal/'):
        if file.endswith('.png'):
            os.remove('/home/jabrane/Downloads/pfa/project/noteFinal/'+file)

    noteFinal = ""
    for img in images:
        img = img.reshape(1,1,28,28).astype('float32')
        img = img / 255
        prediction = model.predict_classes(img)
        noteFinal = noteFinal + str(prediction[0])

    if len(images) > 2:
        print("Note final = " + noteFinal[0:2] + ","+ noteFinal[2:] + "/20")
        note = noteFinal[0:2] + ","+ noteFinal[2:] + "/20"
    else:
        print("Note final = " + noteFinal + "/20")
        note = noteFinal + "/20"

    return note