Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 1x 1x 1x 1x 1x 1x 1x 22x 1x 1x 22x 22x 1x 27x 27x 1x 9x 9x 9x 9x 9x 9x 1x 1x 1x 1x 14x 14x 1x 3x 3x 1x 5x 5x 1x 9x 9x 1x | /**
 * Represents a voice-activated command that can trigger game actions.
 * 
 * @interface GameCommand
 * @example
 * ```typescript
 * const jumpCommand: GameCommand = {
 *   name: "jump",
 *   action: () => player.jump(),
 *   description: "Makes the player character jump",
 *   active: true
 * };
 * ```
 */
export interface GameCommand {
    /**
     * The name/trigger phrase for the command.
     * This is the word or phrase that will be recognized to trigger the action.
     * 
     * @type {string}
     * @example "jump", "move left", "fire weapon"
     */
    name: string;
 
    /**
     * The callback function to execute when this command is triggered.
     * This function contains the game logic that should run when the voice command is recognized.
     * 
     * @type {() => void}
     * @example () => player.jump()
     */
    action: () => void;
 
    /**
     * A human-readable description of what this command does.
     * Used for documentation, help menus, or accessibility features.
     * 
     * @type {string}
     * @example "Makes the player character jump into the air"
     */
    description: string;
 
    /**
     * Whether this command is currently enabled and can be triggered.
     * Inactive commands will not respond to voice input.
     * 
     * @type {boolean}
     * @default true
     */
    active: boolean;
}
 
/**
 * CommandLibrary contains a HashMap that:
 * Can be called by CommandMapper.
 * Maps a String command to the corresponding GameCommand.
*/
 
export class CommandLibrary {
    private commandMap: Map<string, GameCommand>;
 
    private static instance: CommandLibrary;
 
    constructor() {
        this.commandMap = new Map<string, GameCommand>();
    }
    
    /**
     * @returns The singleton instance of CommandLibrary.
     */
    public static getInstance(): CommandLibrary {
        if (!CommandLibrary.instance) {
            CommandLibrary.instance = new CommandLibrary();
        }
        return CommandLibrary.instance;
    }
 
    private normalize(name: string): string {
        return name.toLowerCase().trim();
    }
 
    /** Add a command (returns false if name already exists) */
    public add(command: GameCommand): boolean {
        const key = this.normalize(command.name);
        if (!key) return false;
        if (this.commandMap.has(key)) return false;
        // store normalized name internally
        this.commandMap.set(key, { ...command, name: key, active: command.active ?? true });
        return true;
    }
 
    /** Remove a command by name */
    public remove(name: string): boolean {
        return this.commandMap.delete(this.normalize(name));
    }
 
    /** Check if a command exists */
    public has(name: string): boolean {
        return this.commandMap.has(this.normalize(name));
    }
 
    /** Get a command by name */
    public get(name: string): GameCommand | undefined {
        return this.commandMap.get(this.normalize(name));
    }
 
    /** List all commands */
    public list(): GameCommand[] {
        return Array.from(this.commandMap.values());
    }
 
    /** Clear all commands */
    public clear(): void {
        this.commandMap.clear();
    }
}
  |