Laserlicht 1 年之前
父节点
当前提交
490f1bfee6

+ 0 - 19
client/ClientCommandManager.cpp

@@ -355,22 +355,6 @@ void ClientCommandManager::handleGetScriptsCommand()
 #endif
 }
 
-void ClientCommandManager::handleGetStatistic()
-{
-	printCommandMessage("Command accepted.\t");
-
-	const boost::filesystem::path outPath = VCMIDirs::get().userExtractedPath() / "statistic";
-	boost::filesystem::create_directories(outPath);
-
-	const boost::filesystem::path filePath = outPath / (vstd::getDateTimeISO8601Basic(std::time(nullptr)) + ".csv");
-	std::ofstream file(filePath.c_str());
-	std::string csv = CSH->client->gameState()->statistic.toCsv();
-	file << csv;
-
-	printCommandMessage("Writing statistic done :)\n");
-	printCommandMessage("Statistic files can be found in " + outPath.string() + " directory\n");
-}
-
 void ClientCommandManager::handleGetTextCommand()
 {
 	printCommandMessage("Command accepted.\t");
@@ -613,9 +597,6 @@ void ClientCommandManager::processCommand(const std::string & message, bool call
 	else if(message=="get scripts")
 		handleGetScriptsCommand();
 
-	else if(message=="get statistic")
-		handleGetStatistic();
-
 	else if(message=="get txt")
 		handleGetTextCommand();
 

+ 0 - 3
client/ClientCommandManager.h

@@ -57,9 +57,6 @@ class ClientCommandManager //take mantis #2292 issue about account if thinking a
 	// Dumps all scripts in Extracted/Scripts
 	void handleGetScriptsCommand();
 
-	// Dumps statistic in file
-	void handleGetStatistic();
-
 	// Dumps all .txt files from DATA into Extracted/DATA
 	void handleGetTextCommand();
 

+ 27 - 2
lib/gameState/GameStatistics.cpp

@@ -9,6 +9,9 @@
  */
 #include "StdInc.h"
 #include "GameStatistics.h"
+#include "../CPlayerState.h"
+#include "../constants/StringConstants.h"
+#include "CGameState.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -17,15 +20,37 @@ void StatisticDataSet::add(StatisticDataSetEntry entry)
 	data.push_back(entry);
 }
 
+StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, const CGameState * gs)
+{
+	StatisticDataSetEntry data;
+
+	data.day = gs->getDate(Date::DAY);
+	data.player = ps->color;
+	data.team = ps->team;
+	data.resources = ps->resources;
+	data.heroesCount = ps->heroes.size();
+	data.townCount = ps->towns.size();
+
+	return data;
+}
+
 std::string StatisticDataSet::toCsv()
 {
 	std::stringstream ss;
 
-	ss << "Day" << ";" << "Player" << "\r\n";
+	auto resources = std::vector<EGameResID>{EGameResID::GOLD, EGameResID::WOOD, EGameResID::MERCURY, EGameResID::ORE, EGameResID::SULFUR, EGameResID::CRYSTAL, EGameResID::GEMS};
+
+	ss << "Day" << ";" << "Player" << ";" << "Team" << ";" << "HeroesCount" << ";" << "TownCount";
+	for(auto & resource : resources)
+		ss << ";" << GameConstants::RESOURCE_NAMES[resource];
+	ss << "\r\n";
 
 	for(auto & entry : data)
 	{
-		ss << entry.day << ";" << entry.player.getNum() << "\r\n";
+		ss << entry.day << ";" << GameConstants::PLAYER_COLOR_NAMES[entry.player] << ";" << entry.team.getNum() <<  ";" << entry.heroesCount <<  ";" << entry.townCount;
+		for(auto & resource : resources)
+			ss << ";" << entry.resources[resource];
+		ss << "\r\n";
 	}
 
 	return ss.str();

+ 13 - 0
lib/gameState/GameStatistics.h

@@ -10,18 +10,30 @@
 #pragma once
 
 #include "../GameConstants.h"
+#include "../ResourceSet.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+struct PlayerState;
+class CGameState;
+
 struct DLL_LINKAGE StatisticDataSetEntry
 {
     int day;
     PlayerColor player;
+	TeamID team;
+	TResources resources;
+	int heroesCount;
+	int townCount;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
 		h & day;
 		h & player;
+		h & team;
+		h & resources;
+		h & heroesCount;
+		h & townCount;
 	}
 };
 
@@ -31,6 +43,7 @@ class DLL_LINKAGE StatisticDataSet
 
 public:
     void add(StatisticDataSetEntry entry);
+	static StatisticDataSetEntry createEntry(const PlayerState * ps, const CGameState * gs);
     std::string toCsv();
 
 	template <typename Handler> void serialize(Handler &h)

+ 1 - 4
server/CGameHandler.cpp

@@ -676,10 +676,7 @@ void CGameHandler::addStatistics()
 		if (elem.first == PlayerColor::NEUTRAL || !elem.first.isValidPlayer())
 			continue;
 
-		StatisticDataSetEntry data;
-
-		data.day = getDate(Date::DAY);
-		data.player = elem.first;
+		auto data = StatisticDataSet::createEntry(&elem.second, gs);
 
 		gameState()->statistic.add(data);
 	}

+ 21 - 0
server/processors/PlayerMessageProcessor.cpp

@@ -29,6 +29,7 @@
 #include "../../lib/networkPacks/PacksForClient.h"
 #include "../../lib/networkPacks/StackLocation.h"
 #include "../../lib/serializer/Connection.h"
+#include "../lib/VCMIDirs.h"
 
 PlayerMessageProcessor::PlayerMessageProcessor(CGameHandler * gameHandler)
 	:gameHandler(gameHandler)
@@ -133,12 +134,30 @@ void PlayerMessageProcessor::commandCheaters(PlayerColor player, const std::vect
 		broadcastSystemMessage("No cheaters registered!");
 }
 
+void PlayerMessageProcessor::commandStatistic(PlayerColor player, const std::vector<std::string> & words)
+{
+	bool isHost = gameHandler->gameLobby()->isPlayerHost(player);
+	if(!isHost)
+		return;
+
+	const boost::filesystem::path outPath = VCMIDirs::get().userCachePath() / "statistic";
+	boost::filesystem::create_directories(outPath);
+
+	const boost::filesystem::path filePath = outPath / (vstd::getDateTimeISO8601Basic(std::time(nullptr)) + ".csv");
+	std::ofstream file(filePath.c_str());
+	std::string csv = gameHandler->gameState()->statistic.toCsv();
+	file << csv;
+
+	broadcastSystemMessage("Statistic files can be found in " + outPath.string() + " directory\n");
+}
+
 void PlayerMessageProcessor::commandHelp(PlayerColor player, const std::vector<std::string> & words)
 {
 	broadcastSystemMessage("Available commands to host:");
 	broadcastSystemMessage("'!exit' - immediately ends current game");
 	broadcastSystemMessage("'!kick <player>' - kick specified player from the game");
 	broadcastSystemMessage("'!save <filename>' - save game under specified filename");
+	broadcastSystemMessage("'!statistic' - save game statistics as csv file");
 	broadcastSystemMessage("Available commands to all players:");
 	broadcastSystemMessage("'!help' - display this help");
 	broadcastSystemMessage("'!cheaters' - list players that entered cheat command during game");
@@ -319,6 +338,8 @@ void PlayerMessageProcessor::handleCommand(PlayerColor player, const std::string
 		commandSave(player, words);
 	if(words[0] == "!cheaters")
 		commandCheaters(player, words);
+	if(words[0] == "!statistic")
+		commandStatistic(player, words);
 }
 
 void PlayerMessageProcessor::cheatGiveSpells(PlayerColor player, const CGHeroInstance * hero)

+ 1 - 0
server/processors/PlayerMessageProcessor.h

@@ -62,6 +62,7 @@ class PlayerMessageProcessor
 	void commandKick(PlayerColor player, const std::vector<std::string> & words);
 	void commandSave(PlayerColor player, const std::vector<std::string> & words);
 	void commandCheaters(PlayerColor player, const std::vector<std::string> & words);
+	void commandStatistic(PlayerColor player, const std::vector<std::string> & words);
 	void commandHelp(PlayerColor player, const std::vector<std::string> & words);
 	void commandVote(PlayerColor player, const std::vector<std::string> & words);