test: cover manualObjective and statObjective

This commit is contained in:
dualfroz committed 2026-09-12 23:00:22 +02:00
1 parent dcba0c8da0
commit 5f13d20936
1 file changed
+157
+157
View File
@@ -0,0 +1,157 @@
#include "testHarness.h"
#include "vf/Scoreboard.h"
#include <string>
using namespace vf;
namespace {
ScoreObjective manualObjective(const std::string& name) {
ScoreObjective objective;
objective.name = name;
objective.displayName = name;
return objective;
}
ScoreObjective statObjective(const std::string& name, StatKind kind, int subject = -1) {
ScoreObjective objective = manualObjective(name);
objective.criterion = ScoreObjective::Criterion::Statistic;
objective.statKind = kind;
objective.statSubject = subject;
return objective;
}
ScoreTeam makeTeam(const std::string& name, ScoreTeam::Color color) {
ScoreTeam team;
team.name = name;
team.displayName = name;
team.color = color;
return team;
}
} // namespace
VF_TEST(statSheetsTallyEveryKindWithAndWithoutASubject) {
StatSheet sheet;
CHECK_EQ(sheet.revision(), 0);
CHECK_EQ(sheet.total(StatKind::Deaths), 0);
sheet.add(StatKind::Deaths, 1);
sheet.add(StatKind::PlayTicks, 12000);
sheet.add(StatKind::DistanceWalked, 450);
sheet.add(StatKind::DistanceSprinted, 1200);
sheet.addBlockBroken(Block::Stone, 40);
sheet.addBlockBroken(Block::Dirt, 7);
sheet.addItemUsed(ItemId::IronPickaxe, 3);
sheet.addMobKilled(Species::Zombie, 2);
sheet.addMobKilled(Species::Creeper);
CHECK_EQ(sheet.total(StatKind::Deaths), 1);
CHECK_EQ(sheet.total(StatKind::PlayTicks), 12000);
CHECK_EQ(sheet.blocksBroken(Block::Stone), 40);
CHECK_EQ(sheet.blocksBroken(Block::Sand), 0);
CHECK_EQ(sheet.total(StatKind::BlocksBroken), 47);
CHECK_EQ(sheet.itemsUsed(ItemId::IronPickaxe), 3);
CHECK_EQ(sheet.mobsKilled(Species::Zombie), 2);
CHECK_EQ(sheet.mobsKilled(Species::Creeper), 1);
CHECK_EQ(sheet.total(StatKind::MobsKilled), 3);
CHECK_EQ(sheet.distanceTravelled(), 1650);
CHECK_EQ(sheet.distinctSubjects(StatKind::BlocksBroken), 2);
CHECK_EQ(sheet.distinctSubjects(StatKind::Deaths), 1);
long long before = sheet.revision();
sheet.add(StatKind::Deaths, 0);
CHECK_EQ(sheet.revision(), before);
sheet.add(StatKind::Deaths, 1);
CHECK_EQ(sheet.revision(), before + 1);
CHECK_EQ(sheet.total(StatKind::Deaths), 2);
std::vector<StatCounter> counters = sheet.counters();
CHECK_EQ(counters.size(), static_cast<std::size_t>(9));
for (std::size_t i = 1u; i < counters.size(); ++i) {
bool ordered = counters[i - 1u].kind < counters[i].kind ||
(counters[i - 1u].kind == counters[i].kind &&
counters[i - 1u].subject < counters[i].subject);
CHECK(ordered);
}
sheet.clear();
CHECK_EQ(sheet.counters().size(), static_cast<std::size_t>(0));
CHECK_EQ(sheet.total(StatKind::BlocksBroken), 0);
CHECK(sheet.revision() > before);
for (int i = 0; i < static_cast<int>(StatKind::Count); ++i) {
StatKind kind = static_cast<StatKind>(i);
StatKind reparsed = StatKind::Count;
CHECK(parseStatKindName(statKindName(kind), reparsed));
CHECK(reparsed == kind);
}
StatKind unknown = StatKind::Count;
CHECK(!parseStatKindName("blocksPlaced", unknown));
CHECK(statKindHasSubject(StatKind::BlocksBroken));
CHECK(!statKindHasSubject(StatKind::Deaths));
CHECK(statKindIsDistance(StatKind::DistanceFallen));
CHECK(!statKindIsDistance(StatKind::PlayTicks));
}
VF_TEST(anAutomaticObjectiveFollowsTheStatSheetWithNoUpdateStep) {
Scoreboard board;
CHECK(board.addObjective(statObjective("mined", StatKind::BlocksBroken)));
CHECK(board.addObjective(statObjective("stone", StatKind::BlocksBroken,
static_cast<int>(Block::Stone))));
CHECK(board.addObjective(statObjective("deaths", StatKind::Deaths)));
CHECK_EQ(board.score("mined", "foksiu"), 0);
CHECK(!board.tracked("mined", "foksiu"));
board.stats("foksiu").addBlockBroken(Block::Stone, 12);
CHECK(board.tracked("mined", "foksiu"));
CHECK_EQ(board.score("mined", "foksiu"), 12);
CHECK_EQ(board.score("stone", "foksiu"), 12);
board.stats("foksiu").addBlockBroken(Block::Dirt, 5);
CHECK_EQ(board.score("mined", "foksiu"), 17);
CHECK_EQ(board.score("stone", "foksiu"), 12);
board.stats("foksiu").add(StatKind::Deaths, 1);
CHECK_EQ(board.score("deaths", "foksiu"), 1);
CHECK_EQ(board.score("mined", "foksiu"), 17);
// An automatic objective refuses to be written by hand.
CHECK(!board.setScore("mined", "foksiu", 999));
CHECK(!board.addScore("mined", "foksiu", 1));
CHECK_EQ(board.score("mined", "foksiu"), 17);
CHECK(!board.addObjective(statObjective("mined", StatKind::Deaths)));
CHECK_EQ(board.objectiveNames().size(), static_cast<std::size_t>(3));
CHECK(board.objective("mined")->automatic());
CHECK(board.objective("nothing") == nullptr);
CHECK_EQ(board.score("nothing", "foksiu"), 0);
}
VF_TEST(manualObjectivesOnlyMoveWhenSomethingSetsThem) {
Scoreboard board;
CHECK(board.addObjective(manualObjective("bounty")));
CHECK(!board.addObjective(manualObjective("")));
CHECK(!board.tracked("bounty", "foksiu"));
CHECK(board.setScore("bounty", "foksiu", 10));
CHECK(board.tracked("bounty", "foksiu"));
CHECK_EQ(board.score("bounty", "foksiu"), 10);
CHECK(board.addScore("bounty", "foksiu", -4));
CHECK_EQ(board.score("bounty", "foksiu"), 6);
CHECK(board.addScore("bounty", "newcomer", 3));
CHECK_EQ(board.score("bounty", "newcomer"), 3);
CHECK(!board.setScore("absent", "foksiu", 1));
CHECK(board.resetScore("bounty", "foksiu"));
CHECK(!board.resetScore("bounty", "foksiu"));
CHECK(!board.tracked("bounty", "foksiu"));
CHECK_EQ(board.score("bounty", "foksiu"), 0);
board.stats("newcomer").add(StatKind::Deaths, 2);
board.resetPlayer("newcomer");
CHECK(!board.tracked("bounty", "newcomer"));
CHECK(board.statsFor("newcomer") == nullptr);