From e83d91385243024955ff8f7395cca328ed63a3b5 Mon Sep 17 00:00:00 2001 From: wancat Date: Thu, 7 Mar 2024 00:25:50 +0800 Subject: [PATCH] refactor: separate matchers --- packages/game/package.json | 10 +++ packages/game/src/condition.ts | 73 ------------------- packages/game/src/condition/commandMatcher.ts | 13 ++++ packages/game/src/condition/condition.ts | 30 ++++++++ packages/game/src/condition/errorMatcher.ts | 18 +++++ packages/game/src/{ => condition}/matcher.ts | 2 +- packages/game/src/condition/outputMatcher.ts | 13 ++++ packages/game/src/condition/pwdMatcher.ts | 10 +++ packages/game/test/condition.test.ts | 29 +++----- packages/game/tsconfig.json | 8 ++ 10 files changed, 114 insertions(+), 92 deletions(-) create mode 100644 packages/game/package.json delete mode 100644 packages/game/src/condition.ts create mode 100644 packages/game/src/condition/commandMatcher.ts create mode 100644 packages/game/src/condition/condition.ts create mode 100644 packages/game/src/condition/errorMatcher.ts rename packages/game/src/{ => condition}/matcher.ts (64%) create mode 100644 packages/game/src/condition/outputMatcher.ts create mode 100644 packages/game/src/condition/pwdMatcher.ts create mode 100644 packages/game/tsconfig.json diff --git a/packages/game/package.json b/packages/game/package.json new file mode 100644 index 0000000..7e6a856 --- /dev/null +++ b/packages/game/package.json @@ -0,0 +1,10 @@ +{ + "name": "@linux-odyssey/game", + "version": "1.0.0", + "main": "dist/index.ts", + "license": "MIT", + "scripts": { + "build": "tsc -b" + }, + "dependencies": {} +} diff --git a/packages/game/src/condition.ts b/packages/game/src/condition.ts deleted file mode 100644 index 9b4857d..0000000 --- a/packages/game/src/condition.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* eslint-disable max-classes-per-file */ -import { Command } from './command' -import { Matcher } from './matcher' - -export class CommandMatcher implements Matcher { - private matcher: RegExp - constructor(pattern: string, args?: string) { - this.matcher = new RegExp(pattern, args) - } - - match(command: Partial): boolean { - return !!command.command && this.matcher.test(command.command) - } -} - -export class ErrorMatcher implements Matcher { - private matcher?: RegExp - constructor(errorPattern?: string) { - if (errorPattern) { - this.matcher = new RegExp(errorPattern) - } - } - - match(command: Partial): boolean { - if (!this.matcher) { - return !command.error - } - return this.matcher.test(command.error || '') - } -} - -export class PwdMatcher implements Matcher { - constructor(private pwd: string) {} - - match(command: Partial): boolean { - return command.pwd === this.pwd - } -} - -export class OutputMatcher implements Matcher { - private matcher: RegExp - constructor(pattern: string, args?: string) { - this.matcher = new RegExp(pattern, args) - } - - match(command: Partial): boolean { - return !!command.output && this.matcher.test(command.output.trim()) - } -} - -export interface ICondition { - command?: string - output?: string - error?: string - pwd?: string -} - -export class Condition { - private matchers: Matcher[] = [] - - constructor({ command, output, error, pwd }: ICondition) { - if (command) this.matchers.push(new CommandMatcher(command)) - if (output) this.matchers.push(new OutputMatcher(output)) - if (pwd) this.matchers.push(new PwdMatcher(pwd)) - this.matchers.push(new ErrorMatcher(error)) // always check unexpected error - } - - match(command: Partial): boolean { - return this.matchers.every((matcher) => { - return matcher.match(command) - }) - } -} diff --git a/packages/game/src/condition/commandMatcher.ts b/packages/game/src/condition/commandMatcher.ts new file mode 100644 index 0000000..2d102b3 --- /dev/null +++ b/packages/game/src/condition/commandMatcher.ts @@ -0,0 +1,13 @@ +import { Command } from '../command.js' +import { Matcher } from './matcher.js' + +export class CommandMatcher implements Matcher { + private matcher: RegExp + constructor(command: string, flags?: string) { + this.matcher = new RegExp(command, flags) + } + + match(command: Partial): boolean { + return !!command.command && this.matcher.test(command.command) + } +} diff --git a/packages/game/src/condition/condition.ts b/packages/game/src/condition/condition.ts new file mode 100644 index 0000000..f65d9b8 --- /dev/null +++ b/packages/game/src/condition/condition.ts @@ -0,0 +1,30 @@ +import { Command } from '../command.js' +import { PwdMatcher } from './pwdMatcher.js' +import { CommandMatcher } from './commandMatcher.js' +import { ErrorMatcher } from './errorMatcher.js' +import { Matcher } from './matcher.js' +import { OutputMatcher } from './outputMatcher.js' + +export interface ICondition { + command?: string + output?: string + error?: string + pwd?: string +} + +export class Condition { + private matchers: Matcher[] = [] + + constructor({ command, output, error, pwd }: ICondition) { + if (command) this.matchers.push(new CommandMatcher(command)) + if (output) this.matchers.push(new OutputMatcher(output)) + if (pwd) this.matchers.push(new PwdMatcher(pwd)) + this.matchers.push(new ErrorMatcher(error)) // always check unexpected error + } + + match(command: Partial): boolean { + return this.matchers.every((matcher) => { + return matcher.match(command) + }) + } +} diff --git a/packages/game/src/condition/errorMatcher.ts b/packages/game/src/condition/errorMatcher.ts new file mode 100644 index 0000000..53898fb --- /dev/null +++ b/packages/game/src/condition/errorMatcher.ts @@ -0,0 +1,18 @@ +import { Matcher } from './matcher.js' +import { Command } from '../command.js' + +export class ErrorMatcher implements Matcher { + private matcher?: RegExp + constructor(errorPattern?: string) { + if (errorPattern) { + this.matcher = new RegExp(errorPattern) + } + } + + match(command: Partial): boolean { + if (!this.matcher) { + return !command.error + } + return this.matcher.test(command.error || '') + } +} diff --git a/packages/game/src/matcher.ts b/packages/game/src/condition/matcher.ts similarity index 64% rename from packages/game/src/matcher.ts rename to packages/game/src/condition/matcher.ts index b1de51d..29afe3f 100644 --- a/packages/game/src/matcher.ts +++ b/packages/game/src/condition/matcher.ts @@ -1,4 +1,4 @@ -import { Command } from './command' +import { Command } from '../command.js' export interface Matcher { match(command: Partial): boolean diff --git a/packages/game/src/condition/outputMatcher.ts b/packages/game/src/condition/outputMatcher.ts new file mode 100644 index 0000000..3bedb55 --- /dev/null +++ b/packages/game/src/condition/outputMatcher.ts @@ -0,0 +1,13 @@ +import { Command } from '../command.js' +import { Matcher } from './matcher.js' + +export class OutputMatcher implements Matcher { + private matcher: RegExp + constructor(pattern: string, args?: string) { + this.matcher = new RegExp(pattern, args) + } + + match(command: Partial): boolean { + return !!command.output && this.matcher.test(command.output.trim()) + } +} diff --git a/packages/game/src/condition/pwdMatcher.ts b/packages/game/src/condition/pwdMatcher.ts new file mode 100644 index 0000000..f4e276a --- /dev/null +++ b/packages/game/src/condition/pwdMatcher.ts @@ -0,0 +1,10 @@ +import { Command } from '../command.js' +import { Matcher } from './matcher.js' + +export class PwdMatcher implements Matcher { + constructor(private pwd: string) {} + + match(command: Partial): boolean { + return command.pwd === this.pwd + } +} diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts index 53c8922..0310331 100644 --- a/packages/game/test/condition.test.ts +++ b/packages/game/test/condition.test.ts @@ -1,23 +1,16 @@ import { test, expect } from '@jest/globals' -import { - CommandMatcher, - ErrorMatcher, - PwdMatcher, - OutputMatcher, - Condition, -} from '../src/condition' -import { Command } from '../src/command' +import { Condition } from '../src/condition/condition' +import { OutputMatcher } from '../src/condition/outputMatcher' +import { PwdMatcher } from '../src/condition/pwdMatcher' +import { CommandMatcher } from '../src/condition/commandMatcher' +import { ErrorMatcher } from '../src/condition/errorMatcher.js' test('command match', () => { - const command: Command = { - command: 'echo start', - output: 'start', - error: '', - pwd: '/home/user', - } - - const matcher = new CommandMatcher('^echo start$', 'i') - expect(matcher.match(command)).toBe(true) + const matcher = new CommandMatcher('^echo start$') + expect(matcher.match({ command: 'echo start' })).toBe(true) + expect(matcher.match({ command: 'echo start1' })).toBe(false) + // Currently not supported + expect(matcher.match({ command: 'echo "start"' })).toBe(false) }) test('error matcher', () => { @@ -50,7 +43,7 @@ test('output matcher', () => { expect(matcher.match({ output: 'start\n' })).toBe(true) }) -test('condition match', () => { +test('condition match command', () => { const condition = new Condition({ command: '^echo start$', }) diff --git a/packages/game/tsconfig.json b/packages/game/tsconfig.json new file mode 100644 index 0000000..49e05ce --- /dev/null +++ b/packages/game/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "include": ["src"] +}