In Jurassic Park, we need a comprehensive system to monitor all dinosaurs. In this project, you'll build a fully functional monitoring system using everything you've learned: arrays, array methods (filter, map, reduce, find), functions with default and rest parameters, object methods, and method chaining.
You need to build a
DinosaurMonitor system that:You'll build a monitoring system that:
The first step is creating the park's database. Each dinosaur is an object with properties, and the entire population is stored in an array.
1// Park dinosaur database
2const dinosaurs = [
3 {
4 id: 1,
5 name: "Rex",
6 species: "Tyrannosaurus Rex",
7 weight: 8500,
8 diet: "carnivore",
9 enclosure: "A-1",
10 isHealthy: true,
11 heartRate: 72,
12 lastFed: "2024-03-15 08:00"
13 },
14 {
15 id: 2,
16 name: "Tricia",
17 species: "Triceratops",
18 weight: 6200,
19 diet: "herbivore",
20 enclosure: "B-3",
21 isHealthy: true,
22 heartRate: 55,
23 lastFed: "2024-03-15 07:30"
24 },
25 {
26 id: 3,
27 name: "Blue",
28 species: "Velociraptor",
29 weight: 75,
30 diet: "carnivore",
31 enclosure: "C-2",
32 isHealthy: false,
33 heartRate: 110,
34 lastFed: "2024-03-14 18:00"
35 },
36 {
37 id: 4,
38 name: "Dippy",
39 species: "Diplodocus",
40 weight: 12000,
41 diet: "herbivore",
42 enclosure: "D-1",
43 isHealthy: true,
44 heartRate: 40,
45 lastFed: "2024-03-15 06:00"
46 },
47 {
48 id: 5,
49 name: "Spike",
50 species: "Stegosaurus",
51 weight: 3500,
52 diet: "herbivore",
53 enclosure: "B-2",
54 isHealthy: true,
55 heartRate: 48,
56 lastFed: "2024-03-15 07:00"
57 }
58];
59
60// Adding a new dinosaur to the database
61const addDinosaur = (name, species, weight, diet, enclosure) => {
62 const newId = dinosaurs.length + 1;
63 const newDino = {
64 id: newId,
65 name,
66 species,
67 weight,
68 diet,
69 enclosure,
70 isHealthy: true,
71 heartRate: 60,
72 lastFed: new Date().toISOString()
73 };
74 dinosaurs.push(newDino);
75 console.log("Registered:", newDino.name, "(" + newDino.species + ")");
76 return newDino;
77};
78
79addDinosaur("Echo", "Velociraptor", 68, "carnivore", "C-2");
80console.log("Total dinosaur count:", dinosaurs.length);The system needs to enable quick filtering of the population by various criteria. Here you'll use
filter, map, reduce, and find.1// Filtering carnivores with filter
2const carnivores = dinosaurs.filter(dino => dino.diet === "carnivore");
3console.log("Carnivores:", carnivores.map(d => d.name));
4
5// Filtering unhealthy dinosaurs
6const unhealthyDinos = dinosaurs.filter(dino => !dino.isHealthy);
7console.log("Need treatment:", unhealthyDinos.map(d => d.name));
8
9// Mapping - creating a weight report
10const weightReport = dinosaurs.map(dino => {
11 return {
12 name: dino.name,
13 weight: dino.weight,
14 category: dino.weight > 5000 ? "heavy" : "light"
15 };
16});
17console.log("Weight report:");
18weightReport.forEach(entry => {
19 console.log(" " + entry.name + ": " + entry.weight + " kg (" + entry.category + ")");
20});
21
22// Reduce - calculating total population weight
23const totalWeight = dinosaurs.reduce((sum, dino) => sum + dino.weight, 0);
24console.log("Total population weight:", totalWeight, "kg");
25
26// Average weight
27const avgWeight = totalWeight / dinosaurs.length;
28console.log("Average weight:", Math.round(avgWeight), "kg");
29
30// Finding the heaviest dinosaur
31const heaviest = dinosaurs.reduce((max, dino) =>
32 dino.weight > max.weight ? dino : max
33);
34console.log("Heaviest:", heaviest.name, "-", heaviest.weight, "kg");
35
36// find - searching for a specific dinosaur
37const blue = dinosaurs.find(dino => dino.name === "Blue");
38console.log("Found:", blue ? blue.name + " in " + blue.enclosure : "not found");
39
40// some and every - checking conditions
41const allHealthy = dinosaurs.every(dino => dino.isHealthy);
42const anyUnhealthy = dinosaurs.some(dino => !dino.isHealthy);
43console.log("All healthy:", allHealthy);
44console.log("Any unhealthy:", anyUnhealthy);The system needs a set of monitoring functions with different parameter types. Pay attention to variable scope and the difference between regular and arrow functions in the context of
this.1// Function with default parameters
2function generateAlert(dinoName, alertType = "INFO", priority = "normal") {
3 const timestamp = new Date().toLocaleTimeString();
4 console.log("[" + timestamp + "] [" + alertType + "] [" + priority + "] " + dinoName);
5}
6
7generateAlert("Rex", "WARNING", "high");
8generateAlert("Tricia"); // uses default values
9generateAlert("Blue", "DANGER"); // priority will be "normal"
10
11// Function with rest parameter - logging multiple events
12const logEvents = (enclosure, ...events) => {
13 console.log("Enclosure " + enclosure + " - " + events.length + " events registered:");
14 events.forEach((event, index) => {
15 console.log(" " + (index + 1) + ". " + event);
16 });
17};
18
19logEvents("A-1", "Feeding at 8:00", "Veterinary check", "Movement activity");
20logEvents("C-2", "Escape attempt!");
21
22// Monitor object with methods - this in context
23const enclosureMonitor = {
24 sector: "A",
25 alertCount: 0,
26
27 // Traditional method - this points to the object
28 checkFence: function() {
29 this.alertCount++;
30 console.log("Checking fence in sector " + this.sector +
31 " (alert #" + this.alertCount + ")");
32 },
33
34 // ES6 shorthand method
35 getStatus() {
36 return "Sector " + this.sector + " - " + this.alertCount + " alerts";
37 }
38};
39
40enclosureMonitor.checkFence();
41enclosureMonitor.checkFence();
42console.log(enclosureMonitor.getStatus());
43
44// Variable scope - block vs function
45function monitorHeartRates() {
46 const threshold = 100; // available throughout the function
47
48 for (let i = 0; i < dinosaurs.length; i++) {
49 const dino = dinosaurs[i]; // available only in this block
50 if (dino.heartRate > threshold) {
51 let status = "ELEVATED"; // available only in this if block
52 console.log(dino.name + ": heart rate " + dino.heartRate + " - " + status);
53 }
54 }
55
56 // console.log(status); // ERROR! status doesn't exist outside the if block
57 // console.log(dino); // ERROR! dino doesn't exist outside the for loop
58 console.log("Alert threshold:", threshold); // OK - threshold is in function scope
59}
60
61monitorHeartRates();In a real monitoring system, we often need to chain multiple operations together. Array methods are perfect for this.
1// Method chaining - security report
2const securityReport = dinosaurs
3 .filter(dino => dino.diet === "carnivore") // only carnivores
4 .map(dino => ({ // data transformation
5 name: dino.name,
6 enclosure: dino.enclosure,
7 danger: dino.weight > 1000 ? "HIGH" : "MEDIUM"
8 }))
9 .sort((a, b) => a.name.localeCompare(b.name)); // sorting
10
11console.log("=== SECURITY REPORT ===");
12securityReport.forEach(entry => {
13 console.log(entry.name + " [" + entry.enclosure + "] - threat: " + entry.danger);
14});
15
16// Grouping dinosaurs by diet using reduce
17const groupedByDiet = dinosaurs.reduce((groups, dino) => {
18 const key = dino.diet;
19 if (!groups[key]) {
20 groups[key] = [];
21 }
22 groups[key].push(dino.name);
23 return groups;
24}, {});
25
26console.log("=== DIET GROUPS ===");
27console.log("Herbivores:", groupedByDiet.herbivore);
28console.log("Carnivores:", groupedByDiet.carnivore);
29
30// Higher-order function - creating filters
31function createFilter(property, value) {
32 return (dino) => dino[property] === value;
33}
34
35const isCarnivore = createFilter("diet", "carnivore");
36const isInSectorB = createFilter("enclosure", "B-3");
37
38const carnivoreDinos = dinosaurs.filter(isCarnivore);
39const sectorBDinos = dinosaurs.filter(isInSectorB);
40
41console.log("Carnivores:", carnivoreDinos.map(d => d.name));
42console.log("Sector B-3:", sectorBDinos.map(d => d.name));
43
44// Population statistics
45const stats = {
46 total: dinosaurs.length,
47 healthy: dinosaurs.filter(d => d.isHealthy).length,
48 unhealthy: dinosaurs.filter(d => !d.isHealthy).length,
49 avgHeartRate: Math.round(
50 dinosaurs.reduce((sum, d) => sum + d.heartRate, 0) / dinosaurs.length
51 ),
52 heaviest: dinosaurs.reduce((max, d) => d.weight > max.weight ? d : max).name,
53 lightest: dinosaurs.reduce((min, d) => d.weight < min.weight ? d : min).name
54};
55
56console.log("=== POPULATION STATISTICS ===");
57console.log("Total:", stats.total);
58console.log("Healthy:", stats.healthy);
59console.log("Unhealthy:", stats.unhealthy);
60console.log("Average heart rate:", stats.avgHeartRate, "bpm");
61console.log("Heaviest:", stats.heaviest);
62console.log("Lightest:", stats.lightest);Now let's combine everything into a comprehensive class-based monitoring system.
1const parkData = [
2 { name: 'Rex', species: 'T-Rex', zone: 'A', health: 95, weight: 8000, dangerous: true, hunger: 30 },
3 { name: 'Blue', species: 'Velociraptor', zone: 'B', health: 40, weight: 15, dangerous: true, hunger: 80 },
4 { name: 'Stego', species: 'Stegosaurus', zone: 'C', health: 80, weight: 3500, dangerous: false, hunger: 20 },
5 { name: 'Brachi', species: 'Brachiosaurus', zone: 'C', health: 90, weight: 25000, dangerous: false, hunger: 50 },
6 { name: 'Delta', species: 'Velociraptor', zone: 'B', health: 85, weight: 14, dangerous: true, hunger: 60 },
7 { name: 'Echo', species: 'Velociraptor', zone: 'B', health: 30, weight: 13, dangerous: true, hunger: 90 }
8];
9
10class DinosaurMonitor {
11 constructor(dinosaurs) {
12 // Deep copy so we don't modify the original
13 this.dinosaurs = dinosaurs.map(d => ({ ...d }));
14 this.incidents = [];
15 }
16
17 // Find dinosaurs needing attention (health < threshold)
18 findCritical(threshold = 50) {
19 return this.dinosaurs.filter(d => d.health < threshold);
20 }
21
22 // Get dinosaurs in a specific zone
23 getByZone(zone) {
24 return this.dinosaurs.filter(d => d.zone === zone);
25 }
26
27 // Feed one or more dinosaurs (rest parameters)
28 feed(amount = 30, ...dinoNames) {
29 const targets = dinoNames.length > 0
30 ? this.dinosaurs.filter(d => dinoNames.includes(d.name))
31 : this.dinosaurs; // feed all if no names given
32
33 targets.forEach(d => {
34 d.hunger = Math.max(0, d.hunger - amount);
35 });
36
37 console.log(`Fed ${targets.length} dinosaurs (${amount}% hunger reduction)`);
38 return this;
39 }
40
41 // Calculate park statistics
42 getStats() {
43 const total = this.dinosaurs.length;
44 const avgHealth = this.dinosaurs.reduce((sum, d) => sum + d.health, 0) / total;
45 const critical = this.dinosaurs.filter(d => d.health < 50).length;
46 const totalWeight = this.dinosaurs.reduce((sum, d) => sum + d.weight, 0);
47
48 return {
49 total,
50 avgHealth: avgHealth.toFixed(1),
51 critical,
52 totalWeight,
53 dangerous: this.dinosaurs.filter(d => d.dangerous).length
54 };
55 }
56
57 // Generate zone report using method chaining internally
58 generateZoneReport() {
59 const zones = [...new Set(this.dinosaurs.map(d => d.zone))].sort();
60
61 return zones.map(zone => {
62 const zoneDinos = this.dinosaurs.filter(d => d.zone === zone);
63 return {
64 zone,
65 count: zoneDinos.length,
66 avgHealth: (zoneDinos.reduce((s, d) => s + d.health, 0) / zoneDinos.length).toFixed(1),
67 hungry: zoneDinos.filter(d => d.hunger > 70).map(d => d.name)
68 };
69 });
70 }
71
72 // Log an incident
73 logIncident(type, description, ...affectedDinos) {
74 const incident = {
75 id: this.incidents.length + 1,
76 type,
77 description,
78 affectedDinos,
79 timestamp: new Date().toISOString()
80 };
81 this.incidents.push(incident);
82 console.log(`Incident #${incident.id} logged: ${type}`);
83 return this;
84 }
85
86 // Generate summary report
87 report() {
88 const stats = this.getStats();
89 const critical = this.findCritical();
90
91 console.log('=== JURASSIC PARK STATUS REPORT ===');
92 console.log(`Total dinosaurs: ${stats.total}`);
93 console.log(`Average health: ${stats.avgHealth}%`);
94 console.log(`Critical (health < 50): ${stats.critical}`);
95
96 if (critical.length > 0) {
97 console.log('Critical dinosaurs:');
98 critical.forEach(d => console.log(` - ${d.name} (${d.species}): ${d.health}%`));
99 }
100
101 console.log(`Total incidents logged: ${this.incidents.length}`);
102 return this;
103 }
104}
105
106// Usage
107const monitor = new DinosaurMonitor(parkData);
108
109// Chain operations
110monitor
111 .feed(40, 'Blue', 'Echo') // Feed the most hungry
112 .logIncident('HEALTH', 'Multiple dinosaurs critical', 'Blue', 'Echo')
113 .report();
114
115// Zone analysis
116const zoneReports = monitor.generateZoneReport();
117zoneReports.forEach(r => {
118 console.log(`Zone ${r.zone}: ${r.count} dinos, avg health ${r.avgHealth}%`);
119 if (r.hungry.length > 0) console.log(` Hungry: ${r.hungry.join(', ')}`);
120});When building your monitoring system, pay attention to:
filter, map, reduce), and regular functions for object methods that need this...args) - ideal when the number of arguments varies (e.g., event list)filter().map().sort() is more readable than nested loopslet and const have block scope, var has function scope - choose wiselyfilter, map, reduce create new arrays, but push, splice, sort modify the originalTime to step into the role of the head operator of Jurassic Park! Create your own Monitoring System in the editor below. Combine arrays, functions, array methods, and objects into one working system. Remember - every dinosaur in the park depends on your code. As John Hammond said: "We spared no expense" - and you shouldn't spare any code!
"This monitoring system is Jurassic Park's backbone" - says Dr. Rex. "Notice how we chain operations, use default parameters for flexibility, and rest parameters for variable input. The array methods make complex analysis readable and elegant. This is real JavaScript in action!"