diff --git a/core/src/Scoreboard.cpp b/core/src/Scoreboard.cpp new file mode 100644 index 0000000..57af12f --- /dev/null +++ b/core/src/Scoreboard.cpp @@ -0,0 +1,153 @@ +#include "vf/Scoreboard.h" + +#include + +namespace vf { + +namespace { + +int clampToScore(long long value) { + const long long high = 2147483647ll; + const long long low = -2147483648ll; + if (value > high) return static_cast(high); + if (value < low) return static_cast(low); + return static_cast(value); +} + +std::string twoDigits(long long value) { + std::string text = std::to_string(value); + return text.size() < 2u ? "0" + text : text; +} + +} // namespace + +const char* statKindName(StatKind kind) { + switch (kind) { + case StatKind::DistanceWalked: return "distanceWalked"; + case StatKind::DistanceSprinted: return "distanceSprinted"; + case StatKind::DistanceSwum: return "distanceSwum"; + case StatKind::DistanceFallen: return "distanceFallen"; + case StatKind::DistanceClimbed: return "distanceClimbed"; + case StatKind::BlocksBroken: return "blocksBroken"; + case StatKind::ItemsUsed: return "itemsUsed"; + case StatKind::MobsKilled: return "mobsKilled"; + case StatKind::Deaths: return "deaths"; + case StatKind::DamageDealt: return "damageDealt"; + case StatKind::DamageTaken: return "damageTaken"; + case StatKind::PlayTicks: return "playTicks"; + case StatKind::Count: break; + } + return "unknown"; +} + +bool parseStatKindName(const std::string& text, StatKind& out) { + for (int i = 0; i < static_cast(StatKind::Count); ++i) { + StatKind kind = static_cast(i); + if (text == statKindName(kind)) { + out = kind; + return true; + } + } + return false; +} + +bool statKindHasSubject(StatKind kind) { + return kind == StatKind::BlocksBroken || kind == StatKind::ItemsUsed || + kind == StatKind::MobsKilled; +} + +bool statKindIsDistance(StatKind kind) { + return kind == StatKind::DistanceWalked || kind == StatKind::DistanceSprinted || + kind == StatKind::DistanceSwum || kind == StatKind::DistanceFallen || + kind == StatKind::DistanceClimbed; +} + +void StatSheet::add(StatKind kind, long long amount) { addFor(kind, 0, amount); } + +void StatSheet::addFor(StatKind kind, int subject, long long amount) { + if (amount == 0) return; + cells[std::make_pair(kind, subject)] += amount; + ++changes; +} + +void StatSheet::addBlockBroken(Block block, long long amount) { + addFor(StatKind::BlocksBroken, static_cast(block), amount); +} + +void StatSheet::addItemUsed(ItemId item, long long amount) { + addFor(StatKind::ItemsUsed, static_cast(item), amount); +} + +void StatSheet::addMobKilled(Species species, long long amount) { + addFor(StatKind::MobsKilled, static_cast(species), amount); +} + +void StatSheet::clear() { + if (cells.empty()) return; + cells.clear(); + ++changes; +} + +long long StatSheet::total(StatKind kind) const { + long long sum = 0; + for (const auto& cell : cells) + if (cell.first.first == kind) sum += cell.second; + return sum; +} + +long long StatSheet::value(StatKind kind, int subject) const { + auto found = cells.find(std::make_pair(kind, subject)); + return found == cells.end() ? 0 : found->second; +} + +long long StatSheet::blocksBroken(Block block) const { + return value(StatKind::BlocksBroken, static_cast(block)); +} + +long long StatSheet::itemsUsed(ItemId item) const { + return value(StatKind::ItemsUsed, static_cast(item)); +} + +long long StatSheet::mobsKilled(Species species) const { + return value(StatKind::MobsKilled, static_cast(species)); +} + +long long StatSheet::distanceTravelled() const { + long long sum = 0; + for (int i = 0; i < static_cast(StatKind::Count); ++i) { + StatKind kind = static_cast(i); + if (statKindIsDistance(kind)) sum += total(kind); + } + return sum; +} + +std::vector StatSheet::counters() const { + std::vector out; + out.reserve(cells.size()); + for (const auto& cell : cells) { + StatCounter counter; + counter.kind = cell.first.first; + counter.subject = cell.first.second; + counter.value = cell.second; + out.push_back(counter); + } + return out; +} + +int StatSheet::distinctSubjects(StatKind kind) const { + int count = 0; + for (const auto& cell : cells) + if (cell.first.first == kind) ++count; + return count; +} + +const char* displaySlotName(DisplaySlot slot) { + switch (slot) { + case DisplaySlot::PlayerList: return "playerList"; + case DisplaySlot::Sidebar: return "sidebar"; + case DisplaySlot::BelowName: return "belowName"; + case DisplaySlot::Count: break; + } + return "unknown"; +} +