Back to js-functions
05-dabbawala-tracker.js
JavaScript
1/**
2 * 🚂 Dabbawala Delivery Tracker - Closures
3 *
4 * Mumbai ke famous dabbawala system ka tracker bana! Yahan closure ka
5 * use hoga — ek function ke andar private state rakhna hai jo bahar se
6 * directly access nahi ho sakta. Sirf returned methods se access hoga.
7 *
8 * Function: createDabbawala(name, area)
9 *
10 * Returns an object with these methods (sab ek hi private state share karte hain):
11 *
12 * - addDelivery(from, to)
13 * Adds a new delivery. Returns auto-incremented id (starting from 1).
14 * Each delivery: { id, from, to, status: "pending" }
15 * Agar from ya to empty/missing, return -1
16 *
17 * - completeDelivery(id)
18 * Marks delivery as "completed". Returns true if found and was pending.
19 * Returns false if not found or already completed.
20 *
21 * - getActiveDeliveries()
22 * Returns array of deliveries with status "pending" (copies, not references)
23 *
24 * - getStats()
25 * Returns: { name, area, total, completed, pending, successRate }
26 * successRate = completed/total as percentage string "85.00%" (toFixed(2) + "%")
27 * Agar total is 0, successRate = "0.00%"
28 *
29 * - reset()
30 * Clears all deliveries, resets id counter to 0. Returns true.
31 *
32 * IMPORTANT: Private state (deliveries array, nextId counter) should NOT
33 * be accessible as properties on the returned object.
34 * Two instances created with createDabbawala should be completely independent.
35 *
36 * Hint: Use closure to keep variables private. The returned object's methods
37 * form a closure over those variables.
38 *
39 * @param {string} name - Dabbawala's name
40 * @param {string} area - Delivery area
41 * @returns {object} Object with delivery management methods
42 *
43 * @example
44 * const ram = createDabbawala("Ram", "Dadar");
45 * ram.addDelivery("Andheri", "Churchgate"); // => 1
46 * ram.addDelivery("Bandra", "CST"); // => 2
47 * ram.completeDelivery(1); // => true
48 * ram.getStats();
49 * // => { name: "Ram", area: "Dadar", total: 2, completed: 1, pending: 1, successRate: "50.00%" }
50 */
51export function createDabbawala(name, area) {
52 let deliveries = []
53 let id = 1
54
55 return {
56 addDelivery(from, to) {
57 if ( !from || !to) {
58 return -1
59 }
60 const currId = id
61 deliveries.push({ id: currId, from, to, status: "pending" })
62 id++
63 return currId
64 },
65
66 completeDelivery(id) {
67 if (typeof id !== "number") {
68 return -1
69 }
70 for (let deliver of deliveries) {
71 if (deliver.id === id) {
72 if (deliver.status === "pending") {
73 deliver.status = "completed"
74 return true
75 }
76 return false
77 }
78 }
79 return false
80 },
81 getActiveDeliveries() {
82 return deliveries.filter(del => del.status === "pending").map(d => ({ ...d }))
83 },
84
85 getStats() {
86 const total = deliveries.length
87
88 const completed = deliveries.filter(
89 (del) => del.status === "completed",
90 ).length
91
92 const pending = total - completed
93
94 let successRate;
95 if (total === 0) {
96 successRate = "0.00%"
97 } else {
98 successRate = ((completed / total) * 100).toFixed(2) + "%"
99 }
100
101 return { name, area, total, completed, pending, successRate }
102 },
103 reset() {
104 deliveries = []
105 id = 1
106 return true
107 },
108 }
109}