#include "stage.hpp" #include #include #include #include // Implementación de StageData StageData::StageData(int power_to_complete, int min_menace, int max_menace, std::string name) : status_(StageStatus::LOCKED), name_(std::move(name)), power_to_complete_(power_to_complete), min_menace_(min_menace), max_menace_(max_menace) {} // Implementación de StageManager StageManager::StageManager() : power_change_callback_(nullptr), power_collection_state_(PowerCollectionState::ENABLED), current_stage_index_(0), current_power_(0), total_power_(0) { initialize(); } void StageManager::initialize() { stages_.clear(); createDefaultStages(); reset(); } void StageManager::initialize(const std::string& stages_file) { stages_.clear(); // Intentar cargar desde archivo, si falla usar valores predeterminados if (!loadStagesFromFile(stages_file)) { createDefaultStages(); } reset(); } void StageManager::reset() { current_power_ = 0; total_power_ = 0; current_stage_index_ = 0; power_collection_state_ = PowerCollectionState::ENABLED; updateStageStatuses(); } void StageManager::createDefaultStages() { // Crear las 10 fases predeterminadas con dificultad progresiva stages_.emplace_back(200, 7 + (4 * 1), 7 + (4 * 3), "Tutorial"); stages_.emplace_back(300, 7 + (4 * 2), 7 + (4 * 4), "Primeros pasos"); stages_.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5), "Intensificación"); stages_.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5), "Persistencia"); stages_.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6), "Desafío medio"); stages_.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6), "Resistencia"); stages_.emplace_back(650, 7 + (4 * 5), 7 + (4 * 7), "Aproximación final"); stages_.emplace_back(750, 7 + (4 * 5), 7 + (4 * 7), "Penúltimo obstáculo"); stages_.emplace_back(850, 7 + (4 * 6), 7 + (4 * 8), "Clímax"); stages_.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10), "Maestría"); } auto StageManager::loadStagesFromFile(const std::string& filename) -> bool { std::ifstream file(filename); if (!file.is_open()) { return false; // No se pudo abrir el archivo } std::string line; while (std::getline(file, line)) { // Ignorar líneas vacías y comentarios (líneas que empiezan con #) if (line.empty() || line[0] == '#') { continue; } // Parsear línea: power_to_complete,min_menace,max_menace,name std::stringstream ss(line); std::string token; std::vector tokens; // Dividir por comas while (std::getline(ss, token, ',')) { // Eliminar espacios en blanco al inicio y final token.erase(0, token.find_first_not_of(" \t")); token.erase(token.find_last_not_of(" \t") + 1); tokens.push_back(token); } // Verificar que tenemos exactamente 4 campos if (tokens.size() != 4) { // Error de formato, continuar con la siguiente línea continue; } try { // Convertir a enteros los primeros tres campos int power_to_complete = std::stoi(tokens[0]); int min_menace = std::stoi(tokens[1]); int max_menace = std::stoi(tokens[2]); std::string name = tokens[3]; // Validar valores if (power_to_complete <= 0 || min_menace < 0 || max_menace < min_menace) { continue; // Valores inválidos, saltar línea } // Crear y añadir la fase stages_.emplace_back(power_to_complete, min_menace, max_menace, name); } catch (const std::exception&) { // Error de conversión, continuar con la siguiente línea continue; } } file.close(); // Verificar que se cargó al menos una fase return !stages_.empty(); } auto StageManager::advanceToNextStage() -> bool { if (!isCurrentStageCompleted() || current_stage_index_ >= stages_.size() - 1) { return false; } current_stage_index_++; current_power_ = 0; // Reiniciar poder para la nueva fase updateStageStatuses(); return true; } auto StageManager::jumpToStage(size_t target_stage_index) -> bool { if (!validateStageIndex(target_stage_index)) { return false; } // Calcular el poder acumulado hasta la fase objetivo int accumulated_power = 0; for (size_t i = 0; i < target_stage_index; ++i) { accumulated_power += stages_[i].getPowerToComplete(); } // Actualizar estado current_stage_index_ = target_stage_index; current_power_ = 0; // Comenzar la fase objetivo sin poder total_power_ = accumulated_power; // Poder total como si se hubieran completado las anteriores updateStageStatuses(); return true; } auto StageManager::setTotalPower(int target_total_power) -> bool { if (target_total_power < 0) { return false; } int total_power_needed = getTotalPowerNeededToCompleteGame(); if (target_total_power > total_power_needed) { return false; } // Calcular en qué fase debería estar y cuánto poder de esa fase int accumulated_power = 0; size_t target_stage_index = 0; int target_current_power = 0; for (size_t i = 0; i < stages_.size(); ++i) { int stage_power = stages_[i].getPowerToComplete(); if (accumulated_power + stage_power > target_total_power) { // El objetivo está dentro de esta fase target_stage_index = i; target_current_power = target_total_power - accumulated_power; break; } accumulated_power += stage_power; if (accumulated_power == target_total_power) { // El objetivo coincide exactamente con el final de esta fase // Mover a la siguiente fase (si existe) con power 0 target_stage_index = (i + 1 < stages_.size()) ? i + 1 : i; target_current_power = (i + 1 < stages_.size()) ? 0 : stage_power; break; } } // Actualizar estado current_stage_index_ = target_stage_index; current_power_ = target_current_power; total_power_ = target_total_power; updateStageStatuses(); return true; } auto StageManager::subtractPower(int amount) -> bool { if (amount <= 0 || current_power_ < amount) { return false; } current_power_ -= amount; updateStageStatuses(); return true; } void StageManager::enablePowerCollection() { power_collection_state_ = PowerCollectionState::ENABLED; } void StageManager::disablePowerCollection() { power_collection_state_ = PowerCollectionState::DISABLED; } auto StageManager::getCurrentStage() const -> std::optional { return getStage(current_stage_index_); } auto StageManager::getStage(size_t index) const -> std::optional { if (!validateStageIndex(index)) { return std::nullopt; } return stages_[index]; } auto StageManager::isCurrentStageCompleted() const -> bool { auto current_stage = getCurrentStage(); if (!current_stage.has_value()) { return false; } return current_power_ >= current_stage->getPowerToComplete(); } auto StageManager::isGameCompleted() const -> bool { return current_stage_index_ >= stages_.size() - 1 && isCurrentStageCompleted(); } auto StageManager::getProgressPercentage() const -> double { if (stages_.empty()) { return 0.0; } int total_power_needed = getTotalPowerNeededToCompleteGame(); if (total_power_needed == 0) { return 100.0; } return (static_cast(total_power_) / total_power_needed) * 100.0; } auto StageManager::getCurrentStageProgressPercentage() const -> double { return getCurrentStageProgressFraction() * 100.0; } auto StageManager::getCurrentStageProgressFraction() const -> double { auto current_stage = getCurrentStage(); if (!current_stage.has_value()) { return 0.0; } int power_needed = current_stage->getPowerToComplete(); if (power_needed == 0) { return 1.0; } // Devuelve una fracción entre 0.0 y 1.0 double fraction = static_cast(current_power_) / power_needed; return std::min(fraction, 1.0); } auto StageManager::getPowerNeededForCurrentStage() const -> int { auto current_stage = getCurrentStage(); if (!current_stage.has_value()) { return 0; } return std::max(0, current_stage->getPowerToComplete() - current_power_); } auto StageManager::getTotalPowerNeededToCompleteGame() const -> int { int total_power_needed = 0; for (const auto& stage : stages_) { total_power_needed += stage.getPowerToComplete(); } return total_power_needed; } auto StageManager::getPowerNeededToReachStage(size_t target_stage_index) const -> int { if (!validateStageIndex(target_stage_index)) { return 0; } int power_needed = 0; for (size_t i = 0; i < target_stage_index; ++i) { power_needed += stages_[i].getPowerToComplete(); } return power_needed; } // Implementación de la interfaz IStageInfo auto StageManager::canCollectPower() const -> bool { return power_collection_state_ == PowerCollectionState::ENABLED; } void StageManager::addPower(int amount) { if (amount <= 0 || !canCollectPower()) { return; } current_power_ += amount; total_power_ += amount; // Ejecutar callback si está registrado if (power_change_callback_) { power_change_callback_(amount); } // Verificar si se completó la fase actual if (isCurrentStageCompleted()) { auto current_stage = getCurrentStage(); if (current_stage.has_value()) { stages_[current_stage_index_].setStatus(StageStatus::COMPLETED); } } updateStageStatuses(); } auto StageManager::getCurrentMenaceLevel() const -> int { auto current_stage = getCurrentStage(); if (!current_stage.has_value()) { return 0; } return current_stage->getMinMenace(); } // Gestión de callbacks void StageManager::setPowerChangeCallback(PowerChangeCallback callback) { power_change_callback_ = std::move(callback); } void StageManager::removePowerChangeCallback() { power_change_callback_ = nullptr; } // Métodos privados auto StageManager::validateStageIndex(size_t index) const -> bool { return index < stages_.size(); } void StageManager::updateStageStatuses() { // Actualizar el estado de cada fase según su posición relativa a la actual for (size_t i = 0; i < stages_.size(); ++i) { if (i < current_stage_index_) { stages_[i].setStatus(StageStatus::COMPLETED); } else if (i == current_stage_index_) { stages_[i].setStatus(StageStatus::IN_PROGRESS); } else { stages_[i].setStatus(StageStatus::LOCKED); } } }