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(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); } }