Ticket #3403: 3403_summary_graphs_v0.2.patch
File 3403_summary_graphs_v0.2.patch, 36.3 KB (added by , 7 years ago) |
---|
-
binaries/data/mods/public/gui/session/session.js
1332 1332 // Serialize the statistics for each player into a comma-separated list. 1333 1333 // Ignore gaia 1334 1334 for (let i = 1; i < extendedSimState.players.length; ++i) 1335 { 1335 {TODO 1336 1336 let player = extendedSimState.players[i]; 1337 1337 1338 1338 playerStates += player.state + ","; -
binaries/data/mods/public/gui/summary/counters.js
1 var g_TeamHelperData = [];1 var g_TeamHelperData = {}; 2 2 3 3 function resetDataHelpers() 4 4 { 5 g_TeamHelperData = [];5 g_TeamHelperData = {}; 6 6 } 7 7 8 8 function formatTrained(trained, killed, lost) … … 61 61 62 62 function updateCountersPlayer(playerState, counters, idGUI) 63 63 { 64 let index = playerState.sequences.time.length - 1; 64 65 for (let w in counters) 65 66 { 66 67 let fn = counters[w].fn; 67 Engine.GetGUIObjectByName(idGUI + "[" + w + "]").caption = fn && fn(playerState, w);68 Engine.GetGUIObjectByName(idGUI + "[" + w + "]").caption = fn && fn(playerState, index, w); 68 69 } 69 70 } 70 71 function addArray(array1, array2) 72 { 73 //warn("a1: " + JSON.stringify(array1) + " a2: " + JSON.stringify(array2)); 74 array1 = array1.map((value, index) => value + array2[index]); 75 //warn("a1result: " + JSON.stringify(array1)); 76 } 71 77 // Updates g_TeamHelperData by appending some data from playerState 72 78 function calculateTeamCounters(playerState) 73 79 { 74 80 if (!g_TeamHelperData[playerState.team]) 75 81 g_TeamHelperData[playerState.team] = { 76 "food": 0,77 "vegetarianFood": 0,78 "female": 0,79 "worker": 0,80 "enemyUnitsKilled": 0,81 "unitsLost": 0,82 "percentMapControlled": 0,83 "peakPercentMapControlled": 0,84 "percentMapExplored": 0,85 "totalBought": 0,86 "totalSold": 082 "food": new Array(playerState.sequences.time.length).fill(0), 83 "vegetarianFood": new Array(playerState.sequences.time.length).fill(0), 84 "female": new Array(playerState.sequences.time.length).fill(0), 85 "worker": new Array(playerState.sequences.time.length).fill(0), 86 "enemyUnitsKilled": new Array(playerState.sequences.time.length).fill(0), 87 "unitsLost": new Array(playerState.sequences.time.length).fill(0), 88 "percentMapControlled": new Array(playerState.sequences.time.length).fill(0), 89 "peakPercentMapControlled": new Array(playerState.sequences.time.length).fill(0), 90 "percentMapExplored": new Array(playerState.sequences.time.length).fill(0), 91 "totalBought": new Array(playerState.sequences.time.length).fill(0), 92 "totalSold": new Array(playerState.sequences.time.length).fill(0) 87 93 }; 94 //warn("teamHelper: " + JSON.stringify(g_TeamHelperData)); 88 95 89 g_TeamHelperData[playerState.team].food += playerState.statistics.resourcesGathered.food;90 g_TeamHelperData[playerState.team].vegetarianFood += playerState.statistics.resourcesGathered.vegetarianFood;96 addArray(g_TeamHelperData[playerState.team].food, playerState.sequences.resourcesGathered.food); 97 addArray(g_TeamHelperData[playerState.team].vegetarianFood, playerState.sequences.resourcesGathered.vegetarianFood); 91 98 92 g_TeamHelperData[playerState.team].female += playerState.statistics.unitsTrained.Female;93 g_TeamHelperData[playerState.team].worker += playerState.statistics.unitsTrained.Worker;99 addArray(g_TeamHelperData[playerState.team].female, playerState.sequences.unitsTrained.Female); 100 addArray(g_TeamHelperData[playerState.team].worker, playerState.sequences.unitsTrained.Worker); 94 101 95 g_TeamHelperData[playerState.team].enemyUnitsKilled += playerState.statistics.enemyUnitsKilled.total;96 g_TeamHelperData[playerState.team].unitsLost += playerState.statistics.unitsLost.total;102 addArray(g_TeamHelperData[playerState.team].enemyUnitsKilled, playerState.sequences.enemyUnitsKilled.total); 103 addArray(g_TeamHelperData[playerState.team].unitsLost, playerState.sequences.unitsLost.total); 97 104 98 g_TeamHelperData[playerState.team].percentMapControlled = playerState.s tatistics.teamPercentMapControlled;99 g_TeamHelperData[playerState.team].peakPercentMapControlled = playerState.s tatistics.teamPeakPercentMapControlled;105 g_TeamHelperData[playerState.team].percentMapControlled = playerState.sequences.teamPercentMapControlled; 106 g_TeamHelperData[playerState.team].peakPercentMapControlled = playerState.sequences.teamPeakPercentMapControlled; 100 107 101 g_TeamHelperData[playerState.team].percentMapExplored = playerState.s tatistics.teamPercentMapExplored;108 g_TeamHelperData[playerState.team].percentMapExplored = playerState.sequences.teamPercentMapExplored; 102 109 103 for (let type in playerState.s tatistics.resourcesBought)104 g_TeamHelperData[playerState.team].totalBought += playerState.statistics.resourcesBought[type];110 for (let type in playerState.sequences.resourcesBought) 111 addArray(g_TeamHelperData[playerState.team].totalBought, playerState.sequences.resourcesBought[type]); 105 112 106 for (let type in playerState.statistics.resourcesSold) 107 g_TeamHelperData[playerState.team].totalSold += playerState.statistics.resourcesSold[type]; 113 for (let type in playerState.sequences.resourcesSold) 114 addArray(g_TeamHelperData[playerState.team].totalSold, playerState.sequences.resourcesSold[type]); 115 //warn("teamHelper2: " + JSON.stringify(g_TeamHelperData)); 108 116 } 109 117 110 function calculateEconomyScore(playerState )118 function calculateEconomyScore(playerState, index) 111 119 { 112 120 let total = 0; 113 for (let type in playerState.s tatistics.resourcesGathered)114 total += playerState.s tatistics.resourcesGathered[type];121 for (let type in playerState.sequences.resourcesGathered) 122 total += playerState.sequences.resourcesGathered[type][index]; 115 123 116 124 return Math.round(total / 10); 117 125 } 118 126 119 function calculateMilitaryScore(playerState )127 function calculateMilitaryScore(playerState, index) 120 128 { 121 return Math.round((playerState.s tatistics.enemyUnitsKilledValue+122 playerState.s tatistics.enemyBuildingsDestroyedValue+123 playerState.s tatistics.buildingsCapturedValue) / 10);129 return Math.round((playerState.sequences.enemyUnitsKilledValue[index] + 130 playerState.sequences.enemyBuildingsDestroyedValue[index] + 131 playerState.sequences.buildingsCapturedValue[index]) / 10); 124 132 } 125 133 126 function calculateExplorationScore(playerState )134 function calculateExplorationScore(playerState, index) 127 135 { 128 return playerState.s tatistics.percentMapExplored* 10;136 return playerState.sequences.percentMapExplored[index] * 10; 129 137 } 130 138 131 function calculateScoreTotal(playerState )139 function calculateScoreTotal(playerState, index) 132 140 { 133 return calculateEconomyScore(playerState ) +134 calculateMilitaryScore(playerState ) +135 calculateExplorationScore(playerState );141 return calculateEconomyScore(playerState, index) + 142 calculateMilitaryScore(playerState, index) + 143 calculateExplorationScore(playerState, index); 136 144 } 137 145 138 function calculateScoreTeam(counters )146 function calculateScoreTeam(counters, index) 139 147 { 140 148 for (let t in g_Teams) 141 149 { … … 148 156 let total = 0; 149 157 150 158 if (w == 2) // Team exploration score (not additive) 151 total = g_TeamHelperData[t].percentMapExplored * 10;159 total = g_TeamHelperData[t].percentMapExplored[index] * 10; 152 160 else 153 161 for (let p = 0; p < g_Teams[t]; ++p) 154 162 total += +Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + p + "][" + w + "]").caption; … … 164 172 } 165 173 } 166 174 167 function calculateBuildings(playerState, position)175 function calculateBuildings(playerState, index, position) 168 176 { 169 177 let type = g_BuildingsTypes[position]; 170 178 return formatCaptured( 171 playerState.s tatistics.buildingsConstructed[type],172 playerState.s tatistics.enemyBuildingsDestroyed[type],173 playerState.s tatistics.buildingsCaptured[type],174 playerState.s tatistics.buildingsLost[type]);179 playerState.sequences.buildingsConstructed[type][index], 180 playerState.sequences.enemyBuildingsDestroyed[type][index], 181 playerState.sequences.buildingsCaptured[type][index], 182 playerState.sequences.buildingsLost[type][index]); 175 183 } 176 184 177 function calculateBuildingsTeam(counters )185 function calculateBuildingsTeam(counters, index) 178 186 { 179 187 for (let t in g_Teams) 180 188 { … … 208 216 } 209 217 } 210 218 211 function calculateUnitsTeam(counters )219 function calculateUnitsTeam(counters, index) 212 220 { 213 221 for (let t in g_Teams) 214 222 { … … 259 267 } 260 268 } 261 269 262 function calculateUnitsWithCaptured(playerState, position)270 function calculateUnitsWithCaptured(playerState, index, position) 263 271 { 264 272 let type = g_UnitsTypes[position]; 265 273 266 274 return formatCaptured( 267 playerState.s tatistics.unitsTrained[type],268 playerState.s tatistics.enemyUnitsKilled[type],269 playerState.s tatistics.unitsCaptured[type],270 playerState.s tatistics.unitsLost[type]);275 playerState.sequences.unitsTrained[type][index], 276 playerState.sequences.enemyUnitsKilled[type][index], 277 playerState.sequences.unitsCaptured[type][index], 278 playerState.sequences.unitsLost[type][index]); 271 279 } 272 280 273 function calculateUnits(playerState, position)281 function calculateUnits(playerState, index, position) 274 282 { 275 283 let type = g_UnitsTypes[position]; 276 284 277 285 return formatTrained( 278 playerState.s tatistics.unitsTrained[type],279 playerState.s tatistics.enemyUnitsKilled[type],280 playerState.s tatistics.unitsLost[type]);286 playerState.sequences.unitsTrained[type][index], 287 playerState.sequences.enemyUnitsKilled[type][index], 288 playerState.sequences.unitsLost[type][index]); 281 289 } 282 290 283 function calculateResources(playerState, position)291 function calculateResources(playerState, index, position) 284 292 { 285 293 let type = g_ResourceData.GetCodes()[position]; 286 294 287 295 return formatIncome( 288 playerState.s tatistics.resourcesGathered[type],289 playerState.s tatistics.resourcesUsed[type] - playerState.statistics.resourcesSold[type]);296 playerState.sequences.resourcesGathered[type][index], 297 playerState.sequences.resourcesUsed[type][index] - playerState.sequences.resourcesSold[type][index]); 290 298 } 291 299 292 function calculateTotalResources(playerState )300 function calculateTotalResources(playerState, index) 293 301 { 294 302 let totalGathered = 0; 295 303 let totalUsed = 0; … … 296 304 297 305 for (let type of g_ResourceData.GetCodes()) 298 306 { 299 totalGathered += playerState.s tatistics.resourcesGathered[type];300 totalUsed += playerState.s tatistics.resourcesUsed[type] - playerState.statistics.resourcesSold[type];307 totalGathered += playerState.sequences.resourcesGathered[type][index]; 308 totalUsed += playerState.sequences.resourcesUsed[type][index] - playerState.sequences.resourcesSold[type][index]; 301 309 } 302 310 303 311 return formatIncome(totalGathered, totalUsed); 304 312 } 305 313 306 function calculateTreasureCollected(playerState )314 function calculateTreasureCollected(playerState, index) 307 315 { 308 return playerState.s tatistics.treasuresCollected;316 return playerState.sequences.treasuresCollected[index]; 309 317 } 310 318 311 function calculateLootCollected(playerState )319 function calculateLootCollected(playerState, index) 312 320 { 313 return playerState.s tatistics.lootCollected;321 return playerState.sequences.lootCollected[index]; 314 322 } 315 323 316 function calculateTributeSent(playerState )324 function calculateTributeSent(playerState, index) 317 325 { 318 326 return formatIncome( 319 playerState.s tatistics.tributesSent,320 playerState.s tatistics.tributesReceived);327 playerState.sequences.tributesSent[index], 328 playerState.sequences.tributesReceived[index]); 321 329 } 322 330 323 function calculateResourcesTeam(counters )331 function calculateResourcesTeam(counters, index) 324 332 { 325 333 for (let t in g_Teams) 326 334 { … … 360 368 } 361 369 } 362 370 363 function calculateResourceExchanged(playerState, position)371 function calculateResourceExchanged(playerState, index, position) 364 372 { 365 373 let type = g_ResourceData.GetCodes()[position]; 366 374 367 375 return formatIncome( 368 playerState.s tatistics.resourcesBought[type],369 playerState.s tatistics.resourcesSold[type]);376 playerState.sequences.resourcesBought[type][index], 377 playerState.sequences.resourcesSold[type][index]); 370 378 } 371 379 372 function calculateBarterEfficiency(playerState )380 function calculateBarterEfficiency(playerState, index) 373 381 { 374 382 let totalBought = 0; 375 383 let totalSold = 0; 376 384 377 for (let type in playerState.s tatistics.resourcesBought)378 totalBought += playerState.s tatistics.resourcesBought[type];385 for (let type in playerState.sequences.resourcesBought) 386 totalBought += playerState.sequences.resourcesBought[type][index]; 379 387 380 for (let type in playerState.s tatistics.resourcesSold)381 totalSold += playerState.s tatistics.resourcesSold[type];388 for (let type in playerState.sequences.resourcesSold) 389 totalSold += playerState.sequences.resourcesSold[type][index]; 382 390 383 391 return formatPercent(totalBought, totalSold); 384 392 } 385 393 386 function calculateTradeIncome(playerState )394 function calculateTradeIncome(playerState, index) 387 395 { 388 return playerState.s tatistics.tradeIncome;396 return playerState.sequences.tradeIncome[index]; 389 397 } 390 398 391 function calculateMarketTeam(counters )399 function calculateMarketTeam(counters, index) 392 400 { 393 401 for (let t in g_Teams) 394 402 { … … 418 426 419 427 let teamTotal; 420 428 if (w == 4) 421 teamTotal = formatPercent(g_TeamHelperData[t].totalBought , g_TeamHelperData[t].totalSold);429 teamTotal = formatPercent(g_TeamHelperData[t].totalBought[index], g_TeamHelperData[t].totalSold[index]); 422 430 else if (w > 4) 423 431 teamTotal = total.income; 424 432 else … … 429 437 } 430 438 } 431 439 432 function calculateVegetarianRatio(playerState )440 function calculateVegetarianRatio(playerState, index) 433 441 { 434 442 return formatPercent( 435 playerState.s tatistics.resourcesGathered.vegetarianFood,436 playerState.s tatistics.resourcesGathered.food);443 playerState.sequences.resourcesGathered.vegetarianFood[index], 444 playerState.sequences.resourcesGathered.food[index]); 437 445 } 438 446 439 function calculateFeminization(playerState )447 function calculateFeminization(playerState, index) 440 448 { 441 449 return formatPercent( 442 playerState.s tatistics.unitsTrained.Female,443 playerState.s tatistics.unitsTrained.Worker);450 playerState.sequences.unitsTrained.Female[index], 451 playerState.sequences.unitsTrained.Worker[index]); 444 452 } 445 453 446 function calculateKillDeathRatio(playerState )454 function calculateKillDeathRatio(playerState, index) 447 455 { 448 456 return formatRatio( 449 playerState.s tatistics.enemyUnitsKilled.total,450 playerState.s tatistics.unitsLost.total);457 playerState.sequences.enemyUnitsKilled.total[index], 458 playerState.sequences.unitsLost.total[index]); 451 459 } 452 460 453 function calculateMapExploration(playerState )461 function calculateMapExploration(playerState, index) 454 462 { 455 return playerState.s tatistics.percentMapExplored+ "%";463 return playerState.sequences.percentMapExplored[index] + "%"; 456 464 } 457 465 458 function calculateMapFinalControl(playerState )466 function calculateMapFinalControl(playerState, index) 459 467 { 460 return playerState.s tatistics.percentMapControlled+ "%";468 return playerState.sequences.percentMapControlled[index] + "%"; 461 469 } 462 470 463 function calculateMapPeakControl(playerState )471 function calculateMapPeakControl(playerState, index) 464 472 { 465 return playerState.s tatistics.peakPercentMapControlled+ "%";473 return playerState.sequences.peakPercentMapControlled[index] + "%"; 466 474 } 467 475 468 function calculateMiscellaneous(counters )476 function calculateMiscellaneous(counters, index) 469 477 { 470 478 for (let t in g_Teams) 471 479 { … … 477 485 let teamTotal; 478 486 479 487 if (w == 0) 480 teamTotal = formatPercent(g_TeamHelperData[t].vegetarianFood , g_TeamHelperData[t].food);488 teamTotal = formatPercent(g_TeamHelperData[t].vegetarianFood[index], g_TeamHelperData[t].food[index]); 481 489 else if (w == 1) 482 teamTotal = formatPercent(g_TeamHelperData[t].female , g_TeamHelperData[t].worker);490 teamTotal = formatPercent(g_TeamHelperData[t].female[index], g_TeamHelperData[t].worker[index]); 483 491 else if (w == 2) 484 teamTotal = formatRatio(g_TeamHelperData[t].enemyUnitsKilled , g_TeamHelperData[t].unitsLost);492 teamTotal = formatRatio(g_TeamHelperData[t].enemyUnitsKilled[index], g_TeamHelperData[t].unitsLost[index]); 485 493 else if (w == 3) 486 teamTotal = g_TeamHelperData[t].percentMapExplored + "%";494 teamTotal = g_TeamHelperData[t].percentMapExplored[index] + "%"; 487 495 else if (w == 4) 488 teamTotal = g_TeamHelperData[t].peakPercentMapControlled + "%";496 teamTotal = g_TeamHelperData[t].peakPercentMapControlled[index] + "%"; 489 497 else if (w == 5) 490 teamTotal = g_TeamHelperData[t].percentMapControlled + "%";498 teamTotal = g_TeamHelperData[t].percentMapControlled[index] + "%"; 491 499 492 500 Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = teamTotal; 493 501 } -
binaries/data/mods/public/gui/summary/layout.js
1 /*var g_GraphData = { 2 "score": { 3 "caption": translate("Score"), 4 "values": [ 5 { 6 "caption": translate("Economy score"), 7 "fn": calculateEconomyScore 8 }, 9 { 10 "caption": translate("Military score"), 11 "fn": calculateMilitaryScore 12 } 13 ] 14 }, 15 "buildings": { 16 "caption": translate("Buildings"), 17 "values": [ 18 { 19 "caption": translate("Houses"), 20 "fn": calculateBuildings 21 } 22 ] 23 } 24 };*/ 25 1 26 var g_ScorePanelsData = { 2 27 "score": { 28 "caption": translate("Score"), 3 29 "headings": [ 4 { "caption ": translate("Player name"), "yStart": 26, "width": 200 },5 { "caption ": translate("Economy score"), "yStart": 16, "width": 100 },6 { "caption ": translate("Military score"), "yStart": 16, "width": 100 },7 { "caption ": translate("Exploration score"), "yStart": 16, "width": 100 },8 { "caption ": translate("Total score"), "yStart": 16, "width": 100 }30 { "captionRaw": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 }, 31 { "captionRaw": "economyScore", "caption": translate("Economy score"), "yStart": 16, "width": 100 }, 32 { "captionRaw": "militaryScore", "caption": translate("Military score"), "yStart": 16, "width": 100 }, 33 { "captionRaw": "explorationScore", "caption": translate("Exploration score"), "yStart": 16, "width": 100 }, 34 { "captionRaw": "totalScore", "caption": translate("Total score"), "yStart": 16, "width": 100 } 9 35 ], 10 36 "titleHeadings": [], 11 37 "counters": [ … … 17 43 "teamCounterFn": calculateScoreTeam 18 44 }, 19 45 "buildings": { 46 "caption": translate("Buildings"), 20 47 "headings": [ 21 { "caption ": translate("Player name"), "yStart": 26, "width": 200 },22 { "caption ": translate("Total"), "yStart": 34, "width": 105 },23 { "caption ": translate("Houses"), "yStart": 34, "width": 85 },24 { "caption ": translate("Economic"), "yStart": 34, "width": 85 },25 { "caption ": translate("Outposts"), "yStart": 34, "width": 85 },26 { "caption ": translate("Military"), "yStart": 34, "width": 85 },27 { "caption ": translate("Fortresses"), "yStart": 34, "width": 85 },28 { "caption ": translate("Civ centers"), "yStart": 34, "width": 85 },29 { "caption ": translate("Wonders"), "yStart": 34, "width": 85 }48 { "captionRaw": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 }, 49 { "captionRaw": "total", "caption": translate("Total"), "yStart": 34, "width": 105 }, 50 { "captionRaw": "houses", "caption": translate("Houses"), "yStart": 34, "width": 85 }, 51 { "captionRaw": "economic", "caption": translate("Economic"), "yStart": 34, "width": 85 }, 52 { "captionRaw": "outposts", "caption": translate("Outposts"), "yStart": 34, "width": 85 }, 53 { "captionRaw": "military", "caption": translate("Military"), "yStart": 34, "width": 85 }, 54 { "captionRaw": "fortresses", "caption": translate("Fortresses"), "yStart": 34, "width": 85 }, 55 { "captionRaw": "civCenters", "caption": translate("Civ centers"), "yStart": 34, "width": 85 }, 56 { "captionRaw": "wonders", "caption": translate("Wonders"), "yStart": 34, "width": 85 } 30 57 ], 31 58 "titleHeadings": [ 32 59 { … … 54 81 "teamCounterFn": calculateBuildingsTeam 55 82 }, 56 83 "units": { 84 "caption": translate("Units"), 57 85 "headings": [ 58 { "caption ": translate("Player name"), "yStart": 26, "width": 200 },59 { "caption ": translate("Total"), "yStart": 34, "width": 105 },60 { "caption ": translate("Infantry"), "yStart": 34, "width": 85 },61 { "caption ": translate("Worker"), "yStart": 34, "width": 85 },62 { "caption ": translate("Cavalry"), "yStart": 34, "width": 85 },63 { "caption ": translate("Champion"), "yStart": 34, "width": 85 },64 { "caption ": translate("Heroes"), "yStart": 34, "width": 85 },65 { "caption ": translate("Siege"), "yStart": 34, "width": 85 },66 { "caption ": translate("Navy"), "yStart": 34, "width": 85 },67 { "caption ": translate("Traders"), "yStart": 34, "width": 85 }86 { "captionRaw": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 }, 87 { "captionRaw": "total", "caption": translate("Total"), "yStart": 34, "width": 105 }, 88 { "captionRaw": "infantry", "caption": translate("Infantry"), "yStart": 34, "width": 85 }, 89 { "captionRaw": "worker", "caption": translate("Worker"), "yStart": 34, "width": 85 }, 90 { "captionRaw": "cavalry", "caption": translate("Cavalry"), "yStart": 34, "width": 85 }, 91 { "captionRaw": "champion", "caption": translate("Champion"), "yStart": 34, "width": 85 }, 92 { "captionRaw": "heroes", "caption": translate("Heroes"), "yStart": 34, "width": 85 }, 93 { "captionRaw": "siege", "caption": translate("Siege"), "yStart": 34, "width": 85 }, 94 { "captionRaw": "navy", "caption": translate("Navy"), "yStart": 34, "width": 85 }, 95 { "captionRaw": "traders", "caption": translate("Traders"), "yStart": 34, "width": 85 } 68 96 ], 69 97 "titleHeadings": [ 70 98 { … … 81 109 ], 82 110 "counters": [ 83 111 { "width": 105, "fn": calculateUnitsWithCaptured, "verticalOffset": 3 }, 84 { "width": 85, "fn": calculateUnits, "verticalOffset": 12},85 { "width": 85, "fn": calculateUnits, "verticalOffset": 12},86 { "width": 85, "fn": calculateUnits, "verticalOffset": 12},87 { "width": 85, "fn": calculateUnits, "verticalOffset": 12},88 { "width": 85, "fn": calculateUnits, "verticalOffset": 12},112 { "width": 105, "fn": calculateUnits, "verticalOffset": 3 }, 113 { "width": 105, "fn": calculateUnits, "verticalOffset": 3 }, 114 { "width": 105, "fn": calculateUnits, "verticalOffset": 3 }, 115 { "width": 105, "fn": calculateUnits, "verticalOffset": 3 }, 116 { "width": 105, "fn": calculateUnits, "verticalOffset": 3 }, 89 117 { "width": 105, "fn": calculateUnitsWithCaptured, "verticalOffset": 3 }, 90 118 { "width": 85, "fn": calculateUnits, "verticalOffset": 12 }, 91 119 { "width": 85, "fn": calculateUnits, "verticalOffset": 12 } … … 93 121 "teamCounterFn": calculateUnitsTeam 94 122 }, 95 123 "resources": { 124 "caption": translate("Resources"), 96 125 "headings": [ 97 { "caption ": translate("Player name"), "yStart": 26, "width": 200 },126 { "captionRaw": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 }, 98 127 ...g_ResourceData.GetResources().map(res => ({ 128 "captionRaw": res.name, 99 129 "caption": translateWithContext("firstWord", res.name), 100 130 "yStart": 34, 101 131 "width": 100 102 132 })), 103 { "caption ": translate("Total"), "yStart": 34, "width": 110 },133 { "captionRaw": "total", "caption": translate("Total"), "yStart": 34, "width": 110 }, 104 134 { 135 "captionRaw": "tributes", 105 136 "caption": sprintf(translate("Tributes \n(%(sent)s / %(received)s)"), 106 137 { 107 138 "sent": g_IncomeColor + translate("Sent") + '[/color]', … … 110 141 "yStart": 16, 111 142 "width": 121 112 143 }, 113 { "caption ": translate("Treasures collected"), "yStart": 16, "width": 100 },114 { "caption ": translate("Loot"), "yStart": 16, "width": 100 }144 { "captionRaw": "treasuresCollected", "caption": translate("Treasures collected"), "yStart": 16, "width": 100 }, 145 { "captionRaw": "loot", "caption": translate("Loot"), "yStart": 16, "width": 100 } 115 146 ], 116 147 "titleHeadings": [ 117 148 { … … 138 169 "teamCounterFn": calculateResourcesTeam 139 170 }, 140 171 "market": { 172 "caption": translate("Market"), 141 173 "headings": [ 142 { "caption ": translate("Player name"), "yStart": 26, "width": 200 },174 { "captionRaw": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 }, 143 175 ...g_ResourceData.GetResources().map(res => { 144 176 return { 177 "captionRaw": res.name, 145 178 "caption": 146 179 // Translation: use %(resourceWithinSentence)s if needed 147 180 sprintf(translate("%(resourceFirstWord)s exchanged"), { … … 152 185 "width": 100 153 186 }; 154 187 }), 155 { "caption ": translate("Barter efficiency"), "yStart": 16, "width": 100 },156 { "caption ": translate("Trade income"), "yStart": 16, "width": 100 }188 { "captionRaw": "barterEfficency", "caption": translate("Barter efficiency"), "yStart": 16, "width": 100 }, 189 { "captionRaw": "tradeIncome", "caption": translate("Trade income"), "yStart": 16, "width": 100 } 157 190 ], 158 191 "titleHeadings": [], 159 192 "counters": [ … … 168 201 "teamCounterFn": calculateMarketTeam 169 202 }, 170 203 "misc": { 204 "caption": translate("Miscellaneous"), 171 205 "headings": [ 172 { "caption ": translate("Player name"), "yStart": 26, "width": 200 },173 { "caption ": translate("Vegetarian\nratio"), "yStart": 16, "width": 100 },174 { "caption ": translate("Feminization"), "yStart": 16, "width": 100 },175 { "caption ": translate("Kill / Death\nratio"), "yStart": 16, "width": 100 },176 { "caption ": translate("Map\nexploration"), "yStart": 16, "width": 100 },177 { "caption ": translate("At peak"), "yStart": 34, "width": 100 },178 { "caption ": translate("At finish"), "yStart": 34, "width": 100 }206 { "captionRaw": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 }, 207 { "captionRaw": "vegetarianRatio", "caption": translate("Vegetarian\nratio"), "yStart": 16, "width": 100 }, 208 { "captionRaw": "feminization", "caption": translate("Feminization"), "yStart": 16, "width": 100 }, 209 { "captionRaw": "killDeath", "caption": translate("Kill / Death\nratio"), "yStart": 16, "width": 100 }, 210 { "captionRaw": "mapExploration", "caption": translate("Map\nexploration"), "yStart": 16, "width": 100 }, 211 { "captionRaw": "mapControlPeak", "caption": translate("At peak"), "yStart": 34, "width": 100 }, 212 { "captionRaw": "mapControlFinish", "caption": translate("At finish"), "yStart": 34, "width": 100 } 179 213 ], 180 214 "titleHeadings": [ 181 215 { "caption": translate("Map control"), "xOffset": 400, "yStart": 16, "width": 200 } -
binaries/data/mods/public/gui/summary/summary.js
35 35 var g_GameData; 36 36 var g_ResourceData = new Resources(); 37 37 38 var g_Charts = ["population", "explored"]; 39 38 40 function selectPanel(panel) 39 41 { 40 42 // TODO: move panel buttons to a custom parent object … … 47 49 48 50 adjustTabDividers(panel.size); 49 51 50 updatePanelData(g_ScorePanelsData[panel.name.substr(0, panel.name.length - "PanelButton".length)]); 52 let generalPanel = Engine.GetGUIObjectByName("generalPanel"); 53 let chartsPanel = Engine.GetGUIObjectByName("chartsPanel"); 54 if (panel.name != "chartsPanelButton") 55 { 56 generalPanel.hidden = false; 57 chartsPanel.hidden = true; 58 updatePanelData(g_ScorePanelsData[panel.name.substr(0, panel.name.length - "PanelButton".length)]); 59 } 60 else 61 { 62 generalPanel.hidden = true; 63 chartsPanel.hidden = false; 64 updateCathegoryDropdown(1); 65 updateCathegoryDropdown(2); 66 } 51 67 } 52 68 69 function initCharts() 70 { 71 let player_colors = []; 72 for (let i = 0; i < g_PlayerCount; ++i) 73 { 74 let playerState = g_GameData.sim.playerStates[i+1]; 75 player_colors.push( 76 Math.floor(playerState.color.r * 255) + " " + 77 Math.floor(playerState.color.g * 255) + " " + 78 Math.floor(playerState.color.b * 255) 79 ); 80 } 81 let chart1 = Engine.GetGUIObjectByName("chart1"); 82 chart1.series_color = player_colors; 83 let chart2 = Engine.GetGUIObjectByName("chart2"); 84 chart2.series_color = player_colors; 85 } 86 87 function transformArrays(times, values) 88 { 89 return times.map((time, index) => [time, values[index]]); 90 } 91 92 function updateCathegoryDropdown(number) 93 { 94 let chartCathegory = Engine.GetGUIObjectByName("chart" + number + "CathegorySelection"); 95 chartCathegory.list_data = Object.keys(g_ScorePanelsData); 96 chartCathegory.list = Object.keys(g_ScorePanelsData).map(panel => g_ScorePanelsData[panel].caption); 97 chartCathegory.onSelectionChange = function() { 98 if (this.list_data[this.selected]) 99 updateValueDropdown(number, this.list_data[this.selected]); 100 }; 101 chartCathegory.selected = 0; 102 //updateValueDropdown(number); 103 } 104 105 function updateValueDropdown(number, cathegory) 106 { 107 let chartValue = Engine.GetGUIObjectByName("chart" + number + "ValueSelection"); 108 let list = g_ScorePanelsData[cathegory].headings.map(heading => heading.caption); 109 list.shift(); 110 chartValue.list = list; 111 let list_data = g_ScorePanelsData[cathegory].headings.map(heading => heading.captionRaw); 112 list_data.shift(); 113 chartValue.list_data = list_data; 114 chartValue.onSelectionChange = function() { 115 if (this.list_data[this.selected]) 116 updateChart(number, cathegory, this.selected); 117 }; 118 chartValue.selected = 0; 119 } 120 121 function updateChart(number, cathegory, selected) 122 {//warn("updateChart: " + number + ", "+cathegory+", "+selected); 123 if (!g_ScorePanelsData[cathegory].counters[selected].fn) 124 return; 125 let chart = Engine.GetGUIObjectByName("chart" + number); 126 let series = []; 127 for (let j = 0; j < g_PlayerCount; ++j) 128 { 129 let playerState = g_GameData.sim.playerStates[j+1]; 130 let data = []; 131 for (let index in playerState.sequences.time) 132 data.push([playerState.sequences.time[index], g_ScorePanelsData[cathegory].counters[selected].fn(playerState, index)]); 133 series.push(data); 134 //series.push(transformArrays(playerState.sequences.time, playerState.sequences.time.map((v, i) => calculateEconomyScore(playerState, i)))); 135 //warn("series: " + JSON.stringify(series)); 136 } 137 chart.series = series; 138 } 139 140 /*function updateCharts() 141 {let panelInfo = "score"; 142 /*for (let fn of g_ScorePanelsData[panelInfo].counters) 143 { 144 let chart = Engine.GetGUIObjectByName("chart2"); 145 let series = []; 146 for (let j = 0; j < g_PlayerCount; ++j) 147 { 148 let playerState = g_GameData.sim.playerStates[j+1]; 149 series.push(transformArrays(playerState.sequences.time, playerState.sequences.time.map((v, i) => calculateEconomyScore(playerState, i)))); 150 warn("series: " + JSON.stringify(series)); 151 } 152 chart.series = series; 153 /*} 154 }*/ 155 53 156 function adjustTabDividers(tabSize) 54 157 { 55 158 let leftSpacer = Engine.GetGUIObjectByName("tabDividerLeft"); … … 143 246 144 247 let teamCounterFn = panelInfo.teamCounterFn; 145 248 if (g_Teams && teamCounterFn) 146 teamCounterFn(panelInfo.counters );249 teamCounterFn(panelInfo.counters, g_GameData.sim.playerStates[1].sequences.time.length -1); 147 250 } 148 251 149 252 function confirmStartReplay() … … 214 317 assignedState.state == "defeated" ? 215 318 translate("You have been defeated...") : 216 319 translate("You have abandoned the game."); 217 320 //warn(JSON.stringify(g_GraphData)); 218 321 initPlayerBoxPositions(); 219 322 220 323 Engine.GetGUIObjectByName("timeElapsed").caption = sprintf( … … 265 368 for (let i = 0; i < g_Teams.length; ++i) 266 369 g_WithoutTeam -= g_Teams[i] ? g_Teams[i] : 0; 267 370 } 268 371 //warn("summ: " + JSON.stringify(g_GameData.sim.playerStates[1].sequences)); 372 //warn("Length: " + g_GameData.sim.playerStates[1].sequences.time.length); 373 initCharts(); 269 374 selectPanel(Engine.GetGUIObjectByName("scorePanelButton")); 270 375 } -
binaries/data/mods/public/gui/summary/summary.xml
98 98 </object> 99 99 </object> 100 100 101 <object name="chartsPanelButton" type="button" sprite="BackgroundTab" style="TabButton" size="762 92 880 120"> 102 <action on="Press">selectPanel(this);</action> 103 <object type="text" style="ModernLabelText" ghost="true"> 104 <translatableAttribute id="caption">Charts</translatableAttribute> 105 </object> 106 </object> 107 101 108 <object name="generalPanel" type="image" sprite="ForegroundBody" size="20 120 100%-20 100%-54"> 102 109 <object size="0 0 100% 100%-50"> 103 110 <object name="playerNameHeading" type="text" style="ModernLeftTabLabelText"> … … 151 158 </repeat> 152 159 </object> 153 160 </object> 161 162 <object name="chartsPanel" type="image" sprite="ForegroundBody" size="20 120 100%-20 100%-54"> 163 <object name="chart1" 164 type="chart" 165 ghost="true" 166 size="20 80 50%-20 100%-20"/> 167 <object name="chart2" 168 type="chart" 169 ghost="true" 170 size="50%+20 80 100%-20 100%-20"/> 154 171 172 <object name="chart1CathegorySelection" 173 type="dropdown" 174 style="ModernDropDown" 175 size="20 12 170 40"> 176 <translatableAttribute id="tooltip">Cathegory</translatableAttribute> 177 </object> 178 <object name="chart2CathegorySelection" 179 type="dropdown" 180 style="ModernDropDown" 181 size="50%+20 12 50%+170 40"> 182 <translatableAttribute id="tooltip">Cathegory</translatableAttribute> 183 </object> 184 185 <object name="chart1ValueSelection" 186 type="dropdown" 187 style="ModernDropDown" 188 size="190 12 340 40"> 189 <translatableAttribute id="tooltip">Value</translatableAttribute> 190 </object> 191 <object name="chart2ValueSelection" 192 type="dropdown" 193 style="ModernDropDown" 194 size="50%+190 12 50%+340 40"> 195 <translatableAttribute id="tooltip">Value</translatableAttribute> 196 </object> 197 </object> 198 155 199 <object type="button" name="replayButton" style="ModernButtonRed" size="100%-310 100%-48 100%-170 100%-20"> 156 200 <translatableAttribute id="caption">Replay</translatableAttribute> 157 201 <action on="Press">confirmStartReplay();</action> -
binaries/data/mods/public/simulation/components/GuiInterface.js
193 193 let playerEnt = cmpPlayerManager.GetPlayerByID(i); 194 194 let cmpPlayerStatisticsTracker = Engine.QueryInterface(playerEnt, IID_StatisticsTracker); 195 195 if (cmpPlayerStatisticsTracker) 196 ret.players[i].s tatistics = cmpPlayerStatisticsTracker.GetStatistics();196 ret.players[i].sequences = cmpPlayerStatisticsTracker.GetSequences(); 197 197 } 198 198 199 199 return ret; -
binaries/data/mods/public/simulation/components/StatisticsTracker.js
1 1 function StatisticsTracker() {} 2 2 3 const UPDATE_SEQUENCE_INTERVAL = 30000; // 30 seconds 4 3 5 StatisticsTracker.prototype.Schema = 4 6 "<a:component type='system'/><empty/>"; 5 7 … … 142 144 this.lootCollected = 0; 143 145 this.peakPercentMapControlled = 0; 144 146 this.teamPeakPercentMapControlled = 0; 147 148 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 149 if (!cmpTimer) 150 return; 151 this.updateTimer = cmpTimer.SetInterval( 152 this.entity, IID_StatisticsTracker, "updateSequences", 0, UPDATE_SEQUENCE_INTERVAL); 145 153 }; 146 154 147 155 /** … … 195 203 }; 196 204 }; 197 205 206 StatisticsTracker.prototype.GetSequences = function() 207 { 208 let ret = clone(this.sequences); 209 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 210 if (!cmpTimer) 211 return; 212 213 ret.time.push(cmpTimer.GetTime() / 1000); 214 this.PushValue(this.GetStatistics(), ret); 215 return ret; 216 } 217 198 218 /** 199 219 * Increments counter associated with certain entity/counter and type of given entity. 200 220 * @param cmpIdentity The entity identity component … … 492 512 this.teamPeakPercentMapControlled = newPercent; 493 513 }; 494 514 515 StatisticsTracker.prototype.PushValue = function(fromData, toData) 516 { 517 if (typeof fromData == "object") 518 for (let prop in fromData) 519 { 520 if (typeof toData[prop] != "object") 521 { 522 toData[prop] = []; 523 toData[prop].push(fromData[prop]); 524 } 525 else 526 this.PushValue(fromData[prop], toData[prop]); 527 } 528 else 529 toData.push(fromData); 530 }; 531 532 StatisticsTracker.prototype.updateSequences = function() 533 { 534 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 535 if (!cmpTimer) 536 return; 537 //let deltaTime = (cmpTimer.GetTime() - data.startTime) / 1000; 538 539 if (!this.sequences) 540 { 541 //deltaTime = 0; 542 this.sequences = clone(this.GetStatistics()); 543 this.sequences.time = []; 544 } 545 546 this.sequences.time.push(cmpTimer.GetTime() / 1000); 547 this.PushValue(this.GetStatistics(), this.sequences); 548 } 549 495 550 Engine.RegisterComponentType(IID_StatisticsTracker, "StatisticsTracker", StatisticsTracker);