Back to js-datatype-intermediate
12-railway-pnr-system.js
JavaScript
1/**
2 * 🚂 Indian Railway PNR Status System
3 *
4 * IRCTC ka PNR status system bana! PNR data milega with train info,
5 * passengers, aur current statuses. Tujhe ek complete status report
6 * generate karna hai with formatted output aur analytics.
7 *
8 * pnrData object:
9 * {
10 * pnr: "1234567890",
11 * train: { number: "12301", name: "Rajdhani Express", from: "NDLS", to: "HWH" },
12 * classBooked: "3A",
13 * passengers: [
14 * { name: "Rahul Kumar", age: 28, gender: "M", booking: "B1", current: "B1" },
15 * { name: "Priya Sharma", age: 25, gender: "F", booking: "WL5", current: "B3" },
16 * { name: "Amit Singh", age: 60, gender: "M", booking: "WL12", current: "WL8" }
17 * ]
18 * }
19 *
20 * Status rules (based on current field):
21 * - Starts with "B" or "S" (berth/seat) => status = "CONFIRMED"
22 * - Starts with "WL" => status = "WAITING"
23 * - Equals "CAN" => status = "CANCELLED"
24 * - Starts with "RAC" => status = "RAC"
25 *
26 * For each passenger generate:
27 * - formattedName: name.padEnd(20) + "(" + age + "/" + gender + ")"
28 * - bookingStatus: booking field value
29 * - currentStatus: current field value
30 * - statusLabel: one of "CONFIRMED", "WAITING", "CANCELLED", "RAC"
31 * - isConfirmed: boolean (true only if statusLabel === "CONFIRMED")
32 *
33 * Summary (use array methods on processed passengers):
34 * - totalPassengers: count of passengers
35 * - confirmed: count of CONFIRMED
36 * - waiting: count of WAITING
37 * - cancelled: count of CANCELLED
38 * - rac: count of RAC
39 * - allConfirmed: boolean - every passenger confirmed? (use every)
40 * - anyWaiting: boolean - some passenger waiting? (use some)
41 *
42 * Other fields:
43 * - chartPrepared: true if every NON-CANCELLED passenger is confirmed
44 * - pnrFormatted: "123-456-7890" (3-3-4 dash pattern, use slice + join or concatenation)
45 * - trainInfo: template literal =>
46 * "Train: {number} - {name} | {from} → {to} | Class: {classBooked}"
47 *
48 * Hint: Use padEnd(), slice(), join(), map(), filter(), every(), some(),
49 * startsWith(), template literals, typeof, Array.isArray()
50 *
51 * Validation:
52 * - Agar pnrData object nahi hai ya null hai, return null
53 * - Agar pnr string nahi hai ya exactly 10 digits nahi hai, return null
54 * - Agar train object missing hai, return null
55 * - Agar passengers array nahi hai ya empty hai, return null
56 *
57 * @param {object} pnrData - PNR data object
58 * @returns {{ pnrFormatted: string, trainInfo: string, passengers: Array<{ formattedName: string, bookingStatus: string, currentStatus: string, statusLabel: string, isConfirmed: boolean }>, summary: { totalPassengers: number, confirmed: number, waiting: number, cancelled: number, rac: number, allConfirmed: boolean, anyWaiting: boolean }, chartPrepared: boolean } | null}
59 *
60 * @example
61 * processRailwayPNR({
62 * pnr: "1234567890",
63 * train: { number: "12301", name: "Rajdhani Express", from: "NDLS", to: "HWH" },
64 * classBooked: "3A",
65 * passengers: [
66 * { name: "Rahul", age: 28, gender: "M", booking: "B1", current: "B1" }
67 * ]
68 * })
69 * // => { pnrFormatted: "123-456-7890",
70 * // trainInfo: "Train: 12301 - Rajdhani Express | NDLS → HWH | Class: 3A",
71 * // passengers: [...], summary: { ..., allConfirmed: true }, chartPrepared: true }
72 */
73export function processRailwayPNR(pnrData) {
74 if (!pnrData || typeof pnrData !== 'object') return null;
75 if (typeof pnrData.pnr !== 'string') return null;
76 if (pnrData.pnr.length !== 10 || !/^\d{10}$/.test(pnrData.pnr)) return null;
77 if (!pnrData.train || typeof pnrData.train !== 'object') return null;
78 if (!Array.isArray(pnrData.passengers) || pnrData.passengers.length === 0) return null;
79
80 const pnrFormatted = pnrData.pnr.slice(0, 3) + "-"
81 + pnrData.pnr.slice(3, 6) + "-"
82 + pnrData.pnr.slice(6);
83
84 const { number, name, from, to } = pnrData.train;
85 const trainInfo = `Train: ${number} - ${name} | ${from} → ${to} | Class: ${pnrData.classBooked}`;
86
87 const passengers = pnrData.passengers.map(p => {
88 let statusLabel;
89 if (p.current === "CAN") statusLabel = "CANCELLED";
90 else if (p.current.startsWith("WL")) statusLabel = "WAITING";
91 else if (p.current.startsWith("RAC")) statusLabel = "RAC";
92 else statusLabel = "CONFIRMED";
93
94 return {
95 formattedName: p.name.padEnd(20) + `(${p.age}/${p.gender})`,
96 bookingStatus: p.booking,
97 currentStatus: p.current,
98 statusLabel,
99 isConfirmed: statusLabel === "CONFIRMED"
100 };
101 });
102
103 const confirmed = passengers.filter(p => p.statusLabel === "CONFIRMED").length;
104 const waiting = passengers.filter(p => p.statusLabel === "WAITING").length;
105 const cancelled = passengers.filter(p => p.statusLabel === "CANCELLED").length;
106 const rac = passengers.filter(p => p.statusLabel === "RAC").length;
107
108 const summary = {
109 totalPassengers: passengers.length,
110 confirmed, waiting, cancelled, rac,
111 allConfirmed: passengers.every(p => p.isConfirmed),
112 anyWaiting: passengers.some(p => p.statusLabel === "WAITING")
113 };
114
115 const nonCancelled = passengers.filter(p => p.statusLabel !== "CANCELLED");
116 const chartPrepared = nonCancelled.every(p => p.isConfirmed);
117
118 return { pnrFormatted, trainInfo, passengers, summary, chartPrepared };
119}
120