Repository navigation
Expand file tree
/
Copy pathlogger.cpp
More file actions
51 lines (43 loc) · 1.88 KB
/
Copy pathlogger.cpp
File metadata and controls
51 lines (43 loc) · 1.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// GameLogger 的实现:订阅 TickResult 流,累积 LogEntry,局末追加写入日志文件。
//
// 说明:Replayer 在 DESIGN.md 中定位为占位接口(依赖 GameState 完整回放),
// 本阶段不提供其定义,仅实现文件写入与解析相关部分。
#include "log/logger.hpp"
#include <fstream>
#include <stdexcept>
namespace snake::log {
void GameLogger::begin(std::int32_t width, std::int32_t height,
core::Position initial_head, core::Position first_fruit) {
entry_ = LogEntry{};
entry_.board_width = width;
entry_.board_height = height;
// 核心 0 基坐标 → 日志 1 基「行×列」坐标(换算见 DESIGN.md §3)。
entry_.initial_head = {initial_head.x + 1, initial_head.y + 1};
entry_.append_fruit({first_fruit.x + 1, first_fruit.y + 1});
}
void GameLogger::on_tick(const core::TickResult& r) {
// 每个 tick 的方向都入方向流。
entry_.append_move(r.moved);
// 吃到果实且新果实已生成时,把新果实位置追加进果实序列。
if (r.ate_fruit && r.fruit_exists) {
// 核心 0 基坐标 → 日志 1 基「行×列」坐标。
entry_.append_fruit({r.fruit.x + 1, r.fruit.y + 1});
}
}
std::string GameLogger::finish(core::Phase final_phase,
const std::filesystem::path& file) {
// Won 之外的结局(Lost / Running 等)一律记 {L}。
entry_.outcome = (final_phase == core::Phase::Won) ? Outcome::Won : Outcome::Lost;
const std::string line = entry_.serialize();
std::ofstream ofs(file, std::ios::app);
if (!ofs) {
throw std::runtime_error("GameLogger: cannot open log file for append: " +
file.string());
}
ofs << line << '\n';
return line;
}
const LogEntry& GameLogger::pending() const noexcept {
return entry_;
}
} // namespace snake::log