From 2909596c42b942695a2f56560cfe92de082bc296 Mon Sep 17 00:00:00 2001 From: kimden <23140380+kimden@users.noreply.github.com> Date: Fri, 29 Aug 2025 01:26:04 +0400 Subject: [PATCH] Initial commit [skip ci] Overall structure changed, around 0.5/5 scorings are rewritten --- src/modes/world_with_rank.cpp | 2 +- src/utils/gp_scoring.cpp | 167 ------------------ src/utils/lobby_context.cpp | 2 +- src/utils/lobby_gp_manager.cpp | 2 +- src/utils/scoring/exponential_gap_scoring.cpp | 91 ++++++++++ src/utils/scoring/exponential_gap_scoring.hpp | 51 ++++++ src/utils/scoring/fixed_scoring.cpp | 44 +++++ .../fixed_scoring.hpp} | 41 ++--- src/utils/scoring/incremental_scoring.cpp | 51 ++++++ src/utils/scoring/incremental_scoring.hpp | 45 +++++ src/utils/scoring/linear_gap_scoring.cpp | 55 ++++++ src/utils/scoring/linear_gap_scoring.hpp | 45 +++++ src/utils/scoring/scoring.cpp | 87 +++++++++ src/utils/scoring/scoring.hpp | 81 +++++++++ src/utils/scoring/standard_scoring.cpp | 42 +++++ src/utils/scoring/standard_scoring.hpp | 45 +++++ 16 files changed, 658 insertions(+), 193 deletions(-) delete mode 100644 src/utils/gp_scoring.cpp create mode 100644 src/utils/scoring/exponential_gap_scoring.cpp create mode 100644 src/utils/scoring/exponential_gap_scoring.hpp create mode 100644 src/utils/scoring/fixed_scoring.cpp rename src/utils/{gp_scoring.hpp => scoring/fixed_scoring.hpp} (61%) create mode 100644 src/utils/scoring/incremental_scoring.cpp create mode 100644 src/utils/scoring/incremental_scoring.hpp create mode 100644 src/utils/scoring/linear_gap_scoring.cpp create mode 100644 src/utils/scoring/linear_gap_scoring.hpp create mode 100644 src/utils/scoring/scoring.cpp create mode 100644 src/utils/scoring/scoring.hpp create mode 100644 src/utils/scoring/standard_scoring.cpp create mode 100644 src/utils/scoring/standard_scoring.hpp diff --git a/src/modes/world_with_rank.cpp b/src/modes/world_with_rank.cpp index d9f933a565d..94654ece93a 100644 --- a/src/modes/world_with_rank.cpp +++ b/src/modes/world_with_rank.cpp @@ -24,7 +24,7 @@ #include "tracks/graph.hpp" #include "tracks/track.hpp" #include "tracks/track_sector.hpp" -#include "utils/gp_scoring.hpp" +#include "utils/scoring/scoring.hpp" #include "utils/log.hpp" #include diff --git a/src/utils/gp_scoring.cpp b/src/utils/gp_scoring.cpp deleted file mode 100644 index 5722d0c9482..00000000000 --- a/src/utils/gp_scoring.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2025 kimden -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 3 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "utils/gp_scoring.hpp" - -#include "network/server_config.hpp" -#include "utils/string_utils.hpp" -#include "utils/log.hpp" - -#include -#include - - -std::shared_ptr GPScoring::createFromIntParamString(const std::string& input) -{ - std::shared_ptr new_scoring = std::make_shared(); - - std::set available_scoring_types = { - "standard", "default", "", "inc", "fixed", "linear-gap", "exp-gap" - }; - if (!input.empty()) - { - std::vector params = StringUtils::split(input, ' '); - if (params.empty()) - { - new_scoring->m_type = ""; - return new_scoring; - } - new_scoring->m_type = params[0]; - if (available_scoring_types.count(params[0]) == 0) - throw std::logic_error("Unknown scoring type " + params[0]); - - for (unsigned i = 1; i < params.size(); i++) - { - int param; - if (!StringUtils::fromString(params[i], param)) - throw std::logic_error("Unable to parse integer from custom scoring data"); - - new_scoring->m_params.push_back(param); - } - } - return new_scoring; -} // createFromIntParamString -//----------------------------------------------------------------------------- - -bool GPScoring::isStandard() const -{ - return m_type == "" - || m_type == "standard" - || m_type == "default"; -} // isStandard -//----------------------------------------------------------------------------- - -void GPScoring::refreshCustomScores(int num_karts, - std::vector& score_for_position) -{ - if (m_type == "inc") - { - // Testing indicates that number of parameters is not validated. - // Do it when splitting into separate classes. - score_for_position.clear(); - for (unsigned i = 2; i < m_params.size(); i++) - score_for_position.push_back(m_params[i]); - score_for_position.resize(num_karts, 0); - std::sort(score_for_position.begin(), score_for_position.end()); - for (unsigned i = 1; i < score_for_position.size(); i++) - score_for_position[i] += score_for_position[i - 1]; - std::reverse(score_for_position.begin(), score_for_position.end()); - } - else if (m_type == "fixed") - { - score_for_position.clear(); - for (unsigned i = 2; i < m_params.size(); i++) - score_for_position.push_back(m_params[i]); - score_for_position.resize(num_karts, 0); - } - else if (m_type == "linear-gap" - || m_type == "exp-gap") - { - score_for_position.clear(); - score_for_position.resize(num_karts, 0); - } -} // refreshCustomScores -//----------------------------------------------------------------------------- - -int GPScoring::getPolePoints() const -{ - return m_params[0]; -} // getPolePoints -//----------------------------------------------------------------------------- - -int GPScoring::getFastestLapPoints() const -{ - return m_params[1]; -} // getFastestLapPoints -//----------------------------------------------------------------------------- - -int GPScoring::getScoreForPosition(int p, float time, - std::map& race_times, - const std::vector& score_for_position) const -{ - race_times[p] = time; - if (m_type == "inc" || m_type == "fixed") - return score_for_position[p - 1]; - if (m_type == "linear-gap" - || m_type == "exp-gap") - { - double delta = time - race_times[1]; - if (m_type == "exp-gap") - { - if (race_times[1] < 1e-6) // just in case - return 0; - delta = log(time / race_times[1]) / log(2); - } - double points = m_params[2] * 0.001; - bool continuous = (m_params[5] != 0); - double time_step = m_params[3] * 0.001; - double decrease = m_params[4] * 0.001; - delta /= time_step; - if (!continuous) - delta = floor(delta); - points -= delta * decrease; - if (points < 0.0) - points = 0.0; - return round(points); - } - Log::error("GPScoring", "Unknown scoring type: %s. Giving 0 points", m_type.c_str()); - return 0; -} // getScoreForPosition -//----------------------------------------------------------------------------- - -bool GPScoring::canGetScoreForPosition(int p, const std::map& race_times) const -{ - if (m_type == "linear-gap" - || m_type == "exp-gap") - { - if (p == 1 || race_times.count(1)) - return true; - return false; - } - return true; -} // canGetScoreForPosition -//----------------------------------------------------------------------------- - -std::string GPScoring::toString() const -{ - std::string res = m_type; - for (int param: m_params) - res += StringUtils::insertValues(" %d", param); - return res; -} // toString -//----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/utils/lobby_context.cpp b/src/utils/lobby_context.cpp index d14781bc90f..1c4ff344aae 100644 --- a/src/utils/lobby_context.cpp +++ b/src/utils/lobby_context.cpp @@ -29,7 +29,7 @@ #include "utils/team_manager.hpp" #include "utils/tournament.hpp" #include "utils/lobby_gp_manager.hpp" -#include "utils/gp_scoring.hpp" +#include "utils/scoring/scoring.hpp" #include "utils/crown_manager.hpp" #include "network/game_setup.hpp" #include "network/database_connector.hpp" diff --git a/src/utils/lobby_gp_manager.cpp b/src/utils/lobby_gp_manager.cpp index 874122aec36..00c0bfae5df 100644 --- a/src/utils/lobby_gp_manager.cpp +++ b/src/utils/lobby_gp_manager.cpp @@ -27,7 +27,7 @@ #include "network/network_string.hpp" #include "network/protocols/server_lobby.hpp" #include "network/server_config.hpp" -#include "utils/gp_scoring.hpp" +#include "utils/scoring/scoring.hpp" #include "utils/string_utils.hpp" #include "utils/team_manager.hpp" diff --git a/src/utils/scoring/exponential_gap_scoring.cpp b/src/utils/scoring/exponential_gap_scoring.cpp new file mode 100644 index 00000000000..cd0462404a6 --- /dev/null +++ b/src/utils/scoring/exponential_gap_scoring.cpp @@ -0,0 +1,91 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "utils/scoring/exponential_gap_scoring.hpp" +#include "utils/string_utils.hpp" + +#include +#include + + +void ExponentialGapScoring::fromIntParamString(const std::string& input) +{ + auto argv = StringUtils::split(input, ' '); + m_pole_points = Scoring::parse(argv, 0); + m_fastest_lap_points = Scoring::parse(argv, 1); + m_win_points = Scoring::parseThousandth(argv, 2); + m_time_log_unit = Scoring::parseThousandth(argv, 3); + m_decrease = Scoring::parseThousandth(argv, 4); + m_continuous = Scoring::parse(argv, 5); + + m_allow_negative = true; + m_allow_pure_negative = false; // kimden: pay attention + m_round = true; +} // fromIntParamString +//----------------------------------------------------------------------------- + +void ExponentialGapScoring::fromString(const std::string& input) +{ + +} // fromString +//----------------------------------------------------------------------------- + +void ExponentialGapScoring::refreshCustomScores(int num_karts, + std::vector& score_for_position) +{ + score_for_position.clear(); + score_for_position.resize(num_karts, 0); +} // refreshCustomScores +//----------------------------------------------------------------------------- + +int ExponentialGapScoring::getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const +{ + race_times[p] = time; + double delta = time - race_times[1]; + if (race_times[1] < 1e-6) // just in case + return 0; + + delta = log(time / race_times[1]) / log(2); + double points = m_win_points; + bool continuous = (m_continuous != 0); + double time_step = m_time_log_unit; + double decrease = m_decrease; + delta /= time_step; + if (!continuous) + delta = floor(delta); + points -= delta * decrease; + + if (points < 0.0) + points = 0.0; + + if (m_round) + points = round(points); + + return points; +} // getScoreForPosition +//----------------------------------------------------------------------------- + +bool ExponentialGapScoring::canGetScoreForPosition(int p, const std::map& race_times) const +{ + if (p == 1 || race_times.count(1)) + return true; + return false; +} // canGetScoreForPosition +//----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/utils/scoring/exponential_gap_scoring.hpp b/src/utils/scoring/exponential_gap_scoring.hpp new file mode 100644 index 00000000000..e7c7ec335e8 --- /dev/null +++ b/src/utils/scoring/exponential_gap_scoring.hpp @@ -0,0 +1,51 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef EXPONENTIAL_GAP_SCORING_HPP +#define EXPONENTIAL_GAP_SCORING_HPP + +#include "utils/scoring/scoring.hpp" + +class ExponentialGapScoring: public Scoring +{ +private: + double m_win_points; + double m_continuous; + double m_time_log_unit; + double m_decrease; + +public: + void fromIntParamString(const std::string& input) final; + + void fromString(const std::string& input) final; + + bool isStandard() const final { return false; } + + void refreshCustomScores(int num_karts, std::vector& score_for_position) final; + + int getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const final; + + bool canGetScoreForPosition(int p, const std::map& race_times) const final; + + std::string toString() const; +}; + + +#endif // EXPONENTIAL_GAP_SCORING_HPP \ No newline at end of file diff --git a/src/utils/scoring/fixed_scoring.cpp b/src/utils/scoring/fixed_scoring.cpp new file mode 100644 index 00000000000..e607bafd1fd --- /dev/null +++ b/src/utils/scoring/fixed_scoring.cpp @@ -0,0 +1,44 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "utils/scoring/fixed_scoring.hpp" + + +void GPScoring::refreshCustomScores(int num_karts, + std::vector& score_for_position) +{ + score_for_position.clear(); + for (unsigned i = 2; i < m_params.size(); i++) + score_for_position.push_back(m_params[i]); + score_for_position.resize(num_karts, 0); +} // refreshCustomScores + +int GPScoring::getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const +{ + race_times[p] = time; + return score_for_position[p - 1]; +} // getScoreForPosition +//----------------------------------------------------------------------------- + +bool GPScoring::canGetScoreForPosition(int p, const std::map& race_times) const +{ + return true; +} // canGetScoreForPosition +//----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/utils/gp_scoring.hpp b/src/utils/scoring/fixed_scoring.hpp similarity index 61% rename from src/utils/gp_scoring.hpp rename to src/utils/scoring/fixed_scoring.hpp index b49793eaf38..c7d82746972 100644 --- a/src/utils/gp_scoring.hpp +++ b/src/utils/scoring/fixed_scoring.hpp @@ -16,35 +16,30 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#ifndef GP_SCORING_HPP -#define GP_SCORING_HPP +#ifndef FIXED_SCORING_HPP +#define FIXED_SCORING_HPP -#include "irrString.h" +#include "utils/scoring/scoring.hpp" -#include -#include -#include -#include -#include - -class GPScoring +class FixedScoring: public Scoring { public: - static std::shared_ptr createFromIntParamString(const std::string& input); - bool isStandard() const; - void refreshCustomScores(int num_karts, - std::vector& score_for_position); - int getPolePoints() const; - int getFastestLapPoints() const; + void fromIntParamString(const std::string& input) final; + + void fromString(const std::string& input) final; + + bool isStandard() const final { return false; } + + void refreshCustomScores(int num_karts, std::vector& score_for_position) final; + int getScoreForPosition(int p, float time, std::map& race_times, - const std::vector& score_for_position) const; - bool canGetScoreForPosition(int p, const std::map& race_times) const; - std::string toString() const; + const std::vector& score_for_position) const final; + + bool canGetScoreForPosition(int p, const std::map& race_times) const final; -private: - std::vector m_params; - std::string m_type; + std::string toString() const; }; -#endif // GP_SCORING_HPP \ No newline at end of file + +#endif // FIXED_SCORING_HPP \ No newline at end of file diff --git a/src/utils/scoring/incremental_scoring.cpp b/src/utils/scoring/incremental_scoring.cpp new file mode 100644 index 00000000000..bb927abf83f --- /dev/null +++ b/src/utils/scoring/incremental_scoring.cpp @@ -0,0 +1,51 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "utils/scoring/incremental_scoring.hpp" + + +void GPScoring::refreshCustomScores(int num_karts, + std::vector& score_for_position) +{ + // Testing indicates that number of parameters is not validated. + // Do it when splitting into separate classes. + score_for_position.clear(); + for (unsigned i = 2; i < m_params.size(); i++) + score_for_position.push_back(m_params[i]); + score_for_position.resize(num_karts, 0); + std::sort(score_for_position.begin(), score_for_position.end()); + for (unsigned i = 1; i < score_for_position.size(); i++) + score_for_position[i] += score_for_position[i - 1]; + std::reverse(score_for_position.begin(), score_for_position.end()); +} // refreshCustomScores + + +int GPScoring::getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const +{ + race_times[p] = time; + return score_for_position[p - 1]; +} // getScoreForPosition +//----------------------------------------------------------------------------- + +bool GPScoring::canGetScoreForPosition(int p, const std::map& race_times) const +{ + return true; +} // canGetScoreForPosition +//----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/utils/scoring/incremental_scoring.hpp b/src/utils/scoring/incremental_scoring.hpp new file mode 100644 index 00000000000..45cbc127459 --- /dev/null +++ b/src/utils/scoring/incremental_scoring.hpp @@ -0,0 +1,45 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef INCREMENTAL_SCORING_HPP +#define INCREMENTAL_SCORING_HPP + +#include "utils/scoring/scoring.hpp" + +class IncrementalScoring: public Scoring +{ +public: + void fromIntParamString(const std::string& input) final; + + void fromString(const std::string& input) final; + + bool isStandard() const final { return false; } + + void refreshCustomScores(int num_karts, std::vector& score_for_position) final; + + int getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const final; + + bool canGetScoreForPosition(int p, const std::map& race_times) const final; + + std::string toString() const; +}; + + +#endif // INCREMENTAL_SCORING_HPP \ No newline at end of file diff --git a/src/utils/scoring/linear_gap_scoring.cpp b/src/utils/scoring/linear_gap_scoring.cpp new file mode 100644 index 00000000000..58830990a71 --- /dev/null +++ b/src/utils/scoring/linear_gap_scoring.cpp @@ -0,0 +1,55 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "utils/scoring/linear_gap_scoring.hpp" + + +void GPScoring::refreshCustomScores(int num_karts, + std::vector& score_for_position) +{ + score_for_position.clear(); + score_for_position.resize(num_karts, 0); +} // refreshCustomScores + +int GPScoring::getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const +{ + race_times[p] = time; + double delta = time - race_times[1]; + double points = m_params[2] * 0.001; + bool continuous = (m_params[5] != 0); + double time_step = m_params[3] * 0.001; + double decrease = m_params[4] * 0.001; + delta /= time_step; + if (!continuous) + delta = floor(delta); + points -= delta * decrease; + if (points < 0.0) + points = 0.0; + return round(points); +} // getScoreForPosition +//----------------------------------------------------------------------------- + +bool GPScoring::canGetScoreForPosition(int p, const std::map& race_times) const +{ + if (p == 1 || race_times.count(1)) + return true; + return false; +} // canGetScoreForPosition +//----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/utils/scoring/linear_gap_scoring.hpp b/src/utils/scoring/linear_gap_scoring.hpp new file mode 100644 index 00000000000..73c7e5344ed --- /dev/null +++ b/src/utils/scoring/linear_gap_scoring.hpp @@ -0,0 +1,45 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef LINEAR_GAP_SCORING_HPP +#define LINEAR_GAP_SCORING_HPP + +#include "utils/scoring/scoring.hpp" + +class LinearGapScoring: public Scoring +{ +public: + void fromIntParamString(const std::string& input) final; + + void fromString(const std::string& input) final; + + bool isStandard() const final { return false; } + + void refreshCustomScores(int num_karts, std::vector& score_for_position) final; + + int getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const final; + + bool canGetScoreForPosition(int p, const std::map& race_times) const final; + + std::string toString() const; +}; + + +#endif // LINEAR_GAP_SCORING_HPP \ No newline at end of file diff --git a/src/utils/scoring/scoring.cpp b/src/utils/scoring/scoring.cpp new file mode 100644 index 00000000000..b620b08b315 --- /dev/null +++ b/src/utils/scoring/scoring.cpp @@ -0,0 +1,87 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "utils/scoring/scoring.hpp" +#include "utils/scoring/exponential_gap_scoring.hpp" +#include "utils/scoring/fixed_scoring.hpp" +#include "utils/scoring/incremental_scoring.hpp" +#include "utils/scoring/linear_gap_scoring.hpp" +#include "utils/scoring/standard_scoring.hpp" +#include "utils/string_utils.hpp" + +#include + +namespace +{ + struct ScoringAndDescription + { + std::shared_ptr scoring; + std::string description; + }; + + ScoringAndDescription scoringObjectAndDesc(const std::string& input) + { + std::string type; + std::string description; + if (input == "") + { + type = "standard"; + description = ""; + } + else + { + size_t pos = input.find(' '); + if (pos == std::string::npos) + throw std::logic_error("Scoring description should start with type and space"); + + type = input.substr(0, pos); + description = input.substr(pos + 1); + } + + std::shared_ptr res; + if (type == "standard") + res = std::make_shared(); + else if (type == "linear-gap") + res = std::make_shared(); + else if (type == "exp-gap") + res = std::make_shared(); + else if (type == "fixed") + res = std::make_shared(); + else if (type == "inc") + res = std::make_shared(); + else + throw std::logic_error(StringUtils::insertValues( + "Unknown scoring type %s", type.c_str())); + + return {res, description}; + } // scoringObjectAndDesc +} + +std::shared_ptr Scoring::unknownScoringFromIntParamString(const std::string& input) +{ + auto [res, description] = std::move(scoringObjectAndDesc(input)); + res->fromIntParamString(description); + return res; +} + +std::shared_ptr Scoring::unknownScoringFromString(const std::string& input) +{ + auto [res, description] = std::move(scoringObjectAndDesc(input)); + res->fromString(description); + return res; +} diff --git a/src/utils/scoring/scoring.hpp b/src/utils/scoring/scoring.hpp new file mode 100644 index 00000000000..8c88e591da8 --- /dev/null +++ b/src/utils/scoring/scoring.hpp @@ -0,0 +1,81 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef SCORING_HPP +#define SCORING_HPP + +#include +#include +#include +#include + +class Scoring +{ +protected: + double m_pole_points = 0.; + double m_fastest_lap_points = 0.; + double m_quit_points = 0.; + double m_absence_points = 0.; + + bool m_allow_negative = true; + bool m_allow_pure_negative = false; + bool m_round = true; + +public: + static std::shared_ptr unknownScoringFromIntParamString(const std::string& input); + static std::shared_ptr unknownScoringFromString(const std::string& input); + + virtual void fromIntParamString(const std::string& input) = 0; + virtual void fromString(const std::string& input) = 0; + virtual bool isStandard() const = 0; + virtual void refreshCustomScores(int num_karts, std::vector& score_for_position) = 0; + virtual int getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const = 0; + virtual bool canGetScoreForPosition(int p, const std::map& race_times) const = 0; + virtual std::string toString() const = 0; + + double getPolePoints() const { return m_pole_points; } + double getFastestLapPoints() const { return m_fastest_lap_points; } + double getQuitPoints() const { return m_quit_points; } + double getAbsencePoints() const { return m_absence_points; } + + static double parseThousandth(std::vector& argv, int idx) + { + int temp; + if (!StringUtils::parseString(argv[idx], &temp)) + throw std::domain_error(StringUtils::insertValues( + "Argument %s is not a valid integer", idx)); + + return temp * 0.001; + } + + template + static T parse(std::vector& argv, T idx) + { + T temp; + if (!StringUtils::parseString(argv[idx], &temp)) + throw std::domain_error(StringUtils::insertValues( + "Argument %s cannot be parsed", idx)); + + return temp; + } +}; + + +#endif // SCORING_HPP \ No newline at end of file diff --git a/src/utils/scoring/standard_scoring.cpp b/src/utils/scoring/standard_scoring.cpp new file mode 100644 index 00000000000..da6a91caafa --- /dev/null +++ b/src/utils/scoring/standard_scoring.cpp @@ -0,0 +1,42 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "utils/scoring/standard_scoring.hpp" + + +void GPScoring::refreshCustomScores(int num_karts, + std::vector& score_for_position) +{ + // nothing? +} // refreshCustomScores + + +int GPScoring::getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const +{ + Log::error("GPScoring", "Unknown scoring type: %s. Giving 0 points", m_type.c_str()); + return 0; +} // getScoreForPosition +//----------------------------------------------------------------------------- + +bool GPScoring::canGetScoreForPosition(int p, const std::map& race_times) const +{ + return true; +} // canGetScoreForPosition +//----------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/utils/scoring/standard_scoring.hpp b/src/utils/scoring/standard_scoring.hpp new file mode 100644 index 00000000000..c915fde7dbe --- /dev/null +++ b/src/utils/scoring/standard_scoring.hpp @@ -0,0 +1,45 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2025 kimden +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef STANDARD_SCORING_HPP +#define STANDARD_SCORING_HPP + +#include "utils/scoring/scoring.hpp" + +class StandardScoring: public Scoring +{ +public: + void fromIntParamString(const std::string& input) final; + + void fromString(const std::string& input) final; + + bool isStandard() const final { return true; } + + void refreshCustomScores(int num_karts, std::vector& score_for_position) final; + + int getScoreForPosition(int p, float time, + std::map& race_times, + const std::vector& score_for_position) const final; + + bool canGetScoreForPosition(int p, const std::map& race_times) const final; + + std::string toString() const; +}; + + +#endif // STANDARD_SCORING_HPP \ No newline at end of file