INF.04-02-24.01-SGStyczeń 2024 · 25 kroków · ok. 72 min · 34 kryteria z klucza
Rozwiązanie krok po kroku: Aplikacja wizyt u weterynarza (Java + Android)
Rozwiązujemy arkusz z narzędziami dla tekstu i zapisami do weterynarza w wersji Java + Android Studio: w konsoli klasa StringTools z dwiema metodami statycznymi - liczenie samogłosek i usuwanie znaków powtórzonych obok siebie - przetestowana na tekście z klawiatury; w aplikacji mobilnej formularz wizyty: właściciel, gatunek z listy, wiek z suwaka, którego maksimum zależy od gatunku, cel wizyty, godzina i przycisk OK, który wypisuje dane pod spodem. Do tego komentarz dokumentujący klasę według wzoru z arkusza, zrzuty i dokument egzamin.
Kroki idą zdanie po zdaniu za treścią arkusza - każdy zaczyna się poleceniem z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Najpierw piszemy najprostszą wersję, której wymaga klucz, a w etapie „Dobre praktyki” poprawiamy to, czego klucz nie sprawdza.
Co widać w podglądzie. Wyniki programu konsolowego pochodzą z prawdziwego uruchomienia kodu z danego kroku (JDK 21) dla przykładów z tabeli w arkuszu i przypadków z klucza (powtórzenia na początku i na końcu tekstu); każdy wynik porównaliśmy z niezależnie policzonym wzorcem. Ekran telefonu to symulacja w przeglądarce zbudowana z pliku XML danego kroku; jej zachowanie odpowiada kodowi Javy z kroku - wybierz gatunek, przesuń suwak, wpisz dane i kliknij „OK”. Każdy stan aplikacji zbudowaliśmy też w Android Studio (Gradle) i sprawdziliśmy na emulatorze Pixel 8.
Arkusz pozwala też na C++, C# albo Pythona w konsoli i na .NET MAUI w części mobilnej - ten wariant to jedna z możliwych dróg.
Jak liczą się punkty. Klucz ma 34 kryteria (R.1.1 - R.4.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 26 punktów - 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.
Krok 1 · po tym etapie masz 0 z 34 kryteriów (pkt)
Krok 1: Folder zdającego i podfoldery
ok. 1 min
Polecenie z arkusza
Utwórz folder i nazwij go numerem zdającego. W folderze utwórz podfoldery: konsola, mobilna, dokumentacja.
Na pulpicie zakładamy folder o nazwie z numerem PESEL, a w nim konsola, mobilna i dokumentacja. Arkusz nie ma załączników - gatunki i ich maksymalny wiek są w treści zadania.
Etap 2: Aplikacja konsolowa
Kroki 2-7 · po tym etapie masz 17 z 34 kryteriów (pkt)
Krok 2: Projekt konsola w Javie
ok. 3 min
Polecenie z arkusza
Napisz program implementujący klasę z narzędziami dla typu łańcuchowego (string). Program wykonywany w konsoli. Zastosowany obiektowy język programowania zgodny z zainstalowanym na stanowisku egzaminacyjnym: C++ lub C#, lub Java, lub Python.
Wybieramy Javę - tę samą, w której napiszemy aplikację mobilną. W IntelliJ IDEA: New Project → Java, nazwa konsola. Program główny to Main.java, klasę narzędzi zapiszemy w osobnym pliku.
R.2.1 Program składa się z programu głównego oraz definicji klasy, w której znajduje się przynajmniej jedna metoda zgodna z treścią zadania (może być niedokończona, lub z błędami)
R.1.4 Użyto polskie lub angielskie, znaczące nazewnictwo zmiennych oraz klasy. Wyjątkami od reguły są zmienne bufor, tmp, iteratory pętli itp. Kryterium nie jest spełnione tylko wtedy, gdy nazwy zmiennych nic nie znaczą, np. x, fun, foo, tab, tablica
ok. 2 min
Polecenie z arkusza
Klasa ma charakter biblioteki narzędziowej, nie jest przewidziane powoływanie obiektów tej klasy, wszystkie jej metody są statyczne i są widzialne poza klasą. Przez samogłoski rozumie się znaki: „aąeęiouóyAĄEĘIOUÓY”.
New → Java Class → StringTools (narzędzia dla napisów - arkusz pozwala na angielskie nazwy) (R.2.1, R.1.4). Samogłoski zapisujemy raz, w stałej VOWELS: static final - jedna dla całej klasy i niezmienna, private - to szczegół wewnętrzny klasy. Napis jest dokładnie taki jak w arkuszu, małe i wielkie litery, także polskie.
R.2.2 Zdefiniowane w klasie metody są statyczne o zakresie public
R.2.3 Metoda zliczająca samogłoski ma zmienną łańcuchową jako parametr oraz zwraca wartość typu całkowitego. Zastosowano instrukcję return dla każdej ścieżki decyzyjnej
R.2.4 Metoda zliczająca samogłoski jest zabezpieczona przed wartościami argumentu null lub pusty napis - w obu przypadkach zwraca 0. Metoda nie powoduje błędów odwołania się do nieistniejącego indeksu
R.1.3 Użyto znaczące nazewnictwo metod / funkcji
R.1.5 Zastosowano typy zmiennych pasujące do problemu (np. dowolny typ numeryczny dla licznika; dowolny typ napisowy)
ok. 4 min
Polecenie z arkusza
Metoda licząca wszystkie samogłoski: jako parametr przyjmuje zmienną typu tekstowego, zwraca liczbę samogłosek znajdujących się w parametrze. W przypadku, gdy parametrem jest pusty łańcuch znaków lub null, metoda zwraca 0.
Metoda public static - widoczna poza klasą i wywoływana bez tworzenia obiektu: StringTools.countVowels(text) (R.2.2). Parametr String, wynik int (R.2.3, R.1.5).
Najpierw zabezpieczenie: dla null albo pustego napisu od razu return 0 (R.2.4). Kolejność warunków ma znaczenie: text == null sprawdzamy przedtext.isEmpty() - wywołanie metody na null kończy się NullPointerException, a operator || przy prawdziwym pierwszym warunku drugiego już nie sprawdza.
Pętla idzie po indeksach od 0 do length() - 1, więc nie wychodzi poza napis. VOWELS.indexOf(znak) zwraca pozycję znaku w napisie samogłosek albo -1, gdy go tam nie ma - stąd warunek >= 0.
Obie ścieżki kończą się return (R.2.3).
Typowe błędy
text.isEmpty() || text == null - przy null metoda wywołuje isEmpty() na pustej referencji i program kończy się wyjątkiem (R.2.4).
konsola/src/StringTools.javaJavazmienione: 13 linii
Krok 5: Metoda removeRepeats: bez powtórzeń obok siebie
Kryteria: , , , ,
R.2.2 Zdefiniowane w klasie metody są statyczne o zakresie public
R.2.5 Zmienna łańcuchowa jest parametrem metody usuwającej duplikaty. Metoda zwraca łańcuch. Zastosowano instrukcję return dla każdej ścieżki decyzyjnej
R.2.6 Metoda usuwająca duplikaty jest zabezpieczona przed wartościami argumentu null lub pusty napis - w obu przypadkach zwraca pusty napis. Metoda nie powoduje błędów odwołania się do nieistniejącego indeksu
R.1.1 Kod źródłowy zapisano w sposób czytelny: instrukcje w osobnych liniach, stosowane spacje pomiędzy operatorami, konsekwentnie stosowana wybrana konwencja dla nawiasów klamrowych
R.1.2 Kod zapisano z wcięciami dla zagłębień bloków
ok. 4 min
Polecenie z arkusza
Metoda usuwająca powtórzenia znaków występujące obok siebie: jako parametr przyjmuje łańcuch, w którym będą szukane powtórzenia, zwraca łańcuch bez powtórzeń. W przypadku, gdy parametrem jest pusty łańcuch lub null, metoda zwraca pusty łańcuch. Wszystkie znaki łańcucha są sprawdzane, czy znak następny jest tym samym znakiem. Jeśli tak, jest on pomijany w wyjściowym łańcuchu znaków.
Algorytm wprost z arkusza: dla każdego znaku sprawdzamy, czy następny jest taki sam. Jeśli tak - pomijamy bieżący (zostanie ostatni z serii); jeśli nie - dopisujemy go do wyniku. Z „Abba” zostaje „Aba”, z „;;;” - „;”.
Zabezpieczenie: null i pusty napis dają pusty łańcuch"" (R.2.6).
Ostatni znak nie ma następnego - warunek i == text.length() - 1 stoi pierwszy, więc dla ostatniego znaku text.charAt(i + 1) nie jest wywoływane i nie wychodzimy poza napis (R.2.6).
Wynik budujemy w StringBuilder - dopisywanie do niego nie tworzy za każdym razem nowego napisu, jak += na String.
Metoda zwraca String na obu ścieżkach (R.2.5).
Typowe błędy
Pętla porównująca text.charAt(i + 1) bez warunku dla ostatniego znaku - StringIndexOutOfBoundsException dla każdego tekstu (R.2.6). Porównanie z poprzednim znakiem przez charAt(i - 1) od i = 0 - ten sam błąd na początku napisu.
konsola/src/StringTools.javaJavazmienione: 13 linii
Krok 6: Program główny: tekst z klawiatury i wyniki obu metod
Kryteria: , ,
R.1.7 Program nawiązuje zrozumiałą komunikację z użytkownikiem: monit o wprowadzenie danych, wyprowadzanie wyników opatrzone komentarzem. Jeżeli kod nie uruchamia się z powodu błędów kompilacji - sprawdzić w kodzie aplikacji
R.2.8 Program liczy samogłoski "aąeęiouóyAĄEĘIOUÓY" w łańcuchu i wyświetla ich liczbę
R.2.9 Program usuwa duplikaty znaków występujące obok siebie i wypisuje łańcuch bez nich. Sprawdzić dla wielokrotnych spacji, liter, znaków specjalnych. Sprawdzić, gdy powtórzenie jest na początku łańcucha oraz na końcu łańcucha
ok. 3 min
Polecenie z arkusza
W programie głównym należy przetestować obie metody, wczytując łańcuch z klawiatury i wyświetlając liczbę samogłosek oraz łańcuch po eliminacji duplikatów. Program powinien podejmować zrozumiałą komunikację z użytkownikiem.
Tekst wczytujemy nextLine() - cały wiersz razem ze spacjami (samo next() wczytałoby tylko pierwsze słowo, a powtórzone spacje to jeden z przypadków z arkusza). Prośba o dane i wyniki są opisane (R.1.7). Metody wołamy przez nazwę klasy - bez new StringTools().
Podgląd to prawdziwe uruchomienia dla przykładów z tabeli arkusza - „Przykład tekstu” z podwójną spacją i „Abba;;;to zespół” - oraz dla powtórzeń na początku i na końcu tekstu, które sprawdza egzaminator (R.2.8, R.2.9).
konsola/src/Main.javaJavazmienione: 8 linii
import java.util.Scanner;publicclassMain {publicstaticvoidmain(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Podaj tekst: "); String text = scanner.nextLine(); System.out.println("Liczba samogłosek: " + StringTools.countVowels(text)); System.out.println("Tekst bez powtórzeń: " + StringTools.removeRepeats(text)); }}
Wynik programu po tym kroku
> java Main
Podaj tekst: Przykład tekstu
Liczba samogłosek: 4
Tekst bez powtórzeń: Przykład tekstu
> java Main
Podaj tekst: Abba;;;to zespół
Liczba samogłosek: 5
Tekst bez powtórzeń: Aba;to zespół
> java Main
Podaj tekst: aaala mmma kotaa!!
Liczba samogłosek: 8
Tekst bez powtórzeń: ala ma kota!
Krok 7: Folder konsola: archiwum, źródła i zrzuty
Kryteria: , ,
R.1.6 Podjęto próbę skompilowania kodu lub uruchomienia w interpreterze, co udokumentowano zrzutem ekranowym przedstawiającym uruchomiony program lub jego kompilację
R.2.7 Program uruchamia się w konsoli, co udokumentowano zrzutem ekranu
R.4.6 Zapisano przynajmniej jeden zrzut ekranu z uruchomienia lub kompilacji aplikacji konsolowej, na zrzucie widoczne jest środowisko, w którym powstała aplikacja
ok. 3 min
Polecenie z arkusza
Kod aplikacji przygotuj do nagrania na płytę. W podfolderze konsola zapisz archiwum całego projektu o nazwie konsola.zip, plik z kodem źródłowym programu oraz plik uruchomieniowy, jeżeli istnieje. Aplikacja konsolowa – dokumentująca interakcje dowolna liczba zrzutów o nazwach konsola1, konsola2, ...
Uruchamiamy program dla obu przykładów z arkusza i robimy zrzuty całego ekranu z IntelliJ (widoczny pasek zadań) - konsola1, konsola2 w folderze dokumentacja (R.1.6, R.2.7, R.4.6). Folder projektu pakujemy do konsola.zip (po dopisaniu komentarza z części III), obok kopiujemy StringTools.java i Main.java.
Kroki 8-20 · po tym etapie masz 28 z 34 kryteriów (pkt)
Krok 8: Nowy projekt Weterynarz w Android Studio
ok. 3 min
Polecenie z arkusza
Za pomocą środowiska programistycznego dostępnego na stanowisku egzaminacyjnym wykonaj aplikację mobilną obsługującą zapisy na wizytę u weterynarza.
New Project → szablon Empty Views Activity (z widokami w XML). Nazwa Weterynarz, pakiet com.example.weterynarz, język Java. Będziemy zmieniać res/layout/activity_main.xml (wygląd) i MainActivity.java (logika).
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 9: Pionowy LinearLayout w kolorze LightGreen
Kryteria: ,
R.3.1 Zastosowano język znaczników XML/XAML lub inny do opisu interfejsu użytkownika oraz kod zawiera przynajmniej jeden element / kontrolkę interfejsu graficznego
R.3.2 Zastosowano rozkład liniowy wertykalny (LinearLayout / StackLayout lub inny o tej idei) z zagłębionym rozkładem liniowym horyzontalnym dla kontrolek dotyczących wieku (napisy i suwak). Dla rozkładu głównego lub dla strony zastosowano kolor tła LightGreen (#90EE90)
ok. 2 min
Polecenie z arkusza
Interfejs użytkownika zapisany za pomocą języka znaczników wspieranego w danym środowisku (np. XAML, XML). Zastosowany rozkład liniowy wertykalny (Linear / Stack lub inny o tej idei). Kolor głównego rozkładu: LightGreen (#90EE90).
W widoku Code zamieniamy ConstraintLayout na pionowy LinearLayout (R.3.1, R.3.2) i zostawiamy android:id="@+id/main" (używa go kod szablonu). Tło #90EE90 (R.3.2). Układ wypełnia cały ekran, więc zielony jest też pod paskiem stanu - szablon edge-to-edge tylko odsuwa zawartość od pasków.
Weterynarz/app/src/main/res/layout/activity_main.xmlXMLzmienione: 4 linie
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 10: Tytuł na tle SeaGreen z paddingiem 10
Kryteria:
R.3.3 Zastosowano przynajmniej dwa pola tekstowe, dla pola "Wizyta u weterynarza" zastosowano czcionkę większą niż pozostałych elementów, kolor tła SeaGreen (#2E8B57) i padding 10 oraz zastosowano dwa pola edycyjne, przynajmniej jedno ma podpowiedź "Imię i nazwisko właściciela...” lub "Cel wizyty"
ok. 2 min
Polecenie z arkusza
Pole tekstowe z tytułem „Wizyta u weterynarza”. Cechy tytułu: zapisany czcionką większą niż pozostałe kontrolki, kolor tła: SeaGreen (#2E8B57), marginesy wewnętrzne 10.
Tytuł na całą szerokość z tłem #2E8B57, marginesem wewnętrznym android:padding="10dp" (odstęp tekstu od krawędzi tła) i czcionką 24sp - pozostałe elementy będą miały 14-18sp (R.3.3).
Weterynarz/app/src/main/res/layout/activity_main.xmlXMLzmienione: 8 linii
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#90EE90"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#2E8B57"android:padding="10dp"android:text="Wizyta u weterynarza"android:textSize="24sp"/></LinearLayout>
Ekran telefonu po tym kroku
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 11: Pole właściciela i napis „Gatunek”
Kryteria:
R.3.3 Zastosowano przynajmniej dwa pola tekstowe, dla pola "Wizyta u weterynarza" zastosowano czcionkę większą niż pozostałych elementów, kolor tła SeaGreen (#2E8B57) i padding 10 oraz zastosowano dwa pola edycyjne, przynajmniej jedno ma podpowiedź "Imię i nazwisko właściciela...” lub "Cel wizyty"
ok. 2 min
Polecenie z arkusza
Pole edycyjne z podpowiedzią „Imię i nazwisko właściciela...”. Pole tekstowe „Gatunek”.
EditText z podpowiedzią (hint) - szary napis, który znika po wpisaniu tekstu (R.3.3). inputType="textPersonName" mówi klawiaturze, że to imię i nazwisko (zaczyna od wielkiej litery). Pod nim zwykły napis „Gatunek” - nagłówek listy.
Weterynarz/app/src/main/res/layout/activity_main.xmlXMLzmienione: 12 linii
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#90EE90"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#2E8B57"android:padding="10dp"android:text="Wizyta u weterynarza"android:textSize="24sp"/><EditTextandroid:id="@+id/ownerInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Imię i nazwisko właściciela..."android:inputType="textPersonName"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Gatunek"/></LinearLayout>
Ekran telefonu po tym kroku
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 12: Lista gatunków z wysokością dopasowaną do elementów
ok. 2 min
Polecenie z arkusza
Lista z elementami tekstowymi: „Pies”, „Kot”, „Świnka morska”. Cechy listy: wysokość dopasowana do liczby elementów.
ListView z layout_height="wrap_content" - lista zajmie tyle miejsca, ile jej wiersze, i nie zepchnie reszty formularza na dół ekranu (match_parent zabrałoby całą wolną wysokość). Elementy dołoży kod Javy, więc na razie lista jest pusta.
Weterynarz/app/src/main/res/layout/activity_main.xmlXMLzmienione: 5 linii
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#90EE90"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#2E8B57"android:padding="10dp"android:text="Wizyta u weterynarza"android:textSize="24sp"/><EditTextandroid:id="@+id/ownerInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Imię i nazwisko właściciela..."android:inputType="textPersonName"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Gatunek"/><ListViewandroid:id="@+id/speciesList"android:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout>
Ekran telefonu po tym kroku
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 13: Wiersz wieku: napisy i suwak 0-20 obok siebie
Kryteria: ,
R.3.2 Zastosowano rozkład liniowy wertykalny (LinearLayout / StackLayout lub inny o tej idei) z zagłębionym rozkładem liniowym horyzontalnym dla kontrolek dotyczących wieku (napisy i suwak). Dla rozkładu głównego lub dla strony zastosowano kolor tła LightGreen (#90EE90)
R.3.4 Zastosowano suwak (Slider lub SeekBar) o wartości początkowej 0 i i wartości maksymalnej 20 oraz kontrolkę do wpisania czasu (TimePicker lub EditText z android:inputType="time") o wartości początkowej 16:00 lub 4:00PM
ok. 3 min
Polecenie z arkusza
Jedno lub dwa pola tekstowe o treści „Ile ma lat?” oraz „0” (wartość reprezentująca wiek zwierzęcia). Suwak, w postaci kontrolki Slider lub SeekBar o wartości początkowej 0 i wartości maksymalnej 20. Zastosowany rozkład liniowy wertykalny z zagnieżdżonym rozkładem liniowym horyzontalnym dla kontrolek dotyczących wieku (napisy i suwak).
Zagnieżdżony poziomy LinearLayout (R.3.2), w nim:
„Ile ma lat?” i osobny napis ageText z „0” - kod będzie zmieniał tylko liczbę,
SeekBar z android:max="20" i android:progress="0" (R.3.4); layout_width="0dp" z layout_weight="1" - suwak zajmie resztę szerokości wiersza.
gravity="center_vertical" wyrównuje napisy i suwak w pionie do środka wiersza.
Weterynarz/app/src/main/res/layout/activity_main.xmlXMLzmienione: 28 linii
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#90EE90"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#2E8B57"android:padding="10dp"android:text="Wizyta u weterynarza"android:textSize="24sp"/><EditTextandroid:id="@+id/ownerInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Imię i nazwisko właściciela..."android:inputType="textPersonName"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Gatunek"/><ListViewandroid:id="@+id/speciesList"android:layout_width="match_parent"android:layout_height="wrap_content"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Ile ma lat?"/><TextViewandroid:id="@+id/ageText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:text="0"/><SeekBarandroid:id="@+id/ageSeekBar"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:max="20"android:progress="0"/></LinearLayout></LinearLayout>
Ekran telefonu po tym kroku
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 14: Pole „Cel wizyty” i pole czasu 16:00
Kryteria: ,
R.3.3 Zastosowano przynajmniej dwa pola tekstowe, dla pola "Wizyta u weterynarza" zastosowano czcionkę większą niż pozostałych elementów, kolor tła SeaGreen (#2E8B57) i padding 10 oraz zastosowano dwa pola edycyjne, przynajmniej jedno ma podpowiedź "Imię i nazwisko właściciela...” lub "Cel wizyty"
R.3.4 Zastosowano suwak (Slider lub SeekBar) o wartości początkowej 0 i i wartości maksymalnej 20 oraz kontrolkę do wpisania czasu (TimePicker lub EditText z android:inputType="time") o wartości początkowej 16:00 lub 4:00PM
ok. 2 min
Polecenie z arkusza
Pole edycyjne z podpowiedzią „Cel wizyty”. Pole dedykowane do zapisu czasu z wartością początkową 4:00PM lub 16:00.
Drugie pole edycyjne z podpowiedzią „Cel wizyty” (R.3.3). Czas to EditText z android:inputType="time" - klawiatura pokazuje cyfry i dwukropek - i wartością 16:00 wpisaną jako treść, nie podpowiedź (R.3.4). Klucz dopuszcza też kontrolkę TimePicker, ale zajmuje ona pół ekranu; obraz 1a pokazuje właśnie pole tekstowe.
Typowe błędy
android:hint="16:00" - pole wygląda podobnie, ale jest puste i godzina nie trafi do podsumowania (R.3.4).
Weterynarz/app/src/main/res/layout/activity_main.xmlXMLzmienione: 14 linii
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#90EE90"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#2E8B57"android:padding="10dp"android:text="Wizyta u weterynarza"android:textSize="24sp"/><EditTextandroid:id="@+id/ownerInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Imię i nazwisko właściciela..."android:inputType="textPersonName"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Gatunek"/><ListViewandroid:id="@+id/speciesList"android:layout_width="match_parent"android:layout_height="wrap_content"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Ile ma lat?"/><TextViewandroid:id="@+id/ageText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:text="0"/><SeekBarandroid:id="@+id/ageSeekBar"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:max="20"android:progress="0"/></LinearLayout><EditTextandroid:id="@+id/purposeInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Cel wizyty"android:inputType="text"/><EditTextandroid:id="@+id/timeInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="time"android:text="16:00"/></LinearLayout>
Ekran telefonu po tym kroku
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 15: Przycisk OK i miejsce na komunikat
ok. 2 min
Polecenie z arkusza
Przycisk o treści: „OK”. Rozmieszczenie elementów zgodne z obrazami 1a lub 1b.
Przycisk „OK” i pod nim pusty napis resultText - tu pojawi się podsumowanie wizyty (arkusz pozwala na napis pod przyciskiem albo okno komunikatu; wybieramy napis, jak na obrazie 2c). Ekran ma wszystkie elementy z obrazu 1a poza wierszami listy.
Weterynarz/app/src/main/res/layout/activity_main.xmlXMLzmienione: 10 linii
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#90EE90"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#2E8B57"android:padding="10dp"android:text="Wizyta u weterynarza"android:textSize="24sp"/><EditTextandroid:id="@+id/ownerInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Imię i nazwisko właściciela..."android:inputType="textPersonName"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Gatunek"/><ListViewandroid:id="@+id/speciesList"android:layout_width="match_parent"android:layout_height="wrap_content"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Ile ma lat?"/><TextViewandroid:id="@+id/ageText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:text="0"/><SeekBarandroid:id="@+id/ageSeekBar"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:max="20"android:progress="0"/></LinearLayout><EditTextandroid:id="@+id/purposeInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Cel wizyty"android:inputType="text"/><EditTextandroid:id="@+id/timeInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="time"android:text="16:00"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="OK"/><TextViewandroid:id="@+id/resultText"android:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout>
Ekran telefonu po tym kroku
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 16: Tablica gatunków podpięta do listy
Kryteria: ,
R.3.5 Zdefiniowano zmienną dowolnej kolekcji o typie tekstowym powiązaną z kontrolką listy, np. String[], List<string> z elementami: „Pies”, „Kot”, „Świnka morska”
R.3.6 Pole listy wypełniono elementami: „Pies”, „Kot”, „Świnka morska” (sprawdzić w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)
ok. 3 min
Polecenie z arkusza
Lista z elementami tekstowymi: „Pies”, „Kot”, „Świnka morska”.
Gatunki trzymamy w tablicy String[] species (R.3.5). Listę wypełnia ArrayAdapter: dostaje aktywność, systemowy wygląd wiersza android.R.layout.simple_list_item_1 (pojedynczy tekst) i tablicę. setAdapter łączy go z listą - pojawiają się trzy wiersze (R.3.6), a lista ma dokładnie ich wysokość.
Weterynarz/app/src/main/java/com/example/weterynarz/MainActivity.javaJavazmienione: 8 linii
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 17: Gatunek z listy zmienia maksimum suwaka
Kryteria:
R.3.8 Po wybraniu elementu z listy zmienia się wartość maksymalna suwaka na: 18 dla psa, 20 dla kota, 9 dla świnki morskiej (sprawdzić w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)
ok. 4 min
Polecenie z arkusza
Po kliknięciu gatunku z listy, wartość maksymalna suwaka zmienia się na: 18 dla psa, 20 dla kota, 9 dla świnki morskiej.
Maksymalny wiek zapisujemy w tablicy maxAges w tej samej kolejności co gatunki: indeks 0 to pies i 18, indeks 1 - kot i 20, indeks 2 - świnka i 9. Kliknięcie wiersza obsługuje setOnItemClickListener; parametr position to numer klikniętego wiersza, więc maxAges[position] daje od razu właściwe maksimum (R.3.8). Zapamiętujemy też wybrany gatunek - przyda się w podsumowaniu.
Słuchacza zapisujemy wyrażeniem lambda(parent, view, position, id) -> { ... } - to krótszy zapis klasy anonimowej z jedną metodą onItemClick.
Jeśli suwak stał wyżej niż nowe maksimum (np. 15, a wybrano świnkę), setMax sam przesuwa go na 9.
Weterynarz/app/src/main/java/com/example/weterynarz/MainActivity.javaJavazmienione: 10 linii
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 18: Suwak: wiek w napisie obok
Kryteria:
R.3.9 W momencie przesuwania suwaka wartość wieku z suwaka wyświetla się w polu tekstowym oznaczającym wiek zwierzęcia, zapis w postaci liczby całkowitej (sprawdzić w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)
ok. 3 min
Polecenie z arkusza
W momencie przesuwania suwaka zmienia się odpowiednio wartość wieku w polu tekstowym obok suwaka (obraz 3). Wartość wieku jest zawsze liczbą całkowitą.
Zmianę suwaka odbiera OnSeekBarChangeListener; potrzebna jest tylko metoda onProgressChanged, a jej parametr progress to liczba całkowita (R.3.9). setText wymaga tekstu, dlatego String.valueOf(progress).
Wybierz w podglądzie „Pies” i przesuń suwak do końca - wiek zatrzyma się na 18, jak na obrazie 3.
Typowe błędy
ageText.setText(progress) z liczbą - kompiluje się, bo Android traktuje liczbę jako identyfikator tekstu z zasobów, a po przesunięciu suwaka aplikacja zatrzymuje się z Resources$NotFoundException (R.3.9).
Weterynarz/app/src/main/java/com/example/weterynarz/MainActivity.javaJavazmienione: 18 linii
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 19: OK: dane wizyty pod przyciskiem
Kryteria:
R.3.7 Zdefiniowano funkcję powiązaną ze zdarzeniem kliknięcia przycisku. Funkcja wypisuje pod przyciskiem lub w oknie dane wpisane do kontrolek: właściciel, gatunek, wiek zwierzęcia, cel wizyty i czas. Dane są oddzielone przecinkiem (sprawdzić w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)
ok. 4 min
Polecenie z arkusza
Po kliknięciu przycisku, wartości z formularza: imię i nazwisko właściciela, gatunek, wiek, cel wizyty, czas są wyświetlane w postaci napisu pod przyciskiem albo w postaci okna z komunikatem. Poszczególne wartości są rozdzielone przecinkiem (obraz 2b i 2c). Formularz nie musi być walidowany.
Metodę showVisit wiążemy z przyciskiem atrybutem android:onClick (R.3.7). Skleja pięć wartości w kolejności z arkusza, oddzielonych przecinkiem: tekst z pola właściciela, zapamiętany gatunek, wiek z suwaka (getProgress()), cel wizyty i godzinę. Wynik trafia do napisu pod przyciskiem, jak na obrazie 2c.
Formularz nie musi być walidowany - jeśli nikt nie wybrał gatunku, zostaje pusty napis z deklaracji selectedSpecies = "".
Wybierz gatunek, ustaw wiek, wpisz właściciela i cel wizyty, kliknij „OK”.
Weterynarz/app/src/main/java/com/example/weterynarz/MainActivity.javaJavazmienione: 17 linii
Weterynarz/app/src/main/res/layout/activity_main.xmlXMLzmienione: 1 linia
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#90EE90"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="#2E8B57"android:padding="10dp"android:text="Wizyta u weterynarza"android:textSize="24sp"/><EditTextandroid:id="@+id/ownerInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Imię i nazwisko właściciela..."android:inputType="textPersonName"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Gatunek"/><ListViewandroid:id="@+id/speciesList"android:layout_width="match_parent"android:layout_height="wrap_content"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Ile ma lat?"/><TextViewandroid:id="@+id/ageText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:text="0"/><SeekBarandroid:id="@+id/ageSeekBar"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:max="20"android:progress="0"/></LinearLayout><EditTextandroid:id="@+id/purposeInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Cel wizyty"android:inputType="text"/><EditTextandroid:id="@+id/timeInput"android:layout_width="match_parent"android:layout_height="wrap_content"android:inputType="time"android:text="16:00"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="showVisit"android:text="OK"/><TextViewandroid:id="@+id/resultText"android:layout_width="match_parent"android:layout_height="wrap_content"/></LinearLayout>
Ekran telefonu po tym kroku
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
Krok 20: Uruchomienie w emulatorze, zrzuty i folder mobilna
Kryteria: ,
R.3.10 Aplikacja kompiluje się i uruchamia w emulatorze, co udokumentowano zrzutem ekranu. Jej układ jest zgodny z obrazem 1a lub 1b w arkuszu egzaminacyjnym
R.4.7 Zapisano przynajmniej jeden zrzut ekranu z uruchomienia lub kompilacji aplikacji mobilnej, na zrzucie widoczne jest środowisko, w którym powstała aplikacja
ok. 4 min
Polecenie z arkusza
Aplikacja mobilna – dokumentująca interakcje dowolna liczba zrzutów o nazwach mobile1, mobile2, ... (co najmniej stan początkowy, zmiana wartości maksymalnej suwaka, np. dla psa, zmiany suwaka, po zatwierdzeniu przyciskiem). W podfolderze mobilna zapisz archiwum całego projektu o nazwie mobilna.zip, plik (lub pliki) z kodem źródłowym interfejsu użytkownika (XAML lub XML) oraz plik źródłowy kodu skojarzonego z interfejsem użytkownika.
Uruchamiamy aplikację w emulatorze. Zrzuty całego ekranu z Android Studio do folderu dokumentacja: mobile1 - stan początkowy, mobile2 - po wybraniu psa, mobile3 - suwak przesunięty, mobile4 - po kliknięciu „OK” (R.3.10, R.4.7). W folderze mobilna: mobilna.zip, activity_main.xml, MainActivity.java.
Kroki 21-22 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 21: Nagłówek klasy StringTools według listingu 1
Kryteria: , , , ,
R.4.1 Dla klasy z aplikacji konsolowej zapisano nagłówek w postaci komentarza zgodny z Listingiem 1 z arkusza egzaminacyjnego (nie liczymy gwiazdek), komentarz może być wieloliniowy lub kilka jednoliniowych lub Docstrings (potrójny cudzysłów) - w tym przypadku opis znajduje się pod słowem class (na początku definicji klasy)
R.4.2 W komentarzu ujęto nazwę i opis działania klasy
R.4.3 W komentarzu ujęto nazwy tylu metod ile znajduje się w klasie
R.4.4 Dla metod, które ujęto w komentarzu zapisano opis
R.4.5 W komentarzu ujęto numer zdającego
ok. 4 min
Polecenie z arkusza
W kodzie źródłowym aplikacji konsolowej utwórz komentarz do klasy, według wzoru z listingu 1. Komentarz powinien znaleźć się nad klasą lub pod jej nagłówkiem. W miejscu nawiasów <> należy podać odpowiednie opisy. W miejscu autor należy podać numer zdającego.
Komentarz wieloliniowy /* ... */ nad public class StringTools z polami listingu 1 (R.4.1): nazwa klasy i opis, co reprezentuje i wykonuje (R.4.2), obie metody (R.4.3), każda z opisem, co zwraca (R.4.4), i autor (R.4.5). Na egzaminie w polu autor wpisujemy numer PESEL - tu stoi Bartosz Bryniarski.
konsola/src/StringTools.javaJavazmienione: 11 linii
/* ****************************************************** klasa: StringTools opis: biblioteka narzędzi dla napisów; nie tworzy się jej obiektów, wszystkie metody są statyczne metody: countVowels - zwraca liczbę samogłosek w tekście (0 dla null i pustego tekstu) removeRepeats - zwraca tekst bez znaków powtórzonych obok siebie (pusty tekst dla null i pustego tekstu) autor: Bartosz Bryniarski ****************************************************** */publicclassStringTools {privatestaticfinal String VOWELS = "aąeęiouóyAĄEĘIOUÓY";publicstaticintcountVowels(String text) {if (text == null || text.isEmpty()) {return0; }int count = 0;for (int i = 0; i < text.length(); i++) {if (VOWELS.indexOf(text.charAt(i)) >= 0) { count++; } }return count; }publicstatic String removeRepeats(String text) {if (text == null || text.isEmpty()) {return""; } StringBuilder result = new StringBuilder();for (int i = 0; i < text.length(); i++) {if (i == text.length() - 1 || text.charAt(i) != text.charAt(i + 1)) { result.append(text.charAt(i)); } }return result.toString(); }}
Wynik programu po tym kroku
> java Main
Podaj tekst: Abba;;;to zespół
Liczba samogłosek: 5
Tekst bez powtórzeń: Aba;to zespół
Krok 22: Dokument egzamin
Kryteria:
R.4.8 Dokumentacja zawiera: nazwę systemu operacyjnego, nazwy środowisk, emulatora, nazwy języków programowania
ok. 3 min
Polecenie z arkusza
W edytorze tekstu pakietu biurowego utwórz plik z dokumentacją i nazwij go egzamin. Dokument powinien zawierać podpisane zrzuty ekranu oraz zapisane informacje dotyczące narzędzi, z których korzystał zdający podczas egzaminu: nazwę systemu operacyjnego, nazwy środowisk programistycznych, nazwy języków programowania, nazwę emulatora dla aplikacji mobilnej.
W Wordzie albo Writerze dokument egzamin w folderze dokumentacja: podpisane zrzuty, system, środowiska, języki i emulator (R.4.8).
egzamin.txtTekstnowy plik
Zrzuty ekranu: konsola1, konsola2 - oba przykłady z arkusza; mobile1 - stan początkowy; mobile2 - wybrany pies (maksimum 18); mobile3 - przesunięty suwak; mobile4 - podsumowanie po kliknięciu OKSystem operacyjny: Windows 11Środowiska programistyczne: IntelliJ IDEA (aplikacja konsolowa), Android Studio (aplikacja mobilna)Języki programowania: Java (aplikacja konsolowa i mobilna), XML (układ aplikacji mobilnej)Emulator: Pixel 8 (Android 16, API 36) z Android Studio
Kroki 23-24 · po tym etapie masz 34 z 34 kryteriów (pkt)
Krok 23: Konsola: klasa, której obiektu nie da się utworzyć
ok. 2 min
Polecenie z arkusza
Klasa ma charakter biblioteki narzędziowej, nie jest przewidziane powoływanie obiektów tej klasy.
Arkusz mówi, że obiektów tej klasy nie tworzymy - ale new StringTools() nadal się kompiluje, bo Java dodaje domyślny konstruktor publiczny. Prywatny konstruktor blokuje tworzenie obiektów poza klasą, a final - dziedziczenie po niej. Tak zbudowane są klasy narzędziowe biblioteki Javy, np. Math.
Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
konsola/src/StringTools.javaJavazmienione: 6 linii
/* ****************************************************** klasa: StringTools opis: biblioteka narzędzi dla napisów; nie tworzy się jej obiektów, wszystkie metody są statyczne metody: countVowels - zwraca liczbę samogłosek w tekście (0 dla null i pustego tekstu) removeRepeats - zwraca tekst bez znaków powtórzonych obok siebie (pusty tekst dla null i pustego tekstu) autor: Bartosz Bryniarski ****************************************************** */publicfinalclassStringTools {privateStringTools() {// klasa narzędziowa - obiektów nie tworzymy }privatestaticfinal String VOWELS = "aąeęiouóyAĄEĘIOUÓY";publicstaticintcountVowels(String text) {if (text == null || text.isEmpty()) {return0; }int count = 0;for (int i = 0; i < text.length(); i++) {if (VOWELS.indexOf(text.charAt(i)) >= 0) { count++; } }return count; }publicstatic String removeRepeats(String text) {if (text == null || text.isEmpty()) {return""; } StringBuilder result = new StringBuilder();for (int i = 0; i < text.length(); i++) {if (i == text.length() - 1 || text.charAt(i) != text.charAt(i + 1)) { result.append(text.charAt(i)); } }return result.toString(); }}
Wynik programu po tym kroku
> java Main
Podaj tekst: Przykład tekstu
Liczba samogłosek: 4
Tekst bez powtórzeń: Przykład tekstu
Krok 24: Android: podsumowanie przez String.join
ok. 2 min
Polecenie z arkusza
Poszczególne wartości są rozdzielone przecinkiem (obraz 2b i 2c).
Sklejanie + ", " + pięć razy łatwo popsuć - wystarczy zgubić jeden przecinek. String.join(", ", ...) wstawia separator między wszystkie podane wartości sam, a każda wartość stoi w osobnym wierszu kodu. trim() usuwa przypadkowe spacje z początku i końca wpisanego tekstu.
Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.
Weterynarz/app/src/main/java/com/example/weterynarz/MainActivity.javaJavazmienione: 6 linii
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). Treść arkusza i klucza oceniania pochodzi z CKE.