diff --git a/lib/gameState/GameStatistics.cpp b/lib/gameState/GameStatistics.cpp index d4f84d83a..ec3ae5653 100644 --- a/lib/gameState/GameStatistics.cpp +++ b/lib/gameState/GameStatistics.cpp @@ -21,6 +21,8 @@ #include "../mapObjects/CGObjectInstance.h" #include "../mapObjects/MiscObjects.h" #include "../mapping/CMap.h" +#include "../entities/building/CBuilding.h" + VCMI_LIB_NAMESPACE_BEGIN @@ -55,6 +57,8 @@ StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, cons data.income = Statistic::getIncome(gs, ps); data.mapExploredRatio = Statistic::getMapExploredRatio(gs, ps->color); data.obeliskVisitedRatio = Statistic::getObeliskVisitedRatio(gs, ps->team); + data.townBuiltRatio = Statistic::getTownBuiltRatio(ps); + data.hasGrail = param.hasGrail; 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; @@ -64,6 +68,9 @@ StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, cons data.numWinBattlesPlayer = gs->statistic.values.numWinBattlesPlayer.count(ps->color) ? gs->statistic.values.numWinBattlesPlayer.at(ps->color) : 0; data.numHeroSurrendered = gs->statistic.values.numHeroSurrendered.count(ps->color) ? gs->statistic.values.numHeroSurrendered.at(ps->color) : 0; data.numHeroEscaped = gs->statistic.values.numHeroEscaped.count(ps->color) ? gs->statistic.values.numHeroEscaped.at(ps->color) : 0; + data.spentResourcesForArmy = gs->statistic.values.spentResourcesForArmy.count(ps->color) ? gs->statistic.values.spentResourcesForArmy.at(ps->color) : TResources(); + data.spentResourcesForBuildings = gs->statistic.values.spentResourcesForBuildings.count(ps->color) ? gs->statistic.values.spentResourcesForBuildings.at(ps->color) : TResources(); + data.tradeVolume = gs->statistic.values.tradeVolume.count(ps->color) ? gs->statistic.values.tradeVolume.at(ps->color) : TResources(); return data; } @@ -90,6 +97,8 @@ std::string StatisticDataSet::toCsv() ss << "Income" << ";"; ss << "MapExploredRatio" << ";"; ss << "ObeliskVisitedRatio" << ";"; + ss << "TownBuiltRatio" << ";"; + ss << "HasGrail" << ";"; ss << "Score" << ";"; ss << "MaxHeroLevel" << ";"; ss << "NumBattlesNeutral" << ";"; @@ -102,6 +111,12 @@ std::string StatisticDataSet::toCsv() ss << ";" << GameConstants::RESOURCE_NAMES[resource]; for(auto & resource : resources) ss << ";" << GameConstants::RESOURCE_NAMES[resource] + "Mines"; + for(auto & resource : resources) + ss << ";" << GameConstants::RESOURCE_NAMES[resource] + "SpentResourcesForArmy"; + for(auto & resource : resources) + ss << ";" << GameConstants::RESOURCE_NAMES[resource] + "SpentResourcesForBuildings"; + for(auto & resource : resources) + ss << ";" << GameConstants::RESOURCE_NAMES[resource] + "TradeVolume"; ss << "\r\n"; for(auto & entry : data) @@ -122,6 +137,8 @@ std::string StatisticDataSet::toCsv() ss << entry.income << ";"; ss << entry.mapExploredRatio << ";"; ss << entry.obeliskVisitedRatio << ";"; + ss << entry.townBuiltRatio << ";"; + ss << entry.hasGrail << ";"; ss << entry.score << ";"; ss << entry.maxHeroLevel << ";"; ss << entry.numBattlesNeutral << ";"; @@ -134,6 +151,12 @@ std::string StatisticDataSet::toCsv() ss << ";" << entry.resources[resource]; for(auto & resource : resources) ss << ";" << entry.numMines[resource]; + for(auto & resource : resources) + ss << ";" << entry.spentResourcesForArmy[resource]; + for(auto & resource : resources) + ss << ";" << entry.spentResourcesForBuildings[resource]; + for(auto & resource : resources) + ss << ";" << entry.tradeVolume[resource]; ss << "\r\n"; } @@ -335,4 +358,23 @@ std::map Statistic::getNumMines(const CGameState * gs, const Pl return tmp; } +float Statistic::getTownBuiltRatio(const PlayerState * ps) +{ + float built = 0.0; + float total = 0.0; + + for(const auto & t : ps->towns) + { + built += t->builtBuildings.size(); + for(const auto & b : t->town->buildings) + if(!t->forbiddenBuildings.count(b.first)) + total += 1; + } + + if(total < 1) + return 0; + + return built / total; +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/gameState/GameStatistics.h b/lib/gameState/GameStatistics.h index d8b7fdd60..7734f7977 100644 --- a/lib/gameState/GameStatistics.h +++ b/lib/gameState/GameStatistics.h @@ -38,6 +38,8 @@ struct DLL_LINKAGE StatisticDataSetEntry int income; float mapExploredRatio; float obeliskVisitedRatio; + float townBuiltRatio; + bool hasGrail; std::map numMines; int score; int maxHeroLevel; @@ -47,6 +49,9 @@ struct DLL_LINKAGE StatisticDataSetEntry int numWinBattlesPlayer; int numHeroSurrendered; int numHeroEscaped; + TResources spentResourcesForArmy; + TResources spentResourcesForBuildings; + TResources tradeVolume; template void serialize(Handler &h) { @@ -67,6 +72,8 @@ struct DLL_LINKAGE StatisticDataSetEntry h & income; h & mapExploredRatio; h & obeliskVisitedRatio; + h & townBuiltRatio; + h & hasGrail; h & numMines; h & score; h & maxHeroLevel; @@ -76,6 +83,9 @@ struct DLL_LINKAGE StatisticDataSetEntry h & numWinBattlesPlayer; h & numHeroSurrendered; h & numHeroEscaped; + h & spentResourcesForArmy; + h & spentResourcesForBuildings; + h & tradeVolume; } }; @@ -88,7 +98,7 @@ public: static StatisticDataSetEntry createEntry(const PlayerState * ps, const CGameState * gs); std::string toCsv(); - struct ValueStorage + struct ValueStorage // holds some actual values needed for stats { std::map numBattlesNeutral; std::map numBattlesPlayer; @@ -96,6 +106,9 @@ public: std::map numWinBattlesPlayer; std::map numHeroSurrendered; std::map numHeroEscaped; + std::map spentResourcesForArmy; + std::map spentResourcesForBuildings; + std::map tradeVolume; template void serialize(Handler &h) { @@ -130,6 +143,7 @@ public: static int getObeliskVisited(const CGameState * gs, const TeamID & t); static float getObeliskVisitedRatio(const CGameState * gs, const TeamID & t); static std::map getNumMines(const CGameState * gs, const PlayerState * ps); + static float getTownBuiltRatio(const PlayerState * ps); }; VCMI_LIB_NAMESPACE_END diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 60f9e0ec4..1c0994af1 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2463,7 +2463,10 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, //Take cost if(!force) + { giveResources(t->tempOwner, -requestedBuilding->resources); + gs->statistic.values.spentResourcesForBuildings[t->tempOwner] += requestedBuilding->resources; + } //We know what has been built, apply changes. Do this as final step to properly update town window sendAndApply(&ns); @@ -2565,7 +2568,9 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst } //recruit - giveResources(army->tempOwner, -(c->getFullRecruitCost() * cram)); + TResources cost = (c->getFullRecruitCost() * cram); + giveResources(army->tempOwner, -cost); + gs->statistic.values.spentResourcesForArmy[army->tempOwner] += cost; SetAvailableCreatures sac; sac.tid = objid; @@ -2618,6 +2623,7 @@ bool CGameHandler::upgradeCreature(ObjectInstanceID objid, SlotID pos, CreatureI //take resources giveResources(player, -totalCost); + gs->statistic.values.spentResourcesForArmy[player] += totalCost; //upgrade creature changeStackType(StackLocation(obj, pos), upgID.toCreature()); @@ -3242,6 +3248,9 @@ bool CGameHandler::tradeResources(const IMarket *market, ui32 amountToSell, Play giveResource(player, toSell, -b1 * amountToBoy); giveResource(player, toBuy, b2 * amountToBoy); + gs->statistic.values.tradeVolume[player][toSell] += -b1 * amountToBoy; + gs->statistic.values.tradeVolume[player][toBuy] += b2 * amountToBoy; + return true; }