Serwis używa plików cookies do analizy ruchu i poprawy działania. Szczegóły
EE.09-04-20.06-SGCzerwiec 2020 · 46 kroków · ok. 86 min · 33 kryteria z klucza
Rozwiązanie krok po kroku: Salon kosmetyczny z kalkulatorem zabiegów (Wersja podstawowa)
Aplikacja internetowa salonu kosmetycznego: baza egzamin1 zaimportowana z pliku i cztery zapytania - usługi tańsze niż 30 zł (WHERE), suma cen usług kosmetycznych (SUM), nowe konto bazy kosmetyczka (CREATE USER) i nadanie mu prawa przeglądania i wstawiania rekordów w jednej tabeli (GRANT). Do tego dwa zdjęcia przeskalowane z zachowaniem proporcji, dwie strony index.html i twarz.html z czterema blokami ułożonymi w dwie kolumny i stopką, style w styl.css z efektem :hover na obrazach oraz skrypt w JavaScript, który liczy cenę zabiegów zaznaczonych polami checkbox.
To arkusz EE.09 z czerwca 2020 - kwalifikacji formuły 2017, którą zastąpiła INF.03. Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypt jest napisany najprościej, polami i zdarzeniami z tabeli arkusza (getElementById, checked, onclick, innerHTML). Strony nie mają PHP, więc podgląd od kroku z HTML-em to działająca strona - pola i przycisk można klikać.
To jest wersja podstawowa. W zakładce „Nowoczesny kod (flex, addEventListener)” jest drugi sposób rozwiązania tego samego arkusza: semantyczne znaczniki w kontenerze flex, zmienne CSS, etykiety <label>, ceny zapisane przy polach w atrybutach data- i skrypt w osobnym pliku podpięty przez addEventListener - obie wersje są zgodne z kluczem.
Baza i zdjęcia pochodzą z oryginalnego archiwum CKE egzamin1.zip (załącznik do pobrania na stronie arkusza, hasło w treści zadania). Zapytania i zrzuty są policzone na MariaDB 10.4 - tej samej, która jest w XAMPP, a uprawnienia nowego konta sprawdzone logowaniem na nie. Działanie skryptu sprawdzone w Chrome dla wszystkich 16 kombinacji zaznaczeń.
Jak liczą się punkty. Klucz ma 33 kryteria (R.1.1 - R.5.4), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 25 punktów (75% z 33 to 24,75, zaokrąglone w górę) - można stracić 8 kryteriów i nadal zdać. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
Etap 1: Baza danych
Kroki 1-7 · po tym etapie masz 6 z 33 kryteriów (pkt)
Krok 1: Folder zdającego i archiwum egzamin1.zip
ok. 2 min
Polecenie z arkusza
Na pulpicie znajdziesz archiwum ZIP o nazwie egzamin1.zip zabezpieczone hasłem: Do{Rozp4kow4ni4}. Archiwum należy rozpakować. Na pulpicie konta Egzamin utwórz folder. Jako nazwy folderu użyj swojego numeru PESEL. Umieść w tym folderze rozpakowane pliki.
Na pulpicie tworzysz folder nazwany numerem PESEL - w tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora, Bartosz Bryniarski. Archiwum egzamin1.zip rozpakowujesz do tego folderu, podając hasło Do{Rozp4kow4ni4} - z klamrami, wielką literą D i R oraz cyframi 4 w miejscu liter „a”. W środku są trzy pliki: egzamin.sql, obraz1.jpg i obraz2.jpg.
Do tego folderu trafia wszystko, co powstanie: zrzuty, kwerendy.txt, strony, style i przeskalowane zdjęcia.
Typowe błędy
Hasło przepisuj znak po znaku - w czcionce arkusza łatwo pomylić { z (, a cyfrę 4 z literą A.
Krok 2: XAMPP i pusta baza egzamin1
ok. 2 min
Polecenie z arkusza
Uruchom usługi MySQL i Apache za pomocą XAMPP Control Panel. Za pomocą narzędzia phpMyAdmin wykonaj podane operacje na bazie danych: Utwórz bazę danych o nazwie egzamin1
W XAMPP Control PanelStart przy Apache i MySQL, potem http://localhost/phpmyadmin, Nowa, nazwa egzamin1 (z cyfrą 1 na końcu), Utwórz. Strony w tym zadaniu nie łączą się z bazą - baza służy do importu i czterech zapytań.
Krok 3: Import pliku egzamin.sql i zrzut egzamin.jpg
Kryteria:
R.1.1 Wykonano import tabel do bazy danych egzamin1 , czynność udokumentowano plikiem o nazwie egzamin w formacie JPEG. Zrzut zawiera cały obszar ekranu monitora z widocznym paskiem zadań
ok. 3 min
Polecenie z arkusza
Do bazy egzamin1 zaimportuj tabele z pliku egzamin.sql z rozpakowanego archiwum. Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie JPEG o nazwie egzamin, w folderze opisanym numerem PESEL. Nie kadruj zrzutu. Zrzut powinien obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel
Zaznacz bazę egzamin1, karta Import, Wybierz plik → egzamin.sql, Wykonaj. Plik tworzy sześć tabel, choć arkusz opisuje tylko dwie: kadra (5 pracowników) i uslugi (10 usług) oraz niepotrzebne w tym zadaniu matematycy, typy, uzytkownik i wyniki. Klucze główne i AUTO_INCREMENT ustawiają polecenia ALTER TABLE na końcu pliku.
Na zrzucie ma być widać zielony komunikat o sukcesie i tabele w lewym panelu. Zrzut całego ekranu z paskiem zadań zapisujesz jako egzamin.jpg - na przykład Print Screen, wklejenie do edytora grafiki i eksport do JPEG.
Typowe błędy
Zrzut importu ma być w JPEG, a zrzuty zapytań w PNG - pomylony format to strata punktu. Wykadrowanego zrzutu albo zrzutu bez paska zadań klucz nie ocenia.
Podgląd strony po tym kroku
Krok 4: Zapytanie 1: usługi tańsze niż 30 zł
Kryteria: ,
R.1.2 Zapisano plik tekstowy o nazwie kwerendy zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania
R.1.3 Utworzono zapytanie 1 wybierające jedynie pola nazwa i cena z tabeli uslugi dla usług, których cena jest niższa od 30 zł. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT nazwa, cena FROM uslugi WHERE cena < 30; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczne są jedynie trzy rekordy, jedynie pola nazwa i cena o wartościach: Masaz twarzy 20, Regulacja brwi 5, Henna 10
ok. 3 min
Polecenie z arkusza
Zapisz i wykonaj zapytania SQL działające na bazie egzamin1. Zapytania zapisz w pliku kwerendy.txt, w folderze z numerem PESEL. Wykonaj zrzuty ekranu przedstawiające wyniki działania kwerend. Zrzuty zapisz w formacie PNG i nadaj im nazwy kw1, kw2, kw3, kw4. Zrzuty powinny obejmować cały ekran monitora, z widocznym paskiem zadań. Zapytanie 1: wybierające jedynie pola nazwa i cena z tabeli uslugi dla usług, których cena jest niższa od 30 zł
Zaznacz bazę egzamin1 i otwórz kartę SQL:
SELECT nazwa, cena - tylko dwie kolumny; „jedynie” wyklucza SELECT *,
FROM uslugi,
WHERE cena < 30 - ostro mniejsze, bo arkusz mówi „niższa od 30 zł”; usługa za dokładnie 30 zł (Maska) się nie łapie.
Wynik: Masaz twarzy 20, Regulacja brwi 5 i Henna 10 - dokładnie te trzy rekordy wymienia klucz. Nazwy są bez polskich liter, bo tak zapisano je w pliku egzamin.sql. Zapytanie kopiujesz do nowego pliku kwerendy.txt, zrzut całego ekranu - do kw1.png.
Typowe błędy
cena <= 30 doda Maskę i Czesanie - pięć rekordów zamiast trzech to brak punktu.
kwerendy.txtTekstnowy plik
-- Zapytanie 1SELECT nazwa, cena FROM uslugi WHERE cena < 30;
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: suma cen usług kosmetycznych
Kryteria:
R.1.4 Utworzono zapytanie 2 liczące sumę ceny dla wszystkich usług kosmetycznych (rodzaj=1). W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT SUM(cena) FROM uslugi WHERE rodzaj=1; oraz wynik działania zapytania udokumentowano zrzutem, na którym widoczna jest jedynie wartość 180 wynikająca z wydanego zapytania 2
ok. 2 min
Polecenie z arkusza
Zapytanie 2: liczące sumę cen dla wszystkich usług kosmetycznych (rodzaj odpowiada usługom kosmetycznym)
Arkusz podaje znaczenie pola rodzaj: 1 - usługi kosmetyczne, 2 - fryzjerskie, 3 - inne.
SELECT SUM(cena) - funkcja SUM dodaje wartości kolumny ze wszystkich wierszy, które przeszły przez warunek,
FROM uslugi,
WHERE rodzaj = 1 - tylko usługi kosmetyczne.
Kosmetyczne są: Piling enzymatyczny 45, Maska 30, Regulacja brwi 5, Henna 10 i Paznokcie 90, razem 180 - ta wartość jest w kluczu. Masaż twarzy ma rodzaj 3 („inne”), więc do sumy nie wchodzi. Zrzut: kw2.png.
Typowe błędy
COUNT(cena) policzy usługi (5), a nie ich ceny. Zapytanie ma działać dla dowolnych danych - warunek po polu rodzaj, nie lista nazw usług.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT nazwa, cena FROM uslugi WHERE cena < 30;-- Zapytanie 2SELECT SUM(cena) FROM uslugi WHERE rodzaj = 1;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: konto kosmetyczka na localhost
Kryteria:
R.1.5 Utworzono zapytanie 3 tworzące użytkownika kosmetyczka na localhost z hasłem Kosmet34 W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER 'kosmetyczka'@'localhost' IDENTIFIED BY 'Kosmet34'; oraz wynik działania zapytania udokumentowano zrzutem wskazującym na pomyślne dodanie użytkownika kosmetyczka nie uznajemy za spełnione jeśli nie jest widoczne hasło (np wygenerowano z kreatora)
ok. 2 min
Polecenie z arkusza
Zapytanie 3: tworzące użytkownika kosmetyczka na localhost z hasłem Kosmet34
CREATE USER 'kosmetyczka'@'localhost' - nowe konto serwera bazy danych (nie wiersz w tabeli); część @'localhost' oznacza, że konto może się łączyć tylko z tego samego komputera, na którym działa serwer,
IDENTIFIED BY 'Kosmet34' - hasło konta; wielkość liter ma znaczenie.
phpMyAdmin odpowiada „MySQL zwrócił pusty wynik” - polecenie niczego nie wybiera, więc to znak sukcesu. Konto widać potem na karcie Konta użytkowników. Zrzut: kw3.png.
Typowe błędy
Klucz nie uznaje konta założonego kreatorem Dodaj konto użytkownika, bo na zrzucie nie widać hasła - zapytanie wpisz na karcie SQL. Drugie wykonanie zgłosi błąd #1396 - konto już istnieje.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT nazwa, cena FROM uslugi WHERE cena < 30;-- Zapytanie 2SELECT SUM(cena) FROM uslugi WHERE rodzaj = 1;-- Zapytanie 3CREATE USER 'kosmetyczka'@'localhost' IDENTIFIED BY 'Kosmet34';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: prawa SELECT i INSERT do tabeli uslugi
Kryteria:
R.1.6 Utworzono zapytanie 4 nadające prawa przeglądania danych i wstawiania rekordów do tabeli uslugi bazy egzamin1 dla użytkownika kosmetyczka. W pliku z kwerendami lub na zrzucie istnieje zapis np.: GRANT SELECT, INSERT ON egzamin1.uslugi TO 'kosmetyczka'@'localhost'; oraz wynik działania zapytania udokumentowano zrzutem wskazującym na pomyślne wykonanie zapytania 4
ok. 3 min
Polecenie z arkusza
Zapytanie 4: nadające prawa przeglądania danych i wstawiania rekordów do tabeli uslugi bazy egzamin1 dla użytkownika kosmetyczka
GRANT SELECT, INSERT - przeglądanie danych to SELECT, wstawianie rekordów to INSERT,
ON egzamin1.uslugi - zapis baza.tabela ogranicza prawa do jednej tabeli; egzamin1.* dałoby je do wszystkich sześciu,
TO 'kosmetyczka'@'localhost' - konto podane tak samo jak przy tworzeniu, razem z hostem.
Sprawdzone poleceniem SHOW GRANTS: konto ma GRANT SELECT, INSERT ON egzamin1.uslugi i nic więcej. Zrzut: kw4.png; plik kwerendy.txt ma komplet czterech zapytań.
Typowe błędy
TO 'kosmetyczka' bez hosta oznacza konto 'kosmetyczka'@'%', którego nie ma - serwer zgłosi błąd albo (w innych ustawieniach) utworzy drugie konto bez hasła.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1SELECT nazwa, cena FROM uslugi WHERE cena < 30;-- Zapytanie 2SELECT SUM(cena) FROM uslugi WHERE rodzaj = 1;-- Zapytanie 3CREATE USER 'kosmetyczka'@'localhost' IDENTIFIED BY 'Kosmet34';-- Zapytanie 4GRANT SELECT, INSERT ON egzamin1.uslugi TO 'kosmetyczka'@'localhost';
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 8-29 · po tym etapie masz 17 z 33 kryteriów (pkt)
Krok 8: Grafika: obraz1.jpg o wysokości 250 px
Kryteria:
R.2.1 Plik obraz1.jpg przeskalowano z zachowaniem proporcji do wysokości 250 px, odpowiadająca temu szerokość wynosi 200 px (± 2 px) lub plik obraz2.jpg przeskalowano z zachowaniem proporcji do szerokości 800 px, odpowiadająca temu wysokość wynosi 339 px (± 2 px)
ok. 2 min
Polecenie z arkusza
Plik obraz1.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego wysokość wynosiła dokładnie 250 px
Oryginał ma 352 × 440 px. W GIMP-ie Obraz → Skaluj obraz, łańcuch między szerokością a wysokością złączony (to jest zachowanie proporcji), wysokość 250 - szerokość przelicza się sama: 352 × 250 / 440 = 200 px. Klucz podaje właśnie 200 px (±2). Plik → Nadpisz obraz1.jpg.
Typowe błędy
Ustawienie wymiarów atrybutem height albo w CSS nie zmienia pliku - klucz mierzy sam plik. Wpisanie wysokości przy rozpiętym łańcuchu da obraz 352 × 250, rozciągnięty w poziomie.
Podgląd strony po tym kroku
Krok 9: Grafika: obraz2.jpg o szerokości 800 px
ok. 2 min
Polecenie z arkusza
Plik obraz2.jpg, wypakowany z archiwum, należy przeskalować z zachowaniem proporcji tak, aby jego szerokość wynosiła dokładnie 800 px
Oryginał ma 900 × 381 px. Ta sama operacja, tym razem wpisujesz szerokość 800 - wysokość: 381 × 800 / 900 = 338,7, czyli 339 px (klucz: 339 px ±2). Wystarczy jeden z dwóch obrazów, żeby dostać R.2.1, ale arkusz wymaga obu.
Podgląd strony po tym kroku
Krok 10: Plik index.html
ok. 2 min
Polecenie z arkusza
Składa się ze stron o nazwach index.html oraz twarz.html. Obie strony różnią się jedynie drugim blokiem prawym
Najpierw powstaje komplet strony index.html, a plik twarz.html będzie jej kopią z innym drugim blokiem prawym - tak nie trzeba pisać wspólnych części dwa razy. <!DOCTYPE html> oznacza HTML5, lang="pl" mówi przeglądarce, że treść jest po polsku. Strony nie potrzebują PHP - można je otworzyć prosto z dysku.
R.2.2 Witrynę internetową zapisano w plikach HTML o nazwach index i twarz oraz na przynajmniej jednej stronie zastosowano właściwy standard kodowania polskich znaków
ok. 1 min
Polecenie z arkusza
Zastosowany właściwy standard kodowania polskich znaków
<meta charset="UTF-8"> jako pierwszy element <head>, plik zapisany w UTF-8 (w Notepad++ menu Kodowanie). Nazwy plików index i twarz razem z kodowaniem dają R.2.2 - drugi plik powstanie za kilka kroków.
R.3.5 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl, formatowanie pochodzi jedynie z tego arkusza Uwaga: Kryterium to nie jest spełnione również, gdy zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)
ok. 1 min
Polecenie z arkusza
Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony
<link rel="stylesheet" href="styl.css"> w <head>. Plik stylów powstanie po HTML-u. Wszystkie style idą do tego pliku - klucz R.3.5 wymaga, żeby formatowanie pochodziło jedynie z niego.
Typowe błędy
Kropka zamiast # przy identyfikatorze bloku (albo odwrotnie) odbiera R.3.5, nawet gdy reszta stylów działa. Atrybut style w HTML-u też łamie zasadę „jedynie z arkusza”.
R.2.4 Wygląd przynajmniej jednej strony zdefiniowano dzieląc ją na bloki: dwa bloki po lewej stronie i dwa po prawej, poniżej stopka. Zastosowano znaczniki sekcji
ok. 3 min
Polecenie z arkusza
Podział strony na bloki: dwa bloki po lewej stronie i dwa po prawej, poniżej stopka. Podział zrealizowany za pomocą znaczników sekcji, tak aby po uruchomieniu w przeglądarce układ bloków był zgodny z Obrazem 2
Cztery znaczniki <section> z identyfikatorami left1, left2, right1, right2 (nazwy po angielsku - arkusz ich nie narzuca) i <footer> na stopkę.
Kolejność w kodzie jest celowa: lewy 1, prawy 1, prawy 2, lewy 2. Bloki ustawi float - lewe do lewej krawędzi, prawe do prawej - a pływający blok nie może zacząć się wyżej niż blok pływający zapisany przed nim. Gdyby lewy 2 stał w kodzie przed prawym 2, prawy 2 zacząłby się dopiero na wysokości 500 px, pod pierwszym lewym blokiem. Kolejność bloków na ekranie zgadza się z obrazem 2 - sprawdzi to pomiar w kroku z układem.
Krok 17: Lista numerowana zagnieżdżona w „Zabiegi na twarz”
Kryteria:
R.2.7 Na przynajmniej jednej stronie w pierwszym bloku lewym umieszczono listę punktową z trzema elementami, pierwszy z elementów ma zagnieżdżoną listę numerowaną z trzema elementami, zastosowano znaczniki <ul>, <ol>, <li> oraz ich zamknięcia
ok. 2 min
Polecenie z arkusza
Element „Zabiegi na twarz” ma zagnieżdżoną listę numerowaną (uporządkowaną) z elementami: Piling, Maska, Regulacja brwi
Lista numerowana (uporządkowana) to <ol>. „Zagnieżdżona w elemencie” znaczy, że stoi wewnątrz<li> „Zabiegi na twarz” - przed jego znacznikiem zamykającym </li>. Przeglądarka sama wcina ją i numeruje 1, 2, 3. Komplet <ul>, <ol>, <li> z zamknięciami to R.2.7.
Typowe błędy
<ol> wstawiona między dwa <li> (po </li>) to błąd składni HTML - lista nie należy wtedy do żadnego elementu, choć przeglądarka może ją pokazać podobnie.
Krok 18: Odnośnik „Zabiegi na twarz” do twarz.html
Kryteria:
R.3.2 Na przynajmniej jednej stronie odnośnik "Zabiegi na twarz" prowadzi do strony twarz.html
ok. 1 min
Polecenie z arkusza
Tekst elementu „Zabiegi na twarz” jest równocześnie odnośnikiem do strony twarz.html
Sam tekst elementu obejmujesz znacznikiem <a href="twarz.html"> - lista zagnieżdżona zostaje poza odnośnikiem. Ścieżka względna (sama nazwa pliku, bez C:\Users\...), bo strony leżą w jednym folderze - klucz wymaga ścieżki względnej.
Typowe błędy
Ścieżka bezwzględna file:///C:/Users/Egzamin/Desktop/... działa tylko na komputerze zdającego - egzaminator otwiera pliki z płyty i klucz jej nie uznaje.
Zawartość drugiego bloku po lewej stronie: obraz o nazwie obraz1.jpg z tekstem alternatywnym „Kosmetyczka”
<img> z plikiem przeskalowanym wcześniej i atrybutem alt - tekstem, który przeczyta czytnik ekranu i który pojawi się, gdy plik się nie wczyta. W HTML5 <img> nie ma znacznika zamykającego ani ukośnika na końcu.
Zawartość stopki: akapit (paragraf) o treści „Autor: ”, dalej wstawiony numer PESEL zdającego
Akapit <p> w <footer>. Na egzaminie po dwukropku wpisujesz swój numer PESEL. W tym rozwiązaniu w jego miejscu stoi imię i nazwisko autora: Bartosz Bryniarski.
R.2.6 Na przynajmniej jednej stronie umieszczono w drugim bloku lewym obraz obraz1.jpg z tekstem alternatywnym "Kosmetyczka" oraz na stronie index.html umieszczono w drugim panelu prawym obraz obraz2.jpg z tekstem alternatywnym "Zabiegi kosmetyczne"
ok. 1 min
Polecenie z arkusza
Zawartość drugiego bloku po prawej stronie dla index.html: Obraz o nazwie obraz2.jpg z tekstem alternatywnym „Zabiegi kosmetyczne”
Drugi <img>, tym razem w bloku right2. Oba obrazy z właściwymi tekstami alternatywnymi w swoich blokach to R.2.6.
Akapit (paragraf) o treści zgodnej z Obrazem 2, łamanie wiersza zgodne z Obrazem 2. Treść akapitu: „Witaj! Miło nam, że odwiedziłeś nasz salon. Zapoznaj się z ofertą i sprawdź ceny zabiegów lub skontaktuj się z nami”
Na obrazie 2 tekst łamie się po pierwszym zdaniu: „…nasz salon.” i w nowej linii „Zapoznaj się…”. Takie łamanie wymuszasz znacznikiem <br> - sam enter w kodzie HTML przeglądarka traktuje jak spację. Treść przepisz z ramki pod obrazem 2, bez cudzysłowów.
Typowe błędy
Dwa osobne akapity zamiast <br> dadzą większy odstęp między liniami niż na obrazie 2.
index.htmlHTMLzmienione: 2 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Usługi kosmetyczne</title> <linkrel="stylesheet"href="styl.css"></head><body> <sectionid="left1"> <h2>W ofercie</h2> <ul> <li><ahref="twarz.html">Zabiegi na twarz</a> <ol> <li>Piling</li> <li>Maska</li> <li>Regulacja brwi</li> </ol> </li> <li>Masaż</li> <li>Diety oczyszczające</li> </ul> <ahref="index.html">Do strony głównej</a> </section> <sectionid="right1"> <h1>Salon Kosmetyczny</h1> </section> <sectionid="right2"> <imgsrc="obraz2.jpg"alt="Zabiegi kosmetyczne"> <p>Witaj! Miło nam, że odwiedziłeś nasz salon.<br> Zapoznaj się z ofertą i sprawdź ceny zabiegów lub skontaktuj się z nami</p> </section> <sectionid="left2"> <imgsrc="obraz1.jpg"alt="Kosmetyczka"> </section> <footer> <p>Autor: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (index.html)
Krok 25: Nagłówek „Telefon: 111 222 333”
ok. 1 min
Polecenie z arkusza
Nagłówek czwartego stopnia o treści „Telefon: 111 222 333”
Czwartego stopnia to <h4>. Strona index.html jest kompletna.
index.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Usługi kosmetyczne</title> <linkrel="stylesheet"href="styl.css"></head><body> <sectionid="left1"> <h2>W ofercie</h2> <ul> <li><ahref="twarz.html">Zabiegi na twarz</a> <ol> <li>Piling</li> <li>Maska</li> <li>Regulacja brwi</li> </ol> </li> <li>Masaż</li> <li>Diety oczyszczające</li> </ul> <ahref="index.html">Do strony głównej</a> </section> <sectionid="right1"> <h1>Salon Kosmetyczny</h1> </section> <sectionid="right2"> <imgsrc="obraz2.jpg"alt="Zabiegi kosmetyczne"> <p>Witaj! Miło nam, że odwiedziłeś nasz salon.<br> Zapoznaj się z ofertą i sprawdź ceny zabiegów lub skontaktuj się z nami</p> <h4>Telefon: 111 222 333</h4> </section> <sectionid="left2"> <imgsrc="obraz1.jpg"alt="Kosmetyczka"> </section> <footer> <p>Autor: Bartosz Bryniarski</p> </footer></body></html>
Podgląd strony po tym kroku (index.html)
Krok 26: Strona twarz.html: kopia z nagłówkiem „Sprawdź cenę swojej wizyty”
Kryteria:
R.2.5 Na przynajmniej jednej stronie w pierwszym bloku lewym zapisano nagłówek h2: "W ofercie", w pierwszym bloku prawym zapisano nagłówek h1: "Salon Kosmetyczny", w bloku drugim prawym nagłówek h4: "Telefon: 111 222 333" i nagłówek h2: "Sprawdź cenę swojej wizyty" oraz przynajmniej jeden paragraf (znacznik <p>)
ok. 2 min
Polecenie z arkusza
Wygląd drugiego bloku po prawej stronie dla twarz.html przedstawiono na Obrazie 3, jego zawartość to: Nagłówek drugiego stopnia o treści „Sprawdź cenę swojej wizyty”
Plik index.html zapisujesz jako twarz.html (Plik → Zapisz jako) i w bloku right2 usuwasz obraz, akapit i telefon, a wstawiasz nagłówek <h2>. Reszta strony zostaje bez zmian - arkusz mówi, że strony różnią się jedynie drugim blokiem prawym, więc w obu działają te same style i odnośniki.
Komplet nagłówków z klucza - <h2> „W ofercie”, <h1> „Salon Kosmetyczny”, <h4> z telefonem, <h2> „Sprawdź cenę swojej wizyty” - i akapit to R.2.5.
Cztery pola checkbox jeden pod drugim z podpisami: Piling, Maska, Masaż twarzy, Regulacja brwi
Pole wyboru to <input type="checkbox">, a podpis stoi zaraz za nim. <br> po każdym podpisie przenosi następne pole do nowej linii („jeden pod drugim”). Każde pole dostaje identyfikator (piling, mask, massage, brows) - po nim skrypt sprawdzi, czy pole jest zaznaczone.
Typowe błędy
Bez identyfikatorów (albo z dwoma takimi samymi) skrypt nie odróżni pól. Identyfikator w HTML-u musi być unikalny na stronie.
Kroki 30-39 · po tym etapie masz 28 z 33 kryteriów (pkt)
Krok 30: Plik styl.css: krój Garamond dla całej strony
Kryteria:
R.4.1 Ustawiono domyślny krój czcionki dla całej strony na Garamond (dla selektora * lub body, lub html, lub kontenera całej strony)
ok. 1 min
Polecenie z arkusza
Cechy formatowania CSS, działające na obu stronach: Domyślne dla całej strony: krój czcionki Garamond
Nowy plik styl.css - obie strony mają do niego odnośnik, więc każda reguła działa na obu. Selektor * obejmuje wszystkie elementy, także przycisk, który kroju po body nie dziedziczy (R.4.1). Jeśli w systemie nie ma Garamonda, przeglądarka użyje kroju zastępczego.
styl.cssCSSnowy plik
* {font-family: Garamond;}
Podgląd strony po tym kroku (index.html)
Krok 31: Pierwszy blok lewy: wymiary i tło
ok. 1 min
Polecenie z arkusza
Dla pierwszego lewego bloku: wysokość 500 px, szerokość 25%, kolor tła Lavender
Selektor #left1 - krzyżyk, bo left1 to identyfikator. Nazwy kolorów CSS (Lavender, Indigo) można pisać dowolną wielkością liter.
Krok 33: Pierwszy blok prawy: wymiary, tło, biały tekst
ok. 2 min
Polecenie z arkusza
Dla pierwszego prawego bloku: wysokość 150 px, szerokość 75%, kolor tła Indigo, biały kolor czcionki, rozmiar czcionki 200%, wyrównanie tekstu do środka
Kolor czcionki to właściwość color, wyrównanie - text-align: center. Rozmiar 200% to dwa razy więcej niż rozmiar odziedziczony, a nagłówek <h1> jest jeszcze większy względem bloku - napis „Salon Kosmetyczny” wychodzi duży, jak na obrazie 2.
Krok 34: Drugi blok prawy: wymiary, tło, rozmiar i wyrównanie
Kryteria: , ,
R.4.4 Ustawiono wysokość bloków lewych kolejno na 500px i 300px oraz bloków prawych kolejno na 150px i 650px
R.4.5 Ustawiono szerokość bloków lewych 25% oraz prawych 75%
R.4.7 Ustawiono rozmiar czcionki na 200% dla bloków prawych
ok. 2 min
Polecenie z arkusza
Dla drugiego prawego bloku: wysokość 650 px, szerokość 75%, kolor tła Lavender, rozmiar czcionki 200%, wyrównanie tekstu do środka
Prawa kolumna ma 150 + 650 = 800 px, tyle samo co lewa. Wysokości wszystkich czterech bloków (R.4.4), szerokości 25% i 75% (R.4.5) i rozmiar 200% w obu blokach prawych (R.4.7) są ustawione.
Krok 35: Stopka: tło, biały tekst, wyrównanie do prawej
Kryteria: , ,
R.4.2 Ustawiono kolor tła Indigo dla pierwszego bloku prawego i stopki oraz kolor Lavender dla pozostałych bloków
R.4.3 Ustawiono biały kolor czcionki dla pierwszego bloku prawego i stopki
R.4.6 Ustawiono wyrównanie tekstu do środka dla bloków prawych oraz wyrównanie tekstu do prawej dla bloku stopki
ok. 2 min
Polecenie z arkusza
Dla stopki: kolor tła Indigo, biały kolor czcionki, wyrównanie tekstu do prawej strony
Selektor znacznika footer (bez krzyżyka - stopka nie ma identyfikatora). Komplet teł: Indigo w pierwszym bloku prawym i stopce, Lavender w pozostałych (R.4.2), biały tekst w tych dwóch blokach (R.4.3), wyrównanie do środka w blokach prawych i do prawej w stopce (R.4.6).
Krok 36: Układ: dwie kolumny bloków, stopka pod nimi
Kryteria:
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest w pełni zgodny z Obrazem 2 w arkuszu egzaminacyjnym
ok. 3 min
Polecenie z arkusza
Podział zrealizowany za pomocą znaczników sekcji, tak aby po uruchomieniu w przeglądarce układ bloków był zgodny z Obrazem 2
Trzy reguły:
bloki lewe float: left przyklejają się do lewej krawędzi, a clear: left każe drugiemu lewemu zejść pod pierwszy (bez niego stanąłby obok),
bloki prawe float: right i clear: right - to samo przy prawej krawędzi,
stopka z clear: both zaczyna się pod najniższym blokiem obu kolumn.
Kolejność bloków w kodzie (lewy 1, prawy 1, prawy 2, lewy 2) z kroku z sekcjami sprawia, że prawy 2 zaczyna się zaraz pod prawym 1, na wysokości 150 px. Zmierzone w Chrome przy szerokości okna 1280 px: kolumny mają 25% i 75% szerokości, prawy 2 zaczyna się 150 px od góry, lewy 2 - 500 px od góry, a stopka - 800 px od góry, pod obiema kolumnami (R.3.1). Wersja nowoczesna pokazuje ten sam układ na flex.
Typowe błędy
Wszystkie bloki z float: left (bez clear) ustawią się w jednym rzędzie i zawiną w przypadkowych miejscach - układ z obrazu 2 przepada.
R.4.10 Ustawiono styl dla obrazu z pseudoklasą hover: marginesy wewnętrzne (padding) 4 px oraz obramowanie linią ciągłą o szerokości 1 px i kolorze Indigo
ok. 2 min
Polecenie z arkusza
W momencie, gdy kursor znajduje się na obrazie, styl obrazu zmienia się na: marginesy wewnętrzne 4 px oraz obramowanie linią ciągłą o szerokości 1 px i kolorze Indigo (efekt ten jest widoczny na Obrazie 2)
Pseudoklasa :hover działa, gdy kursor jest nad elementem. border: 1px solid Indigo to ramka: grubość, linia ciągła (solid), kolor (R.4.10).
Dlaczego padding maleje z 5 do 4 px: ramka 1 px dochodzi do zewnętrznego rozmiaru obrazu, więc 4 + 1 = 5 px - obraz pod kursorem ma dokładnie te same wymiary co bez niego i nic na stronie nie przeskakuje. Najedź kursorem na zdjęcie w podglądzie.
R.3.4 Po wciśnięciu przycisku wywoływana jest funkcja zapisana skryptem
R.5.1 Skrypt napisano w języku uruchamianym po stronie przeglądarki i zawiera on co najmniej jedną instrukcję tego języka zapisaną zgodnie ze składnią
ok. 3 min
Polecenie z arkusza
Napisany w języku wykonywanym po stronie przeglądarki. Uruchamia się po wciśnięciu przycisku na stronie twarz.html
Językiem wykonywanym w przeglądarce jest JavaScript. Skrypt stoi w znaczniku <script> na końcu <body> strony twarz.html - przeglądarka zna już wtedy wszystkie pola.
funkcja checkPrice() zbierze całe obliczenie; na razie ma tylko zmienną sum z wartością początkową 0,
przycisk dostaje atrybut onclick="checkPrice()" (zdarzenie z tabeli arkusza) - kliknięcie wywołuje funkcję (R.3.4, R.5.1).
Typowe błędy
onclick="checkPrice" bez nawiasów nie wywoła funkcji - przeglądarka tylko odczyta jej nazwę.
Krok 41: Pierwsze pole: sprawdzenie stanu instrukcją if
Kryteria:
R.5.2 Skrypt pobiera wartości z przynajmniej jednego pola checkbox i sprawdza jego stan za pomocą instrukcji warunkowej lub wyboru
ok. 3 min
Polecenie z arkusza
Oblicza łączną cenę zabiegów wybranych za pomocą pól checkbox zgodnie z cennikiem w tabeli
Właściwość checked pola checkbox ma wartość true, gdy pole jest zaznaczone, i false, gdy nie jest. Instrukcja if dodaje cenę Pilingu z cennika (45) do sumy tylko przy zaznaczonym polu (R.5.2):
document.getElementById('piling') - pole o identyfikatorze piling,
.checked - jego stan,
sum = sum + 45 - do dotychczasowej sumy dochodzi cena zabiegu.
Typowe błędy
.value pola checkbox to zawsze tekst on, niezależnie od zaznaczenia - stan pola niesie wyłącznie checked.
Krok 42: Pozostałe pola: Maska, Masaż twarzy, Regulacja brwi
Kryteria:
R.5.3 Skrypt liczy sumę jedynie wszystkich zaznaczonych pól checkbox zgodnie z cenami podanymi w tabeli w arkuszu
ok. 3 min
Polecenie z arkusza
Oblicza łączną cenę zabiegów wybranych za pomocą pól checkbox zgodnie z cennikiem w tabeli
Trzy kolejne instrukcje if, każda z ceną z tabeli w arkuszu: Maska 30, Masaż 20, Regulacja brwi 5. To cztery osobne instrukcje, nie else if - zaznaczyć można kilka pól naraz i każde zaznaczone dokłada swoją cenę. Suma obejmuje tylko zaznaczone pola (R.5.3).
W cenniku zabieg nazywa się „Masaż”, a podpis pola - „Masaż twarzy”; to ten sam zabieg za 20 zł.
Typowe błędy
else if zamiast osobnych if liczy tylko pierwsze zaznaczone pole - przy Masce i Regulacji brwi wyszłoby 30 zamiast 35.
twarz.htmlHTMLzmienione: 9 linii
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Usługi kosmetyczne</title> <linkrel="stylesheet"href="styl.css"></head><body> <sectionid="left1"> <h2>W ofercie</h2> <ul> <li><ahref="twarz.html">Zabiegi na twarz</a> <ol> <li>Piling</li> <li>Maska</li> <li>Regulacja brwi</li> </ol> </li> <li>Masaż</li> <li>Diety oczyszczające</li> </ul> <ahref="index.html">Do strony głównej</a> </section> <sectionid="right1"> <h1>Salon Kosmetyczny</h1> </section> <sectionid="right2"> <h2>Sprawdź cenę swojej wizyty</h2> <inputtype="checkbox"id="piling"> Piling<br> <inputtype="checkbox"id="mask"> Maska<br> <inputtype="checkbox"id="massage"> Masaż twarzy<br> <inputtype="checkbox"id="brows"> Regulacja brwi<br> <buttononclick="checkPrice()">Sprawdź cenę</button> <pid="result"></p> </section> <sectionid="left2"> <imgsrc="obraz1.jpg"alt="Kosmetyczka"> </section> <footer> <p>Autor: Bartosz Bryniarski</p> </footer> <script>function checkPrice() {var sum = 0;if (document.getElementById('piling').checked) { sum = sum + 45; }if (document.getElementById('mask').checked) { sum = sum + 30; }if (document.getElementById('massage').checked) { sum = sum + 20; }if (document.getElementById('brows').checked) { sum = sum + 5; } } </script></body></html>
Podgląd strony po tym kroku (twarz.html)
Krok 43: Wynik pod przyciskiem: „Cena zabiegów: suma”
Kryteria:
R.5.4 Skrypt wypisuje wynik pod przyciskiem według wzoru: "Cena zabiegów: <suma>”, gdzie <suma> oznacza sumę wyliczoną przez skrypt
ok. 2 min
Polecenie z arkusza
Wyświetla wynik działania pod przyciskiem według wzoru: „Cena zabiegów: <suma>”, gdzie <suma> oznacza całkowitą cenę wybranych zabiegów
Ostatnia linia funkcji wpisuje tekst do akapitu result pod przyciskiem: innerHTML (z tabeli arkusza) zastępuje zawartość elementu, a operator + skleja napis 'Cena zabiegów: ' z liczbą (R.5.4). Spacja po dwukropku jest w napisie, liczba - bez jednostki, jak na obrazie 3.
Sprawdzone w Chrome dla wszystkich 16 kombinacji zaznaczeń: od „Cena zabiegów: 0” (nic nie zaznaczone) do „Cena zabiegów: 100” (wszystko). Maska z Regulacją brwi dają 35 - jak na obrazie 3. Kliknij pola i przycisk w podglądzie.
Typowe błędy
document.write po załadowaniu strony zamazuje całą stronę wynikiem - wynik ma stanąć pod przyciskiem, więc trzeba wpisać go do elementu.
twarz.htmlHTMLzmienione: 1 linia
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Usługi kosmetyczne</title> <linkrel="stylesheet"href="styl.css"></head><body> <sectionid="left1"> <h2>W ofercie</h2> <ul> <li><ahref="twarz.html">Zabiegi na twarz</a> <ol> <li>Piling</li> <li>Maska</li> <li>Regulacja brwi</li> </ol> </li> <li>Masaż</li> <li>Diety oczyszczające</li> </ul> <ahref="index.html">Do strony głównej</a> </section> <sectionid="right1"> <h1>Salon Kosmetyczny</h1> </section> <sectionid="right2"> <h2>Sprawdź cenę swojej wizyty</h2> <inputtype="checkbox"id="piling"> Piling<br> <inputtype="checkbox"id="mask"> Maska<br> <inputtype="checkbox"id="massage"> Masaż twarzy<br> <inputtype="checkbox"id="brows"> Regulacja brwi<br> <buttononclick="checkPrice()">Sprawdź cenę</button> <pid="result"></p> </section> <sectionid="left2"> <imgsrc="obraz1.jpg"alt="Kosmetyczka"> </section> <footer> <p>Autor: Bartosz Bryniarski</p> </footer> <script>function checkPrice() {var sum = 0;if (document.getElementById('piling').checked) { sum = sum + 45; }if (document.getElementById('mask').checked) { sum = sum + 30; }if (document.getElementById('massage').checked) { sum = sum + 20; }if (document.getElementById('brows').checked) { sum = sum + 5; }document.getElementById('result').innerHTML = 'Cena zabiegów: ' + sum; } </script></body></html>
Podgląd strony po tym kroku (twarz.html)
Etap 5: Dobre praktyki (poza kluczem)
Kroki 44-45 · po tym etapie masz 33 z 33 kryteriów (pkt)
Krok 44: Konto kosmetyczka: najmniejsze uprawnienia sprawdzone w praktyce
ok. 3 min
Polecenie z arkusza
Zapytanie 4: nadające prawa przeglądania danych i wstawiania rekordów do tabeli uslugi bazy egzamin1 dla użytkownika kosmetyczka
Zapytanie 4 to dobry przykład zasady najmniejszych uprawnień: konto dostaje tylko to, czego potrzebuje do pracy, i tylko w jednej tabeli. Sprawdzone przez zalogowanie się na konto kosmetyczka (na zrzucie wynik SHOW GRANTS dla tego konta):
SELECT COUNT(*) FROM uslugi - działa, wynik 10,
DELETE FROM uslugi WHERE id = 8 - serwer odmawia: ERROR 1142 (42000): DELETE command denied to user 'kosmetyczka'@'localhost' for tableegzamin1.uslugi``,
UPDATE uslugi SET cena = 1 WHERE id = 9 - odmowa z tym samym kodem 1142,
SELECT * FROM kadra - odmowa, bo prawa dotyczą tylko tabeli uslugi.
Gdyby ktoś przejął hasło tego konta, może czytać cennik i dopisywać usługi, ale nie usunie ani nie przeceni istniejących i nie zobaczy danych pracowników. Dwie rzeczy, które w prawdziwym systemie trzeba zrobić inaczej niż na egzaminie:
hasło Kosmet34 jest krótkie i przewidywalne (słowo z dwiema cyframi) - konto bazy dostaje długie, losowe hasło,
hasło zapisane w kwerendy.txt to hasło w zwykłym pliku tekstowym - na egzaminie tego wymaga arkusz, w pracy hasło do bazy nie trafia do dokumentów ani do repozytorium kodu.
Na egzaminie zapisz zapytania 3 i 4 dokładnie tak, jak każe arkusz - klucz tego nie sprawdza.
Podgląd strony po tym kroku (twarz.html)
Krok 45: Cena z przeglądarki to tylko informacja; textContent zamiast innerHTML
ok. 3 min
Polecenie z arkusza
Wyświetla wynik działania pod przyciskiem według wzoru: „Cena zabiegów: <suma>”, gdzie <suma> oznacza całkowitą cenę wybranych zabiegów
Skrypt działa w przeglądarce użytkownika, więc użytkownik ma nad nim pełną władzę. Sprawdzone w Chrome: jedna linia wpisana w konsoli narzędzi deweloperskich (F12) - document.getElementById('result').innerHTML = 'Cena zabiegów: 1' - zmienia wyświetloną cenę Maski z 30 na 1 zł. Wniosek: cena policzona skryptem po stronie przeglądarki jest tylko podpowiedzią dla klienta. Gdyby strona przyjmowała rezerwacje, serwer musiałby policzyć cenę jeszcze raz, z własnego cennika (np. z tabeli uslugi), i nie ufać liczbie przysłanej z przeglądarki.
Druga zmiana dotyczy wypisywania: textContent wstawia tekst dosłownie, a innerHTML interpretuje go jako HTML. Dziś skrypt skleja stały napis z liczbą, więc różnicy nie widać - ale gdy do wyniku trafi kiedyś tekst od użytkownika albo z bazy, innerHTML wykona wstawione w nim znaczniki (np. obrazek z atrybutem onerror uruchamiającym skrypt), a textContent pokaże je jako zwykłe znaki. Stara linia zostaje w komentarzu, wynik dla wszystkich 16 kombinacji jest ten sam. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
twarz.htmlHTMLzmienione: 2 linie
<!DOCTYPE html><htmllang="pl"><head> <metacharset="UTF-8"> <title>Usługi kosmetyczne</title> <linkrel="stylesheet"href="styl.css"></head><body> <sectionid="left1"> <h2>W ofercie</h2> <ul> <li><ahref="twarz.html">Zabiegi na twarz</a> <ol> <li>Piling</li> <li>Maska</li> <li>Regulacja brwi</li> </ol> </li> <li>Masaż</li> <li>Diety oczyszczające</li> </ul> <ahref="index.html">Do strony głównej</a> </section> <sectionid="right1"> <h1>Salon Kosmetyczny</h1> </section> <sectionid="right2"> <h2>Sprawdź cenę swojej wizyty</h2> <inputtype="checkbox"id="piling"> Piling<br> <inputtype="checkbox"id="mask"> Maska<br> <inputtype="checkbox"id="massage"> Masaż twarzy<br> <inputtype="checkbox"id="brows"> Regulacja brwi<br> <buttononclick="checkPrice()">Sprawdź cenę</button> <pid="result"></p> </section> <sectionid="left2"> <imgsrc="obraz1.jpg"alt="Kosmetyczka"> </section> <footer> <p>Autor: Bartosz Bryniarski</p> </footer> <script>function checkPrice() {var sum = 0;if (document.getElementById('piling').checked) { sum = sum + 45; }if (document.getElementById('mask').checked) { sum = sum + 30; }if (document.getElementById('massage').checked) { sum = sum + 20; }if (document.getElementById('brows').checked) { sum = sum + 5; }// document.getElementById('result').innerHTML = 'Cena zabiegów: ' + sum;document.getElementById('result').textContent = 'Cena zabiegów: ' + sum; } </script></body></html>
Podgląd strony po tym kroku (twarz.html)
Etap 6: Oddanie pracy
Krok 46 · po tym etapie masz 33 z 33 kryteriów (pkt)
Krok 46: Plik przeglądarka.txt i nagranie płyty
ok. 5 min
Polecenie z arkusza
Po zakończeniu pracy utwórz plik tekstowy. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowałeś poprawność działania witryny. Nazwij plik przeglądarka.txt i zapisz go w folderze z numerem PESEL. Nagraj płytę z rezultatami pracy.
W przeglądarka.txt wpisujesz nazwę przeglądarki, w której sprawdzasz strony i skrypt.
W folderze z numerem PESEL muszą być: index.html, twarz.html, egzamin.jpg, kw1.png - kw4.png, kwerendy.txt, obraz1.jpg, obraz2.jpg, przeglądarka.txt i styl.css. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem PESEL - zapakowana w pudełko zostaje na stanowisku razem z arkuszem.
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.
Autor rozwiązania: Bartosz Bryniarski. Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.