Ticket #3403: 3403_summary_graphs_v0.2.patch

File 3403_summary_graphs_v0.2.patch, 36.3 KB (added by Imarok, 7 years ago)

Here is a proposal on how to generically display all values shown in the summary

  • binaries/data/mods/public/gui/session/session.js

     
    13321332    // Serialize the statistics for each player into a comma-separated list.
    13331333    // Ignore gaia
    13341334    for (let i = 1; i < extendedSimState.players.length; ++i)
    1335     {
     1335    {TODO
    13361336        let player = extendedSimState.players[i];
    13371337
    13381338        playerStates += player.state + ",";
  • binaries/data/mods/public/gui/summary/counters.js

     
    1 var g_TeamHelperData = [];
     1var g_TeamHelperData = {};
    22
    33function resetDataHelpers()
    44{
    5     g_TeamHelperData = [];
     5    g_TeamHelperData = {};
    66}
    77
    88function formatTrained(trained, killed, lost)
     
    6161
    6262function updateCountersPlayer(playerState, counters, idGUI)
    6363{
     64    let index = playerState.sequences.time.length - 1;
    6465    for (let w in counters)
    6566    {
    6667        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);
    6869    }
    6970}
    70 
     71function 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}
    7177// Updates g_TeamHelperData by appending some data from playerState
    7278function calculateTeamCounters(playerState)
    7379{
    7480    if (!g_TeamHelperData[playerState.team])
    7581        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": 0
     82            "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)
    8793        };
     94//warn("teamHelper: " + JSON.stringify(g_TeamHelperData));
    8895
    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);
    9198
    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);
    94101
    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);
    97104
    98     g_TeamHelperData[playerState.team].percentMapControlled = playerState.statistics.teamPercentMapControlled;
    99     g_TeamHelperData[playerState.team].peakPercentMapControlled = playerState.statistics.teamPeakPercentMapControlled;
     105    g_TeamHelperData[playerState.team].percentMapControlled = playerState.sequences.teamPercentMapControlled;
     106    g_TeamHelperData[playerState.team].peakPercentMapControlled = playerState.sequences.teamPeakPercentMapControlled;
    100107
    101     g_TeamHelperData[playerState.team].percentMapExplored = playerState.statistics.teamPercentMapExplored;
     108    g_TeamHelperData[playerState.team].percentMapExplored = playerState.sequences.teamPercentMapExplored;
    102109
    103     for (let type in playerState.statistics.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]);
    105112
    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));
    108116}
    109117
    110 function calculateEconomyScore(playerState)
     118function calculateEconomyScore(playerState, index)
    111119{
    112120    let total = 0;
    113     for (let type in playerState.statistics.resourcesGathered)
    114         total += playerState.statistics.resourcesGathered[type];
     121    for (let type in playerState.sequences.resourcesGathered)
     122        total += playerState.sequences.resourcesGathered[type][index];
    115123
    116124    return Math.round(total / 10);
    117125}
    118126
    119 function calculateMilitaryScore(playerState)
     127function calculateMilitaryScore(playerState, index)
    120128{
    121     return Math.round((playerState.statistics.enemyUnitsKilledValue +
    122         playerState.statistics.enemyBuildingsDestroyedValue +
    123         playerState.statistics.buildingsCapturedValue) / 10);
     129    return Math.round((playerState.sequences.enemyUnitsKilledValue[index] +
     130        playerState.sequences.enemyBuildingsDestroyedValue[index] +
     131        playerState.sequences.buildingsCapturedValue[index]) / 10);
    124132}
    125133
    126 function calculateExplorationScore(playerState)
     134function calculateExplorationScore(playerState, index)
    127135{
    128     return playerState.statistics.percentMapExplored * 10;
     136    return playerState.sequences.percentMapExplored[index] * 10;
    129137}
    130138
    131 function calculateScoreTotal(playerState)
     139function calculateScoreTotal(playerState, index)
    132140{
    133     return calculateEconomyScore(playerState) +
    134         calculateMilitaryScore(playerState) +
    135         calculateExplorationScore(playerState);
     141    return calculateEconomyScore(playerState, index) +
     142        calculateMilitaryScore(playerState, index) +
     143        calculateExplorationScore(playerState, index);
    136144}
    137145
    138 function calculateScoreTeam(counters)
     146function calculateScoreTeam(counters, index)
    139147{
    140148    for (let t in g_Teams)
    141149    {
     
    148156            let total = 0;
    149157
    150158            if (w == 2) // Team exploration score (not additive)
    151                 total = g_TeamHelperData[t].percentMapExplored * 10;
     159                total = g_TeamHelperData[t].percentMapExplored[index] * 10;
    152160            else
    153161                for (let p = 0; p < g_Teams[t]; ++p)
    154162                    total += +Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + p + "][" + w + "]").caption;
     
    164172    }
    165173}
    166174
    167 function calculateBuildings(playerState, position)
     175function calculateBuildings(playerState, index, position)
    168176{
    169177    let type = g_BuildingsTypes[position];
    170178    return formatCaptured(
    171         playerState.statistics.buildingsConstructed[type],
    172         playerState.statistics.enemyBuildingsDestroyed[type],
    173         playerState.statistics.buildingsCaptured[type],
    174         playerState.statistics.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]);
    175183}
    176184
    177 function calculateBuildingsTeam(counters)
     185function calculateBuildingsTeam(counters, index)
    178186{
    179187    for (let t in g_Teams)
    180188    {
     
    208216    }
    209217}
    210218
    211 function calculateUnitsTeam(counters)
     219function calculateUnitsTeam(counters, index)
    212220{
    213221    for (let t in g_Teams)
    214222    {
     
    259267    }
    260268}
    261269
    262 function calculateUnitsWithCaptured(playerState, position)
     270function calculateUnitsWithCaptured(playerState, index, position)
    263271{
    264272    let type = g_UnitsTypes[position];
    265273
    266274    return formatCaptured(
    267         playerState.statistics.unitsTrained[type],
    268         playerState.statistics.enemyUnitsKilled[type],
    269         playerState.statistics.unitsCaptured[type],
    270         playerState.statistics.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]);
    271279}
    272280
    273 function calculateUnits(playerState, position)
     281function calculateUnits(playerState, index, position)
    274282{
    275283    let type = g_UnitsTypes[position];
    276284
    277285    return formatTrained(
    278         playerState.statistics.unitsTrained[type],
    279         playerState.statistics.enemyUnitsKilled[type],
    280         playerState.statistics.unitsLost[type]);
     286        playerState.sequences.unitsTrained[type][index],
     287        playerState.sequences.enemyUnitsKilled[type][index],
     288        playerState.sequences.unitsLost[type][index]);
    281289}
    282290
    283 function calculateResources(playerState, position)
     291function calculateResources(playerState, index, position)
    284292{
    285293    let type = g_ResourceData.GetCodes()[position];
    286294
    287295    return formatIncome(
    288         playerState.statistics.resourcesGathered[type],
    289         playerState.statistics.resourcesUsed[type] - playerState.statistics.resourcesSold[type]);
     296        playerState.sequences.resourcesGathered[type][index],
     297        playerState.sequences.resourcesUsed[type][index] - playerState.sequences.resourcesSold[type][index]);
    290298}
    291299
    292 function calculateTotalResources(playerState)
     300function calculateTotalResources(playerState, index)
    293301{
    294302    let totalGathered = 0;
    295303    let totalUsed = 0;
     
    296304
    297305    for (let type of g_ResourceData.GetCodes())
    298306    {
    299         totalGathered += playerState.statistics.resourcesGathered[type];
    300         totalUsed += playerState.statistics.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];
    301309    }
    302310
    303311    return formatIncome(totalGathered, totalUsed);
    304312}
    305313
    306 function calculateTreasureCollected(playerState)
     314function calculateTreasureCollected(playerState, index)
    307315{
    308     return playerState.statistics.treasuresCollected;
     316    return playerState.sequences.treasuresCollected[index];
    309317}
    310318
    311 function calculateLootCollected(playerState)
     319function calculateLootCollected(playerState, index)
    312320{
    313     return playerState.statistics.lootCollected;
     321    return playerState.sequences.lootCollected[index];
    314322}
    315323
    316 function calculateTributeSent(playerState)
     324function calculateTributeSent(playerState, index)
    317325{
    318326    return formatIncome(
    319         playerState.statistics.tributesSent,
    320         playerState.statistics.tributesReceived);
     327        playerState.sequences.tributesSent[index],
     328        playerState.sequences.tributesReceived[index]);
    321329}
    322330
    323 function calculateResourcesTeam(counters)
     331function calculateResourcesTeam(counters, index)
    324332{
    325333    for (let t in g_Teams)
    326334    {
     
    360368    }
    361369}
    362370
    363 function calculateResourceExchanged(playerState, position)
     371function calculateResourceExchanged(playerState, index, position)
    364372{
    365373    let type = g_ResourceData.GetCodes()[position];
    366374
    367375    return formatIncome(
    368         playerState.statistics.resourcesBought[type],
    369         playerState.statistics.resourcesSold[type]);
     376        playerState.sequences.resourcesBought[type][index],
     377        playerState.sequences.resourcesSold[type][index]);
    370378}
    371379
    372 function calculateBarterEfficiency(playerState)
     380function calculateBarterEfficiency(playerState, index)
    373381{
    374382    let totalBought = 0;
    375383    let totalSold = 0;
    376384
    377     for (let type in playerState.statistics.resourcesBought)
    378         totalBought += playerState.statistics.resourcesBought[type];
     385    for (let type in playerState.sequences.resourcesBought)
     386        totalBought += playerState.sequences.resourcesBought[type][index];
    379387
    380     for (let type in playerState.statistics.resourcesSold)
    381         totalSold += playerState.statistics.resourcesSold[type];
     388    for (let type in playerState.sequences.resourcesSold)
     389        totalSold += playerState.sequences.resourcesSold[type][index];
    382390
    383391    return formatPercent(totalBought, totalSold);
    384392}
    385393
    386 function calculateTradeIncome(playerState)
     394function calculateTradeIncome(playerState, index)
    387395{
    388     return playerState.statistics.tradeIncome;
     396    return playerState.sequences.tradeIncome[index];
    389397}
    390398
    391 function calculateMarketTeam(counters)
     399function calculateMarketTeam(counters, index)
    392400{
    393401    for (let t in g_Teams)
    394402    {
     
    418426
    419427            let teamTotal;
    420428            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]);
    422430            else if (w > 4)
    423431                teamTotal = total.income;
    424432            else
     
    429437    }
    430438}
    431439
    432 function calculateVegetarianRatio(playerState)
     440function calculateVegetarianRatio(playerState, index)
    433441{
    434442    return formatPercent(
    435         playerState.statistics.resourcesGathered.vegetarianFood,
    436         playerState.statistics.resourcesGathered.food);
     443        playerState.sequences.resourcesGathered.vegetarianFood[index],
     444        playerState.sequences.resourcesGathered.food[index]);
    437445}
    438446
    439 function calculateFeminization(playerState)
     447function calculateFeminization(playerState, index)
    440448{
    441449    return formatPercent(
    442         playerState.statistics.unitsTrained.Female,
    443         playerState.statistics.unitsTrained.Worker);
     450        playerState.sequences.unitsTrained.Female[index],
     451        playerState.sequences.unitsTrained.Worker[index]);
    444452}
    445453
    446 function calculateKillDeathRatio(playerState)
     454function calculateKillDeathRatio(playerState, index)
    447455{
    448456    return formatRatio(
    449         playerState.statistics.enemyUnitsKilled.total,
    450         playerState.statistics.unitsLost.total);
     457        playerState.sequences.enemyUnitsKilled.total[index],
     458        playerState.sequences.unitsLost.total[index]);
    451459}
    452460
    453 function calculateMapExploration(playerState)
     461function calculateMapExploration(playerState, index)
    454462{
    455     return playerState.statistics.percentMapExplored + "%";
     463    return playerState.sequences.percentMapExplored[index] + "%";
    456464}
    457465
    458 function calculateMapFinalControl(playerState)
     466function calculateMapFinalControl(playerState, index)
    459467{
    460     return playerState.statistics.percentMapControlled + "%";
     468    return playerState.sequences.percentMapControlled[index] + "%";
    461469}
    462470
    463 function calculateMapPeakControl(playerState)
     471function calculateMapPeakControl(playerState, index)
    464472{
    465     return playerState.statistics.peakPercentMapControlled + "%";
     473    return playerState.sequences.peakPercentMapControlled[index] + "%";
    466474}
    467475
    468 function calculateMiscellaneous(counters)
     476function calculateMiscellaneous(counters, index)
    469477{
    470478    for (let t in g_Teams)
    471479    {
     
    477485            let teamTotal;
    478486
    479487            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]);
    481489            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]);
    483491            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]);
    485493            else if (w == 3)
    486                 teamTotal = g_TeamHelperData[t].percentMapExplored + "%";
     494                teamTotal = g_TeamHelperData[t].percentMapExplored[index] + "%";
    487495            else if (w == 4)
    488                 teamTotal = g_TeamHelperData[t].peakPercentMapControlled + "%";
     496                teamTotal = g_TeamHelperData[t].peakPercentMapControlled[index] + "%";
    489497            else if (w == 5)
    490                 teamTotal = g_TeamHelperData[t].percentMapControlled + "%";
     498                teamTotal = g_TeamHelperData[t].percentMapControlled[index] + "%";
    491499
    492500            Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = teamTotal;
    493501        }
  • 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
    126var g_ScorePanelsData = {
    227    "score": {
     28        "caption": translate("Score"),
    329        "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 }
    935        ],
    1036        "titleHeadings": [],
    1137        "counters": [
     
    1743        "teamCounterFn": calculateScoreTeam
    1844    },
    1945    "buildings": {
     46        "caption": translate("Buildings"),
    2047        "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 }
    3057        ],
    3158        "titleHeadings": [
    3259            {
     
    5481        "teamCounterFn": calculateBuildingsTeam
    5582    },
    5683    "units": {
     84        "caption": translate("Units"),
    5785        "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 }
    6896        ],
    6997        "titleHeadings": [
    7098            {
     
    81109        ],
    82110        "counters": [
    83111            { "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 },
    89117            { "width": 105, "fn": calculateUnitsWithCaptured, "verticalOffset": 3 },
    90118            { "width": 85, "fn": calculateUnits, "verticalOffset": 12 },
    91119            { "width": 85, "fn": calculateUnits, "verticalOffset": 12 }
     
    93121        "teamCounterFn": calculateUnitsTeam
    94122    },
    95123    "resources": {
     124        "caption": translate("Resources"),
    96125        "headings": [
    97             { "caption": translate("Player name"), "yStart": 26, "width": 200 },
     126            { "captionRaw": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 },
    98127            ...g_ResourceData.GetResources().map(res => ({
     128                "captionRaw": res.name,
    99129                "caption": translateWithContext("firstWord", res.name),
    100130                "yStart": 34,
    101131                "width": 100
    102132            })),
    103             { "caption": translate("Total"), "yStart": 34, "width": 110 },
     133            { "captionRaw": "total", "caption": translate("Total"), "yStart": 34, "width": 110 },
    104134            {
     135                "captionRaw": "tributes",
    105136                "caption": sprintf(translate("Tributes \n(%(sent)s / %(received)s)"),
    106137                    {
    107138                        "sent": g_IncomeColor + translate("Sent") + '[/color]',
     
    110141                "yStart": 16,
    111142                "width": 121
    112143            },
    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 }
    115146        ],
    116147        "titleHeadings": [
    117148            {
     
    138169        "teamCounterFn": calculateResourcesTeam
    139170    },
    140171    "market": {
     172        "caption": translate("Market"),
    141173        "headings": [
    142             { "caption": translate("Player name"), "yStart": 26, "width": 200 },
     174            { "captionRaw": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 },
    143175            ...g_ResourceData.GetResources().map(res => {
    144176                return {
     177                    "captionRaw": res.name,
    145178                    "caption":
    146179                        // Translation: use %(resourceWithinSentence)s if needed
    147180                        sprintf(translate("%(resourceFirstWord)s exchanged"), {
     
    152185                    "width": 100
    153186                };
    154187            }),
    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 }
    157190        ],
    158191        "titleHeadings": [],
    159192        "counters": [
     
    168201        "teamCounterFn": calculateMarketTeam
    169202    },
    170203    "misc": {
     204        "caption": translate("Miscellaneous"),
    171205        "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 }
    179213        ],
    180214        "titleHeadings": [
    181215            { "caption": translate("Map control"), "xOffset": 400, "yStart": 16, "width": 200 }
  • binaries/data/mods/public/gui/summary/summary.js

     
    3535var g_GameData;
    3636var g_ResourceData = new Resources();
    3737
     38var g_Charts = ["population", "explored"];
     39
    3840function selectPanel(panel)
    3941{
    4042    // TODO: move panel buttons to a custom parent object
     
    4749
    4850    adjustTabDividers(panel.size);
    4951
    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    }
    5167}
    5268
     69function 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
     87function transformArrays(times, values)
     88{
     89    return times.map((time, index) => [time, values[index]]);
     90}
     91
     92function 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
     105function 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
     121function 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
    53156function adjustTabDividers(tabSize)
    54157{
    55158    let leftSpacer = Engine.GetGUIObjectByName("tabDividerLeft");
     
    143246
    144247    let teamCounterFn = panelInfo.teamCounterFn;
    145248    if (g_Teams && teamCounterFn)
    146         teamCounterFn(panelInfo.counters);
     249        teamCounterFn(panelInfo.counters, g_GameData.sim.playerStates[1].sequences.time.length -1);
    147250}
    148251
    149252function confirmStartReplay()
     
    214317        assignedState.state == "defeated" ?
    215318            translate("You have been defeated...") :
    216319            translate("You have abandoned the game.");
    217 
     320//warn(JSON.stringify(g_GraphData));
    218321    initPlayerBoxPositions();
    219322
    220323    Engine.GetGUIObjectByName("timeElapsed").caption = sprintf(
     
    265368        for (let i = 0; i < g_Teams.length; ++i)
    266369            g_WithoutTeam -= g_Teams[i] ? g_Teams[i] : 0;
    267370    }
    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();
    269374    selectPanel(Engine.GetGUIObjectByName("scorePanelButton"));
    270375}
  • binaries/data/mods/public/gui/summary/summary.xml

     
    9898            </object>
    9999        </object>
    100100
     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
    101108        <object name="generalPanel" type="image" sprite="ForegroundBody" size="20 120 100%-20 100%-54">
    102109            <object size="0 0 100% 100%-50">
    103110                <object name="playerNameHeading" type="text" style="ModernLeftTabLabelText">
     
    151158                </repeat>
    152159            </object>
    153160        </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"/>
    154171
     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
    155199        <object type="button" name="replayButton" style="ModernButtonRed" size="100%-310 100%-48 100%-170 100%-20">
    156200            <translatableAttribute id="caption">Replay</translatableAttribute>
    157201            <action on="Press">confirmStartReplay();</action>
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    193193        let playerEnt = cmpPlayerManager.GetPlayerByID(i);
    194194        let cmpPlayerStatisticsTracker = Engine.QueryInterface(playerEnt, IID_StatisticsTracker);
    195195        if (cmpPlayerStatisticsTracker)
    196             ret.players[i].statistics = cmpPlayerStatisticsTracker.GetStatistics();
     196            ret.players[i].sequences = cmpPlayerStatisticsTracker.GetSequences();
    197197    }
    198198
    199199    return ret;
  • binaries/data/mods/public/simulation/components/StatisticsTracker.js

     
    11function StatisticsTracker() {}
    22
     3const UPDATE_SEQUENCE_INTERVAL = 30000; // 30 seconds
     4
    35StatisticsTracker.prototype.Schema =
    46    "<a:component type='system'/><empty/>";
    57
     
    142144    this.lootCollected = 0;
    143145    this.peakPercentMapControlled = 0;
    144146    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);
    145153};
    146154
    147155/**
     
    195203    };
    196204};
    197205
     206StatisticsTracker.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
    198218/**
    199219 * Increments counter associated with certain entity/counter and type of given entity.
    200220 * @param cmpIdentity The entity identity component
     
    492512        this.teamPeakPercentMapControlled = newPercent;
    493513};
    494514
     515StatisticsTracker.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
     532StatisticsTracker.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
    495550Engine.RegisterComponentType(IID_StatisticsTracker, "StatisticsTracker", StatisticsTracker);