From 28e8fc8dc6771a2d33b35e758d2b025a52e9f30a Mon Sep 17 00:00:00 2001 From: indifferentketchup Date: Thu, 30 Apr 2026 20:34:50 +0000 Subject: [PATCH] Add ProjectZomboidChatLog (chat.txt) Handles both chat-engine events (bracketed level prefix) and bare server-alert lines via an optional level group. Detectors: filename match on _chat.txt plus content signatures for ChatMessage{...} log entries and the chat-server initialization banner. CHAT_MESSAGE and SERVER_ALERT named-group regexes ride along on ChatPattern for analyser extraction in phase B. --- .../ProjectZomboid/ProjectZomboidChatLog.php | 47 ++++++++++++++++ src/Pattern/ProjectZomboid/ChatPattern.php | 24 +++++++++ .../ProjectZomboid/fixtures/chat-minimal.txt | 13 +++++ .../Log/ProjectZomboidChatLogTest.php | 53 +++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 src/Log/ProjectZomboid/ProjectZomboidChatLog.php create mode 100644 src/Pattern/ProjectZomboid/ChatPattern.php create mode 100644 test/src/Games/ProjectZomboid/fixtures/chat-minimal.txt create mode 100644 test/tests/Games/ProjectZomboid/Log/ProjectZomboidChatLogTest.php diff --git a/src/Log/ProjectZomboid/ProjectZomboidChatLog.php b/src/Log/ProjectZomboid/ProjectZomboidChatLog.php new file mode 100644 index 0000000..971b75e --- /dev/null +++ b/src/Log/ProjectZomboid/ProjectZomboidChatLog.php @@ -0,0 +1,47 @@ +setPattern('/_chat\.txt$/') + ->setWeight(0.95), + (new WeightedSinglePatternDetector()) + ->setPattern('/Got message:ChatMessage\{chat=\w+/') + ->setWeight(0.95), + (new WeightedSinglePatternDetector()) + ->setPattern('/Start chat server initialization/') + ->setWeight(0.85), + ]; + } + + public function getTitle(): string + { + return "Project Zomboid Chat Log"; + } +} diff --git a/src/Pattern/ProjectZomboid/ChatPattern.php b/src/Pattern/ProjectZomboid/ChatPattern.php new file mode 100644 index 0000000..801914c --- /dev/null +++ b/src/Pattern/ProjectZomboid/ChatPattern.php @@ -0,0 +1,24 @@ +\w+), author=\'(?[^\']+)\', text=\'(?.*?)\'\}/'; + + public const string SERVER_ALERT = '/^Server alert message:\s*\'(?.*?)\'\s+sent\.\.?$/'; +} diff --git a/test/src/Games/ProjectZomboid/fixtures/chat-minimal.txt b/test/src/Games/ProjectZomboid/fixtures/chat-minimal.txt new file mode 100644 index 0000000..5a22b71 --- /dev/null +++ b/test/src/Games/ProjectZomboid/fixtures/chat-minimal.txt @@ -0,0 +1,13 @@ +[16-04-26 16:16:34.105][info] Start chat server initialization.... +[16-04-26 16:16:34.108][info] General chat has id = 0. +[16-04-26 16:16:34.108][info] Say chat has id = 1. +[16-04-26 16:16:34.108][info] Shout chat has id = 2. +[16-04-26 16:16:34.108][info] Radio chat has id = 3. +[16-04-26 17:05:03.280][info] Got message:ChatMessage{chat=Local, author='Player1', text='hello'}. +[16-04-26 17:05:03.282][info] Message ChatMessage{chat=Local, author='Player1', text='hello'} sent to chat (id = 2) members. +[16-04-26 17:22:55.182][info] Got message:ChatMessage{chat=Local, author='Player2', text='hi there'}. +[16-04-26 17:22:55.184][info] Got message:ChatMessage{chat=Global, author='Player1', text='who is online'}. +[16-04-26 17:22:55.186][info] Got message:ChatMessage{chat=Local, author='AdminUser', text='cleanup soon'}. +[16-04-26 18:25:19.523] Server alert message: 'Test Server: Server will restart in 5 seconds for mod updates.' sent.. +[16-04-26 18:25:21.323] Server alert message: 'Test Server: Server will restart in 4 seconds for mod updates.' sent.. +[16-04-26 18:25:23.123] Server alert message: 'Test Server: Server will restart in 3 seconds for mod updates.' sent.. diff --git a/test/tests/Games/ProjectZomboid/Log/ProjectZomboidChatLogTest.php b/test/tests/Games/ProjectZomboid/Log/ProjectZomboidChatLogTest.php new file mode 100644 index 0000000..0633f79 --- /dev/null +++ b/test/tests/Games/ProjectZomboid/Log/ProjectZomboidChatLogTest.php @@ -0,0 +1,53 @@ +setLogFile(new PathLogFile($this->fixturePath())); + $log->parse(); + + $this->assertCount(13, $log->getEntries()); + } + + public function testInfoBracketIsParsedAsLevel(): void + { + $log = (new ProjectZomboidChatLog())->setLogFile(new PathLogFile($this->fixturePath())); + $log->parse(); + + $first = $log->getEntries()[0]; + $this->assertSame(Level::INFO, $first->getLevel()); + $this->assertNotNull($first->getTime()); + } + + public function testServerAlertLinesParseWithoutLevel(): void + { + $log = (new ProjectZomboidChatLog())->setLogFile(new PathLogFile($this->fixturePath())); + $log->parse(); + + $alert = $log->getEntries()[10]; + $this->assertStringContainsString('Server alert message', (string) $alert); + } + + public function testDetectiveDispatchesByContent(): void + { + $detective = (new Detective()) + ->setLogFile(new PathLogFile($this->fixturePath())) + ->addPossibleLogClass(ProjectZomboidChatLog::class); + + $this->assertInstanceOf(ProjectZomboidChatLog::class, $detective->detect()); + } +}