Mirroar/hivemind

View on GitHub
src/dispatcher/dispatcher.ts

Summary

Maintainability
A
1 hr
Test Coverage
import TaskProvider from 'dispatcher/task-provider';
import utilities from 'utilities';

export default class Dispatcher<TaskType extends Task, ContextType> {
    protected providers: Record<string, TaskProvider<TaskType, ContextType>> = {};

    getTask(context: ContextType): TaskType {
        const options: TaskType[] = [];
        let highestPriority = -10;

        for (const provider of this.getProvidersByPriority(context)) {
            if (provider.getHighestPriority(context) < highestPriority) break;

            for (const option of provider.getTasks(context)) {
                if (option.priority < highestPriority) continue;
                if (!provider.isValid(option, context)) continue;

                options.push(option);
                if (highestPriority < option.priority) highestPriority = option.priority;
            }
        }

        return utilities.getBestOption(options);
    }

    addProvider(provider: TaskProvider<TaskType, ContextType>) {
        this.providers[provider.getType()] = provider;
    }

    hasProvider(type: string): boolean {
        return Boolean(this.providers[type]);
    }

    getProvidersByPriority(context: ContextType): Array<TaskProvider<TaskType, ContextType>> {
        return _.sortBy(this.providers, provider => -provider.getHighestPriority(context));
    }

    validateTask(task: TaskType, context: ContextType) {
        if (!this.hasProvider(task.type)) throw new Error('Invalid task type: ' + task.type);

        return this.providers[task.type].isValid(task, context);
    }

    executeTask(task: TaskType, context: ContextType) {
        if (!this.hasProvider(task.type)) throw new Error('Invalid task type: ' + task.type);

        this.providers[task.type].execute(task, context);
    }
}