Welcome back to Jurassic Park! In the previous module, we learned the basics of arrays in JavaScript. Now we will dive into the basic array methods that are essential for everyday data work. These methods allow you to add, remove, and manipulate elements in arrays, which is crucial for managing the dinosaur inventory, planning feedings, and organizing park staff.
First, let's look at methods that modify the original array. These are called mutating methods.
The
push() method adds one or more elements to the end of an array and returns the new length of the array:1// Managing dinosaur species in our enclosure
2const dinoEnclosure = ["T-Rex", "Velociraptor"];
3
4// Adding a new dinosaur species
5dinoEnclosure.push("Dilophosaurus");
6console.log(dinoEnclosure); // ["T-Rex", "Velociraptor", "Dilophosaurus"]
7
8// Adding several species at once
9const newLength = dinoEnclosure.push("Gallimimus", "Compsognathus");
10console.log(dinoEnclosure);
11// ["T-Rex", "Velociraptor", "Dilophosaurus", "Gallimimus", "Compsognathus"]
12console.log(`Current number of species in enclosure: ${newLength}`); // 5When to use
push():The
pop() method removes the last element from an array and returns that element:1// List of dinosaurs in our enclosure
2const dinoEnclosure = ["T-Rex", "Velociraptor", "Dilophosaurus", "Compsognathus"];
3
4// Moving the last dinosaur to a new enclosure
5const removedDino = dinoEnclosure.pop();
6console.log(`Moved dinosaur: ${removedDino}`); // "Compsognathus"
7console.log(`Remaining dinosaurs: ${dinoEnclosure}`); // ["T-Rex", "Velociraptor", "Dilophosaurus"]
8
9// We can continue removing
10const anotherRemovedDino = dinoEnclosure.pop();
11console.log(`Moved another dinosaur: ${anotherRemovedDino}`); // "Dilophosaurus"
12console.log(`Current enclosure contents: ${dinoEnclosure}`); // ["T-Rex", "Velociraptor"]When to use
pop():The
unshift() method adds one or more elements to the beginning of an array and returns the new length of the array:1// Queue of dinosaurs waiting for examination
2const dinoQueue = ["Velociraptor", "Triceratops"];
3
4// Priority addition of T-Rex to the front of the queue
5dinoQueue.unshift("T-Rex");
6console.log(`Current queue: ${dinoQueue}`); // ["T-Rex", "Velociraptor", "Triceratops"]
7
8// Adding several dinosaurs at once to the front
9const newQueueSize = dinoQueue.unshift("Brachiosaurus", "Stegosaurus");
10console.log(`Current queue: ${dinoQueue}`);
11// ["Brachiosaurus", "Stegosaurus", "T-Rex", "Velociraptor", "Triceratops"]
12console.log(`Number of dinosaurs in queue: ${newQueueSize}`); // 5When to use
unshift():The
shift() method removes the first element from an array and returns that element:1// Queue of dinosaurs waiting for examination
2const dinoQueue = ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus"];
3
4// Getting the first dinosaur for examination
5const nextDino = dinoQueue.shift();
6console.log(`Examining dinosaur: ${nextDino}`); // "T-Rex"
7console.log(`Remaining queue: ${dinoQueue}`); // ["Velociraptor", "Triceratops", "Stegosaurus"]
8
9// Processing the next dinosaur
10const anotherDino = dinoQueue.shift();
11console.log(`Next dinosaur for examination: ${anotherDino}`); // "Velociraptor"
12console.log(`Current queue state: ${dinoQueue}`); // ["Triceratops", "Stegosaurus"]When to use
shift():The
splice() method changes the contents of an array by removing, replacing, or adding elements. It is extremely versatile because it allows modification of the array at any position.Basic syntax:
array.splice(startIndex, deleteCount, item1, item2, ...):startIndex: the index at which to start the changedeleteCount: the number of elements to removeitem1, item2, ...: (optional) elements to add1// List of dinosaur species in the park
2const dinosaurs = ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus", "Brachiosaurus"];
3
4// Remove 2 elements starting from index 1 (the second element)
5const removedDinos = dinosaurs.splice(1, 2);
6console.log(`Removed dinosaurs: ${removedDinos}`); // ["Velociraptor", "Triceratops"]
7console.log(`Remaining dinosaurs: ${dinosaurs}`); // ["T-Rex", "Stegosaurus", "Brachiosaurus"]1// List of dinosaur species
2const dinosaurs = ["T-Rex", "Dilophosaurus", "Triceratops", "Stegosaurus"];
3
4// Replace Dilophosaurus with Velociraptor
5const replaced = dinosaurs.splice(1, 1, "Velociraptor");
6console.log(`Replaced dinosaur: ${replaced}`); // ["Dilophosaurus"]
7console.log(`Current list: ${dinosaurs}`); // ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus"]
8
9// Replace multiple elements at once
10dinosaurs.splice(2, 2, "Brachiosaurus", "Ankylosaurus", "Parasaurolophus");
11console.log(`New roster: ${dinosaurs}`);
12// ["T-Rex", "Velociraptor", "Brachiosaurus", "Ankylosaurus", "Parasaurolophus"]1// List of dinosaur species
2const dinosaurs = ["T-Rex", "Velociraptor"];
3
4// Add new species at index 1 (between T-Rex and Velociraptor)
5dinosaurs.splice(1, 0, "Dilophosaurus", "Compsognathus");
6console.log(dinosaurs); // ["T-Rex", "Dilophosaurus", "Compsognathus", "Velociraptor"]When to use
splice():The
sort() method sorts the elements of an array in place and returns the sorted array:1// List of dinosaurs for feeding
2const feedingList = ["Velociraptor", "T-Rex", "Dilophosaurus", "Gallimimus", "Compsognathus"];
3
4// Alphabetical sorting
5feedingList.sort();
6console.log(`Feeding list (alphabetical): ${feedingList}`);
7// ["Compsognathus", "Dilophosaurus", "Gallimimus", "T-Rex", "Velociraptor"]
8
9// Array with dinosaur sizes (in cm)
10const dinoSizes = [1200, 300, 800, 2000, 40];
11
12// Default sort treats numbers as strings - this won't work correctly!
13dinoSizes.sort();
14console.log("Incorrectly sorted sizes:", dinoSizes);
15// Probably: [1200, 2000, 300, 40, 800] - incorrect!
16
17// Correct number sorting with a compare function
18dinoSizes.sort((a, b) => a - b);
19console.log("Correctly sorted sizes (ascending):", dinoSizes);
20// [40, 300, 800, 1200, 2000]
21
22// Descending sort
23dinoSizes.sort((a, b) => b - a);
24console.log("Sizes sorted descending:", dinoSizes);
25// [2000, 1200, 800, 300, 40]1// Dinosaur data for feeding
2const dinosaurs = [
3 { name: "T-Rex", weight: 7000, priority: 1 },
4 { name: "Velociraptor", weight: 100, priority: 2 },
5 { name: "Triceratops", weight: 9000, priority: 3 },
6 { name: "Gallimimus", weight: 450, priority: 4 }
7];
8
9// Sort by feeding priority
10dinosaurs.sort((a, b) => a.priority - b.priority);
11console.log("Feeding order by priority:");
12dinosaurs.forEach(dino => console.log(`${dino.name} (priority: ${dino.priority})`));
13
14// Sort by weight (heaviest first)
15dinosaurs.sort((a, b) => b.weight - a.weight);
16console.log("\nOrder by weight (heaviest first):");
17dinosaurs.forEach(dino => console.log(`${dino.name} (${dino.weight} kg)`));
18
19// Sort alphabetically by name
20dinosaurs.sort((a, b) => a.name.localeCompare(b.name));
21console.log("\nDinosaurs alphabetically:");
22dinosaurs.forEach(dino => console.log(`${dino.name}`));The
sort() method takes an optional compare function that should return:When to use
sort():The
reverse() method reverses the order of elements in an array and returns the reversed array:1// List of dinosaurs from oldest to youngest
2const dinosaursByAge = ["Brachiosaurus", "Stegosaurus", "Triceratops", "Velociraptor", "T-Rex"];
3
4// Reverse the order to get youngest to oldest
5dinosaursByAge.reverse();
6console.log("From youngest to oldest:", dinosaursByAge);
7// ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus", "Brachiosaurus"]
8
9// Often used in combination with sort()
10const dinoHeights = [500, 900, 200, 1200, 350];
11// Descending sort by sorting ascending + reversing
12dinoHeights.sort((a, b) => a - b).reverse();
13console.log("Heights descending:", dinoHeights);
14// [1200, 900, 500, 350, 200]When to use
reverse():The
fill() method fills all elements of an array from a start index to an end index (not including) with a specified value:1// Preparing an array for dinosaur temperature readings (10 readings)
2const temperatures = new Array(10);
3
4// Fill with a default value (38.5 degrees Celsius)
5temperatures.fill(38.5);
6console.log(`Default temperatures: ${temperatures}`);
7// [38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5]
8
9// Fill only part of the array
10temperatures.fill(39.2, 2, 5); // From index 2 (inclusive) to 5 (exclusive)
11console.log(`Updated temperatures: ${temperatures}`);
12// [38.5, 38.5, 39.2, 39.2, 39.2, 38.5, 38.5, 38.5, 38.5, 38.5]
13
14// Using with a new array and negative indices (counted from the end)
15const feedingSchedule = new Array(7).fill("Standard");
16feedingSchedule.fill("Extra portion", -3); // Last 3 days
17console.log(`Weekly feeding plan: ${feedingSchedule}`);
18// ["Standard", "Standard", "Standard", "Standard", "Extra portion", "Extra portion", "Extra portion"]When to use
fill():Now let's combine the methods we've learned to solve more practical scenarios in our Jurassic Park:
1// Dinosaur food management system
2const feedingSystem = {
3 // System state
4 foodInventory: [],
5 feedingQueue: [],
6 feedingHistory: [],
7
8 // Adding a new food supply
9 addFoodSupply: function(type, quantity, expirationDate) {
10 const supply = { type, quantity, expirationDate, addedOn: new Date() };
11 this.foodInventory.push(supply);
12
13 // Sort by expiration date (soonest first)
14 this.foodInventory.sort((a, b) =>
15 new Date(a.expirationDate) - new Date(b.expirationDate)
16 );
17
18 console.log(`Added ${quantity}kg of "${type}" food to supplies.`);
19 return supply;
20 },
21
22 // Adding a dinosaur to the feeding queue
23 scheduleDinoFeeding: function(dinoId, dinoName, foodType, quantity, priority) {
24 const feedingRequest = {
25 dinoId,
26 dinoName,
27 foodType,
28 quantity,
29 priority,
30 scheduledAt: new Date()
31 };
32
33 if (priority === "high") {
34 // Add to the front of the queue
35 this.feedingQueue.unshift(feedingRequest);
36 } else {
37 // Add to the end of the queue
38 this.feedingQueue.push(feedingRequest);
39 }
40
41 console.log(`Scheduled feeding for ${dinoName} (priority: ${priority})`);
42 return this.feedingQueue.length;
43 },
44
45 // Getting the next dinosaur to feed
46 getNextDinoToFeed: function() {
47 if (this.feedingQueue.length === 0) {
48 console.log("All dinosaurs fed. Queue empty.");
49 return null;
50 }
51
52 const nextFeeding = this.feedingQueue.shift();
53 console.log(`Next to feed: ${nextFeeding.dinoName}`);
54 return nextFeeding;
55 },
56
57 // Dispensing food from the warehouse
58 dispenseFoodForDino: function(dinoFeeding) {
59 const { foodType, quantity, dinoName } = dinoFeeding;
60
61 // Search for the appropriate food supply
62 let remainingQuantity = quantity;
63 const usedSupplies = [];
64
65 // Iterate from the oldest supply (expires soonest)
66 for (let i = 0; i < this.foodInventory.length && remainingQuantity > 0; i++) {
67 const supply = this.foodInventory[i];
68
69 if (supply.type === foodType && supply.quantity > 0) {
70 // How much we can take from this supply
71 const amountToTake = Math.min(remainingQuantity, supply.quantity);
72 supply.quantity -= amountToTake;
73 remainingQuantity -= amountToTake;
74
75 usedSupplies.push({
76 type: supply.type,
77 amount: amountToTake,
78 expirationDate: supply.expirationDate
79 });
80
81 // If the supply is empty, remove it from inventory
82 if (supply.quantity === 0) {
83 this.foodInventory.splice(i, 1);
84 i--; // Adjust index after removing element
85 }
86 }
87 }
88
89 // Add record to feeding history
90 const feedingRecord = {
91 ...dinoFeeding,
92 fedAt: new Date(),
93 suppliesUsed: usedSupplies,
94 fullyFed: remainingQuantity === 0
95 };
96
97 this.feedingHistory.push(feedingRecord);
98
99 if (remainingQuantity > 0) {
100 console.log(`WARNING: Missing ${remainingQuantity}kg of "${foodType}" food for ${dinoName}!`);
101 return false;
102 }
103
104 console.log(`Fed ${dinoName} using ${quantity}kg of "${foodType}" food.`);
105 return feedingRecord;
106 },
107
108 // Performing a full feeding cycle
109 processFeedingCycle: function(maxFeedings = 5) {
110 console.log("=== STARTING FEEDING CYCLE ===");
111 let feedingsProcessed = 0;
112
113 // Process a specified number of feedings or until the queue is empty
114 while (feedingsProcessed < maxFeedings && this.feedingQueue.length > 0) {
115 const nextDino = this.getNextDinoToFeed();
116
117 if (nextDino) {
118 const result = this.dispenseFoodForDino(nextDino);
119
120 if (!result) {
121 // If feeding failed, move the dinosaur to the end of the queue
122 this.feedingQueue.push({
123 ...nextDino,
124 priority: "high", // Raise priority for unfed dinosaur
125 scheduledAt: new Date()
126 });
127 console.log(`${nextDino.dinoName} moved to end of queue with high priority.`);
128 }
129
130 feedingsProcessed++;
131 }
132 }
133
134 console.log(`=== FEEDING CYCLE COMPLETE (processed: ${feedingsProcessed}) ===`);
135 console.log(`Remaining in queue: ${this.feedingQueue.length} dinosaurs`);
136 return feedingsProcessed;
137 },
138
139 // Reporting inventory status
140 reportInventoryStatus: function() {
141 console.log("=== INVENTORY STATUS REPORT ===");
142
143 if (this.foodInventory.length === 0) {
144 console.log("Warehouse is empty! Order new food supplies!");
145 return { isEmpty: true, totalQuantity: 0, types: [] };
146 }
147
148 // Group supplies by type
149 const inventory = this.foodInventory.reduce((acc, supply) => {
150 if (!acc[supply.type]) {
151 acc[supply.type] = 0;
152 }
153 acc[supply.type] += supply.quantity;
154 return acc;
155 }, {});
156
157 // Calculate total quantity
158 const totalQuantity = Object.values(inventory).reduce((sum, qty) => sum + qty, 0);
159
160 console.log(`Total food supply: ${totalQuantity}kg`);
161 Object.entries(inventory).forEach(([type, qty]) => {
162 console.log(`- ${type}: ${qty}kg`);
163 });
164
165 // Check supplies expiring soon (within 3 days)
166 const today = new Date();
167 const threeDaysLater = new Date(today);
168 threeDaysLater.setDate(today.getDate() + 3);
169
170 const expiringSupplies = this.foodInventory.filter(supply =>
171 new Date(supply.expirationDate) <= threeDaysLater
172 );
173
174 if (expiringSupplies.length > 0) {
175 console.log("\nSupplies expiring within 3 days:");
176 expiringSupplies.forEach(supply => {
177 console.log(`- ${supply.quantity}kg ${supply.type} (expires: ${supply.expirationDate})`);
178 });
179 }
180
181 return {
182 isEmpty: false,
183 totalQuantity,
184 types: Object.keys(inventory),
185 inventory,
186 expiringSupplies
187 };
188 }
189};
190
191// System demonstration
192console.log("=== FOOD MANAGEMENT SYSTEM DEMONSTRATION ===");
193
194// 1. Adding food supplies
195feedingSystem.addFoodSupply("Meat", 500, "2023-07-15");
196feedingSystem.addFoodSupply("Plants", 800, "2023-07-10");
197feedingSystem.addFoodSupply("Fish", 200, "2023-07-05");
198feedingSystem.addFoodSupply("Meat", 300, "2023-07-20");
199
200// 2. Scheduling feedings
201feedingSystem.scheduleDinoFeeding("TRX-01", "Rex", "Meat", 150, "high");
202feedingSystem.scheduleDinoFeeding("VEL-02", "Blue", "Meat", 50, "normal");
203feedingSystem.scheduleDinoFeeding("TRCP-03", "Trixie", "Plants", 120, "normal");
204feedingSystem.scheduleDinoFeeding("BRCH-04", "Bronty", "Plants", 250, "normal");
205feedingSystem.scheduleDinoFeeding("STEG-05", "Spike", "Plants", 100, "high");
206
207// 3. Inventory status report before feeding
208feedingSystem.reportInventoryStatus();
209
210// 4. Processing feeding cycle
211feedingSystem.processFeedingCycle(3); // Process only 3 feedings
212
213// 5. Check inventory status after feeding
214feedingSystem.reportInventoryStatus();
215
216// 6. Complete the feeding cycle
217feedingSystem.processFeedingCycle(5); // Process remaining feedings
218
219// 7. Check inventory status after full cycle
220feedingSystem.reportInventoryStatus();1// Jurassic Park staff team management system
2const staffManagementSystem = {
3 // System data
4 departments: [
5 { id: "OPS", name: "Operations" },
6 { id: "SCI", name: "Scientific Research" },
7 { id: "SEC", name: "Security" },
8 { id: "VET", name: "Veterinary" },
9 { id: "MAINT", name: "Maintenance" }
10 ],
11 staff: [],
12 teams: [],
13
14 // Adding a new employee
15 addStaffMember: function(name, role, skills, departmentId) {
16 // Check if department exists
17 const department = this.departments.find(dept => dept.id === departmentId);
18 if (!department) {
19 console.log(`Error: Department with ID "${departmentId}" does not exist.`);
20 return null;
21 }
22
23 // Generate employee ID
24 const id = `${departmentId}-${(this.staff.length + 1).toString().padStart(3, '0')}`;
25
26 const staffMember = {
27 id,
28 name,
29 role,
30 skills: Array.isArray(skills) ? skills : [skills],
31 departmentId,
32 departmentName: department.name,
33 hireDate: new Date().toISOString().split('T')[0]
34 };
35
36 this.staff.push(staffMember);
37 console.log(`Added employee: ${name} (${role}) to department ${department.name}`);
38
39 return staffMember;
40 },
41
42 // Creating a new team
43 createTeam: function(name, mission, leaderId) {
44 // Check if leader exists
45 const leader = this.staff.find(person => person.id === leaderId);
46 if (!leader) {
47 console.log(`Error: Employee with ID "${leaderId}" does not exist.`);
48 return null;
49 }
50
51 const teamId = `TEAM-${(this.teams.length + 1).toString().padStart(3, '0')}`;
52
53 const team = {
54 id: teamId,
55 name,
56 mission,
57 createdAt: new Date().toISOString().split('T')[0],
58 leaderId,
59 leaderName: leader.name,
60 members: [leaderId],
61 status: "active"
62 };
63
64 this.teams.push(team);
65 console.log(`Created team: ${name} (mission: ${mission}), leader: ${leader.name}`);
66
67 return team;
68 },
69
70 // Adding an employee to a team
71 addMemberToTeam: function(teamId, memberId) {
72 // Find team
73 const teamIndex = this.teams.findIndex(team => team.id === teamId);
74 if (teamIndex === -1) {
75 console.log(`Error: Team with ID "${teamId}" does not exist.`);
76 return false;
77 }
78
79 // Find employee
80 const member = this.staff.find(person => person.id === memberId);
81 if (!member) {
82 console.log(`Error: Employee with ID "${memberId}" does not exist.`);
83 return false;
84 }
85
86 // Check if employee is already in the team
87 if (this.teams[teamIndex].members.includes(memberId)) {
88 console.log(`${member.name} is already a member of team ${this.teams[teamIndex].name}.`);
89 return false;
90 }
91
92 // Add employee to team
93 this.teams[teamIndex].members.push(memberId);
94 console.log(`Added ${member.name} to team ${this.teams[teamIndex].name}.`);
95
96 return true;
97 },
98
99 // Removing an employee from a team
100 removeMemberFromTeam: function(teamId, memberId) {
101 // Find team
102 const teamIndex = this.teams.findIndex(team => team.id === teamId);
103 if (teamIndex === -1) {
104 console.log(`Error: Team with ID "${teamId}" does not exist.`);
105 return false;
106 }
107
108 // Check if employee is the leader
109 if (this.teams[teamIndex].leaderId === memberId) {
110 console.log(`Error: Cannot remove the team leader. Change the leader first.`);
111 return false;
112 }
113
114 // Find employee index in the team
115 const memberIndex = this.teams[teamIndex].members.indexOf(memberId);
116 if (memberIndex === -1) {
117 console.log(`Employee is not a member of team ${this.teams[teamIndex].name}.`);
118 return false;
119 }
120
121 // Find employee for informational purposes
122 const member = this.staff.find(person => person.id === memberId);
123
124 // Remove employee from team
125 this.teams[teamIndex].members.splice(memberIndex, 1);
126 console.log(`Removed ${member ? member.name : memberId} from team ${this.teams[teamIndex].name}.`);
127
128 return true;
129 },
130
131 // Changing team leader
132 changeTeamLeader: function(teamId, newLeaderId) {
133 // Find team
134 const teamIndex = this.teams.findIndex(team => team.id === teamId);
135 if (teamIndex === -1) {
136 console.log(`Error: Team with ID "${teamId}" does not exist.`);
137 return false;
138 }
139
140 // Check if new leader exists
141 const newLeader = this.staff.find(person => person.id === newLeaderId);
142 if (!newLeader) {
143 console.log(`Error: Employee with ID "${newLeaderId}" does not exist.`);
144 return false;
145 }
146
147 // Check if new leader is a team member
148 if (!this.teams[teamIndex].members.includes(newLeaderId)) {
149 // Add new leader to team if not already a member
150 this.teams[teamIndex].members.push(newLeaderId);
151 console.log(`${newLeader.name} was added to the team as the new leader.`);
152 }
153
154 // Save old leader info for the message
155 const oldLeaderId = this.teams[teamIndex].leaderId;
156 const oldLeader = this.staff.find(person => person.id === oldLeaderId);
157
158 // Update leader
159 this.teams[teamIndex].leaderId = newLeaderId;
160 this.teams[teamIndex].leaderName = newLeader.name;
161
162 console.log(`Team ${this.teams[teamIndex].name} leader changed from ${oldLeader.name} to ${newLeader.name}.`);
163 return true;
164 },
165
166 // Deactivating a team
167 deactivateTeam: function(teamId, reason) {
168 // Find team
169 const teamIndex = this.teams.findIndex(team => team.id === teamId);
170 if (teamIndex === -1) {
171 console.log(`Error: Team with ID "${teamId}" does not exist.`);
172 return false;
173 }
174
175 // Save state before modification
176 const teamName = this.teams[teamIndex].name;
177
178 // Update team status
179 this.teams[teamIndex].status = "inactive";
180 this.teams[teamIndex].deactivatedAt = new Date().toISOString().split('T')[0];
181 this.teams[teamIndex].deactivationReason = reason || "Unspecified";
182
183 console.log(`Team ${teamName} has been deactivated. Reason: ${this.teams[teamIndex].deactivationReason}`);
184 return true;
185 },
186
187 // Generating a teams report
188 generateTeamsReport: function(includeInactive = false) {
189 console.log("=== JURASSIC PARK TEAMS REPORT ===");
190
191 // Filter teams by status if not including inactive
192 const teamsToReport = includeInactive
193 ? this.teams
194 : this.teams.filter(team => team.status === "active");
195
196 if (teamsToReport.length === 0) {
197 console.log("No teams to display.");
198 return { teams: [] };
199 }
200
201 // Prepare report data
202 const teamsData = teamsToReport.map(team => {
203 // Get full member information
204 const memberDetails = team.members.map(memberId => {
205 const member = this.staff.find(person => person.id === memberId);
206 return member ? {
207 id: member.id,
208 name: member.name,
209 role: member.role,
210 isLeader: memberId === team.leaderId
211 } : { id: memberId, name: "Unknown", role: "Unknown", isLeader: false };
212 });
213
214 return {
215 id: team.id,
216 name: team.name,
217 mission: team.mission,
218 status: team.status,
219 memberCount: team.members.length,
220 leader: this.staff.find(person => person.id === team.leaderId),
221 members: memberDetails,
222 createdAt: team.createdAt,
223 deactivatedAt: team.deactivatedAt,
224 deactivationReason: team.deactivationReason
225 };
226 });
227
228 // Sort teams - active first, then by creation date
229 teamsData.sort((a, b) => {
230 if (a.status !== b.status) {
231 return a.status === "active" ? -1 : 1;
232 }
233 return new Date(b.createdAt) - new Date(a.createdAt);
234 });
235
236 // Display summary
237 console.log(`Number of teams: ${teamsData.length}`);
238 console.log(`Active teams: ${teamsData.filter(t => t.status === "active").length}`);
239 if (includeInactive) {
240 console.log(`Inactive teams: ${teamsData.filter(t => t.status === "inactive").length}`);
241 }
242
243 // Display details for each team
244 teamsData.forEach(team => {
245 console.log(`\n${team.id}: ${team.name} (Status: ${team.status})`);
246 console.log(`Mission: ${team.mission}`);
247 console.log(`Leader: ${team.leader ? team.leader.name : 'None'} (${team.leader ? team.leader.role : ''})`);
248 console.log(`Number of members: ${team.memberCount}`);
249 console.log("Members:");
250 team.members.forEach(member => {
251 console.log(` - ${member.name} (${member.role})${member.isLeader ? ' [LEADER]' : ''}`);
252 });
253
254 if (team.status === "inactive") {
255 console.log(`Deactivated: ${team.deactivatedAt}`);
256 console.log(`Reason: ${team.deactivationReason}`);
257 }
258 });
259
260 return { teams: teamsData };
261 },
262
263 // Reorganizing teams
264 reorganizeTeams: function(fromTeamId, toTeamId, memberIds, dissolveSourceTeam = false) {
265 // Check if teams exist
266 const fromTeamIndex = this.teams.findIndex(team => team.id === fromTeamId);
267 const toTeamIndex = this.teams.findIndex(team => team.id === toTeamId);
268
269 if (fromTeamIndex === -1 || toTeamIndex === -1) {
270 console.log(`Error: One or both teams do not exist.`);
271 return false;
272 }
273
274 // Check if teams are active
275 if (this.teams[fromTeamIndex].status !== "active" || this.teams[toTeamIndex].status !== "active") {
276 console.log(`Error: Teams must be active to reorganize them.`);
277 return false;
278 }
279
280 // If no specific members specified, transfer all (except leader)
281 const membersToMove = memberIds ||
282 this.teams[fromTeamIndex].members.filter(id => id !== this.teams[fromTeamIndex].leaderId);
283
284 // Transfer members
285 for (const memberId of membersToMove) {
286 // Check if employee is part of the source team
287 if (!this.teams[fromTeamIndex].members.includes(memberId)) {
288 console.log(`Error: Employee with ID ${memberId} is not a member of the source team.`);
289 continue;
290 }
291
292 // Check if employee is the leader (if we don't want to transfer everyone)
293 if (memberIds && memberId === this.teams[fromTeamIndex].leaderId) {
294 console.log(`Cannot transfer team leader. Change the leader first.`);
295 continue;
296 }
297
298 // Check if employee is already part of the target team
299 if (this.teams[toTeamIndex].members.includes(memberId)) {
300 console.log(`Employee with ID ${memberId} is already a member of the target team.`);
301 continue;
302 }
303
304 // Remove from original team
305 const fromIndex = this.teams[fromTeamIndex].members.indexOf(memberId);
306 this.teams[fromTeamIndex].members.splice(fromIndex, 1);
307
308 // Add to new team
309 this.teams[toTeamIndex].members.push(memberId);
310
311 // Find employee name for logs
312 const member = this.staff.find(person => person.id === memberId);
313 console.log(`Transferred ${member ? member.name : memberId} from team ${this.teams[fromTeamIndex].name} to ${this.teams[toTeamIndex].name}`);
314 }
315
316 // If chosen to dissolve source team and no members left
317 if (dissolveSourceTeam || this.teams[fromTeamIndex].members.length === 0) {
318 this.deactivateTeam(fromTeamId, "Reorganization - team transferred");
319 }
320
321 return true;
322 }
323};
324
325// Staff team management system demonstration
326console.log("=== STAFF TEAM MANAGEMENT SYSTEM DEMONSTRATION ===");
327
328// 1. Adding employees
329const owen = staffManagementSystem.addStaffMember("Owen Grady", "Dinosaur Trainer", ["Animal behavior", "Training", "First aid"], "OPS");
330const claire = staffManagementSystem.addStaffMember("Claire Dearing", "Operations Director", ["Management", "Marketing", "Administration"], "OPS");
331const dr_wu = staffManagementSystem.addStaffMember("Dr. Henry Wu", "Chief Geneticist", ["Genetics", "Bioengineering", "Cloning"], "SCI");
332const barry = staffManagementSystem.addStaffMember("Barry", "Assistant Trainer", ["Training", "Animal care"], "OPS");
333const lowery = staffManagementSystem.addStaffMember("Lowery Cruthers", "Systems Technician", ["IT", "Monitoring", "Communication"], "SEC");
334const vivian = staffManagementSystem.addStaffMember("Vivian Krill", "Security Coordinator", ["Security", "Communication", "Crisis management"], "SEC");
335const muldoon = staffManagementSystem.addStaffMember("Robert Muldoon", "Security Specialist", ["Firearms", "Security", "Tracking"], "SEC");
336const malcolm = staffManagementSystem.addStaffMember("Dr. Ian Malcolm", "Mathematician", ["Chaos theory", "Risk analysis", "Modeling"], "SCI");
337const sattler = staffManagementSystem.addStaffMember("Dr. Ellie Sattler", "Paleobotanist", ["Botany", "Paleontology", "Ecology"], "SCI");
338const harding = staffManagementSystem.addStaffMember("Dr. Gerry Harding", "Veterinarian", ["Veterinary medicine", "Zoology", "Medicine"], "VET");
339
340// 2. Creating teams
341const raptorTeam = staffManagementSystem.createTeam("Velociraptor Team", "Training and care of Velociraptors", owen.id);
342staffManagementSystem.addMemberToTeam(raptorTeam.id, barry.id);
343
344const securityTeam = staffManagementSystem.createTeam("Security Team", "Ensuring park safety", muldoon.id);
345staffManagementSystem.addMemberToTeam(securityTeam.id, vivian.id);
346staffManagementSystem.addMemberToTeam(securityTeam.id, lowery.id);
347
348const scienceTeam = staffManagementSystem.createTeam("Science Team", "Scientific research and development", dr_wu.id);
349staffManagementSystem.addMemberToTeam(scienceTeam.id, malcolm.id);
350staffManagementSystem.addMemberToTeam(scienceTeam.id, sattler.id);
351
352// 3. Teams report
353staffManagementSystem.generateTeamsReport();
354
355// 4. Team reorganization
356console.log("\n=== TEAM REORGANIZATION ===");
357
358// Creating a new crisis management team
359const crisisTeam = staffManagementSystem.createTeam("Crisis Management Team", "Responding to crisis situations", claire.id);
360
361// Transferring members from other teams
362staffManagementSystem.reorganizeTeams(securityTeam.id, crisisTeam.id, [vivian.id]);
363staffManagementSystem.addMemberToTeam(crisisTeam.id, malcolm.id); // Adding Malcolm as risk advisor
364staffManagementSystem.addMemberToTeam(crisisTeam.id, harding.id); // Adding veterinarian
365
366// Changing science team leader
367staffManagementSystem.changeTeamLeader(scienceTeam.id, sattler.id);
368
369// Deactivating one team
370staffManagementSystem.deactivateTeam(raptorTeam.id, "Project suspended - raptor incident");
371
372// 5. Final teams report (including inactive)
373staffManagementSystem.generateTeamsReport(true);In this module, we learned the basic array modification methods in JavaScript:
The ability to effectively use these methods is crucial when working with data in JavaScript. They allow you to manage collections, implement data structures (such as stacks and queues), and efficiently manipulate data.
It is worth remembering that the above methods modify the original array (except when you create a copy before applying them). In the next module, we will learn array methods that do not modify the original but return a new array or value.