boardgame-core/src/commands/CommandLog.ts

204 lines
4.2 KiB
TypeScript

import { signal, Signal } from '@preact/signals-core';
import type { Command, CommandLogEntry, CommandExecutionResult, StepResult, QueuedCommand } from './Command';
import { CommandStatus } from './Command';
/**
* 命令日志过滤器
*/
export interface CommandLogFilter {
commandId?: string;
success?: boolean;
startTime?: number;
endTime?: number;
}
/**
* 命令日志类
* 记录所有执行的命令及其结果
*/
export class CommandLog {
/** 日志条目信号 */
private entries: Signal<CommandLogEntry[]>;
/** 待执行队列 */
private queue: QueuedCommand[];
constructor() {
this.entries = signal<CommandLogEntry[]>([]);
this.queue = [];
}
/**
* 记录命令执行
*/
log(
command: Command,
result: CommandExecutionResult,
stepResults: StepResult[]
): void {
const entry: CommandLogEntry = {
timestamp: Date.now(),
commandId: command.id,
commandName: command.name,
result,
stepResults,
};
const current = this.entries.value;
this.entries.value = [...current, entry];
}
/**
* 获取所有日志条目
*/
getEntries(): CommandLogEntry[] {
return this.entries.value;
}
/**
* 获取日志信号
*/
getEntriesSignal(): Signal<CommandLogEntry[]> {
return this.entries;
}
/**
* 根据过滤器获取日志条目
*/
getFilteredEntries(filter: CommandLogFilter): CommandLogEntry[] {
return this.entries.value.filter((entry) => {
if (filter.commandId && entry.commandId !== filter.commandId) {
return false;
}
if (filter.success !== undefined && entry.result.success !== filter.success) {
return false;
}
if (filter.startTime && entry.timestamp < filter.startTime) {
return false;
}
if (filter.endTime && entry.timestamp > filter.endTime) {
return false;
}
return true;
});
}
/**
* 获取命令的执行历史
*/
getCommandHistory(commandId: string): CommandLogEntry[] {
return this.getFilteredEntries({ commandId });
}
/**
* 获取失败的命令
*/
getFailedCommands(): CommandLogEntry[] {
return this.getFilteredEntries({ success: false });
}
/**
* 获取成功的命令
*/
getSuccessfulCommands(): CommandLogEntry[] {
return this.getFilteredEntries({ success: true });
}
/**
* 清空日志
*/
clear(): void {
this.entries.value = [];
}
/**
* 导出日志为 JSON
*/
exportToJson(): string {
return JSON.stringify(this.entries.value, null, 2);
}
/**
* 获取日志条目数量
*/
getCount(): number {
return this.entries.value.length;
}
/**
* 获取最后一个日志条目
*/
getLastEntry(): CommandLogEntry | null {
const entries = this.entries.value;
return entries.length > 0 ? entries[entries.length - 1] : null;
}
// ========== 队列管理 ==========
/**
* 添加命令到队列
*/
enqueue(command: Command): QueuedCommand {
const queued: QueuedCommand = {
id: command.id,
command,
status: CommandStatus.Pending,
queuedAt: Date.now(),
};
this.queue.push(queued);
return queued;
}
/**
* 从队列中移除命令
*/
dequeue(): QueuedCommand | null {
if (this.queue.length === 0) {
return null;
}
return this.queue.shift() || null;
}
/**
* 获取队列中的所有命令
*/
getQueue(): QueuedCommand[] {
return [...this.queue];
}
/**
* 更新队列中命令的状态
*/
updateQueueStatus(commandId: string, status: CommandStatus, result?: CommandExecutionResult): void {
const index = this.queue.findIndex((q) => q.command.id === commandId);
if (index !== -1) {
this.queue[index].status = status;
if (status === CommandStatus.Completed || status === CommandStatus.Failed) {
this.queue[index].executedAt = Date.now();
this.queue[index].result = result;
}
}
}
/**
* 清空队列
*/
clearQueue(): void {
this.queue = [];
}
/**
* 获取队列长度
*/
getQueueLength(): number {
return this.queue.length;
}
}
/**
* 创建命令日志
*/
export function createCommandLog(): CommandLog {
return new CommandLog();
}