#Author-Ajay(Your Father)
#Description-

import adsk.core, adsk.fusion, adsk.cam, traceback

#Basic core modules
import sys, os, inspect, subprocess, time

#Updated Basic modules
from .Modules import pip

#Modules needed to read Excel sheet
from .Modules import xlrd
#from .Modules import numpy as np
from .Modules import xlwt

script_path = os.path.abspath(inspect.getfile(inspect.currentframe()))
script_name = os.path.splitext(os.path.basename(script_path))[0]
script_dir = os.path.dirname(script_path)

sys.path.append(script_dir + "\Modules")
try:
    from openpyxl import load_workbook

finally:
    del sys.path[-1]

#from .Modules import win32com
#Moduels needed to write Excel Sheet
#from .Modules import openpyxl
#from .Modules.openpyxl import load_workbook
#from .Modules import editpyxl
#from .Modules import xlsxwriter
#from .Modules import xlutils
#from .Modules.xlutils import copy
#from .Modules import workbook
#from .Modules import worksheet

#Path of the Excel sheet(r: means raw address)
fileLocation = r"C:\Users\Internet\Desktop\Ajay's Project\Scalable Drone(Second Phase)\ScalableDroneProject(Spyder Script)\Mod UAV - Updated.xlsx"
sheetName = 'Initial Sizing'

#workbsook = xlrd.open_workbook(fileLocation)
workbookRead = xlrd.open_workbook(fileLocation, on_demand = True)
worksheetRead = workbookRead.sheet_by_name(sheetName)

workbookWrite = load_workbook(fileLocation)
worksheetWrite = workbookWrite.get_sheet_by_name(sheetName)
#worksheetWrite['A1'] = 'A1'
#workbookWrite.save(fileLocation)
#print(workbookWrite.sheetnames)
#sheetNamesAll = workbook.sheet_names()
#print(sheetNamesAll)

#Selecting which sheet to get the data
#workbook = xlutils.copy(workbook)

## get Sheet
#source = workbookWrite.get_sheet_by_name(sheetName)
#
## copy sheet
#target = workbookWrite.copy_worksheet(source)

#worksheetWrite = workbookWrite[sheetName]

# Creating classes to import datas
class Motor:

    def __init__(self, modelName, mass, baseDiameter, holeSize, holeDistanceXaxis, holeDistanceYaxis, maxCurrentDraw, recommendedVoltage):
        self.modelName = modelName
        self.mass = mass
        self.measurements = self.Measurements( baseDiameter, holeSize, holeDistanceXaxis, holeDistanceYaxis)
        self.maxCurrentDraw = maxCurrentDraw
        self.recommendedVoltage = recommendedVoltage

    def show(self):
        print("\n\n\n\nMotor Model: {0}\nMass: {1}g\nMax Current Draw: {2}A\nRecommended Voltage: {3}V".format( self.modelName, self.mass, self.maxCurrentDraw, self.recommendedVoltage))
        self.measurements.show()

    class Measurements:

        def __init__(self, baseDiameter, holeSize, holeDistanceXaxis, holeDistanceYaxis):
            self.baseDiameter = baseDiameter
            self.holeSize = holeSize
            self.holeDistanceXaxis = holeDistanceXaxis
            self.holeDistanceYaxis = holeDistanceYaxis

        def show(self):
            print("Base Diameter: {0}mm\nHole Size: {1}mm\nHole Distance X axis: {2}mm\nHole Distance Y axis: {3}mm\n".format( self.baseDiameter, self.holeSize, self.holeDistanceXaxis, self.holeDistanceYaxis))

class Camera:

    def __init__(self, modelName, mass, frameRate, resolution, length, width, height):
        self.modelName = modelName
        self.mass = mass
        self.frameRate = frameRate
        self.resolution = resolution
        self.measurements = self.Measurements( length, width, height)

    def show(self):
        print("\n\n\n\nCamera Model: {0}\nMass: {1}g\nFrame Rate: {2}fps\nResolution: {3}p".format( self.modelName, self.mass, self.frameRate, self.resolution))
        self.measurements.show()

    class Measurements:

        def __init__( self, length, width, height):
            self.length = length
            self.width = width
            self.height = height

        def show(self):
            print("Length: {0}mm\nWidth: {1}mm\nHeight: {2}mm\n".format( self.length, self.width, self.height))

class FlightController:

    def __init__(self, modelName, mass, length, width, height):
        self.modelName = modelName
        self.mass = mass
        self.measurements = self.Measurements( length, width, height)

    def show(self):
        print("\n\n\n\nFCC Model: {0}\nMass: {1}g".format( self.modelName, self.mass))
        self.measurements.show()

    class Measurements:

        def __init__(self, length, width, height):
            self.length = length
            self.width = width
            self.height = height

        def show(self):
            print("Length: {0}mm\nWidth: {1}mm\nHeight: {2}mm".format( self.length, self.width, self.height))

class ElectronicSpeedController:

    def __init__(self, modelName, massPerArm, length, width, height, currentFactor, maxCurrentRequired, typeESC, maxContinousCurrent, builtInESC):
        self.modelName = modelName
        self.massPerArm = massPerArm
        self.measurements = self.Measurements(length, width, height)
        self.currentFactor = currentFactor
        self.maxCurrentRequired = maxCurrentRequired
        self.typeESC = typeESC
        self.maxContinousCurrent = maxContinousCurrent
        self.builtInESC = builtInESC

    def show(self):
        print("\n\n\n\nESC Model: {0}\nMass Per Arm: {1}g\nCurrent Factor: {2}\nMax Current Required: {3}A\nESC Type: {4}\nMax Continous Current: {5}A\nBuilt-in ESC: {6}".format(self.modelName, self.massPerArm, self.currentFactor, self.maxCurrentRequired, self.typeESC, self.maxContinousCurrent, self.builtInESC))
        self.measurements.show()

    class Measurements:

        def __init__(self, length, width, height):
            self.length = length
            self.width = width
            self.height = height

        def show(self):
            print("Length: {0}mm\nWidth: {1}mm\nHeight: {2}mm\n".format( self.length, self.width, self.height))

class Battery:

    def __init__(self, modelName, mass, capacity, cell, discharge, length, width, height):
        self.modelName = modelName
        self.mass = mass
        self.capacity = capacity
        self.cell = cell
        self.discharge = discharge
        self.measurements = self.Measurements(length, width, height)

    def show(self):
        print("\n\n\n\nBattery Model: {0}\nMass: {1}g\nCapacity: {2}mAh\nCell: {3}S\nDischarge: {4}C".format(self.modelName, self.mass, self.capacity, self.cell, self.discharge))
        self.measurements.show()

    class Measurements:

        def __init__(self, length, width, height):
            self.length = length
            self.width = width
            self.height = height

        def show(self):
           print("Length: {0}mm\nWidth: {1}mm\nHeight: {2}mm".format( self.length, self.width, self.height))

class Telemetry:

    def __init__(self, modelName, mass, antennaLength, length, width, height):
        self.modelName = modelName
        self.mass = mass
        self.antennaLength = antennaLength
        self.measurements = self.Measurements(length, width, height)

    def show(self):
        print("\n\n\n\nTelemetry Model: {0}\nMass: {1}g\nAntenna Length: {2}mm".format(self.modelName, self.mass, self.antennaLength))
        self.measurements.show()

    class Measurements:

        def __init__(self, length, width, height):
            self.length = length
            self.width = width
            self.height = height

        def show(self):
            print("Length: {0}mm\nWidth: {1}mm\nHeight: {2}mm".format( self.length, self.width, self.height))

class GPS:

    def __init__ (self, modelName, mass, length, width, height):
        self.modelName = modelName
        self.mass = mass
        self.measurements = self.Measurements(length, width, height)

    def show(self):
        print("\n\n\n\nGPS Model: {0}\nMass: {1}g".format(self.modelName, self.mass))
        self.measurements.show()

    class Measurements:

        def __init__(self, length, width, height):
            self.length = length
            self.width = width
            self.height = height

        def show(self):
            print("Length: {0}mm\nWidth: {1}mm\nHeight: {2}mm\n".format( self.length, self.width, self.height))

class PowerDistributionBoard:

    def __init__(self, modelName, mass, length, width, height):
        self.modelName = modelName
        self.mass = mass
        self.measurements = self.Measurements(length, width, height)

    def show(self):
        print("\n\n\n\nPDB Model: {0}\nMass: {1}g".format(self.modelName, self.mass))
        self.measurements.show()

    class Measurements:

        def __init__(self, length, width, height):
            self.length = length
            self.width = width
            self.height = height

        def show(self):
            print("Length: {0}mm\nWidth: {1}mm\nHeight: {2}mm\n".format( self.length, self.width, self.height))

class Drone:

    def __init__(self, length, width, height, mass, centerGravity, area, density, volume, thickness, offsetLength, offsetWidth, offsetHeight):
        self.length = length
        self.width = width
        self.height = height
        self.mass = mass
        self.centerGravity = centerGravity
        self.area = area
        self.density = density
        self.volume = volume
        self.design = self.Design(thickness, offsetLength, offsetWidth, offsetHeight)

    class Design:

        def __init__(self, thickness, offsetLength, offsetWidth, offsetHeight):
            self.thickness = thickness
            self.offsetLength = offsetLength
            self.offsetWidth = offsetWidth
            self.offsetHeight = offsetHeight

        def show(self):
            print("\n\n\n\nDrone Design:\nThickness: {0}mm\nOffset Length: {1}\nOffset Width: {2}\nOffset Height: {3}".format(self.thickness, self.offsetLength, self.offsetWidth, self.offsetHeight))
class Propeller:

    def __init__(self, modelName, radius, mass):
        self.modelName = modelName
        self.radius = radius
        self.mass = mass

    def show(self):
        print("\n\n\n\nPropeller:\nModel Name: {0}\nRadius: {1}mm\nMass: {2}g\n".format(self.modelName, self.radius, self.mass))

class PrintSpecs:

    def __init__ (self, maxLength, maxWidth, maxHeight):
        self.maxLength = maxLength
        self.maxWidth = maxWidth
        self.maxHeight = maxHeight

    def show(self):
         print("\n\n\n\nPriner Bed Size:\nMax Length: {0}mm\nMax Width: {1}mm\nMax Height: {2}mm\n".format(self.maxLength, self.maxWidth, self.maxHeight))

class UserInput:

    def __init__(self, resolution, cameraStability, endurance, camMassAsMTOW):
        self.resolution = resolution
        self.cameraStability = cameraStability
        self.endurance = endurance
        self.camMassAsMTOW = camMassAsMTOW

    def show(self):
        print("User Input Selection:\nCamera Resolution selected: {0}p\nCamera Stability selected: {1}\nEndurance selected(hrs): {2}hrs\nCam-Mass-as-MTOW selected(%): {3}%\n".format(self.resolution, self.cameraStability, self.endurance, self.camMassAsMTOW))

#Function to open excel for User
def updateExcelSheet():

    #Getting the updated changes
    #Open Excel File
    def openExcel():
        os.startfile(fileLocation)

    def closeExcel():
        os.system('TASKKILL /F /IM EXCEl.exe')

    print("Please Save and Close excel sheet after selecting.")

    openExcel()

    def process_exists(process_name):
        call = 'TASKLIST', '/FI', 'imagename eq %s' % process_name
        # use buildin check_output right away
        output = subprocess.check_output(call)
#        # check in last line for process name
        last_line = output.strip().split()[-1]

        #print(last_line)
        if(last_line == b'K'):
            return True
        else:
            return False
#        # because Fail message could be translated
        #return last_line.lower().startswith(process_name).lower()

    print(process_exists('EXCEL.exe'))

    while(process_exists('EXCEL.exe') == True):
        time.sleep(2.5)

    workbookRead = xlrd.open_workbook(fileLocation, on_demand = True)
    worksheetRead = workbookRead.sheet_by_name(sheetName)

##Default Values
#Motor Properties
motor = Motor('1105-7500KV', 5.9, 27.5, 3, 16, 19, 0, 0)

#Camera Properties
camera = Camera('GWY CMOS Camera with VCR', 20, 60, 720, 26, 28, 25)

#Flight Controller Properties
flightCC = FlightController('PixRacer R15', 10.54, 36, 36 , 11.5)

#Electronic Speed Controller Properties
esc = ElectronicSpeedController('Turnighy MultiStar Race 4-in-1 10A', 13, 27, 27, 3, 0, 0, 0, 0, 0)

#Battery Properties
battery = Battery('ZIPPY Compact', 264, 3700, 3, 25, 146, 43, 19)

#Telemetry Properties
telemetry = Telemetry('Holybro 100mW FPV Transceiver Telemetry Radio Set (433Mhz)', 'unknown', 26, 56, 26, 19)

#GPS Properties
gps = GPS('Ublox Neo-M9N', 22.4, 3.7,  3.7, 1.2)

#Power Distribution board Properties
pdb = PowerDistributionBoard('Diatone v8.3 LC Filtered', 5.5, 3.6,  3.6, 1)

#Drone Properties
drone = Drone(0, 0, 0, 0, 0, 0, 0, 0, 3, 10, 0, 5)

#Propeller Properties
prop = Propeller('GF5152-3' , 64.77, 5.3)

#3D Printer Properties
threeDprinter = PrintSpecs(215, 197, 200)

#User Input
userInput = UserInput(0, 0, 0, 0)

def droneLengthCalculation():

    totalLength = 0
    #totalLength = camera.measurements.length + flightCC.measurements.length + esc.measurements.length + telemetry.measurements.length + telemetry.antennaLength + (4*drone.design.offsetLength)

    #Second Method
    totalLengthArray = [camera.measurements.length, flightCC.measurements.length, esc.measurements.length, telemetry.measurements.length, telemetry.antennaLength, drone.design.offsetLength]

    for x in totalLengthArray:
        #print(x)

        if(x == drone.design.offsetLength):
            numberOfComponent = len(totalLengthArray) - 2
            totalLength = totalLength + (numberOfComponent)*(drone.design.offsetLength)
        elif(x != 0):
            totalLength = totalLength + x
        else:
            i = 0
            i = i + 1
            print("Warning: {0} is NULL in totalLengthArray list".format(i))

    return totalLength

def droneWidthCalculation():
    totalWidth = 0

    totalWidthArray = [camera.measurements.width, flightCC.measurements.width, esc.measurements.width, telemetry.measurements.width, battery.measurements.width]

    #print(totalWidthArray)

    totalWidthArray.sort(reverse = True)
    #print(totalWidthArray)
    totalWidth = totalWidth + totalWidthArray[0]

    for x in totalWidthArray:
        #print(x)

        if(x == 0):
            i = 0
            i = i + 0
            print("Warning: {0} is NULL in totalWidthArray list".format(i))

    totalWidth = totalWidth + 2*drone.design.offsetWidth

    return totalWidth

def droneHeightCalculation():
    totalHeight = 0

    totalHeightArray = [camera.measurements.height, flightCC.measurements.width, esc.measurements.height, telemetry.measurements.height]
    #print(totalHeightArray)
    totalHeightArray.sort(reverse = True)
    #print(totalHeightArray)

    totalHeight = totalHeight + totalHeightArray[0]

    totalHeight = totalHeight + drone.design.offsetHeight

    return totalHeight

#Function: makeing sure that data is not empyty
def checkingDataExcel(row, col):

    workbookRead = xlrd.open_workbook(fileLocation, on_demand = True)
    worksheetRead = workbookRead.sheet_by_name(sheetName)

    if(worksheetRead.cell(row, col).value != xlrd.empty_cell.value):
        #print(workbookMainData.cell(axisY, axisX).value)
        return worksheetRead.cell(row, col).value
    else:
        print("Warning: Empty input at {0}\n({1},{2})".format(worksheetRead.cell(row, col).value, row, col))

#Search string cell function, returns value of the string
def execlSearchCell(string, addRow, addCol):

    workbookRead = xlrd.open_workbook(fileLocation, on_demand = True)
    worksheetRead = workbookRead.sheet_by_name(sheetName)

    i=0
    area = worksheetRead.nrows*worksheetRead.ncols
    for row in range(worksheetRead.nrows):
        for col in range(worksheetRead.ncols):
            currentCell = worksheetRead.cell(row, col)
            if(currentCell.value == string):
                return checkingDataExcel(row + addRow, col + addCol)
            elif(i + 1 == area):
                #print(i)
                print("\nInvalid string in Excel Sheet: {0}".format(string))
            else:
                i = i + 1

#Editing date from excel sheet
def editDataFrameExcel():

    workbookWrite = load_workbook(fileLocation)
    worksheetWrite = workbookWrite.get_sheet_by_name(sheetName)

    #fileGeneratedpath = r"C:\Users\Internet\Desktop\Ajay's Project\Scalable Drone(Second Phase)\ScalableDroneProject(Spyder Script)/python.xlsx"

    #save workbook
    #workbookWrite.save(fileGeneratedpath)

#    workbookWrite1 = openpyxl.load_workbook(fileGeneratedpath)
#    worksheetWrite1 = workbookWrite1[sheetName]

#    print(worksheetWrite.cell(6 +1,1 +1).value)
#    print(worksheetRead.cell(6,1).value)
#    worksheetWrite.cell(6 +1,1 +1).value = 1440
#    print(worksheetWrite.cell(6 +1,1 +1).value)
#    print(worksheetRead.cell(6,1).value)

    #Writing user inputs

    userInput.resolution = 720
    userInput.cameraStability = 0
    userInput.endurance = 0.3
    userInput.camMassAsMTOW = 0.1

    worksheetWrite['B7'] = userInput.resolution
    worksheetWrite['B8'] = userInput.cameraStability
    worksheetWrite['B9'] = userInput.endurance
    worksheetWrite['B15'] = userInput.camMassAsMTOW

    workbookWrite.save(fileLocation)

#Getting data from excel sheet
def getDataFrameExcel():

    convertFromMToMM = 1000
    convertToPercentage = 100
    addRow = 0
    #Getting the value back beside the search string
    addCol = 1

    userInput.resolution = execlSearchCell('Camera Resolution', addRow, addCol)
    userInput.cameraStability = execlSearchCell('Camera Stability (0 - min OR 3 - max)', addRow, addCol)
    userInput.endurance = execlSearchCell('Desired Endurance', addRow, addCol)
    userInput.camMassAsMTOW = execlSearchCell('Cam-mass-as-MTOW %', addRow, addCol)*convertToPercentage

    motor.modelName = execlSearchCell('Motor Model', addRow, addCol)
    motor.mass = execlSearchCell('Motor Mass', addRow, addCol)
    motor.maxCurrentDraw = execlSearchCell('Motor Max Current Draw', addRow, addCol)
    motor.recommendedVoltage = execlSearchCell('Motor Recommended Voltage', addRow, addCol)

    camera.modelName = execlSearchCell('Camera Model', addRow, addCol)
    camera.resolution = execlSearchCell('Camera Resolution', addRow, addCol)
    camera.mass = execlSearchCell('Camera Mass', addRow, addCol)
    camera.frameRate = ('NIL ', addRow, addCol)

    flightCC.mass = execlSearchCell('FCC Mass', addRow, addCol)
    flightCC.measurements.length = round(execlSearchCell('FCC Length', addRow, addCol)*convertFromMToMM, 2)
    flightCC.measurements.width = round(execlSearchCell('FCC Width', addRow, addCol)*convertFromMToMM, 2)
    #flightCC.measurements.height = execlSearchCell('FCC Height')*convertToMM

    esc.modelName = execlSearchCell('ESC Model', addRow, addCol)
    esc.massPerArm = execlSearchCell('ESC Mass Per Arm', addRow, addCol)
    esc.currentFactor = execlSearchCell('ESC Current Factor', addRow, addCol)
    esc.maxCurrentRequired = round(execlSearchCell('ESC Current Required (Max)', addRow, addCol), 2)
    esc.typeESC = execlSearchCell('ESC Type', addRow, addCol)
    esc.maxContinousCurrent = execlSearchCell('ESC Max Continous Current', addRow, addCol)
    esc.builtInESC = execlSearchCell('ESC Built-in ESC', addRow, addCol)

    battery.modelName = execlSearchCell('Battery Model', addRow, addCol)
    battery.mass = execlSearchCell('Battery Mass', addRow, addCol)
    battery.capacity = execlSearchCell('Battery Capacity', addRow, addCol)
    battery.cell = execlSearchCell('Battery Cell Count', addRow, addCol)
    battery.measurements.length = round(execlSearchCell('Battery Length', addRow, addCol)*convertFromMToMM, 2)
    battery.measurements.width = round(execlSearchCell('Battery Width', addRow, addCol)*convertFromMToMM, 2)
    battery.measurements.height = round(execlSearchCell('Battery Height', addRow, addCol)*convertFromMToMM, 2)

def droneBody():
    drone.length = round(droneLengthCalculation(), 2)

    drone.width = round(droneWidthCalculation(), 2)

    drone.height = round(droneHeightCalculation(), 2)

    if(drone.length > threeDprinter.maxLength):
        print("Warning: Drone Length exceed 3D printer bed size.\nDrone Length:{0}mm\n3D printer Max Length:{1}mm".format(drone.length, threeDprinter.maxLength))
    else:
        print("Total Drone Length: {0}mm".format(drone.length))

    if(drone.width > threeDprinter.maxWidth):
        print("Warning: Drone Width exceed 3D printer bed size.\nDrone Width:{0}mm\n3D printer Max Width:{1}mm".format(drone.width, threeDprinter.maxWidth))
    else:
        print("Total Drone Width: {0}mm".format(drone.width))

    if(drone.height > threeDprinter.maxHeight):
         print("Warning: Drone Height exceed 3D printer bed size.\nDrone Height:{0}mm\n3D printer Max Height:{1}mm".format(drone.width, threeDprinter.maxWidth))
    else:
        print("Total Drone Height: {0}mm\n".format(drone.height))

def updateParameters():

    app = adsk.core.Application.get()
    ui  = app.userInterface
    design = adsk.fusion.Design.cast(app.activeProduct)

    # Get the root component of the active design.
    rootComp = design.rootComponent
    #get array of occurrences
    perviousOccurrences = rootComp.occurrences.asList

    #Delete all User parameters
#    perviousParameters = design.userParameters
#    print(perviousParameters.count)
#    if(perviousParameters.count-1 > 0):
#        for x in range(perviousParameters.count-1):
#            perviousParameters.item(x+2).deleteMe()

    #Delete all previous Component
#    if(perviousOccurrences.count > 0):
#        for i in range(perviousOccurrences.count):
#            perviousOccurrences.item(i).deleteMe()

    # Access the import manager and root component
    importManager = app.importManager
    rootComp = app.activeProduct.rootComponent

    # Get the file to be imported, here we telling it where the file is located
    filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), "Drone Frame.f3d")

    # Create the input options and import them to the target
    importOptions = importManager.createFusionArchiveImportOptions(filename)
    importManager.importToTarget(importOptions, rootComp)

    # Get the occurance of the imported component
    droneOccurance = rootComp.occurrences.item(rootComp.occurrences.count-1)

    # Accessing the parameters
    parameters = droneOccurance.component.parentDesign.allParameters
    parameters.itemByName('Drone_Length').expression = str(drone.length)
    parameters.itemByName('Drone_Width').expression = str(drone.width)
    parameters.itemByName('Drone_Height').expression = str(drone.design.thickness)

    #First method
#    design = adsk.fusion.Design.cast(app.activeProduct)
#    userParams = design.userParameters
#
#    userParams.itemByName('Drone_Length').expression = str(drone.length)
#    userParams.itemByName('Drone_Width').expression = str(drone.width)
#    userParams.itemByName('Drone_Height').expression = str(drone.height)

def droneGeneratedData():

    app = adsk.core.Application.get()
    ui  = app.userInterface

    product = app.activeProduct
    design = adsk.fusion.Design.cast(product)

    # Get the root component of the active design.
    rootComp = design.rootComponent

    # Get physical properties from component (very high accuracy)
    physicalProperties = rootComp.getPhysicalProperties(adsk.fusion.CalculationAccuracy.VeryHighCalculationAccuracy)

    #converting from g/mm^3 to g/cm^3
    convertDensity = 1000
    #converting from kg to g
    convertMass = 1000

    # Get data from physical properties
    drone.area = round(physicalProperties.area, 2)
    drone.density = round(physicalProperties.density*convertDensity, 2)
    drone.mass = round(physicalProperties.mass*convertMass, 2)
    drone.volume = round(physicalProperties.volume, 2)

    # Get center of mass from physical properties
    drone.centerGravity = physicalProperties.centerOfMass

    print('Drone Generated:\nSurface Area: {0}mm^2\nDensity: {1}g/cm^3\nMass: {2}g\nVoulme: {3}cm^3\n'.format(drone.area, drone.density, drone.mass, drone.volume))

#Main Programmes
def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        #ui.messageBox('Hello script')

        # Create a document.
        doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)

        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)

        # Get the root component of the active design.
        rootComp = design.rootComponent

        editDataFrameExcel()
        updateExcelSheet()
        getDataFrameExcel()
        droneBody()
        #Print default values
#        motor.show()
#        camera.show()
#        flightCC.show()
#        esc.show()
#        battery.show()
#        telemetry.show()
#        gps.show()
#        pdb.show()
#        drone.design.show()
#        prop.show()
#        threeDprinter.show()
#       userInput.show()

        updateParameters()
        droneGeneratedData()

        print('Hello World')

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="static")

@app.get("/")
async def main():
    return FileResponse("static/views/index.html")

@app.get("/config")
async def get(request: Request):
    return templates.TemplateResponse(
        "views/index.html",
        {
            "request": request,
        },
    )


from torch import nn

class StackedAutoencoder(nn.Module):
    def __init__(self, autoencoders):
        super().__init__()

        self.autoencoders = nn.ModuleList(autoencoders)

    def forward(self, x):
        latent = self.encode(x)
        reconstructed = self.decode(latent)
        return latent, reconstructed

    def encode(self, x):
        for i, ae in enumerate(self.autoencoders):
            x = ae.encode(x)

            if i != len(self.autoencoders) - 1:
                x = ae.dropout(x)

        return x

    def decode(self, x):
        for i, ae in enumerate(reversed(self.autoencoders)):
            if i != 0:
                x = ae.activation(x)

            x = ae.decode(x)

        return x

class Autoencoder(nn.Module):
    def __init__(self, in_features, latent_size, dropout=0, activation=nn.Sigmoid(), tie_weights=True):
        """
        Instantiates a Autoencoder.

        :param in_features: The number of features (rows) of the input.
        :param latent_size: The size of the latent representation.
        :param dropout: The dropout probability before decoding.
        :param activation: The activation function.
        :param tie_weights: Whether to use the same weight matrix in the encoder and decoder.
        """
        super().__init__()

        encode = nn.Linear(in_features, latent_size)
        decode = nn.Linear(latent_size, in_features)

        if tie_weights:
            decode.weight.data = encode.weight.data.t()

        self.dropout = nn.Dropout(dropout)
        self.activation = activation

        self.encode = nn.Sequential(
            encode,
            self.activation,
        )
        self.decode = nn.Sequential(
            self.dropout,
            decode,
        )

    def forward(self, x):
        latent = self.encode(x)
        reconstructed = self.decode(latent)
        return latent, reconstructed


from utils import *
import os
import json
import pickle

data_path = '/data/yzzhao/pythonCode/Code_Intelligence/data/CodeXGLUE/Code-Text/dataset'

benchmark = ['go', 'java','javascript','php','python','ruby']

types = ['train', 'valid', 'test']

def trans_code_to_graph_txt():
    for language in benchmark:
        for prefix in types:
            count = 0
            filepath = os.path.join(data_path, language, prefix)
            if not os.path.exists(filepath):
                os.makedirs(filepath)
            filename = filepath + '.jsonl'
            with open(filename, encoding="utf-8") as f:
                for idx, line in enumerate(f):
                    line = line.strip()
                    js = json.loads(line)
                    if 'idx' not in js:
                        js['idx'] = idx
                    code = js['code']
                    name = os.path.join(filepath, str(count)+'.txt')
                    count += 1
                    parser = parsers[language]
                    code_tokens, dfg = extract_dataflow(code, parser, language)
                    transform(dfg, name)

def read_graph_and_convert_to_vector():
    for language in benchmark:
        for prefix in types:
            filepath = os.path.join(data_path, language, prefix)
            with open(os.path.join(filepath, 'embedding.pkl'), "wb") as tf:
                for f in os.listdir(filepath):
                    filename = os.path.join(filepath, f)
                    G = nx.read_edgelist(filename,
                                         create_using=nx.DiGraph(), nodetype=None, data=[('weight', int)])
                    model = DeepWalk(G, walk_length=10, num_walks=10, workers=10)
                    try:
                        model.train(window_size=5, iter=3)
                    except:
                        print(G.nodes())
                        print(G.edges())
                    embeddings = model.get_embeddings()
                    pickle.dump(embeddings, tf)

if __name__ == '__main__':
    # trans_code_to_graph_txt()
    read_graph_and_convert_to_vector()


from enum import Enum
from random import random
from time import sleep
from timeit import default_timer

import mss
import pyautogui
from PyQt5.QtCore import *

from buyer import evaluate_listing
from screenshotter import ScreenShotter
from screenwatcher import ScreenWatcher
from windowtitle import get_foreground_window_title

pyautogui.PAUSE = 0.1
pyautogui.FAILSAFE = False

PURCHASE_OFFSET = 1730, 185
TRADING_BUTTON = 1268, 1065

class State(Enum):
    WAIT_FOR_REFRESH = 0
    WAIT_FOR_LISTINGS = 1
    WAIT_FOR_BUY_BUTTON = 2
    WAIT_FOR_BUY_RESULT = 3

# noinspection PyArgumentList
class MarketBot(QThread):
    listings_signal = pyqtSignal(object)
    successful_buy_signal = pyqtSignal(object)
    # fault_signal = pyqtSignal(object)  # TODO (eg. Item move error)

    def __init__(self, parentQWidget=None):
        super(MarketBot, self).__init__(parentQWidget)

        self.screenwatcher = None

        self.buying = False
        self.price = None
        self.state = State.WAIT_FOR_LISTINGS
        self.next_refresh = 0
        self.listings = None
        self.last_buy_number = None
        self.unavailable_listings = None

    @pyqtSlot(bool)
    def buying_changed(self, buying):
        self.buying = buying

    @pyqtSlot(int)
    def price_changed(self, price):
        self.price = price

    def run(self):
        with ScreenShotter() as sct:
            self.screenwatcher = ScreenWatcher(sct)

            while True:
                if not self.buying or not get_foreground_window_title() == "EscapeFromTarkov":
                    self.state = State.WAIT_FOR_REFRESH
                    sleep(0.5)
                    continue

                if self.state is State.WAIT_FOR_REFRESH:
                    if self.next_refresh < default_timer():
                        self.refresh()
                        sleep(0.08)
                        self.next_refresh = default_timer() + self.refresh_interval()
                        self.unavailable_listings = set()
                        self.state = State.WAIT_FOR_LISTINGS

                elif self.next_refresh + 10 < default_timer():
                    print("Stuck failsafe triggered")
                    error = self.screenwatcher.find_error_ok_button()
                    if error:
                        pyautogui.click(error)
                    pyautogui.click(TRADING_BUTTON)
                    sleep(1)
                    self.state = State.WAIT_FOR_REFRESH

                elif self.state is State.WAIT_FOR_LISTINGS:
                    self.listings = self.screenwatcher.find_listings()
                    if self.listings:
                        print(self.listings)
                        self.listings_signal.emit(self.listings)
                        self.state = State.WAIT_FOR_BUY_BUTTON

                elif self.state is State.WAIT_FOR_BUY_BUTTON:
                    wait_more = False
                    buyable_items = self.screenwatcher.find_purchase_buttons() - self.unavailable_listings
                    for i in range(0, len(self.listings)):
                        if i not in self.unavailable_listings and evaluate_listing(self.listings[i], self.price):
                            wait_more = True
                            if i in buyable_items:
                                self.buy(i)
                                self.state = State.WAIT_FOR_BUY_RESULT
                                break
                    if not wait_more:
                        self.state = State.WAIT_FOR_REFRESH

                elif self.state is State.WAIT_FOR_BUY_RESULT:
                    if self.last_buy_number in self.screenwatcher.find_purchase_or_outofstock():
                        sleep(0.1)
                        error = self.screenwatcher.find_error_ok_button()
                        if error:
                            print("\tFAIL")
                            self.unavailable_listings.add(self.last_buy_number)
                            pyautogui.click(error)
                            self.state = State.WAIT_FOR_BUY_BUTTON
                        else:
                            print("\tSUCCESS")
                            self.successful_buy_signal.emit(self.listings[self.last_buy_number])
                            self.state = State.WAIT_FOR_LISTINGS

    def refresh(self):
        # Todo: right click filter by item
        self.listings = None
        pyautogui.press('f5')

    def refresh_interval(self):
        # Todo intelligent backoff based on price
        return 3.1 + random()

    def buy(self, listing_no):
        self.last_buy_number = listing_no
        listing = self.listings[listing_no]
        print("Buying {}".format(listing))
        pyautogui.click(x=PURCHASE_OFFSET[0], y=PURCHASE_OFFSET[1] + listing.coord)
        pyautogui.press('y')
        pyautogui.moveTo(x=PURCHASE_OFFSET[0], y=120)


from typing import Collection

import tensorflow as tf
from typeguard import typechecked

class TensorFlowNetwork:
    @typechecked
    def __init__(self, sess: tf.Session, state_dim: int, action_dim: int):
        self._sess = sess
        with self._sess.graph.as_default(), tf.variable_scope(
                name_or_scope=None, default_name=self.__class__.__name__):
            existing_vars = tf.trainable_variables()
            self._construct_nn(state_dim, action_dim)
            self._variables: Collection[tf.Variable] = [
                var for var in tf.trainable_variables() if var not in existing_vars]

    @typechecked
    def _construct_nn(self, state_dim: int, action_dim: int) -> None:
        raise NotImplementedError

    @staticmethod
    def _include_batchnorm():
        return tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS))

class TargetNetwork(TensorFlowNetwork):
    def __init__(self, online_nn_vars: Collection[tf.Variable], tau: float, **kwargs):
        super(TargetNetwork, self).__init__(**kwargs)
        with self._sess.graph.as_default():
            self._target_nn_update_ops = self._setup_target_nn_update_ops(
                online_vars=online_nn_vars, tau=tau)

    def _setup_target_nn_update_ops(self, tau, online_vars: Collection[tf.Variable]):
        update_ops = []
        for online_var, target_var in zip(online_vars, self._variables):
            new_target_var = (1-tau)*target_var + tau*online_var
            update_ops.append(target_var.assign(new_target_var))
        return update_ops

    def update(self):
        self._sess.run(self._target_nn_update_ops)

class OnlineNetwork:
    def create_target_network(self, tau: float) -> TargetNetwork:
        raise NotImplementedError


"""
metody typu d under - DOUBLE underscore
__str__ - STRing
"""

import random

class Rocket:

    def __init__(self, name, speed=1):
        self.altitude = 0

        self.speed = speed

    def moveUp(self):
        self.altitude += self.speed

    def __str__(self):
        return "Rakieta jest na wysokosci" + str(self.altitude)

rockets = [Rocket(random.randint(1, 6))
           for _ in range(5)]

for _ in range(10):
    RocketIndexToMove = random.randint(0, 4)
    rockets[RocketIndexToMove].moveUp()

for rocket in rockets:
    print(rocket)


import logging

from django.db import transaction
from django.conf.urls import url
from django.urls import reverse
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.shortcuts import redirect, render
from django_tables2 import RequestConfig

from hub.models import CourseCode, Course, UserCourseCodeBinding, UserCourseBinding
from hub.models import Assignment, UserAssignmentBinding
from hub.models import Image

from kooplex.lib import now, translate_date

from hub.forms import FormAssignment
from hub.forms import T_BIND_ASSIGNMENT, T_COLLECT_ASSIGNMENT, T_FEEDBACK_ASSIGNMENT, T_SUBMIT_ASSIGNMENT

logger = logging.getLogger(__name__)

@login_required
def teaching(request):
    """Renders the projectlist page for courses taught."""
    logger.debug('Rendering teaching.html')
    context_dict = {
        'menu_teaching': 'active',
        'next_page': 'education:teaching',
    }
    return render(request, 'edu/teaching.html', context = context_dict)

@login_required
def courses(request):
    """Renders the projectlist page for students."""
    logger.debug('Rendering courses.html')
    context_dict = {
        'menu_teaching': 'active',
        'next_page': 'education:courses',
    }
    return render(request, 'edu/courses.html', context = context_dict)

@login_required
def conf_meta(request, course_id, next_page):
    user = request.user
    logger.debug("method: %s, course id: %s, user: %s" % (request.method, course_id, user))
    try:
        course = Course.get_usercourse(course_id = course_id, user = request.user)
    except Course.DoesNotExist as e:
        logger.error('abuse by %s course id: %s -- %s' % (user, course_id, e))
        messages.error(request, 'Course does not exist')
        return redirect(next_page)

    if request.method == 'POST' and request.POST.get('button') == 'apply':
        course.description = request.POST.get('description')
        imagename = request.POST['course_image']
        course.image = Image.objects.get(name = imagename) if imagename != 'None' else None
        course.save()
        return redirect(next_page)
    else:
        context_dict = {
            'images': Image.objects.all(),
            'course': course,
            'submenu': 'meta',
            'next_page': next_page,
        }
        return render(request, 'edu/configure.html', context = context_dict)

@login_required
def newassignment(request, course_id):
    """Renders assignment management form."""
    user = request.user
    logger.debug("user %s, method: %s" % (user, request.method))
    try:
        course = Course.objects.get(id = course_id)
        binding = UserCourseBinding.objects.get(user = user, course = course, is_teacher = True)
    except Course.DoesNotExist:
        logger.error("Missing course id %s and user %s" % (course_id, user))
        return redirect('education:teaching')
    except UserCourseBinding.DoesNotExist:
        logger.error("Missing course id %s and user %s" % (course_id, user))
        messages.error(request, 'You are not allowed to create an assignment for %s' % (course))
        return redirect('education:teaching')
    if request.method == 'GET':
        context_dict = {
            'course': course,
            'f_assignment': FormAssignment(user = user, course = course),
            'menu_teaching': 'active',
            'submenu': 'new',
            'next_page': 'education:teaching',
        }
        return render(request, 'edu/assignment-teacher.html', context = context_dict)
    elif request.method == 'POST':
        coursecode_ids = request.POST.getlist("coursecodes")
        name = request.POST.get("name").strip()
        description = request.POST.get("description").strip()
        folder = request.POST.get("folder")
        timenow = now()
        valid_from = translate_date(request.POST.get('valid_from')) or timenow
        expires_at = translate_date(request.POST.get('expires_at'))
        is_massassignment = bool(request.POST.get("is_massassignment"))
        can_studentsubmit = bool(request.POST.get("can_studentsubmit"))
        remove_collected = bool(request.POST.get("remove_collected"))
        try:
            assert valid_from >= timenow, "You try to shedule assignment behind time."
            assert len(name), "You need to provide a name"
            assert len(coursecode_ids), "You need to select at least one course code"
            extra = {}
            if expires_at:
                assert (expires_at - valid_from).total_seconds() >= 60, "Expiry is too close to handout. "
            for coursecodeid in coursecode_ids:
                coursecode = CourseCode.objects.get(id = coursecodeid)
                assert coursecode.course == course, "Course code mismatch"
                #UserCourseCodeBinding.objects.get(coursecode = coursecode, user = user, is_teacher = True)
                logger.debug("coursecode id %s" % coursecodeid)
                with transaction.atomic():
                    assignments = Assignment.objects.filter(
                        coursecode = coursecode,
                        name = name,
                        creator = user,
                        description = description,
                        folder = folder,
                        can_studentsubmit = can_studentsubmit,
                        remove_collected = remove_collected,
                        is_massassignment = is_massassignment,
                        expires_at = expires_at
                        )
                    if len(assignments):
                        logger.warning('Prevented from duplicating assignments for course code %s' % (coursecode))
                        messages.warning(request, 'Maybe you double clicked on assignments.')
                        continue
                    Assignment.objects.create(
                        coursecode = coursecode,
                        name = name,
                        creator = user,
                        description = description,
                        folder = folder,
                        can_studentsubmit = can_studentsubmit,
                        remove_collected = remove_collected,
                        is_massassignment = is_massassignment,
                        valid_from = valid_from,
                        expires_at = expires_at
                    )
                    logger.info('New assignments for course code %s' % (coursecode))
                    messages.info(request, 'New assignments for course code %s' % (coursecode))
        except Exception as e:
            logger.error(e)
            messages.error(request, 'Cannot fully register assignment -- %s' % e)
            return redirect('education:newassignment', course.id)
    return redirect('education:teaching')

@login_required
def bindassignment(request, course_id):
    from django.contrib.auth.models import User
    """Bind assignment and user"""
    user = request.user
    logger.debug("user %s, method: %s" % (user, request.method))
    try:
        course = Course.objects.get(id = course_id)
        assert len(list(UserCourseBinding.objects.filter(user = user, course = course, is_teacher = True))) > 0, "%s is not a teacher of course %s" % (user, course)
    except Exception as e:
        logger.error("Invalid request with course id %s and user %s -- %s" % (course_id, user, e))
        return redirect('indexpage')
    if request.method == 'GET':
        s_name = request.GET.get('name', '')
        s_username = request.GET.get('username', '')
        s_assignment = request.GET.get('assignment', '')
        table_bind = T_BIND_ASSIGNMENT(course.bindableassignments())
        RequestConfig(request).configure(table_bind)
        context_dict = {
            'course': course,
            't_bind': table_bind,
            'search_name': s_name,
            'search_username': s_username,
            'search_assignment': s_assignment,
            'menu_teaching': 'active',
            'submenu': 'bind',
            'next_page': 'education:teaching',
        }
        return render(request, 'edu/assignment-teacher.html', context = context_dict)
    elif request.method == 'POST':
        thetime = now()
        oopses = 0
        done = 0
        for br in request.POST.getlist('binding_representation'):
            user_id, assignment_id = br.split('_')
            try:
                assignment = Assignment.objects.get(id = assignment_id)
                student = User.objects.get(id = user_id)
                assert student in assignment.list_students_bindable(), "Cannot bind %s to %s" % (student, assignment)
                assert user.profile.is_coursecodeteacher(assignment.coursecode), "You are not a teacher of %s" % assignment.coursecode
            except Exception as e:
                raise
                logger.error("oops -- %s" % e)
                oopses += 1
                continue
            try:
                binding = UserAssignmentBinding.objects.get(user = student, assignment = assignment)
                logger.error("Will not create a duplicate %s" % binding)
                messages.error(request, "Prevented from creating a duplicate assignment %s for student %s" % (assignment.name, student))
            except UserAssignmentBinding.DoesNotExist:
                pass
            valid_from = translate_date(request.POST.get('valid_from_%s' % br))
            expires_at = translate_date(request.POST.get('expires_at_%s' % br))
            if valid_from and valid_from > thetime:
                UserAssignmentBinding.objects.create(user = student, assignment = assignment, valid_from = valid_from, expires_at = expires_at, state = UserAssignmentBinding.ST_QUEUED)
            else:
                UserAssignmentBinding.objects.create(user = student, assignment = assignment, valid_from = valid_from, expires_at = expires_at)
    #FIXME> expiry check in model init!
            messages.info(request, "Creating an assignment %s for student %s" % (assignment.name, student))
        url_next = reverse('education:bindassignment', kwargs = {'course_id': course_id})
        pager = request.POST.get('pager')
        logger.debug("next: %s %s" % (url_next, pager))
        return redirect(url_next + "?%s" % pager) if pager else redirect('education:bindassignment', course_id)
    else:
        return redirect('education:teaching')

@login_required
def collectassignment(request, course_id):
    """Handle assignment collection"""
    user = request.user
    logger.debug("user %s, method: %s" % (user, request.method))
    per_page=20
    try:
        course = Course.objects.get(id = course_id)
        assert len(list(UserCourseBinding.objects.filter(user = user, course = course, is_teacher = True))) > 0, "%s is not a teacher of course %s" % (user, course)
    except Exception as e:
        logger.error("Invalid request with course id %s and user %s -- %s" % (course_id, user, e))
        return redirect('indexpage')
    if request.method == 'POST' and request.POST['button'] == 'search':
        s_name = request.POST.get('name')
        per_page = request.POST.get('per_page')
        s_username = request.POST.get('username')
        s_assignment = request.POST.get('assignment')
        render_page = True
    elif request.method == 'GET':
        s_name = None
        s_username = None
        s_assignment = None
        render_page = True
    else:
        render_page = False
    if render_page:
        table_collect = T_COLLECT_ASSIGNMENT(course.userassignmentbindings(s_assignment = s_assignment, s_name = s_name, s_username = s_username, s_assignmentstate = UserAssignmentBinding.ST_WORKINPROGRESS))
        RequestConfig(request,  paginate={'per_page': per_page}).configure(table_collect)
        context_dict = {
            'course': course,
            't_collect': table_collect,
            'search_name': s_name if s_name else '',
            'search_username': s_username if s_username else '',
            'search_assignment': s_assignment if s_assignment else '',
            'per_page': per_page,
            'menu_teaching': 'active',
            'submenu': 'collect',
            'next_page': 'education:feedback',
        }
        return render(request, 'edu/assignment-teacher.html', context = context_dict)
    elif request.method == 'POST':
        userassignmentbinding_ids = request.POST.getlist('userassignmentbinding_ids')
        for binding_id in userassignmentbinding_ids:
            try:
                binding = UserAssignmentBinding.objects.get(id = binding_id)
                coursecode = binding.assignment.coursecode
                assert coursecode.course == course, "course code mismatch"
                #UserCourseCodeBinding.objects.get(user = user, coursecode = coursecode, is_teacher = True)
                UserCourseBinding.objects.get(user = user, course = binding.assignment.coursecode.course, is_teacher = True)
                binding.do_collect()
                messages.info(request, 'Assignment %s of %s for course code %s is collected' % (binding.assignment.name, binding.user, coursecode))
            except Exception as e:
                logger.error(e)
                messages.error(request, 'Cannot mark assignment collected -- %s' % e)
        url_next = reverse('education:collectassignment', kwargs = {'course_id': course_id})
        pager = request.POST.get('pager')
        return redirect(url_next + "?%s" % pager) if pager else redirect('education:collectassignment', course_id)
    else:
        return redirect('indexpage')

@login_required
def feedbackassignment(request, course_id):
    """Mark assignments to correct"""
    from hub.models.assignment import ST_LOOKUP
    user = request.user
    logger.debug("user %s, method: %s" % (user, request.method))
    per_page=20
    try:
        course = Course.objects.get(id = course_id)
        assert len(list(UserCourseBinding.objects.filter(user = user, course = course, is_teacher = True))) > 0, "%s is not a teacher of course %s" % (user, course)
    except Exception as e:
        logger.error("Invalid request with course id %s and user %s -- %s" % (course_id, user, e))
        return redirect('indexpage')
    if request.method == 'POST' and request.POST['button'] == 'search':
        per_page = request.POST.get('per_page')
        s_name = request.POST.get('name')
        s_username = request.POST.get('username')
        s_assignment = request.POST.get('assignment')
        s_assignmentstate = request.POST.get('assignmentstate') if request.POST.get('assignmentstate') else None
        render_page = True
    elif request.method == 'GET':
        s_name = None
        s_username = None
        s_assignment = None
        s_assignmentstate = None
        render_page = True
    else:
        render_page = False
    if render_page:
        table_feedback = T_FEEDBACK_ASSIGNMENT(course.userassignmentbindings(s_assignment = s_assignment, s_name = s_name, s_username = s_username, s_assignmentstate = s_assignmentstate))
        RequestConfig(request,  paginate={'per_page': per_page}).configure(table_feedback)
        context_dict = {
            'course': course,
            't_feedback': table_feedback,
            'search_name': s_name if s_name else '',
            'search_username': s_username if s_username else '',
            'search_assignment': s_assignment if s_assignment else '',
            'search_assignmentstate': s_assignmentstate if s_assignmentstate else '',
            'states': ST_LOOKUP,
            'menu_teaching': 'active',
            'submenu': 'feedback',
            'per_page': per_page,
            'next_page': 'education:feedback',
        }
        return render(request, 'edu/assignment-teacher.html', context = context_dict)
    elif request.method == 'POST':
        for k, v in request.POST.items():
            try:
                task, binding_id = k.split('_')
                assert task == 'task'
                assert v in [ 'correct', 'ready', 'reassign' ]
                task = v
            except:
                continue
            try:
                binding = UserAssignmentBinding.objects.get(id = binding_id)
                #UserCourseCodeBinding.objects.get(user = user, coursecode = binding.assignment.coursecode, is_teacher = True)
                UserCourseBinding.objects.get(user = user, course = binding.assignment.coursecode.course, is_teacher = True)
                score = request.POST.get('score_%s' % binding_id)
                feedback_text = request.POST.get('feedback_text_%s' % binding_id)
                if task == 'correct':
                    binding.state = UserAssignmentBinding.ST_CORRECTING
                    binding.corrector = user
                elif task == 'ready':
                    binding.state = UserAssignmentBinding.ST_FEEDBACK
                    binding.corrected_at = now()
                    binding.score = float(score)
                    if feedback_text:
                        binding.feedback_text = feedback_text.strip()
                elif task == 'reassign':
                    binding.state = UserAssignmentBinding.ST_WORKINPROGRESS
                    binding.corrected_at = now()
                binding.save()
                messages.info(request, '%s\'s assignment %s for course code %s is now %s' % (binding.user.username, binding.assignment.name, binding.assignment.coursecode.courseid, binding.assignment.state))
            except Exception as e:
                logger.error(e)
                messages.error(request, 'Cannot mark assignment corrected -- %s' % e)
        url_next = reverse('education:feedback', kwargs = {'course_id': course_id})
        pager = request.POST.get('pager')
        return redirect(url_next + "?%s" % pager) if pager else redirect('education:feedback', course_id)
    else:
        return redirect('education:teaching')

@login_required
def summaryassignment(request, course_id):
    """Summary of the grades for each assignment"""
    from hub.models.assignment import ST_LOOKUP
    from pandas import DataFrame
    from django_pandas.io import read_frame
    from hub.models import UserAssignmentBinding

    user = request.user
    logger.debug("user %s, method: %s" % (user, request.method))
    per_page=20
    course = Course.objects.get(id = course_id)
    qs = UserAssignmentBinding.objects.filter(assignment__coursecode__course__id=course_id)
    if len(list(qs)) == 0:
        newdf = DataFrame()
        messages.warning(request, 'Course %s has no assignments yet' % (course.name))
    else:
        try:
            df = read_frame(qs)
            df['Assignments'] = df.assignment.apply(lambda x: x.split("[")[0].strip())
            df.score.fillna(0, inplace=True)
            assert len(list(UserCourseBinding.objects.filter(user = user, course = course, is_teacher = True))) > 0, "%s is not a teacher of course %s" % (user, course)
            newdf = df.pivot_table(index='user', columns='Assignments', values='score')#, aggfunc='count')
            #qs.to_dataframe(['age', 'wage'], index='full_name'])
            #qs.filter(age__gt=20, department='IT').to_dataframe(index='full_name')
            newdf['Sum'] = df.groupby(['user']).sum().score
        except Exception as e:
            logger.error("Invalid request with course id %s and user %s -- %s" % (course_id, user, e))
            try:
                 assert len(list(UserCourseBinding.objects.filter(user = user, course = course, is_teacher = False))) > 0, "%s is not even a student of course %s" % (user, course)
                 df = df[df.user == user.username]
                 newdf = df.pivot_table(index='user', columns='Assignments', values='score')#, aggfunc='count')
                 newdf['Sum'] = df.groupby(['user']).sum().score
            except Exception as e:
                 logger.error("Invalid request with course id %s and user %s -- %s" % (course_id, user, e))
                 return redirect('indexpage')
    if request.method == 'GET':
        render_page = True
    else:
        render_page = False
    if render_page:
        context_dict = {
            'course': course,
            'pd': newdf.sort_values(by=['Sum'], ascending=True).to_html(table_id='datatable', col_space=300),
            'menu_teaching': 'active',
            'submenu': 'summary',
            'per_page': per_page,
            'next_page': 'education:summary',
        }
        return render(request, 'edu/assignment-teacher.html', context = context_dict)
    else:
        return redirect('education:teaching')

@login_required
def submitassignment(request, course_id):
    """Handle assignment submission"""
    user = request.user
    logger.debug("user %s, method: %s" % (user, request.method))
    try:
        course = Course.objects.get(id = course_id)
        assert len(list(UserCourseBinding.objects.filter(user = user, course = course, is_teacher = False))) == 1, "%s is not a student of course %s" % (user, course)
    except Exception as e:
        logger.error("Invalid request with course id %s and user %s -- %s" % (course_id, user, e))
        return redirect('indexpage')
    if request.method == 'GET':
        table_submit = T_SUBMIT_ASSIGNMENT(course.userassignmentbindings(user = user))
        RequestConfig(request).configure(table_submit)
        context_dict = {
            'course': course,
            't_submit': table_submit,
            'menu_teaching': 'active',
            'submenu': 'submit',
            'next_page': 'education:course',
        }
        return render(request, 'edu/assignment-student.html', context = context_dict)
    elif request.method == 'POST':
        userassignmentbinding_ids = request.POST.getlist('userassignmentbinding_ids')
        for binding_id in userassignmentbinding_ids:
            try:
                binding = UserAssignmentBinding.objects.get(id = binding_id, user = user)
                binding.state = UserAssignmentBinding.ST_SUBMITTED
                binding.submitted_at = now()
                binding.save()
                assignment = binding.assignment
                coursecode = assignment.coursecode
                messages.info(request, '%s assignment is submitted for course %s (%s)' % (assignment.name, coursecode.course.name, coursecode.courseid))
            except Exception as e:
                logger.error(e)
                messages.error(request, 'Cannot fully submit assignment -- %s' % e)
    return redirect('education:courses')

urlpatterns = [
    url(r'^teaching/?$', teaching, name = 'teaching'),
    url(r'^courses/?$', courses, name = 'courses'),
    url(r'^configurecourse/(?P<course_id>\d+)/meta/(?P<next_page>\w+:?\w*)$', conf_meta, name = 'conf_meta'),
    url(r'^newassignemnt/(?P<course_id>\d+)$', newassignment, name = 'newassignment'),
    url(r'^bindassignment/(?P<course_id>\d+)$', bindassignment, name = 'bindassignment'),
    url(r'^collectassignment/(?P<course_id>\d+)$', collectassignment, name = 'collectassignment'),
    url(r'^feedback/(?P<course_id>\d+)$', feedbackassignment, name = 'feedback'),
    url(r'^summary/(?P<course_id>\d+)$', summaryassignment, name = 'summary'),
    url(r'^submitassignment/(?P<course_id>\d+)$', submitassignment, name = 'submitassignment'),
]


import re
import math
import pandas as pd
from datetime import datetime, timedelta
from parameter import Parameter
from trentoTrain import TrentoTrain

class TrentoData(object):
    '''
    Reads and stores train information from NS' TRENTO train database
    '''

    def __init__(self, param):
        #retrieve start and end date
        self.dateStart = param.dateStart
        self.dateEnd = param.dateEnd
        self.midnightCaseStudy = param.midnightCaseStudy
        self.dayCaseStudyString = param.dayCaseStudyString

        #get set of relevant trains
        self.relevantTrainSet = self.getRelevantTrainSet()

        #read trento data for a set of trains contained by trainSet
        self.trainDict = self.readTrento()

    def __repr__(self):

        trentoDataStr = "\nRelevant TRENTO trains:\n"

        for trainNumber, train in self.trainDict.items():
            trentoDataStr += "%s: %s\n" % (trainNumber,train)

        trentoDataStr += "(total: %d trains)\n" % len(self.trainDict)

        return trentoDataStr

    def getRelevantTrainSet(self):
        #define relevant columns of Trento data set
        relevantColumnsTrento = ['Vkdatum', 'Treinnr', 'Drp', 'Spoor',
            'Aankomsttijd', 'Vertrektijd', 'Vgb_plan_aankomst', 'Vgb_plan_vertrek']
        titleColumnsTrento = ['dateDispatch', 'trainNumber', 'stationAbbreviation', 'trackNumber',
            'arrTimeReal', 'depTimeReal', 'arrTimeSched', 'depTimeSched']

        #set of relevant train numbers
        trainNumberSet = set()

        for trentoFilePath in Parameter.trentoFiles:
            #load relevant columns
            trentoFull = pd.read_csv(trentoFilePath, usecols=relevantColumnsTrento)

            #rename headers
            trentoFull.columns = titleColumnsTrento

            #retain data for case study date
            trentoData = trentoFull.loc[ ( trentoFull['dateDispatch'] == self.dayCaseStudyString ) &
                           ( trentoFull['stationAbbreviation'].isin( Parameter.stationAbbreviationDict.keys() ) ) ]

            for _, trentoEntry in trentoData.iterrows():

                stationID = Parameter.stationAbbreviationDict[ trentoEntry["stationAbbreviation"] ]
                stationName = Parameter.stationNameDict[stationID]

                #get track number in integer format
                trackNumberRaw = trentoEntry["trackNumber"]
                if isinstance(trackNumberRaw,int):
                    trackNumber = trackNumberRaw
                else:
                    #get first integer from track number
                    trackNumber = int( re.findall(r'\d+', trackNumberRaw)[0] )

                #skip to next entry unless train served by considered platform
                if not (trackNumber in Parameter.tracksConsidered[stationName]):
                    continue

                #arrival and departure date: use realized if available, otherwise scheduled time
                if isinstance(trentoEntry['arrTimeReal'], str):
                    arrDate = datetime.strptime( trentoEntry['arrTimeReal'] , '%Y-%m-%d %H:%M:%S' )
                elif isinstance(trentoEntry['arrTimeSched'], str):
                    arrDate = datetime.strptime( trentoEntry['arrTimeSched'] , '%Y-%m-%d %H:%M:%S' )
                else:
                    arrDate = None

                #skip to next entry if current train movement is too late
                if (arrDate is not None) and (self.dateEnd < arrDate):
                    continue

                if isinstance( trentoEntry['depTimeReal'] , str):
                    depDate = datetime.strptime( trentoEntry['depTimeReal'] , '%Y-%m-%d %H:%M:%S' )
                elif isinstance( trentoEntry['depTimeSched'] , str):
                    depDate = datetime.strptime( trentoEntry['depTimeSched'] , '%Y-%m-%d %H:%M:%S' )
                else:
                    depDate = None

                #skip to next entry if current train movement is too early
                if (depDate is not None) and (depDate < self.dateStart):
                    #if train departs before simulation starts, skip train
                    continue

                #if no arrival, and departure time outside time window: skip train
                if arrDate is None and not (self.dateStart <= depDate <= self.dateEnd):
                    continue

                #if no departure, and arrival time outside time window: skip train
                if depDate is None and not (self.dateStart <= arrDate <= self.dateEnd):
                    continue

                #train movement is within considered time interval and served by relevant platform
                trainNumber = trentoEntry["trainNumber"]

                trainNumberSet.add(trainNumber)

        return trainNumberSet

    #provide Trento trains in format readable for pedQN
    def getTrainDict(self):
        return self.trainDict

    def readTrento(self):
        relevantColumnsTrento = ['Vkdatum', 'Treinnr', 'Drp', 'Spoor',
            'Mat_a_soort', 'Mat_a_bakken', 'Mat_a_lengte', 'Mat_v_soort', 'Mat_v_bakken', 'Mat_v_lengte',
            'Aankomsttijd', 'Vertrektijd', 'Vgb_plan_aankomst', 'Vgb_plan_vertrek']

        titleColumnsTrento = ['dateDispatch', 'trainNumber', 'stationAbbreviation', 'trackNumber',
            'rollingStockTypeArr', 'numCarsArr', 'trainLengthArr', 'rollingStockTypeDep', 'numCarsDep', 'trainLengthDep',
            'arrTimeReal', 'depTimeReal', 'arrTimeSched', 'depTimeSched']

        #list of dataframes generated from reading trento raw files
        trentoDataFrames = list()

        for trentoFilePath in Parameter.trentoFiles:
            #read current trento file and rename headers
            trentoFull = pd.read_csv(trentoFilePath, usecols=relevantColumnsTrento)
            trentoFull.columns = titleColumnsTrento

            #select entries corresponding to case study date and train list
            trentoDataInstance = trentoFull.loc[ ( trentoFull['dateDispatch'] == self.dayCaseStudyString ) &
                               ( trentoFull['trainNumber'].isin( self.relevantTrainSet ) ) ]

            trentoDataFrames.append(trentoDataInstance)

        #concatenate various trento files into single document
        trentoData = pd.concat(trentoDataFrames, ignore_index=True)

        #dict of trento trains
        trentoTrainDict = dict()

        for trainNumber in self.relevantTrainSet:
            #retrieve TRENTO data for current train
            curTrainData = trentoData.loc[ trentoData['trainNumber'] == trainNumber ].sort_values(['depTimeSched'])

            #check if train exists in TRENTO database
            assert(not curTrainData.empty)

            #infer scheduled and realized train arrival/departure times
            arrTimeReal = list()
            depTimeReal = list()
            arrTimeSched = list()
            depTimeSched = list()
            platformSequence = list()
            stationNameSequence = list()

            #train-specific information
            rollingStockSet = set()
            numCarsSet = set()
            trainLengthSet = set()

            #valid train flag: true if stops at one or more modeled platforms
            validTrain = False

            for _, entry  in curTrainData.iterrows():

                stationAbbreviation = entry['stationAbbreviation']
                stationID = Parameter.stationAbbreviationDict[stationAbbreviation]
                stationName = Parameter.stationNameDict[stationID]

                #get track number in integer format
                trackNumberRaw = entry["trackNumber"]
                if isinstance(trackNumberRaw,int):
                    trackNumber = trackNumberRaw
                else:
                    #get first integer from track number
                    trackNumber = int( re.findall(r'\d+', trackNumberRaw)[0] )

                platform = '%s%s%s' % (stationName[0], 'P', trackNumber )

                #if current stop of train outside the modeled parameter, skip stop
                if trackNumber not in Parameter.tracksConsidered[stationName]:
                    #if Parameter.showWarnings:
                    #    print("Warning: Train %s served by unmodeled platform (%s instead of %s)" %\
                    #        (trainNumber, platform, Parameter.tracksConsidered[stationName]))
                    #skip current stop
                    continue

                #train neither arrives or departs
                if not (isinstance(entry['arrTimeReal'],str) or isinstance(entry['depTimeReal'],str)):
                    if Parameter.showWarnings:
                        print("Train %s neither departs nor arrives in %s. " % (trainNumber,stationName), end='')
                        print("Track: %s, depReal: %s; arrReal: %s; depSched: %s; arrSched: %s" % (trackNumber, entry['depTimeReal'], entry['arrTimeReal'], entry['depTimeSched'], entry['arrTimeSched']) )

                    #skip current stop
                    continue

                validTrain = True

                trainOnlyDeparts = False

                if isinstance(entry['arrTimeReal'],str):
                    arrReal = datetime.strptime( entry['arrTimeReal'] , '%Y-%m-%d %H:%M:%S' )
                    arrSched = datetime.strptime( entry['arrTimeSched'] , '%Y-%m-%d %H:%M:%S' )

                #train only departs
                else:
                    if Parameter.showWarnings:
                        print("Warning: Train %s only departs" % trainNumber)

                    trainOnlyDeparts = True
                    assert(isinstance(entry['arrTimeReal'],float))
                    assert( math.isnan(entry['arrTimeReal']) )

                    #set arbitrary arrival time: 10 min before departure
                    arrReal = datetime.strptime( entry['depTimeReal'] , '%Y-%m-%d %H:%M:%S' ) - timedelta(minutes=10)
                    arrSched = datetime.strptime( entry['depTimeSched'] , '%Y-%m-%d %H:%M:%S' ) - timedelta(minutes=10)

                if isinstance(entry['depTimeReal'],str):
                    depReal = datetime.strptime( entry['depTimeReal'] , '%Y-%m-%d %H:%M:%S' )
                    depSched = datetime.strptime( entry['depTimeSched'] , '%Y-%m-%d %H:%M:%S' )

                #train only arrives
                else:
                    if Parameter.showWarnings:
                        print("Warning: Train %s only arrives" % trainNumber)

                    assert(isinstance(entry['depTimeReal'],float))
                    assert( math.isnan(entry['depTimeReal']) )

                    #set arbitrary departure time: 10 min after arrival
                    depReal = datetime.strptime( entry['arrTimeReal'] , '%Y-%m-%d %H:%M:%S' ) + timedelta(minutes=10)
                    depSched = datetime.strptime( entry['arrTimeReal'] , '%Y-%m-%d %H:%M:%S' ) + timedelta(minutes=10)

                platformSequence.append(platform)
                stationNameSequence.append(stationName)

                arrTimeReal.append( (arrReal - self.midnightCaseStudy).total_seconds() )
                depTimeReal.append( (depReal - self.midnightCaseStudy).total_seconds() )
                arrTimeSched.append( (arrSched - self.midnightCaseStudy).total_seconds() )
                depTimeSched.append( (depSched - self.midnightCaseStudy).total_seconds() )

                if trainOnlyDeparts:
                    rollingStockSet.add( entry['rollingStockTypeDep'] )
                    numCarsSet.add( entry['numCarsDep'] )
                    trainLengthSet.add( entry['trainLengthDep'] )
                else:
                    rollingStockSet.add( entry['rollingStockTypeArr'] )
                    numCarsSet.add( entry['numCarsArr'] )
                    trainLengthSet.add( entry['trainLengthArr'] )

            #if current train is invalid, skip
            if not validTrain:
                if Parameter.showWarnings:
                    print("Skipping train %s. No valid stops found." % trainNumber)

                continue

            #check if rolling stock is consistent across stations
            assert( len(rollingStockSet) == 1 ), "train %s: rolling stock changes during operation: %s" % (trainNumber, rollingStockSet)
            assert( len(numCarsSet) == 1), "train %s: number of cars changes during operation: %s" % (trainNumber, numCarsSet)
            assert( len(trainLengthSet) == 1), "train %s: train length changes during operation: %s" % (trainNumber, trainLengthSet)

            rollingStockTypeSeq = rollingStockSet.pop()
            numCars = int(numCarsSet.pop())
            #trainLength = float( trainLengthSet.pop().replace(',','.') )
            trainLength = trainLengthSet.pop()

            #determine rolling stock type and infer capacity
            rollingStockTypeSet = set(rollingStockTypeSeq.split())
            rollingStockBaseType = next(iter(rollingStockTypeSet))

            #check if train is homogeneous (only one rolling stock type)
            assert( 1==len(rollingStockTypeSet) ), "train %s: rolling stock type varies during operation: %s" % \
                (trainNumber, rollingStockTypeSeq)
            assert( rollingStockBaseType in Parameter.passengerCarCapacity.keys() ), \
                "train %s: rolling stock type '%s' not in rolling stock catalog %s" %\
                (trainNumber, rollingStockBaseType, set(Parameter.passengerCarCapacity.keys()))

            trainKey= (rollingStockBaseType, numCars)
            if trainKey in Parameter.trainLengthDict:
                trainLengthManual = Parameter.trainLengthDict[rollingStockBaseType, numCars]
                #print("trainLengthNew: %s" % trainLengthNew)
            else:
                print("trainKey (%s,%s) missing" % trainKey)

            if not (0.9*trainLengthManual < trainLength < 1.1*trainLengthManual):
                if Parameter.showWarnings:
                    print("Warning: Train length reported by Trento (%s m) differs substantially from rolling stock catalog (%s m). Using the latter." %\
                          (trainLength, trainLengthManual) )

                trainLength = trainLengthManual

            carCapacity = Parameter.passengerCarCapacity[rollingStockBaseType]

            #store train in local TRENTO database
            curTrain = TrentoTrain(platformSequence, stationNameSequence, arrTimeSched, depTimeSched, arrTimeReal, depTimeReal,
                                   rollingStockBaseType, numCars, carCapacity, trainLength)

            trentoTrainDict[trainNumber] = curTrain

        return trentoTrainDict;


# -*- coding: utf-8 -*-
"""
 Sylvain Bertrand, 2023

"""

import numpy as np
import matplotlib.pyplot as plt
import sys

if (len(sys.argv) == 2):
    nbOfRobots = int(sys.argv[1])
else:
    nbOfRobots = 1
    print("Warning: nb of robots set to 1")
    print("syntax: plot_from_csv.py nbOfRobots")

t = []
x = []
y = []

fig, ax = plt.subplots(2)
fig_traj, ax_traj = plt.subplots(1)

colorList = [[1,0,0], [0,1,0], [0,0,1], [1,0.91,0.31], [0.7,0.7,0.7], [0.96,0.18,0.92], [1,0.49,0.37], [0,0,0]]
while len(colorList)<nbOfRobots:
    colorList.append([0.5,0.5,0.5])

legendList = []

for robotNo in range(1,nbOfRobots+1):

    # load CSV file
    fileName = 'csv_directory/_slash_tb3_'+str(robotNo)+'_slash_odom.csv'
    f = np.loadtxt(fileName, skiprows=1, usecols=[4,5,11,12,13], delimiter=',')

    # get fields
    t.append(f[:,0]-f[0,0]+f[:,1]*0.000000001)
    x.append(f[:,2])
    y.append(f[:,3])

    legendList.append(str(robotNo))

    # time plots
    ax[0].plot(t[robotNo-1], x[robotNo-1], color=colorList[robotNo-1])
    ax[1].plot(t[robotNo-1], y[robotNo-1], color=colorList[robotNo-1])

    # trajectory plot
    ax_traj.plot(x[robotNo-1],y[robotNo-1], color=colorList[robotNo-1])

# legend and labels for time plots
ax[0].set_ylabel('x (m)')
ax[0].grid()
ax[0].legend(legendList)
ax[1].set_xlabel('t (s)')
ax[1].set_ylabel('y (m)')
ax[1].grid()
ax[1].legend(legendList)

# legend and labelds for trajectory plot
ax_traj.set_title('Trajectories')
ax_traj.set_xlabel('x (m)')
ax_traj.set_ylabel('y (m)')
ax_traj.grid()
ax_traj.legend(legendList)

# show plots
plt.show()


import datetime

from django.core.exceptions import ValidationError
from django.db import models
from django.contrib.auth import get_user_model

from model_choices import *

User = get_user_model()
class Category(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200)

class Company(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='company')
    name = models.CharField(max_length=50)
    email = models.EmailField()
    phone_number = models.CharField(max_length=20)
    logo = models.ImageField(null=True)
    website = models.URLField(blank=True,null=True)
    staffs_count = models.PositiveSmallIntegerField()
    address = models.CharField(max_length=150, blank=True, null=True)
    description = models.TextField()
    #social network accounts
    telegram = models.URLField(blank=True,null=True)
    linkedin = models.URLField(blank=True,null=True)
    youtube = models.URLField(blank=True,null=True)
    instagram = models.URLField(blank=True,null=True)
    facebook = models.URLField(blank=True,null=True)

    def __str__(self) -> str:
        return self.name

    def count_vacancy(self):
        return self.vacancy.count()

    def clean(self):
        if not self.user.is_employer:
            raise ValidationError(
                {'Error': "User is Empoler True bo'lishi kerak"})

    def save(self, *args, **kwargs):
        self.full_clean()
        return super().save(*args, **kwargs)

class Vacancy(models.Model):
    company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='vacancy', blank=True, null=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='vacancy', blank=True, null=True)
    title = models.CharField(max_length=150)
    deadline = models.DateField(blank=True, null=True)
    location = models.CharField(max_length=150, blank=True, null=True)
    employment_form =  models.CharField(max_length=2, choices=EmploymentForm)
    employment_type =  models.CharField(max_length=2, choices=EmploymentType)
    salary1 = models.IntegerField(blank=True, null=True)
    salary2 = models.IntegerField(blank=True, null=True)
    salary_type = models.CharField(max_length=5, choices=SalaryType)
    currency = models.CharField(max_length=3, choices=Currency)
    experience = models.PositiveSmallIntegerField(blank=True, null=True)
    languages = models.CharField(max_length=200)
    edu_level = models.CharField(max_length=150, default="-")
    description = models.TextField()
    contact = models.CharField(max_length=150, blank=True, null=True)
    created_at = models.DateField(default=datetime.date.today())

    def __str__(self) -> str:
        return self.title

    def update_deadline(self, date):
        self.deadline = date
        self.save()

    def update_exp(self, new):
        self.experience = new
        self.save()

    def update_salary1(self, salary):
        self.salary1 = salary
        self.save()

    def update_salary2(self, salary):
        self.salary2 = salary
        self.save()

    def applies_count(self):
        return self.apply.count()

class Applied(models.Model):
    vacancy = models.ForeignKey(Vacancy, on_delete=models.CASCADE, related_name='apply')
    user = models.ForeignKey(User,  on_delete=models.CASCADE, related_name='apply')
    message = models.CharField(max_length=512)
    applied_date = models.DateField(auto_now_add=True)
    # apply status
    status = models.CharField(max_length=2, choices=APPLY_STATUS, default='UR')


import logging
from StringIO import StringIO
import zlib
class UnzipRequestMiddleware(object):
    """A middleware that unzips POSTed data.

    For this middleware to kick in, the client must provide a value
    for the ``Content-Encoding`` header. The only accepted value is
    ``gzip``. Any other value is ignored.
    """

    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        encoding = environ.get('HTTP_CONTENT_ENCODING')
        if encoding == 'gzip':
            data = environ['wsgi.input'].read()
            try:
                uncompressed = zlib.decompress(data, 31)
                environ['wsgi.input'] = StringIO(uncompressed)
                environ['CONTENT_LENGTH'] = len(uncompressed)
            except zlib.error:
                logging.warning(u"Could not decompress request data.", exc_info=True)
                environ['wsgi.input'] = StringIO(data)
        return self.app(environ, start_response)


import re

def supermarket_shopping(budgets):
    product_name = input("\nEnter product : ")
    product_quantity = float(re.findall(r"[-+]?\d*\.\d+|\d+", input("Enter quantity : "))[0])
    product_price = float(input("Enter price : "))

    amount_left = 0
    for values in shopping_list.values():
        amount_left += values[1]
    amount_left = budgets - amount_left

    if amount_left < product_price:
        print("\nCan't buy the product because it's price is more than left amount.\n")
    else:
        amount_left = 0
        if product_name in shopping_list:
            shopping_list[product_name][0], shopping_list[product_name][1] = product_quantity, product_price
        else:
            shopping_list[product_name] = []
            shopping_list[product_name].append(product_quantity)
            shopping_list[product_name].append(product_price)
        for values in shopping_list.values():
            amount_left += values[1]
        amount_left = budgets - amount_left
        print("\nAmount left : {0}.\n".format(amount_left))

if __name__ == "__main__":
    shopping_list = {}
    budget = int(input("Enter Your Budget : "))
    while True:
        choice = input(
            "1. Add an item.\n2. Exit.\nEnter Your Choice : ")
        if choice == "1":
            supermarket_shopping(budgets=budget)
        elif choice == "2":
            amount_left = 0
            for values in shopping_list.values():
                amount_left += values[1]
            amount_left = budget - amount_left
            product = ""
            max_price_product = 0.0
            for j, i in shopping_list.items():
                if i[1] <= amount_left:
                    if max_price_product < i[1]:
                        product = j
                        max_price_product = i[1]
            if len(product):
                print("\nAmount left can buy you {0}.\n".format(product))
                print("Grocery List is :")
                print("Product Name\tQuantity\tPrice")
                for i, j in shopping_list.items():
                    print(i, "\t", str(j[0]) + " kg", "\t", j[1])
            else:
                exit("Goodbye!!!")
        else:
            print("!!! Wrong Selection.\n")


#
#    Version:  0.1.0  1/1/21
#
#    License:  CC BY-NC-SA 4.0, https://creativecommons.org/licenses/by-nc-sa/4.0/
#
#    Graeme Williams
#    carryonwilliams@gmail.com
#

import pymarc

from . import mydb   # for recordgenerator wrapper

#####  Handling names from 100 and 700 fields  #####
#
# Author names are stored as a tuple, either ( name ), ( name, birthdate ) or ( name, birthdate, deathdate ).
# We use this format instead of, e.g.,  ( name, None, None ) because the latter breaks sorting of tuples
#
# The name is a string either forwards or backwards:  Bob Smith or Smith, Bob.

def namestrip(authorname : str) -> str:
    t = authorname.strip(' ')
    t = t.rstrip(',')
    # strip trailing . unless it's an initial, like "Smith, A."
    if len(t) > 2 and t[-3].isalpha():
        t = t.rstrip('.')
    return t

def flipnames(lastnamefirst:str) -> str:
    lastname, firstnames = lastnamefirst.split(',', 1)  # split only on the first comma
    return namestrip(firstnames) + lastname

def namefromMARC(subfield_a, subfield_d, flip = False) -> tuple:      # subfield_d can be None
    # strip punctuation from subfield a
    t = ( flipnames(subfield_a) ) if flip else ( namestrip(subfield_a) )
    # any punctuation weirdness in subfield d will be carried forward
    if subfield_d:
        dates = subfield_d.split('-')                   # either one date + '' or two dates
        return t + tuple( [ d for d in dates if d ] )   # drop '' if any
    else:
        return t

#####  Handling input streams (file or DB)  #####

# wrapper so reading MARC files looks the same as reading the database:
def readfromfile(filename):
    with open(filename, 'rb') as marc_input:
        for aRecord in pymarc.MARCReader(marc_input):
            # if you have a MARC field you want to use to identify the record
            # assign it to bibnumber here -- as a string
            bibnumber = ""
            yield bibnumber, aRecord

# depending on the input, make a generator out of a MARC
# input file or a database table
def recordgenerator(inputfile:str, dbtable:str):
    if inputfile:
        return readfromfile(inputfile)
    else:
        input_cnx = mydb.Connection(schema="world")
        input_table = mydb.Table(input_cnx, dbtable)
        return input_table.readpymarc(query="")


import pandas as pd

# ETL: Extract, Transform, Load

# Ruta al archivo CSV de origen
archivo_origen = "td1-2023-2/clase_etl/data.csv"

# Leer los datos desde el archivo CSV y especificar que la primera fila es el encabezado
datos = pd.read_csv(archivo_origen, delimiter=';', header=0)

# Verificar los primeros registros
print(datos.head())
print(datos.columns)
# Agregar una nueva columna 'suma' que contenga la suma de dos columnas existentes
# Asumiendo que las columnas se llaman 'columna1' y 'columna2' en tu archivo CSV
datos['suma'] = datos['columna1'] + datos['columna2']

# Verificar los cambios
print(datos.head())

# Ruta al archivo CSV de destino
archivo_destino = "datos_transformados.csv"

# Guardar los datos transformados en un nuevo archivo CSV
datos.to_csv(archivo_destino, index=False)

# Verificar que se haya guardado correctamente
print(f"Los datos transformados se han guardado en {archivo_destino}")


#JOHN EL CONSULTOR PRESENTA
#Aprende PYTHON desde el Telefóno
#APP Gratuita en mi descripción de TK

#DIA 2 Variables
#Son un modo de almacenar la información en python
#El proceso de crear una variable se llama declaración
#Para declarar:
#nombreVariable = Número o Texto

#Uso1 declarando una variable con un string
nombre = "john"
print("Mi nombre es: " + nombre)

#Uso2 declarando una variable con un número
numUno = 10
numDos = 20
#print("la suma es: ", numUno + NumDos) ACÁ ORINGINA ERROR PORQUE NO PUEDO MEZCLAR TIPOS, debo Castear Int a Str (de número a texto)
print("la suma es: ", str(numUno + numDos))


import cone_commands
from cone_commands.core.management.base import BaseCommand, Command

@Command.register()
class VersionCommand(BaseCommand):

    def add_arguments(self, parser):
        parser.add_argument(
            "--version",
            action="version",
            help="Show program's version number and exit.",
        )

    def handle(self, *args, **options):
        self.stdout.write(cone_commands.__version__ + "\n")


# -*- coding: utf-8 -*-
from scrapy import Spider
from scrapy.http import Request

def product_info(response, value):
    return response.xpath('//th[text()="' + value + '"]/following-sibling::td/text()').extract_first()

class BooksSpider(Spider):
    name = 'BooksSpider'
    allowed_domains = ['books.toscrape.com']
    start_urls = ['http://books.toscrape.com']

    def parse(self, response):
        books = response.xpath('//h3/a/@href').extract()
        for book in books:
            absolute_url = response.urljoin(book)
            yield Request(absolute_url, callback=self.parse_book)

        # process next page
        next_page_url = response.xpath('//a[text()="next"]/@href').extract_first()
        absolute_next_page_url = response.urljoin(next_page_url)
        yield Request(absolute_next_page_url)

    def parse_book(self, response):
        title = response.css('h1::text').extract_first()
        price = response.xpath('//*[@class="price_color"]/text()').extract_first()

        image_url = response.xpath('//img/@src').extract_first()
        image_url = image_url.replace('../..', 'http://books.toscrape.com/')

        rating = response.xpath('//*[contains(@class, "star-rating")]/@class').extract_first()
        rating = rating.replace('star-rating ', '')

        description = response.xpath(
            '//*[@id="product_description"]/following-sibling::p/text()').extract_first()

        # book information data
        product_type =  product_info(response, 'Product Type')
        price_without_tax = product_info(response, 'Price (excl. tax)')
        price_with_tax = product_info(response, 'Price (incl. tax)')
        tax = product_info(response, 'Tax')
        availability = product_info(response, 'Availability')
        number_of_reviews = product_info(response, 'Number of reviews')

        yield {
            'title': title,
            'price': price,
            'image_url': image_url,
            'rating': rating,
            'description': description,
            'product_type': product_type,
            'price_without_tax': price_without_tax,
            'price_with_tax': price_with_tax,
            'tax': tax,
            'availability': availability,
            'number_of_reviews': number_of_reviews
        }


"""
股票池，选取可以进行投资的股票
"""
from WindPy import *
from pandas import DataFrame
from pandas.tseries.offsets import YearEnd
from factors.BasicTool import CheckWindData, MongoClient
import numpy as np
import pandas as pd

w.start()
class StockPool:

    def __init__(self, date):
        self.date = date

    def select_stock(self):
        """
        股票池选择标准如下：
        1：剔除当期*ST，ST个股
        2：剔除当期停牌的个股，剔除上市未满四年的个股
        3：剔除当期涨停的股票
        4：近三年经营活动现金流为正，ROE>10 OR FCF/销售收入>5 ,盈利增长速度协调一致
        5：近三年营业利润为正，且发行在外的总股本增长不明显
        :return:
        """
        stockdata = {}
        # 剔除*ST，ST
        stock = w.wset("sectorconstituent", "date=" + self.date + ";sectorid=a001010f00000000")
        stockdata['Codes'] = stock.Data[1]
        # 剔除当期停牌的个股

        status = w.wss(stockdata['Codes'], "trade_status", "tradeDate=" + self.date)
        stockdata['status'] = status.Data[0]

        df = DataFrame(stockdata)
        df = df[df['status'] == u'交易']
        # 剔除涨停的股票
        maxud = w.wss(df['Codes'].values.tolist(), "maxupordown", "tradeDate=" + self.date)
        df['maxud'] = maxud.Data[0]

        df = df[df['maxud'] < 1]
        # 剔除上市未满三年的股票
        ipo_days = w.wss(df['Codes'].values.tolist(), "ipo_listdays", "tradeDate=" + self.date)
        df['ipo_days'] = ipo_days.Data[0]
        df = df[df['ipo_days'] > 4 * 365]
        # 股票池标准
        date = self.date
        date_1 = datetime.strptime(date, "%Y-%m-%d")
        if date_1.month >= 5:
            pre_year_date = datetime.strptime(date, "%Y-%m-%d") - YearEnd(1)
            pre_year_date1 = datetime.strptime(date, "%Y-%m-%d") - YearEnd(2)
            pre_year_date2 = datetime.strptime(date, "%Y-%m-%d") - YearEnd(3)
        else:
            pre_year_date = datetime.strptime(date, "%Y-%m-%d") - YearEnd(2)
            pre_year_date1 = datetime.strptime(date, "%Y-%m-%d") - YearEnd(3)
            pre_year_date2 = datetime.strptime(date, "%Y-%m-%d") - YearEnd(4)

        # roe > 5, pe > 0, inc > 0
        roe = w.wss(df['Codes'].values.tolist(), "roe", "rptDate=" + pre_year_date.strftime("%Y-%m-%d"))
        df['roe'] = roe.Data[0]
        pe = w.wss(df['Codes'].values.tolist(), "pe","tradeDate=" + pre_year_date.strftime("%Y-%m-%d")+ ";ruleType=10")
        df['pe'] = pe.Data[0]
        inc = w.wss(df['Codes'].values.tolist(), "wgsd_net_inc","unit=1;rptDate="+pre_year_date.strftime("%Y-%m-%d")+";rptType=1;currencyType=")
        df['net_inc'] = inc.Data[0]
        df = df[df['roe'] > 5]
        df = df[df['pe'] > 0]
        df = df[df['net_inc'] > 0]

        stockcodes = df['Codes'].values.tolist()

        return stockcodes