Capture statistics summary. Patch by maveric and Imarok, fixes #3216.

Also colorize the headings, use two lines per player and remove
duplication of an ugly regex hack.

This was SVN commit r18395.
This commit is contained in:
elexis 2016-06-17 02:27:11 +00:00
parent df764c0200
commit f60befe098
7 changed files with 212 additions and 79 deletions

View file

@ -12,6 +12,14 @@ function formatTrained(trained, lost, killed)
g_KilledColor + killed + '[/color]';
}
function formatCaptured(constructed, destroyed, captured, lost)
{
return g_TrainedColor + constructed + '[/color] / ' +
g_KilledColor + destroyed + '[/color]\n' +
g_CapturedColor + captured + '[/color] / ' +
g_LostColor + lost + '[/color]\n'
}
function formatIncome(income, outcome)
{
return g_IncomeColor + income + '[/color] / ' +
@ -37,6 +45,19 @@ function formatRatio(divident, divisor)
return Math.round(divident / divisor * 100) / 100;
}
/**
* Clean [Color=""], [/Color], white space, + and % for make the sum more easy
* Remove \n only when removeLineFeed == true
*/
function cleanGUICaption(team, player, counter, removeLineFeed = true)
{
let caption = Engine.GetGUIObjectByName("valueDataTeam[" + team + "][" + player + "][" + counter + "]").caption;
if (removeLineFeed)
return caption.replace(/\[([\w\' \\\"\/\=]*)\]|\+|\%|\s/g, "");
else
return caption.replace(/\[([\w\' \\\"\/\=]*)\]|[\t\r \f]/g, "");
}
function updateCountersPlayer(playerState, counters, idGUI)
{
for (let w in counters)
@ -97,7 +118,8 @@ function calculateEconomyScore(playerState)
function calculateMilitaryScore(playerState)
{
return Math.round((playerState.statistics.enemyUnitsKilledValue +
playerState.statistics.enemyBuildingsDestroyedValue) / 10);
playerState.statistics.enemyBuildingsDestroyedValue +
playerState.statistics.buildingsCapturedValue) / 10);
}
function calculateExplorationScore(playerState)
@ -144,14 +166,48 @@ function calculateScoreTeam(counters)
function calculateBuildings(playerState, position)
{
let type = g_BuildingsTypes[position];
return formatTrained(
return formatCaptured(
playerState.statistics.buildingsConstructed[type],
playerState.statistics.buildingsLost[type],
playerState.statistics.enemyBuildingsDestroyed[type]);
playerState.statistics.enemyBuildingsDestroyed[type],
playerState.statistics.buildingsCaptured[type],
playerState.statistics.buildingsLost[type]);
}
function calculateColorsTeam(counters)
function calculateBuildingsTeam(counters)
{
for (let t in g_Teams)
{
if (t == -1)
continue;
for (let w in counters)
{
let total = {
"constructed" : 0,
"destroyed" : 0,
"captured" : 0,
"lost" : 0
};
for (let p = 0; p < g_Teams[t]; ++p)
{
let splitCaption = cleanGUICaption(t, p, w, false).split("\n");
let first = splitCaption[0].split("/");
let second = splitCaption[1].split("/");
total.constructed += +first[0];
total.destroyed += +first[1];
total.captured += +second[0];
total.lost += +second[1];
}
Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]").caption =
formatCaptured(total.constructed, total.destroyed, total.captured, total.lost);
}
}
}
function calculateUnitsTeam(counters)
{
for (let t in g_Teams)
{
@ -168,11 +224,7 @@ function calculateColorsTeam(counters)
for (let p = 0; p < g_Teams[t]; ++p)
{
let caption = Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + p + "][" + w + "]").caption;
// clean [Color=""], [/Color] and white space for make the sum more easy
caption = caption.replace(/\[([\w\' \\\"\/\=]*)\]|\s/g, "");
let splitCaption = caption.split("/");
let splitCaption = cleanGUICaption(t, p, w).split("/");
total.constructed += +splitCaption[0];
total.lost += +splitCaption[1];
@ -251,9 +303,7 @@ function calculateResourcesTeam(counters)
for (let p = 0; p < g_Teams[t]; ++p)
{
let caption = Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + p + "][" + w + "]").caption;
// clean [Color=""], [/Color] and white space for make the sum more easy
caption = caption.replace(/\[([\w\' \\\"\/\=]*)\]|\s/g, "");
let caption = cleanGUICaption(t, p, w);
if (w >= 6)
total.income += +caption;
@ -321,15 +371,13 @@ function calculateMarketTeam(counters)
for (let p = 0; p < g_Teams[t]; ++p)
{
let caption = Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + p + "][" + w + "]").caption;
// clean [Color=""], [/Color], white space, + and % for make the sum more easy
caption = caption.replace(/\[([\w\' \\\"\/\=]*)\]|\s|\+|\%/g, "");
let caption = cleanGUICaption(t, p, w);
if (w >= 4)
total.income += +caption;
else
{
let splitCaption = caption.split("-");
let splitCaption = caption.split("/");
total.income += +splitCaption[0];
total.outcome += +splitCaption[1];
}

View file

@ -9,10 +9,10 @@ var g_ScorePanelsData = {
],
"titleHeadings": [],
"counters": [
{ "width": 100, "fn": calculateEconomyScore },
{ "width": 100, "fn": calculateMilitaryScore },
{ "width": 100, "fn": calculateExplorationScore },
{ "width": 100, "fn": calculateScoreTotal}
{ "width": 100, "fn": calculateEconomyScore, "verticalOffset": 12 },
{ "width": 100, "fn": calculateMilitaryScore, "verticalOffset": 12 },
{ "width": 100, "fn": calculateExplorationScore, "verticalOffset": 12 },
{ "width": 100, "fn": calculateScoreTotal, "verticalOffset": 12 }
],
"teamCounterFn": calculateScoreTeam
},
@ -29,19 +29,29 @@ var g_ScorePanelsData = {
{ "caption": translate("Wonders"), "yStart": 34, "width": 85 }
],
"titleHeadings": [
{ "caption": translate("Buildings Statistics (Constructed / Lost / Destroyed)"), "yStart": 16, "width": (85 * 7 + 105) }, // width = 700
{
"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]'
}),
"yStart": 16,
"width": (85 * 7 + 105)
}, // width = 700
],
"counters": [
{ "width": 105, "fn": calculateBuildings },
{ "width": 85, "fn": calculateBuildings },
{ "width": 85, "fn": calculateBuildings },
{ "width": 85, "fn": calculateBuildings },
{ "width": 85, "fn": calculateBuildings },
{ "width": 85, "fn": calculateBuildings },
{ "width": 85, "fn": calculateBuildings },
{ "width": 85, "fn": calculateBuildings }
{ "width": 105, "fn": calculateBuildings, "verticalOffset": 3 },
{ "width": 85, "fn": calculateBuildings, "verticalOffset": 3 },
{ "width": 85, "fn": calculateBuildings, "verticalOffset": 3 },
{ "width": 85, "fn": calculateBuildings, "verticalOffset": 3 },
{ "width": 85, "fn": calculateBuildings, "verticalOffset": 3 },
{ "width": 85, "fn": calculateBuildings, "verticalOffset": 3 },
{ "width": 85, "fn": calculateBuildings, "verticalOffset": 3 },
{ "width": 85, "fn": calculateBuildings, "verticalOffset": 3 }
],
"teamCounterFn": calculateColorsTeam
"teamCounterFn": calculateBuildingsTeam
},
"units": {
"headings": [
@ -56,19 +66,28 @@ var g_ScorePanelsData = {
{ "caption": translate("Traders"), "yStart": 34, "width": 100 }
],
"titleHeadings": [
{ "caption": translate("Units Statistics (Trained / Lost / Killed)"), "yStart": 16, "width": (100 * 7 + 120) }, // width = 820
{
"caption": sprintf(translate("Units Statistics (%(trained)s / %(lost)s / %(killed)s)"),
{
"trained": g_TrainedColor + translate("Trained") + '[/color]',
"lost": g_LostColor + translate("Lost") + '[/color]',
"killed": g_KilledColor + translate("Killed") + '[/color]'
}),
"yStart": 16,
"width": (100 * 7 + 120)
}, // width = 820
],
"counters": [
{ "width": 120, "fn": calculateUnits },
{ "width": 100, "fn": calculateUnits },
{ "width": 100, "fn": calculateUnits },
{ "width": 100, "fn": calculateUnits },
{ "width": 100, "fn": calculateUnits },
{ "width": 100, "fn": calculateUnits },
{ "width": 100, "fn": calculateUnits },
{ "width": 100, "fn": calculateUnits }
{ "width": 120, "fn": calculateUnits, "verticalOffset": 12 },
{ "width": 100, "fn": calculateUnits, "verticalOffset": 12 },
{ "width": 100, "fn": calculateUnits, "verticalOffset": 12 },
{ "width": 100, "fn": calculateUnits, "verticalOffset": 12 },
{ "width": 100, "fn": calculateUnits, "verticalOffset": 12 },
{ "width": 100, "fn": calculateUnits, "verticalOffset": 12 },
{ "width": 100, "fn": calculateUnits, "verticalOffset": 12 },
{ "width": 100, "fn": calculateUnits, "verticalOffset": 12 }
],
"teamCounterFn": calculateColorsTeam
"teamCounterFn": calculateUnitsTeam
},
"resources": {
"headings": [
@ -78,22 +97,38 @@ var g_ScorePanelsData = {
{ "caption": translate("Stone"), "yStart": 34, "width": 100 },
{ "caption": translate("Metal"), "yStart": 34, "width": 100 },
{ "caption": translate("Total"), "yStart": 34, "width": 110 },
{ "caption": translate("Tributes (Sent / Received)"), "yStart": 16, "width": 121 },
{
"caption": sprintf(translate("Tributes \n(%(sent)s / %(received)s)"),
{
"sent": g_IncomeColor + translate("Sent") + '[/color]',
"received": g_OutcomeColor + translate("Received") + '[/color]'
}),
"yStart": 16,
"width": 121
},
{ "caption": translate("Treasures collected"), "yStart": 16, "width": 100 },
{ "caption": translate("Loot"), "yStart": 16, "width": 100 }
],
"titleHeadings": [
{ "caption": translate("Resource Statistics (Gathered / Used)"), "yStart": 16, "width": (100 * 4 + 110) }, // width = 510
{
"caption": sprintf(translate("Resource Statistics (%(gathered)s / %(used)s)"),
{
"gathered": g_IncomeColor + translate("Gathered") + '[/color]',
"used": g_OutcomeColor + translate("Used") + '[/color]'
}),
"yStart": 16,
"width": (100 * 4 + 110)
}, // width = 510
],
"counters": [
{ "width": 100, "fn": calculateResources },
{ "width": 100, "fn": calculateResources },
{ "width": 100, "fn": calculateResources },
{ "width": 100, "fn": calculateResources },
{ "width": 110, "fn": calculateTotalResources },
{ "width": 121, "fn": calculateTributeSent },
{ "width": 100, "fn": calculateTreasureCollected },
{ "width": 100, "fn": calculateLootCollected }
{ "width": 100, "fn": calculateResources, "verticalOffset": 12 },
{ "width": 100, "fn": calculateResources, "verticalOffset": 12 },
{ "width": 100, "fn": calculateResources, "verticalOffset": 12 },
{ "width": 100, "fn": calculateResources, "verticalOffset": 12 },
{ "width": 110, "fn": calculateTotalResources, "verticalOffset": 12 },
{ "width": 121, "fn": calculateTributeSent, "verticalOffset": 12 },
{ "width": 100, "fn": calculateTreasureCollected, "verticalOffset": 12 },
{ "width": 100, "fn": calculateLootCollected, "verticalOffset": 12 }
],
"teamCounterFn": calculateResourcesTeam
},
@ -109,12 +144,12 @@ var g_ScorePanelsData = {
],
"titleHeadings": [],
"counters": [
{ "width": 100, "fn": calculateResourceExchanged },
{ "width": 100, "fn": calculateResourceExchanged },
{ "width": 100, "fn": calculateResourceExchanged },
{ "width": 100, "fn": calculateResourceExchanged },
{ "width": 100, "fn": calculateBarterEfficiency },
{ "width": 100, "fn": calculateTradeIncome }
{ "width": 100, "fn": calculateResourceExchanged, "verticalOffset": 12 },
{ "width": 100, "fn": calculateResourceExchanged, "verticalOffset": 12 },
{ "width": 100, "fn": calculateResourceExchanged, "verticalOffset": 12 },
{ "width": 100, "fn": calculateResourceExchanged, "verticalOffset": 12 },
{ "width": 100, "fn": calculateBarterEfficiency, "verticalOffset": 12 },
{ "width": 100, "fn": calculateTradeIncome, "verticalOffset": 12 }
],
"teamCounterFn": calculateMarketTeam
},
@ -132,12 +167,12 @@ var g_ScorePanelsData = {
{ "caption": translate("Map control"), "xOffset": 400, "yStart": 16, "width": 200 }
],
"counters": [
{ "width": 100, "fn": calculateVegetarianRatio },
{ "width": 100, "fn": calculateFeminization },
{ "width": 100, "fn": calculateKillDeathRatio },
{ "width": 100, "fn": calculateMapExploration },
{ "width": 100, "fn": calculateMapPeakControl },
{ "width": 100, "fn": calculateMapFinalControl }
{ "width": 100, "fn": calculateVegetarianRatio, "verticalOffset": 12 },
{ "width": 100, "fn": calculateFeminization, "verticalOffset": 12 },
{ "width": 100, "fn": calculateKillDeathRatio, "verticalOffset": 12 },
{ "width": 100, "fn": calculateMapExploration, "verticalOffset": 12 },
{ "width": 100, "fn": calculateMapPeakControl, "verticalOffset": 12 },
{ "width": 100, "fn": calculateMapFinalControl, "verticalOffset": 12 }
],
"teamCounterFn": calculateMiscellaneous
}
@ -214,7 +249,7 @@ function updateGeneralPanelCounter(counters)
for (let w in counters)
{
counterObject = Engine.GetGUIObjectByName("valueData[" + p + "][" + w + "]");
counterObject.size = left + " 6 " + (left + counters[w].width) + " 100%";
counterObject.size = left + " " + counters[w].verticalOffset + " " + (left + counters[w].width) + " 100%";
counterObject.hidden = false;
left += counters[w].width;
}
@ -229,12 +264,12 @@ function updateGeneralPanelCounter(counters)
for (let w in counters)
{
counterObject = Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + p + "][" + w + "]");
counterObject.size = left + " 6 " + (left + counters[w].width) + " 100%";
counterObject.size = left + " " + counters[w].verticalOffset + " " + (left + counters[w].width) + " 100%";
counterObject.hidden = false;
if (g_Teams[t])
{
let yStart = 30 + g_Teams[t] * (g_PlayerBoxYSize + g_PlayerBoxGap) + 2;
let yStart = 25 + g_Teams[t] * (g_PlayerBoxYSize + g_PlayerBoxGap) + 3 + counters[w].verticalOffset;
counterTotalObject = Engine.GetGUIObjectByName("valueDataTeam[" + t + "][" + w + "]");
counterTotalObject.size = (left + 20) + " " + yStart + " " + (left + counters[w].width) + " 100%";
counterTotalObject.hidden = false;
@ -272,8 +307,8 @@ function updateGeneralPanelTeams()
Engine.GetGUIObjectByName("teamNameHeadingt["+i+"]").caption = "Team "+(i+1);
let teamHeading = Engine.GetGUIObjectByName("teamHeadingt["+i+"]");
let yStartTotal = 30 + g_Teams[i] * (g_PlayerBoxYSize + g_PlayerBoxGap) + 2;
teamHeading.size = "50 "+yStartTotal+" 100% "+(yStartTotal+20);
let yStartTotal = 30 + g_Teams[i] * (g_PlayerBoxYSize + g_PlayerBoxGap) + 10;
teamHeading.size = "50 " + yStartTotal + " 100% " + (yStartTotal + 20);
teamHeading.caption = translate("Team total");
}

View file

@ -3,16 +3,17 @@ const g_MaxHeadingTitle= 8;
// const for filtering long collective headings
const g_LongHeadingWidth = 250;
const g_PlayerBoxYSize = 30;
const g_PlayerBoxYSize = 40;
const g_PlayerBoxGap = 2;
const g_PlayerBoxAlpha = " 32";
const g_PlayerColorBoxAlpha = " 255";
const g_TeamsBoxYStart = 65;
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", "Ship", "Trader" ];

View file

@ -14,9 +14,11 @@
<!-- After settings.js, which defines g_Settings and g_MaxPlayers. -->
<script file="gui/summary/counters.js"/>
<script file="gui/summary/layout.js"/>
<script file="gui/summary/summary.js"/>
<!-- Needs the colors from summary.js -->
<script file="gui/summary/layout.js"/>
<object name="summaryWindow"
type="image"
style="ModernWindow"
@ -123,9 +125,11 @@
<object size="0 30 100% 100%">
<repeat count="8" var="n">
<object type="image" name="playerBoxt[i][n]" size="10 0 10 30" hidden="true">
<object name="playerColorBoxt[i][n]" type="image" size="10 4 30 24"/>
<object name="playerNamet[i][n]" type="text" size="40 2 208 100%" style="ModernLeftLabelText" />
<object name="civIcont[i][n]" type="image" size="208 0 240 32"/>
<object type="image" sprite="ForegroundBox" size="10 9 34 33">
<object name="playerColorBoxt[i][n]" type="image" size="2 2 22 22"/>
</object>
<object name="playerNamet[i][n]" type="text" size="40 2 208 100%" style="ModernLeftLabelText"/>
<object name="civIcont[i][n]" type="image" size="208 5 240 37" />
<repeat var="x" count="8">
<object name="valueDataTeam[i][n][x]" type="text" style="ModernTabLabelText">
</object>
@ -144,11 +148,11 @@
<object type="image" name="noTeamsBox" size="0 65 100% 100%-50" hidden="true">
<repeat count="8">
<object type="image" name="playerBox[n]" size="10 0 10 30" hidden="true">
<object type="image" sprite="ForegroundBox" size="10 4 34 28">
<object type="image" sprite="ForegroundBox" size="10 9 34 33">
<object name="playerColorBox[n]" type="image" size="2 2 22 22"/>
</object>
<object name="playerName[n]" type="text" size="40 2 208 100%" style="ModernLeftLabelText"/>
<object name="civIcon[n]" type="image" size="208 0 240 32"/>
<object name="civIcon[n]" type="image" size="208 5 240 37"/>
<repeat var="x" count="8">
<object name="valueData[n][x]" type="text" style="ModernTabLabelText">
</object>

View file

@ -151,7 +151,15 @@ Capturable.prototype.RegisterCapturePointsChanged = function()
if (this.cp[i] >= this.cp[bestPlayer])
bestPlayer = +i;
let cmpLostPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
if (cmpLostPlayerStatisticsTracker)
cmpLostPlayerStatisticsTracker.LostEntity(this.entity);
cmpOwnership.SetOwner(bestPlayer);
let cmpCapturedPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
if (cmpCapturedPlayerStatisticsTracker)
cmpCapturedPlayerStatisticsTracker.CapturedBuilding(this.entity);
};
Capturable.prototype.GetRegenRate = function()

View file

@ -79,7 +79,7 @@ StatisticsTracker.prototype.Init = function()
"CivCentre": 0,
"Wonder": 0,
"total": 0
};
};
this.buildingsLostValue = 0;
this.enemyBuildingsDestroyed = {
"House": 0,
@ -90,8 +90,19 @@ StatisticsTracker.prototype.Init = function()
"CivCentre": 0,
"Wonder": 0,
"total": 0
};
};
this.enemyBuildingsDestroyedValue = 0;
this.buildingsCaptured = {
"House": 0,
"Economic": 0,
"Outpost": 0,
"Military": 0,
"Fortress": 0,
"CivCentre": 0,
"Wonder": 0,
"total": 0
};
this.buildingsCapturedValue = 0;
this.resourcesGathered = {
"food": 0,
@ -157,6 +168,8 @@ StatisticsTracker.prototype.GetStatistics = function()
"buildingsLostValue": this.buildingsLostValue,
"enemyBuildingsDestroyed": this.enemyBuildingsDestroyed,
"enemyBuildingsDestroyedValue": this.enemyBuildingsDestroyedValue,
"buildingsCaptured": this.buildingsCaptured,
"buildingsCapturedValue": this.buildingsCapturedValue,
"resourcesGathered": this.resourcesGathered,
"resourcesUsed": this.resourcesUsed,
"resourcesSold": this.resourcesSold,
@ -295,6 +308,26 @@ StatisticsTracker.prototype.LostEntity = function(lostEntity)
}
};
StatisticsTracker.prototype.CapturedBuilding = function(capturedBuilding)
{
let cmpCapturedBuildingIdentity = Engine.QueryInterface(capturedBuilding, IID_Identity);
if (!cmpCapturedBuildingIdentity)
return;
for (let type of this.buildingsClasses)
this.CounterIncrement(cmpCapturedBuildingIdentity, "buildingsCaptured", type);
++this.buildingsCaptured.total;
let cmpCost = Engine.QueryInterface(capturedBuilding, IID_Cost);
if (!cmpCost)
return;
let costs = cmpCost.GetResourceCosts();
for (let type in costs)
this.buildingsCapturedValue += costs[type];
};
/**
* @param type Generic type of resource (string)
* @param amount Amount of resource, whick should be added (integer)

View file

@ -126,6 +126,7 @@ AddMock(100, IID_StatisticsTracker, {
"unitsTrained": 10,
"unitsLost": 9,
"buildingsConstructed": 5,
"buildingsCaptured": 7,
"buildingsLost": 4,
"civCentresBuilt": 1,
"resourcesGathered": {
@ -208,6 +209,7 @@ AddMock(101, IID_StatisticsTracker, {
"unitsTrained": 10,
"unitsLost": 9,
"buildingsConstructed": 5,
"buildingsCaptured": 7,
"buildingsLost": 4,
"civCentresBuilt": 1,
"resourcesGathered": {
@ -362,6 +364,7 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
unitsTrained: 10,
unitsLost: 9,
buildingsConstructed: 5,
buildingsCaptured: 7,
buildingsLost: 4,
civCentresBuilt: 1,
resourcesGathered: {
@ -415,6 +418,7 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
unitsTrained: 10,
unitsLost: 9,
buildingsConstructed: 5,
buildingsCaptured: 7,
buildingsLost: 4,
civCentresBuilt: 1,
resourcesGathered: {