Advertisement
ThanoslBsl

Untitled

Jun 25th, 2017
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 39.32 KB | None | 0 0
  1. # This program is free software: you can redistribute it and/or modify
  2. # it under the terms of the GNU General Public License as published by
  3. # the Free Software Foundation, either version 3 of the License, or
  4. # (at your option) any later version.
  5. #
  6. # This program is distributed in the hope that it will be useful,
  7. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. # GNU General Public License for more details.
  10. #
  11. # You should have received a copy of the GNU General Public License
  12. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. # Copyright (C) 2015 - Murilo Faria
  14. # Version: 1.0.5
  15.  
  16. #TODO:
  17. #CHECK THE ZIPPED PY FOR UPDATES
  18.  
  19. import os
  20. import sys
  21. import configparser
  22. import ac
  23. import acsys
  24. import datetime
  25. import win32con
  26. from time import clock, localtime, strftime
  27.  
  28. import platform
  29. if platform.architecture()[0] == "64bit":
  30. sysdir=os.path.dirname(__file__)+'/stdlib64'
  31. else:
  32. sysdir=os.path.dirname(__file__)+'/stdlib'
  33. sys.path.insert(0, sysdir)
  34. os.environ['PATH'] = os.environ['PATH'] + ";."
  35.  
  36. import ctypes
  37. from ctypes import wintypes
  38.  
  39. #from sim_info import info
  40. import sim_info
  41. import threading
  42.  
  43. windowx = 110
  44. windowy = windowx * 0.4181818181818182
  45. scale_mult = windowx/110
  46. windowsscale = 2.3913
  47.  
  48. compound = None #tyre compound
  49. #labels = {}
  50. appWindow = 0
  51. startTracking = False
  52. lastPOT = 0.0 # "POS0.00"
  53. dic = {}
  54. lastTime = 0.0
  55. lastClock = 0.0
  56. lastLapTime = 0.0
  57. lastRealTime = 0.0
  58. TimeOfLastOff = 0.0
  59. recentDelta = 0.0
  60. pitOffset = 0.0
  61. bSetOffset = 0
  62. lastF10Click = 0
  63. deltaStringFormat = "%.2f"
  64. trend = 0
  65. alpha = 1.0
  66. backgroundOpacity = 1.0
  67. drawBorderVar = 1
  68. fullSpeed = 0
  69. prevDelta = 0.0
  70. InitialPosition = 0
  71. Range = 0.06 # originaly 0.001, but this would ultimately depend on the length of the track
  72. SettingsINI = 'apps\python\EsoticDelta\settings.ini'
  73. AdjustIntensity = 1
  74. ResetDuringPit = 0
  75. ResetDuringQualification = 1
  76. ResetDuringPractice = 1
  77. HideIcon = 1
  78. ResetOnCompoundSwitch = 1
  79. UsePitOffset = 1
  80. LastStatus = 0
  81. LastSession = 0
  82. LapValid = 1
  83. displayLabel = 0
  84. ShowLapTimeDelay = 4000.0 #time (in milliseconds) to show the last lap time
  85. allowedtyresout = 4 #default to not tracking valid laps
  86. veritcalAdjust = -3 #ADD TO INI?
  87. MinKPH = 0
  88. MaxKPH = 0
  89. #reset camera while pitting? DONE WITH THE PIT_STOP.INI
  90. #Camera = 0
  91. #CameraTrigger = 0
  92. #CameraChanger = 1 #configini.getboolean('UI', 'pitcamerachanger')
  93. LapTimesOnly = 0 #add this to the INI? Make a "settings" Interface?
  94. key_listener = 0
  95. useHotkey = 1
  96.  
  97. colors = {
  98. "white" : [255, 255, 255],
  99. "yellow" : [255, 255, 0],
  100. "green" : [2, 221, 20],
  101. "red" : [252, 35, 35],
  102. "purple" : [255,0,255],
  103. "aqua" : [0,255,255],
  104. "violet" : [255,150,255],
  105. "blue" : [0,0,255],
  106. "orange" : [255,140,0]
  107. }
  108.  
  109. ##### Create Custom Class (code from RevHunter) #####
  110. class Label:
  111. def __init__(self,appWindow,text = ""):
  112. self.label = ac.addLabel(appWindow, " ")
  113. self.labelText = text
  114. self.labelSize = {"width" : 0, "height" : 0}
  115. self.labelPosition = {"xpos" : 0, "ypos" : 0}
  116. self.labelFontSize = 12
  117. self.labelFontAlign = "left"
  118. self.labelFontColor = {"red" : 1, "green" : 1, "blue" : 1, "alpha" : 0}
  119.  
  120. def setText(self, text):
  121. self.labelText = text
  122. ac.setText(self.label, self.labelText)
  123. return self
  124.  
  125. def setSize(self, width, height):
  126. self.labelSize["width"] = width
  127. self.labelSize["height"] = height
  128. ac.setSize(self.label, self.labelSize["width"], self.labelSize["height"])
  129. return self
  130.  
  131. def setPosition(self, xposition, yposition):
  132. self.labelPosition["xposition"] = xposition
  133. self.labelPosition["yposition"] = yposition
  134. ac.setPosition(self.label, self.labelPosition["xposition"],self.labelPosition["yposition"])
  135. return self
  136.  
  137. def setFontSize(self, fontSize):
  138. self.labelFontSize = fontSize
  139. ac.setFontSize(self.label, self.labelFontSize)
  140. return self
  141.  
  142. def setFontAlign(self, fontAlign = "left"):
  143. self.labelFontAlign = fontAlign
  144. ac.setFontAlignment(self.label, self.labelFontAlign)
  145. return self
  146.  
  147. def setFontColor(self, red, green, blue, alpha):
  148. self.labelFontColor["red"] = red
  149. self.labelFontColor["green"] = green
  150. self.labelFontColor["blue"] = blue
  151. self.labelFontColor["alpha"] = alpha
  152. ac.setFontColor(self.label, self.labelFontColor["red"],self.labelFontColor["green"],self.labelFontColor["blue"],self.labelFontColor["alpha"])
  153. return self
  154.  
  155.  
  156. def acMain(ac_version):
  157. global appWindow, HideIcon, displayLabel, key_listener
  158.  
  159. ReadSettings()
  160.  
  161. appWindow = ac.newApp("EsoticDelta")
  162. ac.setSize(appWindow, windowx, windowy)
  163. #createLabel("deltaLabel", "+0.00", -47, 0, 30)
  164.  
  165. displayLabel = Label(appWindow).setSize(0,0).setPosition((windowx / 2),(windowy*0.0) + veritcalAdjust).setFontSize(30*scale_mult).setFontAlign("center").setText(formatDelta(0.0, deltaStringFormat)) #.setFontColor(*rgb(colors["green"], 1.0)
  166.  
  167. if HideIcon == 1:
  168. ac.setIconPosition(appWindow, 0, -9000)
  169.  
  170. ac.setTitle(appWindow, "")
  171.  
  172. if useHotkey == 1:
  173. ConsoleLog("PD Before Key Listener")
  174. key_listener = threading.Thread(target=listen_key)
  175. key_listener.daemon = True
  176. key_listener.start()
  177. ConsoleLog("PD After Key Listener")
  178.  
  179. return "EsoticDelta"
  180.  
  181. #def createLabel(name, text, x, y, font_size):
  182. # global app, labels
  183.  
  184. # label = ac.addLabel(app, name)
  185. # ac.setText(label, text)
  186. # ac.setPosition(label, x, y)
  187. # ac.setFontSize(label, font_size)
  188. # ac.setFontAlignment(label, "center")
  189. # #ac.setBackgroundOpacity(label, 1.0)
  190. # labels[name] = label
  191.  
  192.  
  193. def timeToMinSecMsecTuple(t):
  194. mins = t // (60*1000)
  195. secs = (t - 60*1000*mins) // 1000
  196. msecs = (t - 60*1000*mins - secs*1000)
  197. return (mins, secs, msecs)
  198.  
  199. def formatTime(t):
  200. mins, secs, msecs = timeToMinSecMsecTuple(abs(t))
  201. time = "%02d:%02d.%03d" % (mins, secs, msecs)
  202. return time
  203.  
  204. def formatLapTime(t):
  205. mins, secs, msecs = timeToMinSecMsecTuple(abs(t))
  206. msecs = msecs / 100
  207. time = "%01d:%02d.%1d" % (mins, secs, msecs)
  208. return time
  209.  
  210. def formatLapTime3Digits(t):
  211. mins, secs, msecs = timeToMinSecMsecTuple(abs(t))
  212. #msecs = msecs / 100
  213. time = "%01d:%02d.%03d" % (mins, secs, msecs)
  214. return time
  215.  
  216. def ConsoleLog(message):
  217. ac.console(message)
  218. ac.log(message)
  219.  
  220. def getDelta(posOnTrack, lapTime, LapValid):
  221. global lastPOT, lastLapTime, lastRealTime, dic
  222. delta = 0.00
  223.  
  224. message = "POT = %.4f, lapTime = %s, LapValid = %d" % (posOnTrack, formatTime(lapTime), LapValid)
  225. #ac.console(message)
  226. #ac.log(message)
  227.  
  228. if True:
  229. #4 digits of precision, updated precision below in interpolation
  230. smallestDiff = 0.0001
  231. potAttr = "POT%.4f"%(posOnTrack)
  232. deltaAttr = "DLT%.4f"%(posOnTrack)
  233. lastPOTKey = "POT%.4f"%(lastPOT)
  234. else:
  235. #3 digits of precision
  236. smallestDiff = 0.001
  237. potAttr = "POT%.3f"%(posOnTrack)
  238. deltaAttr = "DLT%.3f"%(posOnTrack)
  239. lastPOTKey = "POT%.3f"%(lastPOT)
  240.  
  241. #ac.log("100")
  242. deltaRealTime = 0.0
  243. if lastLapTime == lapTime:
  244. #ac.log("110")
  245. #assume AC is not updating lapTime effectively?
  246. if lastRealTime != 0.0:
  247. #ac.log("120")
  248. deltaRealTime = clock() - lastRealTime
  249. #ac.log("130")
  250. message = "deltaRealTime = %s" % (formatDelta(deltaRealTime, deltaStringFormat))
  251. #ac.log("140")
  252. #ac.console(message)
  253. else:
  254. #set this everytime lapTime is properly updated
  255. #ac.log("150")
  256. lastRealTime = clock()
  257.  
  258. if lastLapTime != lapTime or deltaRealTime > 0.0:
  259. #ac.log("200")
  260. #only process if POT is newer? would need floats
  261. if potAttr != lastPOTKey:
  262. #ac.log("300")
  263. bestPOTTime = dic.get(potAttr, lapTime + deltaRealTime)
  264. #ac.log("310")
  265. #this should adjust for lack of timing updates in replays
  266. currPOTTime = lapTime + deltaRealTime
  267. #ac.log("320")
  268. delta = currPOTTime - bestPOTTime
  269.  
  270. message = "bestPOTTime = %s, currPOTTime = %s, delta = %s" % (formatTime(bestPOTTime), formatTime(currPOTTime), formatDelta(delta, deltaStringFormat))
  271. #ac.console(message)
  272. #ac.log(message)
  273. #write this regardless, cuz we might need it soon
  274. dic[deltaAttr] = delta
  275.  
  276. #get dic to lowest valid value possible
  277. if LapValid == 1:
  278. if dic.get(potAttr, 0) == 0:
  279. message = "zero, " + potAttr + " = " + formatTime(currPOTTime)
  280. #message = "zero, " + potAttr + message
  281. message = message + " at " + str(datetime.datetime.now())
  282. #ac.log(message)
  283. #ac.console(message)
  284. #ac.log(message)
  285. dic[potAttr] = currPOTTime
  286. elif currPOTTime < bestPOTTime: #dic.get(potAttr, 0):
  287. dic[potAttr] = currPOTTime
  288. message = "best, " + potAttr + " = " + formatTime(currPOTTime)
  289. #ac.log(message)
  290. #ac.console(message)
  291. if round(lastPOT + smallestDiff, 4) < round(posOnTrack, 4):
  292. #interpolate/calc all the values between lastPOT and posOnTrack
  293. message = "calc %.4f < %.4f" % (lastPOT + smallestDiff, posOnTrack)
  294. #ac.console(message)
  295. #ac.log(message)
  296. tmpPOT = lastPOT
  297. tmpTime = lastLapTime # dic.get(lastPOTKey, currPOTTime) # bestPOTTime
  298.  
  299. message = "tmpPOT = %.4f, tmpTime = %s" % (tmpPOT, formatTime(tmpTime))
  300. #ac.log(message)
  301.  
  302. #time delta is CurrentPOT - LastPOT / ((CurrentPot - LastPOT) / smallestDiff)
  303. #THIS CALCULATION MAY BE OFF, or may need more precision for the tight variances we're dealing with
  304. #need to dump some log files to inspect the logic that is happening at high speed
  305. intDenom = int((posOnTrack - lastPOT) / smallestDiff) * 1.0
  306. message = "intDenom = %d" % intDenom
  307. #ac.log(message)
  308. #ac.console(message)
  309.  
  310. timeSlice = 0.0
  311.  
  312. #convert the times to floats and then do the division?
  313. numLapTime = formatDeltaNumOnly(currPOTTime)
  314. numTmpTime = formatDeltaNumOnly(tmpTime)
  315. message = "numLapTime = %.4f, numTmpTime = %.4f" % (numLapTime, numTmpTime)
  316. #ac.log(message)
  317. timeSlice = (numLapTime - numTmpTime) / intDenom
  318.  
  319. strSlice = "%.4f" % timeSlice
  320. message = "strSlice = " + strSlice
  321. #ac.log(message)
  322.  
  323. #time values are in milliseconds
  324. timeSlice = timeSlice * 1000
  325.  
  326. tmpPOT = tmpPOT + smallestDiff
  327. message = "tmpPOT = %.4f, posOnTrack = %.4f" % (tmpPOT, posOnTrack)
  328. #ac.log(message)
  329. while round(tmpPOT, 4) < round(posOnTrack, 4):
  330. #interpolate
  331. message = "int %.4f < %.4f" % (tmpPOT, posOnTrack)
  332. #ac.console(message)
  333. #ac.log(message)
  334. tmpTime = tmpTime + timeSlice
  335. tmpPotAttr = "POT%.4f"%(tmpPOT)
  336. deltaAttr = "DLT%.4f"%(tmpPOT)
  337. #dic[deltaAttr] is only for loading a previously calculated delta on consecutive calls with same POT
  338. #dic[deltaAttr] = delta
  339. if tmpPotAttr != potAttr:
  340. if dic.get(tmpPotAttr, 0) == 0:
  341. message = "zint, " + tmpPotAttr + " = " + formatTime(tmpTime)
  342. #ac.log(message)
  343. #ac.console(message)
  344. dic[tmpPotAttr] = tmpTime
  345. elif currPOTTime < bestPOTTime: #dic.get(potAttr, 0):
  346. message = "bint, " + tmpPotAttr + " = " + formatTime(tmpTime)
  347. #ac.log(message)
  348. #ac.console(message)
  349. dic[tmpPotAttr] = tmpTime
  350. tmpPOT = tmpPOT + smallestDiff
  351. else:
  352. delta = dic.get(deltaAttr, 0)
  353. #ac.console("100")
  354. #ac.log("100")
  355. message = "Retrieved delta from dic = %s" % (formatDelta(delta, "%.2f"))
  356. #ac.console(message)
  357. #ac.log(message)
  358.  
  359. #only set this if lap times are different
  360. lastPOT = posOnTrack
  361. else:
  362. deltaAttr = "DLT%.4f"%(lastPOT)
  363. if deltaAttr in dic:
  364. delta = dic[deltaAttr]
  365. message = "Retrieved delta from dic = %s" % (formatDelta(delta, "%.2f"))
  366. #ac.log(message)
  367.  
  368. #set this all the time?
  369. lastLapTime = lapTime
  370.  
  371. return delta
  372.  
  373. def formatSplit(t):
  374. mins, secs, msecs = timeToMinSecMsecTuple(abs(t))
  375.  
  376. if mins > 0:
  377. secs = (mins * 60) + secs
  378.  
  379. return "%02d.%03d" % (secs, msecs)
  380.  
  381. def formatDiff(t):
  382. mins, secs, msecs = timeToMinSecMsecTuple(abs(t))
  383.  
  384. if mins > 0:
  385. secs = (mins * 60) + secs
  386.  
  387. if t < 0:
  388. pre = "-"
  389. else:
  390. pre = "+"
  391.  
  392. return pre + "%01d.%03d" % (secs, msecs)
  393.  
  394. def formatDelta(t, format):
  395. mins, secs, msecs = timeToMinSecMsecTuple(abs(t))
  396.  
  397. if mins > 0:
  398. secs = (mins * 60) + secs
  399.  
  400. if t < 0:
  401. pre = "-"
  402. else:
  403. pre = "+"
  404.  
  405. time = secs + (msecs / 1000.0)
  406.  
  407. #return pre + "%01d.%02d" % (secs, msecs)
  408. #return pre + "%.2f" % time
  409. return pre + format % time
  410.  
  411. def formatDeltaNumOnly(t):
  412. mins, secs, msecs = timeToMinSecMsecTuple(abs(t))
  413.  
  414. if mins > 0:
  415. secs = (mins * 60) + secs
  416.  
  417. time = secs + (msecs / 1000.0)
  418.  
  419. if t < 0:
  420. time = time * -1
  421.  
  422. #return pre + "%01d.%02d" % (secs, msecs)
  423. return time
  424.  
  425. def formatDeltaNumOnlyHundreths(t):
  426. mins, secs, msecs = timeToMinSecMsecTuple(abs(t))
  427.  
  428. if mins > 0:
  429. secs = (mins * 60) + secs
  430.  
  431. time = secs + (msecs / 1000.0)
  432.  
  433. if t < 0:
  434. time = time * -1
  435.  
  436. return "%01d.%02d" % (secs, msecs)
  437. #return time
  438.  
  439. def rgb(color, a = 1.0, bg = False):
  440. r = color[0] / 255
  441. g = color[1] / 255
  442. b = color[2] / 255
  443. if bg == False:
  444. return r, g, b, a
  445. else:
  446. return r, g, b
  447.  
  448.  
  449. def WriteSettings():
  450. global SettingsINI #, AdjustIntensity, ResetDuringPit, HideIcon, ResetOnCompoundSwitch, windowx, deltaStringFormat
  451.  
  452. try:
  453. section = 'SETTINGS'
  454.  
  455. SettingsConfig = configparser.ConfigParser()
  456. if os.path.isfile(SettingsINI):
  457. SettingsConfig.read(SettingsINI)
  458. else:
  459. ac.console("EsoticDelta writing new settings.ini")
  460.  
  461. if not SettingsConfig.has_section(section):
  462. SettingsConfig.add_section(section)
  463.  
  464. SettingsConfig.set(section,'AdjustIntensity','%d' % AdjustIntensity)
  465. SettingsConfig.set(section,'ResetDuringPit','%d' % ResetDuringPit)
  466. SettingsConfig.set(section,'ResetDuringPractice','%d' % ResetDuringPractice)
  467. SettingsConfig.set(section,'ResetDuringQualification','%d' % ResetDuringQualification)
  468. SettingsConfig.set(section,'HideIcon','%d' % HideIcon)
  469. SettingsConfig.set(section,'AppWidth','%d' % windowx)
  470. SettingsConfig.set(section,'ShowLapTimeDelay','%0.1f' % ShowLapTimeDelay)
  471. SettingsConfig.set(section,'ThreeDigitPrecision','0')
  472. SettingsConfig.set(section,'backgroundOpacity', '%0.1f' % backgroundOpacity)
  473. SettingsConfig.set(section,'drawBorder','%d' % drawBorderVar)
  474. SettingsConfig.set(section,'fullSpeed','%d' % fullSpeed)
  475. SettingsConfig.set(section,'allowedtyresout', '%d' % allowedtyresout)
  476. #UsePitOffset
  477. SettingsConfig.set(section,'UsePitOffset','%d' % UsePitOffset)
  478. SettingsConfig.set(section,'usehotkey', '%d' % useHotkey)
  479.  
  480. with open(SettingsINI, 'w') as configfile:
  481. configfile.write(';Set Values to 1 to turn them on, 0 to turn them off.' + '\n')
  482. configfile.write(';AdjustIntensity toggles showing brighter/dimmer for trending.' + '\n')
  483. configfile.write(';ResetDuringPit toggles resetting delta during pit stop regardless of tire change.' + '\n')
  484. configfile.write(';ResetDuringQualification toggles resetting delta during qualification pit stops regardless of tire change. This is a qualifier for ResetDuringPit, which must be enabled for this to have any effect.' + '\n')
  485. configfile.write(';ResetDuringPractice toggles resetting delta during practice pit stops regardless of tire change. This is a qualifier for ResetDuringPit, which must be enabled for this to have any effect.' + '\n')
  486. configfile.write(';UsePitOffset toggles an adjustment to the lap time to try to make deltas when exiting the pits more relevant. Work in Progress.' + '\n')
  487. configfile.write(';HideIcon hides AC icon.' + '\n')
  488. configfile.write(';Default AppWidth is 110. Change this value to resize the app larger/smaller.' + '\n')
  489. configfile.write(';Default ShowLapTimeDelay is 4000.0 milliseconds, set it to 0.0 to disable it.' + '\n')
  490. configfile.write(';ThreeDigitPrecision toggles showing 2 or 3 digits after the decimal.' + '\n')
  491. configfile.write(';Default backgroundOpacity is 1.0, but you can set it anywhere from 0.0 (transparent) to 1.0 (fully opaque).' + '\n')
  492. configfile.write(';drawBorder toggles drawing the app border.' + '\n')
  493. configfile.write(';fullSpeed toggles showing delta at full speed or every .1 seconds.' + '\n')
  494. configfile.write(';allowedtyresout controls detecting off-lap incidents. set to 4 to disable tracking valid laps (the default), or 1, 2, or 3 to enable.' + '\n')
  495. configfile.write(';UseHotkey enables the F10 hotkey to clear the current values.' + '\n')
  496.  
  497. SettingsConfig.write(configfile)
  498.  
  499. return 1
  500.  
  501. except:
  502. exc_type, exc_value, exc_traceback = sys.exc_info()
  503. ac.console('WriteSettings Error (logged to file)')
  504. ac.log(repr(traceback.format_exception(exc_type, exc_value, exc_traceback)))
  505.  
  506. def ReadSettings():
  507. global SettingsINI, AdjustIntensity, ResetDuringPit, ResetDuringPractice, ResetDuringQualification, UsePitOffset, HideIcon, ResetOnCompoundSwitch, ShowLapTimeDelay
  508. global deltaStringFormat, backgroundOpacity, drawBorderVar, fullSpeed, allowedtyresout
  509. global windowx, windowy, scale_mult, useHotkey
  510.  
  511. try:
  512. if os.path.isfile(SettingsINI):
  513. section = 'SETTINGS'
  514. SettingsConfig = configparser.ConfigParser()
  515. SettingsConfig.read(SettingsINI)
  516. boolWriteSettings = False
  517.  
  518. if SettingsConfig.has_option(section, 'AdjustIntensity'):
  519. AdjustIntensity = SettingsConfig.getint(section, 'AdjustIntensity')
  520. else:
  521. boolWriteSettings = True
  522.  
  523. if SettingsConfig.has_option(section, 'ResetDuringPit'):
  524. ResetDuringPit = SettingsConfig.getint(section, 'ResetDuringPit')
  525. else:
  526. boolWriteSettings = True
  527.  
  528. if SettingsConfig.has_option(section, 'ResetDuringPractice'):
  529. ResetDuringPractice = SettingsConfig.getint(section, 'ResetDuringPractice')
  530. else:
  531. boolWriteSettings = True
  532.  
  533. if SettingsConfig.has_option(section, 'ResetDuringQualification'):
  534. ResetDuringQualification = SettingsConfig.getint(section, 'ResetDuringQualification')
  535. else:
  536. boolWriteSettings = True
  537.  
  538. #UsePitOffset
  539. if SettingsConfig.has_option(section, 'UsePitOffset'):
  540. UsePitOffset = SettingsConfig.getint(section, 'UsePitOffset')
  541. else:
  542. boolWriteSettings = True
  543.  
  544. if SettingsConfig.has_option(section, 'HideIcon'):
  545. HideIcon = SettingsConfig.getint(section, 'HideIcon')
  546. else:
  547. boolWriteSettings = True
  548.  
  549. if SettingsConfig.has_option(section, 'ResetOnCompoundSwitch'):
  550. ResetOnCompoundSwitch = SettingsConfig.getint(section, 'ResetOnCompoundSwitch')
  551. else:
  552. boolWriteSettings = True
  553.  
  554. if SettingsConfig.has_option(section, 'AppWidth'):
  555. windowx = SettingsConfig.getint(section, 'AppWidth')
  556. else:
  557. boolWriteSettings = True
  558.  
  559. #this sets the aspect for the window
  560. windowy = windowx * 0.4181818181818182
  561. #windowsx is 110 by default, so this sets the multiplier for all screen elements
  562. scale_mult = windowx/110
  563.  
  564. #override these values? per car?
  565. if SettingsConfig.has_option(section, 'AppHeight'):
  566. windowy = SettingsConfig.getint(section, 'AppHeight')
  567. if SettingsConfig.has_option(section, 'FontScale'):
  568. scale_mult = SettingsConfig.getfloat(section, 'FontScale')
  569.  
  570. #ShowLapTimeDelay
  571. if SettingsConfig.has_option(section, 'ShowLapTimeDelay'):
  572. ShowLapTimeDelay = SettingsConfig.getfloat(section, 'ShowLapTimeDelay')
  573. else:
  574. boolWriteSettings = True
  575.  
  576. #backgroundOpacity
  577. if SettingsConfig.has_option(section, 'backgroundOpacity'):
  578. backgroundOpacity = SettingsConfig.getfloat(section, 'backgroundOpacity')
  579. else:
  580. boolWriteSettings = True
  581.  
  582. #drawBorderVar
  583. if SettingsConfig.has_option(section, 'drawBorder'):
  584. drawBorderVar = SettingsConfig.getint(section, 'drawBorder')
  585. else:
  586. boolWriteSettings = True
  587.  
  588. #fullSpeed
  589. if SettingsConfig.has_option(section, 'fullSpeed'):
  590. fullSpeed = SettingsConfig.getint(section, 'fullSpeed')
  591. else:
  592. boolWriteSettings = True
  593.  
  594. if SettingsConfig.has_option(section, 'ThreeDigitPrecision'):
  595. ThreeDigitPrecision = SettingsConfig.getint(section, 'ThreeDigitPrecision')
  596. if ThreeDigitPrecision == 1:
  597. deltaStringFormat = "%.3f"
  598. else:
  599. boolWriteSettings = True
  600.  
  601. #allowedtyresout
  602. if SettingsConfig.has_option(section, 'allowedtyresout'):
  603. allowedtyresout = SettingsConfig.getint(section, 'allowedtyresout')
  604. else:
  605. boolWriteSettings = True
  606.  
  607. #useHotkey
  608. if SettingsConfig.has_option(section, 'useHotkey'):
  609. useHotkey = SettingsConfig.getint(section, 'useHotkey')
  610. else:
  611. boolWriteSettings = True
  612.  
  613. if boolWriteSettings == True:
  614. ac.console("EsoticDelta new settings found, writing new settings.ini")
  615. WriteSettings()
  616.  
  617. else:
  618. ac.console("EsoticDelta Unable to read settings.ini, using default values")
  619. WriteSettings()
  620.  
  621. except:
  622. exc_type, exc_value, exc_traceback = sys.exc_info()
  623. ac.console('ReadSettings Error (logged to file)')
  624. ac.log(repr(traceback.format_exception(exc_type, exc_value, exc_traceback)))
  625.  
  626.  
  627. def acUpdate(deltaT):
  628. global displayLabel, startTracking, appWindow, compound, lastTime, prevDelta, trend, alpha, InitialPosition, dic, Range, LastStatus, LastSession, LapValid, lastClock, MinKPH, MaxKPH, TimeOfLastOff, recentDelta, pitOffset, bSetOffset, lastF10Click
  629. #, Camera, CameraTrigger, CameraChanger
  630.  
  631. try:
  632. sim_info_obj = sim_info.SimInfo()
  633.  
  634. ac.setBackgroundOpacity(appWindow, backgroundOpacity)
  635. ac.drawBorder(appWindow, drawBorderVar)
  636.  
  637. bIsQually = False
  638. if sim_info_obj.graphics.session == 1:
  639. bIsQually = True
  640.  
  641. bIsPractice = False
  642. if sim_info_obj.graphics.session == 0:
  643. bIsPractice = True
  644.  
  645. if sim_info_obj.graphics.status != LastStatus or sim_info_obj.graphics.session != LastSession:
  646. #ac.console("status or session changed, startTracking = 0")
  647. #THIS IS JUST COMMENTED OUT FOR THE DEMO, SHOULD BE ON FOR DISTRIBUTION
  648. startTracking = False
  649. #ac.console("REVERT TO NORMAL")
  650.  
  651. LastStatus = sim_info_obj.graphics.status
  652. LastSession = sim_info_obj.graphics.session
  653.  
  654. if sim_info_obj.graphics.status == 2 or sim_info_obj.graphics.status == 1:
  655. #tmpcompound = str(sim_info_obj.graphics.tyreCompound)
  656. tmpcompound = ac.getCarTyreCompound(0)
  657.  
  658. if not compound == tmpcompound and ResetOnCompoundSwitch == 1:
  659. #clear the vars
  660. dic.clear()
  661. compound = tmpcompound
  662.  
  663. #normalizedSplinePosition = round(sim_info_obj.graphics.normalizedCarPosition, 4)
  664. normalizedSplinePosition = ac.getCarState(0,acsys.CS.NormalizedSplinePosition)
  665.  
  666. currentTime = sim_info_obj.graphics.iCurrentTime
  667.  
  668. if lastF10Click > 0:
  669. if abs(currentTime - lastF10Click) > 1000:
  670. #ConsoleLog("Timeout Clearing lastF10Click")
  671. lastF10Click = 0
  672.  
  673. #if sim_info.info.physics.numberOfTyresOut > 2
  674. numTyresOut = sim_info_obj.physics.numberOfTyresOut
  675. if numTyresOut > allowedtyresout:
  676. #this should be zero in a perfect world
  677. LapValid = 0
  678. if numTyresOut > 3:
  679. TimeOfLastOff = currentTime
  680. #ConsoleLog("TimeOfLastOff %.2f"%(TimeOfLastOff))
  681. if ((currentTime - TimeOfLastOff) > 5000.0) or currentTime < 1000.0:
  682. TimeOfLastOff = 0.0
  683.  
  684. #carDamage
  685. #dmgFront, dmgBack, dmgLeft, dmgRight, dmgMax = sim_info_obj.physics.carDamage
  686. #message = "Damage Front %.4f, Back %.4f, Left %.4f, Right %.4f, Max %.4f" % (dmgFront, dmgBack, dmgLeft, dmgRight, dmgMax)
  687. #ac.console(message)
  688.  
  689. #if replay use clock() instead of iCurrentTime? playback speed?
  690.  
  691. #position = "P%.4f"%(normalizedSplinePosition)
  692. #deltaLabel = labels["deltaLabel"]
  693.  
  694. #ac.setText(deltaLabel, position)
  695. Speed = ac.getCarState(0,acsys.CS.SpeedKMH)
  696. inPit = sim_info_obj.graphics.isInPit
  697.  
  698. #if inPit == True and CameraTrigger == 0 and CameraChanger == 1:
  699. # Camera = ac.getCameraMode()
  700. # CameraTrigger = 1
  701. #if inPit == False:
  702. # CameraTrigger = 0
  703.  
  704. inPit = ac.isCarInPitline(0)
  705.  
  706. #track when we cross the "start/finish" (actually cross over from 0.9999 to 0.0000)
  707. if lastPOT > 0.9 and normalizedSplinePosition < 0.1:
  708. #turn this off for now
  709. #ConsoleLog("MinKPH = %d, MaxKPH = %d"%(MinKPH, MaxKPH))
  710. MinKPH = Speed
  711. MaxKPH = Speed
  712. if inPit == False:
  713. pitOffset = 0.0
  714. #bSetOffset = 1
  715. else:
  716. if Speed < MinKPH:
  717. MinKPH = Speed
  718. if Speed > MaxKPH:
  719. MaxKPH = Speed
  720.  
  721. #LapInvalidated
  722. #LapInvalidated = ac.getCarState(0,acsys.CS.LapInvalidated)
  723. #PerformanceMeter = ac.getCarState(0, acsys.CS.PerformanceMeter)
  724.  
  725. #message = "numTyresOut = %d" % numTyresOut
  726. #message = message + " at " + str(datetime.datetime.now())
  727. #ac.console(message)
  728.  
  729. #message = "Speed = %d" % Speed
  730. #ac.console(message)
  731.  
  732. #message = "LapInvalidated = %d" % LapInvalidated
  733. #ac.console(message)
  734.  
  735. #message = "LapInvalidated = %.4f" % LapInvalidated
  736. #ac.console(message)
  737.  
  738. ##position = "D%.4f"%(normalizedSplinePosition)
  739. #message = "PerformanceMeter = %.4f" % PerformanceMeter
  740. #ac.console(message)
  741.  
  742. if InitialPosition == 0:
  743. InitialPosition = normalizedSplinePosition
  744.  
  745. #move these towards the .5 instead of the 0.1 and .99 range
  746. if InitialPosition > 0.5:
  747. InitialPosition = InitialPosition - .5
  748. else:
  749. InitialPosition = InitialPosition + .5
  750.  
  751. Position = 0.0
  752. if normalizedSplinePosition > 0.5:
  753. Position = normalizedSplinePosition - 0.5
  754. else:
  755. Position = normalizedSplinePosition + .5
  756.  
  757. #reset every time in the pits?
  758. if ResetDuringPit == 1 and not (bIsQually == True and ResetDuringQualification == 0) and not (bIsPractice == True and ResetDuringPractice == 0):
  759. if ((InitialPosition-Range < Position < InitialPosition+Range) or inPit) and (Speed < 0.1):
  760. dic.clear()
  761.  
  762. if normalizedSplinePosition < 0.01:
  763. startTracking = True
  764. LapValid = 1
  765. #if inPit:
  766. # return True
  767. # startTracking = False
  768.  
  769. if inPit == True and Speed < 1.0 and UsePitOffset == 1:
  770. #if we're in the pit lane and not moving (pit stall, probably)
  771. #pitOffset = currentTime
  772. bSetOffset = 1
  773.  
  774. if startTracking and not inPit:
  775. #position = "D%.4f"%(normalizedSplinePosition)
  776. delta = getDelta(normalizedSplinePosition, currentTime, LapValid)
  777.  
  778. #are we using an offset?
  779. if bSetOffset == 1:
  780. pitOffset = delta
  781. bSetOffset = 0
  782.  
  783. if pitOffset != 0.0:
  784. delta = delta - pitOffset
  785.  
  786. strDelta = formatDelta(delta, deltaStringFormat)
  787. numDelta = round(formatDeltaNumOnly(delta), 2)
  788.  
  789. #do this based off systemtime, not race time?
  790. #use systemtime to help calc race time?
  791. strCurrTime = formatDelta(currentTime, "%.1f")
  792. strLastTime = formatDelta(lastTime, "%.1f")
  793.  
  794. currentClock = 0.0
  795. if sim_info_obj.graphics.status == 1:
  796. currentClock = clock()
  797. strCurrTime = "%.1f" % currentClock
  798. strLastTime = "%.1f" % lastClock
  799. #message = "strCurrTime = %s, strLastTime = %s" % (strCurrTime, strLastTime)
  800. #ac.log(message)
  801.  
  802. #only update this 10 times a second
  803. #time not as accurate in replay, but fine in live
  804. if strCurrTime != strLastTime or fullSpeed == 1:
  805. lastClock = clock()
  806. alpha = 1
  807. if AdjustIntensity == 1:
  808. if prevDelta < numDelta:
  809. trend = trend + 1
  810. elif prevDelta > numDelta:
  811. trend = trend - 1
  812.  
  813. prevDelta = numDelta
  814.  
  815. if trend < 0:
  816. trend = 0
  817. if trend > 3:
  818. trend = 3
  819.  
  820. if trend == 0:
  821. #0 means our times are improving
  822. alpha = 1.0
  823. elif trend == 3:
  824. #3 means our times are getting worse
  825. alpha = 0.7
  826.  
  827. #example for updated a label
  828. #gear_display.setText("%d" % current_gear).setFontColor(1,0,0,1)
  829.  
  830. #ac.setTitle(app, position)
  831. if LapValid == 0 or (TimeOfLastOff > 0.0 and ((currentTime - TimeOfLastOff) < 5000.0)):
  832. displayLabel.setFontColor(*rgb(colors["purple"], alpha))
  833. #ac.setFontColor(displayLabel, *rgb(colors["purple"], alpha))
  834. elif numDelta >= 0.5:
  835. displayLabel.setFontColor(*rgb(colors["red"], alpha))
  836. #ac.setFontColor(displayLabel, *rgb(colors["red"], alpha))
  837. elif numDelta >= 0.25:
  838. displayLabel.setFontColor(*rgb(colors["orange"], alpha))
  839. #ac.setFontColor(displayLabel, *rgb(colors["orange"], alpha))
  840. elif numDelta > 0.0:
  841. displayLabel.setFontColor(*rgb(colors["yellow"], alpha))
  842. #ac.setFontColor(displayLabel, *rgb(colors["yellow"], alpha))
  843. elif numDelta < -0.5:
  844. displayLabel.setFontColor(*rgb(colors["white"], alpha))
  845. elif numDelta < -0.25:
  846. displayLabel.setFontColor(*rgb(colors["aqua"], alpha))
  847. else:
  848. displayLabel.setFontColor(*rgb(colors["green"], alpha))
  849. #ac.setFontColor(displayLabel, *rgb(colors["green"], alpha))
  850.  
  851. #ac.setFontSize(displayLabel, 30*scale_mult)
  852.  
  853. #will this work?
  854. if True: # LapValid == 1:
  855. displayLabel.setText(strDelta)
  856. #ac.setText(displayLabel, strDelta)
  857. else:
  858. displayLabel.setFontColor(*rgb(colors["green"], 1.0))
  859. displayLabel.setText(formatDelta(0.0, deltaStringFormat))
  860. #ac.setText(displayLabel, "+0.00")
  861.  
  862. lastTime = currentTime
  863. else:
  864. displayLabel.setFontColor(*rgb(colors["blue"], 1.0))
  865. displayLabel.setText(formatDelta(0.0, deltaStringFormat))
  866.  
  867. if False:
  868. #we're going to use the brake value to track 2nd order delta
  869. brake = ac.getCarState(0, acsys.CS.Brake)
  870. if brake > 0.7:
  871. recentDelta = delta
  872. else:
  873. #display the difference in delta and recentDelta?
  874. recentDelta = recentDelta
  875.  
  876. #do this last?
  877. if ShowLapTimeDelay > 0.0:
  878. LastLap = ac.getCarState(0,acsys.CS.LastLap)
  879. if LastLap > 0:
  880. if currentTime < ShowLapTimeDelay:
  881. #ac.setFontSize(displayLabel, 24)
  882. displayLabel.setFontColor(*rgb(colors["white"], 1.0))
  883. #ac.setFontColor(displayLabel, *rgb(colors["white"], 1.0))
  884. strLastLap = formatLapTime3Digits(LastLap)
  885. displayLabel.setText(strLastLap)
  886. #ac.setText(displayLabel, strLastLap)
  887. elif LapTimesOnly == 1:
  888. displayLabel.setText("--:--")
  889. if LapValid == 0 or (TimeOfLastOff > 0.0 and ((currentTime - TimeOfLastOff) < 5000.0)):
  890. displayLabel.setFontColor(*rgb(colors["purple"], alpha))
  891. else:
  892. displayLabel.setFontColor(*rgb(colors["blue"], 1.0))
  893.  
  894.  
  895. #if CameraChanger == 1 and CameraTrigger == 1:
  896. # if ac.getCameraMode() == 5:
  897. # ac.setCameraMode(Camera)
  898. # CameraTrigger = 0
  899.  
  900.  
  901. except:
  902. exc_type, exc_value, exc_traceback = sys.exc_info()
  903. ac.console('EsoticDelta Update Error (logged to file)')
  904. ac.log(repr(traceback.format_exception(exc_type, exc_value, exc_traceback)))
  905.  
  906. def hotkey_offset():
  907. global bSetOffset , lastF10Click , compound , startTracking, lastPOT, lastLapTime, lastRealTime, lastClock , pitOffset , lastTime, recentDelta , prevDelta
  908.  
  909. ConsoleLog("PD hotkey_offset Called")
  910. bSetOffset = 1
  911.  
  912. sim_info_obj = sim_info.SimInfo()
  913. currentTime = sim_info_obj.graphics.iCurrentTime
  914.  
  915. if lastF10Click > 0:
  916. if currentTime - lastF10Click < 1000:
  917. #ConsoleLog("Double Click Detected lastF10Click")
  918. #this is a double click detection, so clear all the vars
  919. dic.clear()
  920. compound = None
  921. bSetOffset = 0
  922. startTracking = False
  923.  
  924. lastPOT = 0
  925. lastLapTime = 0
  926. lastRealTime = 0
  927. lastClock = 0.0
  928. pitOffset = 0.0
  929. lastTime = 0.0
  930. recentDelta = 0.0
  931. prevDelta = 0.0
  932.  
  933. elif currentTime - lastF10Click > 1000:
  934. #ConsoleLog("Clearing lastF10Click")
  935. lastF10Click = 0
  936. else:
  937. #ConsoleLog("Setting lastF10Click")
  938. lastF10Click = currentTime
  939.  
  940. def listen_key():
  941. byref = ctypes.byref
  942. user32 = ctypes.windll.user32
  943.  
  944. ConsoleLog("PD Key Listener")
  945.  
  946. HOTKEYS = {
  947. 1: (win32con.VK_F10, None),
  948. }
  949.  
  950. def handle_f10():
  951. hotkey_offset()
  952. #hotkey_preset()
  953.  
  954. HOTKEY_ACTIONS = {
  955. 1: handle_f10,
  956. }
  957.  
  958. for id, (vk, modifiers) in HOTKEYS.items():
  959. user32.RegisterHotKey(None, id, modifiers, vk)
  960.  
  961. try:
  962. msg = wintypes.MSG()
  963. while user32.GetMessageA(byref(msg), None, 0, 0) != 0:
  964. if msg.message == win32con.WM_HOTKEY:
  965. action_to_take = HOTKEY_ACTIONS.get (msg.wParam)
  966. if action_to_take:
  967. action_to_take()
  968. user32.TranslateMessage(byref(msg))
  969. user32.DispatchMessageA(byref(msg))
  970.  
  971. finally:
  972. for id in HOTKEYS.keys():
  973. user32.UnregisterHotKey(None, id)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement