コード例 #1
0
ファイル: speedtrap.py プロジェクト: prunn/ACTV
class ACSpeedTrap:

    # INITIALIZATION

    def __init__(self): 
        self.rowHeight=36         
        self.lastLapInPit = 0
        self.lastLapInvalidated = 0
        self.lastLapShown = 0
        self.SpeedKMH=Value()
        self.SpeedMPH=Value()
        self.topSpeed=Value()
        self.userTopSpeed=Value()
        self.curTopSpeed=Value()
        self.curTopSpeedMPH=Value()
        self.currentVehicule=Value()
        self.currentVehicule.setValue(0)
        self.session=Value()
        self.session.setValue(-1)
        self.speedText=""
        self.trap=0
        self.userTrap=0
        self.time_end=0
        self.carsCount=0
        self.lapCanBeInvalidated=True
        self.relyOnEveryOne=True
        self.widget_visible=Value()
        self.cursor=Value()
        self.cursor.setValue(False)
        self.ui_row_height = Value(-1)
        self.window = Window(name="ACTV Speed Trap", icon=False, width=250, height=42, texture="")
        self.lbl_title = Label(self.window.app,"").setSize(self.rowHeight, self.rowHeight).setPos(0, 0).setFontSize(26).setAlign("center").setBgColor(rgb([12, 12, 12], bg = True)).setBgOpacity(0.72).setVisible(0)
        self.lbl_time = Label(self.window.app,"").setSize(172, self.rowHeight).setPos(38, 0).setFontSize(26).setAlign("center").setBgColor(rgb([55, 55, 55], bg = True)).setBgOpacity(0.64).setVisible(0)
        self.lbl_border = Label(self.window.app,"").setSize(210, 1).setPos(0, 39).setBgColor(Colors.red(bg = True)).setBgOpacity(0.7).setVisible(0)
        self.useMPH = False
        
        user_path = os.path.join(os.path.expanduser("~"), "Documents","Assetto Corsa","cfg")
        if os.path.exists(user_path + "/gameplay.ini"):
            self.checkMPH(user_path)
        else:
            user_path = "cfg"
            if os.path.exists(user_path + "/gameplay.ini"):
                self.checkMPH(user_path)
        self.loadCFG()
    # PUBLIC METHODS
    
    #--------------------------------------------------------------------------------------------------------------------------------------------- 
    def loadCFG(self):        
        cfg = Config("apps/python/prunn/", "config.ini")        
        if cfg.get("SETTINGS", "lap_can_be_invalidated", "int") == 1:
            self.lapCanBeInvalidated = True
        else:
            self.lapCanBeInvalidated = False
        self.ui_row_height.setValue(cfg.get("SETTINGS", "ui_row_height", "int")) 
        if self.ui_row_height.hasChanged():
            self.reDrawSize()
        
    def reDrawSize(self):
        self.rowHeight=self.ui_row_height.value
        fontSize=getFontSize(self.rowHeight)
        self.lbl_title.setSize(self.rowHeight, self.rowHeight).setFontSize(fontSize)
        self.lbl_time.setSize(self.rowHeight*4.8, self.rowHeight).setPos(self.rowHeight, 0).setFontSize(fontSize)
        self.lbl_border.setSize(self.rowHeight*5.8, 1).setPos(0, self.rowHeight+1)
        
            
    def setFont(self,fontName):
        self.lbl_title.setFont(fontName,0,0)
        self.lbl_time.setFont(fontName,0,0)       
                                                   
    def checkMPH(self,cfg_path):
        conf  = Config(cfg_path, "/gameplay.ini")
        opt_mph = conf.get("OPTIONS", "USE_MPH",type = "int")
        if opt_mph == 1:
            self.useMPH = True
          
    def animate(self):
        self.lbl_title.animate()
        self.lbl_time.animate()
        self.lbl_border.animate()
    
    def resetVisibility(self):  
        self.lbl_time.hide()           
        self.lbl_border.hide()           
        self.lbl_title.hide()
    
    def manageWindow(self):
        pt=POINT()
        result = ctypes.windll.user32.GetCursorPos(ctypes.byref(pt))
        win_x = self.window.getPos().x
        win_y = self.window.getPos().y
        if win_x > 0:
            self.window.last_x = win_x
            self.window.last_y = win_y
        else:
            self.window.setLastPos()
            win_x = self.window.getPos().x
            win_y = self.window.getPos().y
        if result and pt.x > win_x and pt.x < win_x + self.window.width and pt.y > win_y and pt.y < win_y + self.window.height:   
            self.cursor.setValue(True)
        else:
            self.cursor.setValue(False)        
        sessionChanged = self.session.hasChanged() 
        if sessionChanged:
            self.resetVisibility()
            self.time_end = 0
        if self.cursor.hasChanged() or sessionChanged:
            if self.cursor.value:
                self.window.setBgOpacity(0.4).border(0)
                self.window.showTitle(True)  
            else:   
                #pin outside
                self.window.setBgOpacity(0).border(0)
                self.window.showTitle(False)
                    
    def onUpdate(self, sim_info):   
        self.session.setValue(sim_info.graphics.session)  
        sessionTimeLeft=sim_info.graphics.sessionTimeLeft
        sim_info_status=sim_info.graphics.status
        if (sim_info.graphics.iCurrentTime == 0 and sim_info.graphics.completedLaps == 0) or sessionTimeLeft >= 1800000:  
            self.resetVisibility() 
            self.time_end = 0
        self.manageWindow()
        if self.carsCount==0:
            self.carsCount = ac.getCarsCount()
        for x in range(self.carsCount):
            c = ac.getCarState(x,acsys.CS.SpeedKMH)
            if x==0 and self.topSpeed.value < c:
                self.userTopSpeed.setValue(c)
                self.userTrap = ac.getCarState(x,acsys.CS.NormalizedSplinePosition)
                
            if self.relyOnEveryOne and self.topSpeed.value < c and ac.getCarState(x,acsys.CS.DriveTrainSpeed) > c/10 and ac.getCarState(x,acsys.CS.Gas) > 0.9 and ac.getCarState(x,acsys.CS.RPM) > 2000:
                if c > 500:
                    self.relyOnEveryOne=False
                    self.topSpeed.setValue(self.userTopSpeed.value)
                    self.trap = self.userTrap 
                    #ac.console("stop rely")
                    #ac.log("stop rely")
                else:
                    self.topSpeed.setValue(c)
                    #ac.console(str(c) + "-"+str(x)+"-rpm:"+str(ac.getCarState(x,acsys.CS.RPM))+"-Gas:"+str(ac.getCarState(x,acsys.CS.Gas))+"-Gear:"+str(ac.getCarState(x,acsys.CS.Gear))+"-DriveTrainSpeed:"+str(ac.getCarState(x,acsys.CS.DriveTrainSpeed))) 
                    self.trap = ac.getCarState(x,acsys.CS.NormalizedSplinePosition) 
            elif not self.relyOnEveryOne and x == 0 and self.topSpeed.value < c:
                self.topSpeed.setValue(c)
                self.trap = ac.getCarState(x,acsys.CS.NormalizedSplinePosition)      
        
        self.currentVehicule.setValue(ac.getFocusedCar())     
        self.SpeedKMH.setValue(ac.getCarState(self.currentVehicule.value,acsys.CS.SpeedKMH))
        self.SpeedMPH.setValue(ac.getCarState(self.currentVehicule.value,acsys.CS.SpeedMPH))
        LapCount = ac.getCarState(self.currentVehicule.value,acsys.CS.LapCount)                   
        
        if self.curTopSpeed.value < self.SpeedKMH.value:
            self.curTopSpeed.setValue(self.SpeedKMH.value) 
            self.curTopSpeedMPH.setValue(self.SpeedMPH.value)         
        if self.currentVehicule.value==0 and sim_info.physics.numberOfTyresOut >= 4 and self.lapCanBeInvalidated:
            self.lastLapInvalidated = LapCount
        self.animate()
        
        if sim_info_status == 2:
            if self.session.value <= 2  :                
                #Qual-Practise every time
                #isInPit = self.currentVehicule.value==0 and bool(sim_info.physics.pitLimiterOn)
                isInPit = (bool(ac.isCarInPitline(self.currentVehicule.value)) or bool(ac.isCarInPit(self.currentVehicule.value)))
                                      
                if isInPit :
                    self.lastLapInPit = LapCount
                
                if self.lastLapInPit < LapCount and self.curTopSpeed.value < 500 and self.lastLapShown < LapCount and self.lastLapInvalidated < LapCount and self.widget_visible.value == 0 and self.trap < ac.getCarState(self.currentVehicule.value,acsys.CS.NormalizedSplinePosition) + 0.06 and self.trap > ac.getCarState(self.currentVehicule.value,acsys.CS.NormalizedSplinePosition) - 0.08 and self.SpeedKMH.value < self.SpeedKMH.old - 0.6:
                    
                    #show and set timer 0.3
                    self.lastLapShown=LapCount
                    self.widget_visible.setValue(1)
                    if self.useMPH:
                        self.speedText="%.1f mph"%(self.curTopSpeedMPH.value)
                    else:
                        self.speedText="%.1f kph"%(self.curTopSpeed.value)
                    self.time_end = sessionTimeLeft - 9000
                    self.lbl_title.setText("S",hidden=True)
                    self.lbl_time.setText(self.speedText,hidden=True)
                    self.lbl_time.show()
                    self.lbl_border.show()
                    self.lbl_title.show()
                elif self.time_end == 0 or sessionTimeLeft < self.time_end:
                    self.lbl_time.hide()
                    self.lbl_border.hide()
                    self.lbl_title.hide()
                    self.widget_visible.setValue(0)
                    self.time_end=0
                    if self.widget_visible.hasChanged():                        
                        self.curTopSpeed.setValue(0)                      
                        self.curTopSpeedMPH.setValue(0)                   
               
            else:       
                self.resetVisibility()     
                    
        elif sim_info_status == 1:  
            self.resetVisibility()
コード例 #2
0
ファイル: actimer.py プロジェクト: prunn/ACTV
class ACTimer:

	# INITIALIZATION

	def __init__(self):
		self.finish_labels = []
		self.finish_initialised = False
		self.replay_initialised = False
		self.replay_asc = False
		self.replay_rgb=255
		self.session=Value()
		self.cursor=Value()
		self.cursor.setValue(False)
		self.session_draw=Value()
		self.session_draw.setValue(-1)
		self.ui_row_height = Value(-1)
		self.numberOfLaps=0
		self.rowHeight=36
		self.window = Window(name="ACTV Timer", icon=False, width=228, height=42, texture="")
		
		self.lbl_session_info=Label(self.window.app,"Loading").setSize(154, self.rowHeight).setPos(self.rowHeight, 0).setFontSize(26).setAlign("center").setBgColor(rgb([55, 55, 55], bg = True)).setBgOpacity(0.64)
		self.lbl_session_title=Label(self.window.app,"P").setSize(self.rowHeight, self.rowHeight).setPos(0, 0).setFontSize(26).setAlign("center").setBgColor(Colors.red(bg = True)).setBgOpacity(0.64)
		
		self.lbl_session_single=Label(self.window.app,"Loading").setSize(190, self.rowHeight).setPos(0, 0).setFontSize(26).setAlign("center").setBgColor(rgb([55, 55, 55], bg = True)).setBgOpacity(0.64).setColor(Colors.white()).setVisible(0)
		self.lbl_session_border=Label(self.window.app,"").setSize(154+self.rowHeight, 1).setPos(0, self.rowHeight+1).setBgColor(Colors.red(bg = True)).setBgOpacity(0.7).setVisible(1)
		
		trackFilePath = "content/tracks/"+ ac.getTrackName(0) + "/ui/"
		if ac.getTrackConfiguration(0) != "":
			trackFilePath += ac.getTrackConfiguration(0) + "/ui_track.json"
		else:			
			trackFilePath += "ui_track.json"
		if os.path.exists(trackFilePath):
			with open(trackFilePath) as data_file:    
				data = json.load(data_file)			
			self.trackName = data["name"]
			
			if len(self.trackName) > 12:	
				if self.trackName[12] == " " or self.trackName[12] == "-":
					self.trackName = self.trackName[:12]
				else:
					self.trackName = self.trackName[:12]
					#cut multiword
					space = self.trackName.rfind(" ")
					dash = self.trackName.rfind("-")
					if space > 0:
						self.trackName = self.trackName[:space]
					elif dash > 0:
						self.trackName = self.trackName[:dash]
			
		else:
			self.trackName = ac.getTrackName(0)
		if len(self.trackName) > 12:
			self.trackName = self.trackName[:12]
			
		self.loadCFG()
			
		
	# PUBLIC METHODS
	#---------------------------------------------------------------------------------------------------------------------------------------------    
	def loadCFG(self):        
		cfg = Config("apps/python/prunn/", "config.ini")		
		self.ui_row_height.setValue(cfg.get("SETTINGS", "ui_row_height", "int")) 
		if self.ui_row_height.hasChanged():
			self.reDrawSize()

	def reDrawSize(self):
		self.rowHeight=self.ui_row_height.value
		fontSize=getFontSize(self.rowHeight)
		width=self.rowHeight*5
		self.lbl_session_info.setSize(self.rowHeight*4, self.rowHeight).setPos(self.rowHeight, 0).setFontSize(fontSize)		
		self.lbl_session_title.setSize(self.rowHeight, self.rowHeight).setFontSize(fontSize)		
		self.lbl_session_single.setSize(width, self.rowHeight).setFontSize(fontSize)		
		self.lbl_session_border.setSize(width, 1).setPos(0, self.rowHeight+1)	
		if len(self.finish_labels) > 0:
			i=0
			j=0
			height=self.rowHeight/3
			for label in self.finish_labels:
				label.setSize(height, height)
				if i % 2 == 1 and j < 7:		
					label.setPos(height + j*height*2, i*height)
				elif i % 2 == 0:
					label.setPos(j*height*2, i*height)
				j+=1
				if (i % 2 == 0 and j >= 8) or (i % 2 == 1 and j >= 7):
					i+=1
					j=0	

	def setFont(self,fontName):
		self.lbl_session_info.setFont(fontName,0,0)
		self.lbl_session_title.setFont(fontName,0,0) 
		self.lbl_session_single.setFont(fontName,0,0) 

	def time_splitting(self, ms):
		s=ms/1000 
		m,s=divmod(s,60) 
		h,m=divmod(m,60) 
		#d,h=divmod(h,24) 
		if h > 0:
			return "{0}:{1}:{2}".format(int(h), str(int(m)).zfill(2), str(int(s)).zfill(2)) 
		else:  
			return "{0}:{1}".format(int(m), str(int(s)).zfill(2))  
		
	def init_finish(self):
		self.lbl_session_info.setVisible(0)
		self.lbl_session_title.setVisible(0)
		self.lbl_session_border.setVisible(0)
		self.lbl_session_single.setVisible(1)
		self.lbl_session_single.setText("").setBgColor(rgb([255, 255, 255], bg = True)).setBgOpacity(0.76).setVisible(1)		
		if len(self.finish_labels) > 0:			
			for label in self.finish_labels:				
				label.setVisible(1)
		else:
			height=self.rowHeight/3
			for i in range(0,3):			
				for j in range(0,8):
					if i % 2 == 1 and j < 7:
						self.finish_labels.append(Label(self.window.app).setSize(height, height).setPos(height + j*height*2, i*height).setBgColor(rgb([0, 0, 0], bg = True)).setBgOpacity(0.8).setVisible(1))
					elif i % 2 == 0:
						self.finish_labels.append(Label(self.window.app).setSize(height, height).setPos(j*height*2, i*height).setBgColor(rgb([0, 0, 0], bg = True)).setBgOpacity(0.8).setVisible(1))
			
		self.finish_initialised = True
	
	def destoy_finish(self):
		#Destroy
		self.lbl_session_single.setBgColor(rgb([55, 55, 55], bg = True)).setBgOpacity(0.64).setVisible(0)
		for label in self.finish_labels:		
			label.setVisible(0)
		self.finish_initialised = False
	
	def manageWindow(self):
		pt=POINT()
		result = ctypes.windll.user32.GetCursorPos(ctypes.byref(pt))
		win_x = self.window.getPos().x
		win_y = self.window.getPos().y
		if win_x > 0:
			self.window.last_x = win_x
			self.window.last_y = win_y
		else:
			self.window.setLastPos()
			win_x = self.window.getPos().x
			win_y = self.window.getPos().y
		if result and pt.x > win_x and pt.x < win_x + self.window.width and pt.y > win_y and pt.y < win_y + self.window.height:   
			self.cursor.setValue(True)
		else:
			self.cursor.setValue(False)		
		
		if self.cursor.hasChanged() or self.session_draw.hasChanged():
			if self.cursor.value:
				self.window.setBgOpacity(0.4).border(0)  
			else:   
				#pin outside
				self.window.setBgOpacity(0).border(0) 
		
	def onUpdate(self, sim_info):		
		self.session_draw.setValue(sim_info.graphics.session)
		self.manageWindow()
		sim_info_status=sim_info.graphics.status
		if sim_info_status == 2: #LIVE
			if self.replay_initialised:
				self.lbl_session_single.setColor(rgb([255,255,255]))
			self.session.setValue(self.session_draw.value)
			sessionTimeLeft = sim_info.graphics.sessionTimeLeft
			if self.session.value < 2  :				
				#0 to -5000 show finish
				if sessionTimeLeft < 0 and sessionTimeLeft > -5000:
					if not self.finish_initialised:
						self.init_finish()
				else:
					if sessionTimeLeft < 0:
						sessionTimeLeft = 0	
					if self.finish_initialised:
						self.destoy_finish()
					self.lbl_session_info.setVisible(1)
					self.lbl_session_title.setVisible(1)
					self.lbl_session_single.setVisible(0)
					self.lbl_session_border.setVisible(1)
					if self.session.hasChanged():
						self.lbl_session_title.setSize(self.rowHeight, self.rowHeight)
						self.lbl_session_info.setSize(self.rowHeight*4, self.rowHeight).setPos(self.rowHeight, 0)						
						if self.session.value == 1 :
							self.lbl_session_title.setText("Q")
						else:
							self.lbl_session_title.setText("P")  
					self.lbl_session_info.setText(self.time_splitting(sessionTimeLeft))
					if not self.finish_initialised:
						if sim_info.graphics.flag == 2:
							self.lbl_session_info.setBgColor(Colors.yellow(True))
							self.lbl_session_info.setColor(Colors.black(),True)
							self.lbl_session_border.setBgColor(Colors.black(bg = True),True)
							self.lbl_session_title.setBgColor(Colors.black(bg = True),True)
						else:
							self.lbl_session_info.setBgColor(rgb([55, 55, 55], bg = True))
							self.lbl_session_info.setColor(Colors.white(),True)	
							self.lbl_session_border.setBgColor(Colors.red(bg = True),True)	
							self.lbl_session_title.setBgColor(Colors.red(bg = True),True)
					self.lbl_session_border.animate()		
					self.lbl_session_info.animate()
					self.lbl_session_title.animate()
			elif self.session.value == 2 :
				completed=0
				for x in range(ac.getCarsCount()): 
					c = ac.getCarState(x,acsys.CS.LapCount)
					if c > completed:
						completed=c     
				completed+=1    
				if self.numberOfLaps==0:
					self.numberOfLaps=sim_info.graphics.numberOfLaps
				if sessionTimeLeft > 1800000 or (sim_info.graphics.iCurrentTime == 0 and sim_info.graphics.completedLaps == 0):
					if self.finish_initialised:
						self.destoy_finish()
					self.lbl_session_info.setVisible(0)
					self.lbl_session_title.setVisible(0)
					self.lbl_session_single.setVisible(1)
					self.lbl_session_border.setVisible(1)
					self.lbl_session_single.setText(self.trackName)
				elif completed > self.numberOfLaps:
					if not self.finish_initialised:
						self.init_finish()
				elif completed == self.numberOfLaps:
					if self.finish_initialised:
						self.destoy_finish()
					self.lbl_session_info.setVisible(0)
					self.lbl_session_title.setVisible(0)
					self.lbl_session_single.setVisible(1)
					self.lbl_session_border.setVisible(1)
					self.lbl_session_single.setText("Final lap")
				else:
					if self.finish_initialised:
						self.destoy_finish()
					self.lbl_session_info.setVisible(0)
					self.lbl_session_title.setVisible(0)
					self.lbl_session_single.setVisible(1)
					self.lbl_session_border.setVisible(1)
					if self.session.hasChanged():
						self.lbl_session_info.setSize(self.rowHeight*4,  self.rowHeight).setPos(self.rowHeight, 0)
						self.lbl_session_title.setSize(self.rowHeight, self.rowHeight)
						self.lbl_session_title.setText("Lap")
					self.lbl_session_single.setText("{0} / {1}".format(completed,self.numberOfLaps))
				if not self.finish_initialised:
					if sim_info.graphics.flag == 2:
						self.lbl_session_single.setBgColor(Colors.yellow(True),True)
						self.lbl_session_single.setColor(Colors.black(),True)
						self.lbl_session_border.setBgColor(Colors.black(bg = True),True)
					else:
						self.lbl_session_single.setBgColor(rgb([55, 55, 55], bg = True),True)
						self.lbl_session_single.setColor(Colors.white(),True)
						self.lbl_session_border.setBgColor(Colors.red(bg = True),True)
				self.lbl_session_border.animate()		
				self.lbl_session_single.animate()
			else:
				self.lbl_session_info.setVisible(0)
				self.lbl_session_title.setVisible(0)
				self.lbl_session_single.setVisible(0)
				self.lbl_session_border.setVisible(0)
			
					
		elif sim_info_status == 1:
			replayTimeMultiplier=sim_info.graphics.replayTimeMultiplier
			if self.finish_initialised:
				self.destoy_finish()
			self.lbl_session_info.setVisible(0)
			self.lbl_session_title.setVisible(0)
			self.lbl_session_border.setVisible(1)
			self.lbl_session_single.setVisible(1)
			self.replay_initialised=True
			self.lbl_session_single.setColor(rgb([self.replay_rgb,self.replay_rgb,self.replay_rgb]))
			if self.replay_asc and replayTimeMultiplier > 0:
				self.replay_rgb += 2
			elif replayTimeMultiplier > 0:
				self.replay_rgb -= 2
			if self.replay_rgb < 100:
				self.replay_asc=True
			elif self.replay_rgb >= 246:
				self.replay_rgb=246
				self.replay_asc=False
			self.lbl_session_single.setText("REPLAY")
コード例 #3
0
ファイル: acinfo.py プロジェクト: prunn/ACTV
class ACInfo:

    # INITIALIZATION
    def __init__(self):   
        self.rowHeight=36     
        self.lastLapInPit = 0
        self.lastLapInvalidated = 0
        self.situation = 0
        self.carsCount=0
        self.lbl_timing_height = 0
        self.lbl_position_height = 0
        self.lbl_position_text=Value("")
        self.currentVehicule=Value(-1)
        self.ui_row_height = Value(-1)
        self.cursor=Value(False)
        self.fastestLap=Value(0)
        self.fastestLap2=Value(0)
        self.fastestPos=1
        self.lastLap=0
        self.lastLapStart=10000
        self.sector_delay = 5000
        self.lastTimeInPit=0
        self.visible_end = 0
        self.lastLapTime = 0
        self.nameOffset=0
        self.nameOffsetValue=Value(0)
        self.lapCanBeInvalidated=True
        self.fastestLapBorderActive = False
        self.firstLapStarted=False
        self.minLapCount=1
        self.sectorCount=-1
        self.lapTimesArray = []
        self.driversLap = []
        track=ac.getTrackName(0)
        config=ac.getTrackConfiguration(0)
        if track.find("ks_nordschleife")>=0 and config.find("touristenfahrten")>=0:
            self.minLapCount=0
            self.lastLapInvalidated = -1
        elif track.find("drag1000")>=0 or track.find("drag400")>=0:
            self.minLapCount=0
            self.lastLapInvalidated = -1
        self.fastestLapSectors = [0,0,0,0,0,0]
        self.session=Value(-1)
        #self.session.setValue()    
        self.window = Window(name="ACTV Info", icon=False, width=332, height=self.rowHeight*2, texture="")
        
        self.lbl_driver_name=Label(self.window.app,"").setSize(284, self.rowHeight).setPos(0, 0).setBgColor(rgb([20, 20, 20], bg = True)).setBgOpacity(0.8).setVisible(0)
        self.lbl_driver_name2=Label(self.window.app,"Loading").setSize(284, self.rowHeight).setPos(14, 0).setFontSize(26).setAlign("left").setVisible(0)
        self.lbl_driver_name_visible=Value()
        self.lbl_driver_name_visible_fin=Value(0)
        self.lbl_driver_name_text=Value("")
        self.lbl_position_visible=Value(0)
        self.lbl_timing_text=Value()
        self.race_fastest_lap=Value(0)
        #self.race_fastest_lap.setValue(0)
        self.race_fastest_lap_driver=Value()
        self.lbl_timing_visible=Value(0)
        self.lbl_timing=Label(self.window.app,"Loading").setSize(284, self.rowHeight).setPos(0, self.rowHeight).setFontSize(26).setAlign("left").setBgColor(rgb([55, 55, 55], bg = True)).setBgOpacity(0.64).setVisible(0)
        self.lbl_split=Label(self.window.app,"Loading").setSize(220, self.rowHeight).setPos(10, self.rowHeight).setFontSize(26).setAlign("right").setVisible(0)
        self.lbl_fastest_split=Label(self.window.app,"Loading").setSize(220, self.rowHeight).setPos(48, self.rowHeight).setFontSize(26).setAlign("right").setVisible(0)
        self.info_position=Label(self.window.app,"0").setSize(self.rowHeight, self.rowHeight).setPos(0, 0).setFontSize(26).setAlign("center").setBgColor(Colors.red(bg = True)).setBgOpacity(1).setVisible(0)
        self.info_position_lead=Label(self.window.app,"1").setSize(self.rowHeight, self.rowHeight).setPos(246, self.rowHeight).setFontSize(26).setAlign("center").setBgColor(Colors.red(bg = True)).setBgOpacity(1).setVisible(0)
        car = ac.getCarName(0)        
        self.lbl_border=Label(self.window.app,"").setSize(284, 1).setPos(0, self.rowHeight).setBgColor(Colors.colorFromCar(car)).setBgOpacity(0.7).setVisible(0)
        self.loadCFG()
        self.info_position.setAnimationSpeed("o", 0.1)
        self.info_position_lead.setAnimationSpeed("o", 0.1)
        self.lbl_split.setAnimationSpeed("a", 0.1)
        self.lbl_fastest_split.setAnimationSpeed("a", 0.1)
                
        
    # PUBLIC METHODS
    #---------------------------------------------------------------------------------------------------------------------------------------------       
    def loadCFG(self):        
        cfg = Config("apps/python/prunn/", "config.ini") 
        if cfg.get("SETTINGS", "lap_can_be_invalidated", "int") == 1:
            self.lapCanBeInvalidated = True
        else:
            self.lapCanBeInvalidated = False
        self.ui_row_height.setValue(cfg.get("SETTINGS", "ui_row_height", "int")) 
        if self.ui_row_height.hasChanged():
            self.reDrawSize()
        
    def reDrawSize(self):
        self.rowHeight=self.ui_row_height.value+2
        fontSize=getFontSize(self.rowHeight)
        self.row2Height=self.ui_row_height.value
        fontSize2=getFontSize(self.row2Height)
        width=self.rowHeight*7
        self.lbl_driver_name.setSize(width, self.rowHeight).setFontSize(fontSize)
        self.lbl_driver_name2.setSize(width, self.rowHeight).setFontSize(fontSize)
        self.lbl_timing.setSize(width, self.row2Height).setPos(0, self.rowHeight).setFontSize(fontSize2)
        self.lbl_split.setSize(self.rowHeight*4.7, self.row2Height).setPos(self.rowHeight, self.rowHeight).setFontSize(fontSize2)
        self.lbl_fastest_split.setSize(self.rowHeight*5.7, self.row2Height).setPos(self.rowHeight, self.rowHeight).setFontSize(fontSize2)
        self.info_position.setSize(self.rowHeight, self.rowHeight).setFontSize(fontSize)
        self.info_position_lead.setSize(self.row2Height, self.row2Height).setPos(width-self.row2Height, self.rowHeight).setFontSize(fontSize2)      
        self.lbl_border.setSize(width, 1).setPos(0, self.rowHeight)
        
            
    def setFont(self,fontName):
        self.lbl_driver_name.setFont(fontName,0,0)
        self.lbl_driver_name2.setFont(fontName,0,0)
        self.lbl_timing.setFont(fontName,0,0)
        self.lbl_split.setFont(fontName,0,0)
        self.lbl_fastest_split.setFont(fontName,0,0)
        self.info_position.setFont(fontName,0,0)
        self.info_position_lead.setFont(fontName,0,0)
           
    def format_name(self,name):        
        space = name.find(" ")
        if space > 0:
            if len(name) > 14 and space+1 < len(name):
                return name[space+1:].upper()
            return name[:space].capitalize() + name[space:].upper()
        if len(name) > 14:
            return name[:15].upper()
        return name.upper()
            
     
            
    def format_tire(self,name):
        space = name.find("(")
        if space > 0:
            name = name[:space]
        name=name.strip()
        if len(name) > 16:
            return name[:17]
        return name   
                                          
    def time_splitting(self, ms, full = "no"):        
        s=ms/1000 
        m,s=divmod(s,60) 
        h,m=divmod(m,60) 
        #d,h=divmod(h,24) 
        if full == "yes":
            d=ms % 1000
            if h > 0:
                return "{0}:{1}:{2}.{3}".format(int(h), str(int(m)).zfill(2), str(int(s)).zfill(2), str(int(d)).zfill(3))
            elif m > 0:  
                return "{0}:{1}.{2}".format(int(m), str(int(s)).zfill(2), str(int(d)).zfill(3))
            else:
                return "{0}.{1}".format(int(s), str(int(d)).zfill(3))
        else:
            d=ms / 100 % 10 
            if h > 0:
                return "{0}:{1}:{2}.{3}".format(int(h), str(int(m)).zfill(2), str(int(s)).zfill(2), int(d))
            elif m > 0:  
                return "{0}:{1}.{2}".format(int(m), str(int(s)).zfill(2), int(d))
            else:
                return "{0}.{1}".format(int(s), int(d))
    
    def getSector(self):
        splits=ac.getCurrentSplits(self.currentVehicule.value)
        i=0 
        sector=0  
        for c in splits: 
            i+=1
            if c > 0: 
                sector=i
        return sector
    
    def getStandingsPosition(self,vehicule):
        #mainly for replay
        standings = []
        for i in range(self.carsCount): 
            bl=ac.getCarState(i,acsys.CS.BestLap)
            if bl > 0  and bool(ac.isConnected(vehicule)):
                standings.append((i,bl))  
        standings = sorted(standings, key=lambda student: student[1]) 
        p=[i for i, v in enumerate(standings) if v[0] == vehicule] 
        if len(p) > 0:
            return p[0]+1
        return 0
        
        
    def animate(self):
        self.lbl_driver_name.animate()
        self.lbl_driver_name2.animate()
        self.lbl_timing.animate()
        self.info_position.animate()
        self.info_position_lead.animate()        
        self.lbl_split.animate()
        self.lbl_fastest_split.animate()
        self.lbl_border.animate()
     
    def resetVisibility(self):  
        self.lbl_driver_name.hide()
        self.lbl_driver_name2.hideText()
        self.lbl_border.hide()
        self.lbl_driver_name_visible_fin.setValue(0)
        self.lbl_timing.hide()
        self.lbl_timing_visible.setValue(0)
        self.lbl_fastest_split.hideText()
        self.lbl_split.hideText()
        self.info_position_lead.hide()
        self.info_position.hide()  
        self.visible_end = 0   
        
    def visibilityQualif(self):
        self.lbl_fastest_split.hideText()
        if self.lbl_driver_name_visible.value == 1 and self.lbl_driver_name.isVisible.value==0:
            self.lbl_driver_name_visible.changed=True
        if self.lbl_timing_visible.value == 1 and self.lbl_timing.isVisible.value==0:
            self.lbl_timing_visible.changed=True
            
        self.lbl_driver_name_visible_fin.setValue(self.lbl_driver_name_visible.value)
        self.nameOffsetValue.setValue(self.nameOffset)
        if self.lbl_driver_name_visible_fin.hasChanged():         
            if self.lbl_driver_name_visible_fin.value == 0:
                self.lbl_driver_name.hide()
                self.lbl_driver_name2.hideText()
                self.lbl_border.hide()
            else:
                self.lbl_driver_name.show()
                self.lbl_driver_name2.showText()
                self.lbl_border.show()
                
        if self.lbl_timing_visible.hasChanged():         
            if self.lbl_timing_visible.value == 0:
                self.lbl_timing.hide()
            else:
                self.lbl_timing.show()
                
        if self.lbl_driver_name_text.hasChanged():
            self.lbl_driver_name2.setText(self.lbl_driver_name_text.value.lstrip())
        if self.nameOffsetValue.hasChanged(): 
            self.lbl_driver_name2.setX(self.nameOffsetValue.value,True)
        if self.lbl_timing_text.hasChanged():
            self.lbl_timing.setText(self.lbl_timing_text.value)
    
    def visibilityRace(self):
        self.nameOffsetValue.setValue(self.nameOffset)
        if self.lbl_driver_name_visible.hasChanged():         
            if self.lbl_driver_name_visible.value == 0:
                self.lbl_driver_name.hide()
                self.lbl_driver_name2.hideText()
                self.lbl_border.hide()
            else:
                self.lbl_driver_name.show()
                self.lbl_driver_name2.showText()
                self.lbl_border.show()
            
        if self.lbl_timing_visible.hasChanged():         
            if self.lbl_timing_visible.value == 0:
                self.lbl_timing.hide()
            else:
                self.lbl_timing.show()
                
        if self.lbl_driver_name_text.hasChanged():
            self.lbl_driver_name2.setText(self.lbl_driver_name_text.value) 
        if self.nameOffsetValue.hasChanged(): 
            self.lbl_driver_name2.setX(self.nameOffsetValue.value,True) 
        if self.lbl_timing_text.hasChanged():
            self.lbl_timing.setText(self.lbl_timing_text.value,hidden=bool(self.lbl_timing_height < 30)) 
            
    def getBestLap(self,lap=False):
        #old bestLap
        return self.fastestLap2.old
        '''
        if self.fastestLap.hasChanged():
            return self.fastestLap.old
        return self.fastestLap.value
        '''
    
    def manageWindow(self):
        pt=POINT()
        result = ctypes.windll.user32.GetCursorPos(ctypes.byref(pt))
        win_x = self.window.getPos().x
        win_y = self.window.getPos().y
        if win_x > 0:
            self.window.last_x = win_x
            self.window.last_y = win_y
        else:
            self.window.setLastPos()
            win_x = self.window.getPos().x
            win_y = self.window.getPos().y
        if result and pt.x > win_x and pt.x < win_x + self.window.width and pt.y > win_y and pt.y < win_y + self.window.height:   
            self.cursor.setValue(True)
        else:
            self.cursor.setValue(False)
        
        sessionChanged = self.session.hasChanged()
        if sessionChanged:
            self.resetVisibility()  
            self.fastestLapSectors = [0,0,0,0,0,0]               
        if self.cursor.hasChanged() or sessionChanged:
            if self.cursor.value:
                self.window.setBgOpacity(0.4).border(0)
                self.window.showTitle(True)  
            else:   
                self.window.setBgOpacity(0).border(0)
                self.window.showTitle(False)
        
    def onUpdate(self, sim_info, fl):
        self.session.setValue(sim_info.graphics.session)
        self.manageWindow()
        self.animate()
        if self.carsCount==0:
            self.carsCount = ac.getCarsCount()
        sessionTimeLeft=sim_info.graphics.sessionTimeLeft
        sim_info_status=sim_info.graphics.status
        self.currentVehicule.setValue(ac.getFocusedCar())        
        backupLaptime=0
        backupLastLapInPits=0
        if len(self.lapTimesArray) < self.carsCount:
            for x in range(self.carsCount):
                c = ac.getCarState(x,acsys.CS.LapCount)
                self.driversLap.append(Value(c))
                self.lapTimesArray.append(lapTimeStart(c,sessionTimeLeft,0)) 
        else:
            for x in range(self.carsCount):
                c = ac.getCarState(x,acsys.CS.LapCount)
                self.driversLap[x].setValue(c)
                if self.driversLap[x].hasChanged():
                    self.lapTimesArray[x].lap=self.driversLap[x].value
                    self.lapTimesArray[x].time=sessionTimeLeft
                if bool(ac.isCarInPitline(x)) or bool(ac.isCarInPit(x)):
                    self.lapTimesArray[x].lastpit=c
                if x == self.currentVehicule.value:
                    backupLaptime=self.lapTimesArray[x].time-sessionTimeLeft
                    self.lastLapStart = self.lapTimesArray[x].time
                    backupLastLapInPits = self.lapTimesArray[x].lastpit
        
                            
        currentVehiculeChanged=self.currentVehicule.hasChanged()
                    
        if currentVehiculeChanged or (self.fastestLapBorderActive and sessionTimeLeft < self.visible_end-2000):
            self.fastestLapBorderActive = False
            car = ac.getCarName(self.currentVehicule.value)        
            self.lbl_border.setBgColor(Colors.colorFromCar(car))           
            
        if sim_info_status == 2:
            #LIVE
            strOffset = "  "
            #self.nameOffset=14
            if self.session.value != 2 :
                #NOT RACE
                #qtime 
                self.fastestLap.setValue(fl)         
                bestlap = ac.getCarState(self.currentVehicule.value,acsys.CS.BestLap)
                isInPit = (bool(ac.isCarInPitline(self.currentVehicule.value)) or bool(ac.isCarInPit(self.currentVehicule.value)))
                LapCount = ac.getCarState(self.currentVehicule.value,acsys.CS.LapCount)
                if self.lastLap != LapCount:
                    self.lastLap = LapCount
                    self.firstLapStarted=False
                    if self.currentVehicule.value==0:
                        self.lastLapStart = sessionTimeLeft
                curLapTime = ac.getCarState(self.currentVehicule.value, acsys.CS.LapTime)
                if curLapTime == 0 and backupLaptime > 0 and self.minLapCount > 0:
                    curLapTime = backupLaptime
                if curLapTime > 0:
                    self.firstLapStarted=True
                #if self.minLapCount == 0 and self.firstLapStarted and ((self.lastLapTime > curLapTime and curLapTime < 1000) or self.lastLapStart==10000):
                #    self.lastLapStart = sessionTimeLeft                  
                self.lastLapTime = curLapTime
                                  
                if isInPit :
                    self.lastLapInPit = LapCount
                    self.lastTimeInPit = sessionTimeLeft
                if self.currentVehicule.value==0 and sim_info.physics.numberOfTyresOut >= 4 and self.lapCanBeInvalidated:
                    self.lastLapInvalidated = LapCount
                if isInPit and self.minLapCount == 0:
                    self.lastLapInvalidated = -1
                if self.sectorCount < 0:
                    self.sectorCount = sim_info.static.sectorCount    
                
                if self.fastestLap.value > 0:
                    for x in range(self.carsCount): 
                        c = ac.getCarState(x,acsys.CS.BestLap)
                        if self.fastestLap2.value == 0 or (c > 0 and c < self.fastestLap2.value):               
                            self.fastestLap2.setValue(c)
                            self.fastestLapSectors = ac.getLastSplits(x)
                else:
                    self.fastestLapSectors = [0,0,0,0,0,0]
                            
                #lapInvalidated = bool(ac.getCarState(0, acsys.CS.LapInvalidated))
                lapInvalidated = bool(self.lastLapInvalidated==LapCount)
                if currentVehiculeChanged or self.lbl_driver_name_text.value=="":
                    self.lbl_driver_name_text.setValue(self.format_name(ac.getDriverName(self.currentVehicule.value)))
                #sector_delay = 5000
                # live or info      
                #ac.console("("+str(self.lastLapInPit)+" < "+str(LapCount)+" or "+str(self.minLapCount)+"==0) and not "+str(lapInvalidated)+" and ("+str(self.lastTimeInPit)+"==0 or "+str(self.lastTimeInPit)+" > "+str(self.lastLapStart)+")")            
                if ((self.lastLapStart < 0 and self.minLapCount > 0) or (self.minLapCount == 0 and lapInvalidated)) and self.session.value != 0:                    
                    self.lbl_driver_name_visible.setValue(0)
                    self.lbl_timing_visible.setValue(0)  
                    self.lbl_split.hideText()  
                    self.info_position.hide()
                    self.info_position_lead.hide()          
                elif (self.lastLapInPit < LapCount or self.minLapCount==0) and not lapInvalidated and (self.lastTimeInPit==0 or self.lastTimeInPit > self.lastLapStart or self.minLapCount==0) :
                    
                    if self.currentVehicule.value == 0:
                        sector = sim_info.graphics.currentSectorIndex
                    else:
                        sector = self.getSector()
                    
                    self.lbl_driver_name_visible.setValue(1)
                    self.lbl_timing_visible.setValue(1)  
                    
                    #lapTime = ac.getCarState(self.currentVehicule.value, acsys.CS.LapTime)
                    if self.currentVehicule.value == 0:
                        lastLap = sim_info.graphics.iLastTime
                    else: 
                        lastLap=0                       
                        lastSplits = ac.getLastSplits(self.currentVehicule.value)
                        for c in lastSplits:
                            lastLap+=c
                        if lastLap==0:
                            lastLap=ac.getCarState(self.currentVehicule.value, acsys.CS.LastLap)
                            
                    
                    traite=False
                    cur_splits = ac.getCurrentSplits(self.currentVehicule.value)
                    timeSplit=0
                    fastestSplit=0
                    i=0
                    showSplit=False
                    for c in cur_splits: 
                        if c > 0:
                            timeSplit+=c 
                            fastestSplit+=self.fastestLapSectors[i]
                            i+=1
                    fastestSplit_fin=fastestSplit
                    if i < self.sectorCount:
                        fastestSplit_fin+=self.fastestLapSectors[i]
                         
                    #Situation
                    for s in range(0,self.sectorCount):                    
                        if self.fastestLap.value > 0 and curLapTime > fastestSplit_fin - self.sector_delay:
                            #LAST_SECONDS_OF_SECTOR_X, sector == s and
                            self.info_position.hide() 
                            self.nameOffset=self.rowHeight*14/36 #14
                            if self.sectorCount-1 == sector:
                                #LAST_SECONDS_OF_SECTOR_LAP,
                                self.lbl_split.setText(self.time_splitting(self.fastestLap.value,"yes")).setColor(Colors.white()).showText()
                                self.info_position_lead.show() 
                                
                                showSplit=True
                            elif fastestSplit_fin > 0:
                                self.lbl_split.setText(self.time_splitting(fastestSplit_fin,"yes")).setColor(Colors.white()).showText()
                                self.info_position_lead.show() 
                                showSplit=True
                            break
                        if sector == s + 1 and s + 1 <= self.sectorCount and curLapTime - timeSplit <= self.sector_delay and fastestSplit > 0 :
                            #SECTOR_X_FINISHED_BEGIN_SECTOR_Y    
                            self.nameOffset=self.rowHeight*14/36 #14            
                            self.lbl_timing_text.setValue(strOffset + self.time_splitting(timeSplit,"yes")) 
                            if fastestSplit < timeSplit:
                                self.lbl_split.setText("+"+self.time_splitting(timeSplit-fastestSplit,"yes")).setColor(Colors.yellow()).showText()
                            else:
                                self.lbl_split.setText("-"+self.time_splitting(fastestSplit-timeSplit,"yes")).setColor(Colors.green()).showText()
                            self.info_position_lead.show() 
                            self.info_position.hide()
                            traite=True
                            break
                    
                    if not traite:
                        if self.sectorCount-1 == sector and self.fastestLap.value > 0 and curLapTime > self.fastestLap.value - self.sector_delay:
                            #LAST_SECONDS_OF_SECTOR_LAP,
                            self.nameOffset=self.rowHeight*14/36 #14
                            self.lbl_timing_text.setValue(strOffset + self.time_splitting(curLapTime)) 
                            self.info_position.hide()
                            #self.lbl_split.setText(self.time_splitting(self.fastestLap,"yes") + strOffset).setVisible(1)
                        elif self.lastLapInvalidated!=LapCount-1 and ((self.lastLapInPit!=LapCount-1 and sector == 0) or (self.minLapCount==0)) and curLapTime <= self.sector_delay and lastLap > 0:
                            #LAP_FINISHED_BEGIN_NEW_LAP,                       
                            pos = ac.getCarLeaderboardPosition(self.currentVehicule.value)
                            if pos == -1:
                                pos = self.getStandingsPosition(self.currentVehicule.value)                                
                
                            if pos > 1:
                                self.info_position.setColor(Colors.white()).setBgColor(Colors.grey(bg = True)).setBgOpacity(0.8)
                            else:
                                self.info_position.setColor(Colors.white()).setBgColor(Colors.red(bg = True)).setBgOpacity(0.8)
                            self.info_position.setText(str(pos))
                            self.info_position.show()
                            
                            self.nameOffset=self.rowHeight*49/36 #49
                            self.lbl_timing_text.setValue(strOffset + self.time_splitting(lastLap,"yes")) 
                            if self.fastestLap.value < lastLap:
                                self.lbl_split.setText("+"+self.time_splitting(lastLap-self.fastestLap.value,"yes")).setColor(Colors.yellow()).showText()
                            else:                            
                                self.lbl_split.setText("-"+self.time_splitting(self.getBestLap()-lastLap,"yes")).setColor(Colors.green()).showText()
                            self.info_position_lead.show() 
                            
                        else:
                            #OTHER
                            self.nameOffset=self.rowHeight*14/36 #14
                            self.lbl_timing_text.setValue(strOffset + self.time_splitting(curLapTime))  
                            self.info_position.hide()
                            if not showSplit:
                                self.lbl_split.hideText()
                                self.info_position_lead.hide()
                    self.fastestLap.changed=False
                else :                    
                    self.info_position_lead.hide()                     
                    normalizedSplinePosition = ac.getCarState(self.currentVehicule.value,acsys.CS.NormalizedSplinePosition)
                    if normalizedSplinePosition <= 0.001:
                        normalizedSplinePosition=1
                    if sessionTimeLeft > 0 and self.minLapCount==1 and normalizedSplinePosition > 0.95 and not isInPit :          
                        self.lbl_driver_name_visible.setValue(1)
                        self.nameOffset=self.rowHeight*14/36 #14
                        self.lbl_timing_visible.setValue(1)  
                        self.lbl_split.hideText()  
                        self.info_position.hide()
                        self.lbl_timing_text.setValue(strOffset + "0.0") 
                        
                    elif lapInvalidated and self.lastLapInPit < LapCount and self.minLapCount > 0 :
                        self.lbl_driver_name_visible.setValue(0)
                        self.lbl_timing_visible.setValue(0)  
                        self.lbl_split.hideText()  
                        self.info_position.hide()  
                    elif bestlap > 0 :             
                        self.lbl_driver_name_visible.setValue(1)
                        self.lbl_timing_visible.setValue(1)  
                         
                        if self.fastestLap.value < bestlap:
                            self.lbl_split.setText("+"+self.time_splitting(bestlap-self.fastestLap.value,"yes")).setColor(Colors.yellow()).showText()                           
                        else:                            
                            self.lbl_split.hideText()
                        
                        self.lbl_timing_text.setValue(strOffset + self.time_splitting(bestlap,"yes")) 
                                            
                        self.nameOffset=self.rowHeight*49/36 #49
                        #pos = sim_info.graphics.position
                        pos = ac.getCarLeaderboardPosition(self.currentVehicule.value)
                        if pos == -1:
                            pos = self.getStandingsPosition(self.currentVehicule.value) 
                        if pos > 1:
                            self.info_position.setColor(Colors.white()).setBgColor(Colors.grey(bg = True)).setBgOpacity(1)
                        else:
                            self.info_position.setColor(Colors.white()).setBgColor(Colors.red(bg = True)).setBgOpacity(1)
                        self.info_position.setText(str(pos)).show()   
                        self.lbl_position_text.setValue(str(pos))                
                            
                    elif isInPit :     
                        self.lbl_driver_name_visible.setValue(0)
                        self.lbl_timing_visible.setValue(0)  
                        self.lbl_split.hideText()  
                        self.info_position.hide()
                    else :
                        self.nameOffset=self.rowHeight*14/36 #14
                        self.lbl_driver_name_visible.setValue(1)
                        self.lbl_timing_visible.setValue(1)
                        if self.currentVehicule.value==0:
                            self.lbl_timing_text.setValue(strOffset + self.format_tire(sim_info.graphics.tyreCompound))
                        else:
                            self.lbl_timing_text.setValue(strOffset + "Out Lap")
                        self.lbl_split.hideText()
                        self.info_position.hide() 
                     
                if curLapTime <= self.sector_delay and ac.getCarState(self.currentVehicule.value, acsys.CS.LastLap) > 0 and backupLastLapInPits + 1 < ac.getCarState(x,acsys.CS.LapCount) and sessionTimeLeft < 0:
                    self.nameOffset=self.rowHeight*49/36 #49
                    self.lbl_driver_name_visible.setValue(1)
                    self.lbl_timing_visible.setValue(1)
                    self.lbl_split.showText()
                    self.info_position.show() 
                    #time vis
                self.visibilityQualif()
                    
            else:
                ################ Race ################
                self.info_position_lead.hide() 
                self.lbl_split.hideText()
                #fastest lap
                completed=0
                for x in range(self.carsCount): 
                    c = ac.getCarState(x,acsys.CS.LapCount)
                    if c > completed:
                        completed=c
                if completed <=1:
                    self.race_fastest_lap.setValue(0)
                else:
                    for i in range(self.carsCount): 
                        bl=ac.getCarState(i,acsys.CS.BestLap)
                        l = ac.getCarState(i,acsys.CS.LapCount)
                        if bl > 0 and l > self.minLapCount and (self.race_fastest_lap.value == 0 or bl < self.race_fastest_lap.value):
                            self.race_fastest_lap.setValue(bl)
                            self.race_fastest_lap_driver.setValue(i)
                        
                if self.race_fastest_lap.hasChanged() and self.race_fastest_lap.value > 0:
                    self.fastestLapBorderActive = True
                    car = ac.getCarName(self.race_fastest_lap_driver.value)        
                    self.lbl_border.setBgColor(Colors.colorFromCar(car))            
                    self.visible_end = sessionTimeLeft - 8000
                    self.lbl_driver_name_visible.setValue(1)
                    self.lbl_driver_name_text.setValue(self.format_name(ac.getDriverName(self.race_fastest_lap_driver.value)))
                    self.nameOffset=self.rowHeight*14/36 #14
                    self.lbl_timing_text.setValue(strOffset + "Fastest Lap")
                    self.lbl_timing_visible.setValue(1)
                    self.info_position.hide() 
                    self.lbl_fastest_split.setText(self.time_splitting(self.race_fastest_lap.value,"yes")).showText()
                    
                elif currentVehiculeChanged:  
                    #driver info                  
                    self.visible_end = sessionTimeLeft - 8000
                    self.lbl_driver_name_visible.setValue(1)
                    self.lbl_driver_name_text.setValue(self.format_name(ac.getDriverName(self.currentVehicule.value)))
                    self.nameOffset=self.rowHeight*49/36 #49
                    #pos = ac.getCarLeaderboardPosition(self.currentVehicule.value)
                    pos = ac.getCarRealTimeLeaderboardPosition(self.currentVehicule.value) + 1
                    if pos > 1:
                        self.info_position.setColor(Colors.white()).setBgColor(Colors.grey(bg = True)).setBgOpacity(1)
                    else:
                        self.info_position.setColor(Colors.white()).setBgColor(Colors.red(bg = True)).setBgOpacity(1)
                    self.info_position.setText(str(pos)).show() 
                    self.lbl_timing_visible.setValue(0)
                    self.lbl_fastest_split.hideText()
                elif self.visible_end == 0 or sessionTimeLeft < self.visible_end or sessionTimeLeft > 1800000:
                    self.lbl_driver_name_visible.setValue(0)
                    self.info_position.hide()
                    self.lbl_timing_visible.setValue(0)
                    self.lbl_fastest_split.hideText()
                    
                self.visibilityRace()
                    
        elif sim_info_status == 1 and self.session.value != 2:
            #Replay Qualif
            strOffset = "  "
            showSplit=False
            LapCount = ac.getCarState(self.currentVehicule.value,acsys.CS.LapCount)
            curLapTime = ac.getCarState(self.currentVehicule.value, acsys.CS.LapTime)
            isInPit = (bool(ac.isCarInPitline(self.currentVehicule.value)) or bool(ac.isCarInPit(self.currentVehicule.value)))
            if currentVehiculeChanged or self.lbl_driver_name_text.value=="":
                self.lbl_driver_name_text.setValue(self.format_name(ac.getDriverName(self.currentVehicule.value)))
            if isInPit:
                self.lbl_driver_name_visible.setValue(0)
                self.lbl_timing_visible.setValue(0)  
                self.lbl_split.hideText()  
                self.info_position.hide()
            elif curLapTime <= self.sector_delay and LapCount > 1:
                #show last lap
                self.lbl_driver_name_visible.setValue(1)
                self.lbl_timing_visible.setValue(1)
                if self.currentVehicule.value == 0:
                    lastLap = sim_info.graphics.iLastTime
                else: 
                    lastLap=0                       
                    lastSplits = ac.getLastSplits(self.currentVehicule.value)
                    for c in lastSplits:
                        lastLap+=c
                    if lastLap==0:
                        lastLap=ac.getCarState(self.currentVehicule.value, acsys.CS.LastLap)
                pos = ac.getCarLeaderboardPosition(self.currentVehicule.value)
                if pos == -1:
                    pos = self.getStandingsPosition(self.currentVehicule.value)                                
    
                if pos > 1:
                    self.info_position.setColor(Colors.white()).setBgColor(Colors.grey(bg = True)).setBgOpacity(0.8)
                else:
                    self.info_position.setColor(Colors.white()).setBgColor(Colors.red(bg = True)).setBgOpacity(0.8)
                self.info_position.setText(str(pos))
                self.info_position.show()
                self.nameOffset=self.rowHeight*49/36 #49
                self.lbl_timing_text.setValue(strOffset + self.time_splitting(lastLap,"yes")) 
                if self.fastestLap.value < lastLap:
                    self.lbl_split.setText("+"+self.time_splitting(lastLap-self.fastestLap.value,"yes")).setColor(Colors.yellow()).showText()
                else:                            
                    self.lbl_split.setText("-"+self.time_splitting(self.fastestLap.old-lastLap,"yes")).setColor(Colors.green()).showText()
                self.info_position_lead.show()
                self.fastestLap.changed=False
            elif LapCount > self.minLapCount:
                #showTiming
                self.lbl_driver_name_visible.setValue(1)
                self.lbl_timing_visible.setValue(1)
                self.info_position_lead.hide() 
                self.nameOffset=self.rowHeight*14/36 #14
                self.lbl_timing_text.setValue(strOffset + self.time_splitting(curLapTime))  
                self.info_position.hide()
                if not showSplit:
                    self.lbl_split.hideText()
                    self.info_position_lead.hide()
            else:
                #showTireInfo
                self.info_position_lead.hide() 
                self.nameOffset=self.rowHeight*14/36 #14
                self.lbl_driver_name_visible.setValue(1)
                self.lbl_timing_visible.setValue(1)
                if self.currentVehicule.value==0:
                    self.lbl_timing_text.setValue(strOffset + self.format_tire(sim_info.graphics.tyreCompound))
                else:
                    self.lbl_timing_text.setValue(strOffset + "Out Lap")
                self.lbl_split.hideText()
                self.info_position.hide()            
            
            self.visibilityQualif()
                
                
            
        elif sim_info_status == 1 and self.session.value == 2:
            #Replay Race
            todo=1
            '''
            if currentVehiculeChanged:
                self.visible_end = sessionTimeLeft - 8000
                self.lbl_driver_name_visible.setValue(1)
                self.lbl_driver_name_text.setValue(self.format_name(ac.getDriverName(self.currentVehicule.value)))
                self.nameOffset=self.rowHeight*49/36 #49
                pos = ac.getCarRealTimeLeaderboardPosition(self.currentVehicule.value) + 1
                if pos > 1:
                    self.info_position.setColor(Colors.white()).setBgColor(Colors.grey(bg = True)).setBgOpacity(1)
                else:
                    self.info_position.setColor(Colors.white()).setBgColor(Colors.red(bg = True)).setBgOpacity(1)
                self.info_position.setText(str(pos)).show() 
                self.lbl_timing_visible.setValue(0)
                self.lbl_fastest_split.hideText()
                
                if self.lbl_driver_name_visible.hasChanged():         
                    if self.lbl_driver_name_visible.value == 0:
                        self.lbl_driver_name.hide()
                        self.lbl_border.hide()
                    else:
                        self.lbl_driver_name.show()
                        self.lbl_border.show()
                    
                if self.lbl_timing_visible.hasChanged():         
                    if self.lbl_timing_visible.value == 0:
                        self.lbl_timing.hide()
                    else:
                        self.lbl_timing.show()
                        
                if self.lbl_driver_name_text.hasChanged():
                    self.lbl_driver_name.setText(self.lbl_driver_name_text.value)  
                if self.lbl_timing_text.hasChanged():
                    self.lbl_timing.setText(self.lbl_timing_text.value,hidden=bool(self.lbl_timing_height < 30)) 
            '''
        else:
            #REPLAY
            self.resetVisibility()
コード例 #4
0
ファイル: acdelta.py プロジェクト: prunn/ACTV
class ACDelta:
    resetPressed = False
    configChanged = False
    ui_row_height = 38
    # INITIALIZATION
    def __init__(self):
        self.window = Window(name="ACTV Delta", icon=False, width=240, height=184, texture="")
        self.cursor = Value(False)
        self.session = Value(-1)
        self.performance = Value(0)
        self.spline = Value(0)
        self.laptime = Value(0)
        self.TimeLeftUpdate = Value(0)
        self.referenceLap = []
        self.referenceLapTime = Value(0)
        self.lastLapTime = Value(0)
        self.lapCount = 0
        self.lastLapIsValid = True
        self.currentLap = []
        self.deltaLoaded = False
        self.thread_save = False
        self.highlight_end = 0
        self.rowHeight = Value(-1)
        self.lbl_delta = (
            Label(self.window.app, "+0.000")
            .setSize(150, 36)
            .setPos(0, 60)
            .setFontSize(26)
            .setAlign("right")
            .setVisible(1)
        )
        self.lbl_lap = (
            Label(self.window.app, "0.000")
            .setSize(150, 32)
            .setPos(0, 86)
            .setFontSize(17)
            .setAlign("right")
            .setVisible(1)
        )
        self.btn_reset = (
            Button(self.window.app, self.onResetPress)
            .setPos(90, 68)
            .setSize(60, 20)
            .setText("Reset")
            .setAlign("center")
            .setBgColor(rgb([255, 12, 12], bg=True))
            .setVisible(0)
        )
        self.spin_row_height = ac.addSpinner(self.window.app, "")
        ac.setRange(self.spin_row_height, 20, 48)
        ac.setPosition(self.spin_row_height, 20, 28)
        ac.setValue(self.spin_row_height, self.__class__.ui_row_height)
        ac.addOnValueChangeListener(self.spin_row_height, self.onSpinRowHeightChanged)
        ac.setVisible(self.spin_row_height, 0)
        fontName = "Segoe UI"
        if ac.initFont(0, fontName, 0, 0) > 0:
            self.lbl_delta.setFont(fontName, 0, 1)
        self.cfg = Config("apps/python/prunn/", "config.ini")
        self.loadCFG()

    @staticmethod
    def onSpinRowHeightChanged(value):
        ACDelta.ui_row_height = value
        ACDelta.configChanged = True

    @staticmethod
    def onResetPress(a, b):
        ACDelta.resetPressed = True

    # PUBLIC METHODS
    def loadCFG(self):
        self.__class__.ui_row_height = self.cfg.get("DELTA", "delta_row_height", "int")
        ac.setValue(self.spin_row_height, self.__class__.ui_row_height)
        self.reDrawSize()

    def saveCFG(self):
        self.reDrawSize()
        self.cfg.set("DELTA", "delta_row_height", self.__class__.ui_row_height)

    def reDrawSize(self):
        if self.__class__.ui_row_height > 0:
            self.rowHeight.setValue(self.__class__.ui_row_height)
        else:
            self.rowHeight.setValue(38)
        if self.rowHeight.hasChanged():
            fontSize = getFontSize(self.rowHeight.value)
            fontSize2 = getFontSize(self.rowHeight.value - 16)
            rowHeight2 = self.rowHeight.value - 16
            # width=self.rowHeight*5
            self.lbl_delta.setSize(rowHeight2 / 24 * 32 + 120, self.rowHeight.value).setFontSize(fontSize)
            self.lbl_lap.setSize(rowHeight2 / 24 * 32 + 120, rowHeight2).setPos(
                0, self.rowHeight.value + 54
            ).setFontSize(fontSize2)
            self.btn_reset.setSize(self.rowHeight.value + 26, rowHeight2).setPos(
                90, self.rowHeight.value * 2 + 48
            ).setFontSize(fontSize2)

    def getDeltaFilePath(self):
        trackFilePath = os.path.join(
            os.path.expanduser("~"), "Documents", "Assetto Corsa", "plugins", "actv_deltas", "default"
        )
        if not os.path.exists(trackFilePath):
            os.makedirs(trackFilePath)
        trackFilePath += "/" + ac.getTrackName(0)
        if ac.getTrackConfiguration(0) != "":
            trackFilePath += "_" + ac.getTrackConfiguration(0)
        trackFilePath += "_" + ac.getCarName(0) + ".delta"

        return trackFilePath

    def saveDelta(self):
        # ac.log(str(time.time())+" saveDelta start:")
        referenceLap = list(self.referenceLap)
        # referenceLap=self.referenceLap
        referenceLapTime = self.referenceLapTime.value
        if len(referenceLap) > 0:
            try:
                times = []
                for l in referenceLap:
                    times.append((l.sector, l.time))
                data_file = {
                    "lap": referenceLapTime,
                    "times": times,
                    "track": ac.getTrackName(0),
                    "config": ac.getTrackConfiguration(0),
                    "car": ac.getCarName(0),
                    "user": ac.getDriverName(0),
                }
                file = self.getDeltaFilePath()
                with gzip.open(file, "wt") as outfile:
                    json.dump(data_file, outfile)
            except:
                Log.w("Error tower")

            # ac.console("lap saved:" + str(referenceLapTime) + ","+str(len(referenceLap)))
            # ac.log(str(time.time())+" lap saved:" + str(referenceLapTime) + ","+str(len(referenceLap)))

    def loadDelta(self):
        self.deltaLoaded = True
        file = self.getDeltaFilePath()
        if os.path.exists(file):
            try:
                with gzip.open(file, "rt") as data_file:
                    data = json.load(data_file)
                    self.referenceLapTime.setValue(data["lap"])
                    times = data["times"]
                    self.referenceLap = []
                    for t in times:
                        self.referenceLap.append(raceGaps(t[0], t[1]))
                    ac.console("AC Delta: File loaded")
            except:
                Log.w("Error tower")

    def getPerformanceGap(self, sector, time):
        if len(self.referenceLap) < 10:
            return round(ac.getCarState(0, acsys.CS.PerformanceMeter) * 1000)
        # if self.referenceLap[sector*100]
        if sector > 0.5:
            referenceLap = reversed(self.referenceLap)
        else:
            referenceLap = self.referenceLap
        for l in referenceLap:
            if l.sector == sector:
                return time - l.time
        # do not update
        return False

    def time_splitting(self, ms, full="no"):
        s = ms / 1000
        m, s = divmod(s, 60)
        h, m = divmod(m, 60)
        # d,h=divmod(h,24)
        if full == "yes":
            d = ms % 1000
            if h > 0:
                return "{0}:{1}:{2}.{3}".format(
                    int(h), str(int(m)).zfill(2), str(int(s)).zfill(2), str(int(d)).zfill(3)
                )
            elif m > 0:
                return "{0}:{1}.{2}".format(int(m), str(int(s)).zfill(2), str(int(d)).zfill(3))
            else:
                return "{0}.{1}".format(int(s), str(int(d)).zfill(3))
        else:
            d = ms / 100 % 10
            if h > 0:
                return "{0}:{1}:{2}.{3}".format(int(h), str(int(m)).zfill(2), str(int(s)).zfill(2), int(d))
            elif m > 0:
                return "{0}:{1}.{2}".format(int(m), str(int(s)).zfill(2), int(d))
            else:
                return "{0}.{1}".format(int(s), int(d))

    def manageWindow(self):
        pt = POINT()
        result = ctypes.windll.user32.GetCursorPos(ctypes.byref(pt))
        win_x = self.window.getPos().x
        win_y = self.window.getPos().y
        if win_x > 0:
            self.window.last_x = win_x
            self.window.last_y = win_y
        else:
            self.window.setLastPos()
            win_x = self.window.getPos().x
            win_y = self.window.getPos().y
        if (
            result
            and pt.x > win_x
            and pt.x < win_x + self.window.width
            and pt.y > win_y
            and pt.y < win_y + self.window.height
        ):
            self.cursor.setValue(True)
        else:
            self.cursor.setValue(False)
        sessionChanged = self.session.hasChanged()
        if sessionChanged:
            self.resetData()
        if self.cursor.hasChanged() or sessionChanged:
            if self.cursor.value:
                self.window.setBgOpacity(0.4).border(0)
                self.window.showTitle(True)
                self.btn_reset.setVisible(1)
                ac.setVisible(self.spin_row_height, 1)
            else:
                self.window.setBgOpacity(0).border(0)
                self.window.showTitle(False)
                self.btn_reset.setVisible(0)
                ac.setVisible(self.spin_row_height, 0)

    def resetData(self):
        self.currentLap = []
        self.lastLapIsValid = True
        self.lapCount = 0
        self.highlight_end = 0

    def onUpdate(self, sim_info):
        if self.__class__.configChanged:
            self.saveCFG()
            self.__class__.configChanged = False
        if not self.deltaLoaded:
            thread_load = threading.Thread(target=self.loadDelta)
            thread_load.daemon = True
            thread_load.start()
        if self.__class__.resetPressed:
            self.referenceLapTime.setValue(0)
            self.referenceLap = []
            self.__class__.resetPressed = False
        self.session.setValue(sim_info.graphics.session)
        self.manageWindow()
        self.lbl_delta.animate()
        self.lbl_lap.animate()
        sim_info_status = sim_info.graphics.status
        if sim_info_status == 2:  # LIVE
            sessionTimeLeft = sim_info.graphics.sessionTimeLeft
            if math.isinf(
                sessionTimeLeft
            ):  # or (sim_info.graphics.iCurrentTime == 0 and sim_info.graphics.completedLaps == 0):
                self.resetData()
            elif self.session.value == 2 and sessionTimeLeft > 1800000:
                self.resetData()
            elif bool(ac.isCarInPitline(0)) or bool(ac.isCarInPit(0)):
                self.resetData()
            self.spline.setValue(round(ac.getCarState(0, acsys.CS.NormalizedSplinePosition), 3))

            if self.lastLapIsValid and sim_info.physics.numberOfTyresOut >= 4:
                self.lastLapIsValid = False

            if self.spline.hasChanged():
                self.laptime.setValue(round(ac.getCarState(0, acsys.CS.LapTime), 3))
                self.lastLapTime.setValue(ac.getCarState(0, acsys.CS.LastLap))
                gap = self.getPerformanceGap(self.spline.value, self.laptime.value)
                if gap != False:
                    self.performance.setValue(gap)
                # new lap
                if self.lastLapTime.hasChanged():
                    # ac.console("newlap----")(self.laptime.old > self.laptime.value) or
                    # ac.console("lastLap=currentLap---waiting " + str(self.laptime.old) + ":" + str(self.laptime.value))
                    # ac.log(str(time.time()) +" lastLap=currentLap---waiting " + str(self.laptime.old) + ":" + str(self.laptime.value))
                    if (
                        (self.referenceLapTime.value == 0 or self.lastLapTime.value < self.referenceLapTime.value)
                        and self.lastLapIsValid
                        and self.lastLapTime.value > 0
                        and self.lapCount < ac.getCarState(0, acsys.CS.LapCount)
                    ):
                        self.referenceLapTime.setValue(self.lastLapTime.value)
                        # self.referenceLap=list(self.lastLap)
                        self.referenceLap = list(self.currentLap)
                        if len(self.referenceLap) > 2000:  # 2laps in
                            ac.console("too many laps in reference----")
                            ac.log("too many laps in reference----")
                            how_much = math.floor(len(self.referenceLap) / 1000)
                            del self.referenceLap[0 : math.floor(len(self.referenceLap) / how_much)]
                        # self.referenceLap=self.lastLap#self.lastLap=list(self.currentLap)
                        # ac.log(str(time.time()) +" referenceLap=lastlap --- lets save")
                        # ac.console("referenceLap=lastlap --- lets save")
                        thread_save = threading.Thread(target=self.saveDelta)
                        thread_save.daemon = True
                        thread_save.start()
                        # make it green for 5 sec
                        self.highlight_end = sim_info.graphics.sessionTimeLeft - 6000
                        self.lbl_lap.setColor(Colors.green(), True)
                    # else:
                    #    ac.log(str(time.time()) +" dismissed")
                    # self.lastLap=self.currentLap
                    self.currentLap = []
                    self.lapCount = ac.getCarState(0, acsys.CS.LapCount)
                    self.lastLapIsValid = True

                self.currentLap.append(raceGaps(self.spline.value, self.laptime.value))
                # ac.console("--currentLap : " + str(len(self.currentLap)) + " --lastLap : " + str(len(self.lastLap)) + " --referenceLap : " + str(len(self.referenceLap)))

            # update graphics
            if not math.isinf(sessionTimeLeft):
                self.TimeLeftUpdate.setValue(int(sessionTimeLeft / 500))
            if self.TimeLeftUpdate.hasChanged():
                if self.performance.hasChanged():
                    time_prefix = ""
                    color = Colors.white()
                    if self.performance.value > 0:
                        time_prefix = "+"
                        if self.lastLapIsValid:
                            color = Colors.yellow()
                        else:
                            color = Colors.red()
                    elif self.performance.value < 0:
                        time_prefix = "-"
                        if self.lastLapIsValid:
                            color = Colors.green()
                        else:
                            color = Colors.orange()
                    else:
                        if not self.lastLapIsValid:
                            color = Colors.red()
                    self.lbl_delta.setText(
                        time_prefix + self.time_splitting(abs(self.performance.value), "yes")
                    ).setColor(color, True)

            if self.referenceLapTime.hasChanged():
                self.lbl_lap.setText(self.time_splitting(self.referenceLapTime.value, "yes"))
            if self.highlight_end == 0 or sessionTimeLeft < self.highlight_end:
                self.lbl_lap.setColor(Colors.white(), True)