Learn Practice Daily golf Reference
Vertical movement·Lesson 6 of 6·9 min·0/4 exercisesPro

Delete the dead code

The whole of track four against the clock: tour legacy.js with every vertical motion, then cut its last three dead functions with d}.

Scene

Friday, 4:00 p.m. Three dead functions are still in legacy.js: the old receipt printer, the 2019 "burrito of the month", and a CSV export nobody ever used. The team wants them gone before the weekend, and they'd like a quick tour of what's left on the way.

One hour, 290 lines, and every way you know to cross a long file.

From memory

Warm-up from earlier chapters

Two from earlier chapters, from memory, before the new idea. Two wrong tries show the answer.

The sixth line from the top of the screen.
press the keys…2 keys
1 of 2
The sixth line from the top of the screen.

The whole book, on one card

The ruler for lines you can see (13j), page numbers for lines you're told (214G, gg, G), paragraph breaks for the next function (} {), half pages for reading (Ctrl-d Ctrl-u), and the open page's top, middle and bottom (H M L). Pick by what you know about where you're going.

gg
// legacy.js — Byte Burrito, 2019–present. Please don't add anything here.
// (Everyone has added something here.)
const TAX_RATE = 0.0875;
const MAX_DISTANCE_KM = 8;
const OPEN_HOUR = 11;
const CLOSE_HOUR = 23;
const RUSH_START = 12;
const RUSH_END = 14;
function isOpen(now) {
const hour = now.getHours();
return hour >= OPEN_HOUR && hour < CLOSE_HOUR;
}
G
// legacy.js — Byte Burrito, 2019–present. Please don't add anything here.
// (Everyone has added something here.)
const TAX_RATE = 0.0875;
const MAX_DISTANCE_KM = 8;
const OPEN_HOUR = 11;
const CLOSE_HOUR = 23;
const RUSH_START = 12;
const RUSH_END = 14;
function isOpen(now) {
const hour = now.getHours();
return hour >= OPEN_HOUR && hour < CLOSE_HOUR;
}
}
// legacy.js — Byte Burrito, 2019–present. Please don't add anything here.
// (Everyone has added something here.)
const TAX_RATE = 0.0875;
const MAX_DISTANCE_KM = 8;
const OPEN_HOUR = 11;
const CLOSE_HOUR = 23;
const RUSH_START = 12;
const RUSH_END = 14;
function isOpen(now) {
const hour = now.getHours();
return hour >= OPEN_HOUR && hour < CLOSE_HOUR;
}
{
// legacy.js — Byte Burrito, 2019–present. Please don't add anything here.
// (Everyone has added something here.)
const TAX_RATE = 0.0875;
const MAX_DISTANCE_KM = 8;
const OPEN_HOUR = 11;
const CLOSE_HOUR = 23;
const RUSH_START = 12;
const RUSH_END = 14;
function isOpen(now) {
const hour = now.getHours();
return hour >= OPEN_HOUR && hour < CLOSE_HOUR;
}
H
// legacy.js — Byte Burrito, 2019–present. Please don't add anything here.
// (Everyone has added something here.)
const TAX_RATE = 0.0875;
const MAX_DISTANCE_KM = 8;
const OPEN_HOUR = 11;
const CLOSE_HOUR = 23;
const RUSH_START = 12;
const RUSH_END = 14;
function isOpen(now) {
const hour = now.getHours();
return hour >= OPEN_HOUR && hour < CLOSE_HOUR;
}
L
// legacy.js — Byte Burrito, 2019–present. Please don't add anything here.
// (Everyone has added something here.)
const TAX_RATE = 0.0875;
const MAX_DISTANCE_KM = 8;
const OPEN_HOUR = 11;
const CLOSE_HOUR = 23;
const RUSH_START = 12;
const RUSH_END = 14;
function isOpen(now) {
const hour = now.getHours();
return hour >= OPEN_HOUR && hour < CLOSE_HOUR;
}
4j
// legacy.js — Byte Burrito, 2019–present. Please don't add anything here.
// (Everyone has added something here.)
const TAX_RATE = 0.0875;
const MAX_DISTANCE_KM = 8;
const OPEN_HOUR = 11;
const CLOSE_HOUR = 23;
const RUSH_START = 12;
const RUSH_END = 14;
function isOpen(now) {
const hour = now.getHours();
return hour >= OPEN_HOUR && hour < CLOSE_HOUR;
}
One press each from the same cursor, on a page short enough to see whole.
Boss round

Stage 1 · The tour

4:05. Before anything is deleted, the team wants a look at six functions that stay, so nobody cuts the wrong one. They ask in their own order, all over the file; the goal bar gives each line number and why it stays. Any vertical motion.

1 of 6Line 242 · riderReport stays: the dispatch screen
1// legacy.js — Byte Burrito, 2019–present. Please don't add anything here.
1// (Everyone has added something here.)
2
3const TAX_RATE = 0.0875;
4const MAX_DISTANCE_KM = 8;
5const OPEN_HOUR = 11;
6const CLOSE_HOUR = 23;
7const RUSH_START = 12;
8const RUSH_END = 14;
9
10function isOpen(now) {
11 const hour = now.getHours();
12 return hour >= OPEN_HOUR && hour < CLOSE_HOUR;
13}
14
15function isLunchRush(now) {
16 const hour = now.getHours();
17 return hour >= RUSH_START && hour < RUSH_END;
18}
19
20function formatPrice(cents) {
21 const dollars = Math.floor(cents / 100);
22 const rest = String(cents % 100).padStart(2, "0");
23 return "$" + dollars + "." + rest;
24}
25
26function subtotal(items) {
27 let sum = 0;
28 for (const item of items) {
29 sum += item.price * item.qty;
30 }
31 return sum;
32}
33
34function taxFor(amount) {
35 return Math.round(amount * TAX_RATE);
36}
37
38function totalFor(order) {
39 const base = subtotal(order.items);
40 const tax = taxFor(base);
41 const tip = order.tip || 0;
42 return base + tax + tip;
43}
44
45function validateOrder(order) {
46 if (!order.items || order.items.length === 0) return "empty";
47 if (order.items.some((i) => i.qty <= 0)) return "bad quantity";
48 if (!order.address) return "no address";
49 if (!isOpen(new Date())) return "closed";
50 return null;
51}
52
53function applyCoupon(order, code) {
54 const coupon = COUPONS[code];
55 if (!coupon) return order;
56 if (coupon.expires < Date.now()) return order;
57 const off = Math.round(subtotal(order.items) * coupon.percent);
58 return { ...order, discount: off };
59}
60
61function studentDiscount(order, user) {
62 if (!user.isStudent) return 0;
63 return Math.round(subtotal(order.items) * 0.1);
64}
65
66function distanceKm(a, b) {
67 const dLat = (b.lat - a.lat) * 111;
68 const dLng = (b.lng - a.lng) * 111 * Math.cos((a.lat * Math.PI) / 180);
69 return Math.sqrt(dLat * dLat + dLng * dLng);
70}
71
72function nearestRider(riders, address) {
73 let best = null;
74 for (const rider of riders) {
75 if (!rider.online) continue;
76 const d = distanceKm(rider.position, address.position);
77 if (d > MAX_DISTANCE_KM) continue;
78 if (!best || d < best.distance) best = { rider, distance: d };
79 }
80 return best;
81}
82
83function assignRider(order, riders) {
84 const match = nearestRider(riders, order.address);
85 if (!match) return refund(order, "No rider nearby, sorry!");
86 order.riderId = match.rider.id;
87 order.eta = Math.ceil(match.distance * 4) + 10;
88 notify(match.rider.phone, "New order: " + order.id);
89 return order;
90}
91
92function etaMinutes(order, now) {
93 const rush = isLunchRush(now) ? 10 : 0;
94 return order.eta + rush;
95}
96
97function refund(order, reason) {
98 order.status = "refunded";
99 order.refundReason = reason;
100 payments.refund(order.paymentId, totalFor(order));
101 notify(order.customerPhone, "Refunded: " + reason);
102 return order;
103}
104
105function markDelivered(order, now) {
106 order.status = "delivered";
107 order.deliveredAt = now.toISOString();
108 const late = now - new Date(order.placedAt) > order.eta * 60000;
109 if (late) order.lateBy = Math.round((now - new Date(order.placedAt)) / 60000 - order.eta);
110 return order;
111}
112
113function kitchenTicket(order) {
114 const lines = order.items.map((i) => i.qty + " x " + i.name);
115 lines.unshift("ORDER " + order.id);
116 if (order.notes) lines.push("NOTE: " + order.notes);
117 return lines.join("\n");
118}
119
120function printTicket(order) {
121 const ticket = kitchenTicket(order);
122 printer.print(ticket);
123 log("printed", order.id);
124}
125
126// DEAD CODE: the old receipt printer, replaced by email receipts
127function printReceipt(order) {
128 const lines = order.items.map((i) => i.name + " " + formatPrice(i.price * i.qty));
129 lines.push("TOTAL " + formatPrice(totalFor(order)));
130 receiptPrinter.print(lines.join("\n"));
131}
132
133function emailReceipt(order, user) {
134 const body = renderReceipt(order);
135 mailer.send(user.email, "Your Byte Burrito receipt", body);
136}
137
138function menuItem(id) {
139 const item = MENU.find((m) => m.id === id);
140 if (!item) throw new Error("not on the menu: " + id);
141 return item;
142}
143
144function isSpicy(id) {
145 return menuItem(id).spicy === true;
146}
147
148function happyHourPrice(item, now) {
149 const hour = now.getHours();
150 if (hour >= 17 && hour < 19) return Math.round(item.price * 0.8);
151 return item.price;
152}
153
154function priceList(now) {
155 return MENU.map((item) => ({
156 id: item.id,
157 name: item.name,
158 price: formatPrice(happyHourPrice(item, now)),
159 }));
160}
161
162// DEAD CODE: the 2019 "burrito of the month", never shipped
163function burritoOfTheMonth(month) {
164 const picks = ["al-pastor", "veggie", "carnitas", "birria"];
165 return menuItem(picks[month % picks.length]);
166}
167
168function placeOrder(cart, user, now) {
169 const order = { id: newId(), items: cart.items, address: user.address, placedAt: now.toISOString() };
170 const problem = validateOrder(order);
171 if (problem) throw new Error(problem);
172 const fee = deliveryFee(order, distanceKm(KITCHEN, order.address));
173 order.discount = studentDiscount(order, user);
174 order.total = totalFor(order) - order.discount + fee;
175 return order;
176}
177
178function deliveryFee(order, km) {
179 const base = km <= 2 ? 0 : 1.5;
180 const perKm = km > 2 ? (km - 2) * 0.4 : 0;
181 const rush = isLunchRush(new Date()) ? 1 : 0;
182 return Math.round((base + perKm + rush) * 100) / 100;
183}
184
185function newId() {
186 return "BB-" + Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 6);
187}
188
189function log(event, ...details) {
190 console.log("[" + new Date().toISOString() + "] " + event, ...details);
191}
192
193function notify(phone, text) {
194 if (!phone) return;
195 sms.send(phone, text.slice(0, 160));
196}
197
198function saveUser(user) {
199 db.users.put(user.id, user);
200}
201
202function loadUser(id) {
203 return db.users.get(id);
204}
205
206function saveOrder(order) {
207 db.orders.put(order.id, order);
208 log("saved", order.id);
209}
210
211function loadOrder(id) {
212 return db.orders.get(id);
213}
214
215function ordersToday(now) {
216 const day = now.toISOString().slice(0, 10);
217 return db.orders.all().filter((o) => o.placedAt.startsWith(day));
218}
219
220function revenueToday(now) {
221 return ordersToday(now).reduce((sum, o) => sum + o.total, 0);
222}
223
224function busiestHour(now) {
225 const counts = new Array(24).fill(0);
226 for (const o of ordersToday(now)) counts[new Date(o.placedAt).getHours()]++;
227 return counts.indexOf(Math.max(...counts));
228}
229
230// DEAD CODE: the CSV export the accountant asked for, then never used
231function exportCsv(orders) {
232 const rows = orders.map((o) => [o.id, o.total, o.status].join(","));
233 rows.unshift("id,total,status");
234 return rows.join("\n");
235}
236
237function ridersOnline(riders) {
238 return riders.filter((r) => r.online).length;
239}
240
241function riderReport(riders, now) {
242 const online = ridersOnline(riders);
243 const rush = isLunchRush(now);
244 return { online, rush, short: rush && online < 6 };
245}
246
247function weatherDelay(weather) {
248 if (weather === "rain") return 8;
249 if (weather === "snow") return 20;
250 return 0;
251}
252
253function adjustEta(order, weather) {
254 order.eta = order.eta + weatherDelay(weather);
255 return order;
256}
257
258function cancelOrder(order, reason) {
259 if (order.status === "delivered") return order;
260 order.status = "cancelled";
261 return refund(order, reason);
262}
263
264function reorder(previous, user, now) {
265 const cart = { items: previous.items.map((i) => ({ ...i })) };
266 return placeOrder(cart, user, now);
267}
268
269function favourite(user) {
270 const counts = {};
271 for (const o of db.orders.byUser(user.id)) {
272 for (const i of o.items) counts[i.id] = (counts[i.id] || 0) + i.qty;
273 }
274 return Object.keys(counts).sort((a, b) => counts[b] - counts[a])[0];
275}
276
277module.exports = {
278 isOpen,
279 placeOrder,
280 assignRider,
281 markDelivered,
282 printTicket,
283 emailReceipt,
284 priceList,
285 revenueToday,
286 riderReport,
287 cancelOrder,
288 reorder,
289};
NORMALLoading the editor…1/60.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

Boss round

Stage 2 · Cut the dead

4:40. The three dead functions, top to bottom: the old receipt printer, the burrito of the month and the CSV export. Cut each one, comment and all, and leave one blank line between the functions around it. Any route you like.

Stuck? Show a hint
Pro
The rest of this lesson is in Pro

The first exercise of every lesson is free. Pro unlocks the rest, every track, for good.

See Pro

This exercise needs a keyboard. Read on, and play it at your computer.

The maintenance listFinish the exercise above to see it.
From memory

The whole track, from memory

Seven situations from this week.

The gutter says 12 next to the line below you. Get there.
scroll here, then press the keys3 keys
1 of 7
The gutter says 12 next to the line below you. Get there.

Extra practice optional

The chapter is done. These rounds keep going as long as you like: stop whenever it stops being useful.

Endless

The long book

Endless stops anywhere in legacy.js, with every vertical motion allowed.

Pro
The rest of this lesson is in Pro

The first exercise of every lesson is free. Pro unlocks the rest, every track, for good.

See Pro

This exercise needs a keyboard. Read on, and play it at your computer.