Skip to content

Instantly share code, notes, and snippets.

@ViniciusGibran
Last active December 26, 2021 02:57
Show Gist options
  • Select an option

  • Save ViniciusGibran/5660814cccc7b3456e65db1e68814be3 to your computer and use it in GitHub Desktop.

Select an option

Save ViniciusGibran/5660814cccc7b3456e65db1e68814be3 to your computer and use it in GitHub Desktop.
DRIVER RATING - UPDATES
// DRIVER RATINGS LOGICS
//SETUPS
// this class exists to get data from SPRINT RACE and calculate DRIVER RATINGS
let RATING_DATA = SpreadsheetApp.getActive().getSheetByName("RATING_DATA")
let IRC_DATA_SHEET = SpreadsheetApp.openById("1QaQUnQSiL_bKDY7zdCNp458fmDe8cS6N7taMem-b654")
let DRIVER_DATA = IRC_DATA_SHEET.getSheetByName("DRIVER_DATA")
// PROPERTIES
// max xp limit to regular
let XP_LIMIT_CUT = 100
// a max xp lvl to make even hard to earn points
let SECOND_XP_CUT = 90
let FIRST_XP_CUT = 70
// this is the maximum value for the rating addition on lap times
// driver can receive up to LAP_TIME_INITIAL_BONUS
let RP_INITIAL_BONUS = 100
// race time target additional
let RACE_LAP_TIME_TARGET_ADD = 1.5 // make an average from last season data (with top first & last drivers)
// max random value for possibility point
let POSSIBILITY_MAX_POINT = 3 //means max 2 -> review it to make a parameter?
// TODO: APL - driver DNF by other driver incident
// TODO: copy/use this for race result adding DNS [3.0,4.0]
let RATINGS_PARAMS = {
"experience": {
"DNS": [2.5,3.5],
"DNF": [1.0, 1.2],
"DSQ": [1.0, 1.2],
"APL": [0.0,0.0],
"avg_DNF": [0.5,1.0],
"in_game_warning_mult": [0.3, 0.4],
"in_game_penalty_mult": [0.3, 0.6],
"fia_warning_mult": [0.3, 1.0],
"fia_penalty_mult": [0.3, 1.6],
"performance_history": [0.5, 1.0],
"result_div": [2.8,3.5],
"fastest_lap": [1.0,2.0],
"dotd": [1.5, 3.0],
"avg_result": [1.0,2.4],
"pos_mult": [0.2, 0.4],
"consistency": [1.0,2.0],
"time_lap": [2.0,2.5],
"race_aditional": [2.0, 2.5],
},
"race_craft": {
"DNS": [2.5,3.5],
"DNF": [1.0, 1.4],
"DSQ": [1.0, 1.5],
"APL": [0.0,0.0],
"avg_DNF": [0.5,1.0],
"in_game_warning_mult": [0.3, 0.4],
"in_game_penalty_mult": [1.0, 1.6],
"fia_warning_mult": [0.3, 1.0],
"fia_penalty_mult": [0.3, 1.6],
"performance_history": [0.5, 1.0],
"result_div": [2.5,3.2],
"fastest_lap": [2.0,2.5],
"dotd": [2.0, 4.0],
"avg_result": [1.0,2.0],
"pos_mult": [0.35, 0.7],
"consistency": [1.0,2.0],
"time_lap": [3.0,3.5],
"race_aditional": [2.2, 2.5]
},
"awareness": {
"DNS": [2.5,3.5],
"DNF": [2.0, 2.5],
"DSQ": [2.1, 3.0],
"APL": [0.0,0.0],
"avg_DNF": [0.5,1.0],
"in_game_warning_mult": [0.3, 0.4],
"in_game_penalty_mult": [1.3, 1.6],
"fia_warning_mult": [0.3, 1.0],
"fia_penalty_mult": [0.3, 1.6],
"performance_history": [0.5, 1.0],
"result_div": [2.0,3.0],
"fastest_lap": [0.0,0.4],
"dotd": [2.4, 4.2],
"avg_result": [1.0,2.0],
"pos_mult": [0.3, 0.5],
"consistency": [1.0,2.0],
"time_lap": [2.3,3.0],
"race_aditional": [2.2, 2.5]
},
"pace": {
"DNS": [2.5,3.5],
"DNF": [0.5, 1.0],
"DSQ": [0.5, 1.2],
"APL": [0.0,0.0],
"avg_DNF": [0.5,1.0],
"in_game_warning_mult": [0.3, 0.4],
"in_game_penalty_mult": [0.3, 0.6],
"fia_warning_mult": [0.3, 1.0],
"fia_penalty_mult": [0.3, 1.6],
"performance_history": [0.5, 1.0],
"result_div": [2.5,3.2],
"fastest_lap": [1.5, 2.2],
"dotd": [1.5, 2.2],
"avg_result": [1.0,2.0],
"pos_mult": [0.45, 1.25],
"consistency": [1.0,2.0],
"time_lap": [2.5,3.4],
"race_aditional": [1.0, 1.5]
}
}
let LICENSES = {
"s_license": {
"emoji_id": "<:s_license:917610460562477066>",
"img_url": "https://drive.google.com/uc?id=1wirknHWI37qYyX5nCa82buukmgsvrcg3",
"min_sp": 18,
"max_sp": 20
},
"a_license": {
"emoji_id": "<:a_license:917610460285648927>",
"img_url": "https://drive.google.com/uc?id=1n7xXoUMeijt_Cok9V2oRuoxv71MwJ-ut",
"min_sp": 14,
"max_sp": 17
},
"b_license": {
"emoji_id": "<:b_license:917610460067545188>",
"img_url": "https://drive.google.com/uc?id=10DJ15KS3kSWsppNCMpsjk-PbbXi_3JOt",
"min_sp": 10,
"max_sp": 13
},
"c_license": {
"emoji_id": "<:c_license:917610459992043580>",
"img_url": "https://drive.google.com/uc?id=1dKvBzOl7OdHA2volZEizGH-qJofqIooM",
"min_sp": 7,
"max_sp": 9
},
"d_license": {
"emoji_id": "<:d_license:917610459975286844>",
"img_url": "https://drive.google.com/uc?id=1oqBEw6jveh0HaA8KolzcRKbxhivXRHnQ",
"min_sp": 4,
"max_sp": 6
},
"n_license": {
"emoji_id": "<:n_license:924330517233537074>",
"img_url": "https://drive.google.com/uc?id=1PJGY74fNeodEzda5OiWEBEXL2dFFf6Ro",
"min_sp": 0,
"max_sp": 3
}
}
//------------------------------------------------------------------------------------------------------
function GET_RACE_RESULTS() {
var minIndex = 3
let maxIndex = 22
var raceResults = []
// sort list by quali order
SORT_BY_QUALI()
// loop to get results
while(minIndex <= maxIndex) {
// race resut data
let driverName = RATING_DATA.getRange(`C${minIndex}`).getValue()
let rowRef = RATING_DATA.getRange(`D${minIndex}`).getValue()
let qualiTime = parseFloat(RATING_DATA.getRange(`E${minIndex}`).getValue().toString().slice(2))
let raceTime = parseFloat(RATING_DATA.getRange(`F${minIndex}`).getValue().toString().slice(2))
let result = RATING_DATA.getRange(`G${minIndex}`).getValue()
let inGameWarnings = RATING_DATA.getRange(`H${minIndex}`).getValue()
let inGamePenalties = RATING_DATA.getRange(`I${minIndex}`).getValue()
let fiaWarnings = RATING_DATA.getRange(`J${minIndex}`).getValue()
let fiaPenalties = RATING_DATA.getRange(`K${minIndex}`).getValue()
let backgroundDOTD = RATING_DATA.getRange(`C${minIndex}`).getFontColor()
let backgroundFLP = RATING_DATA.getRange(`G${minIndex}`).getFontColor()
let eventType = RATING_DATA.getRange("E24:F24").getValue().toString()
let circuit = RATING_DATA.getRange("G24:H24").getValue().toString()
let ratingDataRowRef = minIndex
// check if reach last driver data
if (driverName == "") { break }
// pole
let isPole = false
if (minIndex == 3) { isPole = true }
// is winner
let isWinner = false
if (parseInt(result) == 1) { isWinner = true }
// is podium
let isPodium = false
if (minIndex <= 5) { isPodium = true }
// driver data (rating)
var driverXp = parseInt(DRIVER_DATA.getRange(`T${rowRef}`).getValue())
let driverRc = parseInt(DRIVER_DATA.getRange(`U${rowRef}`).getValue())
let driverAw = parseInt(DRIVER_DATA.getRange(`V${rowRef}`).getValue())
let driverPa = parseInt(DRIVER_DATA.getRange(`W${rowRef}`).getValue())
let driverAvg = parseInt(DRIVER_DATA.getRange(`X${rowRef}`).getValue())
let totalDNFs = parseInt(DRIVER_DATA.getRange(`R${rowRef}`).getValue()) // not counting this event result
let numberOfSprintsRaced = parseInt(DRIVER_DATA.getRange(`L${rowRef}`).getValue())
let numberOfRacesRaced = parseInt(DRIVER_DATA.getRange(`M${rowRef}`).getValue())
let totalOfRacesRaced = numberOfRacesRaced + numberOfSprintsRaced + 1
// last results
var lastResults = []
let lastResultsString = DRIVER_DATA.getRange(`S${rowRef}`).getValue().toString()
lastResultsString = lastResultsString.replace("DNS", "25").replace("DNF", "22").replace("DSQ", "24").replace("APL", "")
if (lastResultsString != "0") { lastResults = lastResultsString.split(",").map(Number).filter(number => number > 0) }
if (!isNaN(result)) { lastResults.push(parseInt(result)) }
// result avarage, variance, deviation (consistency)
let avgRaceResult = CALCULATE_AVERAGE_RESULTS(lastResults)
let variance = CALCULATE_DRIVER_RESULT_VARIANCE(lastResults)
let deviation = CALCULATE_DRIVER_RESULT_DEVIATION(lastResults)
// fastet lap & dotd
let isFastestLap = (backgroundFLP == "#6842d5")
let isDriverOfTheDay = (backgroundDOTD == "#10a499")
console.log(isFastestLap)
console.log(isDriverOfTheDay)
// avg lap time target
let qualiTargetFastesLap = parseFloat(RATING_DATA.getRange("I24:J24").getValue().toString().slice(2))
let qualiTargetSlowestLap = parseFloat(RATING_DATA.getRange("K24:L24").getValue().toString().slice(2))
// lap target values
let raceAdditional = RACE_LAP_TIME_TARGET_ADD
let avgTargetFastestLap = (qualiTargetFastesLap + (qualiTargetFastesLap + raceAdditional)) / 2
let avgTargetSlowestLap = (qualiTargetSlowestLap + qualiTargetSlowestLap + raceAdditional) / 2
let avgLapTime = (qualiTime + raceTime) / 2
// driver time target result
let avgTargetRange = avgTargetSlowestLap - avgTargetFastestLap
let driverDeltaTime = avgLapTime - avgTargetFastestLap
let timeTargetResult = driverDeltaTime / avgTargetRange
// performance history multiplier
let titlesTotal = parseInt(DRIVER_DATA.getRange(`K${rowRef}`).getValue()) * 1.2
let polesTotal = parseInt(DRIVER_DATA.getRange(`N${rowRef}`).getValue()) * 1.15
let winsTotal = parseInt(DRIVER_DATA.getRange(`O${rowRef}`).getValue()) * 1.1
let podiumsTotal = parseInt(DRIVER_DATA.getRange(`P${rowRef}`).getValue()) * 1.08
let dotdTotal = parseInt(DRIVER_DATA.getRange(`Q${rowRef}`).getValue()) // keep same value
let performanceAvg = (titlesTotal + polesTotal + winsTotal + podiumsTotal + dotdTotal) / 5
let performanceFactor = performanceAvg / totalOfRacesRaced
// create max xp limit factor multiplier
let xpLimitCutFactor = MAKE_XP_LIMIT_CUT_FACTOR(driverAvg)
// safety points
let safetyPoints = parseInt(DRIVER_DATA.getRange(`Z${minIndex}`).getValue())
let raceResult = {
"driver_name": driverName,
"row_ref": rowRef,
"grid_start_pos": minIndex-2,
"quali_time": qualiTime,
"race_time": raceTime,
"avg_lap_time": avgLapTime,
"result": result,
"dnfs_total": totalDNFs,
"in_game_warnings": inGameWarnings,
"in_game_penalties": inGamePenalties,
"fia_warnings": fiaWarnings,
"fia_penalties": fiaPenalties,
"safety_points": safetyPoints,
"last_results": lastResults,
"avg_race_result": avgRaceResult,
"is_fastest_lap": isFastestLap,
"is_dotd": isDriverOfTheDay,
"driver_xp": driverXp,
"driver_rc": driverRc,
"driver_aw": driverAw,
"driver_pa": driverPa,
"driver_avg": driverAvg,
"eventType": eventType,
"circuit": circuit,
"avg_target_fastest_lap": avgTargetFastestLap,
"avg_target_slowest_lap": avgTargetSlowestLap,
"rating_data_row_ref": ratingDataRowRef,
"time_target_result": timeTargetResult,
"number_of_sprints_raced": numberOfSprintsRaced,
"number_of_races_raced": numberOfRacesRaced,
"total_of_races_raced": totalOfRacesRaced,
"variance": variance,
"deviation": deviation,
"performance_factor": performanceFactor,
"xp_limit_cut_factor": xpLimitCutFactor,
"dotd_total": dotdTotal,
"is_pole": isPole,
"is_podium": isPodium,
"is_winner": isWinner
}
raceResults.push(raceResult)
minIndex ++
}
return raceResults
}
//------------------------------------------------------------------------------------------------------
function CALCULATE_AVERAGE_RESULTS(lastResults) {
let length = lastResults.length
if (length == 0) { return 0 }
let average = lastResults?.reduce((a,b) => a+b,0) / length
return average
}
function CALCULATE_DRIVER_RESULT_VARIANCE(lastResults) {
let length = lastResults.length
if (length < 3) { return -1 }
let avgResult = CALCULATE_AVERAGE_RESULTS(lastResults)
let variance = lastResults.map(value => {
let avgDelta = value - avgResult
let squareValue = Math.pow(avgDelta, 2)
return squareValue
}).reduce((a,b) => a+b,0) / (length-1) / 100
return variance
}
function CALCULATE_DRIVER_RESULT_DEVIATION(lastResults) {
let length = lastResults.length
if (length < 3) { return -1 }
let avgResult = CALCULATE_AVERAGE_RESULTS(lastResults)
let deviation = Math.sqrt(
lastResults
.map(value => Math.pow(value - avgResult, 2))
.reduce((a,b) => a+b,0) / (length-1)
) / 20
return deviation
}
// UPDATE RATINGS
//------------------------------------------------------------------------------------------------------
function UPDATE_DRIVER_RATING() {
let raceResults = GET_RACE_RESULTS()
raceResults.forEach(result => {
// TODO: clead this
console.log("######################################")
console.log(result.driver_name)
// experience
let xpRatingFactor = RATINGS_PARAMS.experience
var xpRatingValue = GET_EXPERIENCE_FOR(xpRatingFactor, result)
var xpRating = parseInt(xpRatingValue + result.driver_xp)
let xpValue = Math.min(Math.max(xpRating,50), 100)
//DRIVER_DATA.getRange(`T${result.row_ref}`).setValue(xpValue)
// race cra1ft
let rcRatingFactor = RATINGS_PARAMS.race_craft
let rcRating = parseInt(GET_RATING_FOR(rcRatingFactor, result) + result.driver_rc)
let rcValue = Math.min(Math.max(rcRating,50), 100)
//DRIVER_DATA.getRange(`U${result.row_ref}`).setValue(rcValue)
// awareness
let awRatingFactor = RATINGS_PARAMS.awareness
let awRating = parseInt(GET_RATING_FOR(awRatingFactor, result) + result.driver_aw)
let awValue = Math.min(Math.max(awRating,50), 100)
//DRIVER_DATA.getRange(`V${result.row_ref}`).setValue(awValue)
// pace
let paRatingFactor = RATINGS_PARAMS.pace
let paRating = parseInt(GET_RATING_FOR(paRatingFactor, result) + result.driver_pa)
let paValue = Math.min(Math.max(paRating,50), 100)
//DRIVER_DATA.getRange(`W${result.row_ref}`).setValue(paValue)
// average
let avgValue = Math.ceil((xpValue + rcValue + awValue + paValue) / 4)
//DRIVER_DATA.getRange(`X${result.row_ref}`).setValue(avgValue)
RATING_DATA.getRange(`N${result.rating_data_row_ref}`).setValue(avgValue)
//number of races & sprints
if (result.eventType == "SPRINT") {
let numberOfSprintsRaced = result.number_of_sprints_raced + 1
//DRIVER_DATA.getRange(`L${result.row_ref}`).setValue(numberOfSprintsRaced)
}
if (result.eventType == "RACE") {
let numberOfRacesRaced = result.number_of_races_raced + 1
//DRIVER_DATA.getRange(`M${result.row_ref}`).setValue(numberOfRacesRaced)
}
let ratings = `${xpValue}, ${rcValue}, ${awValue}, ${paValue}`
RATING_DATA.getRange(`M${result.rating_data_row_ref}`).setValue(ratings)
RATING_DATA.getRange(`N26`).setValue(result.total_of_races_raced)
// TODO: right those values on DRIVER DATA
// POLES WINS PODIUMS DOTD's DNF's LAST 5 RESULTS
if (result.is_pole) {
let polesTotal = parseInt(DRIVER_DATA.getRange(`N${result.row_ref}`).getValue()) + 1
//DRIVER_DATA.getRange(`N${result.row_ref}`).setValue(polesTotal)
}
if (result.is_winner) {
let winsTotal = parseInt(DRIVER_DATA.getRange(`O${result.row_ref}`).getValue()) + 1
//DRIVER_DATA.getRange(`O${result.row_ref}`).setValue(winsTotal)
}
if (result.is_podium) {
let podiumsTotal = parseInt(DRIVER_DATA.getRange(`P${result.row_ref}`).getValue()) + 1
//DRIVER_DATA.getRange(`P${result.row_ref}`).setValue(podiumsTotal)
}
// update driver of the day
if (result.is_dotd) {
let dotdTotal = result.dotd_total + 1
//DRIVER_DATA.getRange(`Q${result.row_ref}`).setValue(dotdTotal)
}
// update dnf
if (result.result == "DNF") {
let dnfsTotal = parseInt(DRIVER_DATA.getRange(`R${result.row_ref}`).getValue())
//DRIVER_DATA.getRange(`R${result.row_ref}`).setValue(dnfsTotal+1)
}
// last results
var resultList = []
var driverLastResults = DRIVER_DATA.getRange(`S${result.row_ref}`).getValue().toString()
if (driverLastResults != "0") { resultList = driverLastResults.split(",") }
resultList.push(result.result)
// drop first index (older result)
if (resultList.length > 5) { resultList.shift() }
driverLastResults = resultList.toString()
//DRIVER_DATA.getRange(`S${result.row_ref}`).setValue(driverLastResults)
// TODO: review the logic & move it to own method + calculate all points on GET_DRIVER_DATA and here only update on DRIVER_DATA sheet
// license points
let hasFiaIssuedAPenaltyOrWarning = ((result.fia_penalties <=0) && (result.fia_warnings <= 0))
let hasFinishedOrAppealed = (!(isNaN(result.result)) || (result.result == "APL"))
if (hasFinishedOrAppealed && hasFiaIssuedAPenaltyOrWarning) {
var licensePoints = result.safety_points
if (result.safety_points < 20) {
licensePoints += 1
}
//DRIVER_DATA.getRange(`Y${result.row_ref}`).setValue(licensePoints)
RATING_DATA.getRange(`L${result.rating_data_row_ref}`).setValue(licensePoints)
} else {
let licensePoints = result.safety_points - result.fia_penalties
//DRIVER_DATA.getRange(`Y${result.row_ref}`).setValue(licensePoints)
RATING_DATA.getRange(`L${result.rating_data_row_ref}`).setValue(licensePoints)
}
let totalLicensePoints = parseInt(RATING_DATA.getRange(`L${result.rating_data_row_ref}`).getValue())
let licenseImgUrl = GET_LICENSE_IMG_FORMULA_BY(totalLicensePoints)
let licenseImgFormula = `=IMAGE(\"${licenseImgUrl}\";4;30;30)`
//DRIVER_DATA.getRange(`AA${result.row_ref}`).setFormula(licenseImgFormula)
})
// sort
SORT_TABLE()
}
//------------------------------------------------------------------------------------------------------
// LICENSE HELPER
function GET_LICENSE_IMG_FORMULA_BY(licensePoints) {
if (licensePoints >= LICENSES.s_license.min_sp) {
return LICENSES.s_license.img_url
} else if (licensePoints >= LICENSES.a_license.min_sp) {
return LICENSES.a_license.img_url
} else if (licensePoints >= LICENSES.b_license.min_sp) {
return LICENSES.b_license.img_url
} else if (licensePoints >= LICENSES.c_license.min_sp) {
return LICENSES.c_license.img_url
} else if (licensePoints >= LICENSES.d_license.min_sp) {
return LICENSES.d_license.img_url
} else if (licensePoints >= LICENSES.n_license.min_sp) {
return LICENSES.n_license.img_url
}
}
// RATING METHODS
// calculate value for experience
function GET_EXPERIENCE_FOR(xpRatingFactor, result) {
var xpRatingValue = GET_RATING_FOR(xpRatingFactor, result)
return xpRatingValue
// TODO: Move it to GET_RATING_FOR method and leave here only logic regarding XP (USE DNF's to calculate)
// CHANGE IT TO BE FACTOR WITH MAX XP LVL ( DIVIDE BY 100 & GET PERCENTAGE )
// xp gets harder to earn regarding lvl and
if (result.driver_xp > RP_INITIAL_BONUS) {
// every 3 races may update xp
if (result.total_of_races_raced % 3 == 0) {
// max xp limit to calculations, now is up to possibility
if (result.driver_xp >= MAX_XP_LIMIT) {
return POSSIBILITY_POINT()
}
// limit to 3
if (xpRatingValue > 3) {
xpRatingValue = 3
}
// add possibility
xpRatingValue += POSSIBILITY_POINT()
}
}
// limit point removal to 5
if (xpRatingValue < -5) { xpRatingValue = -5 }
return xpRatingValue
}
// small chance to return up to 2 points
function POSSIBILITY_POINT() {
let possibility = Math.random()
let rating = Math.floor(Math.random() * POSSIBILITY_MAX_POINT)
return possibility > 0.89 ? rating : 0
}
// CALCULATIONS
// timeTargetResult deviation variance total_of_dnfs (get avg of DNFs) lap_time_factor + review
/*
"DNS": [2.5,3.5], ok
"DNF": [1.0, 1.2], ok
"DSQ": [1.0, 1.2], ok
"APL": [0.0,0.0], ok
"avg_DNF": [0.5,1.0],
"in_game_warning_mult": [0.3, 0.4],ok
"in_game_penalty_mult": [0.3, 0.6],ok
"fia_warning_mult": [0.3, 0.4],ok
"fia_penalty_mult": [0.3, 0.6],ok
"result_div": [3.0,4.8], ok
"fastest_lap": [1.0,2.0], ok
"dotd": [1.0, 2.5], ok
"avg_result": [1.0,2.0] ok
"pos_mult": [0.2, 0.4], ok
"consistency": [1.0,2.0], ok
"time_lap": [5.0,7.0] ok
"race_aditional": [2.0, 2.5], ok
*/
//------------------------------------------------------------------------------------------------------
function GET_RATING_FOR(ratingFactor, raceResult) {
var performancePoints = 0
// REMOVEs
// dns
if (raceResult.result == "DNS") {
performancePoints -= RANDOM_VALUES(ratingFactor.DNS)
}
// dnf
if (raceResult.result == "DNF") {
performancePoints -= RANDOM_VALUES(ratingFactor.DNF)
console.log("DNF")
console.log(performancePoints)
}
// dsq
if (raceResult.result == "DSQ") {
performancePoints -= RANDOM_VALUES(ratingFactor.DSQ)
}
// avg dnf's - removes a small factor regarding driver avg dnf's in relation with total races
// change avgDNF to DNF_DEBIT and add 5 debit
// move this to DRIVER DATA initializer
// driver dnf's avg debit - calculate remotion based on DNFs
if (raceResult.dnfs_total > 0) {
// more avg rating means higher dnf debit
var avgDnfFactor = RANDOM_VALUES(ratingFactor.avg_DNF) * (raceResult.driver_avg/100)
console.log("raceResult.dnfs_total")
console.log(raceResult.dnfs_total)
console.log("raceResult.totalOfRacesRaced")
console.log(raceResult.total_of_races_raced)
console.log("avgDnfFactor")
console.log(avgDnfFactor)
// move this to the drive data calculations
performancePoints -= avgDnfFactor * (raceResult.dnfs_total / raceResult.total_of_races_raced)
console.log("avgDnfFactor")
console.log(performancePoints)
}
// TODO: get number of driver DNFs and calculate % with total number of races (make new factor)
// incidents in game
let inGameIncidentMult = RANDOM_VALUES(ratingFactor.in_game_warning_mult)
performancePoints -= inGameIncidentMult * raceResult.in_game_warnings
console.log("inGameIncidentMult")
console.log(performancePoints)
let inGamePenaltyMult = RANDOM_VALUES(ratingFactor.in_game_penalty_mult)
performancePoints -= inGamePenaltyMult * raceResult.in_game_penalties
console.log("inGamePenaltyMult")
console.log(performancePoints)
// incidents FIA
let fiaIncidentMult = RANDOM_VALUES(ratingFactor.fia_warning_mult)
performancePoints -= fiaIncidentMult * raceResult.fia_warnings
console.log("fiaIncidentMult")
console.log(performancePoints)
let fiaPenaltyMult = RANDOM_VALUES(ratingFactor.fia_penalty_mult)
performancePoints -= fiaPenaltyMult * raceResult.fia_penalties
console.log("fiaPenaltyMult")
console.log(performancePoints)
// ADDs
let performanceMult = RANDOM_VALUES(ratingFactor.performance_history)
performancePoints += raceResult.performance_factor * performanceMult
// consistency (variance & deviation)
// only if the value is equal or higher than 0 (means more than 2 races at least)
if (raceResult.variance >= 0 && raceResult.deviation >= 0) {
let consistencyMultiplier = (raceResult.variance + raceResult.deviation) / 2
if (consistencyMultiplier >= 0) {
let consistencyFactor = RANDOM_VALUES(ratingFactor.consistency)
performancePoints += consistencyFactor - ( consistencyFactor * consistencyMultiplier)
console.log("consistencyFactor")
console.log(performancePoints)
}
}
// quali time result additional
let timelapFactor = RANDOM_VALUES(ratingFactor.time_lap)
performancePoints += timelapFactor - (timelapFactor * raceResult.time_target_result).toFixed(2)
console.log("timelapFactor")
console.log(performancePoints)
// race aditional
performancePoints += RANDOM_VALUES(ratingFactor.race_aditional)
console.log("race aditional")
console.log(performancePoints)
// fastest lap
if(raceResult.is_fastest_lap) {
performancePoints += RANDOM_VALUES(ratingFactor.fastest_lap)
console.log("FASTEST LAP")
console.log(performancePoints)
}
// driver of the day
if (raceResult.is_dotd) {
performancePoints += RANDOM_VALUES(ratingFactor.dotd)
console.log("DOTD")
console.log(performancePoints)
}
// TODO: review & test this
if (isNaN(raceResult.result)) {
console.log("result isNaN")
console.log("raceResult.xp_limit_cut_factor")
console.log(raceResult.xp_limit_cut_factor)
console.log("performancePoints")
console.log(Math.floor(performancePoints * raceResult.xp_limit_cut_factor))
return Math.floor(performancePoints * raceResult.xp_limit_cut_factor)
}
// result -> pace CONSIDER REVIEW THIS
let resultFactor = RANDOM_VALUES(ratingFactor.result_div)
performancePoints += resultFactor / raceResult.result
console.log("resultFactor")
console.log(performancePoints)
// TODO: Add factor in %
// avg result (delta) -> pace & race craft
let avgResMult = RANDOM_VALUES(ratingFactor.avg_result)
console.log("avg_race_result")
console.log(raceResult.avg_race_result)
console.log("raceResult.result")
console.log(raceResult.result)
var avgDeltaPos = raceResult.avg_race_result - raceResult.result
console.log("avgDeltaPos")
console.log(avgDeltaPos)
avgDeltaPos = avgDeltaPos == 0 ? 1 : avgDeltaPos
performancePoints += avgResMult * (avgDeltaPos/20)
console.log("avgResMult")
console.log(avgResMult * (avgDeltaPos/20))
console.log(performancePoints)
// result (delta) -> race craft
// start & final position multiplier
let posMult = RANDOM_VALUES(ratingFactor.pos_mult)
var deltaPos = raceResult.grid_start_pos - raceResult.result
deltaPos = deltaPos == 0 ? 1 : deltaPos
performancePoints += posMult * deltaPos
console.log("posMult")
console.log(performancePoints)
//review this -> make this logic that cutting one on XP method
let performancePointsTotal = performancePoints * raceResult.xp_limit_cut_factor
console.log("raceResult.xp_limit_cut_factor")
console.log(raceResult.xp_limit_cut_factor)
console.log("### FINAL performancePointsTotal")
console.log(performancePointsTotal)
if (raceResult.driver_avg >= FIRST_XP_CUT) {
return Math.floor(performancePointsTotal)
}
return Math.ceil(performancePointsTotal)
}
function MAKE_XP_LIMIT_CUT_FACTOR(driverAvg) {
// if a driver has reach avg xp limit
// return less % for new points
if (driverAvg > SECOND_XP_CUT) {
return (XP_LIMIT_CUT - driverAvg) / 110
}
if (driverAvg > FIRST_XP_CUT) {
return (XP_LIMIT_CUT - driverAvg) / 100
}
let bonusFactor = RP_INITIAL_BONUS + XP_LIMIT_CUT
console.log("NORMAL CUT")
console.log((bonusFactor - driverAvg) / 100)
return (bonusFactor - driverAvg) / 100
}
// set quali factor regarding driver avg rating
// this can return high rating values for drivers with target closest time
// NOT TO BE USED ANYMORE
function GET_LAP_TIME_FACTOR_BY(driverAvg) {
// if a driver has reach avg xp limit for the higher lap time factor return a possibility points
if (driverAvg > MAX_LAP_TIME_XP_BONUS) {
return POSSIBILITY_POINT()
}
// first cut returns up to the lap factor limit
let firstCut = MAX_LAP_TIME_XP_BONUS - 15
var lapFactorLimit = LAP_TIME_INITIAL_BONUS
let minimumAvgRating = 50
if (driverAvg <= firstCut) {
let lapTimeFactor = lapFactorLimit - (driverAvg - minimumAvgRating)
return Math.min(Math.max(lapTimeFactor, 2), lapFactorLimit)
}
// second cut retuns lower factor
// driver avg is between limit and first cut
// note: there's a gap between lap factor and avg rating between cuts (minimumAvgRating values)
lapFactorLimit -= 10
minimumAvgRating += 15
let lapTimeFactor = (lapFactorLimit - (driverAvg - minimumAvgRating))
return Math.max(lapTimeFactor, lapFactorLimit)
}
// TODO review shorting
// sort by rating
function SORT_TABLE() {
var range = RATING_DATA.getRange("B3:N22")
range.sort([{column: 14, ascending: false}])
}
function SORT_BY_QUALI() {
var range = RATING_DATA.getRange("B3:N22")
range.sort([{column: 5, ascending: true}])
}
function RANDOM_VALUES(factorValues) {
// randomized between factor range
let min = factorValues[0]
let max = factorValues[1]
let value = parseFloat((Math.random() * (max - min) + min).toFixed(2))
return value
}
//------------------------------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment