Witaj ponownie w centrum dowodzenia Parku Jurajskiego! W tym module poznałeś funkcje, tablice, zasięg zmiennych, hoisting, słowo kluczowe
this, obiekty i prototypy. Teraz nadszedł czas, aby połączyć tę wiedzę w jeden, zintegrowany System Monitorowania Dinozaurów - serce operacyjne całego parku.Wyobraź sobie centralną konsolę, na której operatorzy parku śledzą w czasie rzeczywistym lokalizację, stan zdrowia i zachowanie każdego dinozaura. Czujniki rozmieszczone po całym parku przesyłają dane, które nasz system musi przetwarzać, filtrować i analizować. Bez sprawnego systemu monitorowania, park szybko wymknąłby się spod kontroli - tak jak w filmie!
W tym projekcie stworzysz kompletny system, który wykorzystuje funkcje strzałkowe do przetwarzania danych, metody tablicowe do filtrowania i transformacji, funkcje wyższego rzędu do elastycznej logiki, a obiekty do modelowania encji parku.
Zbudujesz system monitorowania, który:
Pierwszym krokiem jest stworzenie bazy danych parku. Każdy dinozaur jest obiektem z właściwościami, a cała populacja przechowywana jest w tablicy.
1// Baza danych dinozaurów parku
2const dinosaurs = [
3 {
4 id: 1,
5 name: "Rex",
6 species: "Tyrannosaurus Rex",
7 weight: 8500,
8 diet: "carnivore",
9 enclosure: "A-1",
10 isHealthy: true,
11 heartRate: 72,
12 lastFed: "2024-03-15 08:00"
13 },
14 {
15 id: 2,
16 name: "Tricia",
17 species: "Triceratops",
18 weight: 6200,
19 diet: "herbivore",
20 enclosure: "B-3",
21 isHealthy: true,
22 heartRate: 55,
23 lastFed: "2024-03-15 07:30"
24 },
25 {
26 id: 3,
27 name: "Blue",
28 species: "Velociraptor",
29 weight: 75,
30 diet: "carnivore",
31 enclosure: "C-2",
32 isHealthy: false,
33 heartRate: 110,
34 lastFed: "2024-03-14 18:00"
35 },
36 {
37 id: 4,
38 name: "Dippy",
39 species: "Diplodocus",
40 weight: 12000,
41 diet: "herbivore",
42 enclosure: "D-1",
43 isHealthy: true,
44 heartRate: 40,
45 lastFed: "2024-03-15 06:00"
46 },
47 {
48 id: 5,
49 name: "Spike",
50 species: "Stegosaurus",
51 weight: 3500,
52 diet: "herbivore",
53 enclosure: "B-2",
54 isHealthy: true,
55 heartRate: 48,
56 lastFed: "2024-03-15 07:00"
57 }
58];
59
60// Dodawanie nowego dinozaura do bazy
61const addDinosaur = (name, species, weight, diet, enclosure) => {
62 const newId = dinosaurs.length + 1;
63 const newDino = {
64 id: newId,
65 name,
66 species,
67 weight,
68 diet,
69 enclosure,
70 isHealthy: true,
71 heartRate: 60,
72 lastFed: new Date().toISOString()
73 };
74 dinosaurs.push(newDino);
75 console.log("Zarejestrowano:", newDino.name, "(" + newDino.species + ")");
76 return newDino;
77};
78
79addDinosaur("Echo", "Velociraptor", 68, "carnivore", "C-2");
80console.log("Łączna liczba dinozaurów:", dinosaurs.length);System musi umożliwiać szybkie filtrowanie populacji według różnych kryteriów. Tu wykorzystasz
filter, map, reduce i find.1// Filtrowanie drapieżników za pomocą filter
2const carnivores = dinosaurs.filter(dino => dino.diet === "carnivore");
3console.log("Drapieżniki:", carnivores.map(d => d.name));
4
5// Filtrowanie chorych dinozaurów
6const unhealthyDinos = dinosaurs.filter(dino => !dino.isHealthy);
7console.log("Wymagają leczenia:", unhealthyDinos.map(d => d.name));
8
9// Mapowanie - tworzenie raportu z imionami i wagami
10const weightReport = dinosaurs.map(dino => {
11 return {
12 name: dino.name,
13 weight: dino.weight,
14 category: dino.weight > 5000 ? "ciężki" : "lekki"
15 };
16});
17console.log("Raport wagowy:");
18weightReport.forEach(entry => {
19 console.log(" " + entry.name + ": " + entry.weight + " kg (" + entry.category + ")");
20});
21
22// Redukcja - obliczanie łącznej wagi wszystkich dinozaurów
23const totalWeight = dinosaurs.reduce((sum, dino) => sum + dino.weight, 0);
24console.log("Łączna waga populacji:", totalWeight, "kg");
25
26// Średnia waga
27const avgWeight = totalWeight / dinosaurs.length;
28console.log("Średnia waga:", Math.round(avgWeight), "kg");
29
30// Znajdowanie najcięższego dinozaura
31const heaviest = dinosaurs.reduce((max, dino) =>
32 dino.weight > max.weight ? dino : max
33);
34console.log("Najcięższy:", heaviest.name, "-", heaviest.weight, "kg");
35
36// find - szukanie konkretnego dinozaura
37const blue = dinosaurs.find(dino => dino.name === "Blue");
38console.log("Znaleziono:", blue ? blue.name + " w " + blue.enclosure : "nie znaleziono");
39
40// some i every - sprawdzanie warunków
41const allHealthy = dinosaurs.every(dino => dino.isHealthy);
42const anyUnhealthy = dinosaurs.some(dino => !dino.isHealthy);
43console.log("Wszystkie zdrowe:", allHealthy);
44console.log("Są chore dinozaury:", anyUnhealthy);System potrzebuje zestawu funkcji monitorujących z różnymi typami parametrów. Zwróć uwagę na zasięg zmiennych i różnicę między funkcjami zwykłymi a strzałkowymi w kontekście
this.1// Funkcja z parametrami domyślnymi
2function generateAlert(dinoName, alertType = "INFO", priority = "normal") {
3 const timestamp = new Date().toLocaleTimeString();
4 console.log("[" + timestamp + "] [" + alertType + "] [" + priority + "] " + dinoName);
5}
6
7generateAlert("Rex", "WARNING", "high");
8generateAlert("Tricia"); // użyje domyślnych wartości
9generateAlert("Blue", "DANGER"); // priority będzie "normal"
10
11// Funkcja z parametrem rest - rejestracja wielu zdarzeń
12const logEvents = (enclosure, ...events) => {
13 console.log("Wybieg " + enclosure + " - zarejestrowano " + events.length + " zdarzeń:");
14 events.forEach((event, index) => {
15 console.log(" " + (index + 1) + ". " + event);
16 });
17};
18
19logEvents("A-1", "Karmienie o 8:00", "Badanie weterynaryjne", "Aktywność ruchowa");
20logEvents("C-2", "Próba ucieczki!");
21
22// Obiekt monitora z metodami - this w kontekście
23const enclosureMonitor = {
24 sector: "A",
25 alertCount: 0,
26
27 // Metoda tradycyjna - this wskazuje na obiekt
28 checkFence: function() {
29 this.alertCount++;
30 console.log("Sprawdzanie ogrodzenia sektora " + this.sector +
31 " (alert #" + this.alertCount + ")");
32 },
33
34 // Metoda skrócona ES6
35 getStatus() {
36 return "Sektor " + this.sector + " - " + this.alertCount + " alertów";
37 }
38};
39
40enclosureMonitor.checkFence();
41enclosureMonitor.checkFence();
42console.log(enclosureMonitor.getStatus());
43
44// Zasięg zmiennych - blokowy vs funkcyjny
45function monitorHeartRates() {
46 const threshold = 100; // dostępna w całej funkcji
47
48 for (let i = 0; i < dinosaurs.length; i++) {
49 const dino = dinosaurs[i]; // dostępna tylko w tym bloku
50 if (dino.heartRate > threshold) {
51 let status = "PODWYŻSZONE"; // dostępna tylko w tym if
52 console.log(dino.name + ": tętno " + dino.heartRate + " - " + status);
53 }
54 }
55
56 // console.log(status); // BŁĄD! status nie istnieje poza blokiem if
57 // console.log(dino); // BŁĄD! dino nie istnieje poza pętlą for
58 console.log("Próg alertu:", threshold); // OK - threshold jest w zakresie funkcji
59}
60
61monitorHeartRates();W prawdziwym systemie monitorowania często musimy połączyć wiele operacji w łańcuch. Metody tablicowe świetnie się do tego nadają.
1// Łańcuch metod - raport bezpieczeństwa
2const securityReport = dinosaurs
3 .filter(dino => dino.diet === "carnivore") // tylko drapieżniki
4 .map(dino => ({ // transformacja danych
5 name: dino.name,
6 enclosure: dino.enclosure,
7 danger: dino.weight > 1000 ? "WYSOKIE" : "ŚREDNIE"
8 }))
9 .sort((a, b) => a.name.localeCompare(b.name)); // sortowanie
10
11console.log("=== RAPORT BEZPIECZEŃSTWA ===");
12securityReport.forEach(entry => {
13 console.log(entry.name + " [" + entry.enclosure + "] - zagrożenie: " + entry.danger);
14});
15
16// Grupowanie dinozaurów według diety za pomocą reduce
17const groupedByDiet = dinosaurs.reduce((groups, dino) => {
18 const key = dino.diet;
19 if (!groups[key]) {
20 groups[key] = [];
21 }
22 groups[key].push(dino.name);
23 return groups;
24}, {});
25
26console.log("=== PODZIAŁ WEDŁUG DIETY ===");
27console.log("Roślinożercy:", groupedByDiet.herbivore);
28console.log("Mięsożercy:", groupedByDiet.carnivore);
29
30// Funkcja wyższego rzędu - tworzenie filtrów
31function createFilter(property, value) {
32 return (dino) => dino[property] === value;
33}
34
35const isCarnivore = createFilter("diet", "carnivore");
36const isInSectorB = createFilter("enclosure", "B-3");
37
38const carnivoreDinos = dinosaurs.filter(isCarnivore);
39const sectorBDinos = dinosaurs.filter(isInSectorB);
40
41console.log("Mięsożercy:", carnivoreDinos.map(d => d.name));
42console.log("Sektor B-3:", sectorBDinos.map(d => d.name));
43
44// Statystyki populacji
45const stats = {
46 total: dinosaurs.length,
47 healthy: dinosaurs.filter(d => d.isHealthy).length,
48 unhealthy: dinosaurs.filter(d => !d.isHealthy).length,
49 avgHeartRate: Math.round(
50 dinosaurs.reduce((sum, d) => sum + d.heartRate, 0) / dinosaurs.length
51 ),
52 heaviest: dinosaurs.reduce((max, d) => d.weight > max.weight ? d : max).name,
53 lightest: dinosaurs.reduce((min, d) => d.weight < min.weight ? d : min).name
54};
55
56console.log("=== STATYSTYKI POPULACJI ===");
57console.log("Łącznie:", stats.total);
58console.log("Zdrowe:", stats.healthy);
59console.log("Chore:", stats.unhealthy);
60console.log("Średnie tętno:", stats.avgHeartRate, "bpm");
61console.log("Najcięższy:", stats.heaviest);
62console.log("Najlżejszy:", stats.lightest);Budując swój system monitorowania, zwróć uwagę na:
filter, map, reduce), a zwykłych dla metod obiektów, które potrzebują this...args) - idealny gdy liczba argumentów jest zmienna (np. lista zdarzeń)filter().map().sort() jest czytelniejsze niż zagnieżdżone pętlelet i const mają zasięg blokowy, var funkcyjny - wybieraj świadomiefilter, map, reduce tworzą nowe tablice, ale push, splice, sort modyfikują oryginałCzas wcielić się w rolę głównego operatora Parku Jurajskiego! Stwórz swój własny System Monitorowania w edytorze poniżej. Połącz tablice, funkcje, metody tablicowe i obiekty w jeden, działający system. Pamiętaj - każdy dinozaur w parku zależy od Twojego kodu. Jak mówił John Hammond: "Nie szczędziliśmy wydatków" - i Ty nie szczędź kodu!