mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
refactor: Create a new super class Event and prevent duplicate logic
This commit is contained in:
1 parent
2dc40a2254
commit
0f0f43b838
6 files changed
+109
-49
No files matched your search
@@ -0,0 +1,48 @@
|
||||
import { Condition } from './condition/Condition'
|
||||
import {
|
||||
ICommand,
|
||||
ICondition,
|
||||
IFileExistenceChecker,
|
||||
IRequirements,
|
||||
IResponse,
|
||||
} from './schema'
|
||||
|
||||
export class Event {
|
||||
id: string
|
||||
private condition: Condition
|
||||
private requirements: string[]
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
condition: ICondition,
|
||||
private response: IResponse,
|
||||
requirements?: IRequirements
|
||||
) {
|
||||
this.id = id
|
||||
this.condition = new Condition(condition)
|
||||
this.requirements = requirements || []
|
||||
}
|
||||
|
||||
async satisfies(
|
||||
command: ICommand,
|
||||
checker: IFileExistenceChecker
|
||||
): Promise<boolean> {
|
||||
return this.condition.satisfies(command, checker)
|
||||
}
|
||||
|
||||
private checkRequirements(completed: string[]): boolean {
|
||||
return this.requirements.every((req) => completed.includes(req))
|
||||
}
|
||||
|
||||
private finished(completed: string[]): boolean {
|
||||
return completed.includes(this.id)
|
||||
}
|
||||
|
||||
active(completed: string[]): boolean {
|
||||
return !this.finished(completed) && this.checkRequirements(completed)
|
||||
}
|
||||
|
||||
getResponse(): IResponse {
|
||||
return this.response
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
import { Event } from './Event'
|
||||
import { IStageException, IGlobalException } from './schema/exception'
|
||||
|
||||
export class StageException extends Event {
|
||||
readonly catchAll: boolean
|
||||
|
||||
constructor({ id, condition, response, catchAll }: IStageException) {
|
||||
super(id, condition, response)
|
||||
this.catchAll = catchAll
|
||||
}
|
||||
}
|
||||
|
||||
export class GlobalException extends Event {
|
||||
constructor({ id, condition, response, requirements }: IGlobalException) {
|
||||
super(id, condition, response, requirements)
|
||||
}
|
||||
}
|
||||
+21
-16
@@ -1,5 +1,7 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import { Condition } from './condition/Condition'
|
||||
import { Event } from './Event'
|
||||
import { GlobalException, StageException } from './Exception'
|
||||
import {
|
||||
IQuest,
|
||||
IStage,
|
||||
@@ -10,15 +12,28 @@ import {
|
||||
import { Stage } from './Stage'
|
||||
|
||||
export class Quest {
|
||||
private stages: Stage[]
|
||||
private quest: IQuest
|
||||
private stages: Stage[]
|
||||
private exceptions: GlobalException[] = []
|
||||
private events: Map<string, Event> = new Map()
|
||||
|
||||
constructor(
|
||||
quest: IQuest,
|
||||
private checker: IFileExistenceChecker
|
||||
) {
|
||||
this.quest = quest
|
||||
this.stages = quest.stages.map((stage: IStage) => new Stage(stage))
|
||||
this.stages = quest.stages.map((stage) => new Stage(stage))
|
||||
for (const stage of this.stages) {
|
||||
this.events.set(stage.id, stage)
|
||||
for (const exception of stage.getExceptions()) {
|
||||
this.events.set(exception.id, exception)
|
||||
}
|
||||
}
|
||||
for (const exception of quest.exceptions ?? []) {
|
||||
const globalException = new GlobalException(exception)
|
||||
this.exceptions.push(globalException)
|
||||
this.events.set(globalException.id, globalException)
|
||||
}
|
||||
}
|
||||
|
||||
getActiveStages(completed: string[]) {
|
||||
@@ -26,15 +41,7 @@ export class Quest {
|
||||
}
|
||||
|
||||
private getActiveExceptions(completed: string[]) {
|
||||
return (
|
||||
this.quest.exceptions?.filter(
|
||||
(exception) =>
|
||||
!completed.includes(exception.id) &&
|
||||
exception.requirements.every((requirement) =>
|
||||
completed.includes(requirement)
|
||||
)
|
||||
) ?? []
|
||||
)
|
||||
return this.exceptions.filter((exception) => exception.active(completed))
|
||||
}
|
||||
|
||||
async findSatisfiedEvent(
|
||||
@@ -49,17 +56,15 @@ export class Quest {
|
||||
return stage.id
|
||||
}
|
||||
}
|
||||
for (const exception of stages.flatMap((stage) => stage.exceptions)) {
|
||||
const condition = new Condition(exception.condition)
|
||||
for (const exception of stages.flatMap((stage) => stage.getExceptions())) {
|
||||
if (exception.catchAll && !catchAllException) {
|
||||
catchAllException = exception.id
|
||||
} else if (await condition.satisfies(command, this.checker)) {
|
||||
} else if (await exception.satisfies(command, this.checker)) {
|
||||
return exception.id
|
||||
}
|
||||
}
|
||||
for (const exception of this.getActiveExceptions(completed)) {
|
||||
const condition = new Condition(exception.condition)
|
||||
if (await condition.satisfies(command, this.checker)) {
|
||||
if (await exception.satisfies(command, this.checker)) {
|
||||
return exception.id
|
||||
}
|
||||
}
|
||||
|
||||
+18
-30
@@ -1,38 +1,26 @@
|
||||
import { IStage, ICommand, IFileExistenceChecker } from './schema'
|
||||
import { Condition } from './condition/Condition'
|
||||
import { StageException } from './schema/exception'
|
||||
import { IStage } from './schema'
|
||||
import { StageException } from './Exception'
|
||||
import { Event } from './Event'
|
||||
|
||||
export class Stage {
|
||||
id: string
|
||||
export class Stage extends Event {
|
||||
name: string
|
||||
public readonly condition: Condition
|
||||
private requirements: string[]
|
||||
public readonly exceptions: StageException[]
|
||||
private exceptions: StageException[]
|
||||
|
||||
constructor({ id, name, condition, requirements, exceptions }: IStage) {
|
||||
this.id = id
|
||||
constructor({
|
||||
id,
|
||||
name,
|
||||
condition,
|
||||
requirements,
|
||||
exceptions,
|
||||
response,
|
||||
}: IStage) {
|
||||
super(id, condition, response, requirements)
|
||||
this.name = name || ''
|
||||
this.condition = new Condition(condition)
|
||||
this.requirements = requirements || []
|
||||
this.exceptions = exceptions || []
|
||||
this.exceptions =
|
||||
exceptions?.map((exception) => new StageException(exception)) || []
|
||||
}
|
||||
|
||||
async satisfies(
|
||||
command: ICommand,
|
||||
checker: IFileExistenceChecker
|
||||
): Promise<boolean> {
|
||||
return this.condition.satisfies(command, checker)
|
||||
}
|
||||
|
||||
private checkRequirements(completed: string[]): boolean {
|
||||
return this.requirements.every((req) => completed.includes(req))
|
||||
}
|
||||
|
||||
private finished(completed: string[]): boolean {
|
||||
return completed.includes(this.id)
|
||||
}
|
||||
|
||||
active(completed: string[]): boolean {
|
||||
return !this.finished(completed) && this.checkRequirements(completed)
|
||||
getExceptions(): StageException[] {
|
||||
return this.exceptions
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,16 @@ export const exceptionSchema = z.object({
|
||||
response: responseSchema,
|
||||
})
|
||||
|
||||
export type Exception = z.infer<typeof exceptionSchema>
|
||||
export type IException = z.infer<typeof exceptionSchema>
|
||||
|
||||
export const stageExceptionSchema = exceptionSchema.extend({
|
||||
catchAll: z.boolean().default(false),
|
||||
})
|
||||
|
||||
export type StageException = z.infer<typeof stageExceptionSchema>
|
||||
export type IStageException = z.infer<typeof stageExceptionSchema>
|
||||
|
||||
export const globalExceptionSchema = exceptionSchema.extend({
|
||||
requirements: requirementsSchema.default([]),
|
||||
})
|
||||
|
||||
export type GlobalException = z.infer<typeof globalExceptionSchema>
|
||||
export type IGlobalException = z.infer<typeof globalExceptionSchema>
|
||||
@@ -3,6 +3,7 @@ export { stageSchema, IStage } from './stage.js'
|
||||
export { requirementsSchema, IRequirements } from './requirements.js'
|
||||
export { responseSchema, IResponse } from './response.js'
|
||||
export { questSchema, IQuest } from './quest.js'
|
||||
export { exceptionSchema, IException } from './exception.js'
|
||||
|
||||
export interface ICommand {
|
||||
command?: string
|
||||
|
||||
Reference in new issue
Block a user