Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Podstawowe metody tablic w JavaScript

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.

Modyfikacja tablic - metody zmieniające tablicę

Najpierw przyjrzyjmy się metodom, które modyfikują oryginalną tablicę. Są to tak zwane metody mutujące (ang. mutating methods).

1. push() - dodawanie elementów na końcu tablicy

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}`); // 5

Kiedy warto używać

push()
:

  • Gdy potrzebujesz dodać element(y) na końcu tablicy
  • Gdy chcesz śledzić nową długość tablicy po dodaniu elementów
  • Gdy kolejność elementów jest istotna, a nowy element powinien znaleźć się na końcu

2. pop() - usuwanie ostatniego elementu

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()
:

  • Gdy potrzebujesz usunąć ostatni element z tablicy
  • Gdy potrzebujesz pobrać wartość usuwanego elementu
  • Implementując struktury danych typu stos (LIFO - Last In, First Out)

3. unshift() - dodawanie elementów na początku

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}`); // 5

Kiedy warto używać

unshift()
:

  • Gdy chcesz dodać element na początek tablicy
  • Implementując kolejki priorytetowe, gdzie elementy z wyższym priorytetem idą na początek
  • Gdy potrzebujesz śledzić nową długość tablicy

4. shift() - usuwanie pierwszego elementu

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()
:

  • Gdy potrzebujesz usunąć i pobrać pierwszy element tablicy
  • Implementując kolejki (FIFO - First In, First Out)
  • Przetwarzając elementy w kolejności ich dodania

5. splice() - modyfikacja elementów w dowolnym miejscu

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ęcia
  • item1, item2, ...
    : (opcjonalnie) elementy do dodania

5.1. Usuwanie elementów za pomocą splice()

1// 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"]

5.2. Zastępowanie elementów za pomocą splice()

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"]

5.3. Dodawanie elementów bez usuwania

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()
:

  • Gdy potrzebujesz modyfikować tablicę w określonym miejscu, a nie tylko na końcu czy początku
  • Gdy potrzebujesz usunąć i/lub dodać elementy jednocześnie
  • Gdy chcesz zastąpić sekcję tablicy nowymi wartościami

6. sort() - sortowanie tablicy

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]

Sortowanie obiektów

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ć:

  • Wartość ujemną, jeśli a powinno być przed b
  • Zero, jeśli a i b są równoważne pod względem sortowania
  • Wartość dodatnią, jeśli a powinno być po b

Kiedy warto używać

sort()
:

  • Gdy potrzebujesz uporządkować elementy tablicy według określonego kryterium
  • Gdy pracujesz z listami, które muszą być prezentowane w określonej kolejności
  • Gdy implementujesz funkcjonalność sortowania w aplikacji

7. reverse() - odwrócenie kolejności tablicy

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()
:

  • Gdy potrzebujesz odwrócić kolejność elementów w tablicy
  • Gdy chcesz zmienić porządek z rosnącego na malejący (lub odwrotnie) po sortowaniu
  • Gdy implementujesz funkcjonalność "odwróć kolejność" w interfejsie użytkownika

8. fill() - wypełnianie tablicy wartością

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()
:

  • Gdy tworzysz nową tablicę i potrzebujesz wypełnić ją określoną wartością początkową
  • Gdy potrzebujesz zastąpić wszystkie lub niektóre wartości w istniejącej tablicy
  • Gdy inicjalizujesz tablice do przechowywania danych z domyślnymi wartościami

Zastosowanie podstawowych metod tablic w praktyce

Teraz połączmy poznane metody, aby rozwiązać bardziej praktyczne scenariusze w naszym Parku Jurajskim:

Przykład 1: System zarządzania karmą dla dinozaurów

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();

Przykład 2: Zarządzanie zespołami pracowników parku

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);

Podsumowanie

W tym module poznaliśmy podstawowe metody modyfikacji tablic w JavaScript:

  1. push() - dodaje elementy na końcu tablicy
  2. pop() - usuwa i zwraca ostatni element tablicy
  3. unshift() - dodaje elementy na początku tablicy
  4. shift() - usuwa i zwraca pierwszy element tablicy
  5. splice() - dodaje, usuwa lub zastępuje elementy w dowolnym miejscu tablicy
  6. sort() - sortuje elementy tablicy
  7. reverse() - odwraca kolejność elementów w tablicy
  8. fill() - wypełnia elementy tablicy określoną wartością

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ść.

Vai a CodeWorlds