Przejdź do głównej treści
INF.04-02-24.06-SGCzerwiec 2024 · 26 kroków · ok. 76 min · 31 kryteriów z klucza

Rozwiązanie krok po kroku: Aplikacja MojeDźwięki z albumami (C# + WPF)

Rozwiązujemy arkusz z albumami muzycznymi w wersji C# + WPF: w konsoli klasa Album z polami z pliku DataStructure.txt, metoda czytająca wszystkie rekordy z Data.txt do listy i metoda wypisująca je jeden pod drugim, a w aplikacji desktopowej okno „MojeDźwięki” z płytą winylową, danymi albumu, przyciskami przewijania (z przejściem z pierwszego na ostatni i odwrotnie) i przyciskiem „Pobierz”, który zwiększa licznik pobrań. Do tego dokumentacja metody według listingu 1, zrzuty i dokument egzamin.

Kroki idą zdanie po zdaniu za treścią arkusza - każdy zaczyna się cytatem wymagania, 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 (.NET 10) na pliku Data.txt z archiwum pliki2.zip, a wypisane rekordy porównaliśmy z plikiem odczytanym niezależnie. Okno aplikacji to symulacja WPF w przeglądarce zbudowana z XAML danego kroku, z grafikami i danymi z archiwum; jej zachowanie odpowiada kodowi C# z kroku. Każdy stan okna sprawdziliśmy na prawdziwym WPF - także przejścia przez pierwszy i ostatni album i zapamiętanie pobrań.

Arkusz pozwala też na C++, Javę albo Pythona i na inne biblioteki okienkowe - ten wariant to jedna z możliwych dróg.

Jak liczą się punkty. Klucz ma 31 kryteriów (R.1.1 - R.4.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 24 punkty - można stracić 7 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.

  1. Etap 1: Przygotowanie

    Krok 1 · po tym etapie masz 0 z 31 kryteriów (pkt)

    Krok 1: Folder zdającego, podfoldery i archiwum pliki2.zip

    ok. 3 min
    Polecenie z arkusza

    Do rozwiązania zadania wykorzystaj archiwum pliki2.zip z hasłem: My^SoUndS. Utwórz folder i nazwij go numerem zdającego. W folderze utwórz podfoldery: konsolowa, desktopowa, dokumentacja.

    Na pulpicie zakładamy folder o nazwie z numerem PESEL, a w nim konsolowa, desktopowa i dokumentacja. Archiwum pliki2.zip rozpakowujemy hasłem z arkusza. W środku: Data.txt z 14 albumami (po pięć wierszy na album, albumy oddzielone pustym wierszem), DataStructure.txt z opisem pól i trzy grafiki do aplikacji desktopowej.

  2. Etap 2: Aplikacja konsolowa

    Kroki 2-6 · po tym etapie masz 12 z 31 kryteriów (pkt)

    Krok 2: Projekt konsola w C#

    ok. 3 min
    Polecenie z arkusza

    Za pomocą narzędzi do tworzenia aplikacji konsolowych utwórz program do odczytywania i wyświetlania danych z pliku. Zastosowany obiektowy język programowania zgodny z zainstalowanym na stanowisku egzaminacyjnym: C++ lub C#, lub Java, lub Python. Podejście obiektowe lub strukturalne.

    Wybieramy C# i podejście obiektowe. W Visual Studio: Utwórz nowy projekt → Aplikacja konsolowa, nazwa konsola. W Program.cs zostawiamy klasę Program z pustą metodą Main.

    konsola/Program.cs C# nowy plik
    class Program
    {
        static void Main()
        {
        }
    }
    konsola/konsola.csproj Projekt C# nowy plik
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net10.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
    </Project>
  3. Krok 3: Klasa Album z pięcioma polami

    Kryteria: , ,

    R.2.1 W programie zdefiniowano strukturę lub klasę. Do zapisu danych zastosowano dwa typy napisowe, następnie trzy typy całkowite

    R.1.4 Użyto polskie lub angielskie nazewnictwo pól i zmiennych. Nazewnictwo jest znaczące. Wyjątkami od reguły są zmienne: bufor, tmp, iteratory pętli. Kryterium nie jest spełnione tylko wtedy, gdy nazwy zmiennych nic nie znaczą, np.: x, tab, tablica, foo

    R.1.5 Zastosowano typy pasujące do problemu, np. typ plikowy, typ napisowy i typ liczbowy. W przypadku Python, tam gdzie jest to wymagane, zastosowano jawną konwersję do odpowiednich typów

    ok. 3 min
    Polecenie z arkusza

    Plik DataStructure.txt zawiera strukturę rekordu danych o albumach muzycznych. Przy podejściu obiektowym należy utworzyć klasę o takich polach, a przy podejściu strukturalnym - strukturę. Należy dobrać odpowiednie typy dla pól pasujące do danych zamieszczonych w pliku Data.txt. Dla liczby pobrań należy zastosować typ przynajmniej 32 bitowy.

    Pola w kolejności z DataStructure.txt: wykonawca i tytuł to tekst (string), liczba utworów i rok - liczby całkowite (int), liczba pobrań - long (R.2.1, R.1.5).

    Dlaczego long? Największa liczba pobrań w pliku to 1 506 404 300. Typ int (32 bity) mieści jeszcze tę wartość - jego maksimum to około 2,1 miliarda - więc spełnia wymaganie arkusza. Ale po kolejnych pobraniach albo nowych albumach w pliku łatwo go przekroczyć, a long (64 bity) sięga trylionów. Typ short (16 bitów) obciąłby liczbę i dał bzdurną wartość.

    Pola są publiczne (public), żeby Program mógł je wypełniać. Nazwy po angielsku, jak w pliku struktury (R.1.4).

    Typowe błędy

    int.Parse dla liczby pobrań przy polu int działa dla danych z arkusza, ale short albo byte już nie - R.2.6 sprawdza, czy 1506404300 wyświetla się w całości.

    konsola/Program.cs C# zmienione: 9 linii
    class Album
    {
        public string Artist;
        public string Title;
        public int SongsNumber;
        public int Year;
        public long DownloadNumber;
    }
    
    class Program
    {
        static void Main()
        {
        }
    }
  4. Krok 4: Metoda ReadAlbums: wszystkie rekordy z Data.txt do listy

    Kryteria: , , ,

    R.2.2 Zdefiniowano funkcję operującą na pliku, która stosuje prawidłową dla języka programowania technikę odczytania danych z pliku oraz zamknięcia pliku (jeśli jest wymagane) na końcu tych działań

    R.2.3 Odczytywanie danych z pliku lub podział na rekordy ujęto w pętli; działa również, gdy w pliku zmieni się liczba rekordów

    R.2.4 Kolejne rekordy są umieszczane w tablicy lub dowolnej kolekcji. Pola rekordów poprawnie wypełniono, kolejno: artysta, album, liczba piosenek, rok, liczba pobrań

    R.1.3 Użyto polskie lub angielskie nazewnictwo metod / funkcji. Nazewnictwo jest znaczące

    ok. 5 min
    Polecenie z arkusza

    Dane są wczytane z pliku Data.txt (muszą zostać wczytane wszystkie dane zawarte w pliku). Należy założyć, że do pliku mogą zostać dopisane nowe albumy, przy czym jego struktura nigdy się nie zmienia oraz plik jest zawsze poprawny strukturalnie. Dane jednego rekordu są przypisane do odpowiednich pól obiektu lub struktury. Każdy rekord jest zapisywany w tablicy lub dowolnej kolekcji. Wczytanie odbywa się w osobnej metodzie lub funkcji.

    Plik do projektu: kopiujemy Data.txt do folderu projektu i w Visual Studio ustawiamy jego właściwość Kopiuj do katalogu wyjściowego: Kopiuj, jeśli nowszy - w pliku projektu pojawia się wpis CopyToOutputDirectory. Wtedy plik leży obok konsola.exe i program znajdzie go po samej nazwie.

    Metoda ReadAlbums (R.2.2):

    • StreamReader otwiera plik tekstowy (sam rozpoznaje kodowanie UTF-8 z BOM, w którym zapisano Data.txt),
    • pętla while (!reader.EndOfStream) działa, dopóki w pliku są dane - nie zakładamy, że albumów jest 14, więc dopisane albumy też się wczytają (R.2.3),
    • jeden obrót pętli to jeden album: pięć wierszy po kolei do pól, liczby zamieniane z tekstu przez int.Parse i long.Parse, szósty wiersz - pusty separator - czytamy i pomijamy,
    • obiekt dodajemy do listy List<Album> - kolekcji, która rośnie sama (R.2.4),
    • reader.Close() zamyka plik po odczycie.
    Typowe błędy

    Tablica new Album[14] z liczbą albumów wpisaną na sztywno nie wczyta albumów dopisanych do pliku - R.2.3 wymaga pętli działającej dla dowolnej liczby rekordów.

    konsola/Program.cs C# zmienione: 19 linii
    class Album
    {
        public string Artist;
        public string Title;
        public int SongsNumber;
        public int Year;
        public long DownloadNumber;
    }
    
    class Program
    {
        static List<Album> ReadAlbums(string fileName)
        {
            List<Album> albums = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albums.Add(album);
            }
            reader.Close();
            return albums;
        }
    
        static void Main()
        {
        }
    }
    konsola/konsola.csproj Projekt C# zmienione: 6 linii
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net10.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
      </PropertyGroup>
    
      <ItemGroup>
        <None Include="Data.txt">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
      </ItemGroup>
    
    </Project>
  5. Krok 5: Metoda ShowAlbums i program główny

    Kryteria: , , , ,

    R.2.5 Wyświetlanie danych odbywa się w pętli

    R.2.6 Największa liczba pobrań o wartości 1506404300 została prawidłowo wyświetlona (nie jest obcięta ani ujemna) lub, gdy program nie uruchamia się, zastosowano co najmniej 32- bitową konwersję i co najmniej 32-bitowy typ

    R.2.8 Program wyświetla wszystkie rekordy zapisane w tablicy lub kolekcji. Nie należy brać pod uwagę błędów wyświetlenia spowodowanych kodowaniem znaków

    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 instrukcji blokowej

    R.1.2 Kod zapisano z wcięciami dla zagnieżdżeń bloków

    ok. 3 min
    Polecenie z arkusza

    Dane z każdego rekordu są kolejno wyświetlane w konsoli, w osobnych liniach, patrz obraz 1. Wyświetlonych jest tyle rekordów, ile faktycznie zostało wczytanych. Wyświetlenie odbywa się w osobnej metodzie lub funkcji.

    ShowAlbums dostaje listę i pętlą foreach wypisuje każdy album - pole w osobnym wierszu, po albumie pusty wiersz, jak na obrazie 1 (R.2.5). Pętla przechodzi przez tyle albumów, ile jest na liście, czyli tyle, ile wczytano (R.2.8). Main tylko łączy obie metody.

    Podgląd to prawdziwe uruchomienie na pliku z archiwum: 14 albumów, a pobrania Metalliki, 1506404300, wyświetlają się w całości (R.2.6).

    konsola/Program.cs C# zmienione: 15 linii
    class Album
    {
        public string Artist;
        public string Title;
        public int SongsNumber;
        public int Year;
        public long DownloadNumber;
    }
    
    class Program
    {
        static List<Album> ReadAlbums(string fileName)
        {
            List<Album> albums = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albums.Add(album);
            }
            reader.Close();
            return albums;
        }
    
        static void ShowAlbums(List<Album> albums)
        {
            foreach (Album album in albums)
            {
                Console.WriteLine(album.Artist);
                Console.WriteLine(album.Title);
                Console.WriteLine(album.SongsNumber);
                Console.WriteLine(album.Year);
                Console.WriteLine(album.DownloadNumber);
                Console.WriteLine();
            }
        }
    
        static void Main()
        {
            List<Album> albums = ReadAlbums("Data.txt");
            ShowAlbums(albums);
        }
    }
    Wynik programu po tym kroku
    > konsola.exe
    Gorillaz
    "The Now Now"
    11
    2018
    11000102
    
    My Chemical Romance
    "The Black Parade"
    14
    2006
    304666444
    
    Wilki
    "wilki"
    16
    1992
    4000230
    
    30 Seconds To Mars
    "A Beautiful Lie"
    13
    2009
    300120222
    
    30 Seconds To Mars
    "This Is War"
    15
    2009
    22000000
    
    Melanie Martinez
    "Cry Baby"
    16
    2015
    400345042
    
    The Rasmus
    "Dead Letters"
    10
    2003
    253453
    
    Metallica
    "Metallica"
    12
    1991
    1506404300
    
    Meskie Granie Orkiestra 2022
    "Meskie Granie 2022"
    30
    2022
    243085
    
    Krzysztof Zalewski
    "Zloto"
    11
    2016
    4586200
    
    The Cure
    "Disintegration"
    11
    1989
    130000560
    
    Pink Floyd
    "The Division Bell"
    11
    1994
    24332190
    
    Depeche Mode
    "Spirit"
    17
    2017
    24300453
    
    Faith No More
    "Angel Dust"
    14
    1992
    55384200
  6. Krok 6: Folder konsolowa: archiwum, źródło i plik wykonywalny

    ok. 2 min
    Polecenie z arkusza

    Kod aplikacji przygotuj do nagrania na płytę. W folderze konsolowa powinno znaleźć się archiwum całego projektu o nazwie konsola.zip, skopiowany z projektu plik z kodem źródłowym programu oraz plik wykonywalny, jeżeli istnieje.

    Folder projektu (z Data.txt) pakujemy do konsola.zip, obok kopiujemy Program.cs i konsola.exe. Archiwum robimy na końcu, po dopisaniu komentarza z części III.

    Wynik programu bez zmian - taki jak po kroku 5.

  7. Etap 3: Aplikacja desktopowa

    Kroki 7-19 · po tym etapie masz 21 z 31 kryteriów (pkt)

    Krok 7: Nowy projekt WPF desktopowa

    ok. 3 min
    Polecenie z arkusza

    Za pomocą dostępnego na stanowisku egzaminacyjnym środowiska programistycznego wykonaj aplikację desktopową będącą interfejsem graficznym programu utworzonego w konsoli.

    W Visual Studio: Utwórz nowy projekt → Aplikacja WPF, nazwa desktopowa. Wygląd w MainWindow.xaml, logika w MainWindow.xaml.cs; dojdzie jeszcze plik z klasą Album i zmiany w pliku projektu (grafiki i dane).

    desktopowa/MainWindow.xaml XAML nowy plik
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Grid>
    
        </Grid>
    </Window>
    desktopowa/MainWindow.xaml.cs C# nowy plik
    using System.Windows;
    
    namespace desktopowa;
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
    desktopowa/desktopowa.csproj Projekt C# nowy plik
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net10.0-windows</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <UseWPF>true</UseWPF>
      </PropertyGroup>
    
    </Project>
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  8. Krok 8: Tytuł, rozmiar i tło okna

    Kryteria: ,

    R.3.1 Dla okna aplikacji nadano nazwę "MojeDźwięki, Wykonał:" wraz z numerem zdającego oraz umieszczono w oknie trzy przyciski, w tym jeden z treścią "Pobierz", pięć napisów (etykiet) oraz obraz

    R.3.2 Nadano dla okna tło koloru SeaGreen (#2E8B57). Odpowiednim napisom, zgodnie z obrazem 1 w arkuszu egzaminacyjnym nadano kolory: biały i #61D918 oraz nadano rozmiar czcionki 50 (artysta), 30 (tytuł) i 20 (pozostałe). Czcionka tytułu jest pochylona, czcionka przycisku jest pogrubiona

    ok. 2 min
    Polecenie z arkusza

    Okno o nazwie „MojeDźwięki, Wykonał:” następnie wstawiony numer zdającego. Okno ma tło koloru SeaGreen (#2E8B57).

    Title z arkusza - na egzaminie po „Wykonał:” wpisujemy numer PESEL, tu stoi Bartosz Bryniarski. Okno szerokie i niskie jak na obrazie 2, tło kodem SeaGreen (R.3.2).

    desktopowa/MainWindow.xaml XAML zmienione: 2 linie
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
    
        </Grid>
    </Window>
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  9. Krok 9: Dwa przyciski ze strzałkami z grafik

    Kryteria: ,

    R.3.1 Dla okna aplikacji nadano nazwę "MojeDźwięki, Wykonał:" wraz z numerem zdającego oraz umieszczono w oknie trzy przyciski, w tym jeden z treścią "Pobierz", pięć napisów (etykiet) oraz obraz

    R.3.3 Przynajmniej jeden przycisk jest wypełniony grafiką z pliku obraz2.png lub obraz3.png oraz obraz jest wypełniony grafiką z pliku obraz.png

    ok. 3 min
    Polecenie z arkusza

    Kontrolki rozmieszczone i formatowane zgodnie z obrazem 2: Dwa przyciski po prawej i lewej stronie, przyciski są wypełnione grafiką z plików obraz2.png i obraz3.png. Wysokość obrazów 70.

    Grafiki z archiwum kopiujemy do projektu jako zasoby (Akcja kompilacji: Resource - wpis Resource w pliku projektu); zostają wbudowane w program.

    Okno dzielimy na cztery kolumny: przycisk wstecz, płyta, dane albumu, przycisk dalej. Przycisk w WPF może zawierać dowolną kontrolkę, nie tylko tekst - zamiast Content="..." wstawiamy do środka Image z grafiką strzałki i wysokością 70 (R.3.3). Uwaga na pliki: obraz2.png to strzałki w prawo, a obraz3.png w lewo - dlatego przycisk po lewej dostaje obraz3.png, jak na obrazie 2. Przyciski mają nazwy, bo podepniemy do nich zdarzenia, a VerticalAlignment="Center" ustawia je w połowie wysokości okna.

    desktopowa/MainWindow.xaml XAML zmienione: 12 linii
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160" />
                <ColumnDefinition Width="240" />
                <ColumnDefinition />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <Button x:Name="previousButton" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz3.png" Height="70" />
            </Button>
            <Button x:Name="nextButton" Grid.Column="3" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz2.png" Height="70" />
            </Button>
        </Grid>
    </Window>
    desktopowa/desktopowa.csproj Projekt C# zmienione: 4 linie
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net10.0-windows</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <UseWPF>true</UseWPF>
      </PropertyGroup>
    
      <ItemGroup>
        <Resource Include="obraz.png;obraz2.png;obraz3.png" />
      </ItemGroup>
    
    </Project>
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  10. Krok 10: Obraz płyty winylowej

    Kryteria: ,

    R.3.1 Dla okna aplikacji nadano nazwę "MojeDźwięki, Wykonał:" wraz z numerem zdającego oraz umieszczono w oknie trzy przyciski, w tym jeden z treścią "Pobierz", pięć napisów (etykiet) oraz obraz

    R.3.3 Przynajmniej jeden przycisk jest wypełniony grafiką z pliku obraz2.png lub obraz3.png oraz obraz jest wypełniony grafiką z pliku obraz.png

    ok. 2 min
    Polecenie z arkusza

    Obraz płyty winylowej z pliku obraz.png.

    W drugiej kolumnie pionowy StackPanel z kontrolką Image - pod płytą dołożymy jeszcze liczbę pobrań i przycisk „Pobierz”.

    desktopowa/MainWindow.xaml XAML zmienione: 3 linie
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160" />
                <ColumnDefinition Width="240" />
                <ColumnDefinition />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <Button x:Name="previousButton" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz3.png" Height="70" />
            </Button>
            <StackPanel Grid.Column="1" Margin="0,20,0,0">
                <Image Source="obraz.png" Width="200" Height="200" />
            </StackPanel>
            <Button x:Name="nextButton" Grid.Column="3" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz2.png" Height="70" />
            </Button>
        </Grid>
    </Window>
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  11. Krok 11: Etykiety: wykonawca, tytuł, liczba utworów i rok

    Kryteria: ,

    R.3.1 Dla okna aplikacji nadano nazwę "MojeDźwięki, Wykonał:" wraz z numerem zdającego oraz umieszczono w oknie trzy przyciski, w tym jeden z treścią "Pobierz", pięć napisów (etykiet) oraz obraz

    R.3.2 Nadano dla okna tło koloru SeaGreen (#2E8B57). Odpowiednim napisom, zgodnie z obrazem 1 w arkuszu egzaminacyjnym nadano kolory: biały i #61D918 oraz nadano rozmiar czcionki 50 (artysta), 30 (tytuł) i 20 (pozostałe). Czcionka tytułu jest pochylona, czcionka przycisku jest pogrubiona

    ok. 4 min
    Polecenie z arkusza

    5 napisów (etykiet) kolejno z nazwą wykonawcy, tytułem albumu, liczbą utworów, rokiem wydania i liczbą pobrań. Formatowanie napisów: kolor czcionki biały i #61D918, rozmiary czcionek: 50, 30, 20, czcionka pochylona dla nazwy albumu. Zgodnie z obrazem 2.

    Trzecia kolumna: wykonawca 50 i biały, tytuł 30, biały i pochylony (FontStyle="Italic"), a w poziomym panelu liczba utworów i rok - 20 w kolorze #61D918 (R.3.2). Cudzysłów w treści atrybutu XAML zapisujemy encją &quot;.

    Na razie wpisujemy w etykiety dane pierwszego albumu na sztywno, żeby zobaczyć wygląd - za chwilę będzie je ustawiał kod. Każda etykieta ma nazwę (artistLabel, titleLabel...), żeby kod mógł zmienić jej treść.

    desktopowa/MainWindow.xaml XAML zmienione: 8 linii
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160" />
                <ColumnDefinition Width="240" />
                <ColumnDefinition />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <Button x:Name="previousButton" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz3.png" Height="70" />
            </Button>
            <StackPanel Grid.Column="1" Margin="0,20,0,0">
                <Image Source="obraz.png" Width="200" Height="200" />
            </StackPanel>
            <StackPanel Grid.Column="2" Margin="20,25,0,0">
                <Label x:Name="artistLabel" Content="Gorillaz" FontSize="50" Foreground="White" />
                <Label x:Name="titleLabel" Content="&quot;The Now Now&quot;" FontSize="30" FontStyle="Italic" Foreground="White" />
                <StackPanel Orientation="Horizontal">
                    <Label x:Name="songsLabel" Content="11 utworów" FontSize="20" Foreground="#61D918" />
                    <Label x:Name="yearLabel" Content="2018" FontSize="20" Foreground="#61D918" Margin="40,0,0,0" />
                </StackPanel>
            </StackPanel>
            <Button x:Name="nextButton" Grid.Column="3" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz2.png" Height="70" />
            </Button>
        </Grid>
    </Window>
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  12. Krok 12: Liczba pobrań i przycisk Pobierz

    Kryteria: ,

    R.3.1 Dla okna aplikacji nadano nazwę "MojeDźwięki, Wykonał:" wraz z numerem zdającego oraz umieszczono w oknie trzy przyciski, w tym jeden z treścią "Pobierz", pięć napisów (etykiet) oraz obraz

    R.3.2 Nadano dla okna tło koloru SeaGreen (#2E8B57). Odpowiednim napisom, zgodnie z obrazem 1 w arkuszu egzaminacyjnym nadano kolory: biały i #61D918 oraz nadano rozmiar czcionki 50 (artysta), 30 (tytuł) i 20 (pozostałe). Czcionka tytułu jest pochylona, czcionka przycisku jest pogrubiona

    ok. 2 min
    Polecenie z arkusza

    Przycisk o treści „Pobierz”. Formatowanie przycisku do pobrania: kolor tła #61D918, czcionka pogrubiona, rozmiaru 20.

    Pod płytą poziomy panel: piąta etykieta z liczbą pobrań (20, #61D918) i przycisk „Pobierz” - tło #61D918, FontWeight="Bold", FontSize="20". Okno ma wszystkie kontrolki z obrazu 2: trzy przyciski, pięć etykiet i obraz (R.3.1).

    desktopowa/MainWindow.xaml XAML zmienione: 4 linie
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160" />
                <ColumnDefinition Width="240" />
                <ColumnDefinition />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <Button x:Name="previousButton" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz3.png" Height="70" />
            </Button>
            <StackPanel Grid.Column="1" Margin="0,20,0,0">
                <Image Source="obraz.png" Width="200" Height="200" />
                <StackPanel Orientation="Horizontal" Margin="0,15,0,0">
                    <Label x:Name="downloadsLabel" Content="11000102" FontSize="20" Foreground="#61D918" Width="140" />
                    <Button x:Name="downloadButton" Content="Pobierz" FontSize="20" FontWeight="Bold" Background="#61D918" Width="90" />
                </StackPanel>
            </StackPanel>
            <StackPanel Grid.Column="2" Margin="20,25,0,0">
                <Label x:Name="artistLabel" Content="Gorillaz" FontSize="50" Foreground="White" />
                <Label x:Name="titleLabel" Content="&quot;The Now Now&quot;" FontSize="30" FontStyle="Italic" Foreground="White" />
                <StackPanel Orientation="Horizontal">
                    <Label x:Name="songsLabel" Content="11 utworów" FontSize="20" Foreground="#61D918" />
                    <Label x:Name="yearLabel" Content="2018" FontSize="20" Foreground="#61D918" Margin="40,0,0,0" />
                </StackPanel>
            </StackPanel>
            <Button x:Name="nextButton" Grid.Column="3" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz2.png" Height="70" />
            </Button>
        </Grid>
    </Window>
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  13. Krok 13: Klasa Album i wczytanie danych przy starcie okna

    Kryteria:

    R.3.4 W zmiennych aplikacji zawarto informację o albumach

    ok. 4 min
    Polecenie z arkusza

    Działanie aplikacji po załadowaniu okna: Wczytuje dane z pliku Dane.txt.

    Logikę bierzemy z konsoli (arkusz na to pozwala):

    • klasę Album przenosimy do osobnego pliku Album.cs w projekcie (Dodaj → Klasa) - pola mają wartość początkową "", bo projekt WPF sprawdza wartości null,
    • metodę ReadAlbums kopiujemy do okna, a wynik zapisujemy w polu albums - lista żyje tak długo jak okno, więc przyciski będą z niej korzystać (R.3.4),
    • wczytanie wywołujemy w konstruktorze, po InitializeComponent() - czyli przy otwarciu okna.

    Arkusz w tym zdaniu nazywa plik Dane.txt, ale w archiwum jest Data.txt - ten sam plik co w konsoli. Używamy pliku z archiwum (kopiowanego obok programu, jak w konsoli). Okno wygląda tak samo, bo etykiety mają jeszcze treść wpisaną w XAML.

    desktopowa/Album.cs C# nowy plik
    namespace desktopowa;
    
    public class Album
    {
        public string Artist = "";
        public string Title = "";
        public int SongsNumber;
        public int Year;
        public long DownloadNumber;
    }
    desktopowa/MainWindow.xaml.cs C# zmienione: 23 linie
    using System.IO;
    using System.Windows;
    
    namespace desktopowa;
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Album> albums = new List<Album>();
    
        public MainWindow()
        {
            InitializeComponent();
            albums = ReadAlbums("Data.txt");
        }
    
        private List<Album> ReadAlbums(string fileName)
        {
            List<Album> albumList = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albumList.Add(album);
            }
            reader.Close();
            return albumList;
        }
    }
    desktopowa/desktopowa.csproj Projekt C# zmienione: 3 linie
    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net10.0-windows</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <UseWPF>true</UseWPF>
      </PropertyGroup>
    
      <ItemGroup>
        <Resource Include="obraz.png;obraz2.png;obraz3.png" />
        <None Include="Data.txt">
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
      </ItemGroup>
    
    </Project>

    Okno aplikacji bez zmian - taki jak po kroku 12.

  14. Krok 14: Pierwszy album na starcie: metoda ShowAlbum

    Kryteria: ,

    R.3.5 W stanie początkowym aplikacja wyświetla dane zgodne z obrazem 1 arkusza egzaminacyjnego (w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)

    R.3.9 Aplikacja kompiluje się i uruchamia, co udokumentowano zrzutem ekranu, jej układ po uruchomieniu jest zgodny z obrazem 1 w arkuszu egzaminacyjnym

    ok. 3 min
    Polecenie z arkusza

    Dane pierwszego albumu są wyświetlane zgodnie z obrazem 2.

    Usuwamy z XAML treść wpisaną na sztywno - teraz etykiety wypełnia kod. Pole currentIndex pamięta, który album jest wyświetlany (0 = pierwszy). Metoda ShowAlbum bierze album o tym indeksie i przepisuje jego pola do etykiet; do liczby utworów dokleja słowo „utworów”. Konstruktor wywołuje ją zaraz po wczytaniu danych - okno startuje z Gorillaz, jak na obrazie 2 (R.3.5, R.3.9).

    Z ShowAlbum skorzystają wszystkie trzy przyciski: każdy zmieni stan, a potem poprosi o odświeżenie widoku.

    desktopowa/MainWindow.xaml XAML zmienione: 5 linii
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160" />
                <ColumnDefinition Width="240" />
                <ColumnDefinition />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <Button x:Name="previousButton" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz3.png" Height="70" />
            </Button>
            <StackPanel Grid.Column="1" Margin="0,20,0,0">
                <Image Source="obraz.png" Width="200" Height="200" />
                <StackPanel Orientation="Horizontal" Margin="0,15,0,0">
                    <Label x:Name="downloadsLabel" FontSize="20" Foreground="#61D918" Width="140" />
                    <Button x:Name="downloadButton" Content="Pobierz" FontSize="20" FontWeight="Bold" Background="#61D918" Width="90" />
                </StackPanel>
            </StackPanel>
            <StackPanel Grid.Column="2" Margin="20,25,0,0">
                <Label x:Name="artistLabel" FontSize="50" Foreground="White" />
                <Label x:Name="titleLabel" FontSize="30" FontStyle="Italic" Foreground="White" />
                <StackPanel Orientation="Horizontal">
                    <Label x:Name="songsLabel" FontSize="20" Foreground="#61D918" />
                    <Label x:Name="yearLabel" FontSize="20" Foreground="#61D918" Margin="40,0,0,0" />
                </StackPanel>
            </StackPanel>
            <Button x:Name="nextButton" Grid.Column="3" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz2.png" Height="70" />
            </Button>
        </Grid>
    </Window>
    desktopowa/MainWindow.xaml.cs C# zmienione: 12 linii
    using System.IO;
    using System.Windows;
    
    namespace desktopowa;
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Album> albums = new List<Album>();
        private int currentIndex = 0;
    
        public MainWindow()
        {
            InitializeComponent();
            albums = ReadAlbums("Data.txt");
            ShowAlbum();
        }
    
        private void ShowAlbum()
        {
            Album album = albums[currentIndex];
            artistLabel.Content = album.Artist;
            titleLabel.Content = album.Title;
            songsLabel.Content = album.SongsNumber + " utworów";
            yearLabel.Content = album.Year;
            downloadsLabel.Content = album.DownloadNumber;
        }
    
        private List<Album> ReadAlbums(string fileName)
        {
            List<Album> albumList = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albumList.Add(album);
            }
            reader.Close();
            return albumList;
        }
    }
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  15. Krok 15: Przycisk po lewej: poprzedni album

    Kryteria:

    R.3.6 Po wybraniu przycisku po lewej stronie wyświetlane są dane poprzedniego albumu lub po wybraniu przycisku po prawej stronie wyświetlane są dane następnego albumu zgodnie z kolejnością w pliku Dane.txt (w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)

    ok. 2 min
    Polecenie z arkusza

    Działanie aplikacji po kliknięciu przycisku po lewej stronie: Wyświetlane są dane poprzedniego albumu, na przykład, gdy aktualnie wyświetlany jest album siódmy (The Rasmus), zostanie wyświetlony album szósty (Melanie Martinez).

    Kliknięcie zmniejsza indeks o jeden i odświeża widok (R.3.6). Ale przy pierwszym albumie indeks spadłby do -1 - takiego elementu listy nie ma i program zakończyłby się wyjątkiem ArgumentOutOfRangeException. W podglądzie przycisk po lewej na starcie nic nie robi; obsłużymy to w następnym kroku.

    desktopowa/MainWindow.xaml XAML zmienione: 2 linie
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160" />
                <ColumnDefinition Width="240" />
                <ColumnDefinition />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <Button x:Name="previousButton" Width="100" Height="76" VerticalAlignment="Center"
                    Click="PreviousButton_Click">
                <Image Source="obraz3.png" Height="70" />
            </Button>
            <StackPanel Grid.Column="1" Margin="0,20,0,0">
                <Image Source="obraz.png" Width="200" Height="200" />
                <StackPanel Orientation="Horizontal" Margin="0,15,0,0">
                    <Label x:Name="downloadsLabel" FontSize="20" Foreground="#61D918" Width="140" />
                    <Button x:Name="downloadButton" Content="Pobierz" FontSize="20" FontWeight="Bold" Background="#61D918" Width="90" />
                </StackPanel>
            </StackPanel>
            <StackPanel Grid.Column="2" Margin="20,25,0,0">
                <Label x:Name="artistLabel" FontSize="50" Foreground="White" />
                <Label x:Name="titleLabel" FontSize="30" FontStyle="Italic" Foreground="White" />
                <StackPanel Orientation="Horizontal">
                    <Label x:Name="songsLabel" FontSize="20" Foreground="#61D918" />
                    <Label x:Name="yearLabel" FontSize="20" Foreground="#61D918" Margin="40,0,0,0" />
                </StackPanel>
            </StackPanel>
            <Button x:Name="nextButton" Grid.Column="3" Width="100" Height="76" VerticalAlignment="Center">
                <Image Source="obraz2.png" Height="70" />
            </Button>
        </Grid>
    </Window>
    desktopowa/MainWindow.xaml.cs C# zmienione: 6 linii
    using System.IO;
    using System.Windows;
    
    namespace desktopowa;
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Album> albums = new List<Album>();
        private int currentIndex = 0;
    
        public MainWindow()
        {
            InitializeComponent();
            albums = ReadAlbums("Data.txt");
            ShowAlbum();
        }
    
        private void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            currentIndex--;
            ShowAlbum();
        }
    
        private void ShowAlbum()
        {
            Album album = albums[currentIndex];
            artistLabel.Content = album.Artist;
            titleLabel.Content = album.Title;
            songsLabel.Content = album.SongsNumber + " utworów";
            yearLabel.Content = album.Year;
            downloadsLabel.Content = album.DownloadNumber;
        }
    
        private List<Album> ReadAlbums(string fileName)
        {
            List<Album> albumList = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albumList.Add(album);
            }
            reader.Close();
            return albumList;
        }
    }
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  16. Krok 16: Z pierwszego albumu na ostatni

    Kryteria:

    R.3.7 Gdy aktualnie widoczny jest pierwszy album i zostanie wciśnięty przycisk po lewej stronie, zostaje wyświetlony ostatni album lub gdy aktualnie widoczny jest ostatni album i zostanie wciśnięty przycisk po prawej stronie, zostaje wyświetlony pierwszy album (w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)

    ok. 2 min
    Polecenie z arkusza

    Gdy aktualnie wyświetlany jest pierwszy album (Gorillaz), zostanie wyświetlony album ostatni (Faith No More).

    Gdy indeks spadnie poniżej zera, ustawiamy go na ostatni element: albums.Count - 1 - liczba albumów minus jeden, bo indeksy zaczynają się od 0 (R.3.7). Nie wpisujemy 13: po dopisaniu albumów do pliku liczba sama się zmieni. Kliknij w podglądzie strzałkę w lewo na starcie - Faith No More.

    desktopowa/MainWindow.xaml.cs C# zmienione: 4 linie
    using System.IO;
    using System.Windows;
    
    namespace desktopowa;
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Album> albums = new List<Album>();
        private int currentIndex = 0;
    
        public MainWindow()
        {
            InitializeComponent();
            albums = ReadAlbums("Data.txt");
            ShowAlbum();
        }
    
        private void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            currentIndex--;
            if (currentIndex < 0)
            {
                currentIndex = albums.Count - 1;
            }
            ShowAlbum();
        }
    
        private void ShowAlbum()
        {
            Album album = albums[currentIndex];
            artistLabel.Content = album.Artist;
            titleLabel.Content = album.Title;
            songsLabel.Content = album.SongsNumber + " utworów";
            yearLabel.Content = album.Year;
            downloadsLabel.Content = album.DownloadNumber;
        }
    
        private List<Album> ReadAlbums(string fileName)
        {
            List<Album> albumList = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albumList.Add(album);
            }
            reader.Close();
            return albumList;
        }
    }
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  17. Krok 17: Przycisk po prawej: następny album, z ostatniego na pierwszy

    Kryteria: ,

    R.3.6 Po wybraniu przycisku po lewej stronie wyświetlane są dane poprzedniego albumu lub po wybraniu przycisku po prawej stronie wyświetlane są dane następnego albumu zgodnie z kolejnością w pliku Dane.txt (w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)

    R.3.7 Gdy aktualnie widoczny jest pierwszy album i zostanie wciśnięty przycisk po lewej stronie, zostaje wyświetlony ostatni album lub gdy aktualnie widoczny jest ostatni album i zostanie wciśnięty przycisk po prawej stronie, zostaje wyświetlony pierwszy album (w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)

    ok. 2 min
    Polecenie z arkusza

    Działanie aplikacji po kliknięciu przycisku po prawej stronie: Wyświetlane są dane następnego albumu, na przykład, gdy aktualnie wyświetlany jest pierwszy album, zostanie wyświetlony drugi album, patrz obraz 3. Gdy aktualnie wyświetlany jest ostatni album, to zostanie wyświetlony pierwszy album.

    Lustrzane odbicie poprzedniego przycisku: indeks rośnie o jeden, a gdy wyjdzie poza listę (>= albums.Count), wraca na 0 - pierwszy album (R.3.6, R.3.7). Kliknij strzałkę w prawo - My Chemical Romance (obraz 3).

    desktopowa/MainWindow.xaml XAML zmienione: 2 linie
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160" />
                <ColumnDefinition Width="240" />
                <ColumnDefinition />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <Button x:Name="previousButton" Width="100" Height="76" VerticalAlignment="Center"
                    Click="PreviousButton_Click">
                <Image Source="obraz3.png" Height="70" />
            </Button>
            <StackPanel Grid.Column="1" Margin="0,20,0,0">
                <Image Source="obraz.png" Width="200" Height="200" />
                <StackPanel Orientation="Horizontal" Margin="0,15,0,0">
                    <Label x:Name="downloadsLabel" FontSize="20" Foreground="#61D918" Width="140" />
                    <Button x:Name="downloadButton" Content="Pobierz" FontSize="20" FontWeight="Bold" Background="#61D918" Width="90" />
                </StackPanel>
            </StackPanel>
            <StackPanel Grid.Column="2" Margin="20,25,0,0">
                <Label x:Name="artistLabel" FontSize="50" Foreground="White" />
                <Label x:Name="titleLabel" FontSize="30" FontStyle="Italic" Foreground="White" />
                <StackPanel Orientation="Horizontal">
                    <Label x:Name="songsLabel" FontSize="20" Foreground="#61D918" />
                    <Label x:Name="yearLabel" FontSize="20" Foreground="#61D918" Margin="40,0,0,0" />
                </StackPanel>
            </StackPanel>
            <Button x:Name="nextButton" Grid.Column="3" Width="100" Height="76" VerticalAlignment="Center"
                    Click="NextButton_Click">
                <Image Source="obraz2.png" Height="70" />
            </Button>
        </Grid>
    </Window>
    desktopowa/MainWindow.xaml.cs C# zmienione: 10 linii
    using System.IO;
    using System.Windows;
    
    namespace desktopowa;
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Album> albums = new List<Album>();
        private int currentIndex = 0;
    
        public MainWindow()
        {
            InitializeComponent();
            albums = ReadAlbums("Data.txt");
            ShowAlbum();
        }
    
        private void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            currentIndex--;
            if (currentIndex < 0)
            {
                currentIndex = albums.Count - 1;
            }
            ShowAlbum();
        }
    
        private void NextButton_Click(object sender, RoutedEventArgs e)
        {
            currentIndex++;
            if (currentIndex >= albums.Count)
            {
                currentIndex = 0;
            }
            ShowAlbum();
        }
    
        private void ShowAlbum()
        {
            Album album = albums[currentIndex];
            artistLabel.Content = album.Artist;
            titleLabel.Content = album.Title;
            songsLabel.Content = album.SongsNumber + " utworów";
            yearLabel.Content = album.Year;
            downloadsLabel.Content = album.DownloadNumber;
        }
    
        private List<Album> ReadAlbums(string fileName)
        {
            List<Album> albumList = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albumList.Add(album);
            }
            reader.Close();
            return albumList;
        }
    }
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  18. Krok 18: Pobierz: liczba pobrań większa o jeden i zapamiętana

    Kryteria:

    R.3.8 Wciśnięcie przycisku Pobierz powoduje inkrementację liczby pobrań co jest widoczne w oknie aplikacji. Wykonać test: przejść do kolejnego albumu i wrócić - liczba powinna dalej być zwiększona o jeden (w uruchomionej aplikacji lub na zrzucie i obowiązkowo w kodzie)

    ok. 2 min
    Polecenie z arkusza

    Działanie aplikacji po kliknięciu przycisku Pobierz: Zostaje zwiększona o jeden liczba pobrań dla danego albumu. Efekt powinien być widoczny w oknie aplikacji oraz zapamiętany w trakcie jej działania (nie musi być trwale zapisywany do pliku Dane.txt).

    Zwiększamy pole w obiekcie albumu na liście (albums[currentIndex].DownloadNumber++), a nie samą etykietę - dlatego wartość zostaje zapamiętana: po przejściu do innego albumu i powrocie ShowAlbum znowu przepisze z listy już zwiększoną liczbę (R.3.8). Sprawdź w podglądzie: „Pobierz”, strzałka w prawo, strzałka w lewo - 11000103.

    Typowe błędy

    Zwiększenie samej etykiety (downloadsLabel.Content) nie zmienia danych albumu - po przewinięciu wraca stara liczba.

    desktopowa/MainWindow.xaml XAML zmienione: 2 linie
    <Window x:Class="desktopowa.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:desktopowa"
            mc:Ignorable="d"
            Title="MojeDźwięki, Wykonał: Bartosz Bryniarski" Height="340" Width="1200"
            Background="#2E8B57">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160" />
                <ColumnDefinition Width="240" />
                <ColumnDefinition />
                <ColumnDefinition Width="160" />
            </Grid.ColumnDefinitions>
            <Button x:Name="previousButton" Width="100" Height="76" VerticalAlignment="Center"
                    Click="PreviousButton_Click">
                <Image Source="obraz3.png" Height="70" />
            </Button>
            <StackPanel Grid.Column="1" Margin="0,20,0,0">
                <Image Source="obraz.png" Width="200" Height="200" />
                <StackPanel Orientation="Horizontal" Margin="0,15,0,0">
                    <Label x:Name="downloadsLabel" FontSize="20" Foreground="#61D918" Width="140" />
                    <Button x:Name="downloadButton" Content="Pobierz" FontSize="20" FontWeight="Bold" Background="#61D918" Width="90"
                            Click="DownloadButton_Click" />
                </StackPanel>
            </StackPanel>
            <StackPanel Grid.Column="2" Margin="20,25,0,0">
                <Label x:Name="artistLabel" FontSize="50" Foreground="White" />
                <Label x:Name="titleLabel" FontSize="30" FontStyle="Italic" Foreground="White" />
                <StackPanel Orientation="Horizontal">
                    <Label x:Name="songsLabel" FontSize="20" Foreground="#61D918" />
                    <Label x:Name="yearLabel" FontSize="20" Foreground="#61D918" Margin="40,0,0,0" />
                </StackPanel>
            </StackPanel>
            <Button x:Name="nextButton" Grid.Column="3" Width="100" Height="76" VerticalAlignment="Center"
                    Click="NextButton_Click">
                <Image Source="obraz2.png" Height="70" />
            </Button>
        </Grid>
    </Window>
    desktopowa/MainWindow.xaml.cs C# zmienione: 6 linii
    using System.IO;
    using System.Windows;
    
    namespace desktopowa;
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Album> albums = new List<Album>();
        private int currentIndex = 0;
    
        public MainWindow()
        {
            InitializeComponent();
            albums = ReadAlbums("Data.txt");
            ShowAlbum();
        }
    
        private void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            currentIndex--;
            if (currentIndex < 0)
            {
                currentIndex = albums.Count - 1;
            }
            ShowAlbum();
        }
    
        private void NextButton_Click(object sender, RoutedEventArgs e)
        {
            currentIndex++;
            if (currentIndex >= albums.Count)
            {
                currentIndex = 0;
            }
            ShowAlbum();
        }
    
        private void DownloadButton_Click(object sender, RoutedEventArgs e)
        {
            albums[currentIndex].DownloadNumber++;
            ShowAlbum();
        }
    
        private void ShowAlbum()
        {
            Album album = albums[currentIndex];
            artistLabel.Content = album.Artist;
            titleLabel.Content = album.Title;
            songsLabel.Content = album.SongsNumber + " utworów";
            yearLabel.Content = album.Year;
            downloadsLabel.Content = album.DownloadNumber;
        }
    
        private List<Album> ReadAlbums(string fileName)
        {
            List<Album> albumList = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albumList.Add(album);
            }
            reader.Close();
            return albumList;
        }
    }
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  19. Krok 19: Folder desktopowa: archiwum, źródła i plik wykonywalny

    ok. 2 min
    Polecenie z arkusza

    Kod aplikacji przygotuj do nagrania na płytę. W folderze desktopowa powinno znaleźć się archiwum całego projektu o nazwie desktopowa.zip, skopiowane z projektu pliki źródłowe, które były modyfikowane w czasie egzaminu (interfejs użytkownika i logika aplikacji) oraz plik wykonywalny, jeżeli istnieje.

    Pakujemy folder projektu do desktopowa.zip, obok kopiujemy MainWindow.xaml, MainWindow.xaml.cs, Album.cs i desktopowa.exe (z Data.txt obok - program czyta go z własnego folderu).

    Okno aplikacji bez zmian - taki jak po kroku 18.

  20. Etap 4: Dokumentacja aplikacji

    Kroki 20-23 · po tym etapie masz 31 z 31 kryteriów (pkt)

    Krok 20: Nagłówek metody ReadAlbums według listingu 1

    Kryteria: , , , ,

    R.4.1 Dla dowolnej funkcji lub metody z aplikacji konsolowej zapisano nagłówek w postaci komentarza zgodnego z Listingiem 1 z arkusza egzaminacyjnego (nie należy brać pod uwagę liczby gwiazdek), komentarz może być wieloliniowy lub kilka jednoliniowych, lub Docstrings (potrójny cudzysłów) - w tym przypadku opis znajduje się pod nazwą funkcji

    R.4.2 W komentarzu ujęto nazwę funkcji / metody oraz opisano jej działanie

    R.4.3 W komentarzu ujęto wszystkie argumenty funkcji / metody: nazwy i krótki opis lub "brak", gdy nie ma argumentów

    R.4.4 W komentarzu ujęto nazwę typu zwracanego i krótki opis co jest zwracane lub "brak" gdy nic nie zwraca

    R.4.5 W komentarzu ujęto numer zdającego

    ok. 4 min
    Polecenie z arkusza

    W kodzie źródłowym aplikacji konsolowej za pomocą komentarza utwórz nagłówek dowolnej funkcji / metody, według wzoru z listingu 1. W przypadku podejścia obiektowego zamiast słowa „funkcji” można napisać „metody”. Komentarz powinien znaleźć się nad lub pod nazwą funkcji. W miejscu nawiasów <> należy podać odpowiednie opisy.

    Komentarz wieloliniowy nad metodą, z polami listingu 1 (R.4.1): nazwa i opis działania (R.4.2), parametr fileName z opisem (R.4.3), zwracany typ List<Album> z opisem (R.4.4) i autor (R.4.5). Podejście jest obiektowe, więc piszemy „metody”. Na egzaminie w polu autor wpisujemy numer PESEL - tu stoi Bartosz Bryniarski.

    konsola/Program.cs C# zmienione: 10 linii
    class Album
    {
        public string Artist;
        public string Title;
        public int SongsNumber;
        public int Year;
        public long DownloadNumber;
    }
    
    class Program
    {
        /*
        **********************************************
        nazwa metody:        ReadAlbums
        opis metody:         wczytuje z pliku tekstowego wszystkie albumy (po pięć wierszy na album,
                             albumy oddzielone pustym wierszem) i zapisuje je w liście obiektów Album
        parametry:           fileName - nazwa lub ścieżka pliku z danymi albumów
        zwracany typ i opis: List<Album> - lista wczytanych albumów w kolejności z pliku
        autor:               Bartosz Bryniarski
        **********************************************
        */
        static List<Album> ReadAlbums(string fileName)
        {
            List<Album> albums = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albums.Add(album);
            }
            reader.Close();
            return albums;
        }
    
        static void ShowAlbums(List<Album> albums)
        {
            foreach (Album album in albums)
            {
                Console.WriteLine(album.Artist);
                Console.WriteLine(album.Title);
                Console.WriteLine(album.SongsNumber);
                Console.WriteLine(album.Year);
                Console.WriteLine(album.DownloadNumber);
                Console.WriteLine();
            }
        }
    
        static void Main()
        {
            List<Album> albums = ReadAlbums("Data.txt");
            ShowAlbums(albums);
        }
    }
    Wynik programu po tym kroku
    > konsola.exe
    Gorillaz
    "The Now Now"
    11
    2018
    11000102
    
    My Chemical Romance
    "The Black Parade"
    14
    2006
    304666444
    
    Wilki
    "wilki"
    16
    1992
    4000230
    
    30 Seconds To Mars
    "A Beautiful Lie"
    13
    2009
    300120222
    
    30 Seconds To Mars
    "This Is War"
    15
    2009
    22000000
    
    Melanie Martinez
    "Cry Baby"
    16
    2015
    400345042
    
    The Rasmus
    "Dead Letters"
    10
    2003
    253453
    
    Metallica
    "Metallica"
    12
    1991
    1506404300
    
    Meskie Granie Orkiestra 2022
    "Meskie Granie 2022"
    30
    2022
    243085
    
    Krzysztof Zalewski
    "Zloto"
    11
    2016
    4586200
    
    The Cure
    "Disintegration"
    11
    1989
    130000560
    
    Pink Floyd
    "The Division Bell"
    11
    1994
    24332190
    
    Depeche Mode
    "Spirit"
    17
    2017
    24300453
    
    Faith No More
    "Angel Dust"
    14
    1992
    55384200
  21. Krok 21: Zrzut konsola1

    Kryteria: , ,

    R.1.6 Podjęto próbę skompilowania kodu, co udokumentowano zrzutem przedstawiającym uruchomiony program lub jego kompilację

    R.2.7 Program kompiluje się i uruchamia 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. 2 min
    Polecenie z arkusza

    Wykonaj zrzuty ekranu dokumentujące uruchomienie aplikacji utworzonych podczas egzaminu. Zrzuty powinny obejmować cały obszar ekranu monitora z widocznym paskiem zadań. Aplikacja konsolowa – dowolna liczba zrzutów nazwanych konsola1, konsola2, ...

    Program nie pyta o dane, więc wystarczy jeden zrzut: okno konsoli z wypisanymi albumami i środowisko w tle - konsola1.png w folderze dokumentacja (R.1.6, R.2.7, R.4.6). Jeśli wszystkie albumy nie mieszczą się w oknie, drugi zrzut po przewinięciu - konsola2.png.

    Wynik programu bez zmian - taki jak po kroku 20.

  22. Krok 22: Zrzuty desktop1 - desktop5

    Kryteria:

    R.4.7 Zapisano przynajmniej jeden zrzut ekranu z uruchomienia lub kompilacji aplikacji desktopowej, na zrzucie widoczne jest środowisko, w którym powstała aplikacja

    ok. 4 min
    Polecenie z arkusza

    Wykonać należy tyle zrzutów, ile interakcji podejmuje aplikacja (np. stan początkowy, po wybraniu przycisków itd.). Aplikacja desktopowa – dowolna liczba zrzutów nazwanych desktop1, desktop2, ...

    Zrzuty całego ekranu ze środowiskiem: desktop1 - stan początkowy (obraz 2), desktop2 - po strzałce w prawo (obraz 3), desktop3 - ostatni album po strzałce w lewo z pierwszego, desktop4 - po „Pobierz”, desktop5 - ten sam album po przewinięciu tam i z powrotem, z zapamiętaną liczbą pobrań (R.4.7).

    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  23. Krok 23: Dokument egzamin

    Kryteria:

    R.4.8 Dokumentacja zawiera nazwy: systemu operacyjnego, środowisk programistycznych, języków programowania

    ok. 2 min
    Polecenie z arkusza

    W edytorze tekstu pakietu biurowego utwórz plik z dokumentacją i nazwij go egzamin. Dokument powinien zawierać informacje: nazwę systemu operacyjnego, na którym pracował zdający, nazwy środowisk programistycznych, z których zdający korzystał na egzaminie, nazwy języków programowania. Zrzuty ekranu i dokument umieść w podfolderze dokumentacja.

    W Wordzie albo Writerze dokument egzamin w folderze dokumentacja z trzema informacjami o narzędziach (R.4.8).

    egzamin.txt Tekst nowy plik
    System operacyjny: Windows 11
    Środowisko programistyczne: Visual Studio 2022 (aplikacja konsolowa i desktopowa)
    Języki programowania: C# (aplikacja konsolowa), C# i XAML - WPF (aplikacja desktopowa)

    Okno aplikacji bez zmian - taki jak po kroku 22.

  24. Etap 5: Dobre praktyki (poza kluczem)

    Kroki 24-25 · po tym etapie masz 31 z 31 kryteriów (pkt)

    Krok 24: Konsola: using i komunikat zamiast awarii przy braku pliku

    ok. 3 min
    Polecenie z arkusza

    Dane są wczytane z pliku Data.txt (muszą zostać wczytane wszystkie dane zawarte w pliku).

    Dwie poprawki odczytu:

    • using StreamReader reader = ... - plik zamyka się sam na końcu metody, także wtedy, gdy w środku poleci wyjątek (np. int.Parse na zepsutym wierszu). Ręczne Close() w takiej sytuacji nigdy się nie wykona i plik zostaje otwarty,
    • try / catch (FileNotFoundException) w Main - gdy Data.txt nie leży obok programu, zamiast czerwonego śladu stosu użytkownik dostaje zrozumiały komunikat.

    Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    konsola/Program.cs C# zmienione: 11 linii
    class Album
    {
        public string Artist;
        public string Title;
        public int SongsNumber;
        public int Year;
        public long DownloadNumber;
    }
    
    class Program
    {
        /*
        **********************************************
        nazwa metody:        ReadAlbums
        opis metody:         wczytuje z pliku tekstowego wszystkie albumy (po pięć wierszy na album,
                             albumy oddzielone pustym wierszem) i zapisuje je w liście obiektów Album
        parametry:           fileName - nazwa lub ścieżka pliku z danymi albumów
        zwracany typ i opis: List<Album> - lista wczytanych albumów w kolejności z pliku
        autor:               Bartosz Bryniarski
        **********************************************
        */
        static List<Album> ReadAlbums(string fileName)
        {
            List<Album> albums = new List<Album>();
            using StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albums.Add(album);
            }
            // reader.Close(); - zamknie go using
            return albums;
        }
    
        static void ShowAlbums(List<Album> albums)
        {
            foreach (Album album in albums)
            {
                Console.WriteLine(album.Artist);
                Console.WriteLine(album.Title);
                Console.WriteLine(album.SongsNumber);
                Console.WriteLine(album.Year);
                Console.WriteLine(album.DownloadNumber);
                Console.WriteLine();
            }
        }
    
        static void Main()
        {
            try
            {
                List<Album> albums = ReadAlbums("Data.txt");
                ShowAlbums(albums);
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine("Nie znaleziono pliku Data.txt obok programu.");
            }
        }
    }
    Wynik programu po tym kroku
    > konsola.exe
    Gorillaz
    "The Now Now"
    11
    2018
    11000102
    
    My Chemical Romance
    "The Black Parade"
    14
    2006
    304666444
    
    Wilki
    "wilki"
    16
    1992
    4000230
    
    30 Seconds To Mars
    "A Beautiful Lie"
    13
    2009
    300120222
    
    30 Seconds To Mars
    "This Is War"
    15
    2009
    22000000
    
    Melanie Martinez
    "Cry Baby"
    16
    2015
    400345042
    
    The Rasmus
    "Dead Letters"
    10
    2003
    253453
    
    Metallica
    "Metallica"
    12
    1991
    1506404300
    
    Meskie Granie Orkiestra 2022
    "Meskie Granie 2022"
    30
    2022
    243085
    
    Krzysztof Zalewski
    "Zloto"
    11
    2016
    4586200
    
    The Cure
    "Disintegration"
    11
    1989
    130000560
    
    Pink Floyd
    "The Division Bell"
    11
    1994
    24332190
    
    Depeche Mode
    "Spirit"
    17
    2017
    24300453
    
    Faith No More
    "Angel Dust"
    14
    1992
    55384200
  25. Krok 25: Okno: zawijanie resztą z dzielenia, pusty plik, czytelna liczba pobrań

    ok. 4 min
    Polecenie z arkusza

    Aplikacja powinna być zapisana czytelnie, z zachowaniem zasad czystego formatowania kodu, należy stosować znaczące nazwy zmiennych i funkcji.

    Trzy poprawki:

    • przejście „w kółko” jednym wyrażeniem z resztą z dzielenia: (currentIndex + 1) % albums.Count po ostatnim daje 0, a (currentIndex - 1 + albums.Count) % albums.Count przed pierwszym daje ostatni - bez dwóch if,
    • pusty plik nie wywraca okna: ShowAlbum sprawdza, czy lista ma jakiekolwiek albumy,
    • liczba pobrań z separatorem tysięcy - ToString("N0") zamienia 1506404300 na „1 506 404 300”, czytelniej dla użytkownika.

    Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza (a format z odstępami różni się od obrazu 2).

    desktopowa/MainWindow.xaml.cs C# zmienione: 9 linii
    using System.IO;
    using System.Windows;
    
    namespace desktopowa;
    
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private List<Album> albums = new List<Album>();
        private int currentIndex = 0;
    
        public MainWindow()
        {
            InitializeComponent();
            albums = ReadAlbums("Data.txt");
            ShowAlbum();
        }
    
        private void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            currentIndex = (currentIndex - 1 + albums.Count) % albums.Count;
            ShowAlbum();
        }
    
        private void NextButton_Click(object sender, RoutedEventArgs e)
        {
            currentIndex = (currentIndex + 1) % albums.Count;
            ShowAlbum();
        }
    
        private void DownloadButton_Click(object sender, RoutedEventArgs e)
        {
            albums[currentIndex].DownloadNumber++;
            ShowAlbum();
        }
    
        private void ShowAlbum()
        {
            if (albums.Count == 0)
            {
                artistLabel.Content = "Brak albumów";
                return;
            }
            Album album = albums[currentIndex];
            artistLabel.Content = album.Artist;
            titleLabel.Content = album.Title;
            songsLabel.Content = $"{album.SongsNumber} utworów";
            yearLabel.Content = album.Year;
            downloadsLabel.Content = album.DownloadNumber.ToString("N0");
        }
    
        private List<Album> ReadAlbums(string fileName)
        {
            List<Album> albumList = new List<Album>();
            StreamReader reader = new StreamReader(fileName);
            while (!reader.EndOfStream)
            {
                Album album = new Album();
                album.Artist = reader.ReadLine();
                album.Title = reader.ReadLine();
                album.SongsNumber = int.Parse(reader.ReadLine());
                album.Year = int.Parse(reader.ReadLine());
                album.DownloadNumber = long.Parse(reader.ReadLine());
                reader.ReadLine();
                albumList.Add(album);
            }
            reader.Close();
            return albumList;
        }
    }
    Okno aplikacji po tym kroku

    Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.

  26. Etap 6: Oddanie pracy

    Krok 26 · po tym etapie masz 31 z 31 kryteriów (pkt)

    Krok 26: Nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    Nagraj płytę z rezultatami pracy. W folderze z numerem zdającego powinny się znajdować podfoldery desktopowa, dokumentacja, konsolowa.

    Sprawdzamy zawartość przed nagraniem:

    • dokumentacja: konsola1.png, desktop1.png - desktop5.png, egzamin,
    • konsolowa: konsola.zip (spakowany po dopisaniu komentarza), Program.cs, konsola.exe,
    • desktopowa: desktopowa.zip, MainWindow.xaml, MainWindow.xaml.cs, Album.cs, desktopowa.exe.

    Nagrywamy, sprawdzamy odczyt płyty, opisujemy ją numerem zdającego.

    Okno aplikacji bez zmian - taki jak po kroku 25.

Podgląd

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