309 lines
9.1 KiB
C++
309 lines
9.1 KiB
C++
#include "stage.h"
|
|
|
|
#include <algorithm>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <utility>
|
|
|
|
// 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<std::string> 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::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<StageData> {
|
|
return getStage(current_stage_index_);
|
|
}
|
|
|
|
auto StageManager::getStage(size_t index) const -> std::optional<StageData> {
|
|
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<double>(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<double>(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;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
} |