feat: add scoreTeamColorName to Scoreboard

This commit is contained in:
dualfroz committed 2026-09-09 16:10:18 +02:00
1 parent ffbe9f6cfb
commit b39f201628
1 file changed
+173
+173
View File
@@ -151,3 +151,176 @@ const char* displaySlotName(DisplaySlot slot) {
return "unknown"; return "unknown";
} }
std::string ScoreObjective::formatScore(int score) const {
if (format == Format::Distance) {
long long centimetres = score;
std::string sign = centimetres < 0 ? "-" : "";
long long magnitude = centimetres < 0 ? -centimetres : centimetres;
return sign + std::to_string(magnitude / 100) + "." + twoDigits(magnitude % 100) + " m";
}
if (format == Format::Duration) {
long long ticks = score < 0 ? 0 : score;
long long seconds = ticks / ticksPerSecond;
long long hours = seconds / 3600;
long long minutes = (seconds % 3600) / 60;
long long rest = seconds % 60;
if (hours > 0)
return std::to_string(hours) + "h " + twoDigits(minutes) + "m " + twoDigits(rest) + "s";
if (minutes > 0) return std::to_string(minutes) + "m " + twoDigits(rest) + "s";
return std::to_string(rest) + "s";
}
return std::to_string(score);
}
bool ScoreTeam::hasMember(const std::string& player) const {
return std::find(members.begin(), members.end(), player) != members.end();
}
const char* scoreTeamColorName(ScoreTeam::Color color) {
switch (color) {
case ScoreTeam::Color::White: return "white";
case ScoreTeam::Color::Gray: return "gray";
case ScoreTeam::Color::Black: return "black";
case ScoreTeam::Color::Red: return "red";
case ScoreTeam::Color::Green: return "green";
case ScoreTeam::Color::Blue: return "blue";
case ScoreTeam::Color::Yellow: return "yellow";
case ScoreTeam::Color::Aqua: return "aqua";
case ScoreTeam::Color::Purple: return "purple";
case ScoreTeam::Color::Gold: return "gold";
case ScoreTeam::Color::Count: break;
}
return "unknown";
}
bool Scoreboard::addObjective(const ScoreObjective& objective) {
if (objective.name.empty()) return false;
if (objectives.count(objective.name) > 0u) return false;
objectives[objective.name] = objective;
return true;
}
bool Scoreboard::removeObjective(const std::string& name) {
if (objectives.erase(name) == 0u) return false;
manualScores.erase(name);
for (std::string& slot : slots)
if (slot == name) slot.clear();
return true;
}
const ScoreObjective* Scoreboard::objective(const std::string& name) const {
auto found = objectives.find(name);
return found == objectives.end() ? nullptr : &found->second;
}
std::vector<std::string> Scoreboard::objectiveNames() const {
std::vector<std::string> out;
out.reserve(objectives.size());
for (const auto& entry : objectives) out.push_back(entry.first);
return out;
}
StatSheet& Scoreboard::stats(const std::string& player) { return sheets[player]; }
const StatSheet* Scoreboard::statsFor(const std::string& player) const {
auto found = sheets.find(player);
return found == sheets.end() ? nullptr : &found->second;
}
std::vector<std::string> Scoreboard::players() const {
std::vector<std::string> out;
for (const auto& sheet : sheets) out.push_back(sheet.first);
for (const auto& objectiveScores : manualScores)
for (const auto& entry : objectiveScores.second)
if (std::find(out.begin(), out.end(), entry.first) == out.end())
out.push_back(entry.first);
for (const auto& membership : teamByPlayer)
if (std::find(out.begin(), out.end(), membership.first) == out.end())
out.push_back(membership.first);
std::sort(out.begin(), out.end());
return out;
}
bool Scoreboard::setScore(const std::string& objectiveName, const std::string& player, int value) {
const ScoreObjective* target = objective(objectiveName);
if (target == nullptr || target->automatic() || player.empty()) return false;
manualScores[objectiveName][player] = value;
return true;
}
bool Scoreboard::addScore(const std::string& objectiveName, const std::string& player, int delta) {
const ScoreObjective* target = objective(objectiveName);
if (target == nullptr || target->automatic() || player.empty()) return false;
long long updated = static_cast<long long>(score(objectiveName, player)) + delta;
manualScores[objectiveName][player] = clampToScore(updated);
return true;
}
bool Scoreboard::resetScore(const std::string& objectiveName, const std::string& player) {
auto found = manualScores.find(objectiveName);
if (found == manualScores.end()) return false;
return found->second.erase(player) > 0u;
}
void Scoreboard::resetPlayer(const std::string& player) {
for (auto& objectiveScores : manualScores) objectiveScores.second.erase(player);
sheets.erase(player);
}
int Scoreboard::statScore(const ScoreObjective& target, const std::string& player) const {
const StatSheet* sheet = statsFor(player);
if (sheet == nullptr) return 0;
if (target.statSubject < 0) return clampToScore(sheet->total(target.statKind));
return clampToScore(sheet->value(target.statKind, target.statSubject));
}
int Scoreboard::score(const std::string& objectiveName, const std::string& player) const {
const ScoreObjective* target = objective(objectiveName);
if (target == nullptr) return 0;
if (target->automatic()) return statScore(*target, player);
auto objectiveScores = manualScores.find(objectiveName);
if (objectiveScores == manualScores.end()) return 0;
auto entry = objectiveScores->second.find(player);
return entry == objectiveScores->second.end() ? 0 : entry->second;
}
bool Scoreboard::tracked(const std::string& objectiveName, const std::string& player) const {
const ScoreObjective* target = objective(objectiveName);
if (target == nullptr) return false;
if (target->automatic()) return sheets.count(player) > 0u;
auto objectiveScores = manualScores.find(objectiveName);
if (objectiveScores == manualScores.end()) return false;
return objectiveScores->second.count(player) > 0u;
}
std::vector<ScoreEntry> Scoreboard::entries(const std::string& objectiveName) const {
std::vector<ScoreEntry> out;
const ScoreObjective* target = objective(objectiveName);
if (target == nullptr) return out;
if (target->automatic()) {
for (const auto& sheet : sheets) {
ScoreEntry entry;
entry.player = sheet.first;
entry.score = statScore(*target, sheet.first);
out.push_back(entry);
}
} else {
auto objectiveScores = manualScores.find(objectiveName);
if (objectiveScores != manualScores.end()) {
for (const auto& scored : objectiveScores->second) {
ScoreEntry entry;
entry.player = scored.first;
entry.score = scored.second;
out.push_back(entry);
}
}
}
const bool ascending = target->sort == ScoreObjective::Sort::Ascending;
std::sort(out.begin(), out.end(), [ascending](const ScoreEntry& a, const ScoreEntry& b) {
if (a.score != b.score) return ascending ? a.score < b.score : a.score > b.score;
return a.player < b.player;
});
for (ScoreEntry& entry : out) entry.formatted = target->formatScore(entry.score);
return out;
}