@sh66n/telemedicine-queue-optimizer
v1.0.5
Published
Intelligent queue optimization system for telemedicine platforms. Reduces wait times, improves fairness, and optimizes doctor utilization using ML-based priority scoring.
Maintainers
Readme
Telemedicine Queue Optimizer
Priority queue scheduling for telemedicine. Moves urgent patients up without starving everyone else.
npm install @sh66n/telemedicine-queue-optimizerUsage
import { QueueOptimizer } from '@sh66n/telemedicine-queue-optimizer';
const optimizer = new QueueOptimizer({
severityWeight: 0.6,
waitTimeWeight: 0.2,
fairnessWeight: 0.2,
maxWaitTimeForHighPriority: 20,
maxWaitTimeForMediumPriority: 40,
maxWaitTimeForLowPriority: 60,
});
const optimized = optimizer.optimize(patients);API
new QueueOptimizer(config)
| Field | Type | Description |
|---|---|---|
| severityWeight | number | Weight for severity score (0–1) |
| waitTimeWeight | number | Weight for wait time score (0–1) |
| fairnessWeight | number | Reserved; used in weight validation (0–1) |
| maxWaitTimeForHighPriority | number | Minutes before fairness boost kicks in |
| maxWaitTimeForMediumPriority | number | Same for medium |
| maxWaitTimeForLowPriority | number | Same for low |
Weights must sum to
1.0.
QueueOptimizer
| Method | Returns | Notes |
|---|---|---|
| optimize(patients) | Patient[] | Reorders by priority score. Does not mutate input. |
| generateQueueOrder(patients, startTime?) | QueueOrder[] | Attaches timing to each patient. Pass output of optimize(), not raw patients. |
| compareQueues(patients, startTime?) | ComparisonResult | Runs FIFO and optimized side by side. Returns { baseline: { queue, metrics }, optimized: { queue, metrics }, improvements }. |
| getScores(patients) | { patientId, score, explanation }[] | Shows why each patient ranked where they did. |
| validate(patients) | { valid, errors[] } | Checks config weights sum to 1.0 and all patient fields are valid. |
| getConfig() | QueueOptimizationConfig | |
| setConfig(partial) | void | Merges into existing config. Takes effect immediately. |
QueueSimulator
Wraps QueueOptimizer with richer output — recommendations, HTML reports, multi-config testing.
| Method | Returns | Notes |
|---|---|---|
| simulate(patients, startTime?) | OptimizationResult | Runs full comparison. Returns both queues, both metrics sets, improvements, and recommendations. |
| simulateWithConfig(patients, config) | OptimizationResult | One-off run with a different config without mutating the instance. |
| runMultipleSimulations(patients, configs[]) | { name, result }[] | Test multiple configs at once. |
| compareCustomQueues(baseline, optimized) | { baselineMetrics, optimizedMetrics, improvements } | Compare two orderings you supply yourself. |
| getDetailedMetrics(queueOrders) | { byPosition[], bySeverity } | Breaks down metrics by queue position and severity group. |
| exportResult(result) | string | Full JSON. |
| exportSummary(result) | string | Compact JSON. |
| generateHTMLReport(result) | string | Standalone HTML report. |
Types
interface Patient {
id: string
arrivalTime: string // ISO 8601
severity: 'low' | 'medium' | 'high'
waitTime?: number // minutes; calculated from arrivalTime if omitted
estimatedDuration?: number // minutes; predicted from severity if omitted
}
interface QueueOrder {
position: number
patient: Patient
estimatedStartTime: Date
estimatedEndTime: Date
estimatedWaitTime: number
}
interface Metrics {
averageWaitTime: number
maxWaitTime: number
minWaitTime: number
fairnessScore: number // 0–100
doctorUtilization: number // 0–100
throughput: number // patients/hour
}How it works
Every patient gets a priority score. The queue is sorted descending by score — highest score is seen first.
Score formula
baseScore = (severityScore × severityWeight) + (waitScore × waitTimeWeight)
score = baseScore × fairnessBoostSeverity score
A fixed value based on clinical urgency:
| Severity | Score | |---|---| | high | 150 | | medium | 75 | | low | 25 |
Wait score
Normalizes wait time to a 0–100 scale:
waitScore = min((waitTime / 60) × 100, 100)A patient who has waited 60+ minutes gets the maximum wait score of 100. Someone who just arrived gets close to 0.
Fairness boost
This is the starvation-prevention mechanism. It's a multiplier that starts at 1 (no effect) and grows once a patient's wait time exceeds their severity threshold:
boost = 1 if waitTime ≤ threshold
boost = 1 + (waitTime - threshold) / 30 if waitTime > thresholdDefault thresholds:
| Severity | Threshold | |---|---| | high | 20 min | | medium | 40 min | | low | 60 min |
Because the boost is a multiplier on the entire score, it compounds — a patient who has blown past their threshold doesn't just get a small additive bump, their whole score scales up. A low-severity patient waiting 3 hours will eventually outrank a medium-severity patient who just arrived.
Example
Two patients, default config (severityWeight: 0.6, waitTimeWeight: 0.2):
| | P001 | P002 | |---|---|---| | Severity | low (25) | high (150) | | Wait time | 120 min | 10 min | | Wait score | 100 | 16.7 | | Threshold | 60 min | 20 min | | Boost | 1 + (60/30) = 3.0 | 1.0 | | Base score | (25×0.6) + (100×0.2) = 35 | (150×0.6) + (16.7×0.2) = 93.3 | | Final score | 35 × 3.0 = 105 | 93.3 × 1.0 = 93.3 |
P001 (low severity, waited 2 hours) ranks above P002 (high severity, just arrived). This is intentional — the fairness boost exists precisely for this scenario.
If this isn't the behavior you want, increase maxWaitTimeForLowPriority to delay when the boost kicks in, or increase severityWeight to make severity harder to overcome.
Duration prediction
If estimatedDuration is not set, it's predicted automatically:
| Severity | Base | Variance | |---|---|---| | high | 25 min | ±5 min | | medium | 20 min | ±5 min | | low | 12 min | ±5 min |
Set estimatedDuration explicitly on every patient for deterministic timing.
License
MIT
