mirror of
https://github.com/vcmi/vcmi.git
synced 2026-06-19 22:57:37 +02:00
Merge pull request #5882 from Laserlicht/save_stat
Statistics in highscore screen
This commit is contained in:
@@ -37,10 +37,13 @@
|
||||
#include "../../lib/gameState/HighScore.h"
|
||||
#include "../../lib/gameState/GameStatistics.h"
|
||||
#include "../../lib/GameLibrary.h"
|
||||
#include "../../lib/serializer/JsonSerializer.h"
|
||||
#include "../../lib/serializer/JsonDeserializer.h"
|
||||
|
||||
CHighScoreScreen::CHighScoreScreen(HighScorePage highscorepage, int highlighted)
|
||||
: CWindowObject(BORDERED), highscorepage(highscorepage), highlighted(highlighted)
|
||||
{
|
||||
addUsedEvents(LCLICK);
|
||||
addUsedEvents(SHOW_POPUP);
|
||||
|
||||
OBJECT_CONSTRUCTION;
|
||||
@@ -50,7 +53,7 @@ CHighScoreScreen::CHighScoreScreen(HighScorePage highscorepage, int highlighted)
|
||||
addButtons();
|
||||
}
|
||||
|
||||
void CHighScoreScreen::showPopupWindow(const Point & cursorPosition)
|
||||
void CHighScoreScreen::rowEvent(std::function<void(int row, bool currentGameNotInListEntry)> func, const Point & cursorPosition)
|
||||
{
|
||||
for (int i = 0; i < screenRows; i++)
|
||||
{
|
||||
@@ -58,14 +61,33 @@ void CHighScoreScreen::showPopupWindow(const Point & cursorPosition)
|
||||
|
||||
Rect r = Rect(80, 40 + i * 50, 635, 50);
|
||||
if(r.isInside(cursorPosition - pos))
|
||||
{
|
||||
std::string tmp = persistentStorage["highscore"][highscorepage == HighScorePage::SCENARIO ? "scenario" : "campaign"][currentGameNotInListEntry ? highlighted : i]["datetime"].String();
|
||||
if(!tmp.empty())
|
||||
CRClickPopup::createAndPush(tmp);
|
||||
}
|
||||
func(i, currentGameNotInListEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void CHighScoreScreen::clickPressed(const Point & cursorPosition)
|
||||
{
|
||||
rowEvent([this](int row, bool currentGameNotInListEntry){
|
||||
auto node = persistentStorage["highscore"][highscorepage == HighScorePage::SCENARIO ? "scenario" : "campaign"][currentGameNotInListEntry ? highlighted : row];
|
||||
if(node["statistic"].isNull())
|
||||
return;
|
||||
|
||||
JsonDeserializer ser(nullptr, node);
|
||||
StatisticDataSet stat;
|
||||
ser.serializeStruct("statistic", stat);
|
||||
ENGINE->windows().createAndPushWindow<CStatisticScreen>(stat);
|
||||
}, cursorPosition);
|
||||
}
|
||||
|
||||
void CHighScoreScreen::showPopupWindow(const Point & cursorPosition)
|
||||
{
|
||||
rowEvent([this](int row, bool currentGameNotInListEntry){
|
||||
std::string tmp = persistentStorage["highscore"][highscorepage == HighScorePage::SCENARIO ? "scenario" : "campaign"][currentGameNotInListEntry ? highlighted : row]["datetime"].String();
|
||||
if(!tmp.empty())
|
||||
CRClickPopup::createAndPush("{" + LIBRARY->generaltexth->translate("core.help.316.hover") + "}\n\n" + tmp);
|
||||
}, cursorPosition);
|
||||
}
|
||||
|
||||
void CHighScoreScreen::addButtons()
|
||||
{
|
||||
OBJECT_CONSTRUCTION;
|
||||
@@ -251,6 +273,15 @@ int CHighScoreInputScreen::addEntry(std::string text) {
|
||||
newNode["points"].Integer() = calc.calculate().cheater ? 0 : calc.calculate().total;
|
||||
newNode["datetime"].String() = TextOperations::getFormattedDateTimeLocal(std::time(nullptr));
|
||||
newNode["posFlag"].Bool() = true;
|
||||
if(!calc.isCampaign)
|
||||
{
|
||||
JsonSerializer ser(nullptr, newNode);
|
||||
ser.serializeStruct("statistic", stat);
|
||||
}
|
||||
|
||||
int highscoreEntriesCap = settings["general"]["highscoreEntriesCap"].Integer();
|
||||
if (baseNode.size() > highscoreEntriesCap - 1)
|
||||
baseNode.resize(highscoreEntriesCap - 1);
|
||||
|
||||
baseNode.push_back(newNode);
|
||||
boost::range::sort(baseNode, sortFunctor);
|
||||
@@ -258,6 +289,9 @@ int CHighScoreInputScreen::addEntry(std::string text) {
|
||||
int pos = -1;
|
||||
for (int i = 0; i < baseNode.size(); i++)
|
||||
{
|
||||
if(!baseNode[i]["statistic"].isNull() && i >= settings["general"]["highscoreStatisticEntriesCap"].Integer() && baseNode[i]["posFlag"].isNull())
|
||||
baseNode[i]["statistic"].clear();
|
||||
|
||||
if(!baseNode[i]["posFlag"].isNull())
|
||||
{
|
||||
baseNode[i]["posFlag"].clear();
|
||||
|
||||
@@ -38,6 +38,9 @@ private:
|
||||
void buttonResetClick();
|
||||
void buttonExitClick();
|
||||
|
||||
void rowEvent(std::function<void(int row, bool currentGameNotInListEntry)> func, const Point & cursorPosition);
|
||||
|
||||
void clickPressed(const Point & cursorPosition) override;
|
||||
void showPopupWindow(const Point & cursorPosition) override;
|
||||
void showAll(Canvas & to) override;
|
||||
|
||||
|
||||
@@ -46,7 +46,9 @@
|
||||
"enableOverlay",
|
||||
"lastKindomInterface",
|
||||
"enableSubtitle",
|
||||
"ignoreMuteSwitch"
|
||||
"ignoreMuteSwitch",
|
||||
"highscoreEntriesCap",
|
||||
"highscoreStatisticEntriesCap"
|
||||
],
|
||||
"properties" : {
|
||||
"playerName" : {
|
||||
@@ -166,6 +168,14 @@
|
||||
"ignoreMuteSwitch" : {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"highscoreEntriesCap" : {
|
||||
"type" : "number",
|
||||
"default" : 100
|
||||
},
|
||||
"highscoreStatisticEntriesCap" : {
|
||||
"type" : "number",
|
||||
"default" : 15
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "../mapObjects/MiscObjects.h"
|
||||
#include "../mapping/CMap.h"
|
||||
#include "../entities/building/CBuilding.h"
|
||||
#include "../serializer/JsonDeserializer.h"
|
||||
#include "../serializer/JsonUpdater.h"
|
||||
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@@ -79,6 +81,79 @@ StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, cons
|
||||
return data;
|
||||
}
|
||||
|
||||
void StatisticDataSetEntry::serializeJson(JsonSerializeFormat & handler)
|
||||
{
|
||||
handler.serializeString("map", map);
|
||||
handler.serializeInt("timestamp", timestamp);
|
||||
handler.serializeInt("day", day);
|
||||
handler.serializeId("player", player, PlayerColor::CANNOT_DETERMINE);
|
||||
handler.serializeString("playerName", playerName);
|
||||
handler.serializeInt("team", team);
|
||||
handler.serializeBool("isHuman", isHuman);
|
||||
handler.serializeEnum("status", status, {"ingame", "loser", "winner"});
|
||||
resources.serializeJson(handler, "resources");
|
||||
handler.serializeInt("numberHeroes", numberHeroes);
|
||||
handler.serializeInt("numberTowns", numberTowns);
|
||||
handler.serializeInt("numberArtifacts", numberArtifacts);
|
||||
handler.serializeInt("numberDwellings", numberDwellings);
|
||||
handler.serializeInt("armyStrength", armyStrength);
|
||||
handler.serializeInt("totalExperience", totalExperience);
|
||||
handler.serializeInt("income", income);
|
||||
handler.serializeFloat("mapExploredRatio", mapExploredRatio);
|
||||
handler.serializeFloat("obeliskVisitedRatio", obeliskVisitedRatio);
|
||||
handler.serializeFloat("townBuiltRatio", townBuiltRatio);
|
||||
handler.serializeBool("hasGrail", hasGrail);
|
||||
{
|
||||
auto zonesData = handler.enterStruct("numMines");
|
||||
for(TResource idx = 0; idx < (GameConstants::RESOURCE_QUANTITY - 1); idx++)
|
||||
handler.serializeInt(GameConstants::RESOURCE_NAMES[idx], numMines[idx], 0);
|
||||
}
|
||||
handler.serializeInt("score", score);
|
||||
handler.serializeInt("maxHeroLevel", maxHeroLevel);
|
||||
handler.serializeInt("numBattlesNeutral", numBattlesNeutral);
|
||||
handler.serializeInt("numBattlesPlayer", numBattlesPlayer);
|
||||
handler.serializeInt("numWinBattlesNeutral", numWinBattlesNeutral);
|
||||
handler.serializeInt("numWinBattlesPlayer", numWinBattlesPlayer);
|
||||
handler.serializeInt("numHeroSurrendered", numHeroSurrendered);
|
||||
handler.serializeInt("numHeroEscaped", numHeroEscaped);
|
||||
spentResourcesForArmy.serializeJson(handler, "spentResourcesForArmy");
|
||||
spentResourcesForBuildings.serializeJson(handler, "spentResourcesForBuildings");
|
||||
tradeVolume.serializeJson(handler, "tradeVolume");
|
||||
handler.serializeBool("eventCapturedTown", eventCapturedTown);
|
||||
handler.serializeBool("eventDefeatedStrongestHero", eventDefeatedStrongestHero);
|
||||
handler.serializeInt("movementPointsUsed", movementPointsUsed);
|
||||
}
|
||||
|
||||
void StatisticDataSet::PlayerAccumulatedValueStorage::serializeJson(JsonSerializeFormat & handler)
|
||||
{
|
||||
handler.serializeInt("numBattlesNeutral", numBattlesNeutral);
|
||||
handler.serializeInt("numBattlesPlayer", numBattlesPlayer);
|
||||
handler.serializeInt("numWinBattlesNeutral", numWinBattlesNeutral);
|
||||
handler.serializeInt("numWinBattlesPlayer", numWinBattlesPlayer);
|
||||
handler.serializeInt("numHeroSurrendered", numHeroSurrendered);
|
||||
handler.serializeInt("numHeroEscaped", numHeroEscaped);
|
||||
spentResourcesForArmy.serializeJson(handler, "spentResourcesForArmy");
|
||||
spentResourcesForBuildings.serializeJson(handler, "spentResourcesForBuildings");
|
||||
tradeVolume.serializeJson(handler, "tradeVolume");
|
||||
handler.serializeInt("movementPointsUsed", movementPointsUsed);
|
||||
handler.serializeInt("lastCapturedTownDay", lastCapturedTownDay);
|
||||
handler.serializeInt("lastDefeatedStrongestHeroDay", lastDefeatedStrongestHeroDay);
|
||||
}
|
||||
|
||||
void StatisticDataSet::serializeJson(JsonSerializeFormat & handler)
|
||||
{
|
||||
{
|
||||
auto eventsHandler = handler.enterArray("data");
|
||||
eventsHandler.syncSize(data, JsonNode::JsonType::DATA_VECTOR);
|
||||
eventsHandler.serializeStruct(data);
|
||||
}
|
||||
{
|
||||
auto eventsHandler = handler.enterStruct("accumulatedValues");
|
||||
for(auto & val : accumulatedValues)
|
||||
eventsHandler->serializeStruct(GameConstants::PLAYER_COLOR_NAMES[val.first], val.second);
|
||||
}
|
||||
}
|
||||
|
||||
std::string StatisticDataSet::toCsv(std::string sep) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
@@ -57,6 +57,8 @@ struct DLL_LINKAGE StatisticDataSetEntry
|
||||
bool eventDefeatedStrongestHero;
|
||||
si64 movementPointsUsed;
|
||||
|
||||
void serializeJson(JsonSerializeFormat & handler);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & map;
|
||||
@@ -105,6 +107,8 @@ public:
|
||||
std::string toCsv(std::string sep) const;
|
||||
std::string writeCsv() const;
|
||||
|
||||
void serializeJson(JsonSerializeFormat & handler);
|
||||
|
||||
struct PlayerAccumulatedValueStorage // holds some actual values needed for stats
|
||||
{
|
||||
int numBattlesNeutral;
|
||||
@@ -120,6 +124,8 @@ public:
|
||||
int lastCapturedTownDay;
|
||||
int lastDefeatedStrongestHeroDay;
|
||||
|
||||
void serializeJson(JsonSerializeFormat & handler);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h)
|
||||
{
|
||||
h & numBattlesNeutral;
|
||||
|
||||
Reference in New Issue
Block a user