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()
class Configuration: configChanged = False race_mode = 0 qual_mode = 0 lapCanBeInvalidated = 1 max_num_cars = 18 max_num_laps_stint = 8 ui_row_height = 36 # INITIALIZATION def __init__(self): self.session = Value(-1) self.listen_active = True self.window = Window(name="ACTV Config", icon=True, width=251, height=480, texture="").setBgOpacity(0.6) y = 60 self.spin_race_mode = ac.addSpinner(self.window.app, "Race tower mode :") ac.setRange(self.spin_race_mode, 0, 2) ac.setPosition(self.spin_race_mode, 20, y) ac.setValue(self.spin_race_mode, self.__class__.race_mode) ac.addOnValueChangeListener(self.spin_race_mode, self.onSpinRaceModeChanged) self.lbl_race_mode = ( Label(self.window.app, "Auto") .setSize(120, 26) .setPos(186, y - 28) .setFontSize(12) .setAlign("left") .setVisible(1) ) y += 80 self.spin_qual_mode = ac.addSpinner(self.window.app, "Qual tower mode :") ac.setRange(self.spin_qual_mode, 0, 1) ac.setPosition(self.spin_qual_mode, 20, y) ac.setValue(self.spin_qual_mode, self.__class__.qual_mode) ac.addOnValueChangeListener(self.spin_qual_mode, self.onSpinQualModeChanged) self.lbl_qual_mode = ( Label(self.window.app, "Gaps") .setSize(120, 26) .setPos(186, y - 28) .setFontSize(12) .setAlign("left") .setVisible(1) ) y += 80 self.spin_num_cars = ac.addSpinner(self.window.app, "Number cars tower") ac.setRange(self.spin_num_cars, 6, 28) ac.setPosition(self.spin_num_cars, 20, y) ac.setValue(self.spin_num_cars, self.__class__.max_num_cars) ac.addOnValueChangeListener(self.spin_num_cars, self.onSpinNumCarsChanged) y += 80 self.spin_num_laps = ac.addSpinner(self.window.app, "Number laps stint mode") ac.setRange(self.spin_num_laps, 2, 28) ac.setPosition(self.spin_num_laps, 20, y) ac.setValue(self.spin_num_laps, self.__class__.max_num_laps_stint) ac.addOnValueChangeListener(self.spin_num_laps, self.onSpinNumLapsChanged) y += 80 self.spin_row_height = ac.addSpinner(self.window.app, "Row height") ac.setRange(self.spin_row_height, 20, 48) ac.setPosition(self.spin_row_height, 20, y) ac.setValue(self.spin_row_height, self.__class__.ui_row_height) ac.addOnValueChangeListener(self.spin_row_height, self.onSpinRowHeightChanged) y += 60 self.chk_invalidated = ac.addCheckBox(self.window.app, "") ac.setPosition(self.chk_invalidated, 20, y) ac.addOnCheckBoxChanged(self.chk_invalidated, self.onCheckInvalidatedChanged) self.lbl_title_invalidated = ( Label(self.window.app, "Lap can be invalidated") .setSize(200, 26) .setPos(65, y + 1) .setFontSize(16) .setAlign("left") .setVisible(1) ) self.cfg_loaded = False self.cfg = Config("apps/python/prunn/", "config.ini") self.loadCFG() # thread self.key_listener = threading.Thread(target=self.listen_key) self.key_listener.daemon = True self.key_listener.start() def __del__(self): self.listen_active = False def loadCFG(self): self.__class__.lapCanBeInvalidated = self.cfg.get("SETTINGS", "lap_can_be_invalidated", "int") if self.__class__.lapCanBeInvalidated == -1: self.__class__.lapCanBeInvalidated = 1 self.__class__.max_num_cars = self.cfg.get("SETTINGS", "num_cars_tower", "int") if self.__class__.max_num_cars == -1: self.__class__.max_num_cars = 18 self.__class__.max_num_laps_stint = self.cfg.get("SETTINGS", "num_laps_stint", "int") if self.__class__.max_num_laps_stint == -1: self.__class__.max_num_laps_stint = 8 self.__class__.ui_row_height = self.cfg.get("SETTINGS", "ui_row_height", "int") if self.__class__.ui_row_height == -1: self.__class__.ui_row_height = 36 self.__class__.race_mode = self.cfg.get("SETTINGS", "race_mode", "int") if self.__class__.race_mode == -1: self.__class__.race_mode = 0 self.__class__.qual_mode = self.cfg.get("SETTINGS", "qual_mode", "int") if self.__class__.qual_mode == -1: self.__class__.qual_mode = 0 ac.setValue(self.spin_race_mode, self.__class__.race_mode) ac.setValue(self.spin_qual_mode, self.__class__.qual_mode) ac.setValue(self.spin_num_cars, self.__class__.max_num_cars) ac.setValue(self.spin_num_laps, self.__class__.max_num_laps_stint) ac.setValue(self.spin_row_height, self.__class__.ui_row_height) ac.setValue(self.chk_invalidated, self.__class__.lapCanBeInvalidated) self.setLabelQual() self.setLabelRace() self.cfg_loaded = True def saveCFG(self): self.setLabelRace() self.setLabelQual() self.cfg.set("SETTINGS", "race_mode", self.__class__.race_mode) self.cfg.set("SETTINGS", "qual_mode", self.__class__.qual_mode) self.cfg.set("SETTINGS", "lap_can_be_invalidated", self.__class__.lapCanBeInvalidated) self.cfg.set("SETTINGS", "num_cars_tower", self.__class__.max_num_cars) self.cfg.set("SETTINGS", "num_laps_stint", self.__class__.max_num_laps_stint) self.cfg.set("SETTINGS", "ui_row_height", self.__class__.ui_row_height) def setLabelQual(self): if self.__class__.qual_mode == 0: self.lbl_qual_mode.setText("Gaps") else: self.lbl_qual_mode.setText("Times") def setLabelRace(self): if self.__class__.race_mode == 0: self.lbl_race_mode.setText("Auto") elif self.__class__.race_mode == 1: self.lbl_race_mode.setText("Full-Gaps") else: self.lbl_race_mode.setText("Full") def onUpdate(self, sim_info): self.window.setBgOpacity(0.6).border(0) self.session.setValue(sim_info.graphics.session) if self.__class__.configChanged and self.cfg_loaded: self.saveCFG() self.__class__.configChanged = False return True elif self.__class__.configChanged and not self.cfg_loaded: self.__class__.configChanged = False return False def listen_key(self): try: # ctypes.windll.user32.RegisterHotKey(None, 1, 0, apps.util.win32con.VK_F7) ctypes.windll.user32.RegisterHotKey(None, 1, apps.util.win32con.MOD_CONTROL, 0x44) # CTRL+D msg = ctypes.wintypes.MSG() while self.listen_active: if ctypes.windll.user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0: # ac.console("loopmess."+ str(msg.message)) if msg.message == apps.util.win32con.WM_HOTKEY: self.hotkey_pressed() ctypes.windll.user32.TranslateMessage(ctypes.byref(msg)) ctypes.windll.user32.DispatchMessageA(ctypes.byref(msg)) except: Log.w("Error") finally: ctypes.windll.user32.UnregisterHotKey(None, 1) def hotkey_pressed(self): if self.session.value == 2: if self.__class__.race_mode >= 2: self.__class__.race_mode = 0 else: self.__class__.race_mode += 1 ac.setValue(self.spin_race_mode, self.__class__.race_mode) else: if self.__class__.qual_mode >= 1: self.__class__.qual_mode = 0 else: self.__class__.qual_mode += 1 ac.setValue(self.spin_qual_mode, self.__class__.qual_mode) self.__class__.configChanged = True @staticmethod def onCheckInvalidatedChanged(name, state): Configuration.lapCanBeInvalidated = state Configuration.configChanged = True @staticmethod def onSpinNumCarsChanged(value): Configuration.max_num_cars = value Configuration.configChanged = True @staticmethod def onSpinNumLapsChanged(value): Configuration.max_num_laps_stint = value Configuration.configChanged = True @staticmethod def onSpinRowHeightChanged(value): Configuration.ui_row_height = value Configuration.configChanged = True @staticmethod def onSpinRaceModeChanged(value): Configuration.race_mode = value Configuration.configChanged = True @staticmethod def onSpinQualModeChanged(value): Configuration.qual_mode = value Configuration.configChanged = True
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")
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()
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)