# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENCE BLOCK #####

bl_info = {
    "name":"hairmgrplus",
    "author": "Alessandro Tachibana",
    "version": (0,1,0),
    "blender": (2,80,0),
    "location": "Properties",
    "category": "Particle",
    "description": "hair tool",
    "wiki_url": " ",
    "tracker_url":" "
}

import bpy
import mathutils
import numpy as np
import random
import ast

#----------------------------------------
#---------------PROPERTIES---------------
#----------------------------------------
bpy.types.Scene.hamgpImportColl = bpy.props.PointerProperty(
    type = bpy.types.Collection
)
bpy.types.Scene.hamgpExportColl = bpy.props.PointerProperty(
    type = bpy.types.Collection
)

#----------------------------------------
#----------------------------------------
#COPY PASTE FUNCTION VARIABLES
#----------------------------------------
#----------------------------------------
COPY_PASTE_KEY = 'HMGRP_COPY_DATA'

#hair dynamics
prop_hair_dynamics = [[],['use_hair_dynamics']]
prop_hair_dynamics_2 = [['cloth','settings'],['quality','pin_stiffness']]

prop_hd_structure = [['cloth','settings'],['mass','bending_stiffness','bending_damping']]
prop_hd_structure_2 = [['settings'],['bending_random']]
prop_hd_volume = [['cloth','settings'],['air_damping','air_damping','voxel_cell_size','density_target', 'density_strength','internal_friction']]

#--------------------------------------------
#render
prop_render = [['settings'],['render_type','material_slot']]
prop_render_2 = [['id_data'],['show_instancer_for_render']]
prop_render_3 = [[],['parent']]
prop_render_path = [['settings'],['use_hair_bspline','render_step']]
prop_render_timing = [['settings'],['use_absolute_path_time','path_start','path_end','length_random']]
prop_render_extra = [['settings'],['use_parent_particles','show_unborn','use_dead']]

#--------------------------------------------
#viewport display
prop_viewport_display = [['settings'] \
                        ,['display_method','display_color','display_percentage' \
                        ,'display_size','color_maximum','display_step' ]]

prop_viewport_display_2 = [['id_data'],['show_instancer_for_viewport']]

#--------------------------------------------
#children
prop_children = [['settings'] \
                , ['child_type','child_nbr','rendered_child_count' \
                ,'child_length','child_length_threshold' \
                ,'child_size', 'child_size_random','child_radius' \
                ,'child_roundness']]

prop_children_2 = [[],['child_seed']]

prop_children_parting = [['settings'],['child_parting_factor','child_parting_min','child_parting_max']]

prop_children_clumping = [['settings'] \
                        ,['use_clump_curve','clump_factor','clump_shape' \
                        ,'twist','use_twist_curve','twist_curve']]

prop_children_roughness = [['settings'] \
                          ,['use_roughness_curve','roughness_1_size','roughness_endpoint' \
                          ,'roughness_end_shape','roughness_2','roughness_2_size' \
                          , 'roughness_2_threshold', 'roughness_curve']]

prop_children_klin = [['settings'] \
                     ,['kink','kink_amplitude','kink_amplitude_random' \
                     ,'kink_axis','kink_axis_random','kink_frequency' \
                     ,'kink_shape','kink_extra_steps','kink_amplitude' \
                     ,'kink_amplitude_clump','kink_flat','kink_frequency' \
                     ,'kink_shape']]

#--------------------------------------------
#shape
prop_hair_shape = [['settings'] \
                  ,['shape','root_radius','tip_radius' \
                  ,'radius_scale','use_close_tip']]

#---------------------------------------------
#velocity
prop_velocity = [['settings'] \
                ,['normal_factor','tangent_factor', 'tangent_phase' \
                ,'object_align_factor','particle_factor','object_factor' \
                , 'factor_random']]

#----------------------------------------
#----------------------------------------
#add menu name
prop_all_hd = ['Hair Dynamics',[prop_hair_dynamics, prop_hair_dynamics_2, prop_hd_structure, prop_hd_structure_2, prop_hd_volume]]
prop_all_render = ['Render',[prop_render, prop_render_2, prop_render_3, prop_render_path, prop_render_timing, prop_render_extra]]
prop_all_vd = ['Viewport Display',[prop_viewport_display, prop_viewport_display_2]]
prop_all_children = ['Children',[prop_children, prop_children_parting, prop_children_clumping, prop_children_roughness, prop_children_klin]]
prop_all_hs = ['Hair Shape',[prop_hair_shape]]
prop_all_veloc = ['Velocity',[prop_velocity]]
#prop_test_child = ['Test', [prop_children_roughness]]

#prop_all is used to build the panel COPY buttons
prop_all = [prop_all_hd, prop_all_render, prop_all_vd, prop_all_children, prop_all_hs, prop_all_veloc]

#----------------------------------------
#---------------FUNCTIONS----------------
#----------------------------------------
def debugPrint(string):
    print(string)
    pass

def errorPrint(string):
    print(string)
    pass

def setClipBoard(var):
    bpy.context.window_manager.clipboard = var

def getClipBoard():
    return bpy.context.window_manager.clipboard

def evaluateObj(name, context):
    despgraph = context.evaluated_depsgraph_get()
    eval_ob = despgraph.objects.get(name, None)
    return eval_ob

def getObjLocal(context):
    return context.scene

def getImpCol(context):
    return getObjLocal(context).hamgpImportColl

def getExpCol(context):
    return getObjLocal(context).hamgpExportColl

def addToCol(col, obj):
    col.objects.link(obj)

def IsParticleSelected(context):
    var_return = True
    if len(context.selected_objects) == 0:
        var_return = False
    elif context.selected_objects[0].particle_systems is None:
        var_return = False
    elif context.selected_objects[0].particle_systems.active is None:
        var_return = False
    elif context.selected_objects[0].particle_systems.active.settings.type != 'HAIR':
        var_return = False
    return var_return

#----------------------------------------
#----------------------------------------
#----------------------------------------
class Import:
    @classmethod
    def createHairSystem(self, context, col_name, hair_count):

        hairSys = context.selected_objects[0].modifiers.new(col_name, type='PARTICLE_SYSTEM')
        hairSys.particle_system.settings.type = 'HAIR'
        if hair_count < 4:
            hair_count = 4
        hairSys.particle_system.settings.count = hair_count
        #hairSys.particle_system.is_edited = True
        #hairSys = context.selected_objects[0].particle_systems[-1]

        return hairSys

    @classmethod
    def __calcAngle(self, da, db):
        da = round(da, 4)
        db = round(db, 4)
        angle = 0
        if abs(da) > 0:
            angle = np.arctan(abs(db)/abs(da))
            if db > 0 and da > 0: #Q1
                debugPrint('Q1')
                angle += 0
            elif db > 0 and da < 0: #Q2
                debugPrint('Q2')
                angle = (np.pi - angle)
            elif db < 0 and da < 0: #Q3
                debugPrint('Q3')
                angle = -1 * (np.pi - angle)
            elif db < 0 and da > 0: #Q4
                debugPrint('Q4')
                angle = -1 * (angle)
            elif abs(db) == 0 and da < 0:
                debugPrint('D1')
                angle = np.pi
        elif db > 0:
            debugPrint('D2')
            angle = np.pi/2
        elif db < 0:
            debugPrint('D3')
            angle = -1 * (np.pi/2)
        return angle

    @classmethod
    def __solveRotationMax(self, position, particle):
        A = B = C = D = E = F = G = H = I = J = K = 0

        (dx, dy, dz) = position * -1
        TM = np.array([[1,0,0,dx],[0,1,0,dy],[0,0,1,dz],[0,0,0,1]])

        co1 = self.__matMul4x4(TM, particle.hair_keys[1].co)
        co2 = self.__matMul4x4(TM, particle.hair_keys[2].co)
        co3 = self.__matMul4x4(TM, particle.hair_keys[3].co)

        (x1, y1, z1) = co1
        (x2, y2, z2) = co2
        (x3, y3, z3) = co3
        (xl1, yl1, zl1) = particle.hair_keys[1].co_local
        (xl2, yl2, zl2) = particle.hair_keys[2].co_local
        (xl3, yl3, zl3) = particle.hair_keys[3].co_local

        a1 = np.array([[x1, y1, z1],[x2, y2, z2], [x3, y3, z3]])
        b1 = np.array([xl1, xl2, xl3])

        a2 = np.array([[x1, y1, z1],[x2, y2, z2], [x3, y3, z3]])
        b2 = np.array([yl1, yl2, yl3])

        a3 = np.array([[x1, y1, z1],[x2, y2, z2], [x3, y3, z3]])
        b3 = np.array([zl1, zl2, zl3])

        try:
            r1 = np.linalg.solve(a1,b1)
            (A, B, C) = r1
        except Exception as e:
            errorPrint(str(e))

        try:
            r2 = np.linalg.solve(a2,b2)
            (D, E, F) = r2
        except Exception as e:
            errorPrint(str(e))

        try:
            r3 = np.linalg.solve(a3,b3)
            (H, I, J) = r3
        except Exception as e:
            errorPrint(str(e))

        MATRIX = [[A, B, C, dx],[D, E, F, dy],[H, I, J, dz],[0, 0, 0, 1]]

        return MATRIX

    @classmethod
    def __findZMatRot(self, particle, TM, RX, RY):
        #|cosA  sinA   0    0
        #|sinA  cosA   0    0
        #|0      0     1    0
        #|0      0     0    1
        RZ = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[1, 0, 0, 1]]
        pos1 = self.__calcPos(particle.hair_keys[1].co, TM, RX, RY, RZ)
        pos2 = self.__calcPos(particle.hair_keys[2].co, TM, RX, RY, RZ)

        az = 0
        cosZ = 0
        sinZ = 0
        (x1, y1, z1) = pos1
        (x2, y2, z2) = pos2

        (xl1, yl1, zl1) = particle.hair_keys[1].co_local
        (xl2, yl2, zl2) = particle.hair_keys[2].co_local

        # x_local = cozZ * x -sinZ * y
        a = np.array([[x1, y1],[x2, y2]])
        b = np.array([xl1, xl2])
        try:
            x = np.linalg.solve(a,b)
            (cosZ, sinZ) = x
        except Exception as e:
            errorPrint(str(e))

        try:
            az1 = np.arccos(cosZ)
            if not np.isnan(az1):
                az = az1
        except Exception as e:
            errorPrint(str(e))

        try:
            az2 = np.arcsin(sinZ)
            if not np.isnan(az2):
                az = az2
        except Exception as e:
            errorPrint(str(e))

        RZ = np.array([[np.cos(az), -np.sin(az), 0, 0],[np.sin(az), np.cos(az), 0, 0],[0, 0, 1, 0],[0,0,0,1]])
        debugPrint('z angle: ' + str(az))
        debugPrint('RZ: ' + str(RZ))
        return RZ

    @classmethod
    def __calcRotationMax(self, position, normal, center):

        debugPrint('----------------------------')
        debugPrint('----------------------------')
        (dx, dy, dz) = position * -1
        (nx, ny, nz) = normal
        debugPrint('normal: ' + str(np.round_(normal,4)))
        ax = 0 #np.arcsin(nx)  #np.arcsin(nx) #* -1d
        ay = 0 #np.arcsin(ny)  #np.deg2rad(-45) #np.arcsin(ny) #* -1
        az = 0 #np.arcsin(nz) * -1

        hh = np.sqrt(np.power(nx,2) + np.power(ny,2))

        ax = self.__calcAngle(nz, ny)
        RX = np.array([[1,0,0,0],[0, np.cos(ax), -np.sin(ax), 0],[0, np.sin(ax), np.cos(ax), 0],[0,0,0,1]])

        #---------------------------------
        normal_rx = self.__matMul4x4(RX, normal)
        (nrxx, nrxy, nrxz) = normal_rx
        debugPrint('normal_rx: ' + str(np.round_(normal_rx,4)))
        ay = self.__calcAngle(nrxz, nrxx) * -1
        RY = np.array([[np.cos(ay), 0, np.sin(ay),0],[0, 1, 0, 0],[-np.sin(ay), 0, np.cos(ay), 0],[0,0,0,1]])

        #---------------------------------
        normal_ry = self.__matMul4x4(RY, normal_rx)
        debugPrint('normal_ry: ' + str(np.round_(normal_ry,4)))

        az = 0 #np.pi

        #print('hh: ' + str(hh))
        debugPrint('----------------------------')
        debugPrint('----------------------------')
        debugPrint('angle x: ' + str(np.rad2deg(ax)))
        debugPrint('angle y: ' + str(np.rad2deg(ay)))
        debugPrint('angle z: ' + str(np.rad2deg(az)))

        #ROTATION X - [[1,0,0,0][0, cos Ax, -sin Ax, 0][0, sin Ax, cos Ax, 0][0,0,0,1]]
        #ROTATION Y - [[cos Ay, 0, sin Ay,0][0, 1, 0, 0][-sin Ay, 0, cos Ay, 0][0,0,0,1]]
        #ROTATION Z - [[cos Az, -sin Az, 0, 0][sin Az, cos Az, 0, 0][0, 0, 1, 0][0,0,0,1]]
        TM = np.array([[1,0,0,dx],[0,1,0,dy],[0,0,1,dz],[0,0,0,1]])

        RZ = np.array([[np.cos(az), -np.sin(az), 0, 0],[np.sin(az), np.cos(az), 0, 0],[0, 0, 1, 0],[0,0,0,1]])

        return TM, RX, RY, RZ

    @classmethod
    def __vect2Array4x1(self, vector):
        array = np.array(vector)
        arr4x1 = np.append(array, [1])
        return arr4x1

    @classmethod
    def __array4x12Vec(self, array):
        return mathutils.Vector(array[:3])

    @classmethod
    def __calcPos(self, vector, TM, RX, RY, RZ):
        arr4x1 = self.__vect2Array4x1(vector)

        arr4x1 = np.matmul(TM, arr4x1)
        arr4x1 = np.matmul(RX, arr4x1)
        arr4x1 = np.matmul(RY, arr4x1)
        arr4x1 = np.matmul(RZ, arr4x1)

        return self.__array4x12Vec(arr4x1)

    @classmethod
    def printHairKey(self, context):
        eval_ob = evaluateObj(context.selected_objects[0].name, context)
        evalHair = eval_ob.particle_systems[-1]

        debugPrint('----------------------------')
        debugPrint('----------------------------')
        for index in range(len(evalHair.particles)):
            hairEval = evalHair.particles[index]

            faceindex = eval_ob.closest_point_on_mesh(hairEval.location)[-1]
            position = eval_ob.closest_point_on_mesh(hairEval.location)[1]
            #normal = eval_ob.data.polygons[faceindex].normal
            normal = hairEval.velocity
            center = eval_ob.data.polygons[faceindex].center

            #TM, RX, RY, RZ = self.__calcRotationMax(position, normal, center)
            #RZ = self.__findZMatRot(hairEval, TM, RX, RY)

            TMAT = self.__solveRotationMax(position, hairEval)

            debugPrint('----------------------------')
            debugPrint('----------------------------')
            debugPrint('position' + str(position))
            debugPrint('normal' + str(normal))
            debugPrint('center' + str(eval_ob.data.polygons[faceindex].center))

            debugPrint('----------------------------')
            debugPrint('----------------------------')
            debugPrint('location: ' + str(hairEval.location))
            debugPrint('velocity: ' + str(hairEval.velocity))
            debugPrint('rotation: ' + str(hairEval.rotation))

            for index2 in range(len(hairEval.hair_keys)):
                hairkey = hairEval.hair_keys[index2]

                debugPrint('----------------------------')
                debugPrint('co: ' + str(hairkey.co))
                debugPrint('co_local: ' + str(hairkey.co_local))

                #calc = self.__calcPos(hairkey.co, TM, RX, RY, RZ)
                calc = self.__matMul4x4(TMAT, hairkey.co)

                debugPrint('calc_local: ' + str(calc))

    @classmethod
    def returnArrayEq(self, hair_key):
        (xl, yl, zl) = hair_key.co_local
        return xl, yl, zl, hair_key.co

    @classmethod
    def __matMul4x4(self, AT, co):
        (x, y, z) = co
        pos_array = np.array([x,y,z,1])

        co_local = np.matmul(AT,pos_array)

        return co_local[:3]

    @classmethod
    def SetRandomHairPos(self, hairSys, context):

        bpy.ops.particle.particle_edit_toggle()
        bpy.ops.particle.particle_edit_toggle()

        #remove hair with 0 position on any axis
        for index in range(len(hairSys.particles)):
            hair = hairSys.particles[index]

            for index2 in range(1, len(hair.hair_keys)):
                hair_key = hair.hair_keys[index2]
                (x, y, z) = hair_key.co_local
                x = random.uniform(-0.3,0.3) * index2
                y = random.uniform(-0.3,0.3) * index2
                z = random.uniform(0.1,0.3) * index2
                hair_key.co_local =  mathutils.Vector([x, y, z])

            hair.hair_keys[0].co_local = mathutils.Vector([0, 0, 0])

    @classmethod
    def Curves2Hair(self, collCurves, hairSys, context):
        #hairSys = context.selected_objects[0].particle_systems[-1]
        bpy.ops.particle.particle_edit_toggle()
        bpy.ops.particle.particle_edit_toggle()

        print(hairSys.name)
        eval_ob = evaluateObj(context.selected_objects[0].name, context)
        evalHair = eval_ob.particle_systems[-1]

        for index in range(len(hairSys.particles)):
            #print(index)
            if index <= len(collCurves):
                curve = collCurves[index]

                #curveEval = evaluateObj(curve.name, context)
                hair = hairSys.particles[index]
                hairEval = evalHair.particles[index]

                bezier_pts = curve.data.splines.items()[0][1].bezier_points.items()

                faceindex = eval_ob.closest_point_on_mesh(hairEval.location)[-1]
                #position = eval_ob.closest_point_on_mesh(hairEval.location)[1]
                position = hairEval.hair_keys[0].co #uses the first hair key as the translation delta, works if co_local = 0
                normal = eval_ob.data.polygons[faceindex].normal
                center = eval_ob.data.polygons[faceindex].center

                #-------------------------------------
                #calculate the transformation matrix
                #-------------------------------------
                #TM, RX, RY, RZ = self.__calcRotationMax(position, normal, center)
                #RZ = self.__findZMatRot(hair, TM, RX, RY)

                TMAT = self.__solveRotationMax(position, hair)

                for index2 in range(len(hair.hair_keys)):
                    if index2 <= len(bezier_pts) - 1:
                        points = bezier_pts[index2][1]

                        hair_key = hair.hair_keys[index2]
                        hair_kEval = hairEval.hair_keys[index2]

                        #calc = self.__calcPos(points.co, TM, RX, RY, RZ)
                        calc = self.__matMul4x4(TMAT, points.co)

                        #FUCK THIS MOTHERFUCKING SHIT
                        #WHY CAN'T YOU JUST SET THE .CO VARIABLE????????
                        #FUCK FUCK FUCK!!!!!!!!!!!!!!!!!!
                        #hair_key.co_local = calc
                        hair_key.co_local = calc

#----------------------------------------
#----------------------------------------
#----------------------------------------
class Export:
    @classmethod
    def Hair2Curves(self, hairSys, collCurves, context):
        for hair in hairSys.particles.items():
            #create curve
            newCurve = bpy.data.curves.new('haircurve', type='CURVE')
            newCurve.dimensions = '3D'

            spline = newCurve.splines.new('BEZIER')
            spline.bezier_points.add(len(hair[1].hair_keys.items()) -1)
            #print('---------------------------------------------')

            for index, hairkey in hair[1].hair_keys.items():
                #change curves
                spline.bezier_points[index].co = hairkey.co
                spline.bezier_points[index].handle_left_type = "AUTO"
                spline.bezier_points[index].handle_right_type = "AUTO"
                #print(hairkey[1].co_local)
                #print((x, y, z))

            curveObj = bpy.data.objects.new('curveobj', newCurve)
            #curveObj.rotation_mode = 'XYZ'
            #curveObj.rotation_quaternion = hair[1].rotation
            #curveObj.location = hair[1].location

            addToCol(collCurves, curveObj)

    @classmethod
    def Hair2Poly(self, hairSys, collCurves, context):
        pass

#----------------------------------------
#---------------------------------------

#----------------------------------------
#----------------------------------------
#-------------OBJ TYPE-------------------
#----------------------------------------
#----------------------------------------
class HMGRPCopyPasteType:

    class CopyPasteData:

        def __init__(self, path, property, value, vartype, children):
            self.path = path
            self.property = property
            self.value = value
            self.vartype = vartype
            self.children = children

        def toArray(self):
            vchildren =[]
            for ch in self.children:
                vchildren.append(ch.toArray())

            return [self.path, self.property, self.value, self.vartype, vchildren]

        @classmethod
        def arrayToString(self, items):
            returnstr = '['
            for i in range(len(items)):
                if i > 0:
                    returnstr += ','
                returnstr += "\"" + str(items[i]) + "\""
            returnstr += ']'
            return returnstr

        @classmethod
        def castString(self, value, typedef):
            if str(typedef) == '<class \'NoneType\'>':
                return None
            elif str(typedef) == '<class \'bool\'>':
                if value == 'True':
                    return True
                else:
                    return False
            elif str(typedef) == '<class \'float\'>':
                return float(value)
            elif str(typedef) == '<class \'int\'>':
                return int(value)
            elif str(typedef) == '<class \'Vector\'>':
                tmpstr = value[value.find("(")+1:value.find(")")]
                tmparr = tmpstr.split(', ')
                (x, y, z) = tmparr
                x = float(x)
                y = float(y)
                z = float(z)
                tmpvec = mathutils.Vector([x,y,z])
                #debugPrint(tmpvec)
                return mathutils.Vector(tmpvec)
            else:
                return value

    #----------------------------------------------------
    #----------------------------------------------------
    def __CPDObjFromArray(self, parseArray):
        vpath = ''
        vproperty = ''
        vvalue = ''
        vvartype = ''
        vchildren = []

        vtmpch = []
        debugPrint('parseArray: ' + str(parseArray))
        if len(parseArray) == 5:
            vpath = parseArray[0]
            vproperty = parseArray[1]
            vvalue = parseArray[2]
            vvartype = parseArray[3]
            try:
                vtmpch = ast.literal_eval(parseArray[4])
            except:
                pass

        if str(vvartype) == '<class \'bpy.types.CurveMapping\'>' and len(vtmpch) > 0:
            for item in vtmpch:
                debugPrint('------------------------' + item)
                vchild = self.__CPDObjFromArray(item)
                vchildren.append(vchild)

        return self.CopyPasteData(vpath, vproperty, vvalue, vvartype, vchildren)

    def __CPDObjFromValues(self, path, property, value):
        vpath = str(path)
        vproperty = str(property)
        vvalue = str(value)
        vvartype = type(value)
        vchildren = []

        '''
        if str(vvartype) == '<class \'bpy.types.CurveMapping\'>' or str(vvartype) == '<class \'bpy_prop_collection\'>':
            tmp_path = path.copy()
            tmp_path.append(vproperty)

            #debugPrint(tmp_path)
            #debugPrint(dir(value))
            for tmpprop in dir(value):
                if str(tmpprop) != 'bl_rna' and str(tmpprop) != 'rna_type':
                    tmpvalue = getattr(value, tmpprop)
                    #debugPrint(dir(value))
                    data = self.__CPDObjFromValues(tmp_path, tmpprop, tmpvalue)
                    #debugPrint('data: ' + str(data.toArray()))
                    vchildren.append(data)
        '''
        return self.CopyPasteData(vpath, vproperty, vvalue, vvartype, vchildren)

    def __init__(self, strData=''):
        #debugPrint(strData)
        self.__arrayCPData = []
        if len(strData) > 0:
            #debugPrint('paste data: ' + str(strData))
            try:
                tmpData = ast.literal_eval(strData)
                #print(tmpData[0])
                if tmpData[0] == COPY_PASTE_KEY:
                    #debugPrint(tmpData[1])
                    self.__arrayCPData = tmpData[1]
            except Exception as e:
                errorPrint('error:' + str(e))

    def __loadChildren(self, childrenArr):
        return childrenArr

    def __procPath(self, var, hairSys):
        returnVar = hairSys
        for path in var:
            try:
                returnVar = getattr(returnVar, path)
            except:
                errorPrint('error path: ' + str(var))
        return returnVar

    def Load(self, dataArr, hairSys):
        for data in dataArr:
            objpath = self.__procPath(data[0], hairSys)
            for prop in data[1]:
                value = None
                try:
                    value = getattr(objpath, prop)
                except Exception as e:
                    errorPrint('error:' + str(e))

                cpdata = self.__CPDObjFromValues(data[0], prop, value)
                cpstring = cpdata.toArray()
                self.__arrayCPData.append(cpstring)

    def __setHairSysParam(self, hairSys, cpdata):
        #cpdata = CopyPasteData
        #debugPrint('path: ' + cpdata.path)
        if cpdata.property != '':
            objpath = self.__procPath(ast.literal_eval(cpdata.path), hairSys)
            #debugPrint(objpath)
            try:
                #setattr(object, name, value)
                value = self.CopyPasteData.castString(cpdata.value, cpdata.vartype)
                setattr(objpath, cpdata.property, value)
                #debugPrint(str(cpdata.property) + ':' + str(value))
            except Exception as e:
                errorPrint('error:' + str(e) + ', parameter: ' + str(cpdata.toArray()))

    def __UpdtItem2Hair(self, hairSys, arrayData):
        #debugPrint(arrayData)
        for item in arrayData:
            #debugPrint(item)
            cpdata = self.__CPDObjFromArray(item)
            self.__setHairSysParam(hairSys, cpdata)
            if len(cpdata.children) > 0:
                self.__UpdtItem2Hair(hairSys, cpdata.children)

    def UpdateHair(self, hairSys):
        self.__UpdtItem2Hair(hairSys, self.__arrayCPData)

    def Print(self):
        for item in self.__arrayCPData:
            debugPrint(str(item))
            debugPrint('-------------------------------')

    def ToString(self):
        string =  '[\"' + COPY_PASTE_KEY + '\",['
        for i in range(len(self.__arrayCPData)):
            if i > 0:
                string += ','
            string += self.CopyPasteData.arrayToString(self.__arrayCPData[i])
        string += ']]'
        return string
    #----------------------------------------------------
    #----------------------------------------------------

#----------------------------------------
#----------------------------------------
#---------------INTERFACE----------------
#----------------------------------------
#----------------------------------------
class hairmgrplusPanel:
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "particle"
    bl_options = {'DEFAULT_CLOSED'}

#----------------------------------------
#------------OT--------------------------
#----------------------------------------
class HAIRMGRPLUS_OT_force_enable_adv(bpy.types.Operator):
    bl_idname = "hairmgrplus.force_enable_adv"
    bl_label = "TOGGLE ENABLE ADVANCED HAIR"

    @classmethod
    def poll(cls, context):
        return IsParticleSelected(context)

    def execute(self, context):
        settings = context.selected_objects[0].particle_systems.active.settings
        settings.use_advanced_hair = not settings.use_advanced_hair

        return {'FINISHED'}

class HAIRMGRPLUS_OT_create_hair_sys(bpy.types.Operator):
    bl_idname = "hairmgrplus.create_hair_sys"
    bl_label = "Create Hair System"

    @classmethod
    def poll(cls, context):
        var_return = True
        if len(context.selected_objects) == 0:
            var_return = False
        elif getImpCol(context) is None:
            var_return = False
        elif len(getImpCol(context).all_objects.items()) == 0:
            var_return = False

        return var_return

    def execute(self, context):
        self.obj = context.object

        importCol = getImpCol(context)
        filteredCol = []

        for obj in importCol.all_objects.items():
            if obj[1].type == 'CURVE':
                filteredCol.append(obj[1])

        if len(filteredCol) == 0:
            print('Objects need to be of the type = CURVE')
            return {'CANCELLED'}

        pointsCount = 0
        for obj in filteredCol:
            bezier_pts = obj.data.splines.items()[0][1].bezier_points.items()
            if len(bezier_pts) > pointsCount:
                pointsCount = len(bezier_pts)

        partSystem = Import.createHairSystem(context, importCol.name, len(filteredCol))

        partSystem.particle_system.settings.hair_step = pointsCount - 1

        return {'FINISHED'}

class HAIRMGRPLUS_OT_test_calc(bpy.types.Operator):
    bl_idname = "hairmgrplus.test_calc"
    bl_label = "Test Calc"

    @classmethod
    def poll(cls, context):
        var_return = True
        if len(context.selected_objects) == 0:
            var_return = False
        elif getImpCol(context) is None:
            var_return = False
        elif len(getImpCol(context).all_objects.items()) == 0:
            var_return = False

        return var_return

    def execute(self, context):
        self.obj = context.object

        hairSys = context.selected_objects[0].particle_systems[-1]

        #print(dir(hairSys))
        #SetRandomHairPos(hairSys, context)
        Import.printHairKey(context)
        #ExportData(hairSys, context)
        return {'FINISHED'}

class HAIRMGRPLUS_OT_random_pos(bpy.types.Operator):
    bl_idname = "hairmgrplus.random_pos"
    bl_label = "Random Pos"

    @classmethod
    def poll(cls, context):
        var_return = True
        if len(context.selected_objects) == 0:
            var_return = False
        elif getImpCol(context) is None:
            var_return = False
        elif len(getImpCol(context).all_objects.items()) == 0:
            var_return = False

        return var_return

    def execute(self, context):
        self.obj = context.object

        hairSys = context.selected_objects[0].particle_systems[-1]

        #print(dir(hairSys))
        Import.SetRandomHairPos(hairSys, context)
        #Import.printHairKey(context)
        #ExportData(hairSys, context)
        return {'FINISHED'}

class HAIRMGRPLUS_OT_import_from_curves(bpy.types.Operator):
    bl_idname = "hairmgrplus.import_from_curves"
    bl_label = "Import from Curves"

    @classmethod
    def poll(cls, context):
        var_return = True
        if len(context.selected_objects) == 0:
            var_return = False
        elif getImpCol(context) is None:
            var_return = False
        elif len(getImpCol(context).all_objects.items()) == 0:
            var_return = False

        return var_return

    def execute(self, context):
        self.obj = context.object

        importCol = getImpCol(context)
        filteredCol = []

        for obj in importCol.all_objects.items():
            if obj[1].type == 'CURVE':
                filteredCol.append(obj[1])

        if len(filteredCol) == 0:
            print('Objects need to be of the type = CURVE')
            return {'CANCELLED'}

        hairSys = context.selected_objects[0].particle_systems[-1]

        #print(dir(hairSys))
        Import.Curves2Hair(filteredCol, hairSys, context)

        return {'FINISHED'}

class HAIRMGRPLUS_OT_export(bpy.types.Operator):
    bl_idname = "hairmgrplus.export"
    bl_label = "Export"

    export_type: bpy.props.StringProperty()

    @classmethod
    def poll(cls, context):
        var_return = True
        if not IsParticleSelected(context):
            var_return = False
        elif getExpCol(context) is None:
            var_return = False

        return var_return

    def execute(self, context):
        self.obj = context.object

        bpy.ops.particle.particle_edit_toggle()
        bpy.ops.particle.particle_edit_toggle()

        if len(context.selected_objects[0].particle_systems.active.particles.items()) == 0:
            print('Particle system has no hairs')
            return {'CANCELLED'}

        #the .co fields on the hair_keys won't be loaded unless evaluated before
        #--------------------------------------------
        eval_ob = evaluateObj(context.selected_objects[0].name, context)
        #--------------------------------------------

        if self.export_type == 'CURVE':
            Export.Hair2Curves(eval_ob.particle_systems.active, getExpCol(context), context)
        elif self.export_type == 'POLY':
            Export.Hair2Poly(eval_ob.particle_systems.active, getExpCol(context), context)

        return {'FINISHED'}

#----------------------------------------a
#--------COPY/PASTE PARAMETERS-----------
#----------------------------------------
class HAIRMGRPLUS_OT_copy_parameters(bpy.types.Operator):
    bl_idname = "hairmgrplus.copy_parameters"
    bl_label = "COPY PARAMETERS"

    parameter_copy: bpy.props.StringProperty()

    @classmethod
    def poll(cls, context):
        return IsParticleSelected(context)

    def execute(self, context):
        #debugPrint(self.parameter_copy)
        hairSys = context.selected_objects[0].particle_systems.active

        copyData = HMGRPCopyPasteType()

        if self.parameter_copy == 'ALL':
            all = []

            for pp in prop_all:
                for pp2 in pp[1]:
                    all.append(pp2)

            copyData.Load(all, hairSys)
        else:
            index = int(self.parameter_copy)
            copyData.Load(prop_all[index][1], hairSys)
        #copyData.Print()
        setClipBoard(copyData.ToString())

        return {'FINISHED'}

class HAIRMGRPLUS_OT_paste_parameters(bpy.types.Operator):
    bl_idname = "hairmgrplus.paste_parameters"
    bl_label = "PASTE PARAMETERS"

    @classmethod
    def poll(cls, context):
        return IsParticleSelected(context)

    def execute(self, context):
        data = getClipBoard()
        hairSys = context.selected_objects[0].particle_systems.active

        copyData = HMGRPCopyPasteType(data)
        copyData.UpdateHair(hairSys)

        return {'FINISHED'}

#----------------------------------------
#------------PT--------------------------
#----------------------------------------

class HAIRMGRPLUS_PT_panel(hairmgrplusPanel, bpy.types.Panel):
    bl_label = "Hair Manager Plus"
    #bl_owner_id = "HAIRMGRPLUS_PT_panel"
    bl_options = {'DEFAULT_CLOSED'}

    def draw(self, context):
        layout = self.layout

        row = layout.row()

class HAIRMGRPLUS_PT_manager(hairmgrplusPanel, bpy.types.Panel):
    bl_label =  "Management Panel"
    bl_parent_id = "HAIRMGRPLUS_PT_panel"
    bl_options = {'DEFAULT_CLOSED'}

    def draw(self, context):
        layout = self.layout

        #box = layout.box()

        row = layout.row()
        row.operator("hairmgrplus.force_enable_adv")

        layout.separator()
        layout.separator()

        row = layout.row()
        row.operator("hairmgrplus.paste_parameters", text="PASTE PARAMETERS")

        layout.separator()

        row = layout.row()
        row.operator("hairmgrplus.copy_parameters", text="COPY PARAMETERS").parameter_copy = "ALL"

        for index in range(len(prop_all)):
            label = 'COPY - ' + prop_all[index][0]

            row = layout.row()
            row.operator("hairmgrplus.copy_parameters", text=label).parameter_copy = str(index)

class HAIRMGRPLUS_PT_import_curves(hairmgrplusPanel, bpy.types.Panel):
    bl_label = "Import Curves"
    bl_parent_id = "HAIRMGRPLUS_PT_panel"
    bl_options = {'DEFAULT_CLOSED'}

    def draw(self, context):
        self.obj = context.object
        layout = self.layout

        row = layout.row()
        row.label(text = "DOES NOT WORK")

        row = layout.row()
        row.prop(getObjLocal(context), 'hamgpImportColl', text = "Import Col.")

        row = layout.row()
        row.operator("hairmgrplus.create_hair_sys", text="Create Hair")

        row = layout.row()
        row.operator("hairmgrplus.test_calc", text="Test Transf. Matrix")

        row = layout.row()
        row.operator("hairmgrplus.random_pos", text="Random Pos")

        row = layout.row()
        row.operator("hairmgrplus.import_from_curves", text="Import from Curves")

        row = layout.row()

class HAIRMGRPLUS_PT_export_curves(hairmgrplusPanel, bpy.types.Panel):
    bl_label = "Export Curves"
    bl_parent_id = 'HAIRMGRPLUS_PT_panel'
    bl_options = {'DEFAULT_CLOSED'}

    def draw(self, context):
        self.obj = context.object
        layout = self.layout

        row = layout.row()
        row.label(text = "KINDA OFF WORK")

        #box = layout.box()
        row = layout.row()
        row.prop(getObjLocal(context), 'hamgpExportColl', text = "Export Col.")

        row = layout.row()
        button = row.operator("hairmgrplus.export", text="Export to Curves")
        button.export_type = "CURVE"

        #row = layout.row()
        #button = row.operator("hairmgrplus.export", text="Export to Poly")
        #button.export_type =  "POLY"

#----------------------------------------
#----------------------------------------
#----------------------------------------

#----------------------------------------
#----------------REGISTER----------------
#----------------------------------------
classes = (
    HAIRMGRPLUS_PT_panel
    , HAIRMGRPLUS_OT_force_enable_adv
    , HAIRMGRPLUS_OT_copy_parameters
    , HAIRMGRPLUS_OT_paste_parameters
    , HAIRMGRPLUS_OT_create_hair_sys
    , HAIRMGRPLUS_OT_test_calc
    , HAIRMGRPLUS_OT_random_pos
    , HAIRMGRPLUS_OT_import_from_curves
    , HAIRMGRPLUS_OT_export
    , HAIRMGRPLUS_PT_manager
    , HAIRMGRPLUS_PT_import_curves
    , HAIRMGRPLUS_PT_export_curves
)

def register():
    for cls in classes:
        bpy.utils.register_class(cls)

def unregister():
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)

if __name__ == '__main__':
    register()


# encoding:utf-8
__author__ = "Wyatt Huang"

import os
import logSystem
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
import setting
from airtest.core.api import auto_setup
from airtest.cli.parser import cli_setup
import time

# initialize logSystem
log = logSystem.createLog()
log.BEGIN()
log.LOG('begin running')

def endPorgram():
    print('end the program')
    os._exit(0)

# Connect the Android Stimulator and start WeChat
try:
    log.LOG('begin connect android stimulator...')
    if not cli_setup():
        auto_setup(__file__, logdir=True, devices=[
                "Android://127.0.0.1:5037/127.0.0.1:7555?cap_method=JAVACAP&&ori_method=ADBORI",
        ])

    poco = AndroidUiautomationPoco()
    #poco.device.wake()
    #poco(text='微信').click()
except Exception as e:
    log.EXCEPTION(e)
    endPorgram()

# Set the setting item
group_name = input('\ngroup name: ')
update_frequency = float(input('update frequency: '))
log.LOG('Setting Information: \nGroup Name: ' + group_name +
      '\nUpdate Frequency: ' + str(update_frequency) + '\n')

get_into_group = 0
group = poco('com.tencent.mm:id/baj') # group hook in WeChat

for each_group in group:
    if each_group.get_text() == group_name:
        each_group.click()
        get_into_group = 1

if not get_into_group:
    log.EXCEPTION('cannot find group')
    endPorgram()
else:
    log.LOG('successfully get into the group !')

def is_bao_exist():
    try:
        return not poco("android.widget.RelativeLayout").offspring("com.tencent.mm:id/aui")[-1].offspring("com.tencent.mm:id/aul").exists()
    except Exception:
        return 0

def catch_bao(poco_element):
    poco_element.click()
    if poco('com.tencent.mm:id/dam').get_text() == '手慢了，红包派完了':
        poco('com.tencent.mm:id/d84').click()
        return 0
    else:
        poco('com.tencent.mm:id/dan').click()
        if poco('com.tencent.mm:id/d6v').exists():
            return float(poco('com.tencent.mm:id/d62').get_text())

print('\nBegin supervice the Red Envelop...')
log.LOG('supervisor start successfully')

def begin_supervise():
    while (True):
        time.sleep(update_frequency)
        #if poco('com.tencent.mm:id/auk').exists():
        if is_bao_exist():
            status = catch_bao(poco('com.tencent.mm:id/auk')[-1])
            if status == 0:
                print('Fail to get Envelop\n')
                log.LOG('fail to get Envelop')
            else:
                try:
                    print('Win: ' + str(status))
                    log.LOG('Win: ' + str(status))
                    setting.addMoney(float(status))
                    print('Total Win: ' + str(setting.get_money()) + '\n')
                except Exception as e:
                    log.WARMING('setting function cannot be accessed')
                    continue
                poco('com.tencent.mm:id/m1').click()

try:
    begin_supervise()
except Exception as e:
    log.EXCEPTION('supervisor break because: ' + str(e))
    endPorgram()


#!/usr/bin/python3
# -*- coding: UTF-8 -*-

import numpy as np
import MySQLdb
import base64
import sys

if __name__ == '__main__':
    feature = np.array([1.0, 2.0, 3.0])
    print(feature)
    print(feature.dtype)

    try:
        db = MySQLdb.connect("192.168.23.71", "root", "tysxwg07", "test", charset='utf8' )

        # 使用cursor()方法获取操作游标
        cursor = db.cursor()

        # 使用execute方法执行SQL语句
        cursor.execute("SELECT VERSION()")

        # 使用 fetchone() 方法获取一条数据
        data = cursor.fetchone()

        print("Database version : %s " % data)

        bytes_feature = feature.tostring()
        print(bytes_feature)
        #cursor.execute('insert into testblob values (%s, "%s")' % (2, bytes.decode(data)))
        cursor.execute('insert into testblob values (%s, %s)', (2, bytes_feature))

        db.commit()

        cursor.execute('select feature from testblob where framenum = %s' % (2))
        values = cursor.fetchall()

        print(values)
        feature = np.frombuffer(values[0][0], dtype=np.float64) #np.float32
        print(feature)

        # 关闭数据库连接
        db.close()
    except Exception as e:
        print("Exception: ", e);
        sys.exit(1)


from django.urls import path
from . import views

app_name = "admin01"

urlpatterns = [
	path('home/', views.home),
	path('add_category/',views.add_category,name='add_category'),
	path('carousal_control/',views.carousal_control)
]


import socket
import struct
import sys

MULTICAST = "224.1.1.1"
PORT = 5005

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)

sock.bind((MULTICAST,PORT))

group = socket.inet_aton(MULTICAST)
mreq = struct.pack('4sL', group, socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

while True:
    data=sock.recv(1024)
    uid, message = data[0:6].decode(), data[6:].decode()
    print(message)


# https://app.diagrams.net/?page-id=QK2SJbzOO3gyF4ZiwVJe#G1eKp2W5wpHgpv28qTq0SMU-f0MtLq0pst
# 5. Вывести на экран коды и символы таблицы ASCII, начиная с символа под номером 32 и заканчивая 127-м включительно.
# Вывод выполнить в табличной форме: по десять пар "код-символ" в каждой строке.

def show_ascii(text='', num=32, i=0):
    if num == 127:
        return text
    else:
        if i == 10:
            i = 0
            return show_ascii(text + '\n', num + 1, i + 1)
        else:
            return show_ascii(text + str(num) + '-' + chr(num) + ' ', num + 1, i + 1)
print(show_ascii())


# -*- coding: utf-8 -*-
"""
Created on Fri Mar 13 16:58:10 2020

@author: pierr
"""

import numpy as np
from matplotlib import pyplot as plt
import matplotlib
import math

#==============================================================================
#                  Expérience 1
#==============================================================================

#FAIRE EN LOGARITHMIQUE
#ou alors plot en fonction de la surtension, voire faire des droites de tafel

Resistance = np.array([0,0.1,0.33,1,3.3,10,33,100,330,1000000]) #10000=infini
voltage    = np.array([0.065,0.169,0.433,1.34,3.17,3.51,3.66,3.7,3.71,3.72])
courant    = np.array([0.,0.,0.,0.,0.2,0.79,1.03,1.10,1.13,1.14]) #en mA
courant    = courant * 10**(-3) #en Amperes
#print(courant)

def ButlerVolmer(surtension):
    T = 20.+273.15 #température du labo en Kelvin
    z = 2.         #electrons echanges
    R = 8.314
    F = 96500.

    facteur = z*F*surtension / (R*T)
    terme1 = np.exp( 0.5 * facteur)
    terme2 = np.exp(-0.5 * facteur)

    return (terme1 - terme2)

Evaluation = ButlerVolmer(voltage-1.23)
print(Evaluation)

A = np.dot(Evaluation,courant)
B = np.dot(courant,courant)
print(A)
print(B)

print(A/B)

plt.figure("1")
plt.title("Evolution de l'intensité en fonction du voltage")
plt.plot(courant,voltage-1.23,'o-',color='red')
plt.xlabel('Intensité [mA]')
plt.ylabel('Surtension [V]')

surtension = voltage - 1.23
print(surtension)

plt.figure("1bis")
plt.title("Sous forme Butler-Volmer")
plt.plot(surtension,np.log(courant),'o-',color='red')
plt.xlabel('surtension')
plt.ylabel('courant')
#plt.xlim(-3., 3)

#==============================================================================
#                  Expérience 2
#==============================================================================
#faire en log askip

Temps         = np.linspace(25,225,9)
VolumeProduit = np.array([5,10,15,21,26,31,36,41,47])

plt.figure("2")
plt.title("Evolution du volume de H2 produit en fonction du temps")
plt.plot(Temps,VolumeProduit,'o-',color='red')
plt.xlabel('Temps [sec]')
plt.ylabel('Volume produit [cm³(?)]')

#==============================================================================
#                  Expérience 3
#==============================================================================

Voltage = np.array([0.006,0.008,0.015,0.03,0.10,0.30,0.58,0.66,0.71,0.74])
Courant = np.array([0.03,0.03,0.03,0.03,0.03,0.03,0.02,0.,0.,0.])

plt.figure("3")
plt.title("Evolution du potentiel dans la cellule en fonction du courant")
plt.plot(Courant,Voltage,'o-',color='red')
plt.xlabel('Courant [mA]')
plt.ylabel('Voltage [mV]')

#==============================================================================
#                  Expérience 4
#==============================================================================

Temps  = np.linspace(25,1000,40)
Volume = np.array([0.03,0.03,0.03,0.03,0.03,0.03,0.02,0.,0.,0.])

#matplotlib.rcParams['toolbar'] = 'None'
#plt.rcParams['figure.facecolor'] = 'None'
'''
plt.figure("4")
plt.title("Consommatiuon du volume de H2 en fonction du temps")
plt.plot(Courant,Voltage,'-r')
plt.xlabel('Courant [mA]')
plt.ylabel('Voltage [mV]')
'''

#==============================================================================
#                  Butler-Volmer théorique
#==============================================================================

def ButlerVolmer(I0,alpha,surtension):
    T = 20.+273.15 #température du labo en Kelvin
    z = 2.         #electrons echanges
    R = 8.314
    F = 96500.

    facteur = z*F*surtension / (R*T)
    terme1 = np.exp( (1-alpha) * facteur)
    terme2 = np.exp(   -alpha  * facteur)

    return I0 * (terme1 - terme2)

surtension = np.linspace(0.,2.,1000)
I0         = 45.92 #10**(-3.6)*20  #on a 20 cm² avec Platine
alpha      = 0.5   #valeur à trouver
CourantTheorique = ButlerVolmer(I0,alpha,surtension)

plt.figure("1bisbis")
plt.title("Sous forme Butler-Volmer théorique")
plt.plot(surtension,CourantTheorique,color='red')
plt.xlabel('surtension')
plt.ylabel('log courant théorique')

#plt.show()


#Create an empty team dictionary to store all entered players and their scores
team = {}
#Create a new txt file to write the results to with display summary function
outFile = open('./game_results.txt', 'w')

#function to create data structure of names and scores in the team dictionary
def bowling_team(data):
    splitData = data.split()
    team[splitData[0]] = int(splitData[1])
    return team

#function to sort players in the order they were entered
def entered_team(team):
    print("\n===== Listed by Entry =====")
    outFile.write("\n===== Listed by Entry =====")
    for player in team:
        if team[player] == 300:
            print("\t*"+player+"\t\t"+str(team[player]))
            outFile.write("\n*"+player+"\t\t"+str(team[player]))
        else:
            print("\t"+player+"\t\t"+str(team[player]))
            outFile.write("\n"+player+"\t\t"+str(team[player]))

#function to sort the team by their score
def sort_team(team):
    top_score = sorted(team.items(), key=lambda kv: kv[1])
    top_score.reverse()
    print("\n===== Listed by Top Scorer =====")
    outFile.write("\n===== Listed by Top Scorer =====")
    highest_scorer = top_score[0][0]
    highest_score = top_score[0][1]
    for player in top_score:
        if player[1] == 300:
            print("\t*"+player[0] +"\t\t"+str(player[1]))
            outFile.write("\n*"+player[0] +"\t\t"+str(player[1]))
        else:
            print("\t"+player[0] +"\t\t"+str(player[1]))
            outFile.write("\n"+player[0] +"\t\t"+str(player[1]))
    return highest_score, highest_scorer

#function to alphabetize the players
def alpha_team(team):
    print("\n===== Listed Alphabetically =====")
    outFile.write("\n===== Listed Alphabetically =====")
    for player, score in sorted(team.items()):
        if score == 300:
            print("\t*"+player+"\t\t"+str(score))
            outFile.write("\n*"+player+"\t\t"+str(score))
        else:
            print("\t"+player+"\t\t"+str(score))
            outFile.write("\n"+player+"\t\t"+str(score))

#function to show the results of all function above
def display_summary(team):
    top_score = sorted(team.items(), key=lambda kv: kv[1])
    lowest_scorer = top_score[0][0]
    lowest_score = top_score[0][1]
    top_score.reverse()
    highest_scorer = top_score[0][0]
    highest_score = top_score[0][1]

    print("\nCongratulations "+ highest_scorer +"! You were the top score at "+str(highest_score)+"!")
    outFile.write("\nCongratulations "+ highest_scorer +"! You were the top score at "+str(highest_score)+"!")
    print("Sorry "+ lowest_scorer +", you were the lowest score at "+str(lowest_score)+". Keep practicing!")
    outFile.write("\nSorry "+ lowest_scorer +", you were the lowest score at "+str(lowest_score)+". Keep practicing!")
    sum = 0
    for player in top_score:
        sum = sum + player[1]

    avg = sum // len(team)
    print("\nThe average score for the team is: "+str(avg))
    outFile.write("\nThe average score for the team is: "+str(avg))

    return highest_score, highest_scorer, lowest_score, lowest_scorer

#First prompt that the User sees to know that they enter a name and a score
data = input('Enter the name of the player and their score separated by space i.e. John 280 >> ')
#Loop the prompt to allow them to enter as many players as they want, end with enter key
while data != '':
    bowling_team(data)
    data = input('Enter the name of the player and their score (End entry with "Enter")>> ')

#Call all defined functions to sort them into their individual needs and then finally display the summary from each function
entered_team(team)
sort_team(team)
alpha_team(team)
display_summary(team)

outFile.close()


from django.shortcuts import render, redirect
import subprocess
from subprocess import Popen
from backend.models import Website, WebsiteList
from backend.functions import get_site_list, get_current_sites, find_average, process_go_line, get_tone_words_hashmap

"""
Function is invoked whenever the root url is visited
It will give the user an option to either search for a word or add a new url to search
"""
def main_view(request):

    # getting the list of urls for the particular user (first for now)
    master_list = WebsiteList.objects.first()
    sites = get_current_sites(master_list)
    average = 0
    was_search = False

    # either a search was made or a url was added. Each are handled separately
    if request.method == 'POST':

        search_word = request.POST.get('search_word', False)
        url_to_add = request.POST.get('new_url', False)

        # if search was made, we run the golang code and process each output line to store the wordcount for each site
        if search_word:
            was_search = True
            site_list = get_site_list(sites)

            # runs the go executable found in golang directory
            # parameters are the search word and a list of all urls to search (each one separated by a comma)
            go_pipe = Popen(['./golang/main', str(search_word), site_list], stdout=subprocess.PIPE)
            go_pipe.wait()

            for line in go_pipe.stdout:
                process_go_line(line, master_list)

            go_pipe.terminate()

        # a url needs to be added to the master_list for the use
        elif url_to_add:

            if not Website.objects.filter(list=master_list, url=url_to_add).exists():
                new_website = Website(list=master_list, url=url_to_add)
                new_website.save()

        sites = master_list.website_set.all()

        # here we order the sites by search word frequency and calculate the average
        sites = sites.order_by('count')
        sites = sites.reverse()
        average = find_average(sites)

    # we render the page index.html with the parameters in the dictionary
    return render(request, 'index.html', {'sites': sites, 'average': average, 'was_search': was_search})

"""
Function is invoked whenever the /tone url is visited.
This function will calculate the tone score of each site the user currently has in their WebsiteList and will
return the sites in a sorted order
"""
def tone_view(request):
    tone_words= get_tone_words_hashmap()
    master_list = WebsiteList.objects.first()
    sites = get_current_sites(master_list)
    site_list = get_site_list(sites)
    #   key map holds urls as keys and scores as values
    score_map = {}
    for site in sites:
        score_map[site.url] = 0
    # search for the term "key" in the list of sites
    # for each site's frequency of that term, multiply that frequency by tone_words[key]
    # and add the product to that site's score in score_map
    for key in tone_words:
        go_pipe = Popen(['./golang/main', key, site_list], stdout=subprocess.PIPE)
        go_pipe.wait()
        for line in go_pipe.stdout:
            line = line.decode("utf-8")
            results = line.split(',')
            url_searched = results[0]  # the url
            url_searched = url_searched[1:-1]
            if Website.objects.filter(list=master_list, url=url_searched).exists():
                word_count = int(results[1])  # the frequency for that url
                weighted_word_count = word_count*tone_words[key]
                score_map[url_searched] += weighted_word_count
    #   round scores
    for site in sites:
        score_map[site.url] = round(score_map[site.url], 2)

    # sort results
    ordered_values = sorted(score_map.values())
    ordered_values.reverse()

    # get results in a zip array for displaying
    ordered_sites = list(sorted(score_map, key=score_map.__getitem__, reverse=True))
    results = zip(ordered_sites, ordered_values)
    return render(request, 'tone.html', {'map': score_map, 'results': results})

"""
View is invoked when /delete/(id) is visited
The view will delete the url that was clicked on and reroute back to the home page
"""
def delete_url_view(request, id):
    id_to_delete = int(id)
    site_to_delete = Website.objects.get(id=id_to_delete)
    site_to_delete.delete()
    return redirect('/')


import os
import yaml
import pytest
import reseasdk
import subprocess

@pytest.fixture(scope='session')
def package(request):
    """ Creates a package named sandbox. """

    if not os.path.exists('sandbox'):
        # XXX: just for me :D
        try:
            output = subprocess.check_output(
                ['git', 'config', '--get', 'user.email'])
            email = output.decode('ascii').strip()
        except subprocess.CalledProcessError:
            email = ''

        if email == 'nuta@seiya.me':
            uri = 'git@github.com:resea/resea'
        else:
            uri = 'https://github.com/resea/resea'

        subprocess.check_call(['git', 'clone', uri, 'sandbox'])

    os.chdir('sandbox')

    if not os.path.exists('sandbox'):
        reseasdk.main(['new', 'sandbox'])

    packages_yml = yaml.load(open('packages.yml'))
    packages_yml['packages']['sandbox'] = {'path': 'sandbox'}
    yaml.dump(packages_yml, open('packages.yml', 'w'))

    os.chdir('sandbox')

    package_yml = yaml.load(open('package.yml'))
    package_yml['category'] = 'application'
    package_yml['requires'] = ['core']
    yaml.dump(package_yml, open('package.yml', 'w'))

    build_yml = {
        'objs': ['src/startup.o'],
        'test_objs': ['src/test.o'],
        'testable': True
    }
    yaml.dump(build_yml, open('build.yml', 'w'))

    open('src/startup.c', 'w').write("""\
#include <resea.h>

void sandbox_startup(void){

  INFO("Hello, World!");
//FIXME  for(;;);
}
""")

    open('src/test.c', 'w').write("""\
#include <resea.h>

void sandbox_test(void){

  TEST_EXPECT(123 == 124-1);
}
""")

    def fin():
        os.chdir('../..')
    request.addfinalizer(fin)


import torch.nn as nn
import torch.nn.functional as F

class FocalLoss(nn.Module):
    """
    Modified from: https://www.kaggle.com/c/human-protein-atlas-image-classification/discussion/78109
    Put reduction in...
    """
    def __init__(self, gamma=2):
        super().__init__()
        self.gamma = gamma

    def forward(self, logit, target, reduction='mean'):
        target = target.float()
        max_val = (-logit).clamp(min=0)
        loss = logit - logit * target + max_val + ((-max_val).exp() + (-logit - max_val).exp()).log()

        invprobs = F.logsigmoid(-logit * (target * 2.0 - 1.0))
        loss = (invprobs * self.gamma).exp() * loss
        if len(loss.size())==2: loss = loss.sum(dim=1) # This is for multilabel. Loss can be a 2d array.

        if reduction=='mean': return loss.mean()
        elif reduction=='sum': return loss.sum()
        return loss

class FocalLoss_1(nn.Module):
    """
    # Source: https://www.kaggle.com/c/human-protein-atlas-image-classification/discussion/78109
    """
    def __init__(self, gamma=2):
        super().__init__()
        self.gamma = gamma

    def forward(self, logit, target):
        target = target.float()
        max_val = (-logit).clamp(min=0)
        loss = logit - logit * target + max_val + \
               ((-max_val).exp() + (-logit - max_val).exp()).log()

        invprobs = F.logsigmoid(-logit * (target * 2.0 - 1.0))
        loss = (invprobs * self.gamma).exp() * loss
        if len(loss.size())==2: ## Don't know what is this??!!
            loss = loss.sum(dim=1)
        return loss.mean()

class FocalLoss_2(nn.Module):
    """
    # Source: ship detect competiton
    """
    def __init__(self, gamma):
        super().__init__()
        self.gamma = gamma

    def forward(self, input, target):
        if not (target.size() == input.size()):
            raise ValueError("Target size ({}) must be the same as input size ({})"
                             .format(target.size(), input.size()))

        max_val = (-input).clamp(min=0)
        loss = input - input * target + max_val + \
            ((-max_val).exp() + (-input - max_val).exp()).log()

        invprobs = F.logsigmoid(-input * (target * 2.0 - 1.0))
        loss = (invprobs * self.gamma).exp() * loss

        return loss.mean()

# Source: ship detect competiton
def dice_loss(input, target):
    input = F.sigmoid(input)
    smooth = 1.0

    iflat = input.view(-1)
    tflat = target.view(-1)
    intersection = (iflat * tflat).sum()

    return ((2.0 * intersection + smooth) / (iflat.sum() + tflat.sum() + smooth))


#
# Copyright (C) 2014 SINTEF <franck.fleurey@sintef.no>
#
# Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June 2007;
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# 	http://www.gnu.org/licenses/lgpl-3.0.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# -*-coding:Latin-1 -*

import sys
import re
class Tester:
	def create(self,inputString):
		testerFile = open('../tester.thingml', 'w')
		i=0

		testerFile.write('import "thingml.thingml"\n\n'+
			'//Input: '+inputString+'\n\n'+
			'thing Tester includes TestHarness, TimerClient\n{\n\tstatechart Tester init e0 {\n')

		for char in inputString:
			testerFile.write('\t\tstate e' +str(i)+' {\n'+
				'\t\t\ton entry timer!timer_start(10)\n'
				'\t\t\ttransition -> e'+str(i+1)+'\n'
				'\t\t\tevent timer?timer_timeout\n'
				"\t\t\taction test!testIn('\\'"+inputString[0]+"\\'')\n\t\t}\n")
			if (len(inputString) > 1):
				inputString=inputString[1:]
			i=i+1
		testerFile.write('\t\tstate e' +str(i)+' {\n'+
			'\t\t\ton entry timer!timer_start(250)\n'
			'\t\t\ttransition -> e'+str(i+1)+'\n'
			'\t\t\tevent timer?timer_timeout\n\t\t}\n')
		i=i+1
		testerFile.write('\t\tstate e' +str(i)+' {\n'+
		'\t\t\ton entry testEnd!testEnd()\n'
		'\t\t}\n\t}\n}')
		testerFile.close()
"""
for f in onlyfiles:
	match = re.match(r"(.*)\.thingml",f)
	if match is not None:
		name = re.sub(r"(.*)\.thingml",r"\1",f)
		bigname = name[:0]+name[0].upper()+name[1:]
		print(bigname)
		fichier = open('_arduino/'+name+'.thingml', 'w')
		fichier.write('import "../core/_arduino/test.thingml"\n'+
		'import "../'+name+'.thingml"\n\n'+
		'configuration '+name+' {\n'+
		'    instance test : '+bigname+'\n'+
		'    group harness : TestHarnessArduino \n'+
		'    connector test.harness => harness.harness.test\n}')
"""


from lxml import html
import requests
from pprint import pprint

page = requests.get("http://www.fifa.com/worldcup/matches/")
tree = html.fromstring(page.content)

data = []

matches = tree.find_class('fi-mu fixture')
for match in matches:
    info_els = match.cssselect(".fi-mu__info")
    if len(info_els) == 0:
        continue
    info = info_els[0].text_content()

    home = match.cssselect(".home .fi-t__nText")[0].text_content()
    away = match.cssselect(".away .fi-t__nText")[0].text_content()

    if len(home) < 4 or len(away) < 4:
        continue

    data.append({
        "info": info,
        "home": home,
        "away": away
    })

print(len(data))


import numpy as np

with open('record.txt', 'r') as f:
    data = f.read().split(',')[:-1]

print(len(data))
# data = data[20:]
assert len(data) == 100

acc = np.zeros(100)
for n in range(100):
    acc[n] = float(data[n])

# acc[0] = -acc[0]
print(acc[acc<0.8])
print(acc.mean())
print(acc.std())


import os, sys, os.path as op
sys.path.insert(0, op.join(os.getenv('CITY_PATH'), 'src'))
import numpy as np
import logging
from scipy.cluster import hierarchy
from scipy.misc import imresize, imread
from .dbUtilities import bbox2roi, roi2bbox
from .helperDb import deleteCar, carField
from .helperKeys import getCalibration
from .helperImg import ReaderVideo
from scenes.lib.cvScrollZoomWindow import Window
from scenes.lib.homography import getFrameFlattening, getHfromPose
from scenes.lib.cache import PoseCache, MapsCache
from scenes.lib.warp import transformPoint
import cv2

def add_parsers(subparsers):
  labelAzimuthParser(subparsers)

class AzimuthWindow(Window):
  ''' Use Shift + left button to choose azimuth. '''

  def __init__(self, img, x, y, axis_x, axis_y, winsize=500):
    Window.__init__(self, img, winsize, name='azimuth', num_zoom_levels=2)
    self.is_just_a_suggestion = False  # Used to pick color.
    self.yaw = None
    self.selected = False
    self.x, self.y = self.image_to_zoomedimage_coords(x, y)
    self.axis_x = axis_x * self.get_zoom(self.zoom_level)
    self.axis_y = axis_y * self.get_zoom(self.zoom_level)

  def mouseHandler(self, event, x, y, flags, params):

    # Call navigation handler from the base class.
    Window.mouseHandler(self, event, x, y, flags, params)

    # Display and maybe select azimuth.
    #   flags == 16 <=> Shift + no mouse press
    #   flags == 17 <=> Shift + left button down
    if (event == cv2.EVENT_MOUSEMOVE and flags == 16 or
        event == cv2.EVENT_LBUTTONDOWN and flags == 17):
      logging.debug('%s: registered shift + mouse move and maybe press.' % self.name)
      self.is_just_a_suggestion = False
      # 0 is north, 90 is west.
      self.yaw = (- np.arctan2((x - self.x) / self.axis_x,
                              -(y - self.y) / self.axis_y) * 180. / np.pi) % 360
      logging.debug('%s, yaw is at %0.f' % (self.name, self.yaw))
      self.update_cached_zoomed_img()
      self.redraw()
      if event == cv2.EVENT_LBUTTONDOWN:
        self.selected = True
        logging.debug('%s: registered shift + mouse press.' % self.name)

  def update_cached_zoomed_img(self):
    Window.update_cached_zoomed_img(self)
    color = (255,0,0)
    cv2.ellipse(self.cached_zoomed_img,
        (int(self.x), int(self.y)), (int(self.axis_x * 0.6), int(self.axis_y * 0.6)),
        startAngle=0, endAngle=360, angle=0, color=color, thickness=2)
    if self.yaw:
      y1 = self.y - self.axis_y * np.cos(self.yaw * np.pi / 180.) * 1.2
      x1 = self.x + self.axis_x * np.sin(self.yaw * np.pi / 180.) * 1.2
      cv2.arrowedLine(self.cached_zoomed_img,
          (int(self.x),int(self.y)), (int(x1),int(y1)), color=color, thickness=2)
      postfix = '(suggested by azimuth map)' if self.is_just_a_suggestion else ''
      cv2.putText(self.cached_zoomed_img, 'yaw %.0f %s' % (self.yaw, postfix), (10, 70),
          cv2.FONT_HERSHEY_SIMPLEX, 1., color, 2)

def _getFlatteningFromImagefile(poses, imagefile, y_frame, x_frame):
  H = getHfromPose(poses[imagefile])
  if H is not None:
    return getFrameFlattening(H, y_frame, x_frame)
  else:
    return 1

def _getAzimuthSuggestionFromMap(topdown_azimuths, poses, imagefile, y_frame, x_frame):

  def _crop(img, x, y, radius):
    ''' Crop with attention to the borders. '''
    y, x, radius = int(y), int(x), int(radius)
    min_x = max(0, x - radius)
    min_y = max(0, y - radius)
    center_x = x - min_x
    center_y = y - min_y
    max_x = min(img.shape[1], x + radius)
    max_y = min(img.shape[0], y + radius)
    crop = img[min_y:max_y, min_x:max_x]
    return crop, (center_x, center_y)

  def _getDistToPoint(img, x, y):
    X, Y = img.shape[1], img.shape[0]
    delta_x_1D = np.arange(X) - x
    delta_y_1D = np.arange(Y) - y
    delta_x = np.dot( np.ones((Y,1)), delta_x_1D[np.newaxis,:] ).astype(float)
    delta_y = np.dot( delta_y_1D[:,np.newaxis], np.ones((1,X)) ).astype(float)
    dist = np.sqrt(np.square(delta_x) + np.square(delta_y))
    return dist

  def _suggestionFromImage(arr, mask, x, y, pxls_in_meters):
    RADIUS_METERS = 2.
    radius = RADIUS_METERS * pxls_in_meter
    degree_threshold = 10.  # Degrees.
    # First crop to reduce computations.
    arr, _ = _crop(arr, x, y, radius)
    mask, (x, y) = _crop(mask, x, y, radius)
    # Flatten, apply the mask, and sort the array based on distance to (x, y).
    dist = _getDistToPoint(arr, x, y)
    dist_ind = dist[mask].argsort()
    if dist_ind.size == 0:
      return None
    sorted_arr = arr[mask][dist_ind]
    # Cluster based on degree.
    z = hierarchy.linkage(sorted_arr[:,np.newaxis])
    clusters = hierarchy.fcluster(z, 10., criterion="distance").tolist()
    elems = [clusters.index(i) for i in range(1,max(clusters)+1)]
    elems.sort()  # So that coord-wise closer points come first.
    suggestions = [sorted_arr[elem] for elem in elems]
    logging.info('Got suggestions %s from radius of %d pxl and threshold of %.0f deg.' %
       (str(suggestions), radius, degree_threshold))
    # # Debugging - show the cropped image.
    # X, Y = mask.shape[1], mask.shape[0]
    # coords_x = np.dot( np.ones((Y,1)), np.arange(X)[np.newaxis,:] )
    # coords_y = np.dot( np.arange(Y)[:,np.newaxis], np.ones((1,X)) )
    # display = arr.astype(np.uint8)
    # display[np.bitwise_not(mask)] = 0
    # cv2.circle(display, (int(x), int(y)), radius=3, color=(255,), thickness=2)
    # for elem in elems:
    #   x = coords_x[mask][dist_ind][elem]
    #   y = coords_y[mask][dist_ind][elem]
    #   cv2.circle(display, (int(x), int(y)), radius=2, color=(255,), thickness=1)
    #   print (x, y, sorted_arr[elem])
    # cv2.imshow('debug', display)
    # cv2.waitKey(-1)
    return suggestions

  azimuth_map, azimuth_mask = topdown_azimuths[imagefile]
  if azimuth_map is None:
    return None
  H = getHfromPose(poses[imagefile])
  if H is None:
    return None
  x_map, y_map = transformPoint(H, x_frame, y_frame)
  pose = poses[imagefile]
  pxls_in_meter = pose.map['pxls_in_meter'] if pose is not None else None
  suggestions = _suggestionFromImage(azimuth_map, azimuth_mask, x_map, y_map, pxls_in_meter)
  return suggestions

def labelAzimuthParser(subparsers):
  parser = subparsers.add_parser('labelAzimuth',
    description='''Go through cars and label yaw (azimuth)
    by either accepting one of the close yaw values from a map,
    or by assigning a value manually.''')
  parser.set_defaults(func=labelAzimuth)
  parser.add_argument('--display_scale', type=float, default=1.)
  parser.add_argument('--winsize', type=int, default=500)
  parser.add_argument('--shuffle', action='store_true')
  parser.add_argument('--car_constraint', default='1')

def labelAzimuth (c, args):
  logging.info ('==== labelAzimuth ====')

  image_reader = ReaderVideo()
  keys = getCalibration()

  c.execute('SELECT * FROM cars WHERE (%s)' % args.car_constraint)
  car_entries = c.fetchall()
  logging.info('Found %d objects in db.' % len(car_entries))
  if len(car_entries) == 0:
    return

  if args.shuffle:
    np.random.shuffle(car_entries)

  # Cached poses and azimuth maps.
  topdown_azimuths = MapsCache('topdown_azimuth')
  poses = PoseCache()

  button = 0
  index_car = 0
  another_car = True
  char_list = []
  while button != 27:
    go_next_car = False
    update_yaw_in_db = False

    if another_car:
      another_car = False
      suggestions = None
      i_suggestion = None

      logging.info(' ')
      logging.info('Car %d out of %d' % (index_car, len(car_entries)))
      car_entry = car_entries[index_car]
      carid     = carField(car_entry, 'id')
      bbox      = carField(car_entry, 'bbox')
      roi       = carField(car_entry, 'roi')
      imagefile = carField(car_entry, 'imagefile')
      # Update yaw inside the loop in case it was just assigned.
      c.execute('SELECT yaw FROM cars WHERE id=?', (carid,))
      yaw, = c.fetchone()

      y, x = roi[0] * 0.3 + roi[2] * 0.7, roi[1] * 0.5 + roi[3] * 0.5

      flattening = _getFlatteningFromImagefile(poses, imagefile, y, x)
      axis_x = np.linalg.norm(np.asarray(bbox[2:4]), ord=2)
      axis_y = axis_x * flattening

      display = image_reader.imread(imagefile)[:,:,::-1].copy()
      window = AzimuthWindow(display, x, y, axis_x, axis_y, winsize=args.winsize)
      if yaw is not None:
        logging.info('Yaw is: %.0f' % yaw)
        window.yaw = yaw
      else:
        suggestions = _getAzimuthSuggestionFromMap(topdown_azimuths, poses, imagefile, y, x)
        if suggestions is not None:
          i_suggestion = 0
          window.is_just_a_suggestion = True
          window.yaw = suggestions[i_suggestion]
      window.update_cached_zoomed_img()
      window.redraw()

    button = cv2.waitKey(50)

    if button == keys['del']:
      c.execute('UPDATE cars SET yaw=NULL WHERE id=?', (carid,))
      logging.info('Yaw is deleted.')
      go_next_car = True
      char_list = []

    # Space iterates between suggestions.
    if button == ord(' ') and suggestions is not None and len(suggestions) > 1:
      i_suggestion = (i_suggestion + 1) % len(suggestions)
      logging.info('Go to suggestion %d out of %d' % (i_suggestion, len(suggestions)))
      window.is_just_a_suggestion = True
      window.yaw = suggestions[i_suggestion]
      window.update_cached_zoomed_img()
      window.redraw()

    # Entry in keyboard.
    if button >= ord('0') and button <= ord('9') or button == ord('.'):
      char_list += chr(button)
      logging.debug('Added %s character to number and got %s' %
          (chr(button), ''.join(char_list)))
    # Enter accepts a Suggestion, GUI, or keyboard entry.
    elif button == 13:
      if char_list:  # After keyboard entry.
        number_str = ''.join(char_list)
        char_list = []
        try:
          logging.info('Accepting entry from the keyboard.')
          yaw = float(number_str)
          update_yaw_in_db = True
          go_next_car = True
        except ValueError:
          logging.warning('Could not convert entered %s to number.' % number_str)
          continue
      elif suggestions is not None:  # Accept a suggestion.
        logging.info('Accepting the suggestion.')
        yaw = window.yaw
        update_yaw_in_db = True
        go_next_car = True
      else:  # Just navigation.
        logging.info('A navigation Enter.')
        go_next_car = True
    # Entry in GUI.
    elif window.selected == True:
      logging.info('Accepting entry from GUI.')
      yaw = window.yaw
      update_yaw_in_db = True
      go_next_car = True
    # No entry:
    else:
      yaw = None

    # Entry happened one way or the other. Update the yaw and go to the next car.
    if update_yaw_in_db:
      c.execute('UPDATE cars SET yaw=? WHERE id=?', (yaw, carid))
      logging.info('Yaw is assigned to %.f' % yaw)

    # Navigation.
    if button == keys['left']:
      logging.debug ('prev car')
      if index_car > 0:
        index_car -= 1
        another_car = True
      else:
        logging.warning('Already at the first car.')
    elif button == keys['right'] or go_next_car == True:
      logging.debug ('next car')
      if index_car < len(car_entries) - 1:
        index_car += 1
        another_car = True
      else:
        logging.warning('Already at the last car. Press Esc to save and exit.')


import random

from discord.ext import commands
from math import ldexp, degrees, sqrt, sin, cos, tan, sinh, cosh, tanh

class Math(commands.Cog):

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

    @commands.command()
    async def roll(self, ctx, base=100):
        if base < 0:
            base = -base
        await ctx.send(random.randint(0, base))

    @commands.command()
    async def dice(self, ctx, times=1, sides=6):
        if times == 0 and sides == 0:
            await ctx.send('You can\'t roll 0')
        elif times < 0 and sides < 0:
            times = -times
            sides = -sides
            await ctx.send()
        else:
            await ctx.send()

    @commands.command()
    async def pow(self, ctx, base: int, exponent: int):
        # Not using math.pow() since it is vulnerable to not
        # responding on calculating large values

        try:
            answer = ldexp(base, exponent)
        except OverflowError:
            await ctx.send('Nuh uh, nice try. Math range error')
        except ValueError:
            await ctx.send('Nice try placing invalid characters')
        finally:
            await ctx.send(answer)

    @commands.command()
    async def trig(self, ctx, choice: str, x: float):
        if choice == 'sin':
            answer = (sin(x))
        elif choice == 'cos':
            answer = (cos(x))
        elif choice == 'tan':
            answer = (tan(x))
        elif choice == 'sinh':
            answer = (sinh(x))
        elif choice == 'cosh':
            answer = (cosh(x))
        elif choice == 'tanh':
            answer = (tanh(x))
        else:
            answer = 0
        deg = degrees(answer)
        await ctx.send(f'''
        ```
D: {deg}
R: {answer}```''')

    @commands.command()
    async def sqrt(self, ctx, number):
        await ctx.send(sqrt(number))

def setup(client):
    client.add_cog(Math(client))


from typing import Iterable, Union, Optional
from adam.ontology import IS_SPEAKER, IS_ADDRESSEE
from immutablecollections import immutableset
from adam.language.language_generator import LanguageGenerator
from adam.language.dependency import LinearizedDependencyTree
from adam.curriculum import InstanceGroup, GeneratedFromSituationsInstanceGroup
from adam.language_specific.english.english_language_generator import (
    GAILA_PHASE_1_LANGUAGE_GENERATOR,
    GAILA_PHASE_2_LANGUAGE_GENERATOR,
)
from adam.ontology import OntologyNode
from adam.ontology.phase1_ontology import (
    GROUND,
    INANIMATE_OBJECT,
    IS_BODY_PART,
    THING,
    LIQUID,
    LEARNER,
)
from adam.perception.developmental_primitive_perception import (
    DevelopmentalPrimitivePerceptionFrame,
)
from adam.perception.high_level_semantics_situation_to_developmental_primitive_perception import (
    GAILA_PHASE_1_PERCEPTION_GENERATOR,
    HighLevelSemanticsSituationToDevelopmentalPrimitivePerceptionGenerator,
)
from adam.random_utils import RandomChooser
from adam.situation.high_level_semantics_situation import HighLevelSemanticsSituation
from adam.situation.templates.phase1_templates import (
    object_variable,
    TemplatePropertyVariable,
    TemplateObjectVariable,
)

GROUND_OBJECT_TEMPLATE = object_variable("ground", GROUND)
PHASE1_CHOOSER_FACTORY = lambda: RandomChooser.for_seed(0)  # noqa: E731
PHASE1_TEST_CHOOSER_FACTORY = lambda: RandomChooser.for_seed(1)  # noqa: E731
Phase1InstanceGroup = InstanceGroup[  # pylint:disable=invalid-name
    HighLevelSemanticsSituation,
    LinearizedDependencyTree,
    DevelopmentalPrimitivePerceptionFrame,
]

def standard_object(
    debug_handle: str,
    root_node: OntologyNode = INANIMATE_OBJECT,
    *,
    required_properties: Iterable[OntologyNode] = tuple(),
    banned_properties: Iterable[OntologyNode] = immutableset(),
    added_properties: Iterable[
        Union[OntologyNode, TemplatePropertyVariable]
    ] = immutableset(),
    banned_ontology_types: Iterable[OntologyNode] = immutableset(),
) -> TemplateObjectVariable:
    """
    Preferred method of generating template objects as this automatically prevent liquids and
    body parts from object selection.
    """
    banned_properties_final = [IS_BODY_PART, LIQUID]
    banned_properties_final.extend(banned_properties)
    return object_variable(
        debug_handle=debug_handle,
        root_node=root_node,
        banned_properties=banned_properties_final,
        required_properties=required_properties,
        added_properties=added_properties,
        banned_ontology_types=banned_ontology_types,
    )

def body_part_object(
    debug_handle: str,
    root_node: OntologyNode = THING,
    *,
    required_properties: Iterable[OntologyNode] = tuple(),
    banned_properties: Iterable[OntologyNode] = immutableset(),
    added_properties: Iterable[
        Union[OntologyNode, TemplatePropertyVariable]
    ] = immutableset(),
) -> TemplateObjectVariable:
    """
    Method for generating template objects that are body parts.
    """
    required_properties_final = [IS_BODY_PART]
    required_properties_final.extend(required_properties)
    return object_variable(
        debug_handle=debug_handle,
        root_node=root_node,
        banned_properties=banned_properties,
        required_properties=required_properties_final,
        added_properties=added_properties,
    )

def phase1_instances(
    description: str,
    situations: Iterable[HighLevelSemanticsSituation],
    perception_generator: HighLevelSemanticsSituationToDevelopmentalPrimitivePerceptionGenerator = GAILA_PHASE_1_PERCEPTION_GENERATOR,
    language_generator: LanguageGenerator[
        HighLevelSemanticsSituation, LinearizedDependencyTree
    ] = GAILA_PHASE_1_LANGUAGE_GENERATOR,
) -> Phase1InstanceGroup:
    """
    Convenience method for more compactly creating sub-curricula for phase 1.
    """

    return GeneratedFromSituationsInstanceGroup(
        description,
        situations=situations,
        language_generator=language_generator,
        perception_generator=perception_generator,
        chooser=PHASE1_CHOOSER_FACTORY(),
    )

def phase2_instances(
    description: str,
    situations: Iterable[HighLevelSemanticsSituation],
    perception_generator: HighLevelSemanticsSituationToDevelopmentalPrimitivePerceptionGenerator = GAILA_PHASE_1_PERCEPTION_GENERATOR,
    language_generator: LanguageGenerator[
        HighLevelSemanticsSituation, LinearizedDependencyTree
    ] = GAILA_PHASE_2_LANGUAGE_GENERATOR,
) -> Phase1InstanceGroup:
    """
    Convenience method for more compactly creating sub-curricula for phase 2.
    """

    return GeneratedFromSituationsInstanceGroup(
        description,
        situations=situations,
        language_generator=language_generator,
        perception_generator=perception_generator,
        chooser=PHASE1_CHOOSER_FACTORY(),
    )

def make_background(
    salient: Iterable[TemplateObjectVariable],
    all_objects: Iterable[TemplateObjectVariable],
) -> Iterable[TemplateObjectVariable]:
    """
    Convenience method for determining which objects in the situation should be background objects
    """
    return immutableset(object_ for object_ in all_objects if object_ not in salient)

def make_noise_objects(noise_objects: Optional[int]) -> Iterable[TemplateObjectVariable]:
    return immutableset(
        standard_object(f"noise_object_{x}", banned_properties=[IS_SPEAKER, IS_ADDRESSEE])
        for x in range(noise_objects if noise_objects else 0)
    )

def learner_template_factory() -> TemplateObjectVariable:
    return standard_object("learner_factory", LEARNER)


#my first attempt screwed up so now I will start this over
inFile = open("url.txt")
outFile = open("url.dat", "w+") # for convenience, same file name, but different file extension
listDel = ['?expref=next-blog'] # we are gonna get rid of this line from the first url.txt file
for line in inFile:
	for word in listDel:
		line = line.replace(word, "")
	outFile.write(line)
inFile.close()
outFile.close()


"""Define automations for lighting."""
from itertools import chain
import voluptuous as vol

from appbase import AppBase, APP_SCHEMA
from color import color_temperature_to_rgb, color_temperature_kelvin_to_mired
from utils import config_validation as cv

class AreaLighting(AppBase):
    """Define a class for Area Lighting."""

    # pylint: disable=too-many-instance-attributes

    APP_SCHEMA = APP_SCHEMA.extend(
        {
            vol.Required("area"): str,
            vol.Required("motion_sensors"): cv.entity_ids,
            vol.Optional("delay_off", default=600): vol.All(
                vol.Coerce(int), vol.Range(min=1, max=3600)
            ),
            vol.Optional("lights"): cv.entity_ids,
            vol.Optional("lights_ct"): cv.entity_ids,
            vol.Optional("lights_rgb"): cv.entity_ids,
            vol.Optional("default_brightness", default=80): vol.All(
                vol.Coerce(int), vol.Range(min=1, max=100)
            ),
            vol.Optional("lux_sensor"): cv.entity_id,
            vol.Optional("lux_threshold", default=100): vol.Coerce(int),
            vol.Optional("sleep_lights"): cv.entity_ids,
            vol.Optional("sleep_lights_ct"): cv.entity_ids,
            vol.Optional("sleep_brightness"): vol.All(
                vol.Coerce(int), vol.Range(min=1, max=100)
            ),
            vol.Optional("circadian_sensor"): cv.entity_id,
            vol.Optional("min_brightness", default=1): vol.All(
                vol.Coerce(int), vol.Range(min=1, max=100)
            ),
            vol.Optional("max_brightness", default=100): vol.All(
                vol.Coerce(int), vol.Range(min=1, max=100)
            ),
            vol.Optional("min_colortemp", default=2500): vol.All(
                vol.Coerce(int), vol.Range(min=1000, max=12000)
            ),
            vol.Optional("max_colortemp", default=5500): vol.All(
                vol.Coerce(int), vol.Range(min=1000, max=12000)
            ),
            vol.Optional("transition", default=60): vol.All(
                vol.Coerce(int), vol.Range(min=1, max=3600)
            ),
            vol.Optional("update_interval", default=300): vol.All(
                vol.Coerce(int), vol.Range(min=1, max=3600)
            ),
        }
    )

    def configure(self) -> None:
        """Configure."""
        self.area_id = self.args["area"]
        self.motion_sensors = self.args["motion_sensors"]
        self.delay_off = self.args.get("delay_off")
        self.lights = self.args.get("lights")
        self.lights_ct = self.args.get("lights_ct")
        self.lights_rgb = self.args.get("lights_rgb")
        self.default_brightness = self.args.get("default_brightness")
        self.lux_sensor = self.args.get("lux_sensor")
        self.lux_threshold = self.args.get("lux_threshold")
        self.sleep_lights = self.args.get("sleep_lights")
        self.sleep_lights_ct = self.args.get("sleep_lights_ct")
        self.sleep_brightness = self.args.get("sleep_brightness")
        self.circadian_sensor = self.args.get("circadian_sensor")
        self.min_brightness = self.args.get("min_brightness")
        self.max_brightness = self.args.get("max_brightness")
        self.min_colortemp = self.args.get("min_colortemp")
        self.max_colortemp = self.args.get("max_colortemp")
        self.transition = self.args.get("transition")
        self.update_interval = self.args.get("update_interval")

        # Build area entity and get friendly name
        self.area_entity = f"area.{self.area_id}"
        self.area_name = self.adbase.get_state(
            self.area_entity, attribute="friendly_name"
        )

        # Create a list of all lights in the area
        lights = [
            self.lights,
            self.lights_ct,
            self.lights_rgb,
            self.sleep_lights,
            self.sleep_lights_ct,
        ]
        lights = [light for light in lights if light]
        self.all_lights = set(chain(*lights))

        # Listen for motion detected
        for sensor in self.motion_sensors:
            self.hass.listen_state(self.on_motion, sensor, new="on")

        # Listen for changes in light state
        if self.circadian_sensor:
            for light in self.all_lights:
                self.hass.listen_state(self.on_light_change, light)

        # Listen for occupancy changes of area
        self.adbase.listen_state(
            self.on_occupancy_change, self.area_entity, attribute="occupied", new=False
        )

    def on_motion(
        self, entity: str, attribute: str, old: str, new: str, kwargs: dict
    ) -> None:
        """Respond when motion is detected."""
        self.adbase.log(f"Motion detected: {self.area_name}")
        # Turn lights on if not already on
        if not self.lights_on():
            self.turn_lights_on()

        # Set motion state of room to True
        self.set_area_motion(True)

        # Start/Restart timer to turn motion state to False
        self.restart_motion_timer()

    def on_light_change(
        self, entity: str, attribute: str, old: str, new: str, kwargs: dict
    ) -> None:
        """Respond when light changes state."""
        if new != old:
            if new == "on":
                if "circadian_timer" in self.handles:
                    self.adbase.cancel_timer(self.handles["circadian_timer"])
                    self.handles.pop("circadian_timer")
                self.handles["circadian_timer"] = self.adbase.run_every(
                    self.turn_lights_on,
                    f"now+{self.update_interval}",
                    self.update_interval,
                    transition=self.transition,
                )
            elif new == "off":
                # Set motion to False and cancel any existing timers
                if "motion_timer" in self.handles:
                    self.set_area_motion(False)
                    self.adbase.cancel_timer(self.handles["motion_timer"])
                    self.handles.pop("motion_timer")
                if "circadian_timer" in self.handles:
                    self.adbase.cancel_timer(self.handles["circadian_timer"])
                    self.handles.pop("circadian_timer")

    def on_occupancy_change(
        self, entity: str, attribute: str, old: str, new: str, kwargs: dict
    ) -> None:
        """Respond when occupancy of area changed to False."""
        for light in self.all_lights:
            self.hass.turn_off(light)

    def turn_lights_on(self, *args: list, **kwargs: dict) -> None:
        """Turn on lights."""
        if not self.lux_above_threshold():
            if self.is_sleep() and self.sleep_brightness:
                lights = self.sleep_lights
                lights_ct = self.sleep_lights_ct
                lights_rgb = []
            else:
                lights = self.lights
                lights_ct = self.lights_ct
                lights_rgb = self.lights_rgb

            brightness_pct = int(self.calc_brightness_pct())
            colortemp = int(self.calc_colortemp(brightness_pct))
            mired = color_temperature_kelvin_to_mired(colortemp)
            rgb = tuple(map(int, color_temperature_to_rgb(colortemp)))

            transition = args[0]["transition"] if args else 1

            if lights:
                for light in lights:
                    self.hass.turn_on(
                        light, brightness_pct=brightness_pct, transition=transition
                    )
            if lights_ct:
                for light in lights_ct:
                    self.hass.turn_on(
                        light,
                        brightness_pct=brightness_pct,
                        color_temp=mired,
                        transition=transition,
                    )
            if lights_rgb:
                for light in lights_rgb:
                    self.hass.turn_on(
                        light,
                        brightness_pct=brightness_pct,
                        rgb_color=rgb,
                        transition=transition,
                    )

    def set_area_motion(self, motion: bool) -> None:
        """Set motion of area."""
        self.adbase.set_state(self.area_entity, motion=motion)

    def restart_motion_timer(self) -> None:
        """Set/Reset timer to set occupany of are to False."""
        if "motion_timer" in self.handles:
            self.adbase.cancel_timer(self.handles["motion_timer"])
            self.handles.pop("motion_timer")
        self.handles["motion_timer"] = self.adbase.run_in(
            self.disable_area_motion, self.delay_off
        )

    def disable_area_motion(self, *args: list) -> None:
        """Set area motion to False."""
        self.set_area_motion(False)

    def calc_brightness_pct(self) -> float:
        """Calculate brightness percentage."""
        if self.is_sleep() and self.sleep_brightness:
            return self.sleep_brightness

        if self.circadian_sensor:
            brightness_pct = self.hass.get_state(self.circadian_sensor)
            if float(brightness_pct) > 0:
                return self.max_brightness

            return (
                (self.max_brightness - self.min_brightness)
                * ((100 + float(brightness_pct)) / 100)
            ) + self.min_brightness

        return self.default_brightness

    def calc_colortemp(self, brightness_pct: float) -> float:
        """Calculate color temperature based on brightness."""
        if brightness_pct > 0:
            return (
                (self.max_colortemp - self.min_colortemp) * (brightness_pct / 100)
            ) + self.min_colortemp

        return self.min_colortemp

    def lux_above_threshold(self) -> bool:
        """Return true if lux is above threshold."""
        if self.lux_sensor:
            value = self.hass.get_state(self.lux_sensor)
            if value not in ["unavailable", "unknown"]:
                return float(value) > self.lux_threshold

        return False

    def lights_on(self) -> list:
        """Return lights currently on."""
        return [
            entity for entity in self.all_lights if self.hass.get_state(entity) == "on"
        ]

    def is_sleep(self) -> bool:
        """Return true if someone is asleep."""
        sleep_state = self.adbase.get_state(self.area_entity, attribute="sleep_state")
        return sleep_state != "nobody_in_bed"