Add ConnectionFailureAnalyser
First custom Analyser subclass in this game tree. PatternAnalyser operates per-entry without cross-entry state, so pairing 'attempting to join' with 'allowed to join' per Steam ID requires a bespoke pass over the log. The analyser counts attempts and allowed events per Steam ID and emits a ConnectionFailureProblem for each player whose attempt count exceeds their allowed count. Unmatched 'attempting to join used queue' rows are surfaced as failures in v1 because a long queue wait is indistinguishable from a real failure without timing context.
This commit is contained in:
64
src/Analyser/ProjectZomboid/ConnectionFailureAnalyser.php
Normal file
64
src/Analyser/ProjectZomboid/ConnectionFailureAnalyser.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace IndifferentKetchup\Codex\Analyser\ProjectZomboid;
|
||||
|
||||
use IndifferentKetchup\Codex\Analyser\Analyser;
|
||||
use IndifferentKetchup\Codex\Analysis\Analysis;
|
||||
use IndifferentKetchup\Codex\Analysis\AnalysisInterface;
|
||||
use IndifferentKetchup\Codex\Analysis\ProjectZomboid\ConnectionFailureProblem;
|
||||
use IndifferentKetchup\Codex\Pattern\ProjectZomboid\UserPattern;
|
||||
|
||||
/**
|
||||
* Pairs "attempting to join" with subsequent "allowed to join" events per
|
||||
* Steam ID and flags any unmatched attempts. PatternAnalyser cannot express
|
||||
* this because it operates per-entry without cross-entry state, so this
|
||||
* walks the entire log once and aggregates before emitting Problems.
|
||||
*
|
||||
* "attempting to join used queue" is treated as an attempt; a player still
|
||||
* waiting in queue at end-of-log will therefore be flagged. This is
|
||||
* intentional v1 behaviour — a long-lived queue wait looks indistinguishable
|
||||
* from a real failure without timing context, and surfacing both lets a
|
||||
* human triage.
|
||||
*/
|
||||
class ConnectionFailureAnalyser extends Analyser
|
||||
{
|
||||
public function analyse(): AnalysisInterface
|
||||
{
|
||||
$analysis = new Analysis();
|
||||
$analysis->setLog($this->log);
|
||||
|
||||
$attempts = [];
|
||||
$allowed = [];
|
||||
$playerName = [];
|
||||
|
||||
foreach ($this->log as $entry) {
|
||||
$text = (string) $entry;
|
||||
if (preg_match(UserPattern::PLAYER_EVENT, $text, $m) !== 1) {
|
||||
continue;
|
||||
}
|
||||
$steamId = $m['steamid'];
|
||||
$playerName[$steamId] = $m['player'];
|
||||
|
||||
if (str_starts_with($m['event'], 'attempting to join')) {
|
||||
$attempts[$steamId] = ($attempts[$steamId] ?? 0) + 1;
|
||||
} elseif (str_starts_with($m['event'], 'allowed to join')) {
|
||||
$allowed[$steamId] = ($allowed[$steamId] ?? 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($attempts as $steamId => $attemptCount) {
|
||||
$allowedCount = $allowed[$steamId] ?? 0;
|
||||
$unmatched = $attemptCount - $allowedCount;
|
||||
if ($unmatched <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$analysis->addInsight((new ConnectionFailureProblem())
|
||||
->setSteamId($steamId)
|
||||
->setPlayer($playerName[$steamId] ?? '')
|
||||
->setUnmatchedAttempts($unmatched));
|
||||
}
|
||||
|
||||
return $analysis;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user