mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-21 00:19:29 +02:00
Statistics is now managed as part of CGameHandler
This commit is contained in:
@ -83,8 +83,6 @@ public:
|
||||
CBonusSystemNode globalEffects;
|
||||
RumorState currentRumor;
|
||||
|
||||
StatisticDataSet statistic;
|
||||
|
||||
// NOTE: effectively AI mutex, only used by adventure map AI
|
||||
static std::shared_mutex mutex;
|
||||
|
||||
@ -185,7 +183,11 @@ public:
|
||||
std::map<ArtifactID, int> allocatedArtifactsUnused;
|
||||
h & allocatedArtifactsUnused;
|
||||
}
|
||||
if (!h.hasFeature(Handler::Version::SERVER_STATISTICS))
|
||||
{
|
||||
StatisticDataSet statistic;
|
||||
h & statistic;
|
||||
}
|
||||
|
||||
if(!h.saving && h.loadingGamestate)
|
||||
restoreBonusSystemTree();
|
||||
|
@ -31,7 +31,7 @@ void StatisticDataSet::add(StatisticDataSetEntry entry)
|
||||
data.push_back(entry);
|
||||
}
|
||||
|
||||
StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, const CGameState * gs)
|
||||
StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, const CGameState * gs, const StatisticDataSet & accumulatedData)
|
||||
{
|
||||
StatisticDataSetEntry data;
|
||||
|
||||
@ -63,18 +63,18 @@ StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, cons
|
||||
data.numMines = Statistic::getNumMines(gs, ps);
|
||||
data.score = scenarioHighScores.calculate().total;
|
||||
data.maxHeroLevel = Statistic::findBestHero(gs, ps->color) ? Statistic::findBestHero(gs, ps->color)->level : 0;
|
||||
data.numBattlesNeutral = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).numBattlesNeutral : 0;
|
||||
data.numBattlesPlayer = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).numBattlesPlayer : 0;
|
||||
data.numWinBattlesNeutral = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).numWinBattlesNeutral : 0;
|
||||
data.numWinBattlesPlayer = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).numWinBattlesPlayer : 0;
|
||||
data.numHeroSurrendered = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).numHeroSurrendered : 0;
|
||||
data.numHeroEscaped = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).numHeroEscaped : 0;
|
||||
data.spentResourcesForArmy = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).spentResourcesForArmy : TResources();
|
||||
data.spentResourcesForBuildings = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).spentResourcesForBuildings : TResources();
|
||||
data.tradeVolume = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).tradeVolume : TResources();
|
||||
data.eventCapturedTown = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).lastCapturedTownDay == gs->getDate(Date::DAY) : false;
|
||||
data.eventDefeatedStrongestHero = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).lastDefeatedStrongestHeroDay == gs->getDate(Date::DAY) : false;
|
||||
data.movementPointsUsed = gs->statistic.accumulatedValues.count(ps->color) ? gs->statistic.accumulatedValues.at(ps->color).movementPointsUsed : 0;
|
||||
data.numBattlesNeutral = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).numBattlesNeutral : 0;
|
||||
data.numBattlesPlayer = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).numBattlesPlayer : 0;
|
||||
data.numWinBattlesNeutral = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).numWinBattlesNeutral : 0;
|
||||
data.numWinBattlesPlayer = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).numWinBattlesPlayer : 0;
|
||||
data.numHeroSurrendered = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).numHeroSurrendered : 0;
|
||||
data.numHeroEscaped = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).numHeroEscaped : 0;
|
||||
data.spentResourcesForArmy = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).spentResourcesForArmy : TResources();
|
||||
data.spentResourcesForBuildings = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).spentResourcesForBuildings : TResources();
|
||||
data.tradeVolume = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).tradeVolume : TResources();
|
||||
data.eventCapturedTown = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).lastCapturedTownDay == gs->getDate(Date::DAY) : false;
|
||||
data.eventDefeatedStrongestHero = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).lastDefeatedStrongestHeroDay == gs->getDate(Date::DAY) : false;
|
||||
data.movementPointsUsed = accumulatedData.accumulatedValues.count(ps->color) ? accumulatedData.accumulatedValues.at(ps->color).movementPointsUsed : 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ class DLL_LINKAGE StatisticDataSet
|
||||
{
|
||||
public:
|
||||
void add(StatisticDataSetEntry entry);
|
||||
static StatisticDataSetEntry createEntry(const PlayerState * ps, const CGameState * gs);
|
||||
static StatisticDataSetEntry createEntry(const PlayerState * ps, const CGameState * gs, const StatisticDataSet & accumulatedData);
|
||||
std::string toCsv(std::string sep) const;
|
||||
std::string writeCsv() const;
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
/// - change 'CURRENT' to 'CURRENT = NEW_TEST_KEY'.
|
||||
///
|
||||
/// To check for version in serialize() call use form
|
||||
/// if (h.version >= Handler::Version::NEW_TEST_KEY)
|
||||
/// if (h.hasFeature(Handler::Version::NEW_TEST_KEY))
|
||||
/// h & newKey; // loading/saving save of a new version
|
||||
/// else
|
||||
/// newKey = saneDefaultValue; // loading of old save
|
||||
@ -43,8 +43,9 @@ enum class ESerializationVersion : int32_t
|
||||
FLAGGABLE_BONUS_SYSTEM_NODE, // flaggable objects now contain bonus system node
|
||||
RANDOMIZATION_REWORK, // random rolls logic has been moved to server
|
||||
CUSTOM_BONUS_ICONS, // support for custom icons in bonuses
|
||||
SERVER_STATISTICS, // statistics now only saved on server
|
||||
|
||||
CURRENT = CUSTOM_BONUS_ICONS,
|
||||
CURRENT = SERVER_STATISTICS,
|
||||
};
|
||||
|
||||
static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!");
|
||||
|
@ -519,6 +519,7 @@ CGameHandler::CGameHandler(CVCMIServer * lobby)
|
||||
, complainInvalidSlot("Invalid slot accessed!")
|
||||
, turnTimerHandler(std::make_unique<TurnTimerHandler>(*this))
|
||||
, newTurnProcessor(std::make_unique<NewTurnProcessor>(this))
|
||||
, statistics(std::make_unique<StatisticDataSet>())
|
||||
{
|
||||
QID = 1;
|
||||
|
||||
@ -620,7 +621,7 @@ void CGameHandler::addStatistics(StatisticDataSet &stat) const
|
||||
if (elem.first == PlayerColor::NEUTRAL || !elem.first.isValidPlayer())
|
||||
continue;
|
||||
|
||||
auto data = StatisticDataSet::createEntry(&elem.second, &gameState());
|
||||
auto data = StatisticDataSet::createEntry(&elem.second, &gameState(), *statistics);
|
||||
|
||||
stat.add(data);
|
||||
}
|
||||
@ -649,7 +650,7 @@ void CGameHandler::onNewTurn()
|
||||
}
|
||||
else
|
||||
{
|
||||
addStatistics(gameState().statistic); // write at end of turn
|
||||
addStatistics(*statistics); // write at end of turn
|
||||
}
|
||||
|
||||
for (const auto & townID : gameState().getMap().getAllTowns())
|
||||
@ -1035,7 +1036,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
|
||||
|
||||
turnTimerHandler->setEndTurnAllowed(h->getOwner(), !movingOntoWater && !movingOntoObstacle);
|
||||
doMove(TryMoveHero::SUCCESS, lookForGuards, visitDest, LEAVING_TILE);
|
||||
gameState().statistic.accumulatedValues[asker].movementPointsUsed += tmh.movePoints;
|
||||
statistics->accumulatedValues[asker].movementPointsUsed += tmh.movePoints;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1079,7 +1080,7 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, const PlayerColor owne
|
||||
const CGTownInstance * town = dynamic_cast<const CGTownInstance *>(obj);
|
||||
if (town) //town captured
|
||||
{
|
||||
gameState().statistic.accumulatedValues[owner].lastCapturedTownDay = gameState().getDate(Date::DAY);
|
||||
statistics->accumulatedValues[owner].lastCapturedTownDay = gameState().getDate(Date::DAY);
|
||||
|
||||
if (owner.isValidPlayer()) //new owner is real player
|
||||
{
|
||||
@ -1489,7 +1490,7 @@ void CGameHandler::sendToAllClients(CPackForClient & pack)
|
||||
void CGameHandler::sendAndApply(CPackForClient & pack)
|
||||
{
|
||||
sendToAllClients(pack);
|
||||
gameState().apply(pack);
|
||||
gs->apply(pack);
|
||||
logNetwork->trace("\tApplied on gameState(): %s", typeid(pack).name());
|
||||
}
|
||||
|
||||
@ -1646,8 +1647,8 @@ bool CGameHandler::load(const std::string & filename)
|
||||
gameLobby().announceMessage(str);
|
||||
return false;
|
||||
}
|
||||
gameState().preInit(LIBRARY);
|
||||
gameState().updateOnLoad(gameLobby().si.get());
|
||||
gs->preInit(LIBRARY);
|
||||
gs->updateOnLoad(gameLobby().si.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2229,7 +2230,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
|
||||
if(!force)
|
||||
{
|
||||
giveResources(t->tempOwner, -requestedBuilding->resources);
|
||||
gameState().statistic.accumulatedValues[t->tempOwner].spentResourcesForBuildings += requestedBuilding->resources;
|
||||
statistics->accumulatedValues[t->tempOwner].spentResourcesForBuildings += requestedBuilding->resources;
|
||||
}
|
||||
|
||||
//We know what has been built, apply changes. Do this as final step to properly update town window
|
||||
@ -2429,7 +2430,7 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst
|
||||
//recruit
|
||||
TResources cost = (c->getFullRecruitCost() * cram);
|
||||
giveResources(army->tempOwner, -cost);
|
||||
gameState().statistic.accumulatedValues[army->tempOwner].spentResourcesForArmy += cost;
|
||||
statistics->accumulatedValues[army->tempOwner].spentResourcesForArmy += cost;
|
||||
|
||||
SetAvailableCreatures sac;
|
||||
sac.tid = objid;
|
||||
@ -2492,7 +2493,7 @@ bool CGameHandler::upgradeCreature(ObjectInstanceID objid, SlotID pos, CreatureI
|
||||
|
||||
//take resources
|
||||
giveResources(player, -totalCost);
|
||||
gameState().statistic.accumulatedValues[player].spentResourcesForArmy += totalCost;
|
||||
statistics->accumulatedValues[player].spentResourcesForArmy += totalCost;
|
||||
|
||||
//upgrade creature
|
||||
changeStackType(StackLocation(obj->id, pos), upgID.toCreature());
|
||||
@ -3194,8 +3195,8 @@ bool CGameHandler::tradeResources(const IMarket *market, ui32 amountToSell, Play
|
||||
giveResource(player, toSell, -b1 * amountToBoy);
|
||||
giveResource(player, toBuy, b2 * amountToBoy);
|
||||
|
||||
gameState().statistic.accumulatedValues[player].tradeVolume[toSell] += -b1 * amountToBoy;
|
||||
gameState().statistic.accumulatedValues[player].tradeVolume[toBuy] += b2 * amountToBoy;
|
||||
statistics->accumulatedValues[player].tradeVolume[toSell] += -b1 * amountToBoy;
|
||||
statistics->accumulatedValues[player].tradeVolume[toBuy] += b2 * amountToBoy;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -3568,7 +3569,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
|
||||
PlayerEndsGame peg;
|
||||
peg.player = player;
|
||||
peg.victoryLossCheckResult = victoryLossCheckResult;
|
||||
peg.statistic = StatisticDataSet(gameState().statistic);
|
||||
peg.statistic = *statistics;
|
||||
addStatistics(peg.statistic); // add last turn befor win / loss
|
||||
sendAndApply(peg);
|
||||
|
||||
@ -4288,7 +4289,7 @@ std::shared_ptr<CGObjectInstance> CGameHandler::createNewObject(const int3 & vis
|
||||
auto o = handler->create(&gameInfo(), nullptr);
|
||||
handler->configureObject(o.get(), *randomizer);
|
||||
assert(o->ID == objectID);
|
||||
gameState().getMap().generateUniqueInstanceName(o.get());
|
||||
gs->getMap().generateUniqueInstanceName(o.get());
|
||||
|
||||
assert(!handler->getTemplates(terrainType).empty());
|
||||
if (handler->getTemplates().empty())
|
||||
|
@ -27,6 +27,7 @@ class CCommanderInstance;
|
||||
class EVictoryLossCheckResult;
|
||||
class CRandomGenerator;
|
||||
class GameRandomizer;
|
||||
class StatisticDataSet;
|
||||
|
||||
struct StartInfo;
|
||||
struct TerrainTile;
|
||||
@ -68,6 +69,7 @@ public:
|
||||
std::unique_ptr<TurnTimerHandler> turnTimerHandler;
|
||||
std::unique_ptr<NewTurnProcessor> newTurnProcessor;
|
||||
std::unique_ptr<GameRandomizer> randomizer;
|
||||
std::unique_ptr<StatisticDataSet> statistics;
|
||||
std::shared_ptr<CGameState> gs;
|
||||
|
||||
//use enums as parameters, because doMove(sth, true, false, true) is not readable
|
||||
@ -96,7 +98,6 @@ public:
|
||||
void giveSpells(const CGTownInstance *t, const CGHeroInstance *h);
|
||||
|
||||
IGameInfoCallback & gameInfo();
|
||||
CGameState & gameState() { return *gs; }
|
||||
const CGameState & gameState() const { return *gs; }
|
||||
|
||||
// Helpers to create new object of specified type
|
||||
@ -257,6 +258,12 @@ public:
|
||||
h & *turnOrder;
|
||||
h & *turnTimerHandler;
|
||||
|
||||
if (h.hasFeature(Handler::Version::SERVER_STATISTICS))
|
||||
{
|
||||
h & *statistics;
|
||||
}
|
||||
|
||||
|
||||
#if SCRIPTING_ENABLED
|
||||
JsonNode scriptsState;
|
||||
if(h.saving)
|
||||
|
@ -343,21 +343,21 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
||||
if(!strongestHero || hero->exp > strongestHero->exp)
|
||||
strongestHero = hero;
|
||||
if(strongestHero->id == finishingBattle->loserId && strongestHero->level > 5)
|
||||
gameHandler->gameState().statistic.accumulatedValues[finishingBattle->victor].lastDefeatedStrongestHeroDay = gameHandler->gameState().getDate(Date::DAY);
|
||||
gameHandler->statistics->accumulatedValues[finishingBattle->victor].lastDefeatedStrongestHeroDay = gameHandler->gameState().getDate(Date::DAY);
|
||||
}
|
||||
if(battle.sideToPlayer(BattleSide::ATTACKER) == PlayerColor::NEUTRAL || battle.sideToPlayer(BattleSide::DEFENDER) == PlayerColor::NEUTRAL)
|
||||
{
|
||||
gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(BattleSide::ATTACKER)].numBattlesNeutral++;
|
||||
gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(BattleSide::DEFENDER)].numBattlesNeutral++;
|
||||
gameHandler->statistics->accumulatedValues[battle.sideToPlayer(BattleSide::ATTACKER)].numBattlesNeutral++;
|
||||
gameHandler->statistics->accumulatedValues[battle.sideToPlayer(BattleSide::DEFENDER)].numBattlesNeutral++;
|
||||
if(!finishingBattle->isDraw())
|
||||
gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(finishingBattle->winnerSide)].numWinBattlesNeutral++;
|
||||
gameHandler->statistics->accumulatedValues[battle.sideToPlayer(finishingBattle->winnerSide)].numWinBattlesNeutral++;
|
||||
}
|
||||
else
|
||||
{
|
||||
gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(BattleSide::ATTACKER)].numBattlesPlayer++;
|
||||
gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(BattleSide::DEFENDER)].numBattlesPlayer++;
|
||||
gameHandler->statistics->accumulatedValues[battle.sideToPlayer(BattleSide::ATTACKER)].numBattlesPlayer++;
|
||||
gameHandler->statistics->accumulatedValues[battle.sideToPlayer(BattleSide::DEFENDER)].numBattlesPlayer++;
|
||||
if(!finishingBattle->isDraw())
|
||||
gameHandler->gameState().statistic.accumulatedValues[battle.sideToPlayer(finishingBattle->winnerSide)].numWinBattlesPlayer++;
|
||||
gameHandler->statistics->accumulatedValues[battle.sideToPlayer(finishingBattle->winnerSide)].numWinBattlesPlayer++;
|
||||
}
|
||||
|
||||
BattleResultAccepted raccepted;
|
||||
@ -563,13 +563,13 @@ void BattleResultProcessor::battleFinalize(const BattleID & battleID, const Batt
|
||||
|
||||
if (result.result == EBattleResult::SURRENDER)
|
||||
{
|
||||
gameHandler->gameState().statistic.accumulatedValues[finishingBattle->loser].numHeroSurrendered++;
|
||||
gameHandler->statistics->accumulatedValues[finishingBattle->loser].numHeroSurrendered++;
|
||||
gameHandler->heroPool->onHeroSurrendered(finishingBattle->loser, loserHero);
|
||||
}
|
||||
|
||||
if (result.result == EBattleResult::ESCAPE)
|
||||
{
|
||||
gameHandler->gameState().statistic.accumulatedValues[finishingBattle->loser].numHeroEscaped++;
|
||||
gameHandler->statistics->accumulatedValues[finishingBattle->loser].numHeroEscaped++;
|
||||
gameHandler->heroPool->onHeroEscaped(finishingBattle->loser, loserHero);
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ void PlayerMessageProcessor::commandStatistic(PlayerColor player, const std::vec
|
||||
if(!isHost)
|
||||
return;
|
||||
|
||||
std::string path = gameHandler->gameState().statistic.writeCsv();
|
||||
std::string path = gameHandler->statistics->writeCsv();
|
||||
|
||||
auto str = MetaString::createFromTextID("vcmi.broadcast.statisticFile");
|
||||
str.replaceRawString(path);
|
||||
|
Reference in New Issue
Block a user