pos-be/src/modules/queue/domain/usecases/formula/queue-condition.formula.ts

85 lines
2.5 KiB
TypeScript

import { QueueModel } from 'src/modules/queue/data/models/queue.model';
import { toTime } from '../../helpers/time.helper';
import * as math from 'mathjs';
import { QueueTimeFormula } from './queue-time.formula';
import * as moment from 'moment';
export class QueueCondition {
private ticketItems = {};
constructor(readonly items: QueueModel[]) {
items.forEach((item) => {
const item_id = item.item_queue_id;
const currentItem = this.ticketItems[item_id];
this.ticketItems[item_id] = currentItem ? [...currentItem, item] : [item];
});
}
condition(item_id: string) {
const queues: QueueModel[] = this.ticketItems[item_id] ?? [];
const playEstimation = queues[0]?.average ?? 0;
const peakLevel = queues[0]?.peak_level ?? 100;
const [time, last] = this.queueTime(queues, playEstimation);
const nearest = time ? toTime(time) : 0;
const lastTime = last ? toTime(last + playEstimation) : 0;
const queuePeople = this.queuePeople(queues, peakLevel);
return {
available: queuePeople == 0,
average: this.averageTime(queues),
nearest: nearest,
crowded_level: queuePeople,
available_time: lastTime,
};
}
queuePeople(queues: QueueModel[], peakLevel): number {
const queue = this.activeQueue(queues);
const level = peakLevel / 100;
const queuePeople = queue.reduce((acc, q) => {
return acc + q.qty;
}, 0);
return queuePeople * level;
}
activeQueue(queues: QueueModel[]) {
return queues.filter((q) => q.status == 'waiting');
}
queueTime(queues: QueueModel[], average = 0): number[] {
const calledQueue = queues.filter((q) =>
['called', 'done'].includes(q.status),
);
const lastCalledQueue = calledQueue[calledQueue.length - 1];
const activeQueues = this.activeQueue(queues);
const queueTimes = QueueTimeFormula.queueTime(
activeQueues,
lastCalledQueue,
average,
);
const queueEstimation = Object.values<number>(queueTimes);
const first = queueEstimation[0] ?? moment().valueOf();
const last = queueEstimation[queueEstimation.length - 1] ?? 0;
return [first, last];
}
averageTime(queues: QueueModel[]) {
if (queues.length == 0) return 0;
const calledQueue = queues.filter((q) =>
['called', 'done'].includes(q.status),
);
if (calledQueue.length < 1) return 0;
const times = calledQueue.map((queue) => {
return (queue.call_time - queue.time) / 1000;
});
const avg = Math.ceil(math.mean(times));
return Math.max(0, avg);
}
}