#include "jail_engine/jscore.h" #include "stats.h" #include #include #include #include // Constructor Stats::Stats(std::string file, std::string buffer, options_t *options) { this->options = options; bufferPath = buffer; filePath = file; bufferList.clear(); list.clear(); dictionary.clear(); } // Destructor Stats::~Stats() { // Vuelca los datos del buffer en la lista de estadisticas updateListFromBuffer(); // Calcula cual es la habitación con más muertes checkWorstNightmare(); // Guarda las estadísticas saveToServer(); saveToFile(bufferPath, bufferList); saveToFile(filePath, list); bufferList.clear(); list.clear(); dictionary.clear(); } // Inicializador // Se debe llamar a este procediiento una vez se haya creado el diccionario numero-nombre void Stats::init() { loadFromFile(bufferPath, bufferList); loadFromFile(filePath, list); if (options->online.enabled) { loadFromServer(); } // Vuelca los datos del buffer en la lista de estadisticas updateListFromBuffer(); } // Añade una muerte a las estadisticas void Stats::addDeath(std::string name) { // Normaliza el nombre // std::replace(name.begin(), name.end(), ' ', '_'); // Primero busca si ya hay una entrada con ese nombre const int index = findByName(name, bufferList); if (index != -1) { bufferList[index].died++; } // En caso contrario crea la entrada else { stats_t item; item.name = name; item.visited = 0; item.died = 1; bufferList.push_back(item); } } // Añade una visita a las estadisticas void Stats::addVisit(std::string name) { // Normaliza el nombre // std::replace(name.begin(), name.end(), ' ', '_'); // Primero busca si ya hay una entrada con ese nombre const int index = findByName(name, bufferList); if (index != -1) { bufferList[index].visited++; } // En caso contrario crea la entrada else { stats_t item; item.name = name; item.visited = 1; item.died = 0; bufferList.push_back(item); } } // Busca una entrada en la lista por nombre int Stats::findByName(std::string name, std::vector &list) { int i = 0; for (auto l : list) { if (l.name == name) { return i; } i++; } return -1; } // Carga las estadisticas desde un fichero bool Stats::loadFromFile(std::string filePath, std::vector &list) { list.clear(); // Indicador de éxito en la carga bool success = true; // Variables para manejar el fichero std::string line; std::ifstream file(filePath); // Si el fichero se puede abrir if (file.good()) { // Procesa el fichero linea a linea while (std::getline(file, line)) { // Comprueba que la linea no sea un comentario if (line.substr(0, 1) != "#") { stats_t stat; std::stringstream ss(line); std::string tmp; // Obtiene el nombre getline(ss, tmp, ';'); stat.name = tmp; // Obtiene las visitas getline(ss, tmp, ';'); stat.visited = std::stoi(tmp); // Obtiene las muertes getline(ss, tmp, ';'); stat.died = std::stoi(tmp); list.push_back(stat); } } // Cierra el fichero file.close(); } // El fichero no existe else { // Crea el fichero con los valores por defecto saveToFile(filePath, list); } return success; } // Carga las estadisticas desde un servidor void Stats::loadFromServer() { // Limpia los datos del servidor // eraseServerData(); list.clear(); std::string data; if (options->online.enabled) { data = jscore::getUserData(options->online.gameID, options->online.jailerID); } std::stringstream ss(data); std::string tmp; int count = 0; for (int i = 0; i < (int)data.size(); ++i) { if (data[i] == ';') { count++; } } while (count > 0) { stats_t stat; // Obtiene el nombre getline(ss, tmp, ';'); stat.name = numberToName(tmp); // Obtiene las visitas getline(ss, tmp, ';'); stat.visited = std::stoi(tmp); // Obtiene las muertes getline(ss, tmp, ';'); stat.died = std::stoi(tmp); list.push_back(stat); count = count - 3; } } // Guarda las estadisticas en un fichero void Stats::saveToFile(std::string filePath, std::vector &list) { // Crea y abre el fichero de texto std::ofstream file(filePath); // Escribe en el fichero file << "# ROOM NAME;VISITS;DEATHS" << std::endl; for (auto item : list) { file << item.name << ";" << item.visited << ";" << item.died << std::endl; } // Cierra el fichero file.close(); } // Guarda las estadisticas en un servidor void Stats::saveToServer() { std::string data = ""; if (options->online.enabled) { for (auto item : list) { data = data + nameToNumber(item.name) + ";" + std::to_string(item.visited) + ";" + std::to_string(item.died) + ";"; } jscore::setUserData(options->online.gameID, options->online.jailerID, data); } } // Calcula cual es la habitación con más muertes void Stats::checkWorstNightmare() { int deaths = 0; for (auto item : list) { if (item.died > deaths) { deaths = item.died; options->stats.worstNightmare = item.name; } } } // Añade una entrada al diccionario void Stats::addDictionary(std::string number, std::string name) { dictionary.push_back({number, name}); } // Obtiene el nombre de una habitación a partir del número std::string Stats::numberToName(std::string number) { for (auto l : dictionary) { if (l.number == number) { return l.name; } } return ""; } // Obtiene el número de una habitación a partir del nombre std::string Stats::nameToNumber(std::string name) { for (auto l : dictionary) { if (l.name == name) { return l.number; } } return ""; } // Vuelca los datos del buffer en la lista de estadisticas void Stats::updateListFromBuffer() { // Actualiza list desde bufferList for (auto buffer : bufferList) { int index = findByName(buffer.name, list); if (index != -1) { // Encontrado. Aumenta sus estadisticas list[index].visited += buffer.visited; list[index].died += buffer.died; } else { // En caso contrario crea la entrada stats_t item; item.name = buffer.name; item.visited = buffer.visited; item.died = buffer.died; list.push_back(item); } } // Sube los datos al servidor if (options->online.enabled) { saveToServer(); bufferList.clear(); } saveToFile(bufferPath, bufferList); saveToFile(filePath, list); } // Limpia los datos del servidor void Stats::eraseServerData() { jscore::setUserData(options->online.gameID, options->online.jailerID, ""); }