travian/src/Storage/TaskQueue.ts
2020-03-31 12:37:17 +03:00

101 lines
2.5 KiB
TypeScript

import { Command } from '../Common';
import { uniqId } from '../utils';
const QUEUE_NAME = 'task_queue:v3';
export type TaskId = string;
function uniqTaskId(): TaskId {
return uniqId();
}
export class Task {
readonly id: TaskId;
readonly ts: number;
readonly cmd: Command;
constructor(id: TaskId, ts: number, cmd: Command) {
this.id = id;
this.ts = ts;
this.cmd = cmd;
}
withTime(ts: number): Task {
return new Task(this.id, ts, this.cmd);
}
}
export type TaskList = Array<Task>;
export class TaskQueue {
private static normalize(items: TaskList): TaskList {
return items.sort((x, y) => x.ts - y.ts);
}
push(cmd: Command, ts: number): Task {
const id = uniqTaskId();
const task = new Task(id, ts, cmd);
this.log('PUSH TASK', id, ts, cmd);
let items = this.getItems();
items.push(task);
this.flushItems(items);
return task;
}
get(ts: number): Task | undefined {
const readyItems = this.getItems().filter(t => t.ts <= ts);
if (readyItems.length === 0) {
return undefined;
}
return readyItems[0];
}
complete(id: TaskId) {
const [_, items] = this.shiftTask(id);
this.flushItems(items);
}
postpone(id: TaskId, newTs: number) {
const [task, items] = this.shiftTask(id);
if (task) {
this.log('POSTPONE', task);
items.push(task.withTime(newTs));
}
this.flushItems(items);
}
seeItems(): TaskList {
return this.getItems();
}
private shiftTask(id: TaskId): [Task | undefined, TaskList] {
const items = this.getItems();
const task = items.find(t => t.id === id);
const tail = items.filter(t => t.id !== id);
return [task, tail];
}
private getItems(): TaskList {
const serialized = localStorage.getItem(QUEUE_NAME);
const storedItems =
serialized !== null
? (JSON.parse(serialized) as Array<{ [key: string]: any }>)
: [];
const items: TaskList = [];
storedItems.forEach(obj => {
items.push(new Task(obj.id || uniqId(), +obj.ts, obj.cmd));
});
return items;
}
private flushItems(items: TaskList): void {
localStorage.setItem(
QUEUE_NAME,
JSON.stringify(TaskQueue.normalize(items))
);
}
private log(...args) {
console.log('TASK QUEUE:', ...args);
}
}