Witaj ponownie w Parku Jurajskim! W poprzednim module poznaliśmy podstawy tablic w JavaScript. Teraz zagłębimy się w podstawowe metody tablic, które są niezbędne do codziennej pracy z danymi. Te metody pozwalają na dodawanie, usuwanie i manipulowanie elementami w tablicach, co jest kluczowe przy zarządzaniu inwentarzem dinozaurów, planowaniu karmienia czy organizacji personelu parku.
Najpierw przyjrzyjmy się metodom, które modyfikują oryginalną tablicę. Są to tak zwane metody mutujące (ang. mutating methods).
Metoda
push() dodaje jeden lub więcej elementów na końcu tablicy i zwraca nową długość tablicy:1// Zarządzanie gatunkami dinozaurów w naszej zagrodzie
2const dinoEnclosure = ["T-Rex", "Velociraptor"];
3
4// Dodajemy nowy gatunek dinozaura
5dinoEnclosure.push("Dilophosaurus");
6console.log(dinoEnclosure); // ["T-Rex", "Velociraptor", "Dilophosaurus"]
7
8// Dodajemy kilka gatunków naraz
9const newLength = dinoEnclosure.push("Gallimimus", "Compsognathus");
10console.log(dinoEnclosure);
11// ["T-Rex", "Velociraptor", "Dilophosaurus", "Gallimimus", "Compsognathus"]
12console.log(`Aktualna liczba gatunków w zagrodzie: ${newLength}`); // 5Kiedy warto używać
push():Metoda
pop() usuwa ostatni element z tablicy i zwraca ten element:1// Lista dinozaurów w naszej zagrodzie
2const dinoEnclosure = ["T-Rex", "Velociraptor", "Dilophosaurus", "Compsognathus"];
3
4// Przenoszenie ostatniego dinozaura do nowej zagrody
5const removedDino = dinoEnclosure.pop();
6console.log(`Przeniesiono dinozaura: ${removedDino}`); // "Compsognathus"
7console.log(`Pozostałe dinozaury: ${dinoEnclosure}`); // ["T-Rex", "Velociraptor", "Dilophosaurus"]
8
9// Możemy kontynuować usuwanie
10const anotherRemovedDino = dinoEnclosure.pop();
11console.log(`Przeniesiono kolejnego dinozaura: ${anotherRemovedDino}`); // "Dilophosaurus"
12console.log(`Aktualna zawartość zagrody: ${dinoEnclosure}`); // ["T-Rex", "Velociraptor"]Kiedy warto używać
pop():Metoda
unshift() dodaje jeden lub więcej elementów na początku tablicy i zwraca nową długość tablicy:1// Kolejka dinozaurów oczekujących na badania
2const dinoQueue = ["Velociraptor", "Triceratops"];
3
4// Priorytetowe dodanie T-Rexa na początek kolejki
5dinoQueue.unshift("T-Rex");
6console.log(`Aktualna kolejka: ${dinoQueue}`); // ["T-Rex", "Velociraptor", "Triceratops"]
7
8// Dodanie kilku dinozaurów naraz na początek
9const newQueueSize = dinoQueue.unshift("Brachiosaurus", "Stegosaurus");
10console.log(`Aktualna kolejka: ${dinoQueue}`);
11// ["Brachiosaurus", "Stegosaurus", "T-Rex", "Velociraptor", "Triceratops"]
12console.log(`Liczba dinozaurów w kolejce: ${newQueueSize}`); // 5Kiedy warto używać
unshift():Metoda
shift() usuwa pierwszy element z tablicy i zwraca ten element:1// Kolejka dinozaurów oczekujących na badania
2const dinoQueue = ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus"];
3
4// Pobieramy pierwszego dinozaura do badań
5const nextDino = dinoQueue.shift();
6console.log(`Badamy dinozaura: ${nextDino}`); // "T-Rex"
7console.log(`Pozostała kolejka: ${dinoQueue}`); // ["Velociraptor", "Triceratops", "Stegosaurus"]
8
9// Obsługa kolejnego dinozaura
10const anotherDino = dinoQueue.shift();
11console.log(`Następny dinozaur do badań: ${anotherDino}`); // "Velociraptor"
12console.log(`Aktualny stan kolejki: ${dinoQueue}`); // ["Triceratops", "Stegosaurus"]Kiedy warto używać
shift():Metoda
splice() zmienia zawartość tablicy, usuwając, zamieniając lub dodając elementy. Jest niezwykle wszechstronna, ponieważ pozwala na modyfikację tablicy w dowolnym miejscu.Podstawowa składnia:
array.splice(startIndex, deleteCount, item1, item2, ...):startIndex: indeks, od którego zacząć zmianędeleteCount: liczba elementów do usunięciaitem1, item2, ...: (opcjonalnie) elementy do dodania1// Lista gatunków dinozaurów w parku
2const dinosaurs = ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus", "Brachiosaurus"];
3
4// Usuwamy 2 elementy zaczynając od indeksu 1 (drugiego elementu)
5const removedDinos = dinosaurs.splice(1, 2);
6console.log(`Usunięte dinozaury: ${removedDinos}`); // ["Velociraptor", "Triceratops"]
7console.log(`Pozostałe dinozaury: ${dinosaurs}`); // ["T-Rex", "Stegosaurus", "Brachiosaurus"]1// Lista gatunków dinozaurów
2const dinosaurs = ["T-Rex", "Dilophosaurus", "Triceratops", "Stegosaurus"];
3
4// Zastępujemy Dilophosaurus przez Velociraptor
5const replaced = dinosaurs.splice(1, 1, "Velociraptor");
6console.log(`Zastąpiony dinozaur: ${replaced}`); // ["Dilophosaurus"]
7console.log(`Aktualna lista: ${dinosaurs}`); // ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus"]
8
9// Zastępujemy wiele elementów naraz
10dinosaurs.splice(2, 2, "Brachiosaurus", "Ankylosaurus", "Parasaurolophus");
11console.log(`Nowy skład: ${dinosaurs}`);
12// ["T-Rex", "Velociraptor", "Brachiosaurus", "Ankylosaurus", "Parasaurolophus"]1// Lista gatunków dinozaurów
2const dinosaurs = ["T-Rex", "Velociraptor"];
3
4// Dodajemy nowe gatunki na indeksie 1 (między T-Rex a Velociraptor)
5dinosaurs.splice(1, 0, "Dilophosaurus", "Compsognathus");
6console.log(dinosaurs); // ["T-Rex", "Dilophosaurus", "Compsognathus", "Velociraptor"]Kiedy warto używać
splice():Metoda
sort() sortuje elementy tablicy na miejscu i zwraca posortowaną tablicę:1// Lista dinozaurów do karmienia
2const feedingList = ["Velociraptor", "T-Rex", "Dilophosaurus", "Gallimimus", "Compsognathus"];
3
4// Sortowanie alfabetyczne
5feedingList.sort();
6console.log(`Lista karmienia (alfabetycznie): ${feedingList}`);
7// ["Compsognathus", "Dilophosaurus", "Gallimimus", "T-Rex", "Velociraptor"]
8
9// Tablica z wymiarami dinozaurów (w cm)
10const dinoSizes = [1200, 300, 800, 2000, 40];
11
12// Domyślne sortowanie traktuje liczby jako stringi - to nie zadziała poprawnie!
13dinoSizes.sort();
14console.log("Niepoprawnie posortowane wymiary:", dinoSizes);
15// Prawdopodobnie: [1200, 2000, 300, 40, 800] - niepoprawnie!
16
17// Właściwe sortowanie liczb z funkcją porównującą
18dinoSizes.sort((a, b) => a - b);
19console.log("Poprawnie posortowane wymiary (rosnąco):", dinoSizes);
20// [40, 300, 800, 1200, 2000]
21
22// Sortowanie malejąco
23dinoSizes.sort((a, b) => b - a);
24console.log("Wymiary posortowane malejąco:", dinoSizes);
25// [2000, 1200, 800, 300, 40]1// Dane dinozaurów do karmienia
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// Sortowanie według priorytetu karmienia
10dinosaurs.sort((a, b) => a.priority - b.priority);
11console.log("Kolejność karmienia według priorytetu:");
12dinosaurs.forEach(dino => console.log(`${dino.name} (priorytet: ${dino.priority})`));
13
14// Sortowanie według wagi (od najcięższego)
15dinosaurs.sort((a, b) => b.weight - a.weight);
16console.log("
17Kolejność według wagi (od najcięższego):");
18dinosaurs.forEach(dino => console.log(`${dino.name} (${dino.weight} kg)`));
19
20// Sortowanie alfabetycznie według nazwy
21dinosaurs.sort((a, b) => a.name.localeCompare(b.name));
22console.log("
23Dinozaury alfabetycznie:");
24dinosaurs.forEach(dino => console.log(`${dino.name}`));Metoda
sort() przyjmuje opcjonalną funkcję porównującą, która powinna zwrócić:Kiedy warto używać
sort():Metoda
reverse() odwraca kolejność elementów w tablicy i zwraca odwróconą tablicę:1// Lista dinozaurów od najstarszego do najmłodszego
2const dinosaursByAge = ["Brachiosaurus", "Stegosaurus", "Triceratops", "Velociraptor", "T-Rex"];
3
4// Odwrócenie kolejności, aby uzyskać listę od najmłodszego do najstarszego
5dinosaursByAge.reverse();
6console.log("Od najmłodszego do najstarszego:", dinosaursByAge);
7// ["T-Rex", "Velociraptor", "Triceratops", "Stegosaurus", "Brachiosaurus"]
8
9// Często używana w połączeniu z sort()
10const dinoHeights = [500, 900, 200, 1200, 350];
11// Sortowanie malejąco poprzez sortowanie rosnąco + odwrócenie
12dinoHeights.sort((a, b) => a - b).reverse();
13console.log("Wysokości malejąco:", dinoHeights);
14// [1200, 900, 500, 350, 200]Kiedy warto używać
reverse():Metoda
fill() wypełnia wszystkie elementy tablicy od indeksu startowego do indeksu końcowego (nie wliczając) określoną wartością:1// Przygotowanie tablicy na pomiary temperatury dinozaurów (10 pomiarów)
2const temperatures = new Array(10);
3
4// Wypełnienie domyślną wartością (38.5 stopni Celsjusza)
5temperatures.fill(38.5);
6console.log(`Domyślne temperatury: ${temperatures}`);
7// [38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5, 38.5]
8
9// Wypełnienie tylko części tablicy
10temperatures.fill(39.2, 2, 5); // Od indeksu 2 (włącznie) do 5 (wyłączając)
11console.log(`Zaktualizowane temperatury: ${temperatures}`);
12// [38.5, 38.5, 39.2, 39.2, 39.2, 38.5, 38.5, 38.5, 38.5, 38.5]
13
14// Użycie z nową tablicą i indeksami ujemnymi (liczone od końca)
15const feedingSchedule = new Array(7).fill("Standardowe");
16feedingSchedule.fill("Zwiększona porcja", -3); // Ostatnie 3 dni
17console.log(`Plan karmienia na tydzień: ${feedingSchedule}`);
18// ["Standardowe", "Standardowe", "Standardowe", "Standardowe", "Zwiększona porcja", "Zwiększona porcja", "Zwiększona porcja"]Kiedy warto używać
fill():Teraz połączmy poznane metody, aby rozwiązać bardziej praktyczne scenariusze w naszym Parku Jurajskim:
1// System zarządzania karmą dla dinozaurów
2const feedingSystem = {
3 // Stan systemu
4 foodInventory: [],
5 feedingQueue: [],
6 feedingHistory: [],
7
8 // Dodawanie nowego zapasu karmy
9 addFoodSupply: function(type, quantity, expirationDate) {
10 const supply = { type, quantity, expirationDate, addedOn: new Date() };
11 this.foodInventory.push(supply);
12
13 // Sortowanie według daty ważności (najkrótszej)
14 this.foodInventory.sort((a, b) =>
15 new Date(a.expirationDate) - new Date(b.expirationDate)
16 );
17
18 console.log(`Dodano ${quantity}kg karmy typu "${type}" do zapasów.`);
19 return supply;
20 },
21
22 // Dodawanie dinozaura do kolejki karmienia
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 // Dodaj na początek kolejki
35 this.feedingQueue.unshift(feedingRequest);
36 } else {
37 // Dodaj na koniec kolejki
38 this.feedingQueue.push(feedingRequest);
39 }
40
41 console.log(`Zaplanowano karmienie dla ${dinoName} (priorytet: ${priority})`);
42 return this.feedingQueue.length;
43 },
44
45 // Pobieranie następnego dinozaura do nakarmienia
46 getNextDinoToFeed: function() {
47 if (this.feedingQueue.length === 0) {
48 console.log("Wszystkie dinozaury nakarmione. Kolejka pusta.");
49 return null;
50 }
51
52 const nextFeeding = this.feedingQueue.shift();
53 console.log(`Następny do karmienia: ${nextFeeding.dinoName}`);
54 return nextFeeding;
55 },
56
57 // Wydawanie karmy ze spichlerza
58 dispenseFoodForDino: function(dinoFeeding) {
59 const { foodType, quantity, dinoName } = dinoFeeding;
60
61 // Szukanie odpowiedniego zapasu karmy
62 let remainingQuantity = quantity;
63 const usedSupplies = [];
64
65 // Iterujemy od najstarszego zapasu (który wygasa najszybciej)
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 // Ile możemy pobrać z tego zapasu
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 // Jeśli zapas się skończył, usuwamy go z inwentarza
82 if (supply.quantity === 0) {
83 this.foodInventory.splice(i, 1);
84 i--; // Dostosuj indeks po usunięciu elementu
85 }
86 }
87 }
88
89 // Dodaj rekord do historii karmienia
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(`UWAGA: Brakuje ${remainingQuantity}kg karmy typu "${foodType}" dla ${dinoName}!`);
101 return false;
102 }
103
104 console.log(`Nakarmiono ${dinoName} używając ${quantity}kg karmy typu "${foodType}".`);
105 return feedingRecord;
106 },
107
108 // Przeprowadzenie pełnego procesu karmienia
109 processFeedingCycle: function(maxFeedings = 5) {
110 console.log("=== ROZPOCZĘCIE CYKLU KARMIENIA ===");
111 let feedingsProcessed = 0;
112
113 // Przetwarzamy określoną liczbę karmień lub dopóki kolejka się nie opróżni
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 // Jeśli nie udało się nakarmić, przenosimy dinozaura na koniec kolejki
122 this.feedingQueue.push({
123 ...nextDino,
124 priority: "high", // Podnosimy priorytet dla nienakarmionego dinozaura
125 scheduledAt: new Date()
126 });
127 console.log(`${nextDino.dinoName} przesunięty na koniec kolejki z wysokim priorytetem.`);
128 }
129
130 feedingsProcessed++;
131 }
132 }
133
134 console.log(`=== ZAKOŃCZENIE CYKLU KARMIENIA (przetworzono: ${feedingsProcessed}) ===`);
135 console.log(`Pozostało w kolejce: ${this.feedingQueue.length} dinozaurów`);
136 return feedingsProcessed;
137 },
138
139 // Raportowanie stanu zapasów
140 reportInventoryStatus: function() {
141 console.log("=== RAPORT STANU ZAPASÓW ===");
142
143 if (this.foodInventory.length === 0) {
144 console.log("Magazyn jest pusty! Zamów nowe zapasy karmy!");
145 return { isEmpty: true, totalQuantity: 0, types: [] };
146 }
147
148 // Grupowanie zapasów według typu
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 // Obliczanie łącznej ilości
158 const totalQuantity = Object.values(inventory).reduce((sum, qty) => sum + qty, 0);
159
160 console.log(`Łączna ilość karmy: ${totalQuantity}kg`);
161 Object.entries(inventory).forEach(([type, qty]) => {
162 console.log(`- ${type}: ${qty}kg`);
163 });
164
165 // Sprawdzenie zapasów, które wkrótce wygasną (w ciągu 3 dni)
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("
176Zapasy wygasające w ciągu 3 dni:");
177 expiringSupplies.forEach(supply => {
178 console.log(`- ${supply.quantity}kg ${supply.type} (wygasa: ${supply.expirationDate})`);
179 });
180 }
181
182 return {
183 isEmpty: false,
184 totalQuantity,
185 types: Object.keys(inventory),
186 inventory,
187 expiringSupplies
188 };
189 }
190};
191
192// Demonstracja działania systemu
193console.log("=== DEMONSTRACJA SYSTEMU ZARZĄDZANIA KARMĄ ===");
194
195// 1. Dodawanie zapasów karmy
196feedingSystem.addFoodSupply("Mięso", 500, "2023-07-15");
197feedingSystem.addFoodSupply("Rośliny", 800, "2023-07-10");
198feedingSystem.addFoodSupply("Ryby", 200, "2023-07-05");
199feedingSystem.addFoodSupply("Mięso", 300, "2023-07-20");
200
201// 2. Planowanie karmienia
202feedingSystem.scheduleDinoFeeding("TRX-01", "Rex", "Mięso", 150, "high");
203feedingSystem.scheduleDinoFeeding("VEL-02", "Blue", "Mięso", 50, "normal");
204feedingSystem.scheduleDinoFeeding("TRCP-03", "Trixie", "Rośliny", 120, "normal");
205feedingSystem.scheduleDinoFeeding("BRCH-04", "Bronty", "Rośliny", 250, "normal");
206feedingSystem.scheduleDinoFeeding("STEG-05", "Spike", "Rośliny", 100, "high");
207
208// 3. Raport stanu zapasów przed karmieniem
209feedingSystem.reportInventoryStatus();
210
211// 4. Przeprowadzanie cyklu karmienia
212feedingSystem.processFeedingCycle(3); // Przetwarzamy tylko 3 karmienia
213
214// 5. Sprawdzamy stan zapasów po karmieniu
215feedingSystem.reportInventoryStatus();
216
217// 6. Dokończenie cyklu karmienia
218feedingSystem.processFeedingCycle(5); // Przetwarzamy pozostałe karmienia
219
220// 7. Sprawdzamy stan zapasów po pełnym cyklu
221feedingSystem.reportInventoryStatus();1// System zarządzania zespołami pracowników Parku Jurajskiego
2const staffManagementSystem = {
3 // Dane systemu
4 departments: [
5 { id: "OPS", name: "Operacje" },
6 { id: "SCI", name: "Badania naukowe" },
7 { id: "SEC", name: "Bezpieczeństwo" },
8 { id: "VET", name: "Weterynaria" },
9 { id: "MAINT", name: "Konserwacja" }
10 ],
11 staff: [],
12 teams: [],
13
14 // Dodawanie nowego pracownika
15 addStaffMember: function(name, role, skills, departmentId) {
16 // Sprawdzenie, czy dział istnieje
17 const department = this.departments.find(dept => dept.id === departmentId);
18 if (!department) {
19 console.log(`Błąd: Dział o ID "${departmentId}" nie istnieje.`);
20 return null;
21 }
22
23 // Generowanie ID pracownika
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(`Dodano pracownika: ${name} (${role}) do działu ${department.name}`);
38
39 return staffMember;
40 },
41
42 // Utworzenie nowego zespołu
43 createTeam: function(name, mission, leaderId) {
44 // Sprawdzenie, czy leader istnieje
45 const leader = this.staff.find(person => person.id === leaderId);
46 if (!leader) {
47 console.log(`Błąd: Pracownik o ID "${leaderId}" nie istnieje.`);
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(`Utworzono zespół: ${name} (misja: ${mission}), prowadzący: ${leader.name}`);
66
67 return team;
68 },
69
70 // Dodawanie pracownika do zespołu
71 addMemberToTeam: function(teamId, memberId) {
72 // Znajdź zespół
73 const teamIndex = this.teams.findIndex(team => team.id === teamId);
74 if (teamIndex === -1) {
75 console.log(`Błąd: Zespół o ID "${teamId}" nie istnieje.`);
76 return false;
77 }
78
79 // Znajdź pracownika
80 const member = this.staff.find(person => person.id === memberId);
81 if (!member) {
82 console.log(`Błąd: Pracownik o ID "${memberId}" nie istnieje.`);
83 return false;
84 }
85
86 // Sprawdź, czy pracownik już jest w zespole
87 if (this.teams[teamIndex].members.includes(memberId)) {
88 console.log(`${member.name} już jest członkiem zespołu ${this.teams[teamIndex].name}.`);
89 return false;
90 }
91
92 // Dodaj pracownika do zespołu
93 this.teams[teamIndex].members.push(memberId);
94 console.log(`Dodano ${member.name} do zespołu ${this.teams[teamIndex].name}.`);
95
96 return true;
97 },
98
99 // Usunięcie pracownika z zespołu
100 removeMemberFromTeam: function(teamId, memberId) {
101 // Znajdź zespół
102 const teamIndex = this.teams.findIndex(team => team.id === teamId);
103 if (teamIndex === -1) {
104 console.log(`Błąd: Zespół o ID "${teamId}" nie istnieje.`);
105 return false;
106 }
107
108 // Sprawdź, czy pracownik jest liderem
109 if (this.teams[teamIndex].leaderId === memberId) {
110 console.log(`Błąd: Nie można usunąć lidera zespołu. Najpierw zmień lidera.`);
111 return false;
112 }
113
114 // Znajdź indeks pracownika w zespole
115 const memberIndex = this.teams[teamIndex].members.indexOf(memberId);
116 if (memberIndex === -1) {
117 console.log(`Pracownik nie jest członkiem zespołu ${this.teams[teamIndex].name}.`);
118 return false;
119 }
120
121 // Znajdź pracownika dla celów informacyjnych
122 const member = this.staff.find(person => person.id === memberId);
123
124 // Usuń pracownika z zespołu
125 this.teams[teamIndex].members.splice(memberIndex, 1);
126 console.log(`Usunięto ${member ? member.name : memberId} z zespołu ${this.teams[teamIndex].name}.`);
127
128 return true;
129 },
130
131 // Zmiana lidera zespołu
132 changeTeamLeader: function(teamId, newLeaderId) {
133 // Znajdź zespół
134 const teamIndex = this.teams.findIndex(team => team.id === teamId);
135 if (teamIndex === -1) {
136 console.log(`Błąd: Zespół o ID "${teamId}" nie istnieje.`);
137 return false;
138 }
139
140 // Sprawdź, czy nowy lider istnieje
141 const newLeader = this.staff.find(person => person.id === newLeaderId);
142 if (!newLeader) {
143 console.log(`Błąd: Pracownik o ID "${newLeaderId}" nie istnieje.`);
144 return false;
145 }
146
147 // Sprawdź, czy nowy lider jest członkiem zespołu
148 if (!this.teams[teamIndex].members.includes(newLeaderId)) {
149 // Dodaj nowego lidera do zespołu, jeśli jeszcze nie jest członkiem
150 this.teams[teamIndex].members.push(newLeaderId);
151 console.log(`${newLeader.name} został dodany do zespołu jako nowy lider.`);
152 }
153
154 // Zapisz informacje o starym liderze dla komunikatu
155 const oldLeaderId = this.teams[teamIndex].leaderId;
156 const oldLeader = this.staff.find(person => person.id === oldLeaderId);
157
158 // Zaktualizuj lidera
159 this.teams[teamIndex].leaderId = newLeaderId;
160 this.teams[teamIndex].leaderName = newLeader.name;
161
162 console.log(`Lider zespołu ${this.teams[teamIndex].name} zmieniony z ${oldLeader.name} na ${newLeader.name}.`);
163 return true;
164 },
165
166 // Rozwiązanie zespołu
167 deactivateTeam: function(teamId, reason) {
168 // Znajdź zespół
169 const teamIndex = this.teams.findIndex(team => team.id === teamId);
170 if (teamIndex === -1) {
171 console.log(`Błąd: Zespół o ID "${teamId}" nie istnieje.`);
172 return false;
173 }
174
175 // Zapisanie stanu przed modyfikacją
176 const teamName = this.teams[teamIndex].name;
177
178 // Aktualizacja statusu zespołu
179 this.teams[teamIndex].status = "inactive";
180 this.teams[teamIndex].deactivatedAt = new Date().toISOString().split('T')[0];
181 this.teams[teamIndex].deactivationReason = reason || "Nieokreślony";
182
183 console.log(`Zespół ${teamName} został dezaktywowany. Powód: ${this.teams[teamIndex].deactivationReason}`);
184 return true;
185 },
186
187 // Generowanie raportu o zespołach
188 generateTeamsReport: function(includeInactive = false) {
189 console.log("=== RAPORT O ZESPOŁACH PARKU JURAJSKIEGO ===");
190
191 // Filtruj zespoły według statusu, jeśli nie uwzględniamy nieaktywnych
192 const teamsToReport = includeInactive
193 ? this.teams
194 : this.teams.filter(team => team.status === "active");
195
196 if (teamsToReport.length === 0) {
197 console.log("Brak zespołów do wyświetlenia.");
198 return { teams: [] };
199 }
200
201 // Przygotowanie danych do raportu
202 const teamsData = teamsToReport.map(team => {
203 // Pobierz pełne informacje o członkach
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: "Nieznany", role: "Nieznany", 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 // Sortuj zespoły - aktywne pierwsze, potem według daty utworzenia
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 // Wyświetl podsumowanie
237 console.log(`Liczba zespołów: ${teamsData.length}`);
238 console.log(`Aktywne zespoły: ${teamsData.filter(t => t.status === "active").length}`);
239 if (includeInactive) {
240 console.log(`Nieaktywne zespoły: ${teamsData.filter(t => t.status === "inactive").length}`);
241 }
242
243 // Wyświetl szczegóły dla każdego zespołu
244 teamsData.forEach(team => {
245 console.log(`
246${team.id}: ${team.name} (Status: ${team.status})`);
247 console.log(`Misja: ${team.mission}`);
248 console.log(`Lider: ${team.leader ? team.leader.name : 'Brak'} (${team.leader ? team.leader.role : ''})`);
249 console.log(`Liczba członków: ${team.memberCount}`);
250 console.log("Członkowie:");
251 team.members.forEach(member => {
252 console.log(` - ${member.name} (${member.role})${member.isLeader ? ' [LIDER]' : ''}`);
253 });
254
255 if (team.status === "inactive") {
256 console.log(`Dezaktywowano: ${team.deactivatedAt}`);
257 console.log(`Powód: ${team.deactivationReason}`);
258 }
259 });
260
261 return { teams: teamsData };
262 },
263
264 // Reorganizacja zespołów
265 reorganizeTeams: function(fromTeamId, toTeamId, memberIds, dissolveSourceTeam = false) {
266 // Sprawdź, czy zespoły istnieją
267 const fromTeamIndex = this.teams.findIndex(team => team.id === fromTeamId);
268 const toTeamIndex = this.teams.findIndex(team => team.id === toTeamId);
269
270 if (fromTeamIndex === -1 || toTeamIndex === -1) {
271 console.log(`Błąd: Jeden lub oba zespoły nie istnieją.`);
272 return false;
273 }
274
275 // Sprawdź, czy zespoły są aktywne
276 if (this.teams[fromTeamIndex].status !== "active" || this.teams[toTeamIndex].status !== "active") {
277 console.log(`Błąd: Zespoły muszą być aktywne, aby je reorganizować.`);
278 return false;
279 }
280
281 // Jeśli nie podano konkretnych członków, przenieś wszystkich (oprócz lidera)
282 const membersToMove = memberIds ||
283 this.teams[fromTeamIndex].members.filter(id => id !== this.teams[fromTeamIndex].leaderId);
284
285 // Przenieś członków
286 for (const memberId of membersToMove) {
287 // Sprawdź, czy pracownik jest częścią źródłowego zespołu
288 if (!this.teams[fromTeamIndex].members.includes(memberId)) {
289 console.log(`Błąd: Pracownik o ID ${memberId} nie jest członkiem zespołu źródłowego.`);
290 continue;
291 }
292
293 // Sprawdź, czy pracownik nie jest liderem (jeśli nie chcemy przenosić wszystkich)
294 if (memberIds && memberId === this.teams[fromTeamIndex].leaderId) {
295 console.log(`Nie można przenieść lidera zespołu. Najpierw zmień lidera.`);
296 continue;
297 }
298
299 // Sprawdź, czy pracownik już jest częścią docelowego zespołu
300 if (this.teams[toTeamIndex].members.includes(memberId)) {
301 console.log(`Pracownik o ID ${memberId} już jest członkiem zespołu docelowego.`);
302 continue;
303 }
304
305 // Usuń z pierwotnego zespołu
306 const fromIndex = this.teams[fromTeamIndex].members.indexOf(memberId);
307 this.teams[fromTeamIndex].members.splice(fromIndex, 1);
308
309 // Dodaj do nowego zespołu
310 this.teams[toTeamIndex].members.push(memberId);
311
312 // Znajdź nazwę pracownika dla logów
313 const member = this.staff.find(person => person.id === memberId);
314 console.log(`Przeniesiono ${member ? member.name : memberId} z zespołu ${this.teams[fromTeamIndex].name} do ${this.teams[toTeamIndex].name}`);
315 }
316
317 // Jeśli wybrano rozwiązanie źródłowego zespołu i nie ma już członków
318 if (dissolveSourceTeam || this.teams[fromTeamIndex].members.length === 0) {
319 this.deactivateTeam(fromTeamId, "Reorganizacja - zespół przeniesiony");
320 }
321
322 return true;
323 }
324};
325
326// Demonstracja działania systemu zarządzania zespołami
327console.log("=== DEMONSTRACJA SYSTEMU ZARZĄDZANIA ZESPOŁAMI ===");
328
329// 1. Dodawanie pracowników
330const owen = staffManagementSystem.addStaffMember("Owen Grady", "Trener dinozaurów", ["Zachowania zwierząt", "Tresura", "Pierwsza pomoc"], "OPS");
331const claire = staffManagementSystem.addStaffMember("Claire Dearing", "Dyrektor operacyjny", ["Zarządzanie", "Marketing", "Administracja"], "OPS");
332const dr_wu = staffManagementSystem.addStaffMember("Dr. Henry Wu", "Główny genetyk", ["Genetyka", "Bioinżynieria", "Klonowanie"], "SCI");
333const barry = staffManagementSystem.addStaffMember("Barry", "Asystent trenera", ["Tresura", "Opieka nad zwierzętami"], "OPS");
334const lowery = staffManagementSystem.addStaffMember("Lowery Cruthers", "Technik systemów", ["IT", "Monitoring", "Komunikacja"], "SEC");
335const vivian = staffManagementSystem.addStaffMember("Vivian Krill", "Koordynator bezpieczeństwa", ["Bezpieczeństwo", "Komunikacja", "Zarządzanie kryzysowe"], "SEC");
336const muldoon = staffManagementSystem.addStaffMember("Robert Muldoon", "Specjalista ds. bezpieczeństwa", ["Broń", "Bezpieczeństwo", "Tropienie"], "SEC");
337const malcolm = staffManagementSystem.addStaffMember("Dr. Ian Malcolm", "Matematyk", ["Teoria chaosu", "Analiza ryzyka", "Modelowanie"], "SCI");
338const sattler = staffManagementSystem.addStaffMember("Dr. Ellie Sattler", "Paleobotanik", ["Botanika", "Paleontologia", "Ekologia"], "SCI");
339const harding = staffManagementSystem.addStaffMember("Dr. Gerry Harding", "Weterynarz", ["Weterynaria", "Zoologia", "Medycyna"], "VET");
340
341// 2. Tworzenie zespołów
342const raptorTeam = staffManagementSystem.createTeam("Zespół Velociraptor", "Tresura i opieka nad Velociraptorami", owen.id);
343staffManagementSystem.addMemberToTeam(raptorTeam.id, barry.id);
344
345const securityTeam = staffManagementSystem.createTeam("Zespół Bezpieczeństwa", "Zapewnienie bezpieczeństwa w parku", muldoon.id);
346staffManagementSystem.addMemberToTeam(securityTeam.id, vivian.id);
347staffManagementSystem.addMemberToTeam(securityTeam.id, lowery.id);
348
349const scienceTeam = staffManagementSystem.createTeam("Zespół Naukowy", "Badania naukowe i rozwój", dr_wu.id);
350staffManagementSystem.addMemberToTeam(scienceTeam.id, malcolm.id);
351staffManagementSystem.addMemberToTeam(scienceTeam.id, sattler.id);
352
353// 3. Raport o zespołach
354staffManagementSystem.generateTeamsReport();
355
356// 4. Reorganizacja zespołów
357console.log("
358=== REORGANIZACJA ZESPOŁÓW ===");
359
360// Tworzenie nowego zespołu zarządzania kryzysowego
361const crisisTeam = staffManagementSystem.createTeam("Zespół Zarządzania Kryzysowego", "Reagowanie na sytuacje kryzysowe", claire.id);
362
363// Przenoszenie członków z innych zespołów
364staffManagementSystem.reorganizeTeams(securityTeam.id, crisisTeam.id, [vivian.id]);
365staffManagementSystem.addMemberToTeam(crisisTeam.id, malcolm.id); // Dodajemy Malcolma jako doradcę ds. ryzyka
366staffManagementSystem.addMemberToTeam(crisisTeam.id, harding.id); // Dodajemy weterynarza
367
368// Zmiana lidera zespołu naukowego
369staffManagementSystem.changeTeamLeader(scienceTeam.id, sattler.id);
370
371// Dezaktywacja jednego zespołu
372staffManagementSystem.deactivateTeam(raptorTeam.id, "Projekt zawieszony - incydent z raptorami");
373
374// 5. Finalny raport o zespołach (z uwzględnieniem nieaktywnych)
375staffManagementSystem.generateTeamsReport(true);W tym module poznaliśmy podstawowe metody modyfikacji tablic w JavaScript:
Umiejętność efektywnego wykorzystania tych metod jest kluczowa przy pracy z danymi w JavaScript. Pozwalają one na zarządzanie kolekcjami, implementowanie struktur danych (takich jak stosy i kolejki) oraz efektywną manipulację danymi.
Warto pamiętać, że powyższe metody modyfikują oryginalną tablicę (z wyjątkiem przypadków, gdy tworzymy kopię przed ich zastosowaniem). W następnym module poznamy metody tablic, które nie modyfikują oryginału, ale zwracają nową tablicę lub wartość.