Index: binaries/data/mods/public/gui/session/session.js
===================================================================
--- binaries/data/mods/public/gui/session/session.js
+++ binaries/data/mods/public/gui/session/session.js
@@ -1449,6 +1449,16 @@
"resourcesBought"
];
+ let misc = [
+ "tradeIncome",
+ "tributesSent",
+ "tributesReceived",
+ "treasuresCollected",
+ "lootCollected",
+ "feminisation",
+ "percentMapExplored"
+ ];
+
let playerStatistics = {};
// Unit Stats
@@ -1483,19 +1493,13 @@
}
playerStatistics.resourcesGathered.vegetarianFood = "";
- playerStatistics.tradeIncome = "";
- // Tribute
- playerStatistics.tributesSent = "";
- playerStatistics.tributesReceived = "";
+ for (let type of misc)
+ playerStatistics[type] = "";
+
// Total
playerStatistics.economyScore = "";
playerStatistics.militaryScore = "";
playerStatistics.totalScore = "";
- // Various
- playerStatistics.treasuresCollected = "";
- playerStatistics.lootCollected = "";
- playerStatistics.feminisation = "";
- playerStatistics.percentMapExplored = "";
let mapName = g_GameAttributes.settings.Name;
let playerStates = "";
@@ -1508,6 +1512,7 @@
for (let i = 1; i < extendedSimState.players.length; ++i)
{
let player = extendedSimState.players[i];
+ let maxIndex = player.sequences.time.length - 1;
playerStates += player.state + ",";
playerCivs += player.civ + ",";
@@ -1515,31 +1520,28 @@
teamsLocked = teamsLocked && player.teamsLocked;
for (let resourcesCounterType of resourcesCounterTypes)
for (let resourcesType of resourcesTypes)
- playerStatistics[resourcesCounterType][resourcesType] += player.statistics[resourcesCounterType][resourcesType] + ",";
- playerStatistics.resourcesGathered.vegetarianFood += player.statistics.resourcesGathered.vegetarianFood + ",";
+ playerStatistics[resourcesCounterType][resourcesType] += player.sequences[resourcesCounterType][resourcesType][maxIndex] + ",";
+ playerStatistics.resourcesGathered.vegetarianFood += player.sequences.resourcesGathered.vegetarianFood[maxIndex] + ",";
for (let unitCounterType of unitsCountersTypes)
for (let unitsClass of unitsClasses)
- playerStatistics[unitCounterType][unitsClass] += player.statistics[unitCounterType][unitsClass] + ",";
+ playerStatistics[unitCounterType][unitsClass] += player.sequences[unitCounterType][unitsClass][maxIndex] + ",";
for (let buildingCounterType of buildingsCountersTypes)
for (let buildingsClass of buildingsClasses)
- playerStatistics[buildingCounterType][buildingsClass] += player.statistics[buildingCounterType][buildingsClass] + ",";
+ playerStatistics[buildingCounterType][buildingsClass] += player.sequences[buildingCounterType][buildingsClass][maxIndex] + ",";
let total = 0;
- for (let type in player.statistics.resourcesGathered)
- total += player.statistics.resourcesGathered[type];
+ for (let type in player.sequences.resourcesGathered)
+ total += player.sequences.resourcesGathered[type][maxIndex];
playerStatistics.economyScore += total + ",";
- playerStatistics.militaryScore += Math.round((player.statistics.enemyUnitsKilledValue +
- player.statistics.enemyBuildingsDestroyedValue) / 10) + ",";
- playerStatistics.totalScore += (total + Math.round((player.statistics.enemyUnitsKilledValue +
- player.statistics.enemyBuildingsDestroyedValue) / 10)) + ",";
- playerStatistics.tradeIncome += player.statistics.tradeIncome + ",";
- playerStatistics.tributesSent += player.statistics.tributesSent + ",";
- playerStatistics.tributesReceived += player.statistics.tributesReceived + ",";
- playerStatistics.percentMapExplored += player.statistics.percentMapExplored + ",";
- playerStatistics.treasuresCollected += player.statistics.treasuresCollected + ",";
- playerStatistics.lootCollected += player.statistics.lootCollected + ",";
+ playerStatistics.militaryScore += Math.round((player.sequences.enemyUnitsKilledValue[maxIndex] +
+ player.sequences.enemyBuildingsDestroyedValue[maxIndex]) / 10) + ",";
+ playerStatistics.totalScore += (total + Math.round((player.sequences.enemyUnitsKilledValue[maxIndex] +
+ player.sequences.enemyBuildingsDestroyedValue[maxIndex]) / 10)) + ",";
+
+ for (let type of misc)
+ playerStatistics[type] += player.sequences[type][maxIndex] + ",";
}
// Send the report with serialized data
@@ -1577,12 +1579,8 @@
reportObject[(type.substr(0,1)).toLowerCase()+type.substr(1)+"BuildingsLost"] = playerStatistics.buildingsLost[type];
reportObject["enemy"+type+"BuildingsDestroyed"] = playerStatistics.enemyBuildingsDestroyed[type];
}
- reportObject.tributesSent = playerStatistics.tributesSent;
- reportObject.tributesReceived = playerStatistics.tributesReceived;
- reportObject.percentMapExplored = playerStatistics.percentMapExplored;
- reportObject.treasuresCollected = playerStatistics.treasuresCollected;
- reportObject.lootCollected = playerStatistics.lootCollected;
- reportObject.tradeIncome = playerStatistics.tradeIncome;
+ for (let type of misc)
+ reportObject[type] = playerStatistics[type];
Engine.SendGameReport(reportObject);
}
Index: binaries/data/mods/public/gui/summary/counters.js
===================================================================
--- binaries/data/mods/public/gui/summary/counters.js
+++ binaries/data/mods/public/gui/summary/counters.js
@@ -5,44 +5,25 @@
g_TeamHelperData = [];
}
-function formatTrained(trained, killed, lost)
+function calculatePercent(divident, divisor)
{
- return g_TrainedColor + trained + '[/color] / ' +
- g_KilledColor + killed + '[/color] / ' +
- g_LostColor + lost + '[/color]';
+ return { "percent": divisor ? Math.floor(100 * divident / divisor) : 0 };
}
-function formatCaptured(constructed, destroyed, captured, lost)
+function calculateRatio(divident, divisor)
{
- return g_TrainedColor + constructed + '[/color] / ' +
- g_KilledColor + destroyed + '[/color]\n' +
- g_CapturedColor + captured + '[/color] / ' +
- g_LostColor + lost + '[/color]\n';
+ return divident ? +((divident / divisor).toFixed(2)) : 0;
}
-function formatIncome(income, outcome)
+function formatSummaryValue(values)
{
- return g_IncomeColor + income + '[/color] / ' +
- g_OutcomeColor + outcome + '[/color]';
-}
-
-function formatPercent(divident, divisor)
-{
- if (!divisor)
- return "0%";
+ if (typeof values != "object")
+ return values === Infinity ? g_InfinitySymbol : values;
- return Math.floor(100 * divident / divisor) + "%";
-}
-
-function formatRatio(divident, divisor)
-{
- if (!divident)
- return "0.00";
-
- if (!divisor)
- return g_InfiniteSymbol;
-
- return Math.round(divident / divisor * 100) / 100;
+ let ret = "";
+ for (let type in values)
+ ret += g_SummaryTypes[type].color + values[type] + g_SummaryTypes[type].postfix;
+ return ret;
}
/**
@@ -59,83 +40,90 @@
return caption.replace(/\[([\w\' \\\"\/\=]*)\]|[\t\r \f]/g, "");
}
-function updateCountersPlayer(playerState, counters, idGUI)
+function updateCountersPlayer(playerState, counters, headings, idGUI)
{
+ let index = playerState.sequences.time.length - 1;
for (let w in counters)
{
let fn = counters[w].fn;
- Engine.GetGUIObjectByName(idGUI + "[" + w + "]").caption = fn && fn(playerState, w);
+ Engine.GetGUIObjectByName(idGUI + "[" + w + "]").caption = formatSummaryValue(fn && fn(playerState, index, headings[+w+1].identifier));
}
}
+/**
+ * Add two arrays element-wise. So addArray([1,2],[7,42]) will result in [8,44].
+ *
+ * @param {Array} array1 - first summand array.
+ * @param {Array} array2 - second summand array.
+ * @returns {Array} the element-wise sum of array1 and array2.
+ */
+function addArray(array1, array2)
+{
+ array1 = array1.map((value, index) => value + array2[index]);
+}
+
// Updates g_TeamHelperData by appending some data from playerState
function calculateTeamCounters(playerState)
{
if (!g_TeamHelperData[playerState.team])
- g_TeamHelperData[playerState.team] = {
- "food": 0,
- "vegetarianFood": 0,
- "femaleCitizen": 0,
- "worker": 0,
- "enemyUnitsKilled": 0,
- "unitsLost": 0,
- "percentMapControlled": 0,
- "peakPercentMapControlled": 0,
- "percentMapExplored": 0,
- "totalBought": 0,
- "totalSold": 0
- };
-
- g_TeamHelperData[playerState.team].food += playerState.statistics.resourcesGathered.food;
- g_TeamHelperData[playerState.team].vegetarianFood += playerState.statistics.resourcesGathered.vegetarianFood;
-
- g_TeamHelperData[playerState.team].femaleCitizen += playerState.statistics.unitsTrained.FemaleCitizen;
- g_TeamHelperData[playerState.team].worker += playerState.statistics.unitsTrained.Worker;
-
- g_TeamHelperData[playerState.team].enemyUnitsKilled += playerState.statistics.enemyUnitsKilled.total;
- g_TeamHelperData[playerState.team].unitsLost += playerState.statistics.unitsLost.total;
-
- g_TeamHelperData[playerState.team].percentMapControlled = playerState.statistics.teamPercentMapControlled;
- g_TeamHelperData[playerState.team].peakPercentMapControlled = playerState.statistics.teamPeakPercentMapControlled;
-
- g_TeamHelperData[playerState.team].percentMapExplored = playerState.statistics.teamPercentMapExplored;
+ {
+ g_TeamHelperData[playerState.team] = {};
+ for (let value of ["food", "vegetarianFood", "femaleCitizen", "worker", "enemyUnitsKilled",
+ "unitsLost", "percentMapControlled", "peakPercentMapControlled",
+ "percentMapExplored", "totalBought", "totalSold"])
+ g_TeamHelperData[playerState.team][value] = new Array(playerState.sequences.time.length).fill(0);
+ }
+
+ addArray(g_TeamHelperData[playerState.team].food, playerState.sequences.resourcesGathered.food);
+ addArray(g_TeamHelperData[playerState.team].vegetarianFood, playerState.sequences.resourcesGathered.vegetarianFood);
+
+ addArray(g_TeamHelperData[playerState.team].femaleCitizen, playerState.sequences.unitsTrained.FemaleCitizen);
+ addArray(g_TeamHelperData[playerState.team].worker, playerState.sequences.unitsTrained.Worker);
- for (let type in playerState.statistics.resourcesBought)
- g_TeamHelperData[playerState.team].totalBought += playerState.statistics.resourcesBought[type];
+ addArray(g_TeamHelperData[playerState.team].enemyUnitsKilled, playerState.sequences.enemyUnitsKilled.total);
+ addArray(g_TeamHelperData[playerState.team].unitsLost, playerState.sequences.unitsLost.total);
- for (let type in playerState.statistics.resourcesSold)
- g_TeamHelperData[playerState.team].totalSold += playerState.statistics.resourcesSold[type];
+ g_TeamHelperData[playerState.team].percentMapControlled = playerState.sequences.teamPercentMapControlled;
+ g_TeamHelperData[playerState.team].peakPercentMapControlled = playerState.sequences.teamPeakPercentMapControlled;
+
+ g_TeamHelperData[playerState.team].percentMapExplored = playerState.sequences.teamPercentMapExplored;
+
+ for (let type in playerState.sequences.resourcesBought)
+ addArray(g_TeamHelperData[playerState.team].totalBought, playerState.sequences.resourcesBought[type]);
+
+ for (let type in playerState.sequences.resourcesSold)
+ addArray(g_TeamHelperData[playerState.team].totalSold, playerState.sequences.resourcesSold[type]);
}
-function calculateEconomyScore(playerState)
+function calculateEconomyScore(playerState, index)
{
let total = 0;
- for (let type in playerState.statistics.resourcesGathered)
- total += playerState.statistics.resourcesGathered[type];
+ for (let type in playerState.sequences.resourcesGathered)
+ total += playerState.sequences.resourcesGathered[type][index];
return Math.round(total / 10);
}
-function calculateMilitaryScore(playerState)
+function calculateMilitaryScore(playerState, index)
{
- return Math.round((playerState.statistics.enemyUnitsKilledValue +
- playerState.statistics.enemyBuildingsDestroyedValue +
- playerState.statistics.buildingsCapturedValue) / 10);
+ return Math.round((playerState.sequences.enemyUnitsKilledValue[index] +
+ playerState.sequences.enemyBuildingsDestroyedValue[index] +
+ playerState.sequences.buildingsCapturedValue[index]) / 10);
}
-function calculateExplorationScore(playerState)
+function calculateExplorationScore(playerState, index)
{
- return playerState.statistics.percentMapExplored * 10;
+ return playerState.sequences.percentMapExplored[index] * 10;
}
-function calculateScoreTotal(playerState)
+function calculateScoreTotal(playerState, index)
{
- return calculateEconomyScore(playerState) +
- calculateMilitaryScore(playerState) +
- calculateExplorationScore(playerState);
+ return calculateEconomyScore(playerState, index) +
+ calculateMilitaryScore(playerState, index) +
+ calculateExplorationScore(playerState, index);
}
-function calculateScoreTeam(counters)
+function calculateScoreTeam(counters, index)
{
for (let t in g_Teams)
{
@@ -148,7 +136,7 @@
let total = 0;
if (w == 2) // Team exploration score (not additive)
- total = g_TeamHelperData[t].percentMapExplored * 10;
+ total = g_TeamHelperData[t].percentMapExplored[index] * 10;
else
for (let p = 0; p < g_Teams[t]; ++p)
total += +Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + p + "][" + w + "]").caption;
@@ -164,17 +152,17 @@
}
}
-function calculateBuildings(playerState, position)
+function calculateBuildings(playerState, index, type)
{
- let type = g_BuildingsTypes[position];
- return formatCaptured(
- playerState.statistics.buildingsConstructed[type],
- playerState.statistics.enemyBuildingsDestroyed[type],
- playerState.statistics.buildingsCaptured[type],
- playerState.statistics.buildingsLost[type]);
+ return {
+ "constructed": playerState.sequences.buildingsConstructed[type][index],
+ "destroyed": playerState.sequences.enemyBuildingsDestroyed[type][index],
+ "captured": playerState.sequences.buildingsCaptured[type][index],
+ "lost": playerState.sequences.buildingsLost[type][index]
+ };
}
-function calculateBuildingsTeam(counters)
+function calculateBuildingsTeam(counters, index)
{
for (let t in g_Teams)
{
@@ -203,12 +191,12 @@
}
Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption =
- formatCaptured(total.constructed, total.destroyed, total.captured, total.lost);
+ formatSummaryValue(total);
}
}
}
-function calculateUnitsTeam(counters)
+function calculateUnitsTeam(counters, index)
{
for (let t in g_Teams)
{
@@ -227,100 +215,89 @@
for (let p = 0; p < g_Teams[t]; ++p)
{
+ let splitCaption = cleanGUICaption(t, p, w, false).split("\n");
+ let first = splitCaption[0].split("/");
+ total.trained += +first[0];
+ total.killed += +first[1];
+
if (w == 0 || w == 6)
{
- let splitCaption = cleanGUICaption(t, p, w, false).split("\n");
- let first = splitCaption[0].split("/");
let second = splitCaption[1].split("/");
-
- total.trained += +first[0];
- total.killed += +first[1];
total.captured += +second[0];
total.lost += +second[1];
}
else
- {
- let splitCaption = cleanGUICaption(t, p, w).split("/");
- total.trained += +splitCaption[0];
- total.killed += +splitCaption[1];
- total.lost += +splitCaption[2];
- }
+ total.lost += +splitCaption[1];
}
- let formattedCaption = "";
-
- if (w == 0 || w == 6)
- formattedCaption = formatCaptured(total.trained, total.killed, total.captured, total.lost);
- else
- formattedCaption = formatTrained(total.trained, total.killed, total.lost);
+ if (w != 0 && w != 6)
+ delete total.captured;
- Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = formattedCaption;
+ Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = formatSummaryValue(total);
}
}
}
-function calculateUnitsWithCaptured(playerState, position)
+function calculateUnitsWithCaptured(playerState, index, type)
{
- let type = g_UnitsTypes[position];
-
- return formatCaptured(
- playerState.statistics.unitsTrained[type],
- playerState.statistics.enemyUnitsKilled[type],
- playerState.statistics.unitsCaptured[type],
- playerState.statistics.unitsLost[type]);
+ return {
+ "trained": playerState.sequences.unitsTrained[type][index],
+ "killed": playerState.sequences.enemyUnitsKilled[type][index],
+ "captured": playerState.sequences.unitsCaptured[type][index],
+ "lost": playerState.sequences.unitsLost[type][index]
+ };
}
-function calculateUnits(playerState, position)
+function calculateUnits(playerState, index, type)
{
- let type = g_UnitsTypes[position];
-
- return formatTrained(
- playerState.statistics.unitsTrained[type],
- playerState.statistics.enemyUnitsKilled[type],
- playerState.statistics.unitsLost[type]);
+ return {
+ "trained": playerState.sequences.unitsTrained[type][index],
+ "killed": playerState.sequences.enemyUnitsKilled[type][index],
+ "lost": playerState.sequences.unitsLost[type][index]
+ };
}
-function calculateResources(playerState, position)
+function calculateResources(playerState, index, type)
{
- let type = g_ResourceData.GetCodes()[position];
-
- return formatIncome(
- playerState.statistics.resourcesGathered[type],
- playerState.statistics.resourcesUsed[type] - playerState.statistics.resourcesSold[type]);
+ return {
+ "gathered": playerState.sequences.resourcesGathered[type][index],
+ "used": playerState.sequences.resourcesUsed[type][index] - playerState.sequences.resourcesSold[type][index]
+ };
}
-function calculateTotalResources(playerState)
+function calculateTotalResources(playerState, index)
{
let totalGathered = 0;
let totalUsed = 0;
for (let type of g_ResourceData.GetCodes())
{
- totalGathered += playerState.statistics.resourcesGathered[type];
- totalUsed += playerState.statistics.resourcesUsed[type] - playerState.statistics.resourcesSold[type];
+ totalGathered += playerState.sequences.resourcesGathered[type][index];
+ totalUsed += playerState.sequences.resourcesUsed[type][index] - playerState.sequences.resourcesSold[type][index];
}
- return formatIncome(totalGathered, totalUsed);
+ return { "gathered": totalGathered, "used": totalUsed };
}
-function calculateTreasureCollected(playerState)
+function calculateTreasureCollected(playerState, index)
{
- return playerState.statistics.treasuresCollected;
+ return playerState.sequences.treasuresCollected[index];
}
-function calculateLootCollected(playerState)
+function calculateLootCollected(playerState, index)
{
- return playerState.statistics.lootCollected;
+ return playerState.sequences.lootCollected[index];
}
-function calculateTributeSent(playerState)
+function calculateTributeSent(playerState, index)
{
- return formatIncome(
- playerState.statistics.tributesSent,
- playerState.statistics.tributesReceived);
+ return {
+ "sent": playerState.sequences.tributesSent[index],
+ "received": playerState.sequences.tributesReceived[index]
+ };
}
-function calculateResourcesTeam(counters)
+function calculateResourcesTeam(counters, index)
{
for (let t in g_Teams)
{
@@ -352,43 +329,44 @@
let teamTotal;
if (w >= 6)
teamTotal = total.income;
+ else if (w == 5)
+ teamTotal = { "sent": total.income, "received": total.outcome };
else
- teamTotal = formatIncome(total.income, total.outcome);
+ teamTotal = { "gathered": total.income, "used": total.outcome };
- Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = teamTotal;
+ Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = formatSummaryValue(teamTotal);
}
}
}
-function calculateResourceExchanged(playerState, position)
+function calculateResourceExchanged(playerState, index, type)
{
- let type = g_ResourceData.GetCodes()[position];
-
- return formatIncome(
- playerState.statistics.resourcesBought[type],
- playerState.statistics.resourcesSold[type]);
+ return {
+ "bought": playerState.sequences.resourcesBought[type][index],
+ "sold": playerState.sequences.resourcesSold[type][index]
+ };
}
-function calculateBarterEfficiency(playerState)
+function calculateBarterEfficiency(playerState, index)
{
let totalBought = 0;
let totalSold = 0;
- for (let type in playerState.statistics.resourcesBought)
- totalBought += playerState.statistics.resourcesBought[type];
+ for (let type in playerState.sequences.resourcesBought)
+ totalBought += playerState.sequences.resourcesBought[type][index];
- for (let type in playerState.statistics.resourcesSold)
- totalSold += playerState.statistics.resourcesSold[type];
+ for (let type in playerState.sequences.resourcesSold)
+ totalSold += playerState.sequences.resourcesSold[type][index];
- return formatPercent(totalBought, totalSold);
+ return calculatePercent(totalBought, totalSold);
}
-function calculateTradeIncome(playerState)
+function calculateTradeIncome(playerState, index)
{
- return playerState.statistics.tradeIncome;
+ return playerState.sequences.tradeIncome[index];
}
-function calculateMarketTeam(counters)
+function calculateMarketTeam(counters, index)
{
for (let t in g_Teams)
{
@@ -418,54 +396,54 @@
let teamTotal;
if (w == 4)
- teamTotal = formatPercent(g_TeamHelperData[t].totalBought, g_TeamHelperData[t].totalSold);
+ teamTotal = calculatePercent(g_TeamHelperData[t].totalBought[index], g_TeamHelperData[t].totalSold[index]);
else if (w > 4)
teamTotal = total.income;
else
- teamTotal = formatIncome(total.income, total.outcome);
+ teamTotal = total;
- Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = teamTotal;
+ Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = formatSummaryValue(teamTotal);
}
}
}
-function calculateVegetarianRatio(playerState)
+function calculateVegetarianRatio(playerState, index)
{
- return formatPercent(
- playerState.statistics.resourcesGathered.vegetarianFood,
- playerState.statistics.resourcesGathered.food);
+ return calculatePercent(
+ playerState.sequences.resourcesGathered.vegetarianFood[index],
+ playerState.sequences.resourcesGathered.food[index]);
}
-function calculateFeminization(playerState)
+function calculateFeminization(playerState, index)
{
- return formatPercent(
- playerState.statistics.unitsTrained.FemaleCitizen,
- playerState.statistics.unitsTrained.Worker);
+ return calculatePercent(
+ playerState.sequences.unitsTrained.FemaleCitizen[index],
+ playerState.sequences.unitsTrained.Worker[index]);
}
-function calculateKillDeathRatio(playerState)
+function calculateKillDeathRatio(playerState, index)
{
- return formatRatio(
- playerState.statistics.enemyUnitsKilled.total,
- playerState.statistics.unitsLost.total);
+ return calculateRatio(
+ playerState.sequences.enemyUnitsKilled.total[index],
+ playerState.sequences.unitsLost.total[index]);
}
-function calculateMapExploration(playerState)
+function calculateMapExploration(playerState, index)
{
- return playerState.statistics.percentMapExplored + "%";
+ return { "percent": playerState.sequences.percentMapExplored[index] };
}
-function calculateMapFinalControl(playerState)
+function calculateMapFinalControl(playerState, index)
{
- return playerState.statistics.percentMapControlled + "%";
+ return { "percent": playerState.sequences.percentMapControlled[index] };
}
-function calculateMapPeakControl(playerState)
+function calculateMapPeakControl(playerState, index)
{
- return playerState.statistics.peakPercentMapControlled + "%";
+ return { "percent": playerState.sequences.peakPercentMapControlled[index] };
}
-function calculateMiscellaneous(counters)
+function calculateMiscellaneousTeam(counters, index)
{
for (let t in g_Teams)
{
@@ -477,19 +455,19 @@
let teamTotal;
if (w == 0)
- teamTotal = formatPercent(g_TeamHelperData[t].vegetarianFood, g_TeamHelperData[t].food);
+ teamTotal = calculatePercent(g_TeamHelperData[t].vegetarianFood[index], g_TeamHelperData[t].food[index]);
else if (w == 1)
- teamTotal = formatPercent(g_TeamHelperData[t].femaleCitizen, g_TeamHelperData[t].worker);
+ teamTotal = calculatePercent(g_TeamHelperData[t].femaleCitizen[index], g_TeamHelperData[t].worker[index]);
else if (w == 2)
- teamTotal = formatRatio(g_TeamHelperData[t].enemyUnitsKilled, g_TeamHelperData[t].unitsLost);
+ teamTotal = calculateRatio(g_TeamHelperData[t].enemyUnitsKilled[index], g_TeamHelperData[t].unitsLost[index]);
else if (w == 3)
- teamTotal = g_TeamHelperData[t].percentMapExplored + "%";
+ teamTotal = { "percent": g_TeamHelperData[t].percentMapExplored[index] };
else if (w == 4)
- teamTotal = g_TeamHelperData[t].peakPercentMapControlled + "%";
+ teamTotal = { "percent": g_TeamHelperData[t].peakPercentMapControlled[index] };
else if (w == 5)
- teamTotal = g_TeamHelperData[t].percentMapControlled + "%";
+ teamTotal = { "percent": g_TeamHelperData[t].percentMapControlled[index] };
- Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = teamTotal;
+ Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption = formatSummaryValue(teamTotal);
}
}
}
Index: binaries/data/mods/public/gui/summary/layout.js
===================================================================
--- binaries/data/mods/public/gui/summary/layout.js
+++ binaries/data/mods/public/gui/summary/layout.js
@@ -1,11 +1,12 @@
var g_ScorePanelsData = {
"score": {
+ "caption": translate("Score"),
"headings": [
- { "caption": translate("Player name"), "yStart": 26, "width": 200 },
- { "caption": translate("Economy score"), "yStart": 16, "width": 100 },
- { "caption": translate("Military score"), "yStart": 16, "width": 100 },
- { "caption": translate("Exploration score"), "yStart": 16, "width": 100 },
- { "caption": translate("Total score"), "yStart": 16, "width": 100 }
+ { "identifier": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 },
+ { "identifier": "economyScore", "caption": translate("Economy score"), "yStart": 16, "width": 100 },
+ { "identifier": "militaryScore", "caption": translate("Military score"), "yStart": 16, "width": 100 },
+ { "identifier": "explorationScore", "caption": translate("Exploration score"), "yStart": 16, "width": 100 },
+ { "identifier": "totalScore", "caption": translate("Total score"), "yStart": 16, "width": 100 }
],
"titleHeadings": [],
"counters": [
@@ -17,28 +18,29 @@
"teamCounterFn": calculateScoreTeam
},
"buildings": {
+ "caption": translate("Buildings"),
"headings": [
- { "caption": translate("Player name"), "yStart": 26, "width": 200 },
- { "caption": translate("Total"), "yStart": 34, "width": 105 },
- { "caption": translate("Houses"), "yStart": 34, "width": 85 },
- { "caption": translate("Economic"), "yStart": 34, "width": 85 },
- { "caption": translate("Outposts"), "yStart": 34, "width": 85 },
- { "caption": translate("Military"), "yStart": 34, "width": 85 },
- { "caption": translate("Fortresses"), "yStart": 34, "width": 85 },
- { "caption": translate("Civ centers"), "yStart": 34, "width": 85 },
- { "caption": translate("Wonders"), "yStart": 34, "width": 85 }
+ { "identifier": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 },
+ { "identifier": "total", "caption": translate("Total"), "yStart": 34, "width": 105 },
+ { "identifier": "House", "caption": translate("Houses"), "yStart": 34, "width": 85 },
+ { "identifier": "Economic", "caption": translate("Economic"), "yStart": 34, "width": 85 },
+ { "identifier": "Outpost", "caption": translate("Outposts"), "yStart": 34, "width": 85 },
+ { "identifier": "Military", "caption": translate("Military"), "yStart": 34, "width": 85 },
+ { "identifier": "Fortress", "caption": translate("Fortresses"), "yStart": 34, "width": 85 },
+ { "identifier": "CivCentre", "caption": translate("Civ centers"), "yStart": 34, "width": 85 },
+ { "identifier": "Wonder", "caption": translate("Wonders"), "yStart": 34, "width": 85 }
],
"titleHeadings": [
{
"caption": sprintf(translate("Buildings Statistics (%(constructed)s / %(destroyed)s / %(captured)s / %(lost)s)"),
{
- "constructed": g_TrainedColor + translate("Constructed") + '[/color]',
- "destroyed": g_KilledColor + translate("Destroyed") + '[/color]',
- "captured": g_CapturedColor + translate("Captured") + '[/color]',
- "lost": g_LostColor + translate("Lost") + '[/color]'
+ "constructed": getColoredTypeTranslation("constructed"),
+ "destroyed": getColoredTypeTranslation("destroyed"),
+ "captured": getColoredTypeTranslation("captured"),
+ "lost": getColoredTypeTranslation("lost")
}),
"yStart": 16,
- "width": (85 * 7 + 105)
+ "width": 85 * 7 + 105
}, // width = 700
],
"counters": [
@@ -54,71 +56,75 @@
"teamCounterFn": calculateBuildingsTeam
},
"units": {
+ "caption": translate("Units"),
"headings": [
- { "caption": translate("Player name"), "yStart": 26, "width": 200 },
- { "caption": translate("Total"), "yStart": 34, "width": 105 },
- { "caption": translate("Infantry"), "yStart": 34, "width": 85 },
- { "caption": translate("Worker"), "yStart": 34, "width": 85 },
- { "caption": translate("Cavalry"), "yStart": 34, "width": 85 },
- { "caption": translate("Champion"), "yStart": 34, "width": 85 },
- { "caption": translate("Heroes"), "yStart": 34, "width": 85 },
- { "caption": translate("Siege"), "yStart": 34, "width": 85 },
- { "caption": translate("Navy"), "yStart": 34, "width": 85 },
- { "caption": translate("Traders"), "yStart": 34, "width": 85 }
+ { "identifier": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 },
+ { "identifier": "total", "caption": translate("Total"), "yStart": 34, "width": 105 },
+ { "identifier": "Infantry", "caption": translate("Infantry"), "yStart": 34, "width": 85 },
+ { "identifier": "Worker", "caption": translate("Worker"), "yStart": 34, "width": 85 },
+ { "identifier": "Cavalry", "caption": translate("Cavalry"), "yStart": 34, "width": 85 },
+ { "identifier": "Champion", "caption": translate("Champion"), "yStart": 34, "width": 85 },
+ { "identifier": "Hero", "caption": translate("Heroes"), "yStart": 34, "width": 85 },
+ { "identifier": "Siege", "caption": translate("Siege"), "yStart": 34, "width": 85 },
+ { "identifier": "Ship", "caption": translate("Navy"), "yStart": 34, "width": 85 },
+ { "identifier": "Trader", "caption": translate("Traders"), "yStart": 34, "width": 85 }
],
"titleHeadings": [
{
"caption": sprintf(translate("Units Statistics (%(trained)s / %(killed)s / %(captured)s / %(lost)s)"),
{
- "trained": g_TrainedColor + translate("Trained") + '[/color]',
- "killed": g_KilledColor + translate("Killed") + '[/color]',
- "captured": g_CapturedColor + translate("Captured") + '[/color]',
- "lost": g_LostColor + translate("Lost") + '[/color]'
+ "trained": getColoredTypeTranslation("trained"),
+ "killed": getColoredTypeTranslation("killed"),
+ "captured": getColoredTypeTranslation("captured"),
+ "lost": getColoredTypeTranslation("lost")
}),
"yStart": 16,
- "width": (100 * 7 + 120)
- }, // width = 820
+ "width": 85 * 8 + 105
+ }, // width = 785
],
"counters": [
{ "width": 105, "fn": calculateUnitsWithCaptured, "verticalOffset": 3 },
- { "width": 85, "fn": calculateUnits, "verticalOffset": 12 },
- { "width": 85, "fn": calculateUnits, "verticalOffset": 12 },
- { "width": 85, "fn": calculateUnits, "verticalOffset": 12 },
- { "width": 85, "fn": calculateUnits, "verticalOffset": 12 },
- { "width": 85, "fn": calculateUnits, "verticalOffset": 12 },
- { "width": 105, "fn": calculateUnitsWithCaptured, "verticalOffset": 3 },
- { "width": 85, "fn": calculateUnits, "verticalOffset": 12 },
- { "width": 85, "fn": calculateUnits, "verticalOffset": 12 }
+ { "width": 85, "fn": calculateUnits, "verticalOffset": 3 },
+ { "width": 85, "fn": calculateUnits, "verticalOffset": 3 },
+ { "width": 85, "fn": calculateUnits, "verticalOffset": 3 },
+ { "width": 85, "fn": calculateUnits, "verticalOffset": 3 },
+ { "width": 85, "fn": calculateUnits, "verticalOffset": 3 },
+ { "width": 85, "fn": calculateUnitsWithCaptured, "verticalOffset": 3 },
+ { "width": 85, "fn": calculateUnits, "verticalOffset": 3 },
+ { "width": 85, "fn": calculateUnits, "verticalOffset": 3 }
],
"teamCounterFn": calculateUnitsTeam
},
"resources": {
+ "caption": translate("Resources"),
"headings": [
- { "caption": translate("Player name"), "yStart": 26, "width": 200 },
+ { "identifier": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 },
...g_ResourceData.GetResources().map(res => ({
+ "identifier": res.code,
"caption": translateWithContext("firstWord", res.name),
"yStart": 34,
"width": 100
})),
- { "caption": translate("Total"), "yStart": 34, "width": 110 },
+ { "identifier": "total", "caption": translate("Total"), "yStart": 34, "width": 110 },
{
+ "identifier": "tributes",
"caption": sprintf(translate("Tributes \n(%(sent)s / %(received)s)"),
{
- "sent": g_IncomeColor + translate("Sent") + '[/color]',
- "received": g_OutcomeColor + translate("Received") + '[/color]'
+ "sent": getColoredTypeTranslation("sent"),
+ "received": getColoredTypeTranslation("received")
}),
"yStart": 16,
"width": 121
},
- { "caption": translate("Treasures collected"), "yStart": 16, "width": 100 },
- { "caption": translate("Loot"), "yStart": 16, "width": 100 }
+ { "identifier": "treasuresCollected", "caption": translate("Treasures collected"), "yStart": 16, "width": 100 },
+ { "identifier": "loot", "caption": translate("Loot"), "yStart": 16, "width": 100 }
],
"titleHeadings": [
{
"caption": sprintf(translate("Resource Statistics (%(gathered)s / %(used)s)"),
{
- "gathered": g_IncomeColor + translate("Gathered") + '[/color]',
- "used": g_OutcomeColor + translate("Used") + '[/color]'
+ "gathered": getColoredTypeTranslation("gathered"),
+ "used": getColoredTypeTranslation("used")
}),
"yStart": 16,
"width": 100 * g_ResourceData.GetCodes().length + 110
@@ -138,10 +144,12 @@
"teamCounterFn": calculateResourcesTeam
},
"market": {
+ "caption": translate("Market"),
"headings": [
- { "caption": translate("Player name"), "yStart": 26, "width": 200 },
+ { "identifier": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 },
...g_ResourceData.GetResources().map(res => {
return {
+ "identifier": res.code,
"caption":
// Translation: use %(resourceWithinSentence)s if needed
sprintf(translate("%(resourceFirstWord)s exchanged"), {
@@ -152,8 +160,8 @@
"width": 100
};
}),
- { "caption": translate("Barter efficiency"), "yStart": 16, "width": 100 },
- { "caption": translate("Trade income"), "yStart": 16, "width": 100 }
+ { "identifier": "barterEfficency", "caption": translate("Barter efficiency"), "yStart": 16, "width": 100 },
+ { "identifier": "tradeIncome", "caption": translate("Trade income"), "yStart": 16, "width": 100 }
],
"titleHeadings": [],
"counters": [
@@ -168,18 +176,17 @@
"teamCounterFn": calculateMarketTeam
},
"misc": {
+ "caption": translate("Miscellaneous"),
"headings": [
- { "caption": translate("Player name"), "yStart": 26, "width": 200 },
- { "caption": translate("Vegetarian\nratio"), "yStart": 16, "width": 100 },
- { "caption": translate("Feminization"), "yStart": 16, "width": 100 },
- { "caption": translate("Kill / Death\nratio"), "yStart": 16, "width": 100 },
- { "caption": translate("Map\nexploration"), "yStart": 16, "width": 100 },
- { "caption": translate("At peak"), "yStart": 34, "width": 100 },
- { "caption": translate("At finish"), "yStart": 34, "width": 100 }
- ],
- "titleHeadings": [
- { "caption": translate("Map control"), "xOffset": 400, "yStart": 16, "width": 200 }
+ { "identifier": "playername", "caption": translate("Player name"), "yStart": 26, "width": 200 },
+ { "identifier": "vegetarianRatio", "caption": translate("Vegetarian ratio"), "yStart": 16, "width": 100 },
+ { "identifier": "feminization", "caption": translate("Feminization"), "yStart": 16, "width": 100 },
+ { "identifier": "killDeath", "caption": translate("Kill / Death ratio"), "yStart": 16, "width": 100 },
+ { "identifier": "mapExploration", "caption": translate("Map exploration"), "yStart": 16, "width": 100 },
+ { "identifier": "mapControlPeak", "caption": translate("Map control (peak)"), "yStart": 16, "width": 100 },
+ { "identifier": "mapControlFinish", "caption": translate("Map control (finish)"), "yStart": 16, "width": 100 }
],
+ "titleHeadings": [],
"counters": [
{ "width": 100, "fn": calculateVegetarianRatio, "verticalOffset": 12 },
{ "width": 100, "fn": calculateFeminization, "verticalOffset": 12 },
@@ -188,10 +195,15 @@
{ "width": 100, "fn": calculateMapPeakControl, "verticalOffset": 12 },
{ "width": 100, "fn": calculateMapFinalControl, "verticalOffset": 12 }
],
- "teamCounterFn": calculateMiscellaneous
+ "teamCounterFn": calculateMiscellaneousTeam
}
};
+function getColoredTypeTranslation(type)
+{
+ return g_SummaryTypes[type].color + g_SummaryTypes[type].caption + '[/color]';
+}
+
function resetGeneralPanel()
{
for (let h = 0; h < g_MaxHeadingTitle; ++h)
Index: binaries/data/mods/public/gui/summary/summary.js
===================================================================
--- binaries/data/mods/public/gui/summary/summary.js
+++ binaries/data/mods/public/gui/summary/summary.js
@@ -9,18 +9,89 @@
const g_PlayerColorBoxAlpha = " 255";
const g_TeamsBoxYStart = 40;
-// Colors used for units and buildings
-const g_TrainedColor = '[color="201 255 200"]';
-const g_LostColor = '[color="255 213 213"]';
-const g_KilledColor = '[color="196 198 255"]';
-const g_CapturedColor = '[color="255 255 157"]';
-
-const g_BuildingsTypes = [ "total", "House", "Economic", "Outpost", "Military", "Fortress", "CivCentre", "Wonder" ];
-const g_UnitsTypes = [ "total", "Infantry", "Worker", "Cavalry", "Champion", "Hero", "Siege", "Ship", "Trader" ];
-
-// Colors used for gathered and traded resources
-const g_IncomeColor = '[color="201 255 200"]';
-const g_OutcomeColor = '[color="255 213 213"]';
+const g_TypeBlue = '[color="196 198 255"]';
+const g_TypeGreen = '[color="201 255 200"]';
+const g_TypeRed = '[color="255 213 213"]';
+const g_TypeYellow = '[color="255 255 157"]';
+
+// Colors, captions and format used for units, buildings, etc. types
+var g_SummaryTypes = {
+ "percent": {
+ "color": "",
+ "caption": "%",
+ "postfix": "%"
+ },
+ "trained": {
+ "color": g_TypeGreen,
+ "caption": translate("Trained"),
+ "postfix": '[/color] / '
+ },
+ "constructed": {
+ "color": g_TypeGreen,
+ "caption": translate("Constructed"),
+ "postfix": '[/color] / '
+ },
+ "gathered": {
+ "color": g_TypeGreen,
+ "caption": translate("Gathered"),
+ "postfix": '[/color] / '
+ },
+ "sent": {
+ "color": g_TypeGreen,
+ "caption": translate("Sent"),
+ "postfix": '[/color] / '
+ },
+ "bought": {
+ "color": g_TypeGreen,
+ "caption": translate("Bought"),
+ "postfix": '[/color] / '
+ },
+ "income": {
+ "color": g_TypeGreen,
+ "caption": translate("Income"),
+ "postfix": '[/color] / '
+ },
+ "captured": {
+ "color": g_TypeYellow,
+ "caption": translate("Captured"),
+ "postfix": '[/color] / '
+ },
+ "destroyed": {
+ "color": g_TypeBlue,
+ "caption": translate("Destroyed"),
+ "postfix": '[/color]\n'
+ },
+ "killed": {
+ "color": g_TypeBlue,
+ "caption": translate("Killed"),
+ "postfix": '[/color]\n'
+ },
+ "lost": {
+ "color": g_TypeRed,
+ "caption": translate("Lost"),
+ "postfix": '[/color]\n'
+ },
+ "used": {
+ "color": g_TypeRed,
+ "caption": translate("Used"),
+ "postfix": '[/color]\n'
+ },
+ "received": {
+ "color": g_TypeRed,
+ "caption": translate("Recieved"),
+ "postfix": '[/color]\n'
+ },
+ "sold": {
+ "color": g_TypeRed,
+ "caption": translate("Sold"),
+ "postfix": '[/color]\n'
+ },
+ "outcome": {
+ "color": g_TypeRed,
+ "caption": translate("Outcome"),
+ "postfix": '[/color]\n'
+ }
+}
const g_InfiniteSymbol = "\u221E";
@@ -47,7 +118,133 @@
adjustTabDividers(panel.size);
- updatePanelData(g_ScorePanelsData[panel.name.substr(0, panel.name.length - "PanelButton".length)]);
+ let generalPanel = Engine.GetGUIObjectByName("generalPanel");
+ let chartsPanel = Engine.GetGUIObjectByName("chartsPanel");
+ let chartsHidden = panel.name != "chartsPanelButton";
+ generalPanel.hidden = !chartsHidden;
+ chartsPanel.hidden = chartsHidden;
+ if (chartsHidden)
+ updatePanelData(g_ScorePanelsData[panel.name.substr(0, panel.name.length - "PanelButton".length)]);
+ else
+ [0,1].forEach(updateCategoryDropdown);
+}
+
+function initCharts()
+{
+ let player_colors = [];
+ for (let i = 1; i <= g_PlayerCount; ++i)
+ {
+ let playerState = g_GameData.sim.playerStates[i];
+ player_colors.push(
+ Math.floor(playerState.color.r * 255) + " " +
+ Math.floor(playerState.color.g * 255) + " " +
+ Math.floor(playerState.color.b * 255)
+ );
+ }
+ let chart0 = Engine.GetGUIObjectByName("chart[0]");
+ chart0.series_color = player_colors;
+ let chart1 = Engine.GetGUIObjectByName("chart[1]");
+ chart1.series_color = player_colors;
+ let chartLegend = Engine.GetGUIObjectByName("chartLegend");
+ chartLegend.caption = g_GameData.sim.playerStates.slice(1).map(
+ (state, index) => '[color="' + player_colors[index] + '"]■[/color] ' + state.name
+ ).join(" ");
+
+ let chart1Part = Engine.GetGUIObjectByName("chart[1]Part");
+ let chart1PartSize = chart1Part.size;
+ chart1PartSize.rright += 50;
+ chart1PartSize.rleft += 50;
+ chart1PartSize.right -= 5;
+ chart1PartSize.left -= 5;
+ chart1Part.size = chart1PartSize;
+}
+
+function resizeDropdown(dropdown)
+{
+ let size = dropdown.size;
+ size.bottom = dropdown.size.top +
+ (Engine.GetTextWidth(dropdown.font, dropdown.list[dropdown.selected]) >
+ dropdown.size.right - dropdown.size.left - 32 ? 42 : 27);
+ dropdown.size = size;
+}
+
+function updateCategoryDropdown(number)
+{
+ let chartCategory = Engine.GetGUIObjectByName("chart[" + number + "]CategorySelection");
+ chartCategory.list_data = Object.keys(g_ScorePanelsData);
+ chartCategory.list = Object.keys(g_ScorePanelsData).map(panel => g_ScorePanelsData[panel].caption);
+ chartCategory.onSelectionChange = function() {
+ if (!this.list_data[this.selected])
+ return;
+ resizeDropdown(this);
+ updateValueDropdown(number, this.list_data[this.selected]);
+ };
+ chartCategory.selected = 0;
+}
+
+function updateValueDropdown(number, category)
+{
+ let chartValue = Engine.GetGUIObjectByName("chart[" + number + "]ValueSelection");
+ let list = g_ScorePanelsData[category].headings.map(heading => heading.caption);
+ list.shift();
+ chartValue.list = list;
+ let list_data = g_ScorePanelsData[category].headings.map(heading => heading.identifier);
+ list_data.shift();
+ chartValue.list_data = list_data;
+ chartValue.onSelectionChange = function() {
+ if (!this.list_data[this.selected])
+ return;
+ resizeDropdown(this);
+ updateTypeDropdown(number, category, this.list_data[this.selected], this.selected);
+ };
+ chartValue.selected = 0;
+}
+
+function updateTypeDropdown(number, category, item, itemNumber)
+{
+ let testValue = g_ScorePanelsData[category].counters[itemNumber].fn(g_GameData.sim.playerStates[1], 0, item);
+ let hide = !g_ScorePanelsData[category].counters[itemNumber].fn ||
+ typeof testValue != "object" || Object.keys(testValue).length < 2;
+ Engine.GetGUIObjectByName("chart[" + number + "]TypeLabel").hidden = hide;
+ let chartType = Engine.GetGUIObjectByName("chart[" + number + "]TypeSelection");
+ chartType.hidden = hide;
+ if (hide)
+ {
+ updateChart(number, category, item, itemNumber, Object.keys(testValue)[0] || undefined);
+ return;
+ }
+
+ chartType.list = Object.keys(testValue).map(type => g_SummaryTypes[type].caption);
+ chartType.list_data = Object.keys(testValue);
+ chartType.onSelectionChange = function() {
+ if (!this.list_data[this.selected])
+ return;
+ resizeDropdown(this);
+ updateChart(number, category, item, itemNumber, this.list_data[this.selected]);
+ };
+ chartType.selected = 0;
+}
+
+function updateChart(number, category, item, itemNumber, type)
+{
+ if (!g_ScorePanelsData[category].counters[itemNumber].fn)
+ return;
+ let chart = Engine.GetGUIObjectByName("chart[" + number + "]");
+ let series = [];
+ for (let j = 1; j <= g_PlayerCount; ++j)
+ {
+ let playerState = g_GameData.sim.playerStates[j];
+ let data = [];
+ for (let index in playerState.sequences.time)
+ {
+ let value = g_ScorePanelsData[category].counters[itemNumber].fn(playerState, index, item);
+ if (type)
+ value = value[type];
+ data.push([playerState.sequences.time[index], value]);
+ }
+ series.push(data);
+ }
+ chart.series = series;
}
function adjustTabDividers(tabSize)
@@ -126,14 +323,14 @@
civIcon.sprite = "stretched:" + g_CivData[playerState.civ].Emblem;
civIcon.tooltip = g_CivData[playerState.civ].Name;
- updateCountersPlayer(playerState, panelInfo.counters, playerCounterValue);
+ updateCountersPlayer(playerState, panelInfo.counters, panelInfo.headings, playerCounterValue);
calculateTeamCounters(playerState);
}
let teamCounterFn = panelInfo.teamCounterFn;
if (g_Teams && teamCounterFn)
- teamCounterFn(panelInfo.counters);
+ teamCounterFn(panelInfo.counters, g_GameData.sim.playerStates[1].sequences.time.length - 1);
}
function confirmStartReplay()
@@ -256,5 +453,6 @@
g_WithoutTeam -= g_Teams[i] ? g_Teams[i] : 0;
}
+ initCharts();
selectPanel(Engine.GetGUIObjectByName("scorePanelButton"));
}
Index: binaries/data/mods/public/gui/summary/summary.xml
===================================================================
--- binaries/data/mods/public/gui/summary/summary.xml
+++ binaries/data/mods/public/gui/summary/summary.xml
@@ -99,6 +99,13 @@
+
+
@@ -152,6 +159,48 @@
+
+
+
+
+
+ Category:
+
+
+ Category
+
+
+
+ Value:
+
+
+ Value
+
+
+
+ Type:
+
+
+ Type
+
+
+
+
+
+
+
+
+
Replay
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js
+++ binaries/data/mods/public/simulation/components/GuiInterface.js
@@ -194,7 +194,7 @@
let playerEnt = cmpPlayerManager.GetPlayerByID(i);
let cmpPlayerStatisticsTracker = Engine.QueryInterface(playerEnt, IID_StatisticsTracker);
if (cmpPlayerStatisticsTracker)
- ret.players[i].statistics = cmpPlayerStatisticsTracker.GetStatistics();
+ ret.players[i].sequences = cmpPlayerStatisticsTracker.GetSequences();
}
return ret;
Index: binaries/data/mods/public/simulation/components/StatisticsTracker.js
===================================================================
--- binaries/data/mods/public/simulation/components/StatisticsTracker.js
+++ binaries/data/mods/public/simulation/components/StatisticsTracker.js
@@ -1,5 +1,7 @@
function StatisticsTracker() {}
+const g_UpdateSequenceInterval = 30 * 1000;
+
StatisticsTracker.prototype.Schema =
"";
@@ -142,6 +144,10 @@
this.lootCollected = 0;
this.peakPercentMapControlled = 0;
this.teamPeakPercentMapControlled = 0;
+
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ this.updateTimer = cmpTimer.SetInterval(
+ this.entity, IID_StatisticsTracker, "updateSequences", 0, g_UpdateSequenceInterval);
};
/**
@@ -195,11 +201,21 @@
};
};
+StatisticsTracker.prototype.GetSequences = function()
+{
+ let ret = clone(this.sequences);
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+
+ ret.time.push(cmpTimer.GetTime() / 1000);
+ this.PushValue(this.GetStatistics(), ret);
+ return ret;
+}
+
/**
* Increments counter associated with certain entity/counter and type of given entity.
- * @param cmpIdentity The entity identity component
- * @param counter The name of the counter to increment (e.g. "unitsTrained")
- * @param type The type of the counter (e.g. "workers")
+ * @param cmpIdentity - The entity identity component.
+ * @param counter - The name of the counter to increment (e.g. "unitsTrained").
+ * @param type - The type of the counter (e.g. "workers").
*/
StatisticsTracker.prototype.CounterIncrement = function(cmpIdentity, counter, type)
{
@@ -356,9 +372,9 @@
};
/**
- * @param type Generic type of resource (string)
- * @param amount Amount of resource, whick should be added (integer)
- * @param specificType Specific type of resource (string, optional)
+ * @param {string} type - Generic type of resource.
+ * @param {number} amount - Amount of resource, whick should be added.
+ * @param {string} specificType - Specific type of resource.
*/
StatisticsTracker.prototype.IncreaseResourceGatheredCounter = function(type, amount, specificType)
{
@@ -369,8 +385,8 @@
};
/**
- * @param type Generic type of resource (string)
- * @param amount Amount of resource, which should be added (integer)
+ * @param {string} type - Generic type of resource.
+ * @param {number} amount - Amount of resource, which should be added.
*/
StatisticsTracker.prototype.IncreaseResourceUsedCounter = function(type, amount)
{
@@ -493,4 +509,41 @@
this.teamPeakPercentMapControlled = newPercent;
};
+/**
+ * Adds the values of fromData to the end of the arrays of toData.
+ * If toData misses the needed array, one will be created.
+ *
+ * @param fromData - an object of values or a value.
+ * @param toData - an object of arrays or an array.
+**/
+StatisticsTracker.prototype.PushValue = function(fromData, toData)
+{
+ if (typeof fromData == "object")
+ for (let prop in fromData)
+ {
+ if (typeof toData[prop] != "object")
+ toData[prop] = [fromData[prop]];
+ else
+ this.PushValue(fromData[prop], toData[prop]);
+ }
+ else
+ toData.push(fromData);
+};
+
+StatisticsTracker.prototype.updateSequences = function()
+{
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+
+ // Don't do this on Init, because GetStatistics doesn't work in this state of the game
+ // This is probably, because the simulation hasn't totally started/initialized and we query some simulation values
+ if (!this.sequences)
+ {
+ this.sequences = clone(this.GetStatistics());
+ this.sequences.time = [];
+ }
+
+ this.sequences.time.push(cmpTimer.GetTime() / 1000);
+ this.PushValue(this.GetStatistics(), this.sequences);
+}
+
Engine.RegisterComponentType(IID_StatisticsTracker, "StatisticsTracker", StatisticsTracker);
Index: binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
+++ binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
@@ -144,29 +144,29 @@
"percentMapExplored": 10
};
},
- GetStatistics: function() {
+ GetSequences: function() {
return {
- "unitsTrained": 10,
- "unitsLost": 9,
- "buildingsConstructed": 5,
- "buildingsCaptured": 7,
- "buildingsLost": 4,
- "civCentresBuilt": 1,
+ "unitsTrained": [0, 10],
+ "unitsLost": [0, 42],
+ "buildingsConstructed": [1, 3],
+ "buildingsCaptured": [3, 7],
+ "buildingsLost": [3, 10],
+ "civCentresBuilt": [4, 10],
"resourcesGathered": {
- "food": 100,
- "wood": 0,
- "metal": 0,
- "stone": 0,
- "vegetarianFood": 0,
+ "food": [5, 100],
+ "wood": [0, 0],
+ "metal": [0, 0],
+ "stone": [0, 0],
+ "vegetarianFood": [0, 0],
},
- "treasuresCollected": 0,
- "lootCollected": 0,
- "percentMapExplored": 10,
- "teamPercentMapExplored": 10,
- "percentMapControlled": 10,
- "teamPercentMapControlled": 10,
- "peakPercentOfMapControlled": 10,
- "teamPeakPercentOfMapControlled": 10
+ "treasuresCollected": [1, 20],
+ "lootCollected": [0, 2],
+ "percentMapExplored": [0, 10],
+ "teamPercentMapExplored": [0, 10],
+ "percentMapControlled": [0, 10],
+ "teamPercentMapControlled": [0, 10],
+ "peakPercentOfMapControlled": [0, 10],
+ "teamPeakPercentOfMapControlled": [0, 10]
};
},
IncreaseTrainedUnitsCounter: function() { return 1; },
@@ -230,29 +230,29 @@
"percentMapExplored": 10
};
},
- GetStatistics: function() {
+ GetSequences: function() {
return {
- "unitsTrained": 10,
- "unitsLost": 9,
- "buildingsConstructed": 5,
- "buildingsCaptured": 7,
- "buildingsLost": 4,
- "civCentresBuilt": 1,
+ "unitsTrained": [0, 10],
+ "unitsLost": [0, 9],
+ "buildingsConstructed": [0, 5],
+ "buildingsCaptured": [0, 7],
+ "buildingsLost": [0, 4],
+ "civCentresBuilt": [0, 1],
"resourcesGathered": {
- "food": 100,
- "wood": 0,
- "metal": 0,
- "stone": 0,
- "vegetarianFood": 0,
+ "food": [0, 100],
+ "wood": [0, 0],
+ "metal": [0, 0],
+ "stone": [0, 0],
+ "vegetarianFood": [0, 0],
},
- "treasuresCollected": 0,
- "lootCollected": 0,
- "percentMapExplored": 10,
- "teamPercentMapExplored": 10,
- "percentMapControlled": 10,
- "teamPercentMapControlled": 10,
- "peakPercentOfMapControlled": 10,
- "teamPeakPercentOfMapControlled": 10
+ "treasuresCollected": [0, 0],
+ "lootCollected": [0, 0],
+ "percentMapExplored": [0, 10],
+ "teamPercentMapExplored": [0, 10],
+ "percentMapControlled": [0, 10],
+ "teamPercentMapControlled": [0, 10],
+ "peakPercentOfMapControlled": [0, 10],
+ "teamPeakPercentOfMapControlled": [0, 10]
};
},
IncreaseTrainedUnitsCounter: function() { return 1; },
@@ -382,128 +382,148 @@
});
TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
- players: [
+ "players": [
{
- name: "Player 1",
- civ: "gaia",
- color: { r:1, g:1, b:1, a:1 },
- controlsAll: false,
- popCount: 10,
- popLimit: 20,
- popMax: 200,
- panelEntities: [],
- resourceCounts: { food: 100 },
- trainingBlocked: false,
- state: "active",
- team: -1,
- teamsLocked: false,
- cheatsEnabled: false,
- disabledTemplates: {},
- disabledTechnologies: {},
- hasSharedDropsites: false,
- hasSharedLos: false,
- spyCostMultiplier: 1,
- phase: "village",
- isAlly: [false, false],
- isMutualAlly: [false, false],
- isNeutral: [false, false],
- isEnemy: [true, true],
- entityLimits: {"Foo": 10},
- entityCounts: {"Foo": 5},
- entityLimitChangers: {"Foo": {}},
- researchQueued: {},
- researchStarted: {},
- researchedTechs: {},
- classCounts: {},
- typeCountsByClass: {},
- canBarter: false,
- statistics: {
- unitsTrained: 10,
- unitsLost: 9,
- buildingsConstructed: 5,
- buildingsCaptured: 7,
- buildingsLost: 4,
- civCentresBuilt: 1,
- resourcesGathered: {
- food: 100,
- wood: 0,
- metal: 0,
- stone: 0,
- vegetarianFood: 0,
+ "name": "Player 1",
+ "civ": "gaia",
+ "color": { "r":1, "g":1, "b":1, "a":1 },
+ "controlsAll": false,
+ "popCount": 10,
+ "popLimit": 20,
+ "popMax": 200,
+ "panelEntities": [],
+ "resourceCounts": { "food": 100 },
+ "trainingBlocked": false,
+ "state": "active",
+ "team": -1,
+ "teamsLocked": false,
+ "cheatsEnabled": false,
+ "disabledTemplates": {},
+ "disabledTechnologies": {},
+ "hasSharedDropsites": false,
+ "hasSharedLos": false,
+ "spyCostMultiplier": 1,
+ "phase": "village",
+ "isAlly": [false, false],
+ "isMutualAlly": [false, false],
+ "isNeutral": [false, false],
+ "isEnemy": [true, true],
+ "entityLimits": {"Foo": 10},
+ "entityCounts": {"Foo": 5},
+ "entityLimitChangers": {"Foo": {}},
+ "researchQueued": {},
+ "researchStarted": {},
+ "researchedTechs": {},
+ "classCounts": {},
+ "typeCountsByClass": {},
+ "canBarter": false,
+ "statistics": {
+ "resourcesGathered": {
+ "food": 100,
+ "wood": 0,
+ "metal": 0,
+ "stone": 0,
+ "vegetarianFood": 0,
+ },
+ "percentMapExplored": 10
+ },
+ "sequences": {
+ "unitsTrained": [0, 10],
+ "unitsLost": [0, 42],
+ "buildingsConstructed": [1, 3],
+ "buildingsCaptured": [3, 7],
+ "buildingsLost": [3, 10],
+ "civCentresBuilt": [4, 10],
+ "resourcesGathered": {
+ "food": [5, 100],
+ "wood": [0, 0],
+ "metal": [0, 0],
+ "stone": [0, 0],
+ "vegetarianFood": [0, 0],
},
- treasuresCollected: 0,
- lootCollected: 0,
- percentMapExplored: 10,
- teamPercentMapExplored: 10,
- percentMapControlled: 10,
- teamPercentMapControlled: 10,
- peakPercentOfMapControlled: 10,
- teamPeakPercentOfMapControlled: 10
+ "treasuresCollected": [1, 20],
+ "lootCollected": [0, 2],
+ "percentMapExplored": [0, 10],
+ "teamPercentMapExplored": [0, 10],
+ "percentMapControlled": [0, 10],
+ "teamPercentMapControlled": [0, 10],
+ "peakPercentOfMapControlled": [0, 10],
+ "teamPeakPercentOfMapControlled": [0, 10]
},
},
{
- name: "Player 2",
- civ: "mace",
- color: { r:1, g:0, b:0, a:1 },
- controlsAll: true,
- popCount: 40,
- popLimit: 30,
- popMax: 300,
- panelEntities: [],
- resourceCounts: { food: 200 },
- trainingBlocked: false,
- state: "active",
- team: -1,
- teamsLocked: false,
- cheatsEnabled: false,
- disabledTemplates: {},
- disabledTechnologies: {},
- hasSharedDropsites: false,
- hasSharedLos: false,
- spyCostMultiplier: 1,
- phase: "village",
- isAlly: [true, true],
- isMutualAlly: [false, false],
- isNeutral: [false, false],
- isEnemy: [false, false],
- entityLimits: {"Bar": 20},
- entityCounts: {"Bar": 0},
- entityLimitChangers: {"Bar": {}},
- researchQueued: {},
- researchStarted: {},
- researchedTechs: {},
- classCounts: {},
- typeCountsByClass: {},
- canBarter: false,
- statistics: {
- unitsTrained: 10,
- unitsLost: 9,
- buildingsConstructed: 5,
- buildingsCaptured: 7,
- buildingsLost: 4,
- civCentresBuilt: 1,
- resourcesGathered: {
- food: 100,
- wood: 0,
- metal: 0,
- stone: 0,
- vegetarianFood: 0,
+ "name": "Player 2",
+ "civ": "mace",
+ "color": { "r":1, "g":0, "b":0, "a":1 },
+ "controlsAll": true,
+ "popCount": 40,
+ "popLimit": 30,
+ "popMax": 300,
+ "panelEntities": [],
+ "resourceCounts": { "food": 200 },
+ "trainingBlocked": false,
+ "state": "active",
+ "team": -1,
+ "teamsLocked": false,
+ "cheatsEnabled": false,
+ "disabledTemplates": {},
+ "disabledTechnologies": {},
+ "hasSharedDropsites": false,
+ "hasSharedLos": false,
+ "spyCostMultiplier": 1,
+ "phase": "village",
+ "isAlly": [true, true],
+ "isMutualAlly": [false, false],
+ "isNeutral": [false, false],
+ "isEnemy": [false, false],
+ "entityLimits": {"Bar": 20},
+ "entityCounts": {"Bar": 0},
+ "entityLimitChangers": {"Bar": {}},
+ "researchQueued": {},
+ "researchStarted": {},
+ "researchedTechs": {},
+ "classCounts": {},
+ "typeCountsByClass": {},
+ "canBarter": false,
+ "statistics": {
+ "resourcesGathered": {
+ "food": 100,
+ "wood": 0,
+ "metal": 0,
+ "stone": 0,
+ "vegetarianFood": 0,
},
- treasuresCollected: 0,
- lootCollected: 0,
- percentMapExplored: 10,
- teamPercentMapExplored: 10,
- percentMapControlled: 10,
- teamPercentMapControlled: 10,
- peakPercentOfMapControlled: 10,
- teamPeakPercentOfMapControlled: 10
+ "percentMapExplored": 10
+ },
+ "sequences": {
+ "unitsTrained": [0, 10],
+ "unitsLost": [0, 9],
+ "buildingsConstructed": [0, 5],
+ "buildingsCaptured": [0, 7],
+ "buildingsLost": [0, 4],
+ "civCentresBuilt": [0, 1],
+ "resourcesGathered": {
+ "food": [0, 100],
+ "wood": [0, 0],
+ "metal": [0, 0],
+ "stone": [0, 0],
+ "vegetarianFood": [0, 0],
+ },
+ "treasuresCollected": [0, 0],
+ "lootCollected": [0, 0],
+ "percentMapExplored": [0, 10],
+ "teamPercentMapExplored": [0, 10],
+ "percentMapControlled": [0, 10],
+ "teamPercentMapControlled": [0, 10],
+ "peakPercentOfMapControlled": [0, 10],
+ "teamPeakPercentOfMapControlled": [0, 10]
},
}
],
- circularMap: false,
- timeElapsed: 0,
- gameType: "conquest",
- alliedVictory: false,
+ "circularMap": false,
+ "timeElapsed": 0,
+ "gameType": "conquest",
+ "alliedVictory": false,
"barterPrices": {
"buy": { "food": 150 },
"sell": { "food": 25 }