Compares consecutive perks-snapshot rows per Steam ID and emits a SkillProgressionAnomalyProblem for any single skill whose level gained more than THRESHOLD_DELTA between two snapshots. Login/Logout/LevelUp event rows are skipped via a perk-pair regex check on the bracketed event field. Threshold of 3 reflects PZ's slow leveling pace: typical session bridges should not produce four-or-more level jumps in a single skill. The constant is documented inline so operators can tune for modded XP servers without touching analysis logic. Synthetic fixture extended with a PlayerSuspect Steam ID carrying two snapshots: Strength jumps 2 -> 10 (delta +8, triggers), Fitness jumps 2 -> 8 (+6, triggers), Maintenance jumps 0 -> 3 (+3, exactly at threshold, does NOT trigger). The existing single-snapshot players remain noise-free.
67 lines
2.4 KiB
PHP
67 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace IndifferentKetchup\Codex\Test\Tests\Games\ProjectZomboid\Analyser;
|
|
|
|
use IndifferentKetchup\Codex\Analyser\ProjectZomboid\SkillProgressionAnomalyAnalyser;
|
|
use IndifferentKetchup\Codex\Analysis\ProjectZomboid\SkillProgressionAnomalyProblem;
|
|
use IndifferentKetchup\Codex\Log\File\PathLogFile;
|
|
use IndifferentKetchup\Codex\Log\ProjectZomboid\ProjectZomboidPerkLog;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class PerkLogAnalysisTest extends TestCase
|
|
{
|
|
private function fixturePath(): string
|
|
{
|
|
return __DIR__ . '/../../../../src/Games/ProjectZomboid/fixtures/perk-minimal.txt';
|
|
}
|
|
|
|
public function testFlagsSkillsThatExceedDeltaThreshold(): void
|
|
{
|
|
$log = (new ProjectZomboidPerkLog())->setLogFile(new PathLogFile($this->fixturePath()));
|
|
$log->parse();
|
|
$analysis = $log->analyse();
|
|
|
|
$problems = $analysis->getFilteredInsights(SkillProgressionAnomalyProblem::class);
|
|
|
|
$skills = array_map(fn($p) => $p->getSkill(), $problems);
|
|
sort($skills);
|
|
|
|
$this->assertSame(['Fitness', 'Strength'], $skills);
|
|
|
|
foreach ($problems as $problem) {
|
|
$this->assertSame('76561198000000004', $problem->getSteamId());
|
|
$this->assertSame('PlayerSuspect', $problem->getPlayer());
|
|
}
|
|
}
|
|
|
|
public function testDeltaAtThresholdDoesNotTrigger(): void
|
|
{
|
|
$log = (new ProjectZomboidPerkLog())->setLogFile(new PathLogFile($this->fixturePath()));
|
|
$log->parse();
|
|
$analysis = $log->analyse();
|
|
|
|
$problems = $analysis->getFilteredInsights(SkillProgressionAnomalyProblem::class);
|
|
foreach ($problems as $problem) {
|
|
$this->assertNotSame('Maintenance', $problem->getSkill());
|
|
}
|
|
}
|
|
|
|
public function testSinglePlayerWithOneSnapshotProducesNoProblem(): void
|
|
{
|
|
$log = (new ProjectZomboidPerkLog())->setLogFile(new PathLogFile($this->fixturePath()));
|
|
$log->parse();
|
|
$analysis = $log->analyse();
|
|
|
|
$problems = $analysis->getFilteredInsights(SkillProgressionAnomalyProblem::class);
|
|
foreach ($problems as $problem) {
|
|
$this->assertNotSame('76561198000000001', $problem->getSteamId());
|
|
$this->assertNotSame('76561198000000002', $problem->getSteamId());
|
|
}
|
|
}
|
|
|
|
public function testThresholdConstantIsDocumentedAndPositive(): void
|
|
{
|
|
$this->assertGreaterThan(0, SkillProgressionAnomalyAnalyser::THRESHOLD_DELTA);
|
|
}
|
|
}
|