##################################################
# Sidekick by Filip Topuzovic (Topuz)
# 
# Version - 1.11.1
# 
# Credits:
# Erwin Schmidt - Accurate delta calculation
# Rombik - Shared memory Sim Info code
# Boris Lozac, Schnipp - QA, suggestions
# Minolin, Neys - Inspiration to always do more and better
# jCreo - Programming help and advice
# x4fab - Content Manager integration
# Neilski - Gear ratio calculation help
#
# None of the code below is to be redistributed
# or reused without the permission of the
# author(s).
##################################################

import ac, acsys
import platform, os, sys
import codecs, json
import configparser
import bisect
import pickle, threading
import re

if platform.architecture()[0] == "64bit":
	sysdir = os.path.dirname(__file__)+'/stdlib64'
else:
	sysdir = os.path.dirname(__file__)+'/stdlib'

sys.path.insert(0, sysdir)
os.environ['PATH'] = os.environ['PATH'] + ";."

from sidekick_lib.sim_info import info

import ctypes
from ctypes import wintypes

#Assume config doesn't need to be updated
updateConfig = False

#Set config file path
configPath = "apps/python/Sidekick/config.ini"

#Initialize configparser
config = configparser.ConfigParser()
config.read(configPath)

#Check if config file has appropriate content
if config.has_section("Sidekick") != True:
	config.add_section("Sidekick")
	updateConfig = True

#Load the boolean value or set it to default
def getOrSetDefaultBoolean(config, key, default):
	global updateConfig
	try:
		return config.getboolean("Sidekick", key)
	except:
		config.set("Sidekick", key, str(default))
		updateConfig = True
		return default

#Load the float value or set it to default
def getOrSetDefaultFloat(config, key, default):
	global updateConfig
	try:
		return config.getfloat("Sidekick", key)
	except:
		config.set("Sidekick", key, str(default))
		updateConfig = True
		return default
	
#Load or generate customizable parameters
scale = getOrSetDefaultFloat(config, "scale", 100.0) / 100
speedInKPH = getOrSetDefaultBoolean(config, "speedInKPH", True)
showRpmBar = getOrSetDefaultBoolean(config, "showRpmBar", True)
showKersBar = getOrSetDefaultBoolean(config, "showKersBar", True)
showAdditionalBarInfo = getOrSetDefaultBoolean(config, "showAdditionalBarInfo", True)
tyreWearScale = getOrSetDefaultFloat(config, "tyreWearScale", 16.0)
showPressureAsDelta = getOrSetDefaultBoolean(config, "showPressureAsDelta", False)
showBrakeTemperatures = getOrSetDefaultBoolean(config, "showBrakeTemperatures", False)
showBrakeTemperaturesWhileBraking = getOrSetDefaultBoolean(config, "showBrakeTemperaturesWhileBraking", True)
yellowLimitEnabled = getOrSetDefaultBoolean(config, "yellowLimitEnabled", True)
yellowLimitPercentage = getOrSetDefaultFloat(config, "yellowLimitPercentage", 92.0)
redLimitEnabled = getOrSetDefaultBoolean(config, "redLimitEnabled", True)
redLimitPercentage = getOrSetDefaultFloat(config, "redLimitPercentage", 96.0)
optimalShiftLights = getOrSetDefaultBoolean(config, "optimalShiftLights", True)
yellowLimitPowerPercentage = getOrSetDefaultFloat(config, "yellowLimitPowerPercentage", 96.0)
redLimitPowerPercentage = getOrSetDefaultFloat(config, "redLimitPowerPercentage", 100.0)
notifyFFBClipping = getOrSetDefaultBoolean(config, "notifyFFBClipping", True)
ffbClippingThreshold = getOrSetDefaultFloat(config, "ffbClippingThreshold", 500.0)
notifyWheelOffCenter = getOrSetDefaultBoolean(config, "notifyWheelOffCenter", True)
notifySessionEnd = getOrSetDefaultBoolean(config, "notifySessionEnd", True)
notifyLapTimes = getOrSetDefaultBoolean(config, "notifyLapTimes", True)
AIControlInvalidatesLap = getOrSetDefaultBoolean(config, "AIControlInvalidatesLap", True)
usePlainBackground = getOrSetDefaultBoolean(config, "usePlainBackground", False)
autoLooping = getOrSetDefaultBoolean(config, "autoLooping", False)
loopFirstSection = getOrSetDefaultBoolean(config, "loopFirstSection", False)
loopSecondSection = getOrSetDefaultBoolean(config, "loopSecondSection", False)
loopThirdSection = getOrSetDefaultBoolean(config, "loopThirdSection", False)
loopFourthSection = getOrSetDefaultBoolean(config, "loopFourthSection", False)
loopFifthSection = getOrSetDefaultBoolean(config, "loopFifthSection", False)
autoLoopingTime = getOrSetDefaultFloat(config, "autoLoopingTime", 1000.0)
temperatureTransitionRange = getOrSetDefaultFloat(config, "temperatureTransitionRange", 20.0)
pressureTransitionRange = getOrSetDefaultFloat(config, "pressureTransitionRange", 4.0)
brakeTransitionRange = getOrSetDefaultFloat(config, "brakeTransitionRange", 100.0)
showBrandInsteadOfPedals = getOrSetDefaultBoolean(config, "showBrandInsteadOfPedals", False)
disableSectionButtons = getOrSetDefaultBoolean(config, "disableSectionButtons", False)

#Update config if necessary 
if updateConfig:
	with open(configPath, 'w') as fileConfig:
		config.write(fileConfig)

#Timers
timer0 = 0
timer1 = 0
timer2 = 0
timer3 = 0
gearTimer = 0
dominantTimer = 0
autoLoopingTimer = 0

#Run once helpers
runOnce = True
runOnce2 = True
wasAlreadyDisplayed = False

#Sourced from the API or shared memory
rpmValue = 0
turboValue = 0
kersChargeValue = 0
kersInputValue = 0
ersCurrentKJValue = 0
clutchValue = 0
brakeValue = 0
throttleValue = 0
ffbValue = 0

gearValue = 0
driveTrainSpeedValue = 0
tiresOutValue = 0

focusedCarValue = 0
speedValueKPH = 0
speedValueMPH = 0
steerInputValue = 0
currentLapValue = 0
lapProgressValue = 0
lapValue = 0
drsAvailableValue = 0
drsEnabledValue = 0
ersIsChargingValue = 0
P2PStatusValue = 0
P2PActivationsValue = 0

statusValue = 0
rpmMaxValue = 0
sessionTypeValue = 0
sessionTimeValue = 0
raceIsTimed = 0
trackLengthValue = 0
carInPitlineValue = 0
carDrivenByAIValue = 0
positionValue = 0
positionBoardValue = 0
serverIPValue = 0
totalCarsValue = 0
occupiedSlotsValue = 0
totalLapsValue = 0
fuelAmountValue = 0
tyreCompoundValue = 0
tyreWearValue = [0] * 4
tyreTemperatureValue = [0] * 4
tyreTemperatureValueI = [0] * 4
tyreTemperatureValueM = [0] * 4
tyreTemperatureValueO = [0] * 4
tyrePressureValue = [0] * 4
brakeTemperatureValue = [0] * 4
hasERS = 0
hasKERS = 0
ersMaxJValue = 0

#Generated internally
previousStatusValue = 0
lastLapReplayValue = 0
currentLapReplayValue = 0

resetTrigger = 1

rpmPercentageValue = 0

turboMaxValue = 0
turboPercentageValue = 0

DTConstants = [0] * 8
previousRpm = 1
previousGearValue = 0
ratioList = [0] * 7
rpmInNextGear = 0
upperBound = 0
lowerBound = 0
upperBoundInNextGear = 0
lowerBoundInNextGear = 0
coefficient = 0
currentPower = 0
powerInNextGear = 0

currentLapValueMinutes = 0
currentLapValueSeconds = 0
lastLapValue = 0
lastLapValueMinutes = 0
lastLapValueSeconds = 0
bestLapValue = 0
previousBestLapValue = 0
bestLapValueMinutes = 0
bestLapValueSeconds = 0
personalBestLapValue = 0
previousPersonalBestLapValue = 0
personalBestLapValueMinutes = 0
personalBestLapValueSeconds = 0
lapValidityValue = 0
lapWasInvalid = 0

tyrePracticalTemperatureValue = [0] * 4

outLap = 0
practiceIsTimed = 0
carWasInPit = 0
carWasDrivenByAI = 0
P2PActivationsMaxValue = 0

fuelStartValue = 0
fuelEndValue = 0
relevantLapsNumber = 0
fuelSpentValue = 0
fuelPerLapValue = 0

tyreCompoundShort = ""
tyreCompoundCleaned = ""
previousTyreCompoundValue = 0
minimumOptimalTemperature = 0
maximumOptimalTemperature = 0
idealPressureFront = 0
idealPressureRear = 0
minimumOptimalBrakeTemperatureFront = 0
maximumOptimalBrakeTemperatureFront = 0
minimumOptimalBrakeTemperatureRear = 0
maximumOptimalBrakeTemperatureRear = 0

previousLapValue = 0

ffbTimer = 0
ffbWasTooStrong = False

isDominantActive = False

#Triggers and spinners
selectorCounter = 0
previousSelectorCounter = 0
spinnerButtons = []

timerTrigger1 = 0
spinnerButton1 = 0
timerTrigger2 = 0
spinnerButton2 = 0
timerTrigger3 = 0
spinnerButton3 = 0
timerTrigger4 = 0
spinnerButton4 = 0
timerTrigger5 = 0
spinnerButton5 = 0

isSelector = False

#Delta related
previousLapProgressValue = 0
posList = []
timeList = []
bestPosList = []
bestTimeList = []
personalBestPosList = []
personalBestTimeList = []
prevt = 0
prevt2 = 0
ttb = 0
ttb_old = 0
ttpb = 0
ttpb_old = 0

distanceToCar = 0
timeToCar = 0

#Max power rpm
powerCurve = 0
maxPowerRpm = 0
maxPower = 0

#Odometers
odometer = 0
tripOdometer = 0

#Window visibilities
settingsWindowVisibility = 0
carDataWindowVisibility = 0

#Set folder paths
personalBestDir = "apps/python/Sidekick/personal_best/"
compoundsPath = "apps/python/Sidekick/compounds/"
brakesDir = "apps/python/Sidekick/brakes/"
configDir = "apps/python/Sidekick/config/"
gearRatiosDir = "apps/python/Sidekick/gear_ratios/"

#Set odometer path
odometersPath = "apps/python/Sidekick/odometers/odometers.ini"

#Set image paths
background = "apps/python/Sidekick/images/background.png"
plain_background = "apps/python/Sidekick/images/plain_background.png"
border_yellow = "apps/python/Sidekick/images/border_yellow.png"
border_red = "apps/python/Sidekick/images/border_red.png"
separators = "apps/python/Sidekick/images/separators.png"
delta_bad = "apps/python/Sidekick/images/delta_bad.png"
delta_good = "apps/python/Sidekick/images/delta_good.png"
drs_available = "apps/python/Sidekick/images/drs_available.png"
drs_enabled = "apps/python/Sidekick/images/drs_enabled.png"
selection_indicator = "apps/python/Sidekick/images/selection_indicator.png"
settings = "apps/python/Sidekick/images/settings.png"
cmIcon = "apps/python/Sidekick/images/cm_icon.png"

def acMain(ac_version):
	
	global appWindow, rpmBorder, separatorsLabel, selectionIndicatorLabel, gearLabel, speedLabel, speedUnitLabel, firstButton, secondButton, thirdButton, fourthButton, fifthButton, firstLabel, secondLabel, thirdLabel, fourthLabel, fifthLabel, tyreLabelFL, tyreLabelFR, tyreLabelRL, tyreLabelRR, deltaGainLabel, drsLabel, dominantLabel, brandIconLabel, carDataButton, settingsButton
	global carDataWindow, tyreInfoLabel, brakeInfoLabel, shiftsInfoLabel, recalculateGearRatiosLabel, recalculateGearRatiosButton, odometerInfoLabel, tripOdometerInfoLabel, tripOdometerInfoButton, resetPersonalBestLapLabel, resetPersonalBestLapButton
	global settingsWindow, scaleLabel, scaleSpinner, speedInKPHLabel, speedInKPHCheckBox, showRpmBarLabel, showRpmBarCheckBox, showKersBarLabel, showKersBarCheckBox, showAdditionalBarInfoLabel, showAdditionalBarInfoCheckBox, tyreWearScaleLabel, tyreWearScaleSpinner, showPressureAsDeltaLabel, showPressureAsDeltaCheckBox, showBrakeTemperaturesLabel, showBrakeTemperaturesCheckBox, showBrakeTemperaturesWhileBrakingLabel, showBrakeTemperaturesWhileBrakingCheckBox, yellowLimitEnabledLabel, yellowLimitEnabledCheckBox, yellowLimitPercentageLabel, yellowLimitPercentageSpinner, redLimitEnabledLabel, redLimitEnabledCheckBox, redLimitPercentageLabel, redLimitPercentageSpinner, optimalShiftLightsLabel, optimalShiftLightsCheckBox, yellowLimitPowerPercentageLabel, yellowLimitPowerPercentageSpinner, redLimitPowerPercentageLabel, redLimitPowerPercentageSpinner, notifyFFBClippingLabel, notifyFFBClippingCheckBox, ffbClippingThresholdLabel, ffbClippingThresholdSpinner, notifyWheelOffCenterLabel, notifyWheelOffCenterCheckBox, notifySessionEndLabel, notifySessionEndCheckBox, notifyLapTimesLabel, notifyLapTimesCheckBox, AIControlInvalidatesLapLabel, AIControlInvalidatesLapCheckBox, usePlainBackgroundLabel, usePlainBackgroundCheckBox, autoLoopingLabel, autoLoopingCheckBox, sectionsToLoopLabel, loopFirstSectionCheckBox, loopSecondSectionCheckBox, loopThirdSectionCheckBox, loopFourthSectionCheckBox, loopFifthSectionCheckBox, autoLoopingTimeLabel, autoLoopingTimeSpinner, temperatureTransitionRangeLabel, temperatureTransitionRangeSpinner, pressureTransitionRangeLabel, pressureTransitionRangeSpinner, brakeTransitionRangeLabel, brakeTransitionRangeSpinner, showBrandInsteadOfPedalsLabel, showBrandInsteadOfPedalsCheckBox, disableSectionButtonsLabel, disableSectionButtonsCheckBox, appInfoLabel, cmInfoLabel, cmIconLabel, resetToDefaultButton
	
	global carValue
	global trackConfigValue
	
	global filePersonalBest, personalBestLapValue, personalBestLapValueMinutes, personalBestLapValueSeconds
	global filePersonalBestPosList, filePersonalBestTimeList, personalBestPosList, personalBestTimeList
	global fileSectionChoices, spinnerButtons, spinnerButton1, spinnerButton2, spinnerButton3, spinnerButton4, spinnerButton5
	global fileRatioList, ratioList
	
	global optimalShiftLights, powerCurve, maxPowerRpm, maxPower
	
	global compounds, modCompounds, brakes, modBrakes
	global odometers, odometer
	
	#Create file names
	carValue = ac.getCarName(0)
	trackValue = ac.getTrackName(0)
	trackConfigValue = ac.getTrackConfiguration(0)

	filePersonalBest = personalBestDir + carValue + "_" + trackValue + trackConfigValue + "_pb.ini"
	filePersonalBestPosList = personalBestDir + carValue + "_" +trackValue +trackConfigValue + "_pbposlist.ini"
	filePersonalBestTimeList = personalBestDir + carValue + "_" +trackValue +trackConfigValue + "_pbtimelist.ini"
	fileSectionChoices = configDir + "sectionChoices.ini"
	fileRatioList = gearRatiosDir + carValue + "_ratios.ini"

	#Load data from files
	personalBestLapValue = loadFile(filePersonalBest, personalBestLapValue)
	if personalBestLapValue > 0:
		personalBestLapValueSeconds = (personalBestLapValue / 1000) % 60
		personalBestLapValueMinutes = (personalBestLapValue // 1000) // 60
	personalBestPosList = loadFile(filePersonalBestPosList, personalBestPosList)
	personalBestTimeList = loadFile(filePersonalBestTimeList, personalBestTimeList)
	spinnerButtons = loadFile(fileSectionChoices, spinnerButtons)
	spinnerButton1 = spinnerButtons[0]
	spinnerButton2 = spinnerButtons[1]
	spinnerButton3 = spinnerButtons[2]
	spinnerButton4 = spinnerButtons[3]
	spinnerButton5 = spinnerButtons[4]
	ratioList = loadFile(fileRatioList, ratioList)
	
		
	#Figure out what is the max power rpm
	if optimalShiftLights:
		try:
			with codecs.open("content/cars/" + carValue + "/ui/ui_car.json", "r", "utf-8-sig") as uiFile:
				uiDataString = uiFile.read().replace('\r', '').replace('\n', '').replace('\t', '')
			uiDataJson = json.loads(uiDataString)
			powerCurve = uiDataJson["powerCurve"]
			for step in uiDataJson["powerCurve"]:
				if int(step[1]) >= maxPower:
					maxPower = int(step[1])
					maxPowerRpm = int(step[0])
		except:
			ac.console("Sidekick: UTF ui_car.json failed to load")
			try:
				with codecs.open("content/cars/" + carValue + "/ui/ui_car.json", "r", "latin-1") as uiFile:
					uiDataString = uiFile.read().replace('\r', '').replace('\n', '').replace('\t', '')
				uiDataJson = json.loads(uiDataString)
				powerCurve = uiDataJson["powerCurve"]
				for step in uiDataJson["powerCurve"]:
					if int(step[1]) >= maxPower:
						maxPower = int(step[1])
						maxPowerRpm = int(step[0])
			except:
				ac.console("Sidekick: ANSI ui_car.json failed to load")
				optimalShiftLights = False
				
	#Load the brand icon
	brandIcon = "content/cars/" + carValue + "/logo.png"
	if not os.path.isfile(brandIcon):
		if os.path.isfile("content/cars/" + carValue + "/ui/badge.png"):
			brandIcon = "content/cars/" + carValue + "/ui/badge.png"
		else:
			brandIcon = "apps/python/Sidekick/images/ac_icon.png"

	#Initialize font
	ac.initFont(0, "Roboto", 1, 1)
	
	#Initialize configparsers
	compounds = configparser.ConfigParser()
	compounds.read(compoundsPath + "compounds.ini")
	modCompounds = configparser.ConfigParser()
	modCompounds.read(compoundsPath + carValue + ".ini")
	brakes = configparser.ConfigParser()
	brakes.read(brakesDir + "brakes.ini")
	modBrakes = configparser.ConfigParser()
	modBrakes.read(brakesDir + carValue + ".ini")
	
	#Load odometer data
	odometers = configparser.ConfigParser()
	odometers.read(odometersPath)
	if odometers.has_section(carValue):
		odometer = odometers.getfloat(carValue, "odometer")
	else:
		odometers.add_section(carValue)
		
	#App window
	appWindow = ac.newApp("Sidekick")
	ac.setTitle(appWindow, "")
	ac.drawBorder(appWindow, 0)
	ac.setIconPosition(appWindow, 0, -10000)
	ac.setSize(appWindow, 463 * scale, 46 * scale)
	if usePlainBackground:
		ac.setBackgroundTexture(appWindow, plain_background)
	else:
		ac.setBackgroundTexture(appWindow, background)
	
	#RPM border
	rpmBorder = ac.addLabel(appWindow, "")
	ac.setPosition(rpmBorder, 0, -4 * scale)
	ac.setSize(rpmBorder, 416 * scale, 54 * scale)
	
	#Separators
	separatorsLabel = ac.addLabel(appWindow, "")
	ac.setPosition(separatorsLabel, -1 * scale, 0)
	ac.setSize(separatorsLabel, 381 * scale, 50 * scale)
	ac.setBackgroundTexture(separatorsLabel, separators)
	
	#Selection indicator
	selectionIndicatorLabel = ac.addLabel(appWindow, "")
	ac.setPosition(selectionIndicatorLabel, 94 * scale, 34 * scale)
	ac.setSize(selectionIndicatorLabel, 16 * scale, 1 * scale)
	ac.setBackgroundTexture(selectionIndicatorLabel, selection_indicator)
	
	#Gear
	gearLabel = ac.addLabel(appWindow, "-")
	ac.setPosition(gearLabel, 9 * scale, -1 * scale)
	ac.setFontSize(gearLabel, 34 * scale)
	ac.setCustomFont(gearLabel, "Roboto", 1, 1)
	ac.setFontColor(gearLabel, 0.86, 0.86, 0.86, 1)
	
	#Speed
	speedLabel = ac.addLabel(appWindow, "---")
	ac.setPosition(speedLabel, 47 * scale, 6 * scale)
	ac.setFontSize(speedLabel, 16 * scale)
	ac.setCustomFont(speedLabel, "Roboto", 1, 0)
	ac.setFontColor(speedLabel, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(speedLabel, "center")
	
	#Speed unit
	if speedInKPH:
		speedUnitLabel = ac.addLabel(appWindow, "km/h")
	else:
		speedUnitLabel = ac.addLabel(appWindow, "mph")
	ac.setPosition(speedUnitLabel, 46 * scale, 23 * scale)
	ac.setFontSize(speedUnitLabel, 11 * scale)
	ac.setCustomFont(speedUnitLabel, "Roboto", 1, 0)
	ac.setFontColor(speedUnitLabel, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(speedUnitLabel, "center")
	
	#First button
	firstButton = ac.addButton(appWindow, "")
	ac.setPosition(firstButton, 68 * scale, 12 * scale)
	ac.setSize(firstButton, 67 * scale, 22 * scale)
	ac.drawBorder(firstButton, 0)
	ac.setBackgroundOpacity(firstButton, 0)
	ac.addOnClickedListener(firstButton, firstButtonClicked)
	if disableSectionButtons:
		ac.setVisible(firstButton, 0)
	
	#Second button
	secondButton = ac.addButton(appWindow, "")
	ac.setPosition(secondButton, 136 * scale, 12 * scale)
	ac.setSize(secondButton, 54 * scale, 22 * scale)
	ac.drawBorder(secondButton, 0)
	ac.setBackgroundOpacity(secondButton, 0)
	ac.addOnClickedListener(secondButton, secondButtonClicked)
	if disableSectionButtons:
		ac.setVisible(secondButton, 0)
	
	#Third button
	thirdButton = ac.addButton(appWindow, "")
	ac.setPosition(thirdButton, 191 * scale, 12 * scale)
	ac.setSize(thirdButton, 58 * scale, 22 * scale)
	ac.drawBorder(thirdButton, 0)
	ac.setBackgroundOpacity(thirdButton, 0)
	ac.addOnClickedListener(thirdButton, thirdButtonClicked)
	if disableSectionButtons:
		ac.setVisible(thirdButton, 0)
	
	#Fourth button
	fourthButton = ac.addButton(appWindow, "")
	ac.setPosition(fourthButton, 250 * scale, 12 * scale)
	ac.setSize(fourthButton, 54 * scale, 22 * scale)
	ac.drawBorder(fourthButton, 0)
	ac.setBackgroundOpacity(fourthButton, 0)
	ac.addOnClickedListener(fourthButton, fourthButtonClicked)
	if disableSectionButtons:
		ac.setVisible(fourthButton, 0)
	
	#Fifth button
	fifthButton = ac.addButton(appWindow, "")
	ac.setPosition(fifthButton, 305 * scale, 8 * scale)
	ac.setSize(fifthButton, 59 * scale, 30 * scale)
	ac.drawBorder(fifthButton, 0)
	ac.setBackgroundOpacity(fifthButton, 0)
	ac.addOnClickedListener(fifthButton, fifthButtonClicked)
	if disableSectionButtons:
		ac.setVisible(fifthButton, 0)
	
	#First section
	firstLabel = ac.addLabel(appWindow, "-:--.--")
	ac.setPosition(firstLabel, 102 * scale, 11 * scale)
	ac.setFontSize(firstLabel, 17 * scale)
	ac.setCustomFont(firstLabel, "Roboto", 1, 0)
	ac.setFontColor(firstLabel, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(firstLabel, "center")
	
	#Second section
	secondLabel = ac.addLabel(appWindow, "-.--")
	ac.setPosition(secondLabel, 162 * scale, 11 * scale)
	ac.setFontSize(secondLabel, 17 * scale)
	ac.setCustomFont(secondLabel, "Roboto", 1, 0)
	ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(secondLabel, "center")
	
	#Third section
	thirdLabel = ac.addLabel(appWindow, "-/-")
	ac.setPosition(thirdLabel, 220 * scale, 11 * scale)
	ac.setFontSize(thirdLabel, 17 * scale)
	ac.setCustomFont(thirdLabel, "Roboto", 1, 0)
	ac.setFontColor(thirdLabel, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(thirdLabel, "center")
	
	#Fourth section
	fourthLabel = ac.addLabel(appWindow, "--.-")
	ac.setPosition(fourthLabel, 277 * scale, 11 * scale)
	ac.setFontSize(fourthLabel, 17 * scale)
	ac.setCustomFont(fourthLabel, "Roboto", 1, 0)
	ac.setFontColor(fourthLabel, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(fourthLabel, "center")
	
	#Fifth section
	fifthLabel = ac.addLabel(appWindow, "")
	ac.setPosition(fifthLabel, 335 * scale, 11 * scale)
	ac.setFontSize(fifthLabel, 17 * scale)
	ac.setCustomFont(fifthLabel, "Roboto", 1, 0)
	ac.setFontColor(fifthLabel, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(fifthLabel, "center")
	
	#Tyre FL
	tyreLabelFL = ac.addLabel(appWindow, "--")
	ac.setPosition(tyreLabelFL, 322 * scale, 7 * scale)
	ac.setFontSize(tyreLabelFL, 13 * scale)
	ac.setCustomFont(tyreLabelFL, "Roboto", 1, 0)
	ac.setFontColor(tyreLabelFL, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(tyreLabelFL, "center")
	
	#Tyre FR
	tyreLabelFR = ac.addLabel(appWindow, "--")
	ac.setPosition(tyreLabelFR, 349 * scale, 7 * scale)
	ac.setFontSize(tyreLabelFR, 13 * scale)
	ac.setCustomFont(tyreLabelFR, "Roboto", 1, 0)
	ac.setFontColor(tyreLabelFR, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(tyreLabelFR, "center")
	
	#Tyre RL
	tyreLabelRL = ac.addLabel(appWindow, "--")
	ac.setPosition(tyreLabelRL, 322 * scale, 21 * scale)
	ac.setFontSize(tyreLabelRL, 13 * scale)
	ac.setCustomFont(tyreLabelRL, "Roboto", 1, 0)
	ac.setFontColor(tyreLabelRL, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(tyreLabelRL, "center")
	
	#Tyre RR
	tyreLabelRR = ac.addLabel(appWindow, "--")
	ac.setPosition(tyreLabelRR, 349 * scale, 21 * scale)
	ac.setFontSize(tyreLabelRR, 13 * scale)
	ac.setCustomFont(tyreLabelRR, "Roboto", 1, 0)
	ac.setFontColor(tyreLabelRR, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(tyreLabelRR, "center")
	
	#Delta pacing
	deltaGainLabel = ac.addLabel(appWindow, "")
	ac.setPosition(deltaGainLabel, 136 * scale, 12 * scale)
	ac.setSize(deltaGainLabel, 54 * scale, 22 * scale)
	
	#DRS
	drsLabel = ac.addLabel(appWindow, "")
	ac.setPosition(drsLabel, 410 * scale, 0)
	ac.setSize(drsLabel, 20 * scale, 46 * scale)
	
	#Dominant label
	dominantLabel = ac.addLabel(appWindow, "")
	ac.setPosition(dominantLabel, 215 * scale, 11 * scale)
	ac.setFontSize(dominantLabel, 17 * scale)
	ac.setCustomFont(dominantLabel, "Roboto", 1, 0)
	ac.setFontColor(dominantLabel, 0.86, 0.86, 0.86, 1)
	ac.setFontAlignment(dominantLabel, "center")
	ac.setVisible(dominantLabel, 0)
	
	#Brand icon
	brandIconLabel = ac.addLabel(appWindow, "")
	ac.setPosition(brandIconLabel, 371 * scale, 9 * scale)
	ac.setSize(brandIconLabel, 28 * scale, 28 * scale)
	ac.drawBorder(brandIconLabel, 0)
	ac.setBackgroundTexture(brandIconLabel, brandIcon)
	
	#Car data button
	carDataButton = ac.addButton(appWindow, "")
	ac.setPosition(carDataButton, 371 * scale, 9 * scale)
	ac.setSize(carDataButton, 28 * scale, 28 * scale)
	ac.drawBorder(carDataButton, 0)
	ac.setBackgroundOpacity(carDataButton, 0)
	ac.addOnClickedListener(carDataButton, carDataButtonClicked)
	
	#Settings button
	settingsButton = ac.addButton(appWindow, "")
	ac.setPosition(settingsButton, 401 * scale, 0)
	ac.setSize(settingsButton, 14 * scale, 46 * scale)
	ac.drawBorder(settingsButton, 0)
	ac.setBackgroundTexture(settingsButton, settings)
	ac.setBackgroundOpacity(settingsButton, 0)
	ac.addOnClickedListener(settingsButton, settingsButtonClicked)
	
	#Car data window
	carDataWindow = ac.newApp("Sidekick car data")
	ac.drawBorder(carDataWindow, 0)
	ac.setIconPosition(carDataWindow, 0, -10000)
	ac.setSize(carDataWindow, 379 * scale, 226 * scale)
	ac.setBackgroundOpacity(carDataWindow, 0.7)
	ac.setVisible(carDataWindow, carDataWindowVisibility)
	ac.addOnAppActivatedListener(carDataWindow, carDataWindowActivated)
	ac.addOnAppDismissedListener(carDataWindow, carDataWindowDeactivated)

	#Tyre info
	tyreInfoLabel = ac.addLabel(carDataWindow, "")
	ac.setPosition(tyreInfoLabel, 10 * scale, 36 * scale)
	ac.setFontSize(tyreInfoLabel, 14 * scale)
	ac.setCustomFont(tyreInfoLabel, "Roboto", 1, 0)
	
	#Brake info
	brakeInfoLabel = ac.addLabel(carDataWindow, "Brakes: no data found")
	ac.setPosition(brakeInfoLabel, 10 * scale, 62 * scale)
	ac.setFontSize(brakeInfoLabel, 14 * scale)
	ac.setCustomFont(brakeInfoLabel, "Roboto", 1, 0)
	
	#Shifts info
	shiftsInfoLabel = ac.addLabel(carDataWindow, "")
	ac.setPosition(shiftsInfoLabel, 10 * scale, 88 * scale)
	ac.setFontSize(shiftsInfoLabel, 14 * scale)
	ac.setCustomFont(shiftsInfoLabel, "Roboto", 1, 0)

	#Recalculate gear ratios
	recalculateGearRatiosLabel = ac.addLabel(carDataWindow, "Recalculate gear ratios:")
	ac.setPosition(recalculateGearRatiosLabel, 10 * scale, 114 * scale)
	ac.setFontSize(recalculateGearRatiosLabel, 14 * scale)
	ac.setCustomFont(recalculateGearRatiosLabel, "Roboto", 1, 0)
	
	recalculateGearRatiosButton = ac.addButton(carDataWindow, "Recalculate")
	ac.setPosition(recalculateGearRatiosButton, 266 * scale, 114 * scale)
	ac.setSize(recalculateGearRatiosButton, 100 * scale, 22	* scale)
	ac.setFontSize(recalculateGearRatiosButton, 14 * scale)
	ac.setCustomFont(recalculateGearRatiosButton, "Roboto", 1, 0)
	ac.addOnClickedListener(recalculateGearRatiosButton, recalculateGearRatiosButtonClicked)
	
	#Odometer
	odometerInfoLabel = ac.addLabel(carDataWindow, "")
	ac.setPosition(odometerInfoLabel, 10 * scale, 140 * scale)
	ac.setFontSize(odometerInfoLabel, 14 * scale)
	ac.setCustomFont(odometerInfoLabel, "Roboto", 1, 0)
	
	#Trip odometer
	tripOdometerInfoLabel = ac.addLabel(carDataWindow, "")
	ac.setPosition(tripOdometerInfoLabel, 10 * scale, 166 * scale)
	ac.setFontSize(tripOdometerInfoLabel, 14 * scale)
	ac.setCustomFont(tripOdometerInfoLabel, "Roboto", 1, 0)
	
	tripOdometerInfoButton = ac.addButton(carDataWindow, "Reset")
	ac.setPosition(tripOdometerInfoButton, 266 * scale, 166 * scale)
	ac.setSize(tripOdometerInfoButton, 100 * scale, 22	* scale)
	ac.setFontSize(tripOdometerInfoButton, 14 * scale)
	ac.setCustomFont(tripOdometerInfoButton, "Roboto", 1, 0)
	ac.addOnClickedListener(tripOdometerInfoButton, tripOdometerInfoButtonClicked)
	
	#Reset personal best lap
	resetPersonalBestLapLabel = ac.addLabel(carDataWindow, "Reset personal best lap:")
	ac.setPosition(resetPersonalBestLapLabel, 10 * scale, 192 * scale)
	ac.setFontSize(resetPersonalBestLapLabel, 14 * scale)
	ac.setCustomFont(resetPersonalBestLapLabel, "Roboto", 1, 0)
	
	resetPersonalBestLapButton = ac.addButton(carDataWindow, "Reset")
	ac.setPosition(resetPersonalBestLapButton, 266 * scale, 192 * scale)
	ac.setSize(resetPersonalBestLapButton, 100 * scale, 22 * scale)
	ac.setFontSize(resetPersonalBestLapButton, 14 * scale)
	ac.setCustomFont(resetPersonalBestLapButton, "Roboto", 1, 0)
	ac.addOnClickedListener(resetPersonalBestLapButton, resetPersonalBestLapButtonClicked)
	
	#Settings window
	settingsWindow = ac.newApp("Sidekick settings")
	ac.drawBorder(settingsWindow, 0)
	ac.setIconPosition(settingsWindow, 0, -10000)
	ac.setSize(settingsWindow, 768 * scale, 500 * scale)
	ac.setBackgroundOpacity(settingsWindow, 0.7)
	ac.setVisible(settingsWindow, settingsWindowVisibility)
	ac.addOnAppActivatedListener(settingsWindow, settingsWindowActivated)
	ac.addOnAppDismissedListener(settingsWindow, settingsWindowDeactivated)
	
	#Scale
	scaleLabel = ac.addLabel(settingsWindow, "App scale (requires restart):")
	ac.setPosition(scaleLabel, 10 * scale, 36 * scale)
	ac.setFontSize(scaleLabel, 14 * scale)
	ac.setCustomFont(scaleLabel, "Roboto", 1, 0)
	
	scaleSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(scaleSpinner, 50, 200)
	ac.setStep(scaleSpinner, 10)
	ac.setValue(scaleSpinner, scale * 100)
	ac.setPosition(scaleSpinner, 266 * scale, 36 * scale)
	ac.setSize(scaleSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(scaleSpinner, 14 * scale)
	ac.setCustomFont(scaleSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(scaleSpinner, scaleSpinnerClicked)
	
	#Speed unit
	speedInKPHLabel = ac.addLabel(settingsWindow, "Speed and distance in metric units:")
	ac.setPosition(speedInKPHLabel, 10 * scale, 62 * scale)
	ac.setFontSize(speedInKPHLabel, 14 * scale)
	ac.setCustomFont(speedInKPHLabel, "Roboto", 1, 0)
	
	speedInKPHCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(speedInKPHCheckBox, speedInKPH)
	ac.setPosition(speedInKPHCheckBox, 350 * scale, 64 * scale)
	ac.setSize(speedInKPHCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(speedInKPHCheckBox, speedInKPHCheckBoxClicked)
	
	#RPM bar
	showRpmBarLabel = ac.addLabel(settingsWindow, "Show RPM bar:")
	ac.setPosition(showRpmBarLabel, 10 * scale, 88 * scale)
	ac.setFontSize(showRpmBarLabel, 14 * scale)
	ac.setCustomFont(showRpmBarLabel, "Roboto", 1, 0)
	
	showRpmBarCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(showRpmBarCheckBox, showRpmBar)
	ac.setPosition(showRpmBarCheckBox, 350 * scale, 90 * scale)
	ac.setSize(showRpmBarCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(showRpmBarCheckBox, showRpmBarCheckBoxClicked)
	
	#KERS bar
	showKersBarLabel = ac.addLabel(settingsWindow, "Show KERS/P2P bar (on supported cars):")
	ac.setPosition(showKersBarLabel, 10 * scale, 114 * scale)
	ac.setFontSize(showKersBarLabel, 14 * scale)
	ac.setCustomFont(showKersBarLabel, "Roboto", 1, 0)
	
	showKersBarCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(showKersBarCheckBox, showKersBar)
	ac.setPosition(showKersBarCheckBox, 350 * scale, 116 * scale)
	ac.setSize(showKersBarCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(showKersBarCheckBox, showKersBarCheckBoxClicked)
	
	#Additional bar info
	showAdditionalBarInfoLabel = ac.addLabel(settingsWindow, "Show additional info on bars:")
	ac.setPosition(showAdditionalBarInfoLabel, 10 * scale, 140 * scale)
	ac.setFontSize(showAdditionalBarInfoLabel, 14 * scale)
	ac.setCustomFont(showAdditionalBarInfoLabel, "Roboto", 1, 0)
	
	showAdditionalBarInfoCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(showAdditionalBarInfoCheckBox, showAdditionalBarInfo)
	ac.setPosition(showAdditionalBarInfoCheckBox, 350 * scale, 142 * scale)
	ac.setSize(showAdditionalBarInfoCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(showAdditionalBarInfoCheckBox, showAdditionalBarInfoCheckBoxClicked)
	
	#Tyre wear scale
	tyreWearScaleLabel = ac.addLabel(settingsWindow, "Tyre wear scale:")
	ac.setPosition(tyreWearScaleLabel, 10 * scale, 166 * scale)
	ac.setFontSize(tyreWearScaleLabel, 14 * scale)
	ac.setCustomFont(tyreWearScaleLabel, "Roboto", 1, 0)
	
	tyreWearScaleSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(tyreWearScaleSpinner, 1, 16)
	ac.setStep(tyreWearScaleSpinner, 1)
	ac.setValue(tyreWearScaleSpinner, tyreWearScale)
	ac.setPosition(tyreWearScaleSpinner, 266 * scale, 166 * scale)
	ac.setSize(tyreWearScaleSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(tyreWearScaleSpinner, 14 * scale)
	ac.setCustomFont(tyreWearScaleSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(tyreWearScaleSpinner, tyreWearScaleSpinnerClicked)
	
	#Pressure as delta
	showPressureAsDeltaLabel = ac.addLabel(settingsWindow, "Show pressure as delta from ideal:")
	ac.setPosition(showPressureAsDeltaLabel, 10 * scale, 192 * scale)
	ac.setFontSize(showPressureAsDeltaLabel, 14 * scale)
	ac.setCustomFont(showPressureAsDeltaLabel, "Roboto", 1, 0)
	
	showPressureAsDeltaCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(showPressureAsDeltaCheckBox, showPressureAsDelta)
	ac.setPosition(showPressureAsDeltaCheckBox, 350 * scale, 194 * scale)
	ac.setSize(showPressureAsDeltaCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(showPressureAsDeltaCheckBox, showPressureAsDeltaCheckBoxClicked)
	
	#Brake temperatures
	showBrakeTemperaturesLabel = ac.addLabel(settingsWindow, "Show brake temperatures:")
	ac.setPosition(showBrakeTemperaturesLabel, 10 * scale, 218 * scale)
	ac.setFontSize(showBrakeTemperaturesLabel, 14 * scale)
	ac.setCustomFont(showBrakeTemperaturesLabel, "Roboto", 1, 0)
	
	showBrakeTemperaturesCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(showBrakeTemperaturesCheckBox, showBrakeTemperatures)
	ac.setPosition(showBrakeTemperaturesCheckBox, 350 * scale, 220 * scale)
	ac.setSize(showBrakeTemperaturesCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(showBrakeTemperaturesCheckBox, showBrakeTemperaturesCheckBoxClicked)
	
	#Brake temperatures while braking
	showBrakeTemperaturesWhileBrakingLabel = ac.addLabel(settingsWindow, "Show brake temperatures while braking:")
	ac.setPosition(showBrakeTemperaturesWhileBrakingLabel, 10 * scale, 244 * scale)
	ac.setFontSize(showBrakeTemperaturesWhileBrakingLabel, 14 * scale)
	ac.setCustomFont(showBrakeTemperaturesWhileBrakingLabel, "Roboto", 1, 0)
	
	showBrakeTemperaturesWhileBrakingCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(showBrakeTemperaturesWhileBrakingCheckBox, showBrakeTemperaturesWhileBraking)
	ac.setPosition(showBrakeTemperaturesWhileBrakingCheckBox, 350 * scale, 246 * scale)
	ac.setSize(showBrakeTemperaturesWhileBrakingCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(showBrakeTemperaturesWhileBrakingCheckBox, showBrakeTemperaturesWhileBrakingCheckBoxClicked)
	
	#Yellow light
	yellowLimitEnabledLabel = ac.addLabel(settingsWindow, "Enable yellow shift light:")
	ac.setPosition(yellowLimitEnabledLabel, 10 * scale, 270 * scale)
	ac.setFontSize(yellowLimitEnabledLabel, 14 * scale)
	ac.setCustomFont(yellowLimitEnabledLabel, "Roboto", 1, 0)
	
	yellowLimitEnabledCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(yellowLimitEnabledCheckBox, yellowLimitEnabled)
	ac.setPosition(yellowLimitEnabledCheckBox, 350 * scale, 272 * scale)
	ac.setSize(yellowLimitEnabledCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(yellowLimitEnabledCheckBox, yellowLimitEnabledCheckBoxClicked)
	
	#Yellow light offset
	yellowLimitPercentageLabel = ac.addLabel(settingsWindow, "Yellow shift (in % of rpm limit):")
	ac.setPosition(yellowLimitPercentageLabel, 10 * scale, 296 * scale)
	ac.setFontSize(yellowLimitPercentageLabel, 14 * scale)
	ac.setCustomFont(yellowLimitPercentageLabel, "Roboto", 1, 0)
	
	yellowLimitPercentageSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(yellowLimitPercentageSpinner, 80, 100)
	ac.setStep(yellowLimitPercentageSpinner, 1)
	ac.setValue(yellowLimitPercentageSpinner, yellowLimitPercentage)
	ac.setPosition(yellowLimitPercentageSpinner, 266 * scale, 296 * scale)
	ac.setSize(yellowLimitPercentageSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(yellowLimitPercentageSpinner, 14 * scale)
	ac.setCustomFont(yellowLimitPercentageSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(yellowLimitPercentageSpinner, yellowLimitPercentageSpinnerClicked)
	
	#Red light
	redLimitEnabledLabel = ac.addLabel(settingsWindow, "Enable red shift light:")
	ac.setPosition(redLimitEnabledLabel, 10 * scale, 322 * scale)
	ac.setFontSize(redLimitEnabledLabel, 14 * scale)
	ac.setCustomFont(redLimitEnabledLabel, "Roboto", 1, 0)
	
	redLimitEnabledCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(redLimitEnabledCheckBox, redLimitEnabled)
	ac.setPosition(redLimitEnabledCheckBox, 350 * scale, 324 * scale)
	ac.setSize(redLimitEnabledCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(redLimitEnabledCheckBox, redLimitEnabledCheckBoxClicked)
	
	#Red light offset
	redLimitPercentageLabel = ac.addLabel(settingsWindow, "Red shift (in % of rpm limit):")
	ac.setPosition(redLimitPercentageLabel, 10 * scale, 348 * scale)
	ac.setFontSize(redLimitPercentageLabel, 14 * scale)
	ac.setCustomFont(redLimitPercentageLabel, "Roboto", 1, 0)
	
	redLimitPercentageSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(redLimitPercentageSpinner, 80, 100)
	ac.setStep(redLimitPercentageSpinner, 1)
	ac.setValue(redLimitPercentageSpinner, redLimitPercentage)
	ac.setPosition(redLimitPercentageSpinner, 266 * scale, 348 * scale)
	ac.setSize(redLimitPercentageSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(redLimitPercentageSpinner, 14 * scale)
	ac.setCustomFont(redLimitPercentageSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(redLimitPercentageSpinner, redLimitPercentageSpinnerClicked)
	
	#Optimal shift lights
	optimalShiftLightsLabel = ac.addLabel(settingsWindow, "Enable optimal shift lights:")
	ac.setPosition(optimalShiftLightsLabel, 10 * scale, 374 * scale)
	ac.setFontSize(optimalShiftLightsLabel, 14 * scale)
	ac.setCustomFont(optimalShiftLightsLabel, "Roboto", 1, 0)
	
	optimalShiftLightsCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(optimalShiftLightsCheckBox, optimalShiftLights)
	ac.setPosition(optimalShiftLightsCheckBox, 350 * scale, 376 * scale)
	ac.setSize(optimalShiftLightsCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(optimalShiftLightsCheckBox, optimalShiftLightsCheckBoxClicked)
	
	#Optimal yellow light offset
	yellowLimitPowerPercentageLabel = ac.addLabel(settingsWindow, "Optimal yellow shift (in % of curr. gear hp):")
	ac.setPosition(yellowLimitPowerPercentageLabel, 10 * scale, 400 * scale)
	ac.setFontSize(yellowLimitPowerPercentageLabel, 14 * scale)
	ac.setCustomFont(yellowLimitPowerPercentageLabel, "Roboto", 1, 0)
	
	yellowLimitPowerPercentageSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(yellowLimitPowerPercentageSpinner, 86, 106)
	ac.setStep(yellowLimitPowerPercentageSpinner, 1)
	ac.setValue(yellowLimitPowerPercentageSpinner, yellowLimitPowerPercentage)
	ac.setPosition(yellowLimitPowerPercentageSpinner, 266 * scale, 400 * scale)
	ac.setSize(yellowLimitPowerPercentageSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(yellowLimitPowerPercentageSpinner, 14 * scale)
	ac.setCustomFont(yellowLimitPowerPercentageSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(yellowLimitPowerPercentageSpinner, yellowLimitPowerPercentageSpinnerClicked)
	
	#Optimal red light offset
	redLimitPowerPercentageLabel = ac.addLabel(settingsWindow, "Optimal red shift (in % of curr. gear hp):")
	ac.setPosition(redLimitPowerPercentageLabel, 10 * scale, 426 * scale)
	ac.setFontSize(redLimitPowerPercentageLabel, 14 * scale)
	ac.setCustomFont(redLimitPowerPercentageLabel, "Roboto", 1, 0)
	
	redLimitPowerPercentageSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(redLimitPowerPercentageSpinner, 90, 110)
	ac.setStep(redLimitPowerPercentageSpinner, 1)
	ac.setValue(redLimitPowerPercentageSpinner, redLimitPowerPercentage)
	ac.setPosition(redLimitPowerPercentageSpinner, 266 * scale, 426 * scale)
	ac.setSize(redLimitPowerPercentageSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(redLimitPowerPercentageSpinner, 14 * scale)
	ac.setCustomFont(redLimitPowerPercentageSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(redLimitPowerPercentageSpinner, redLimitPowerPercentageSpinnerClicked)
	
	#Notify FFB clipping
	notifyFFBClippingLabel = ac.addLabel(settingsWindow, "Notify FFB clipping:")
	ac.setPosition(notifyFFBClippingLabel, 400 * scale, 36 * scale)
	ac.setFontSize(notifyFFBClippingLabel, 14 * scale)
	ac.setCustomFont(notifyFFBClippingLabel, "Roboto", 1, 0)
	
	notifyFFBClippingCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(notifyFFBClippingCheckBox, notifyFFBClipping)
	ac.setPosition(notifyFFBClippingCheckBox, 740 * scale, 38 * scale)
	ac.setSize(notifyFFBClippingCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(notifyFFBClippingCheckBox, notifyFFBClippingCheckBoxClicked)
	
	#FFB clipping threshold
	ffbClippingThresholdLabel = ac.addLabel(settingsWindow, "FFB clipping threshold (in ms):")
	ac.setPosition(ffbClippingThresholdLabel, 400 * scale, 62 * scale)
	ac.setFontSize(ffbClippingThresholdLabel, 14 * scale)
	ac.setCustomFont(ffbClippingThresholdLabel, "Roboto", 1, 0)
	
	ffbClippingThresholdSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(ffbClippingThresholdSpinner, 0, 1000)
	ac.setStep(ffbClippingThresholdSpinner, 50)
	ac.setValue(ffbClippingThresholdSpinner, ffbClippingThreshold)
	ac.setPosition(ffbClippingThresholdSpinner, 656 * scale, 62 * scale)
	ac.setSize(ffbClippingThresholdSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(ffbClippingThresholdSpinner, 14 * scale)
	ac.setCustomFont(ffbClippingThresholdSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(ffbClippingThresholdSpinner, ffbClippingThresholdSpinnerClicked)
	
	#Notify wheel off center
	notifyWheelOffCenterLabel = ac.addLabel(settingsWindow, "Notify if wheel is off-center at race start:")
	ac.setPosition(notifyWheelOffCenterLabel, 400 * scale, 88 * scale)
	ac.setFontSize(notifyWheelOffCenterLabel, 14 * scale)
	ac.setCustomFont(notifyWheelOffCenterLabel, "Roboto", 1, 0)
	
	notifyWheelOffCenterCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(notifyWheelOffCenterCheckBox, notifyWheelOffCenter)
	ac.setPosition(notifyWheelOffCenterCheckBox, 740 * scale, 90 * scale)
	ac.setSize(notifyWheelOffCenterCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(notifyWheelOffCenterCheckBox, notifyWheelOffCenterCheckBoxClicked)
	
	#Notify session end
	notifySessionEndLabel = ac.addLabel(settingsWindow, "Notify session endings:")
	ac.setPosition(notifySessionEndLabel, 400 * scale, 114 * scale)
	ac.setFontSize(notifySessionEndLabel, 14 * scale)
	ac.setCustomFont(notifySessionEndLabel, "Roboto", 1, 0)
	
	notifySessionEndCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(notifySessionEndCheckBox, notifySessionEnd)
	ac.setPosition(notifySessionEndCheckBox, 740 * scale, 116 * scale)
	ac.setSize(notifySessionEndCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(notifySessionEndCheckBox, notifySessionEndCheckBoxClicked)
	
	#Notify lap times
	notifyLapTimesLabel = ac.addLabel(settingsWindow, "Notify record lap times:")
	ac.setPosition(notifyLapTimesLabel, 400 * scale, 140 * scale)
	ac.setFontSize(notifyLapTimesLabel, 14 * scale)
	ac.setCustomFont(notifyLapTimesLabel, "Roboto", 1, 0)
	
	notifyLapTimesCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(notifyLapTimesCheckBox, notifyLapTimes)
	ac.setPosition(notifyLapTimesCheckBox, 740 * scale, 142 * scale)
	ac.setSize(notifyLapTimesCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(notifyLapTimesCheckBox, notifyLapTimesCheckBoxClicked)
	
	#AI lap invalidation
	AIControlInvalidatesLapLabel = ac.addLabel(settingsWindow, "AI control invalidates lap:")
	ac.setPosition(AIControlInvalidatesLapLabel, 400 * scale, 166 * scale)
	ac.setFontSize(AIControlInvalidatesLapLabel, 14 * scale)
	ac.setCustomFont(AIControlInvalidatesLapLabel, "Roboto", 1, 0)
	
	AIControlInvalidatesLapCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(AIControlInvalidatesLapCheckBox, AIControlInvalidatesLap)
	ac.setPosition(AIControlInvalidatesLapCheckBox, 740 * scale, 168 * scale)
	ac.setSize(AIControlInvalidatesLapCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(AIControlInvalidatesLapCheckBox, AIControlInvalidatesLapCheckBoxClicked)
	
	#Use plain background
	usePlainBackgroundLabel = ac.addLabel(settingsWindow, "Use plain background:")
	ac.setPosition(usePlainBackgroundLabel, 400 * scale, 192 * scale)
	ac.setFontSize(usePlainBackgroundLabel, 14 * scale)
	ac.setCustomFont(usePlainBackgroundLabel, "Roboto", 1, 0)
	
	usePlainBackgroundCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(usePlainBackgroundCheckBox, usePlainBackground)
	ac.setPosition(usePlainBackgroundCheckBox, 740 * scale, 194 * scale)
	ac.setSize(usePlainBackgroundCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(usePlainBackgroundCheckBox, usePlainBackgroundCheckBoxClicked)
	
	#Auto looping
	autoLoopingLabel = ac.addLabel(settingsWindow, "Auto looping:")
	ac.setPosition(autoLoopingLabel, 400 * scale, 218 * scale)
	ac.setFontSize(autoLoopingLabel, 14 * scale)
	ac.setCustomFont(autoLoopingLabel, "Roboto", 1, 0)
	
	autoLoopingCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(autoLoopingCheckBox, autoLooping)
	ac.setPosition(autoLoopingCheckBox, 740 * scale, 220 * scale)
	ac.setSize(autoLoopingCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(autoLoopingCheckBox, autoLoopingCheckBoxClicked)
	
	#Sections to loop
	sectionsToLoopLabel = ac.addLabel(settingsWindow, "Sections to loop:")
	ac.setPosition(sectionsToLoopLabel, 400 * scale, 244 * scale)
	ac.setFontSize(sectionsToLoopLabel, 14 * scale)
	ac.setCustomFont(sectionsToLoopLabel, "Roboto", 1, 0)
	
	loopFirstSectionCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(loopFirstSectionCheckBox, loopFirstSection)
	ac.setPosition(loopFirstSectionCheckBox, 656 * scale, 246 * scale)
	ac.setSize(loopFirstSectionCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(loopFirstSectionCheckBox, loopFirstSectionCheckBoxClicked)
	
	loopSecondSectionCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(loopSecondSectionCheckBox, loopSecondSection)
	ac.setPosition(loopSecondSectionCheckBox, 677 * scale, 246 * scale)
	ac.setSize(loopSecondSectionCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(loopSecondSectionCheckBox, loopSecondSectionCheckBoxClicked)
	
	loopThirdSectionCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(loopThirdSectionCheckBox, loopThirdSection)
	ac.setPosition(loopThirdSectionCheckBox, 698 * scale, 246 * scale)
	ac.setSize(loopThirdSectionCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(loopThirdSectionCheckBox, loopThirdSectionCheckBoxClicked)
	
	loopFourthSectionCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(loopFourthSectionCheckBox, loopFourthSection)
	ac.setPosition(loopFourthSectionCheckBox, 719 * scale, 246 * scale)
	ac.setSize(loopFourthSectionCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(loopFourthSectionCheckBox, loopFourthSectionCheckBoxClicked)
	
	loopFifthSectionCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(loopFifthSectionCheckBox, loopFifthSection)
	ac.setPosition(loopFifthSectionCheckBox, 740 * scale, 246 * scale)
	ac.setSize(loopFifthSectionCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(loopFifthSectionCheckBox, loopFifthSectionCheckBoxClicked)
	
	#Auto looping time
	autoLoopingTimeLabel = ac.addLabel(settingsWindow, "Auto looping speed (in ms):")
	ac.setPosition(autoLoopingTimeLabel, 400 * scale, 270 * scale)
	ac.setFontSize(autoLoopingTimeLabel, 14 * scale)
	ac.setCustomFont(autoLoopingTimeLabel, "Roboto", 1, 0)
	
	autoLoopingTimeSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(autoLoopingTimeSpinner, 1000, 5000)
	ac.setStep(autoLoopingTimeSpinner, 500)
	ac.setValue(autoLoopingTimeSpinner, autoLoopingTime)
	ac.setPosition(autoLoopingTimeSpinner, 656 * scale, 270 * scale)
	ac.setSize(autoLoopingTimeSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(autoLoopingTimeSpinner, 14 * scale)
	ac.setCustomFont(autoLoopingTimeSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(autoLoopingTimeSpinner, autoLoopingTimeSpinnerClicked)
	
	#Temperature transition
	temperatureTransitionRangeLabel = ac.addLabel(settingsWindow, "Tyre temperature transition range (in °C):")
	ac.setPosition(temperatureTransitionRangeLabel, 400 * scale, 296 * scale)
	ac.setFontSize(temperatureTransitionRangeLabel, 14 * scale)
	ac.setCustomFont(temperatureTransitionRangeLabel, "Roboto", 1, 0)
	
	temperatureTransitionRangeSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(temperatureTransitionRangeSpinner, 5, 200)
	ac.setStep(temperatureTransitionRangeSpinner, 5)
	ac.setValue(temperatureTransitionRangeSpinner, temperatureTransitionRange)
	ac.setPosition(temperatureTransitionRangeSpinner, 656 * scale, 296 * scale)
	ac.setSize(temperatureTransitionRangeSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(temperatureTransitionRangeSpinner, 14 * scale)
	ac.setCustomFont(temperatureTransitionRangeSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(temperatureTransitionRangeSpinner, temperatureTransitionRangeSpinnerClicked)
	
	#Pressure transition
	pressureTransitionRangeLabel = ac.addLabel(settingsWindow, "Tyre pressure transition range (in psi):")
	ac.setPosition(pressureTransitionRangeLabel, 400 * scale, 322 * scale)
	ac.setFontSize(pressureTransitionRangeLabel, 14 * scale)
	ac.setCustomFont(pressureTransitionRangeLabel, "Roboto", 1, 0)
	
	pressureTransitionRangeSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(pressureTransitionRangeSpinner, 1, 8)
	ac.setStep(pressureTransitionRangeSpinner, 1)
	ac.setValue(pressureTransitionRangeSpinner, pressureTransitionRange)
	ac.setPosition(pressureTransitionRangeSpinner, 656 * scale, 322 * scale)
	ac.setSize(pressureTransitionRangeSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(pressureTransitionRangeSpinner, 14 * scale)
	ac.setCustomFont(pressureTransitionRangeSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(pressureTransitionRangeSpinner, pressureTransitionRangeSpinnerClicked)
	
	#Brake transition
	brakeTransitionRangeLabel = ac.addLabel(settingsWindow, "Brake temperature transition range (in °C):")
	ac.setPosition(brakeTransitionRangeLabel, 400 * scale, 348 * scale)
	ac.setFontSize(brakeTransitionRangeLabel, 14 * scale)
	ac.setCustomFont(brakeTransitionRangeLabel, "Roboto", 1, 0)
	
	brakeTransitionRangeSpinner = ac.addSpinner(settingsWindow, "")
	ac.setRange(brakeTransitionRangeSpinner, 10, 400)
	ac.setStep(brakeTransitionRangeSpinner, 1)
	ac.setValue(brakeTransitionRangeSpinner, brakeTransitionRange)
	ac.setPosition(brakeTransitionRangeSpinner, 656 * scale, 348 * scale)
	ac.setSize(brakeTransitionRangeSpinner, 100 * scale, 22 * scale)
	ac.setFontSize(brakeTransitionRangeSpinner, 14 * scale)
	ac.setCustomFont(brakeTransitionRangeSpinner, "Roboto", 1, 0)
	ac.addOnValueChangeListener(brakeTransitionRangeSpinner, brakeTransitionRangeSpinnerClicked)
	
	#Brand instead of pedals
	showBrandInsteadOfPedalsLabel = ac.addLabel(settingsWindow, "Show brand instead of pedals:")
	ac.setPosition(showBrandInsteadOfPedalsLabel, 400 * scale, 374 * scale)
	ac.setFontSize(showBrandInsteadOfPedalsLabel, 14 * scale)
	ac.setCustomFont(showBrandInsteadOfPedalsLabel, "Roboto", 1, 0)
	
	showBrandInsteadOfPedalsCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(showBrandInsteadOfPedalsCheckBox, showBrandInsteadOfPedals)
	ac.setPosition(showBrandInsteadOfPedalsCheckBox, 740 * scale, 376 * scale)
	ac.setSize(showBrandInsteadOfPedalsCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(showBrandInsteadOfPedalsCheckBox, showBrandInsteadOfPedalsCheckBoxClicked)
	
	#Section buttons
	disableSectionButtonsLabel = ac.addLabel(settingsWindow, "Disable section buttons:")
	ac.setPosition(disableSectionButtonsLabel, 400 * scale, 400 * scale)
	ac.setFontSize(disableSectionButtonsLabel, 14 * scale)
	ac.setCustomFont(disableSectionButtonsLabel, "Roboto", 1, 0)
	
	disableSectionButtonsCheckBox = ac.addCheckBox(settingsWindow, "")
	ac.setValue(disableSectionButtonsCheckBox, disableSectionButtons)
	ac.setPosition(disableSectionButtonsCheckBox, 740 * scale, 402 * scale)
	ac.setSize(disableSectionButtonsCheckBox, 16 * scale, 16 * scale)
	ac.addOnCheckBoxChanged(disableSectionButtonsCheckBox, disableSectionButtonsCheckBoxClicked)
	
	#App info
	appInfoLabel = ac.addLabel(settingsWindow, "Sidekick v1.11.1 by Topuz")
	ac.setPosition(appInfoLabel, 10 * scale, 466 * scale)
	ac.setFontSize(appInfoLabel, 14 * scale)
	ac.setCustomFont(appInfoLabel, "Roboto", 1, 0)
	
	#CM info
	cmInfoLabel = ac.addLabel(settingsWindow, "Best with Content Manager")
	ac.setPosition(cmInfoLabel, 400 * scale, 466 * scale)
	ac.setFontSize(cmInfoLabel, 14 * scale)
	ac.setCustomFont(cmInfoLabel, "Roboto", 1, 0)
	
	#CM icon
	cmIconLabel = ac.addLabel(settingsWindow, "")
	ac.setPosition(cmIconLabel, 400 * scale, 432 * scale)
	ac.setSize(cmIconLabel, 32 * scale, 32 * scale)
	ac.drawBorder(cmIconLabel, 0)
	ac.setBackgroundTexture(cmIconLabel, cmIcon)
	
	#Reset to default
	resetToDefaultButton = ac.addButton(settingsWindow, "Default")
	ac.setPosition(resetToDefaultButton, 656 * scale, 466 * scale)
	ac.setSize(resetToDefaultButton, 100 * scale, 22 * scale)
	ac.setFontSize(resetToDefaultButton, 14 * scale)
	ac.setCustomFont(resetToDefaultButton, "Roboto", 1, 0)
	ac.addOnClickedListener(resetToDefaultButton, resetToDefaultButtonClicked)
	
	#Render callback
	ac.addRenderCallback(appWindow, onFormRender)
	
def acUpdate(deltaT):

	global timer0, timer1, timer2, timer3, gearTimer, dominantTimer, autoLoopingTimer
	
	global runOnce, runOnce2, wasAlreadyDisplayed
	
	global rpmValue, turboValue, kersChargeValue, kersInputValue, ersCurrentKJValue, clutchValue, brakeValue, throttleValue, ffbValue
	global gearValue, driveTrainSpeedValue, tiresOutValue
	global focusedCarValue, speedValueKPH, speedValueMPH, steerInputValue, currentLapValue, lapProgressValue, lapValue, drsAvailableValue, drsEnabledValue, ersIsChargingValue, P2PStatusValue, P2PActivationsValue
	global statusValue, rpmMaxValue, sessionTypeValue, sessionTimeValue, raceIsTimed, trackLengthValue, carInPitlineValue, carDrivenByAIValue, positionValue, positionBoardValue, serverIPValue, totalCarsValue, occupiedSlotsValue, totalLapsValue, fuelAmountValue, tyreCompoundValue, tyreWearValue, tyreTemperatureValue, tyreTemperatureValueI, tyreTemperatureValueM, tyreTemperatureValueO, tyrePressureValue, brakeTemperatureValue, hasERS, hasKERS, ersMaxJValue
	
	global previousStatusValue, lastLapReplayValue, currentLapReplayValue
	global resetTrigger
	global rpmPercentageValue
	global turboMaxValue, turboPercentageValue
	global DTConstants, previousRpm, previousGearValue, ratioList, rpmInNextGear, upperBound, lowerBound, upperBoundInNextGear, lowerBoundInNextGear, coefficient, currentPower, powerInNextGear
	global currentLapValueMinutes, currentLapValueSeconds, lastLapValue, lastLapValueMinutes, lastLapValueSeconds, bestLapValue, previousBestLapValue, bestLapValueMinutes, bestLapValueSeconds, personalBestLapValue, previousPersonalBestLapValue, personalBestLapValueMinutes, personalBestLapValueSeconds, lapValidityValue, lapWasInvalid
	global tyrePracticalTemperatureValue
	global outLap, practiceIsTimed, carWasInPit, carWasDrivenByAI, P2PActivationsMaxValue
	global fuelStartValue, fuelEndValue, relevantLapsNumber, fuelSpentValue, fuelPerLapValue
	global tyreCompoundShort, tyreCompoundCleaned, previousTyreCompoundValue, minimumOptimalTemperature, maximumOptimalTemperature, idealPressureFront, idealPressureRear, minimumOptimalBrakeTemperatureFront, maximumOptimalBrakeTemperatureFront, minimumOptimalBrakeTemperatureRear, maximumOptimalBrakeTemperatureRear
	global previousLapValue
	global ffbTimer, ffbWasTooStrong
	global isDominantActive
	
	global selectorCounter, previousSelectorCounter
	global timerTrigger1, spinnerButton1, timerTrigger2, spinnerButton2, timerTrigger3, spinnerButton3, timerTrigger4, spinnerButton4, timerTrigger5, spinnerButton5
	
	global previousLapProgressValue, posList, timeList, bestPosList, bestTimeList, personalBestPosList, personalBestTimeList, prevt, prevt2, ttb, ttb_old, ttpb, ttpb_old
	global distanceToCar, timeToCar
	
	global appWindow, rpmBorder, separatorsLabel, selectionIndicatorLabel, gearLabel, speedLabel, speedUnitLabel, firstButton, secondButton, thirdButton, fourthButton, fifthButton, firstLabel, secondLabel, thirdLabel, fourthLabel, fifthLabel, tyreLabelFL, tyreLabelFR, tyreLabelRL, tyreLabelRR, deltaGainLabel, drsLabel, dominantLabel
	global odometerInfoLabel
	global tyreInfoLabel, brakeInfoLabel, shiftsInfoLabel
	
	global trackConfigValue
	global compounds, modCompounds, brakes, modBrakes
	global odometer, tripOdometer
	
	#Opacity needs to be reset if the app was moved
	ac.setBackgroundOpacity(appWindow, 0)
	ac.setBackgroundOpacity(carDataWindow, 0.7)
	ac.setBackgroundOpacity(settingsWindow, 0.7)
	
	#Update the timers
	timer0 += deltaT
	timer1 += deltaT
	timer2 += deltaT
	timer3 += deltaT
	gearTimer += deltaT
	dominantTimer += deltaT
	autoLoopingTimer += deltaT
	
	#Update the odometers
	if statusValue == 2 and not carDrivenByAIValue:
		odometer += deltaT * speedValueKPH / 3600
		tripOdometer += deltaT * speedValueKPH / 3600
	
	#Fetch data 60 times per second
	if timer0 > 0.0166:
		rpmValue = ac.getCarState(0, acsys.CS.RPM)
		turboValue = ac.getCarState(0, acsys.CS.TurboBoost)
		kersChargeValue = ac.getCarState(0, acsys.CS.KersCharge)
		kersInputValue = ac.getCarState(0, acsys.CS.KersInput)
		if hasERS or hasKERS:
			ersCurrentKJValue = ac.getCarState(0, acsys.CS.ERSCurrentKJ)
		clutchValue = ac.getCarState(focusedCarValue, acsys.CS.Clutch)
		brakeValue = ac.getCarState(focusedCarValue, acsys.CS.Brake)
		throttleValue = ac.getCarState(focusedCarValue, acsys.CS.Gas)
		ffbValue = ac.getCarState(focusedCarValue, acsys.CS.LastFF)
		
	#Fetch data 30 times per second
	if timer1 > 0.0333:
		gearValue = ac.getCarState(focusedCarValue, acsys.CS.Gear)
		driveTrainSpeedValue = ac.getCarState(0, acsys.CS.DriveTrainSpeed)
		tiresOutValue = info.physics.numberOfTyresOut
		
	#Fetch data 10 times per second
	if timer2 > 0.1:
		focusedCarValue = ac.getFocusedCar()
		speedValueKPH = ac.getCarState(focusedCarValue, acsys.CS.SpeedKMH)
		speedValueMPH = ac.getCarState(focusedCarValue, acsys.CS.SpeedMPH)
		steerInputValue = ac.getCarState(0, acsys.CS.Steer)
		currentLapValue = info.graphics.iCurrentTime
		#A dirty hack for Nordschleife Tourist
		if trackConfigValue == "touristenfahrten":
			lapProgressValue = (ac.getCarState(0, acsys.CS.NormalizedSplinePosition) + 0.0480) % 1
		else:
			lapProgressValue = ac.getCarState(0, acsys.CS.NormalizedSplinePosition)
		lapValue = ac.getCarState(0, acsys.CS.LapCount)
		drsAvailableValue = ac.getCarState(0, acsys.CS.DrsAvailable)
		drsEnabledValue = ac.getCarState(0, acsys.CS.DrsEnabled)
		ersIsChargingValue = info.physics.ersIsCharging
		P2PStatusValue = ac.getCarState(0, acsys.CS.P2PStatus)
		P2PActivationsValue = ac.getCarState(0, acsys.CS.P2PActivations)
	
	#Fetch data once per second
	if timer3 > 1:
		statusValue = info.graphics.status
		#maxRpm is buggy so we fetch it only if it exists
		if info.static.maxRpm:
			rpmMaxValue = info.static.maxRpm
		sessionTypeValue = info.graphics.session
		sessionTimeValue = info.graphics.sessionTimeLeft // 1000
		raceIsTimed = info.static.isTimedRace
		trackLengthValue = ac.getTrackLength(0)
		carInPitlineValue = ac.isCarInPitline(0)
		carDrivenByAIValue = info.physics.isAIControlled
		positionValue = ac.getCarRealTimeLeaderboardPosition(0)
		positionBoardValue = ac.getCarLeaderboardPosition(0)
		serverIPValue = ac.getServerIP()
		totalCarsValue = ac.getCarsCount()
		occupiedSlotsValue = ac.getServerSlotsCount()
		totalLapsValue = info.graphics.numberOfLaps
		fuelAmountValue = info.physics.fuel
		tyreCompoundValue = info.graphics.tyreCompound
		tyreWearValue = info.physics.tyreWear
		tyreTemperatureValue = info.physics.tyreCoreTemperature
		tyreTemperatureValueI = info.physics.tyreTempI
		tyreTemperatureValueM = info.physics.tyreTempM
		tyreTemperatureValueO = info.physics.tyreTempO
		tyrePressureValue = info.physics.wheelsPressure
		brakeTemperatureValue = info.physics.brakeTemp
		hasERS = info.static.hasERS
		hasKERS = info.static.hasKERS
		if hasERS or hasKERS:
			ersMaxJValue = ac.getCarState(0, acsys.CS.ERSMaxJ)

	#Display/calculate 60 times per second
	if timer0 > 0.0166:
		timer0 = 0
		
		#Shifting stuff
		if rpmMaxValue:
			rpmPercentageValue = rpmValue / rpmMaxValue
		
		#Turbo
		if turboMaxValue:
			turboPercentageValue = turboValue / turboMaxValue
		else:
			turboPercentageValue = 0
		
	#Display/calculate 30 times per second
	if timer1 > 0.0333:
		timer1 = 0
		
		#Gear
		if gearValue == 0: 
			ac.setText(gearLabel, "R")
		elif gearValue == 1: 
			ac.setText(gearLabel, "N")
		else: 
			ac.setText(gearLabel, "{}".format(gearValue - 1))
		
		#Shifting stuff
		if not info.static.maxRpm and rpmValue > rpmMaxValue:
			rpmMaxValue = rpmValue

		#Do this if advanced shifting is disabled or if maxPowerRpm exceeds limiter
		if not maxPowerRpm or not optimalShiftLights or maxPowerRpm >= rpmMaxValue * yellowLimitPercentage / 100 and statusValue == 2:
			ac.setText(shiftsInfoLabel, "Shifts: max power near limiter, limiter used as shift point")
			if yellowLimitEnabled and rpmPercentageValue > yellowLimitPercentage / 100 and rpmPercentageValue < redLimitPercentage / 100:
				ac.setVisible(rpmBorder, 1)
				ac.setBackgroundTexture(rpmBorder, border_yellow)
			elif redLimitEnabled and rpmPercentageValue >= redLimitPercentage / 100:
				ac.setVisible(rpmBorder, 1)
				ac.setBackgroundTexture(rpmBorder, border_red)
			else:
				ac.setVisible(rpmBorder, 0)
		
		#Do this if maxPowerRpm exists, it's turned on and lower than limiter
		elif maxPowerRpm and maxPowerRpm < rpmMaxValue and optimalShiftLights and statusValue == 2:
			ac.setText(shiftsInfoLabel, "Shifts: max power below limiter, adjusted to maximize power")

			#Learn the gear ratios
			if previousGearValue != gearValue:
				gearTimer = 0
			if gearValue > 1 and clutchValue == 1 and rpmValue > 500 and round(driveTrainSpeedValue / rpmValue, 6) != DTConstants[gearValue - 2] and gearTimer > 0.5:
				DTConstants[gearValue - 2] = round(driveTrainSpeedValue / rpmValue, 6)
				#ac.console(str(DTConstants))
				for step in range(len(ratioList)):
					if DTConstants[step] and DTConstants[step + 1] and ratioList[step] != DTConstants[step] / DTConstants[step + 1]:
						ratioList[step] = DTConstants[step] / DTConstants[step + 1]
						#ac.console(str(ratioList))
			previousGearValue = gearValue
				
			#Find rpm in next gear
			if gearValue > 1 and gearValue < 9: 
				rpmInNextGear = rpmValue * ratioList[gearValue - 2]
			
				#Find power in current gear
				for step in range(len(powerCurve)):
					if int(powerCurve[step][0]) > rpmValue:
						upperBound = powerCurve[step]
						if step == 0:
							lowerBound = powerCurve[0]
						else:
							lowerBound = powerCurve[step - 1]
						if int(upperBound[0]) - int(lowerBound[0]):
							coefficient = (rpmValue - int(lowerBound[0])) / (int(upperBound[0]) - int(lowerBound[0]))
						currentPower = int(lowerBound[1]) + (int(upperBound[1]) - int(lowerBound[1])) * coefficient
						break
				
				#Find power in next gear
				for step in range(len(powerCurve)):
					if int(powerCurve[step][0]) > rpmInNextGear:
						upperBoundInNextGear = powerCurve[step]
						if step == 0:
							lowerBoundInNextGear = powerCurve[0]
						else:
							lowerBoundInNextGear = powerCurve[step - 1]
						if int(upperBoundInNextGear[0]) - int(lowerBoundInNextGear[0]):
							coefficient = (rpmInNextGear - int(lowerBoundInNextGear[0])) / (int(upperBoundInNextGear[0]) - int(lowerBoundInNextGear[0]))
						powerInNextGear = int(lowerBoundInNextGear[1]) + (int(upperBoundInNextGear[1]) - int(lowerBoundInNextGear[1])) * coefficient
						break
			
			else:
				rpmInNextGear = 0
				currentPower = 0
				powerInNextGear = 0

			#Optimal shift lights
			if yellowLimitEnabled and powerInNextGear > currentPower * yellowLimitPowerPercentage / 100 and powerInNextGear < currentPower * redLimitPowerPercentage / 100 and rpmValue > maxPowerRpm:
				ac.setVisible(rpmBorder, 1)
				ac.setBackgroundTexture(rpmBorder, border_yellow)
				#ac.console("OPTIMAL YELLOW")
			elif redLimitEnabled and powerInNextGear > currentPower * redLimitPowerPercentage / 100 and rpmValue > maxPowerRpm * redLimitPercentage / 100 and rpmValue > maxPowerRpm:
				ac.setVisible(rpmBorder, 1)
				ac.setBackgroundTexture(rpmBorder, border_red)
				#ac.console("OPTIMAL RED")
			else:
				ac.setVisible(rpmBorder, 0)
			#Fallback in case you're about to hit the limiter
			if yellowLimitEnabled and rpmPercentageValue > yellowLimitPercentage / 100 and rpmPercentageValue < redLimitPercentage / 100:
				ac.setVisible(rpmBorder, 1)
				ac.setBackgroundTexture(rpmBorder, border_yellow)
				#ac.console("RPM YELLOW")
			elif redLimitEnabled and rpmValue > rpmMaxValue * redLimitPercentage / 100:
				ac.setVisible(rpmBorder, 1)
				ac.setBackgroundTexture(rpmBorder, border_red)
				#ac.console("RPM RED")
		
		#Turbo
		if turboValue > turboMaxValue:
			turboMaxValue = turboValue

		#Lap validity check
		if not lapValidityValue and (tiresOutValue > 2 or carWasInPit or (carWasDrivenByAI and AIControlInvalidatesLap)):
			lapValidityValue = 1
		
		#Inform what's being toggled in first section
		if timerTrigger1:
			timerTrigger1 += 0.016
			if timerTrigger1 > 1.2:
				timerTrigger1 = 0
			else:
				if spinnerButton1 == 0:
					ac.setText(firstLabel, "THIS")
				elif spinnerButton1 == 1:
					ac.setText(firstLabel, "LAST")
				elif spinnerButton1 == 2:
					ac.setText(firstLabel, "BEST")
				elif spinnerButton1 == 3:
					ac.setText(firstLabel, "PBEST")
				ac.setFontColor(firstLabel, 0.86, 0.86, 0.86, 1 - 5 * (timerTrigger1 - 1))
				
		#Inform what's being toggled in second section
		if timerTrigger2:
			timerTrigger2 += 0.016
			if timerTrigger2 > 1.2:
				timerTrigger2 = 0
			else:
				if spinnerButton2 == 0:
					ac.setText(secondLabel, "BEST")
				elif spinnerButton2 == 1:
					ac.setText(secondLabel, "PBEST")
				elif spinnerButton2 == 2:
					ac.setText(secondLabel, "FRONT")
				elif spinnerButton2 == 3:
					ac.setText(secondLabel, "BACK")
				ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1 - 5 * (timerTrigger2 - 1))
				
		#Inform what's being toggled in third section
		if timerTrigger3:
			timerTrigger3 += 0.016
			if timerTrigger3 > 1.2:
				timerTrigger3 = 0
			else:
				if spinnerButton3 == 0:
					ac.setText(thirdLabel, "POS")
				elif spinnerButton3 == 1:
					ac.setText(thirdLabel, "LAP")
				elif spinnerButton3 == 2:
					ac.setText(thirdLabel, "TIME")
				ac.setFontColor(thirdLabel, 0.86, 0.86, 0.86, 1 - 5 * (timerTrigger3 - 1))
				
		#Inform what's being toggled in fourth section
		if timerTrigger4:
			timerTrigger4 += 0.016
			if timerTrigger4 > 1.2:
				timerTrigger4 = 0
			else:
				if spinnerButton4 == 0:
					ac.setText(fourthLabel, "L REM")
				elif spinnerButton4 == 1:
					ac.setText(fourthLabel, "L/LAP")
				elif spinnerButton4 == 2:
					ac.setText(fourthLabel, "LAPS")
				elif spinnerButton4 == 3:
					ac.setText(fourthLabel, "L REQ")
				elif spinnerButton4 == 4:
					ac.setText(fourthLabel, "L TOP")
				ac.setFontColor(fourthLabel, 0.86, 0.86, 0.86, 1 - 5 * (timerTrigger4 - 1))
		
		#Inform what's being toggled in fifth section
		if timerTrigger5:
			timerTrigger5 += 0.016
			if timerTrigger5 > 1.2:
				timerTrigger5 = 0
			else:
				if spinnerButton5 == 0:
					ac.setText(fifthLabel, "WEAR")
				elif spinnerButton5 == 1:
					ac.setText(fifthLabel, "TEMP")
				elif spinnerButton5 == 2:
					ac.setText(fifthLabel, "PRESS")
				elif spinnerButton5 == 3:
					ac.setText(fifthLabel, "BRAKE")
				elif spinnerButton5 == 4:
					ac.setText(fifthLabel, "IDEAL")
				ac.setFontColor(fifthLabel, 0.86, 0.86, 0.86, 1 - 5 * (timerTrigger5 - 1))
		
		#START DOMINANT EVENTS#
		
		#FFB clipping detection
		if notifyFFBClipping:
			if ffbValue > 1:
				ffbTimer += 0.016
			else:
				ffbTimer = 0
			if ffbTimer > ffbClippingThreshold / 2000 and runOnce:
				runOnce = True
				dominantEvent()
				dominantTimer = 0
				ac.setFontColor(dominantLabel, 1, 0.17, 0, 1)
				ac.setText(dominantLabel, "CONSIDER REDUCING FFB GAIN")

		#END DOMINANT EVENTS#
				
	#Display/calculate 10 times per second
	if timer2 > 0.1:
		timer2 = 0
		
		#Reset session check
		if resetTrigger == 1 and currentLapValue < 500 and lapValue == 0 and speedValueKPH < 10:
			resetTrigger = 0
			
			ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
			ac.setText(secondLabel, "-.--")
			ac.setVisible(deltaGainLabel, 0)
			
			lastLapValue = 0
			lastLapValueMinutes = 0
			lastLapValueSeconds = 0
			bestLapValue = 0
			previousBestLapValue = 0
			bestLapValueMinutes = 0
			bestLapValueSeconds = 0
			previousPersonalBestLapValue = 0
			lapValidityValue = 0
			lapWasInvalid = False
			
			outLap = 1
			practiceIsTimed = 0
			carWasInPit = 0
			carWasDrivenByAI = 0
			
			relevantLapsNumber = 0
			fuelSpentValue = 0
			fuelPerLapValue = 0
			
			previousLapValue = 0
			
			bestPosList = []
			bestTimeList = []
			prevt = 0
			prevt2 = 0
			
			tripOdometer = 0
			
			#ac.console("Reset!")
		
		elif resetTrigger == 0 and currentLapValue > 500:
			resetTrigger = 1
		if (currentLapValue < 1000 and lapValue == 0 and speedValueKPH > 10 and outLap) or sessionTypeValue == 2 and outLap:
			outLap = 0
			#ac.console("Outlap done!")
			
		#Selection indicator
		if previousSelectorCounter != selectorCounter and (selectorCounter == -1 or selectorCounter == 0):
			previousSelectorCounter = selectorCounter
			ac.setPosition(selectionIndicatorLabel, 94 * scale, 34 * scale)
		elif previousSelectorCounter != selectorCounter and selectorCounter == 1:
			previousSelectorCounter = selectorCounter
			ac.setPosition(selectionIndicatorLabel, 155 * scale, 34 * scale)
		elif previousSelectorCounter != selectorCounter and selectorCounter == 2:
			previousSelectorCounter = selectorCounter
			ac.setPosition(selectionIndicatorLabel, 212 * scale, 34 * scale)
		elif previousSelectorCounter != selectorCounter and selectorCounter == 3:
			previousSelectorCounter = selectorCounter
			ac.setPosition(selectionIndicatorLabel, 269 * scale, 34 * scale)
		elif previousSelectorCounter != selectorCounter and selectorCounter == 4:
			previousSelectorCounter = selectorCounter
			ac.setPosition(selectionIndicatorLabel, 327 * scale, 38 * scale)
		
		#DRS
		if drsEnabledValue:
			ac.setBackgroundTexture(drsLabel, drs_enabled)
			ac.setVisible(drsLabel, 1)
		elif drsAvailableValue:
			ac.setBackgroundTexture(drsLabel, drs_available)
			ac.setVisible(drsLabel, 1)
		else:
			ac.setVisible(drsLabel, 0)
		
		#Speed
		if speedInKPH:
			ac.setText(speedLabel, "{:.0f}".format(speedValueKPH))
		else:
			ac.setText(speedLabel, "{:.0f}".format(speedValueMPH))
		
		#Current lap time
		currentLapValueSeconds = (currentLapValue / 1000) % 60
		currentLapValueMinutes = (currentLapValue // 1000) // 60
		
		#Display timing section
		if not timerTrigger1:
			if spinnerButton1 == 0:
				if lapValidityValue:
					ac.setFontColor(firstLabel, 1, 0.17, 0, 1)
				else:
					ac.setFontColor(firstLabel, 0.86, 0.86, 0.86, 1)
				ac.setText(firstLabel, "{:.0f}:{:06.3f}".format(currentLapValueMinutes, currentLapValueSeconds)[:-2])
			if spinnerButton1 == 1 or (currentLapValue < 4000 and lastLapValue):
				if lapWasInvalid:
					ac.setFontColor(firstLabel, 1, 0.17, 0, 1)
				else:
					ac.setFontColor(firstLabel, 0.86, 0.86, 0.86, 1)
				ac.setText(firstLabel, "{:.0f}:{:06.3f}".format(lastLapValueMinutes, lastLapValueSeconds)[:-1])
			elif spinnerButton1 == 2:
				ac.setFontColor(firstLabel, 0.86, 0.86, 0.86, 1)
				ac.setText(firstLabel, "{:.0f}:{:06.3f}".format(bestLapValueMinutes, bestLapValueSeconds)[:-1])
			elif spinnerButton1 == 3:
				ac.setFontColor(firstLabel, 0.86, 0.86, 0.86, 1)
				ac.setText(firstLabel, "{:.0f}:{:06.3f}".format(personalBestLapValueMinutes, personalBestLapValueSeconds)[:-1])
				
		#Delta harvesting
		if lapProgressValue > previousLapProgressValue and lapProgressValue < 1:
			timeList.append(currentLapValue)
			posList.append(lapProgressValue)
		previousLapProgressValue = lapProgressValue
		
		#Delta section calculation and display
		if currentLapValue > 4000 and lapProgressValue > 0.005 and lapProgressValue < 0.995 and carWasInPit == 0 and spinnerButton2 < 2 and not timerTrigger2:
			if bestLapValue and spinnerButton2 == 0:
				i = bisect.bisect_right(bestPosList, lapProgressValue) - 1
				c = (bestTimeList[i + 1] - bestTimeList[i]) / (bestPosList[i + 1] - bestPosList[i])
				interpolatedLapValue = bestTimeList[i] + c * (lapProgressValue - bestPosList[i])
				t = (currentLapValue - interpolatedLapValue) / 1000
		
				if t == 0:
					ac.setText(secondLabel, "-.--")
					ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
				elif t > 0:
					if t >= 10:
						ac.setText(secondLabel, "{:+.1f}".format(t))
					else:
						ac.setText(secondLabel, "{:+.2f}".format(t))
					ac.setFontColor(secondLabel, 1, 0.17, 0, 1)
				else:
					if t <= -10:
						ac.setText(secondLabel, "{:+.1f}".format(t))
					else:
						ac.setText(secondLabel, "{:+.2f}".format(t))
					ac.setFontColor(secondLabel, 0.17, 1, 0, 1)
					
				if prevt2:
					ttb_old = ttb
					ttb = 2 * t - prevt - prevt2
					
					if ttb == 0 and ttb_old != 0:
						ac.setVisible(deltaGainLabel, 0)
					elif ttb_old >= 0 and ttb < 0:
						if not isDominantActive:
							ac.setVisible(deltaGainLabel, 1)
						ac.setBackgroundTexture(deltaGainLabel, delta_good)
					elif ttb_old <= 0 and ttb > 0:
						if not isDominantActive:
							ac.setVisible(deltaGainLabel, 1)
						ac.setBackgroundTexture(deltaGainLabel, delta_bad)
				
				prevt2 = float(prevt)
				prevt = float(t)
			
			elif bestLapValue == 0 and spinnerButton2 == 0:
				ac.setText(secondLabel, "-.--")
				ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
			
			if personalBestLapValue and spinnerButton2 == 1 and outLap != 1:
				i = bisect.bisect_right(personalBestPosList, lapProgressValue) - 1
				c = (personalBestTimeList[i + 1] - personalBestTimeList[i]) / (personalBestPosList[i + 1] - personalBestPosList[i])
				interpolatedLapValue = personalBestTimeList[i] + c * (lapProgressValue - personalBestPosList[i])
				t = (currentLapValue - interpolatedLapValue) / 1000
		
				if t == 0:
					ac.setText(secondLabel, "-.--")
					ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
				elif t > 0:
					if t >= 10:
						ac.setText(secondLabel, "{:+.1f}".format(t))
					else:
						ac.setText(secondLabel, "{:+.2f}".format(t))
					ac.setFontColor(secondLabel, 1, 0.17, 0, 1)
				else:
					if t <= -10:
						ac.setText(secondLabel, "{:+.1f}".format(t))
					else:
						ac.setText(secondLabel, "{:+.2f}".format(t))
					ac.setFontColor(secondLabel, 0.17, 1, 0, 1)
					
				if prevt2:
					ttpb_old = ttpb
					ttpb = 2 * t - prevt - prevt2
					
					if ttpb == 0 and ttpb_old != 0:
						ac.setVisible(deltaGainLabel, 0)
					elif ttpb_old >= 0 and ttpb < 0:
						if not isDominantActive:
							ac.setVisible(deltaGainLabel, 1)
						ac.setBackgroundTexture(deltaGainLabel, delta_good)
					elif ttpb_old <= 0 and ttpb > 0:
						if not isDominantActive:
							ac.setVisible(deltaGainLabel, 1)
						ac.setBackgroundTexture(deltaGainLabel, delta_bad)
				
				prevt2 = float(prevt)
				prevt = float(t)
					
			elif (personalBestLapValue == 0 or outLap) and spinnerButton2 == 1:
				ac.setVisible(deltaGainLabel, 0)
				ac.setText(secondLabel, "-.--")
				ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
		
		elif currentLapValue > 4000 and carWasInPit and spinnerButton2 < 2 and not timerTrigger2:
			ac.setVisible(deltaGainLabel, 0)
			ac.setText(secondLabel, "-.--")
			ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
			
		elif currentLapValue > 1000 and currentLapValue < 4000 and spinnerButton2 < 2 and not timerTrigger2:
			if bestLapValue and spinnerButton2 == 0 and lapValue > 1:
				if previousBestLapValue and previousBestLapValue > bestLapValue:
					t = (lastLapValue - previousBestLapValue) / 1000
				else:
					t = (lastLapValue - bestLapValue) / 1000
				if t == 0:
					ac.setText(secondLabel, "-.--")
					ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
				elif t > 0:
					if t >= 10:
						ac.setText(secondLabel, "{:+.1f}".format(t))
					else:
						ac.setText(secondLabel, "{:+.2f}".format(t))
					ac.setFontColor(secondLabel, 1, 0.17, 0, 1)
				else:
					if t <= -10:
						ac.setText(secondLabel, "{:+.1f}".format(t))
					else:
						ac.setText(secondLabel, "{:+.2f}".format(t))
					ac.setFontColor(secondLabel, 0.17, 1, 0, 1)
				
			if personalBestLapValue and spinnerButton2 == 1 and lapValue > 0:
				if previousPersonalBestLapValue and previousPersonalBestLapValue > personalBestLapValue:
					t = (lastLapValue - previousPersonalBestLapValue) / 1000
				else:
					t = (lastLapValue - personalBestLapValue) / 1000
				if t == 0:
					ac.setText(secondLabel, "-.--")
					ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
				elif t > 0:
					if t >= 10:
						ac.setText(secondLabel, "{:+.1f}".format(t))
					else:
						ac.setText(secondLabel, "{:+.2f}".format(t))
					ac.setFontColor(secondLabel, 1, 0.17, 0, 1)
				else:
					if t <= -10:
						ac.setText(secondLabel, "{:+.1f}".format(t))
					else:
						ac.setText(secondLabel, "{:+.2f}".format(t))
					ac.setFontColor(secondLabel, 0.17, 1, 0, 1)
					
		elif spinnerButton2 == 2 and not timerTrigger2:
			ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
			ac.setText(secondLabel, "-.--")
			if sessionTypeValue == 2:
				for step in range(1, totalCarsValue):
					if ac.getCarRealTimeLeaderboardPosition(step) == positionValue - 1:
						distanceToCar = max(0, (ac.getCarState(step, acsys.CS.NormalizedSplinePosition) * trackLengthValue + ac.getCarState(step, acsys.CS.LapCount) * trackLengthValue) - (lapProgressValue * trackLengthValue + lapValue * trackLengthValue))
						timeToCar = max(0.0, distanceToCar / max(10, ac.getCarState(0, acsys.CS.SpeedMS)))
						ac.setFontColor(secondLabel, 1, 0.17, 0, 1)
						ac.setText(secondLabel, "+{:.1f}".format(timeToCar))
						if timeToCar >= 60:
							ac.setText(secondLabel, ">1 min")
						'''
						ac.setText(secondLabel, "{:.0f}m".format(distanceToCar))
						if distanceToCar > 1000:
							ac.setText(secondLabel, "{:.1f}km".format(distanceToCar / 1000))
						if distanceToCar > trackLengthValue:
							ac.setText(secondLabel, ">1 lap")
						'''
						break
			else:
				for step in range(1, totalCarsValue):
					if ac.getCarLeaderboardPosition(step) == positionBoardValue - 1:
						timeToCar = (ac.getCarState(0, acsys.CS.BestLap) - ac.getCarState(step, acsys.CS.BestLap)) / 1000
						if timeToCar:
							ac.setFontColor(secondLabel, 1, 0.17, 0, 1)
							ac.setText(secondLabel, "{:+.2f}".format(timeToCar))
							if abs(timeToCar) >= 60:
								ac.setText(secondLabel, ">1 min")
						break
					
		elif spinnerButton2 == 3 and not timerTrigger2:
			ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)
			ac.setText(secondLabel, "-.--")
			if sessionTypeValue == 2:
				for step in range(1, totalCarsValue):
					if ac.getCarRealTimeLeaderboardPosition(step) == positionValue + 1:
						distanceToCar = max(0, (lapProgressValue * trackLengthValue + lapValue * trackLengthValue) - (ac.getCarState(step, acsys.CS.NormalizedSplinePosition) * trackLengthValue + ac.getCarState(step, acsys.CS.LapCount) * trackLengthValue))
						timeToCar = max(0.0, distanceToCar / max(10, ac.getCarState(step, acsys.CS.SpeedMS)))
						ac.setFontColor(secondLabel, 0.17, 1, 0, 1)
						ac.setText(secondLabel, "-{:.1f}".format(timeToCar))
						if timeToCar >= 60:
							ac.setText(secondLabel, ">1 min")
						'''
						ac.setText(secondLabel, "{:.0f}m".format(distanceToCar))
						if distanceToCar > 1000:
							ac.setText(secondLabel, "{:.1f}km".format(distanceToCar / 1000))
						if distanceToCar > trackLengthValue:
							ac.setText(secondLabel, ">1 lap")
						'''
						break
			else:
				for step in range(1, totalCarsValue):
					if ac.getCarLeaderboardPosition(step) == positionBoardValue + 1:
						timeToCar = (ac.getCarState(0, acsys.CS.BestLap) - ac.getCarState(step, acsys.CS.BestLap)) / 1000
						if timeToCar:
							ac.setFontColor(secondLabel, 0.17, 1, 0, 1)
							ac.setText(secondLabel, "{:+.2f}".format(timeToCar))
							if abs(timeToCar) >= 60:
								ac.setText(secondLabel, ">1 min")
						break
						
		elif not timerTrigger2:
			ac.setText(secondLabel, "-.--")
			ac.setFontColor(secondLabel, 0.86, 0.86, 0.86, 1)

		#Position
		if spinnerButton3 == 0 and not timerTrigger3:
			if sessionTypeValue == 3:
				ac.setText(thirdLabel, "--/--")
			elif sessionTypeValue == 2:
				if serverIPValue:
					ac.setText(thirdLabel, "{}/{}".format(positionValue + 1, occupiedSlotsValue))
				else:
					ac.setText(thirdLabel, "{}/{}".format(positionValue + 1, totalCarsValue))
			else:
				if serverIPValue:
					ac.setText(thirdLabel, "{}/{}".format(positionBoardValue, occupiedSlotsValue))
				else:
					ac.setText(thirdLabel, "{}/{}".format(positionBoardValue, totalCarsValue))
			ac.setFontColor(thirdLabel, 0.86, 0.86, 0.86, 1)
		
		#Lap
		if spinnerButton3 == 1 and not timerTrigger3:
			if totalLapsValue:
				if lapValue == totalLapsValue:
					ac.setText(thirdLabel, "{}/{}".format(totalLapsValue, totalLapsValue))
				elif lapValue < totalLapsValue:
					ac.setText(thirdLabel, "{}/{}".format(lapValue + 1, totalLapsValue))
			else:
				ac.setText(thirdLabel, "{}/--".format(lapValue + 1))
			ac.setFontColor(thirdLabel, 0.86, 0.86, 0.86, 1)
			
		#Time
		if spinnerButton3 == 2 and not timerTrigger3:
			ac.setFontColor(thirdLabel, 0.86, 0.86, 0.86, 1)
			if sessionTimeValue < 300:
				ac.setFontColor(thirdLabel, 1, 0.51, 0, 1)
			if sessionTimeValue <= 0:
				ac.setFontColor(thirdLabel, 1, 0.17, 0, 1)
			if sessionTimeValue > 0 and sessionTypeValue == 2 and currentLapValue == 0 and lapValue == 0:
				ac.setText(thirdLabel, "WAIT")
				ac.setFontColor(thirdLabel, 1, 0.51, 0, 1)
			elif sessionTimeValue > 0:
				ac.setText(thirdLabel, "{:02.0f}:{:02.0f}".format(sessionTimeValue // 60, sessionTimeValue % 60))
			else:
				ac.setText(thirdLabel, "00:00")
		
		#Fuel amount
		if spinnerButton4 == 0 and not timerTrigger4:
			ac.setText(fourthLabel, "{:.1f}".format(fuelAmountValue))
			ac.setFontColor(fourthLabel, 0.86, 0.86, 0.86, 1)
		
		#Fuel per lap
		if spinnerButton4 == 1 and not timerTrigger4:		
			ac.setText(fourthLabel, "{:.2f}".format(fuelPerLapValue))
			ac.setFontColor(fourthLabel, 0.86, 0.86, 0.86, 1)
		
		#Fuel for laps
		if spinnerButton4 == 2 and not timerTrigger4:
			if fuelPerLapValue:
				ac.setText(fourthLabel, "{:.1f}".format(fuelAmountValue / fuelPerLapValue))
			else:
				ac.setText(fourthLabel, "--.-")
			ac.setFontColor(fourthLabel, 0.86, 0.86, 0.86, 1)
			
		#Fuel needed and fuel short
		if lapValue > 0 and sessionTypeValue == 2 and not raceIsTimed and not timerTrigger4:
			fuelNeededValue = (totalLapsValue - lapValue - lapProgressValue) * fuelPerLapValue
			if fuelAmountValue < fuelNeededValue and spinnerButton4 == 3:
				ac.setFontColor(fourthLabel, 1, 0.17, 0, 1)
				ac.setText(fourthLabel, "{:.1f}".format(fuelNeededValue))
			elif fuelAmountValue < fuelNeededValue and spinnerButton4 == 4:
				ac.setFontColor(fourthLabel, 1, 0.17, 0, 1)
				ac.setText(fourthLabel, "{:.1f}".format(fuelNeededValue - fuelAmountValue))
			elif spinnerButton4 == 3:
				ac.setFontColor(fourthLabel, 0.86, 0.86, 0.86, 1)
				ac.setText(fourthLabel, "{:.1f}".format(fuelNeededValue))
			elif spinnerButton4 == 4:
				ac.setFontColor(fourthLabel, 0.86, 0.86, 0.86, 1)
				ac.setText(fourthLabel, "--.-")
		elif (spinnerButton4 == 3 or spinnerButton4 == 4) and not timerTrigger4:
			ac.setFontColor(fourthLabel, 0.86, 0.86, 0.86, 1)
			ac.setText(fourthLabel, "--.-")
			
		#Display tyre section
		if not timerTrigger5 and not isDominantActive:
			ac.setVisible(fifthLabel, 0)
			ac.setVisible(tyreLabelFL, 1)
			ac.setVisible(tyreLabelFR, 1)
			ac.setVisible(tyreLabelRL, 1)
			ac.setVisible(tyreLabelRR, 1)
			
			#Wear
			if spinnerButton5 == 0:
				ac.setText(tyreLabelFL, "{:.0f}".format(max(100 - (100 - tyreWearValue[0]) * (tyreWearScale + tyreWearScale * 0.041), 0)))
				tyreWearHelper = min(0.83, (100 - tyreWearValue[0]) / 4.8)
				ac.setFontColor(tyreLabelFL, 0.17 + min(0.83, tyreWearHelper * 2), 1 - tyreWearHelper, 0, 1)
				
				ac.setText(tyreLabelFR, "{:.0f}".format(max(100 - (100 - tyreWearValue[1]) * (tyreWearScale + tyreWearScale * 0.041), 0)))
				tyreWearHelper = min(0.83, (100 - tyreWearValue[1]) / 4.8)
				ac.setFontColor(tyreLabelFR, 0.17 + min(0.83, tyreWearHelper * 2), 1 - tyreWearHelper, 0, 1)
				
				ac.setText(tyreLabelRL, "{:.0f}".format(max(100 - (100 - tyreWearValue[2]) * (tyreWearScale + tyreWearScale * 0.041), 0)))
				tyreWearHelper = min(0.83, (100 - tyreWearValue[2]) / 4.8)
				ac.setFontColor(tyreLabelRL, 0.17 + min(0.83, tyreWearHelper * 2), 1 - tyreWearHelper, 0, 1)
				
				ac.setText(tyreLabelRR, "{:.0f}".format(max(100 - (100 - tyreWearValue[3]) * (tyreWearScale + tyreWearScale * 0.041), 0)))
				tyreWearHelper = min(0.83, (100 - tyreWearValue[3]) / 4.8)
				ac.setFontColor(tyreLabelRR, 0.17 + min(0.83, tyreWearHelper * 2), 1 - tyreWearHelper, 0, 1)
				
			tyrePracticalTemperatureValue[0] = 0.25 * ((tyreTemperatureValueI[0] + tyreTemperatureValueM[0] + tyreTemperatureValueO[0]) / 3) + 0.75 * tyreTemperatureValue[0]
			tyrePracticalTemperatureValue[1] = 0.25 * ((tyreTemperatureValueI[1] + tyreTemperatureValueM[1] + tyreTemperatureValueO[1]) / 3) + 0.75 * tyreTemperatureValue[1]
			tyrePracticalTemperatureValue[2] = 0.25 * ((tyreTemperatureValueI[2] + tyreTemperatureValueM[2] + tyreTemperatureValueO[2]) / 3) + 0.75 * tyreTemperatureValue[2]
			tyrePracticalTemperatureValue[3] = 0.25 * ((tyreTemperatureValueI[3] + tyreTemperatureValueM[3] + tyreTemperatureValueO[3]) / 3) + 0.75 * tyreTemperatureValue[3]
			
			#Temperature
			if spinnerButton5 == 1:
				ac.setText(tyreLabelFL, "{:.0f}".format(tyrePracticalTemperatureValue[0]))
				if minimumOptimalTemperature and maximumOptimalTemperature:
					if int(round(tyrePracticalTemperatureValue[0])) >= minimumOptimalTemperature and int(round(tyrePracticalTemperatureValue[0])) <= maximumOptimalTemperature:
						ac.setFontColor(tyreLabelFL, 0.17, 1, 0, 1)
					elif int(round(tyrePracticalTemperatureValue[0])) < minimumOptimalTemperature:
						idealTemperatureDifference = min(temperatureTransitionRange, minimumOptimalTemperature - tyrePracticalTemperatureValue[0]) / temperatureTransitionRange
						ac.setFontColor(tyreLabelFL, max(0, 0.17 - idealTemperatureDifference / 5.88), max(0.51, 1 - idealTemperatureDifference / 1.96), min(1, 0 + idealTemperatureDifference), 1)
					elif int(round(tyrePracticalTemperatureValue[0])) > maximumOptimalTemperature:
						idealTemperatureDifference = min(temperatureTransitionRange, tyrePracticalTemperatureValue[0] - maximumOptimalTemperature) / temperatureTransitionRange
						ac.setFontColor(tyreLabelFL, min(1, 0.17 + idealTemperatureDifference / 0.83), max(0.17, 1 - idealTemperatureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelFL, 0.86, 0.86, 0.86, 1)
				
				ac.setText(tyreLabelFR, "{:.0f}".format(tyrePracticalTemperatureValue[1]))
				if minimumOptimalTemperature and maximumOptimalTemperature:
					if int(round(tyrePracticalTemperatureValue[1])) >= minimumOptimalTemperature and int(round(tyrePracticalTemperatureValue[1])) <= maximumOptimalTemperature:
						ac.setFontColor(tyreLabelFR, 0.17, 1, 0, 1)
					elif int(round(tyrePracticalTemperatureValue[1])) < minimumOptimalTemperature:
						idealTemperatureDifference = min(temperatureTransitionRange, minimumOptimalTemperature - tyrePracticalTemperatureValue[1]) / temperatureTransitionRange
						ac.setFontColor(tyreLabelFR, max(0, 0.17 - idealTemperatureDifference / 5.88), max(0.51, 1 - idealTemperatureDifference / 1.96), min(1, 0 + idealTemperatureDifference), 1)
					elif int(round(tyrePracticalTemperatureValue[1])) > maximumOptimalTemperature:
						idealTemperatureDifference = min(temperatureTransitionRange, tyrePracticalTemperatureValue[1] - maximumOptimalTemperature) / temperatureTransitionRange
						ac.setFontColor(tyreLabelFR, min(1, 0.17 + idealTemperatureDifference / 0.83), max(0.17, 1 - idealTemperatureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelFR, 0.86, 0.86, 0.86, 1)
				
				ac.setText(tyreLabelRL, "{:.0f}".format(tyrePracticalTemperatureValue[2]))
				if minimumOptimalTemperature and maximumOptimalTemperature:
					if int(round(tyrePracticalTemperatureValue[2])) >= minimumOptimalTemperature and int(round(tyrePracticalTemperatureValue[2])) <= maximumOptimalTemperature:
						ac.setFontColor(tyreLabelRL, 0.17, 1, 0, 1)
					elif int(round(tyrePracticalTemperatureValue[2])) < minimumOptimalTemperature:
						idealTemperatureDifference = min(temperatureTransitionRange, minimumOptimalTemperature - tyrePracticalTemperatureValue[2]) / temperatureTransitionRange
						ac.setFontColor(tyreLabelRL, max(0, 0.17 - idealTemperatureDifference / 5.88), max(0.51, 1 - idealTemperatureDifference / 1.96), min(1, 0 + idealTemperatureDifference), 1)
					elif int(round(tyrePracticalTemperatureValue[2])) > maximumOptimalTemperature:
						idealTemperatureDifference = min(temperatureTransitionRange, tyrePracticalTemperatureValue[2] - maximumOptimalTemperature) / temperatureTransitionRange
						ac.setFontColor(tyreLabelRL, min(1, 0.17 + idealTemperatureDifference / 0.83), max(0.17, 1 - idealTemperatureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelRL, 0.86, 0.86, 0.86, 1)
				
				ac.setText(tyreLabelRR, "{:.0f}".format(tyrePracticalTemperatureValue[3]))
				if minimumOptimalTemperature and maximumOptimalTemperature:
					if int(round(tyrePracticalTemperatureValue[3])) >= minimumOptimalTemperature and int(round(tyrePracticalTemperatureValue[3])) <= maximumOptimalTemperature:
						ac.setFontColor(tyreLabelRR, 0.17, 1, 0, 1)
					elif int(round(tyrePracticalTemperatureValue[3])) < minimumOptimalTemperature:
						idealTemperatureDifference = min(temperatureTransitionRange, minimumOptimalTemperature - tyrePracticalTemperatureValue[3]) / temperatureTransitionRange
						ac.setFontColor(tyreLabelRR, max(0, 0.17 - idealTemperatureDifference / 5.88), max(0.51, 1 - idealTemperatureDifference / 1.96), min(1, 0 + idealTemperatureDifference), 1)
					elif int(round(tyrePracticalTemperatureValue[3])) > maximumOptimalTemperature:
						idealTemperatureDifference = min(temperatureTransitionRange, tyrePracticalTemperatureValue[3] - maximumOptimalTemperature) / temperatureTransitionRange
						ac.setFontColor(tyreLabelRR, min(1, 0.17 + idealTemperatureDifference / 0.83), max(0.17, 1 - idealTemperatureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelRR, 0.86, 0.86, 0.86, 1)
			
			#Pressure
			if spinnerButton5 == 2:
				if showPressureAsDelta and idealPressureFront:
					ac.setText(tyreLabelFL, "{:+.1f}".format(idealPressureFront - tyrePressureValue[0]))
				else:
					ac.setText(tyreLabelFL, "{:.0f}".format(tyrePressureValue[0]))
				if idealPressureFront and idealPressureRear:
					if idealPressureFront == int(round(tyrePressureValue[0])):
						ac.setFontColor(tyreLabelFL, 0.17, 1, 0, 1)
					elif int(round(tyrePressureValue[0])) < idealPressureFront:
						idealPressureDifference = min(pressureTransitionRange, idealPressureFront - tyrePressureValue[0] - 0.5) / pressureTransitionRange
						ac.setFontColor(tyreLabelFL, max(0, 0.17 - idealPressureDifference / 5.88), max(0.51, 1 - idealPressureDifference / 1.96), min(1, 0 + idealPressureDifference), 1)
					elif int(round(tyrePressureValue[0])) > idealPressureFront:
						idealPressureDifference = min(pressureTransitionRange, tyrePressureValue[0] - 0.5 - idealPressureFront) / pressureTransitionRange
						ac.setFontColor(tyreLabelFL, min(1, 0.17 + idealPressureDifference / 0.83), max(0.17, 1 - idealPressureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelFL, 0.86, 0.86, 0.86, 1)
				
				if showPressureAsDelta and idealPressureFront:
					ac.setText(tyreLabelFR, "{:+.1f}".format(idealPressureFront - tyrePressureValue[1]))
				else:
					ac.setText(tyreLabelFR, "{:.0f}".format(tyrePressureValue[1]))
				if idealPressureFront and idealPressureRear:
					if idealPressureFront == int(round(tyrePressureValue[1])):
						ac.setFontColor(tyreLabelFR, 0.17, 1, 0, 1)
					elif int(round(tyrePressureValue[1])) < idealPressureFront:
						idealPressureDifference = min(pressureTransitionRange, idealPressureFront - tyrePressureValue[1] - 0.5) / pressureTransitionRange
						ac.setFontColor(tyreLabelFR, max(0, 0.17 - idealPressureDifference / 5.88), max(0.51, 1 - idealPressureDifference / 1.96), min(1, 0 + idealPressureDifference), 1)
					elif int(round(tyrePressureValue[1])) > idealPressureFront:
						idealPressureDifference = min(pressureTransitionRange, tyrePressureValue[1] - 0.5 - idealPressureFront) / pressureTransitionRange
						ac.setFontColor(tyreLabelFR, min(1, 0.17 + idealPressureDifference / 0.83), max(0.17, 1 - idealPressureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelFR, 0.86, 0.86, 0.86, 1)
				
				if showPressureAsDelta and idealPressureFront:
					ac.setText(tyreLabelRL, "{:+.1f}".format(idealPressureRear - tyrePressureValue[2]))
				else:
					ac.setText(tyreLabelRL, "{:.0f}".format(tyrePressureValue[2]))
				if idealPressureFront and idealPressureRear:
					if idealPressureRear == int(round(tyrePressureValue[2])):
						ac.setFontColor(tyreLabelRL, 0.17, 1, 0, 1)
					elif int(round(tyrePressureValue[2])) < idealPressureRear:
						idealPressureDifference = min(pressureTransitionRange, idealPressureRear - tyrePressureValue[2] - 0.5) / pressureTransitionRange
						ac.setFontColor(tyreLabelRL, max(0, 0.17 - idealPressureDifference / 5.88), max(0.51, 1 - idealPressureDifference / 1.96), min(1, 0 + idealPressureDifference), 1)
					elif int(round(tyrePressureValue[2])) > idealPressureRear:
						idealPressureDifference = min(pressureTransitionRange, tyrePressureValue[2] - 0.5 - idealPressureRear) / pressureTransitionRange
						ac.setFontColor(tyreLabelRL, min(1, 0.17 + idealPressureDifference / 0.83), max(0.17, 1 - idealPressureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelRL, 0.86, 0.86, 0.86, 1)
				
				if showPressureAsDelta and idealPressureFront:
					ac.setText(tyreLabelRR, "{:+.1f}".format(idealPressureRear - tyrePressureValue [3]))
				else:
					ac.setText(tyreLabelRR, "{:.0f}".format(tyrePressureValue[3]))
				if idealPressureFront and idealPressureRear:
					if idealPressureRear == int(round(tyrePressureValue[3])):
						ac.setFontColor(tyreLabelRR, 0.17, 1, 0, 1)
					elif int(round(tyrePressureValue[3])) < idealPressureRear:
						idealPressureDifference = min(pressureTransitionRange, idealPressureRear - tyrePressureValue[3] - 0.5) / pressureTransitionRange
						ac.setFontColor(tyreLabelRR, max(0, 0.17 - idealPressureDifference / 5.88), max(0.51, 1 - idealPressureDifference / 1.96), min(1, 0 + idealPressureDifference), 1)
					elif int(round(tyrePressureValue[3])) > idealPressureRear:
						idealPressureDifference = min(pressureTransitionRange, tyrePressureValue[3] - 0.5 - idealPressureRear) / pressureTransitionRange
						ac.setFontColor(tyreLabelRR, min(1, 0.17 + idealPressureDifference / 0.83), max(0.17, 1 - idealPressureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelRR, 0.86, 0.86, 0.86, 1)
			
			#Brakes
			if spinnerButton5 == 3 or (showBrakeTemperaturesWhileBraking and brakeValue and brakeTemperatureValue[0] > 50):
				ac.setText(tyreLabelFL, "{:.0f}".format(brakeTemperatureValue[0]))
				if minimumOptimalBrakeTemperatureFront and maximumOptimalBrakeTemperatureFront:
					if int(round(brakeTemperatureValue[0])) >= minimumOptimalBrakeTemperatureFront and int(round(brakeTemperatureValue[0])) <= maximumOptimalBrakeTemperatureFront:
						ac.setFontColor(tyreLabelFL, 0.17, 1, 0, 1)
					elif int(round(brakeTemperatureValue[0])) < minimumOptimalBrakeTemperatureFront:
						idealBrakeTemperatureDifference = min(brakeTransitionRange, minimumOptimalBrakeTemperatureFront - brakeTemperatureValue[0]) / brakeTransitionRange
						ac.setFontColor(tyreLabelFL, max(0, 0.17 - idealBrakeTemperatureDifference / 5.88), max(0.51, 1 - idealBrakeTemperatureDifference / 1.96), min(1, 0 + idealBrakeTemperatureDifference), 1)
					elif int(round(brakeTemperatureValue[0])) > maximumOptimalBrakeTemperatureFront:
						idealBrakeTemperatureDifference = min(brakeTransitionRange, brakeTemperatureValue[0] - maximumOptimalBrakeTemperatureFront) / brakeTransitionRange
						ac.setFontColor(tyreLabelFL, min(1, 0.17 + idealBrakeTemperatureDifference / 0.83), max(0.17, 1 - idealBrakeTemperatureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelFL, 0.86, 0.86, 0.86, 1)
				
				ac.setText(tyreLabelFR, "{:.0f}".format(brakeTemperatureValue[1]))
				if minimumOptimalBrakeTemperatureFront and maximumOptimalBrakeTemperatureFront:
					if int(round(brakeTemperatureValue[1])) >= minimumOptimalBrakeTemperatureFront and int(round(brakeTemperatureValue[1])) <= maximumOptimalBrakeTemperatureFront:
						ac.setFontColor(tyreLabelFR, 0.17, 1, 0, 1)
					elif int(round(brakeTemperatureValue[1])) < minimumOptimalBrakeTemperatureFront:
						idealBrakeTemperatureDifference = min(brakeTransitionRange, minimumOptimalBrakeTemperatureFront - brakeTemperatureValue[1]) / brakeTransitionRange
						ac.setFontColor(tyreLabelFR, max(0, 0.17 - idealBrakeTemperatureDifference / 5.88), max(0.51, 1 - idealBrakeTemperatureDifference / 1.96), min(1, 0 + idealBrakeTemperatureDifference), 1)
					elif int(round(brakeTemperatureValue[1])) > maximumOptimalBrakeTemperatureFront:
						idealBrakeTemperatureDifference = min(brakeTransitionRange, brakeTemperatureValue[1] - maximumOptimalBrakeTemperatureFront) / brakeTransitionRange
						ac.setFontColor(tyreLabelFR, min(1, 0.17 + idealBrakeTemperatureDifference / 0.83), max(0.17, 1 - idealBrakeTemperatureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelFR, 0.86, 0.86, 0.86, 1)
				
				ac.setText(tyreLabelRL, "{:.0f}".format(brakeTemperatureValue[2]))
				if minimumOptimalBrakeTemperatureRear and maximumOptimalBrakeTemperatureRear:
					if int(round(brakeTemperatureValue[2])) >= minimumOptimalBrakeTemperatureRear and int(round(brakeTemperatureValue[2])) <= maximumOptimalBrakeTemperatureRear:
						ac.setFontColor(tyreLabelRL, 0.17, 1, 0, 1)
					elif int(round(brakeTemperatureValue[2])) < minimumOptimalBrakeTemperatureRear:
						idealBrakeTemperatureDifference = min(brakeTransitionRange, minimumOptimalBrakeTemperatureRear - brakeTemperatureValue[2]) / brakeTransitionRange
						ac.setFontColor(tyreLabelRL, max(0, 0.17 - idealBrakeTemperatureDifference / 5.88), max(0.51, 1 - idealBrakeTemperatureDifference / 1.96), min(1, 0 + idealBrakeTemperatureDifference), 1)
					elif int(round(brakeTemperatureValue[2])) > maximumOptimalBrakeTemperatureRear:
						idealBrakeTemperatureDifference = min(brakeTransitionRange, brakeTemperatureValue[2] - maximumOptimalBrakeTemperatureRear) / brakeTransitionRange
						ac.setFontColor(tyreLabelRL, min(1, 0.17 + idealBrakeTemperatureDifference / 0.83), max(0.17, 1 - idealBrakeTemperatureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelRL, 0.86, 0.86, 0.86, 1)
				
				ac.setText(tyreLabelRR, "{:.0f}".format(brakeTemperatureValue[3]))
				if minimumOptimalBrakeTemperatureRear and maximumOptimalBrakeTemperatureRear:
					if int(round(brakeTemperatureValue[3])) >= minimumOptimalBrakeTemperatureRear and int(round(brakeTemperatureValue[3])) <= maximumOptimalBrakeTemperatureRear:
						ac.setFontColor(tyreLabelRR, 0.17, 1, 0, 1)
					elif int(round(brakeTemperatureValue[3])) < minimumOptimalBrakeTemperatureRear:
						idealBrakeTemperatureDifference = min(brakeTransitionRange, minimumOptimalBrakeTemperatureRear - brakeTemperatureValue[3]) / brakeTransitionRange
						ac.setFontColor(tyreLabelRR, max(0, 0.17 - idealBrakeTemperatureDifference / 5.88), max(0.51, 1 - idealBrakeTemperatureDifference / 1.96), min(1, 0 + idealBrakeTemperatureDifference), 1)
					elif int(round(brakeTemperatureValue[3])) > maximumOptimalBrakeTemperatureRear:
						idealBrakeTemperatureDifference = min(brakeTransitionRange, brakeTemperatureValue[3] - maximumOptimalBrakeTemperatureRear) / brakeTransitionRange
						ac.setFontColor(tyreLabelRR, min(1, 0.17 + idealBrakeTemperatureDifference / 0.83), max(0.17, 1 - idealBrakeTemperatureDifference / 0.83), 0, 1)
				else:
					ac.setFontColor(tyreLabelRR, 0.86, 0.86, 0.86, 1)
			
			elif spinnerButton5 == 4:
				ac.setVisible(tyreLabelFL, 0)
				ac.setVisible(tyreLabelFR, 0)
				ac.setVisible(tyreLabelRL, 0)
				ac.setVisible(tyreLabelRR, 0)
		
		#START DOMINANT EVENTS#
		
		#Replay
		if statusValue == 1:
			previousStatusValue = 1
			dominantEvent()
			ac.setVisible(rpmBorder, 0)
			ac.setFontColor(dominantLabel, 0.86, 0.86, 0.86, 1)
			currentLapReplayValue = ac.getCarState(ac.getFocusedCar(), acsys.CS.LapTime)
			lastLapReplayValue = ac.getCarState(ac.getFocusedCar(), acsys.CS.LastLap)
			if currentLapReplayValue < 5000 and lastLapReplayValue:
				lastLapReplayValueSeconds = (lastLapReplayValue / 1000) % 60
				lastLapReplayValueMinutes = (lastLapReplayValue // 1000) // 60
				ac.setText(dominantLabel, "LAST LAP: {:.0f}:{:06.3f}".format(lastLapReplayValueMinutes, lastLapReplayValueSeconds)[:-1])
			else:
				currentLapReplayValueSeconds = (currentLapReplayValue / 1000) % 60
				currentLapReplayValueMinutes = (currentLapReplayValue // 1000) // 60
				ac.setText(dominantLabel, "CURRENT LAP: {:.0f}:{:06.3f}".format(currentLapReplayValueMinutes, currentLapReplayValueSeconds)[:-2])
				
		if statusValue != 1 and previousStatusValue:
			previousStatusValue = 0
			clearDominantEvent()
		
		#New personal best
		if notifyLapTimes and previousPersonalBestLapValue > bestLapValue and runOnce and not wasAlreadyDisplayed:
			runOnce = False
			dominantEvent()
			dominantTimer = 0
			wasAlreadyDisplayed = True
			ac.setFontColor(dominantLabel, 0.17, 1, 0, 1)
			ac.setText(dominantLabel, "NEW P. BEST: {:.0f}:{:06.3f}".format(bestLapValueMinutes, bestLapValueSeconds)[:-1])
		
		#New best
		if notifyLapTimes and previousBestLapValue > bestLapValue and runOnce and not wasAlreadyDisplayed:
			runOnce = False
			dominantEvent()
			dominantTimer = 0
			wasAlreadyDisplayed = True
			ac.setFontColor(dominantLabel, 1, 0.51, 0, 1)
			ac.setText(dominantLabel, "NEW BEST: {:.0f}:{:06.3f}".format(bestLapValueMinutes, bestLapValueSeconds)[:-1])
			
		#Session about to end
		if notifySessionEnd and (sessionTypeValue == 0 or sessionTypeValue == 1 or (sessionTypeValue == 2 and currentLapValue)):
			if sessionTimeValue == 300 and runOnce:
				runOnce = False
				dominantEvent()
				dominantTimer = 0
				ac.setFontColor(dominantLabel, 1, 0.51, 0, 1)
				ac.setText(dominantLabel, "SESSION ENDS IN 5 MINUTES")
			elif sessionTimeValue == 240 and runOnce:
				runOnce = False
				dominantEvent()
				dominantTimer = 0
				ac.setFontColor(dominantLabel, 1, 0.51, 0, 1)
				ac.setText(dominantLabel, "SESSION ENDS IN 4 MINUTES")
			elif sessionTimeValue == 180 and runOnce:
				runOnce = False
				dominantEvent()
				dominantTimer = 0
				ac.setFontColor(dominantLabel, 1, 0.51, 0, 1)
				ac.setText(dominantLabel, "SESSION ENDS IN 3 MINUTES")
			elif sessionTimeValue == 120 and runOnce:
				runOnce = False
				dominantEvent()
				dominantTimer = 0
				ac.setFontColor(dominantLabel, 1, 0.51, 0, 1)
				ac.setText(dominantLabel, "SESSION ENDS IN 2 MINUTES")
			elif sessionTimeValue == 60 and runOnce:
				runOnce = False
				dominantEvent()
				dominantTimer = 0
				ac.setFontColor(dominantLabel, 1, 0.51, 0, 1)
				ac.setText(dominantLabel, "SESSION ENDS IN 1 MINUTE")
			elif sessionTimeValue == 1 and runOnce:
				runOnce = False
				dominantEvent()
				dominantTimer = 0
				ac.setFontColor(dominantLabel, 1, 0.17, 0, 1)
				ac.setText(dominantLabel, "SESSION HAS ENDED")
				
		#Wheel not straight
		if notifyWheelOffCenter and abs(steerInputValue) > 20 and speedValueKPH < 1 and sessionTypeValue == 2 and not currentLapValue and statusValue != 1:
			runOnce = False
			dominantEvent()
			dominantTimer = 4.9
			ac.setFontColor(dominantLabel, 1, 0.17, 0, 1)
			ac.setText(dominantLabel, "WHEEL NOT STRAIGHT!")
		
		#Clear dominant events
		if dominantTimer > 5 and isDominantActive and statusValue != 1:
			runOnce = True
			clearDominantEvent()
			
		#END DOMINANT EVENTS#
		
	#Display/calculate once per second
	if timer3 > 1:
		timer3 = 0
		
		#Reset previous laps helper
		if currentLapValue > 4000 and (previousBestLapValue > 0 or previousPersonalBestLapValue > 0):
			previousBestLapValue = 0
			previousPersonalBestLapValue = 0
			
		#Timed practice check
		if not practiceIsTimed and sessionTypeValue == 0 and sessionTimeValue > 0:
			practiceIsTimed = 1
			
		#Section reset checks
		if not ((sessionTypeValue == 0 and practiceIsTimed) or sessionTypeValue == 1 or (sessionTypeValue == 2 and raceIsTimed)) and spinnerButton3 > 1:
			spinnerButton3 = 0
		
		if not (sessionTypeValue == 2 and not raceIsTimed) and spinnerButton4 > 2:
			spinnerButton4 = 0
			
		if spinnerButton5 == 3 and not showBrakeTemperatures:
			spinnerButton5 = 0
		
		#Car in pit check
		if carInPitlineValue:
			carWasInPit = 1
			
		#AI driver check
		if carDrivenByAIValue:
			carWasDrivenByAI = 1
			
		#Remember highest P2P activations
		if P2PActivationsValue > P2PActivationsMaxValue:
			P2PActivationsMaxValue = P2PActivationsValue
			
		#Set ideal tyre temperatures and pressures
		if previousTyreCompoundValue != tyreCompoundValue:
			previousTyreCompoundValue = tyreCompoundValue
			tyreCompoundShort = tyreCompoundValue[tyreCompoundValue.find("(")+1:tyreCompoundValue.find(")")]
			tyreCompoundCleaned = re.sub('\_+$', '', re.sub(r'[^\w]+', '_', tyreCompoundValue)).lower()
			
			if compounds.has_section(carValue + "_" + tyreCompoundCleaned):
				try:
					idealPressureFront = int(compounds.get(carValue + "_" + tyreCompoundCleaned, "IDEAL_PRESSURE_F"))
					idealPressureRear = int(compounds.get(carValue + "_" + tyreCompoundCleaned, "IDEAL_PRESSURE_R"))
					minimumOptimalTemperature = int(compounds.get(carValue + "_" + tyreCompoundCleaned, "MIN_OPTIMAL_TEMP"))
					maximumOptimalTemperature = int(compounds.get(carValue + "_" + tyreCompoundCleaned, "MAX_OPTIMAL_TEMP"))
					ac.setText(tyreInfoLabel, "Tyres: {}, {}psi/{}psi, {}°C-{}°C".format(tyreCompoundValue, idealPressureFront, idealPressureRear, minimumOptimalTemperature, maximumOptimalTemperature))
				except:
					ac.console("Sidekick: Error loading tyre data.")
			elif modCompounds.has_section(carValue + "_" + tyreCompoundCleaned):
				try:
					idealPressureFront = int(modCompounds.get(carValue + "_" + tyreCompoundCleaned, "IDEAL_PRESSURE_F"))
					idealPressureRear = int(modCompounds.get(carValue + "_" + tyreCompoundCleaned, "IDEAL_PRESSURE_R"))
					minimumOptimalTemperature = int(float(modCompounds.get(carValue + "_" + tyreCompoundCleaned, "MIN_OPTIMAL_TEMP")))
					maximumOptimalTemperature = int(float(modCompounds.get(carValue + "_" + tyreCompoundCleaned, "MAX_OPTIMAL_TEMP")))
					ac.setText(tyreInfoLabel, "Tyres: {}, {}psi/{}psi, {}°C-{}°C".format(tyreCompoundValue, idealPressureFront, idealPressureRear, minimumOptimalTemperature, maximumOptimalTemperature))
				except:
					ac.console("Sidekick: Error loading mod tyre data.")
			else:
				ac.setText(tyreInfoLabel, "Tyres: {}, no data found".format(tyreCompoundValue))
			if brakes.has_section(carValue):
				try:
					minimumOptimalBrakeTemperatureFront = int(brakes.get(carValue, "MIN_OPTIMAL_TEMP_F"))
					maximumOptimalBrakeTemperatureFront = int(brakes.get(carValue, "MAX_OPTIMAL_TEMP_F"))
					minimumOptimalBrakeTemperatureRear = int(brakes.get(carValue, "MIN_OPTIMAL_TEMP_R"))
					maximumOptimalBrakeTemperatureRear = int(brakes.get(carValue, "MAX_OPTIMAL_TEMP_R"))
					ac.setText(brakeInfoLabel, "Brakes: {}°C-{}°C (F), {}°C-{}°C (R)".format(minimumOptimalBrakeTemperatureFront, maximumOptimalBrakeTemperatureFront, minimumOptimalBrakeTemperatureRear, maximumOptimalBrakeTemperatureRear))
				except:
					ac.console("Sidekick: Error loading brake data.")
			elif modBrakes.has_section(carValue):
				try:
					minimumOptimalBrakeTemperatureFront = int(modBrakes.get(carValue, "MIN_OPTIMAL_TEMP_F"))
					maximumOptimalBrakeTemperatureFront = int(modBrakes.get(carValue, "MAX_OPTIMAL_TEMP_F"))
					minimumOptimalBrakeTemperatureRear = int(modBrakes.get(carValue, "MIN_OPTIMAL_TEMP_R"))
					maximumOptimalBrakeTemperatureRear = int(modBrakes.get(carValue, "MAX_OPTIMAL_TEMP_R"))
					ac.setText(brakeInfoLabel, "Brakes: {}°C-{}°C (F), {}°C-{}°C (R)".format(minimumOptimalBrakeTemperatureFront, maximumOptimalBrakeTemperatureFront, minimumOptimalBrakeTemperatureRear, maximumOptimalBrakeTemperatureRear))
				except:
					ac.console("Sidekick: Error loading mod brake data.")
			else:
				ac.setText(brakeInfoLabel, "Brakes: no data found")
		
		#Update odometer labels
		if speedInKPH:
			ac.setText(odometerInfoLabel, "Total distance in this car: {:.1f}km".format(odometer))
			ac.setText(tripOdometerInfoLabel, "Distance in this session: {:.2f}km".format(tripOdometer))
		else:
			ac.setText(odometerInfoLabel, "Total distance in this car: {:.1f}mi".format(odometer * 0.62))
			ac.setText(tripOdometerInfoLabel, "Distance in this session: {:.2f}mi".format(tripOdometer * 0.62))
			
	#Display/calculate on lap start
	if currentLapValue > 500 and currentLapValue < 1000:
		lapValidityValue = 0
		
		carWasInPit = 0
		carWasDrivenByAI = 0
		
		fuelStartValue = fuelAmountValue
		
		timeList = []
		posList = []
		prevt = 0
		prevt2 = 0
		ttb = 0
		ttpb = 0
	
	#Display/calculate on lap finish
	if previousLapValue < lapValue:
		previousLapValue = lapValue
		
		#Last lap
		if statusValue != 1:
			lastLapValue = info.graphics.iLastTime
			lastLapValueSeconds = (lastLapValue / 1000) % 60
			lastLapValueMinutes = (lastLapValue // 1000) // 60
			if lapValidityValue:
				lapWasInvalid = True
			else:
				lapWasInvalid = False
		
		#Best lap
		if not lapValidityValue and statusValue != 1:
			previousBestLapValue = bestLapValue
			if not bestLapValue:
				bestLapValue = lastLapValue
			if lastLapValue < bestLapValue:
				bestLapValue = lastLapValue
			bestLapValueSeconds = (bestLapValue / 1000) % 60
			bestLapValueMinutes = (bestLapValue // 1000) // 60
			if bestLapValue < previousBestLapValue or previousBestLapValue == 0:
				bestPosList = list(posList)
				bestTimeList = list(timeList)
		
		#Personal best lap
		if (bestLapValue < personalBestLapValue or personalBestLapValue == 0) and bestLapValue and statusValue != 1:
			previousPersonalBestLapValue = personalBestLapValue
			personalBestLapValue = bestLapValue
			personalBestLapValueSeconds = (personalBestLapValue / 1000) % 60
			personalBestLapValueMinutes = (personalBestLapValue // 1000) // 60
			personalBestPosList = list(posList)
			personalBestTimeList = list(timeList)
			
		#Fuel per lap
		if fuelAmountValue < fuelStartValue and not carWasInPit:
			fuelEndValue = fuelAmountValue
			relevantLapsNumber += 1
			fuelSpentValue += (fuelStartValue - fuelEndValue) + (fuelStartValue - fuelEndValue) * (540 / lastLapValue)
			fuelPerLapValue = fuelSpentValue / relevantLapsNumber
		
		#Reset helpers
		ac.setVisible(deltaGainLabel, 0)
		
		lapValidityValue = 0
		
		outLap = 0	#Just in case the first condition misfired
		
		wasAlreadyDisplayed = False

	#Auto looping
	if autoLooping and autoLoopingTimer > autoLoopingTime / 1000:
		autoLoopingTimer = 0
		
		if loopFirstSection:
			firstButtonClicked()
		if loopSecondSection:
			secondButtonClicked()
		if loopThirdSection:
			thirdButtonClicked()
		if loopFourthSection:
			fourthButtonClicked()
		if loopFifthSection and (not showBrakeTemperaturesWhileBraking or (not brakeValue or brakeTemperatureValue[0] < 50)):
			fifthButtonClicked()
	
		
#GL Drawing		
def onFormRender(deltaT):

	#RPM
	if showRpmBar and statusValue !=1:
		ac.glColor4f(0.86, 0.86, 0.86, 0.3)
		ac.glQuad(67 * scale, 5 * scale, 238 * scale, 2 * scale)
		ac.glColor4f(0.86, 0.86, 0.86, 1)
		ac.glQuad(67 * scale, 5 * scale, min(1, rpmPercentageValue) * 238 * scale, 2 * scale)
		if showAdditionalBarInfo and turboMaxValue:
			ac.glColor4f(0, 0, 0, 0.2)
			ac.glQuad(min(302 * scale, 66 * scale + turboPercentageValue * 236 * scale), 2 * scale, 4 * scale, 8 * scale)
			ac.glColor4f(1, 0.51, 0, 1)
			ac.glQuad(min(303 * scale, 67 * scale + turboPercentageValue * 236 * scale), 3 * scale, 2 * scale, 6 * scale)
			
	#KERS
	if showKersBar and (hasERS or hasKERS) and statusValue != 1:
		ac.glColor4f(0.86, 0.86, 0.86, 0.3)
		ac.glQuad(67 * scale, 39 * scale, 238 * scale, 2 * scale)
		if ersIsChargingValue:
			ac.glColor4f(0.17, 1, 0, 1)
		else:
			ac.glColor4f(0.17, 1, 1, 1)
		ac.glQuad(67 * scale, 39 * scale, kersChargeValue * 238 * scale, 2 * scale)
		if showAdditionalBarInfo:
			ac.glColor4f(0, 0, 0, 0.2)
			ac.glQuad(66 * scale + kersInputValue * 236 * scale, 36 * scale, 4 * scale, 8 * scale)
			ac.glColor4f(0.86, 0.86, 0.86, 1)
			ac.glQuad(67 * scale + kersInputValue * 236 * scale, 37 * scale, 2 * scale, 6 * scale)
			if ersMaxJValue:
				ac.glColor4f(0, 0, 0, 0.2)
				ac.glQuad(66 * scale + (1 - (ersCurrentKJValue / (ersMaxJValue / 1000))) * 236 * scale, 36 * scale, 4 * scale, 8 * scale)
				ac.glColor4f(1, 0.17, 0, 1)
				ac.glQuad(67 * scale + (1 - (ersCurrentKJValue / (ersMaxJValue / 1000))) * 236 * scale, 37 * scale, 2 * scale, 6 * scale)
				
	#P2P
	if showKersBar and P2PStatusValue and statusValue != 1:
		ac.glColor4f(0.86, 0.86, 0.86, 0.3)
		ac.glQuad(67 * scale, 39 * scale, 238 * scale, 2 * scale)
		for step in range(0, P2PActivationsValue):
			if P2PStatusValue == 1:
				ac.glColor4f(1, 0.17, 0, 1)
			if P2PStatusValue == 2:
				ac.glColor4f(0.17, 1, 0, 1)
			if P2PStatusValue == 3:
				ac.glColor4f(0.17, 1, 1, 1)
			ac.glQuad((67 + step * 238 / P2PActivationsMaxValue) * scale, 39 * scale, (238 / P2PActivationsMaxValue - 1) * scale, 2 * scale)
			if P2PStatusValue == 3:
				if currentLapValueSeconds % 1 > 0.5:
					ac.glColor4f(0.17, 1, 1, 0.2)
				else:
					ac.glColor4f(0.17, 1, 1, 1)
				ac.glQuad((67 + (step + 1) * 238 / P2PActivationsMaxValue) * scale, 39 * scale, (238 / P2PActivationsMaxValue - 1) * scale, 2 * scale)
		if not P2PActivationsValue and P2PStatusValue == 3:
			if currentLapValueSeconds % 1 > 0.5:
				ac.glColor4f(0.17, 1, 1, 0.2)
			else:
				ac.glColor4f(0.17, 1, 1, 1)
			ac.glQuad(67 * scale, 39 * scale, (238 / P2PActivationsMaxValue - 1) * scale, 2 * scale)
				
	#Pedals
	if not showBrandInsteadOfPedals:
		ac.setVisible(brandIconLabel, 0)
		
		ac.glColor4f(0.86, 0.86, 0.86, 0.3)
		ac.glQuad(371 * scale, 8 * scale, 4 * scale, 30 * scale)
		ac.glQuad(379 * scale, 8 * scale, 4 * scale, 30 * scale)
		ac.glQuad(387 * scale, 8 * scale, 4 * scale, 30 * scale)
		ac.glQuad(395 * scale, 8 * scale, 4 * scale, 30 * scale)
		
		ac.glColor4f(0.17, 1, 1, 1)
		ac.glQuad(371 * scale, (clutchValue * 27 + 11) * scale, 4 * scale, ((1 - clutchValue) * 27) * scale)
		if clutchValue == 0:
			ac.glQuad(371 * scale, 8 * scale, 4 * scale, 2 * scale)
			
		ac.glColor4f(1, 0.17, 0, 1)
		ac.glQuad(379 * scale, ((1 - brakeValue) * 27 + 11) * scale, 4 * scale, (brakeValue * 27) * scale)
		if brakeValue == 1:
			ac.glQuad(379 * scale, 8 * scale, 4 * scale, 2 * scale)
		
		ac.glColor4f(0.17, 1, 0, 1)
		ac.glQuad(387 * scale, ((1 - throttleValue) * 27 + 11) * scale, 4 * scale, (throttleValue * 27) * scale)
		if throttleValue == 1:
			ac.glQuad(387 * scale, 8 * scale, 4 * scale, 2 * scale)
		
		if statusValue != 1:
			if ffbValue < 1:
				ac.glColor4f(0.86, 0.86, 0.86, 0.5)
				ac.glQuad(395 * scale, ((1 - ffbValue) * 30 + 8) * scale, 4 * scale, (ffbValue * 30) * scale)
			else:
				ac.glColor4f(1, 0.17, 0, 1)
				ac.glQuad(395 * scale, 8 * scale, 4 * scale, 30 * scale)
	
	else:
		ac.setVisible(brandIconLabel, 1)
	
#Do on AC shutdown
def acShutdown():
	global config, updateConfig, configPath
	global personalBestDir, configDir, gearRatiosDir
	global filePersonalBest, personalBestLapValue
	global filePersonalBestPosList, personalBestPosList
	global filePersonalBestTimeList, personalBestTimeList
	global fileSectionChoices, spinnerButton1, spinnerButton2, spinnerButton3, spinnerButton4, spinnerButton5
	global fileRatioList, ratioList
	global odometersDir, odometers, carValue, odometer

	spinnerButtons.clear()
	spinnerButtons.extend([spinnerButton1, spinnerButton2, spinnerButton3, spinnerButton4, spinnerButton5])
	
	#Save important stuff
	writeFile(filePersonalBest, personalBestLapValue, personalBestDir)
	writeFile(filePersonalBestPosList, personalBestPosList, personalBestDir)
	writeFile(filePersonalBestTimeList, personalBestTimeList, personalBestDir)
	writeFile(fileSectionChoices, spinnerButtons, configDir)
	writeFile(fileRatioList, ratioList, gearRatiosDir)
	
	#Update config if needed
	if updateConfig:
		with open(configPath, 'w') as fileConfig:
			config.write(fileConfig)
			
	#Update odometer
	odometers.set(carValue, "odometer", str(odometer))
	if not os.path.exists("apps/python/Sidekick/odometers/"):
		os.makedirs("apps/python/Sidekick/odometers/")
	with open(odometersPath, 'w') as fileOdometers:
		odometers.write(fileOdometers)

#Write file function
def writeFile(file, list, dir):

	if not os.path.exists(dir):
		os.makedirs(dir)

	f = open(file, "wb")
	pickle.dump(list, f)
	f.close()

#Load file function
def loadFile(file, var):

	try:
		if os.path.exists(file):
			f = open(file, "rb")
			var = pickle.load(f)
			f.close()
	except:
		ac.console("Sidekick: Error loading " + str(file))		
	return var
	
#Set dominant event
def dominantEvent():
	global isDominantActive, separatorsLabel, selectionIndicatorLabel, firstLabel, secondLabel, thirdLabel, fourthLabel, fifthLabel, tyreLabelFL, tyreLabelFR, tyreLabelRL, tyreLabelRR, deltaGainLabel, dominantLabel
	
	isDominantActive = True
	
	ac.setVisible(separatorsLabel, 0)
	ac.setVisible(selectionIndicatorLabel, 0)
	ac.setVisible(firstLabel, 0)
	ac.setVisible(secondLabel, 0)
	ac.setVisible(thirdLabel, 0)
	ac.setVisible(fourthLabel, 0)
	ac.setVisible(fifthLabel, 0)
	ac.setVisible(tyreLabelFL, 0)
	ac.setVisible(tyreLabelFR, 0)
	ac.setVisible(tyreLabelRL, 0)
	ac.setVisible(tyreLabelRR, 0)
	ac.setVisible(deltaGainLabel, 0)
	ac.setVisible(dominantLabel, 1)

#Clear dominant event
def clearDominantEvent():
	global isDominantActive, separatorsLabel, selectionIndicatorLabel, firstLabel, secondLabel, thirdLabel, fourthLabel, fifthLabel, tyreLabelFL, tyreLabelFR, tyreLabelRL, tyreLabelRR, deltaGainLabel, dominantLabel, ttb, ttpb
	
	isDominantActive = False
	
	ac.setVisible(separatorsLabel, 1)
	ac.setVisible(selectionIndicatorLabel, 1)
	ac.setVisible(firstLabel, 1)
	ac.setVisible(secondLabel, 1)
	ac.setVisible(thirdLabel, 1)
	ac.setVisible(fourthLabel, 1)
	ac.setVisible(fifthLabel, 1)
	ac.setVisible(dominantLabel, 0)
	ac.setText(dominantLabel, "")
	ac.setFontColor(dominantLabel, 0.86, 0.86, 0.86, 1)
	
	ttb = 0
	ttpb = 0

#Set up virtual button listeners
def firstButtonClicked(*args):
	global spinnerButton1, timerTrigger1, isSelector
	
	if not isSelector:
		spinnerButton1 += 1
	if spinnerButton1 > 3:
		spinnerButton1 = 0
	
	timerTrigger1 = 1
	
def secondButtonClicked(*args):
	global spinnerButton2, timerTrigger2, isSelector
	global deltaGainLabel
	global ttb, ttpb

	if not isSelector:
		spinnerButton2 += 1
	if spinnerButton2 > 3 or (spinnerButton2 > 1 and sessionTypeValue > 2):
		spinnerButton2 = 0
		
	if spinnerButton2 == 0:
		ttb = 0
		ac.setVisible(deltaGainLabel, 0)
	
	elif spinnerButton2 == 1:
		ttpb = 0
		ac.setVisible(deltaGainLabel, 0)
		
	elif spinnerButton2 > 1:
		ttb = 0
		ttpb = 0
		ac.setVisible(deltaGainLabel, 0)
		
	timerTrigger2 = 1
	
def thirdButtonClicked(*args):
	global spinnerButton3, timerTrigger3, isSelector
	
	if not isSelector:
		spinnerButton3 += 1
	if (not ((sessionTypeValue == 0 and practiceIsTimed) or sessionTypeValue == 1 or (sessionTypeValue == 2 and raceIsTimed)) and spinnerButton3 > 1) or spinnerButton3 > 2:
		spinnerButton3 = 0
	
	timerTrigger3 = 1
	
def fourthButtonClicked(*args):
	global spinnerButton4, timerTrigger4, isSelector
	
	if not isSelector:
		spinnerButton4 += 1
	if (not (sessionTypeValue == 2 and not raceIsTimed) and spinnerButton4 > 2) or spinnerButton4 > 4:
		spinnerButton4 = 0
		
	timerTrigger4 = 1
	
def fifthButtonClicked(*args):
	global spinnerButton5, timerTrigger5, isSelector, isDominantActive
	global fifthLabel, tyreLabelFL, tyreLabelFR, tyreLabelRL, tyreLabelRR
	
	if not isDominantActive:
		ac.setVisible(fifthLabel, 1)
	ac.setVisible(tyreLabelFL, 0)
	ac.setVisible(tyreLabelFR, 0)
	ac.setVisible(tyreLabelRL, 0)
	ac.setVisible(tyreLabelRR, 0)
	
	if not isSelector:
		if not showBrakeTemperatures and spinnerButton5 == 2:
			spinnerButton5 += 1
		spinnerButton5 += 1
	if spinnerButton5 > 3:
		spinnerButton5 = 0
		
	timerTrigger5 = 1

#Car data window
def carDataWindowActivated(*args):
	global carDataWindowVisibility
	
	carDataWindowVisibility = 1

def carDataWindowDeactivated(*args):
	global carDataWindowVisibility
	
	carDataWindowVisibility = 0
	
def carDataButtonClicked(*args):
	global carDataWindowVisibility
	global carDataWindow
	
	if carDataWindowVisibility == 0:
		carDataWindowVisibility = 1
	else:
		carDataWindowVisibility = 0
	
	ac.setVisible(carDataWindow, carDataWindowVisibility)
	
#Car data window listeners
def recalculateGearRatiosButtonClicked(*args):
	global DTConstants, ratioList
	
	DTConstants = [0] * 8
	ratioList = [0] * 7
	
def tripOdometerInfoButtonClicked(*args):
	global tripOdometer
	
	tripOdometer = 0
	
def resetPersonalBestLapButtonClicked(*args):
	global personalBestLapValue, personalBestLapValueMinutes, personalBestLapValueSeconds, personalBestPosList, personalBestTimeList
	
	personalBestLapValue = 0
	personalBestLapValueMinutes = 0
	personalBestLapValueSeconds = 0
	personalBestPosList = 0
	personalBestTimeList = 0

#Settings window
def settingsWindowActivated(*args):
	global settingsWindowVisibility
	
	settingsWindowVisibility = 1

def settingsWindowDeactivated(*args):
	global settingsWindowVisibility
	
	settingsWindowVisibility = 0

def settingsButtonClicked(*args):
	global settingsWindowVisibility
	global settingsWindow
	
	if settingsWindowVisibility == 0:
		settingsWindowVisibility = 1
	else:
		settingsWindowVisibility = 0
	
	ac.setVisible(settingsWindow, settingsWindowVisibility)

#Settings window listeners
def scaleSpinnerClicked(*args):
	global config, updateConfig
	
	updateConfig = True
	
	config.set("Sidekick", "scale", str(ac.getValue(scaleSpinner)))

def speedInKPHCheckBoxClicked(*args):
	global config, updateConfig, speedInKPH
	
	updateConfig = True
	
	if speedInKPH:
		speedInKPH = False
		ac.setText(speedUnitLabel, "mph")
	else:
		speedInKPH = True
		ac.setText(speedUnitLabel, "km/h")
		
	config.set("Sidekick", "speedInKPH", str(speedInKPH))
	
def showRpmBarCheckBoxClicked(*args):
	global config, updateConfig, showRpmBar
	
	updateConfig = True
	
	if showRpmBar:
		showRpmBar = False
	else:
		showRpmBar = True
		
	config.set("Sidekick", "showRpmBar", str(showRpmBar))
	
def showKersBarCheckBoxClicked(*args):
	global config, updateConfig, showKersBar
	
	updateConfig = True
	
	if showKersBar:
		showKersBar = False
	else:
		showKersBar = True
		
	config.set("Sidekick", "showKersBar", str(showKersBar))
	
def showAdditionalBarInfoCheckBoxClicked(*args):
	global config, updateConfig, showAdditionalBarInfo
	
	updateConfig = True
	
	if showAdditionalBarInfo:
		showAdditionalBarInfo = False
	else:
		showAdditionalBarInfo = True
		
	config.set("Sidekick", "showAdditionalBarInfo", str(showAdditionalBarInfo))
		
def tyreWearScaleSpinnerClicked(*args):
	global config, updateConfig, tyreWearScale
	
	updateConfig = True
	
	tyreWearScale = ac.getValue(tyreWearScaleSpinner)
	
	config.set("Sidekick", "tyreWearScale", str(tyreWearScale))
	
def showPressureAsDeltaCheckBoxClicked(*args):
	global config, updateConfig, showPressureAsDelta
	
	updateConfig = True
	
	if showPressureAsDelta:
		showPressureAsDelta = False
	else:
		showPressureAsDelta = True
	
	config.set("Sidekick", "showPressureAsDelta", str(showPressureAsDelta))

def showBrakeTemperaturesCheckBoxClicked(*args):
	global config, updateConfig, showBrakeTemperatures
	
	updateConfig = True
	
	if showBrakeTemperatures:
		showBrakeTemperatures = False
	else:
		showBrakeTemperatures = True
		
	config.set("Sidekick", "showBrakeTemperatures", str(showBrakeTemperatures))
	
def showBrakeTemperaturesWhileBrakingCheckBoxClicked(*args):
	global config, updateConfig, showBrakeTemperaturesWhileBraking
	
	updateConfig = True
	
	if showBrakeTemperaturesWhileBraking:
		showBrakeTemperaturesWhileBraking = False
	else:
		showBrakeTemperaturesWhileBraking = True
		
	config.set("Sidekick", "showBrakeTemperaturesWhileBraking", str(showBrakeTemperaturesWhileBraking))

def yellowLimitEnabledCheckBoxClicked(*args):
	global config, updateConfig, yellowLimitEnabled
	
	updateConfig = True
	
	if yellowLimitEnabled:
		yellowLimitEnabled = False
	else:
		yellowLimitEnabled = True
		
	config.set("Sidekick", "yellowLimitEnabled", str(yellowLimitEnabled))


def yellowLimitPercentageSpinnerClicked(*args):
	global config, updateConfig, yellowLimitPercentage
	
	updateConfig = True
	
	yellowLimitPercentage = ac.getValue(yellowLimitPercentageSpinner)

	config.set("Sidekick", "yellowLimitPercentage", str(yellowLimitPercentage))

def redLimitEnabledCheckBoxClicked(*args):
	global config, updateConfig, redLimitEnabled
	
	updateConfig = True
	
	if redLimitEnabled:
		redLimitEnabled = False
	else:
		redLimitEnabled = True
		
	config.set("Sidekick", "redLimitEnabled", str(redLimitEnabled))


def redLimitPercentageSpinnerClicked(*args):
	global config, updateConfig, redLimitPercentage
	
	updateConfig = True
	
	redLimitPercentage = ac.getValue(redLimitPercentageSpinner)

	config.set("Sidekick", "redLimitPercentage", str(redLimitPercentage))

def optimalShiftLightsCheckBoxClicked(*args):
	global config, updateConfig, optimalShiftLights
	
	updateConfig = True
	
	if optimalShiftLights:
		optimalShiftLights = False
	else:
		optimalShiftLights = True
		
	config.set("Sidekick", "optimalShiftLights", str(optimalShiftLights))

def yellowLimitPowerPercentageSpinnerClicked(*args):
	global config, updateConfig, yellowLimitPowerPercentage
	
	updateConfig = True
	
	yellowLimitPowerPercentage = ac.getValue(yellowLimitPowerPercentageSpinner)

	config.set("Sidekick", "yellowLimitPowerPercentage", str(yellowLimitPowerPercentage))

def redLimitPowerPercentageSpinnerClicked(*args):
	global config, updateConfig, redLimitPowerPercentage
	
	updateConfig = True
	
	redLimitPowerPercentage = ac.getValue(redLimitPowerPercentageSpinner)
	
	config.set("Sidekick", "redLimitPowerPercentage", str(redLimitPowerPercentage))
	
def notifyFFBClippingCheckBoxClicked(*args):
	global config, updateConfig, notifyFFBClipping
	
	updateConfig = True
	
	if notifyFFBClipping:
		notifyFFBClipping = False
	else:
		notifyFFBClipping = True
		
	config.set("Sidekick", "notifyFFBClipping", str(notifyFFBClipping))
	
def ffbClippingThresholdSpinnerClicked(*args):
	global config, updateConfig, ffbClippingThreshold

	updateConfig = True
	
	ffbClippingThreshold = ac.getValue(ffbClippingThresholdSpinner)
	
	config.set("Sidekick", "ffbClippingThreshold", str(ffbClippingThreshold))
	
def notifyWheelOffCenterCheckBoxClicked(*args):
	global config, updateConfig, notifyWheelOffCenter
	
	updateConfig = True
	
	if notifyWheelOffCenter:
		notifyWheelOffCenter = False
	else:
		notifyWheelOffCenter = True
		
def notifySessionEndCheckBoxClicked(*args):
	global config, updateConfig, notifySessionEnd
	
	updateConfig = True
	
	if notifySessionEnd:
		notifySessionEnd = False
	else:
		notifySessionEnd = True
		
	config.set("Sidekick", "notifySessionEnd", str(notifySessionEnd))
	
def notifyLapTimesCheckBoxClicked(*args):
	global config, updateConfig, notifyLapTimes
	
	updateConfig = True
	
	if notifyLapTimes:
		notifyLapTimes = False
	else:
		notifyLapTimes = True
		
	config.set("Sidekick", "notifyLapTimes", str(notifyLapTimes))
	
def AIControlInvalidatesLapCheckBoxClicked(*args):
	global config, updateConfig, AIControlInvalidatesLap
	
	updateConfig = True
	
	if AIControlInvalidatesLap:
		AIControlInvalidatesLap = False
	else:
		AIControlInvalidatesLap = True
		
	config.set("Sidekick", "AIControlInvalidatesLap", str(AIControlInvalidatesLap))
	
def usePlainBackgroundCheckBoxClicked(*args):
	global config, updateConfig, usePlainBackground
	
	updateConfig = True
	
	if usePlainBackground:
		usePlainBackground = False
		ac.setBackgroundTexture(appWindow, background)
	else:
		usePlainBackground = True
		ac.setBackgroundTexture(appWindow, plain_background)
	
	config.set("Sidekick", "usePlainBackground", str(usePlainBackground))
	
def autoLoopingCheckBoxClicked(*args):
	global config, updateConfig, autoLooping
	
	updateConfig = True
	
	if autoLooping:
		autoLooping = False
	else:
		autoLooping = True
		
	config.set("Sidekick", "autoLooping", str(autoLooping))
	
def loopFirstSectionCheckBoxClicked(*args):
	global config, updateConfig, loopFirstSection
	
	updateConfig = True
	
	if loopFirstSection:
		loopFirstSection = False
	else:
		loopFirstSection = True
		
	config.set("Sidekick", "loopFirstSection", str(loopFirstSection))
	
def loopSecondSectionCheckBoxClicked(*args):
	global config, updateConfig, loopSecondSection
	
	updateConfig = True
	
	if loopSecondSection:
		loopSecondSection = False
	else:
		loopSecondSection = True
		
	config.set("Sidekick", "loopSecondSection", str(loopSecondSection))
	
def loopThirdSectionCheckBoxClicked(*args):
	global config, updateConfig, loopThirdSection
	
	updateConfig = True
	
	if loopThirdSection:
		loopThirdSection = False
	else:
		loopThirdSection = True
		
	config.set("Sidekick", "loopThirdSection", str(loopThirdSection))
	
def loopFourthSectionCheckBoxClicked(*args):
	global config, updateConfig, loopFourthSection
	
	updateConfig = True
	
	if loopFourthSection:
		loopFourthSection = False
	else:
		loopFourthSection = True
		
	config.set("Sidekick", "loopFourthSection", str(loopFourthSection))
	
def loopFifthSectionCheckBoxClicked(*args):
	global config, updateConfig, loopFifthSection
	
	updateConfig = True
	
	if loopFifthSection:
		loopFifthSection = False
	else:
		loopFifthSection = True
		
	config.set("Sidekick", "loopFifthSection", str(loopFifthSection))
	
def autoLoopingTimeSpinnerClicked(*args):
	global config, updateConfig, autoLoopingTime
	
	updateConfig = True
	
	autoLoopingTime = ac.getValue(autoLoopingTimeSpinner)
	
	config.set("Sidekick", "autoLoopingTime", str(autoLoopingTime))
	
def temperatureTransitionRangeSpinnerClicked(*args):
	global config, updateConfig, temperatureTransitionRange
	
	updateConfig = True
	
	temperatureTransitionRange = ac.getValue(temperatureTransitionRangeSpinner)
	
	config.set("Sidekick", "temperatureTransitionRange", str(temperatureTransitionRange))
	
def pressureTransitionRangeSpinnerClicked(*args):
	global config, updateConfig, pressureTransitionRange
	
	updateConfig = True
	
	pressureTransitionRange = ac.getValue(pressureTransitionRangeSpinner)
	
	config.set("Sidekick", "pressureTransitionRange", str(pressureTransitionRange))
	
def brakeTransitionRangeSpinnerClicked(*args):
	global config, updateConfig, brakeTransitionRange
	
	updateConfig = True
	
	brakeTransitionRange = ac.getValue(brakeTransitionRangeSpinner)
	
	config.set("Sidekick", "brakeTransitionRange", str(brakeTransitionRange))
	
def showBrandInsteadOfPedalsCheckBoxClicked(*args):
	global config, updateConfig, showBrandInsteadOfPedals
	
	updateConfig = True
	
	if showBrandInsteadOfPedals:
		showBrandInsteadOfPedals = False
	else:
		showBrandInsteadOfPedals = True
		
	config.set("Sidekick", "showBrandInsteadOfPedals", str(showBrandInsteadOfPedals))
	
def disableSectionButtonsCheckBoxClicked(*args):
	global config, updateConfig, disableSectionButtons
	
	updateConfig = True
	
	if disableSectionButtons:
		disableSectionButtons = False
		ac.setVisible(firstButton, 1)
		ac.setVisible(secondButton, 1)
		ac.setVisible(thirdButton, 1)
		ac.setVisible(fourthButton, 1)
		ac.setVisible(fifthButton, 1)
	else:
		disableSectionButtons = True
		ac.setVisible(firstButton, 0)
		ac.setVisible(secondButton, 0)
		ac.setVisible(thirdButton, 0)
		ac.setVisible(fourthButton, 0)
		ac.setVisible(fifthButton, 0)
		
	config.set("Sidekick", "disableSectionButtons", str(disableSectionButtons))
	
def resetToDefaultButtonClicked(*args):
	global config, updateConfig, speedInKPH, speedUnitLabel, showRpmBar, showKersBar, showAdditionalBarInfo, tyreWearScale, showPressureAsDelta, showBrakeTemperatures, yellowLimitEnabled, yellowLimitPercentage, redLimitEnabled, redLimitPercentage, optimalShiftLights, yellowLimitPowerPercentage, redLimitPowerPercentage, notifyFFBClipping, ffbClippingThreshold, notifyWheelOffCenter, notifySessionEnd, notifyLapTimes, AIControlInvalidatesLap, usePlainBackground, autoLooping, loopFirstSection, loopSecondSection, loopThirdSection, loopFourthSection, loopFifthSection, autoLoopingTime, temperatureTransitionRange, pressureTransitionRange, brakeTransitionRange, showBrandInsteadOfPedals, disableSectionButtons
	
	updateConfig = True
	
	config.set("Sidekick", "scale", "100")
	ac.setValue(scaleSpinner, 100)
	
	speedInKPH = True
	ac.setText(speedUnitLabel, "km/h")	
	config.set("Sidekick", "speedInKPH", "True")
	ac.setValue(speedInKPHCheckBox, True)
	
	showRpmBar = True
	config.set("Sidekick", "showRpmBar", "True")
	ac.setValue(showRpmBarCheckBox, True)
	
	showKersBar = True
	config.set("Sidekick", "showKersBar", "True")
	ac.setValue(showKersBarCheckBox, True)
	
	showAdditionalBarInfo = True
	config.set("Sidekick", "showAdditionalBarInfo", "True")
	ac.setValue(showAdditionalBarInfoCheckBox, True)
	
	tyreWearScale = 16
	config.set("Sidekick", "tyreWearScale", "16")
	ac.setValue(tyreWearScaleSpinner, 16)
	
	showPressureAsDelta = False
	config.set("Sidekick", "showPressureAsDelta", "False")
	ac.setValue(showPressureAsDeltaCheckBox, False)
	
	showBrakeTemperatures = False
	config.set("Sidekick", "showBrakeTemperatures", "False")
	ac.setValue(showBrakeTemperaturesCheckBox, False)
	
	yellowLimitEnabled = True
	config.set("Sidekick", "yellowLimitEnabled", "True")
	ac.setValue(yellowLimitEnabledCheckBox, True)
	
	yellowLimitPercentage = 92
	config.set("Sidekick", "yellowLimitPercentage", "92")
	ac.setValue(yellowLimitPercentageSpinner, 92)
	
	redLimitEnabled = True
	config.set("Sidekick", "redLimitEnabled", "True")
	ac.setValue(redLimitEnabledCheckBox, True)
	
	redLimitPercentage = 96
	config.set("Sidekick", "redLimitPercentage", "96")
	ac.setValue(redLimitPercentageSpinner, 96)
	
	optimalShiftLights = True
	config.set("Sidekick", "optimalShiftLights", "True")
	ac.setValue(optimalShiftLightsCheckBox, True)
	
	yellowLimitPowerPercentage = 96
	config.set("Sidekick", "yellowLimitPowerPercentage", "96")
	ac.setValue(yellowLimitPowerPercentageSpinner, 96)
	
	redLimitPowerPercentage = 100
	config.set("Sidekick", "redLimitPowerPercentage", "100")
	ac.setValue(redLimitPowerPercentageSpinner, 100)
	
	notifyFFBClipping = True	
	config.set("Sidekick", "notifyFFBClipping", "True")
	ac.setValue(notifyFFBClippingCheckBox, True)
	
	ffbClippingThreshold = 500
	config.set("Sidekick", "ffbClippingThreshold", "500")
	ac.setValue(ffbClippingThresholdSpinner, 500)
	
	notifyWheelOffCenter = True
	config.set("Sidekick", "notifyWheelOffCenter", "True")
	ac.setValue(notifyWheelOffCenterCheckBox, True)
	
	notifySessionEnd = True
	config.set("Sidekick", "notifySessionEnd", "True")
	ac.setValue(notifySessionEndCheckBox, True)
	
	notifyLapTimes = True
	config.set("Sidekick", "notifyLapTimes", "True")
	ac.setValue(notifyLapTimesCheckBox, True)
	
	AIControlInvalidatesLap = True
	config.set("Sidekick", "AIControlInvalidatesLap", "True")
	ac.setValue(AIControlInvalidatesLapCheckBox, True)
	
	usePlainBackground = False
	ac.setBackgroundTexture(appWindow, background)
	config.set("Sidekick", "usePlainBackground", "False")
	ac.setValue(usePlainBackgroundCheckBox, False)
	
	autoLooping = False
	config.set("Sidekick", "autoLooping", "False")
	ac.setValue(autoLoopingCheckBox, False)
	
	loopFirstSection = False
	config.set("Sidekick", "loopFirstSection", "False")
	ac.setValue(loopFirstSectionCheckBox, False)
	
	loopSecondSection = False
	config.set("Sidekick", "loopSecondSection", "False")
	ac.setValue(loopSecondSectionCheckBox, False)
	
	loopThirdSection = False
	config.set("Sidekick", "loopThirdSection", "False")
	ac.setValue(loopThirdSectionCheckBox, False)
	
	loopFourthSection = False
	config.set("Sidekick", "loopFourthSection", "False")
	ac.setValue(loopFourthSectionCheckBox, False)
	
	loopFifthSection = False
	config.set("Sidekick", "loopFifthSection", "False")
	ac.setValue(loopFifthSectionCheckBox, False)
	
	autoLoopingTime = 1000
	config.set("Sidekick", "autoLoopingTime", "1000")
	ac.setValue(autoLoopingTimeSpinner, 1000)
	
	temperatureTransitionRange = 20
	config.set("Sidekick", "temperatureTransitionRange", "20")
	ac.setValue(temperatureTransitionRangeSpinner, 20)
	
	pressureTransitionRange = 4
	config.set("Sidekick", "pressureTransitionRange", "4")
	ac.setValue(pressureTransitionRangeSpinner, 4)
	
	brakeTransitionRange = 100
	config.set("Sidekick", "brakeTransitionRange", "100")
	ac.setValue(brakeTransitionRangeSpinner, 100)
	
	showBrandInsteadOfPedals = False
	config.set("Sidekick", "showBrandInsteadOfPedals", "False")
	ac.setValue(showBrandInsteadOfPedalsCheckBox, False)
	
	disableSectionButtons = False
	ac.setVisible(firstButton, 1)
	ac.setVisible(secondButton, 1)
	ac.setVisible(thirdButton, 1)
	ac.setVisible(fourthButton, 1)
	ac.setVisible(fifthButton, 1)
	config.set("Sidekick", "disableSectionButtons", "False")
	ac.setValue(disableSectionButtonsCheckBox, False)
	
#Set up hotkey listeners
def listenKey1():
	global isSelector, selectorCounter, timerTrigger1, timerTrigger2, timerTrigger3, timerTrigger4, timerTrigger5

	try:
		ctypes.windll.user32.RegisterHotKey(None, 1, 1, 65) #Alt + A
		msg = ctypes.wintypes.MSG()
		while True:
			if ctypes.windll.user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
				if msg.message == 786:
					isSelector = True
					selectorCounter = (selectorCounter + 1) % 5
					if selectorCounter == 0:
						firstButtonClicked()
						isSelector = False
						timerTrigger2 = 0
						timerTrigger3 = 0
						timerTrigger4 = 0
						timerTrigger5 = 0
					elif selectorCounter == 1:
						secondButtonClicked()
						isSelector = False
						timerTrigger1 = 0
						timerTrigger3 = 0
						timerTrigger4 = 0
						timerTrigger5 = 0
					elif selectorCounter == 2:
						thirdButtonClicked()
						isSelector = False
						timerTrigger1 = 0
						timerTrigger2 = 0
						timerTrigger4 = 0
						timerTrigger5 = 0
					elif selectorCounter == 3:
						fourthButtonClicked()
						isSelector = False
						timerTrigger1 = 0
						timerTrigger2 = 0
						timerTrigger3 = 0
						timerTrigger5 = 0
					elif selectorCounter == 4:
						fifthButtonClicked()
						isSelector = False
						timerTrigger1 = 0
						timerTrigger2 = 0
						timerTrigger3 = 0
						timerTrigger4 = 0
				ctypes.windll.user32.TranslateMessage(ctypes.byref(msg))
				ctypes.windll.user32.DispatchMessageA(ctypes.byref(msg))
	finally:
		ctypes.windll.user32.UnregisterHotKey(None, 1)
		
def listenKey2():
	global selectorCounter
	
	try:
		ctypes.windll.user32.RegisterHotKey(None, 1, 1, 83) #Alt + S
		msg = ctypes.wintypes.MSG()
		while True:
			if ctypes.windll.user32.GetMessageA(ctypes.byref(msg), None, 0, 0) != 0:
				if msg.message == 786:
					if selectorCounter == 0:
						firstButtonClicked()
					if selectorCounter == 1:
						secondButtonClicked()
					if selectorCounter == 2:
						thirdButtonClicked()
					if selectorCounter == 3:
						fourthButtonClicked()
					if selectorCounter == 4:
						fifthButtonClicked()
				ctypes.windll.user32.TranslateMessage(ctypes.byref(msg))
				ctypes.windll.user32.DispatchMessageA(ctypes.byref(msg))
	finally:
		ctypes.windll.user32.UnregisterHotKey(None, 1)

#Start hotkey listening threads
keyListener1 = threading.Thread(target = listenKey1)
keyListener1.daemon = True
keyListener1.start()

keyListener2 = threading.Thread(target = listenKey2)
keyListener2.daemon = True
keyListener2.start()