{"id":26954876,"url":"https://github.com/kamilgie/asrt-wdi","last_synced_at":"2025-04-03T02:19:50.681Z","repository":{"id":257994350,"uuid":"872471925","full_name":"kamilGie/ASRT-WDI","owner":"kamilGie","description":"Automatycznie Szablony, Rozwiązania i Testy do WDI na AGH","archived":false,"fork":false,"pushed_at":"2025-03-10T13:11:28.000Z","size":80959,"stargazers_count":10,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-10T14:24:44.498Z","etag":null,"topics":["algorithms","python","unittesting"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kamilGie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-14T13:49:39.000Z","updated_at":"2025-03-10T13:11:32.000Z","dependencies_parsed_at":"2024-10-26T01:09:30.035Z","dependency_job_id":"04621ae8-1fb8-4bff-bc82-59e717aa8c1d","html_url":"https://github.com/kamilGie/ASRT-WDI","commit_stats":null,"previous_names":["kamilgie/wdi","kamilgie/asrt-wdi"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamilGie%2FASRT-WDI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamilGie%2FASRT-WDI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamilGie%2FASRT-WDI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kamilGie%2FASRT-WDI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kamilGie","download_url":"https://codeload.github.com/kamilGie/ASRT-WDI/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246922465,"owners_count":20855402,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","python","unittesting"],"created_at":"2025-04-03T02:19:50.213Z","updated_at":"2025-04-03T02:19:50.669Z","avatar_url":"https://github.com/kamilGie.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.youtube.com/watch?v=4hlLoHqgpVk\" target=\"_blank\"\u003e\n    \u003cpicture\u003e\n      \u003csource srcset=\"https://github.com/user-attachments/assets/15f76714-f182-45d6-bac1-1cf63a849a91\" media=\"(prefers-color-scheme: light)\"\u003e\n      \u003csource srcset=\"https://github.com/user-attachments/assets/c4ded4e3-5b98-4d88-a092-f375211f5fc9\" media=\"(prefers-color-scheme: dark)\"\u003e\n      \u003cimg src=\"https://github.com/user-attachments/assets/15f76714-f182-45d6-bac1-1cf63a849a91\" alt=\"Task solution\" width=\"800\"\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\n\n### 🔧 Używanie Projektu\n\nKażdy folder z zadaniem składa się z czterech składników:\n\n1. **`README.md`** – Zawiera treść zadania, **główne rozwiązanie**. Okazjonalnie, opis rozwiązania.\n2. **`Rozwiązania`** – folder z  gotowymi rozwiązaniami zadania.\n3. **`szablon.py`** – Zawiera szablon do wypełnienia rozwiązaniem.\n4. **`testy.py`** – plik z testami jednostkowymi.\n\n\n### 🧪 Jak testować swoje rozwiązania?\n\nWypełnij plik `szablon.py` i uruchom go, odkomentowując funkcję `odpal_testy()`\n\nhttps://github.com/user-attachments/assets/ad6d166e-bda7-4eca-a8cc-86d984913e0f\n\n### 🌐 Wizualizacje Rozwiązań\nNiektóre zadania zawierają wizualne wyjaśnienia algorytmów, które są hostowane w chmurze na stronie internetowej lub zrealizowane w Pygame, na przykład [Kolokwium 2022 A3](https://github.com/kamilGie/ASRT-WDI/tree/main/Kolokwia/Kolokwium_2/2022_A3), [160](https://github.com/kamilGie/ASRT-WDI/tree/main/Zestaw_5%3A_Rekurencja/160) lub [112](https://github.com/kamilGie/ASRT-WDI/tree/main/Zestaw_3%3A_Tablice_o_większej_liczbie_wymiarów/112) \n\n### 💡 Podpowiedzi\n\nNiektóre zadania mają w `szablon.py` trzy ***podpowiedzi***: 1 Lekko nakieruje, 2 Wyjaśni, 3 Poprowadzi przez zadanie, na przykład [Kolokwium 2021 6](https://github.com/kamilGie/ASRT-WDI/blob/main/Kolokwia/Kolokwium_3/2021_6/szablon2021_6.py), [226](https://github.com/kamilGie/ASRT-WDI/blob/main/Zestaw_8%3A_Wyszukiwanie_i_sortowanie/226/szablon226.py) lub [56](https://github.com/kamilGie/ASRT-WDI/blob/main/Zestaw_1%3A_Proste_programy_z_p%C4%99tlami/56/szablon56.py)\n\n### 🌑 Czarny Motyw Zestawu\nKażdy zestaw oraz każde zadanie zawiera plik `README` z opisem zadań. Jeśli masz ustawiony czarny motyw na GitHubie, zestaw ten będzie wyświetlany w ciemnej wersji.\n\n\n### 🧱 Prototypy\nNierozwiązane zadania znajdują się w plikach `prototyp.py` i czekają na rozwiązanie. Po rozwiązaniu zadania można stworzyć pełne zadanie, automatycznie generując wszystkie pliki.\n\n### 🐛 Zgłaszanie Błędów\nBłędy w rozwiązaniach, testach lub treściach zgłaszaj na \u003ca href=\"https://github.com/kamilgie/ASRT-WDI/issues/new?labels=bug\"\u003e****Issues****\u003c/a\u003e lub \u003ca href=\"https://gieras.pl/\"\u003e****prywatnie****\u003c/a\u003e.\n\n \n---\n\n## Źródła rozwiązań 📚\n\nCzęść rozwiązań została zaczerpnięta (*bezczelnie podkradziona*) z poniższych repozytoriów.  \nJestem ogromnie wdzięczny ich autorom za świetne prace, które bardzo pomogły! \n\n- 🌟 [WDI-2023](https://github.com/pawlowiczf/WDI-2023) - [Filip Pawłowicz](https://github.com/pawlowiczf)\n- 🌟 [WDI2020](https://github.com/Wisien999/WDI2020) - [Wisien999](https://github.com/Wisien999)  \n\n\n\n\n### 🗿 Najwięksi współtwórcy:\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u003ca href=\"https://github.com/kamilGie/ASRT-WDI/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=kamilGie/ASRT-WDI\" alt=\"Najwięksi współtwórcy\" /\u003e\n\u003c/a\u003e\n\n\n\n\n# Szczegóły Projektu\n\n\u003cdetails\u003e\n  \u003csummary\u003e 🤝 Jak pomóc i zostać współtwórcą? \u003c/summary\u003e\n\n## 🤝 Jak pomóc i zostać współtwórcą?\n\n\n- Zalecam [***utworzenie forka***](https://github.com/kamilGie/WDI/fork) i zgłaszanie swoich zmian za pomocą pull requestów.\n\n### 💡 Możliwe Ulepszenia\n- ✏️ Stworzenie Zadania\n- 🛠️ Poprawienie treści zadania, jeśli jest niejasna lub brakuje np. znaków potęgowania.\n- 🔧 Ulepszanie testow poprzez komendy lub stworzeniej własnej [Szczegóły](#komendy)\n- 🧠 Tworzenie Strategi Tworzenia Zadań [Szczegóły](#strategie)\n  \nASRT opiera się na **rozszerzaniu funkcjonalności**. Dzięki temu możesz dodawać nowe funkcje i strategie bez modyfikacji istniejącego kodu, co ułatwia wdrożenie bez potrzeby wiedzy o całym systemie i unika konfliktów.\n### 🐛 Zgłaszanie błędów\n\n- Błędy w rozwiązaniach, testach lub treściach można zgłaszać \u003ca href=\"https://github.com/kamilgie/ASRT-WDI/issues/new?labels=bug\"\u003e ****tutaj**** \u003c/a\u003e\n\n### 💬 Feedback\n\n- Sam feedback na temat tego, jak się pracuje, w jakim kierunku można pójść oraz czego brakuje, również będzie mile widziany. [kontakt](http://www.gieras.pl).\n\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e 🧪 Testowanie Zadania \u003c/summary\u003e\n\n## Testowanie Zadania\nPrzykładowy `szablon.py` wygląda tak: \n```python\n# ====================================================================================================\u003e\n# Zadanie 1\n# Proszę napisać program poszukujący trójkątów Pitagorejskich w których długość przekątnej\n# jest mniejsza od liczby N wprowadzonej z klawiatury.\n# ====================================================================================================\u003e\n# print(a,b,c)\n\ndef Zadanie_1(n): ...\n\n\nif __name__ == \"__main__\":\n    from testy01 import odpal_testy\n\n    Zadanie_1(input('Podaj n: '))\n\n    # odpal_testy()\n```\n### Na górze znajduje się opis zadania, funkcja do wypełnienia i przygotowany main.\nWypełniasz funkcję kodem, o który prosi opis zadania. Wyniki można zwracać lub wypisywać. Jeśli to nie będzie oczywiste, pod opisem zadania powinna być wskazówka od autora testów, jakiego sposobu zwracania wyników oczekuje. W tym przypadku widać, że boki trójkąta powinny być wypisywane kolejno, bez żadnych dodatkowych napisów.\n\nPo tym, jak zrobisz zadanie i będziesz pewny jego poprawności, możesz odkomentować funkcję `odpal_testy()` i uruchomić program normalnie:\n```python\n# ====================================================================================================\u003e\n# Zadanie 1\n# Proszę napisać program poszukujący trójkątów Pitagorejskich w których długość przekątnej\n# jest mniejsza od liczby N wprowadzonej z klawiatury.\n# ====================================================================================================\u003e\n# print(a,b,c)\n\ndef Zadanie_1(n):\n    for a in range(1, n):\n        for b in range(a, n):\n            c = (a * a + b * b) ** 0.5\n            if c.is_integer() and c \u003c= n:\n                print(a, b, c)\n\nif __name__ == \"__main__\":\n     from testy01 import odpal_testy\n\n     odpal_testy()\n```\n### wynik takiego programu dalby taki wynik\n\u003cimg width=\"1504\" alt=\"Zrzut ekranu 2024-10-24 o 22 26 09\" src=\"https://github.com/user-attachments/assets/666313c3-15ec-4697-955c-1e5de81e23d7\"\u003e\n  \nWynik testu wskazuje na błąd: widzimy komunikat `AssertionError: '3 4 5' not found in [''].` Oznacza to, że test oczekiwał pustego stringa `''`, a otrzymał `'3 4 5'`, co sugeruje, że wynik dla c = 5 został niepotrzebnie wypisany.\n\nPo chwili namysłu i ponownym przeczytaniu treści zadania, można zauważyć, że warunek mówi o długości przekątnej mniejszej, niż liczba **N**. Kod należy poprawić i ponownie uruchomić testy z nową nadzieją.\n\n### Czasami można spotkać się z takim przypadkiem:\n \u003cimg width=\"1165\" alt=\"Zrzut ekranu 2024-10-24 o 22 57 49\" src=\"https://github.com/user-attachments/assets/4fe66d52-766c-417a-87ab-738a38271137\"\u003e\nWidzimy, że mimo poprawnego wyniku mamy błędny test, ponieważ wypisujemy wynik w innym typie lub kolejności. W takim przypadku możemy:\n\n- Cieszyć się poprawnym rozwiązaniem i pójść dalej.\n- Zmienić typ lub format wyjścia na taki, jaki jest oczekiwany w teście.\n- Zainteresować się pomocą w rozwijaniu projektu i za pomocą komendy dodać swoją funkcję wraz z jej rozwiązaniem do listy poprawnych odpowiedzi, aby inni użytkownicy mieli dobre testy dla takich samych wyników jak twój.\n\nCzęsto też zadania mają kilka poprawnych odpowiedzi, więc na każdy test trzeba być czujnym i analizować jego poprawność. W takich przypadkach również nalegam, by zgłaszać mi takie zadania, ponieważ będą dodawane inne warianty poprawnej odpowiedzi.\n\nWięcej o tym, jak działa cały projekt w \n\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e ✏️  Tworzenie Zadania z prototypu  \u003c/summary\u003e\n\n\n  \n   \n## Tworzenie Zadań na prototypie\n\n1. Po rozwiązaniu zadania na `prototyp.py` można stworzyć pełne zadanie, odkomentowując funkcję `stworz_zadanie` i przekazując w tablicy funkcje, które mają być objęte testami.\n2. Funkcja `stworz_zadanie` automatycznie przygotuje testy na podstawie przekazanych funkcji. Poprosi również o podanie argumentów testowych, które Twoim zdaniem mogą być interesujące lub problematyczne.\n3. Następnie utworzy folder zadania zawierający pliki: `rozwiazanie.py` oraz `szablon.py` na podstawie `prototyp.py`, a także `testy.py` na podstawie wcześniej wygenerowanych testów.\n\nhttps://github.com/user-attachments/assets/f3316918-a5e9-457f-8c2e-b4a5e5f0f27c\n\n\n## Tworzenie Zadania\n### `stworz_zadanie()` \nKażdy prototyp zawiera funkcję `stworz_zadanie`, importowaną z pliku `Develop`. Funkcja `stworz_zadanie` przesyła funkcje, które chcemy by obejmowały testy oraz wchodziły w skład szablonu do wypelnienia. Wiec przykładowo wypełniony `prototyp` powinnien wygladać tak:\n```python\n# ====================================================================================================\u003e\n# Zadanie 0\n# Stworz 2 funkcje jedna dodaje 2 liczby druga mnoży 2 liczby\n# ====================================================================================================\u003e\n\ndef dodaj(a, b):\n    return a + b\n\ndef mnoż(a, b):\n    return a * b\n\nif __name__ == \"__main__\":\n    from Develop import stworz_zadanie\n\n    # stworz_zadanie([dodaj, mnoż])\n```\n\nFunkcja `stworz_zadanie` działa podobnie jak funkcja `print`. Można ją uruchomić bez dodatkowych parametrów, aby wygenerować domyślną strukturę plików: `README.md`, `testy.py`  `szablon.py` oraz folder `Rozwiązania`. \n\n### Modyfikacje \n\nMożna modyfikować sposób, w jaki generowane są pliki, ustawiając argumenty nazw plików. Modyfikacje są podawane jako stringi, które określają  strategie, z jaką wygenerują się pliki. Dla podstawowego użycia projektu przydatne będą trzy modyfikacje:\n\n```python\n# Stworzy testy, których wyniki będą zaokrąglone.\n# Przydatne w zadaniach zwracających wartości typu `float`, gdzie wyniki mogą się różnić od ustawionego epsilonu.\nstworz_zadanie([dodaj, mnoż], testy=\"float\")\n```\n\n```python\n# Stworzy testy, których wyniki będą w typie `set`.\n#  Przydatne w zadaniach, w których kolejność lub częstotliwość występowania wyników nie ma znaczenia.\nstworz_zadanie([dodaj, mnoż], testy=\"bez_kolejnosci\")\n```\n```python\n#  Nie stworzy pliku.\n#  Przydatne w zadaniach abstrakcyjnych, które nie są możliwe do przetestowania.\nstworz_zadanie([dodaj, mnoż], testy=\"brak\", szablon=\"brak\")\n```\n\n```python\n# Stworzy zadanie które polega na listach przesyłaczowych\nstworz_zadanie([dodaj, mnoż], testy=\"przesylaczowe_t\", szablon=\"przesylaczowe_s\", README=\"przesylaczowe_rm\")\n```\n\n\nDokładniej o modyfikacjach jest w sekcji [strategie](#Strategie)\n\n\u003cdetails\u003e\n   \u003csummary\u003e Domyślna konfiguracja plików \u003c/summary\u003e\n\n### `README.md` \n1. Dodaje kod do wyświetlania treści zależnych od motywu.\n2. Dodaje linię, aby README formatowało się jak Python.\n3. Z szablonu usuwa treści i zaczyna od pierwszej niezkomentowanej linijki.\n4. Po napotkaniu `main` przestaje pisać.\n5. Kończy formatowanie Pythonowe.\n\n\n### `rozwiazanie.py` \n1. przepisuje prototyp do napotkania linijki main\n```python\n# ====================================================================================================\u003e\n# Zadanie 0\n# Stworz 2 funkcje jedna dodaje 2 liczby druga mnoży dwie liczby\n# ====================================================================================================\u003e\n\ndef dodaj(a, b):\n    return a + b\n\ndef mnoż(a, b):\n    return a * b\n\n```\n### `szablon.py` \n1. Przepisuje pierwsze linie, które są komentarzami, aby zostawić opis zadania wraz z ewentualnymi komentarzami twórcy zadania.\n2. Następnie usuwa wszystkie linijki poza linijką zaczynającą się od `def FunkcjaKtoraTestujemy(`. Tę linijkę pozostawia i dopisuje trzy kropki, aby użytkownik wiedział, że te funkcje są do napisania.\n3. Usuwa wszystkie linie do momentu napotkania bloku `if __name__ == \"__main__\":`.\n4. Zapisuje import funkcji `odpal_testy`. oraz `podpowiedz`\n5. Prosi użytkownika o wprowadzenie argumentów, które pojawią się w szablonie wraz z jego zakomentowanym wynikiem.\n6. zakomentwane funkcje podpowiedz\n7. Zakomentowana metoda `odpal_testy()`, która będzie uruchamiać testy.\n   \n```python\n# ====================================================================================================\u003e\n# Zadanie 0\n# Stworz 2 funkcje jedna dodaje 2 liczby druga mnoży dwie liczby\n# ====================================================================================================\u003e\n\ndef dodaj(a, b): ...\n\ndef mnoż(a, b): ...\n\nif __name__ == \"__main__\":\n    from testy01 import odpal_testy, podpowiedz\n\n    dodaj(2, 3) # return 5\n    mnoż(2,2)  # return 4\n\n    # podpowiedz(1)\n    # podpowiedz(2)\n    # podpowiedz(3)\n\n    # odpal_testy()\n```\n\n### `testy.py` \n1. Napisze  importy, funkcje oraz  nagłówek klasy `Testy`\n2. Następnie dla każdej funkcji przekazanej do testowania:\n3. Sprawdza liczbę argumentów, jaką funkcja przyjmuje.\n4. Jeśli liczba argumentów nie wynosi zero, prosi użytkownika o wpisanie argumentów testowych.\n5. Przetwarza input użytkownika, zmieniając go na argumenty według algorytmów.\n6. Uruchamia funkcję z argumentami testowymi, monitorując jednocześnie wartości wypisywane przez `print` oraz wartości zwracane przez funkcję.\n7. Jeśli funkcja nic nie zwróci, wynikiem zostanie to, co zostało przechwycone przez `print`. Jeśli funkcja zwróci inną wartość, to ona będzie wynikiem, a dane wypisane przez `print` zostaną zignorowane.\n8. Z argumentów i wyniku napisze metodę testową o nazwie `test_numerTestu_funkcjaTestowalna`.\n```python\n    def test_Nr1_dodaj(self):\n        self.assertIn( dodaj(2, 2), 4)\n```\n9. Będzie powtarzać proces od punktów 3–8, aż do napotkania argumentu `stop` od użytkownika, który zakończy testy.\n\n\n\u003c/details\u003e\n\n---\n\n## Pisanie Testów\n\n\nPo uruchomieniu funkcji `stworz_testy`, jeśli liczba argumentów przekazanych do testowania funkcji jest większa niż zero, program poprosi użytkownika o podanie argumentów testowych. Argumenty należy wpisywać w tej samej formie, jak w wywołaniu funkcji w Pythonie.\n\nNajpierw program poprosi o wpisanie argumentów do szablonu, aby użytkownik mógł zobaczyć przykładowe wywołanie w szablonie wraz z wynikiem.\n\n\u003cimg width=\"1000\" alt=\"Zrzut ekranu 2024-12-29 o 20 19 47\" src=\"https://github.com/user-attachments/assets/5a342afc-c949-4573-a3d6-4706f3623f1b\" /\u003e\n\nNastępnie program poprosi o wpisywanie argumentów testowych, które posłużą do testowania funkcji w pliku `testy.py`.\n\n\u003cimg width=\"999\" alt=\"Zrzut ekranu 2024-12-29 o 20 18 33\" src=\"https://github.com/user-attachments/assets/570a5893-090e-45a2-b758-89ff0cca42a8\" /\u003e\n\n\nPo stworzeniu odpowiedniej ilości testów, można zakończyć proces tworzenia testów, podając argument `stop`, co zakończy Twój wkład w tworzenie testów.\n\nNa sam koniec program poprosi o podanie trzech podpowiedzi dla użytkownika.\n\u003cimg width=\"1000\" alt=\"Zrzut ekranu 2024-12-29 o 20 23 14\" src=\"https://github.com/user-attachments/assets/80f5396c-1088-4db8-8b07-e6d0691ca9d7\" /\u003e\n\n###  Finalizacja\n\nPo stworzeniu trzech plików funkcja utworzy plik `prototypBackup.py`, aby bezpiecznie móc usunąć prototyp. Plik `prototypBackup.py` jest ignorowany przez `.gitignore`, więc nie będzie dodawany do głównego repozytorium. Został stworzony, aby w przypadku błędnego stworzenia zadania z różnych powodów móc utworzyć zadanie na nowo. Funkcja `stworz_zadanie` dba o to, by nie usunąć pliku `prototypBackup`, dzięki czemu można tworzyć zadania do momentu zadowolenia z efektu końcowego.\n\nNa tym kończy się funkcja `stworz_zadanie`. Jeśli jednak komuś nie podoba się sposób w jaki pliki `README.py`, `szablon.py`, `testy.py` lub folder `Rozwiazania` są tworzone, chciałby dodać jakąś funkcjonalność lub inaczej tworzyć testy zawsze może stworzyć własną Strategię!\n\n---\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e🧠 Strategie\u003c/summary\u003e\n\n## Strategie\nStrategie definiują sposób, w jaki będziemy tworzyć nasze pliki w projekcie. Aktualna lista strategii znajduje się w folderach o odpowiednich nazwach: [srt/README](srt/README) [srt/Szablon](srt/Szablon), [srt/Rozwiazania](srt/Rozwiazania), [srt/Testy](srt/Testy). Każda z nich jest klasą z krótkim komentarzem opisującym jej przeznaczenie i jest dostępna do użycia przez każdego twórcę zadania. \n\nTaki układ projektu pozwala na prosty rozwój i umożliwia rozwijanie go przez każdego, bez potrzeby znajomości całego systemu. Każdy może napisać własną klasę domyślną, która będzie następnie testowana w użyciu. Po tym, jak stanie się powszechniejsza, szybsza lub lepsza, zostanie ustawiona jako domyślna. Można również dodać klasę dodatkową, która obsługuje testy dla określonej puli zadań, dla których domyślne tworzenie zadania nie jest wystarczające.\n\n\n### Podstawy Pisania Strategii\n\nStworzymy kilka przykładowych klas strategii:\n\n- **`Data`** – Jest to strategia szablonu, która działa jak domyślna, z tą różnicą, że na górze pliku zostanie dodana data rozwiązania.\n  \nW folderze [srt/Szablon](srt/Szablon), tworzymy nowy plik z klasa o takiej samej nazwie. Klasa dziedziczy po jednej z klas w jej folderze albo po klasie bazowej. Klasa [srt/Bazowa.py](srt/Bazowa.py) jest abstrakcyjną klasą, z której będą pochodzić wszystkie klasy pochodne.\n\nKlasa bazowa ma abstrakcyjną metodę `__str__`, w której musimy zwrócić wynik w postaci stringa, który później znajdzie się w pliku szablonu. Dla naszego pomysłu ta klasa będzie wyglądać tak:\n\n```python\n# srt/Szablon/data.py\n\n#  Dziedzicze po klasie z pliku szablonów do której metody __str__  mógłbym coś dodać\nfrom domyslne_s import domyslne_s \nfrom datetime import date\n\nclass data(domyslne_s):\n\"\"\" na górze pliku zostanie dodana data rozwiązania. \"\"\"\n    def __str__(self):\n        res = str(date.today().day)\n        res += \"\\n\"\n        res += super().__str__()\n        return res\n```\n\nAby dostosować sposób generowania pliku, można skorzystać z atrybutów klasy bazowej, które są dostępne w klasach pochodnych:\n\n- **`linie_prototypu`** – lista stringów reprezentujących linie prototypu.\n- **`nr_zadania`** – numer zadania, które rozwiązujemy.\n- **`funkcje`** – funkcje przekazane do testów szablonu oraz inne pomocnicze funkcje.\n- **`sciezka`** – ścieżka folderu, w którym znajduje się tworzone zadanie.\n- **`nazwa_pliku`** – domyślna nazwa pliku, która pochodzi od nazwy folderu zawierającego klasę. Na przykład, w folderze *Rozwiazanie*, klasy dziedziczące mają atrybut ustawiony na \"rozwiazanie{`nr_zadania`}.py\".\n\nTe atrybuty mogą być wykorzystywane w klasach pochodnych od klasy bazowej, a poniżej przedstawiamy przykład użycia jednego z nich.\n\n```python\n# srt/Rozwiazanie/meritum.py\n\nfrom bazowa import bazowa\nimport inspect\n\nclass meritum(bazowa):\n    \"\"\"rozwiazania  która koncentruje się wyłącznie na samym rozwiązaniu, pomijając opis zadania oraz sekcję `main`\"\"\"\n\n    def __str__(self):\n        res = \"\"\n        for funkcja in self.funkcje:\n            res += inspect.getsource(funkcja)\n        return res\n```\n\nTak stworzoną klasę możemy już używać w funkcji `stworz_zadanie`, podając argument `rozwiazanie=\"meritum\"`.\n\n---\n\n- **`float`**  strategia testów, która będzie zaokrąglać wyniki.\n\nStrategie testów będą najtrudniejszych do napisania. Najczęściej będą nadpisywały metody już istniejących strategii i modyfikować sposób sprawdzania wyników testów.\n\nAby skutecznie zaimplementować taką strategię, będziemy musieli nadpisać dwie specjalnie wyodrębnione metody klasy `prime`:\n\n```python\nfrom prime import prime\n\nDOKLADNOSCI = int(input(\"podaj dokładność, z jaką testy mogą zaokrąglać: \"))\n\n\nclass float(prime):\n    \"\"\"testy beda zaaokroglac oczekiwany wynik\"\"\"\n\n    def metoda_zwracajaca_testow_bez_kolejnosci(\n        self, NazwaTestu, numerTestu, zmienne, wynikWywolania, zmienne_nazwa\n    ):\n        return f\"\"\"    def test_Nr{numerTestu:02}_{NazwaTestu}_argumenty_{'_'.join(zmienne_nazwa)}(self):\n            wynik  = {NazwaTestu}({', '.join(map(str, zmienne))})\n\n            self.assertAlmostEqual(wynik, { wynikWywolania }, places={DOKLADNOSCI})\\n\"\"\"\n\n    def metoda_nasluchujaca_testow_bez_kolejnosci(\n        self, NazwaTestu, numerTestu, zmienne, wynikWywolania, zmienne_nazwa\n    ):\n        return f\"\"\"    def test_Nr{numerTestu:02}_{NazwaTestu}_argumenty_{'_'.join(zmienne_nazwa)}(self):\n            f = io.StringIO()\n            with redirect_stdout(f):\n                {NazwaTestu}({', '.join(map(str, zmienne))})\n            wynik = f.getvalue().strip()\n\n            self.assertAlmostEqual(wynik, { wynikWywolania }, places={DOKLADNOSCI})\\n\"\"\"\n```\nKlasa `prime` ma wiele metod specjalnie wyodrębnionych do nadpisywania.\n\n---\n\n\u003e Strategie nie mogą od siebie zależeć i muszą być niezależne. Można je odpalić w dowolnej konfiguracji.\n\n\nOgraniczeniem strategii jest to, że nie przyjmuje argumentów innych niż `input` i jest to ustalenie stałe. Jednak, jeśli chcemy utworzyć zadanie, dodając pewne zmienne, możemy skorzystać z **komend**\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003e 💻 Komendy\u003c/summary\u003e\n\n## Komendy\n\n\u003cdetails\u003e\n   \u003csummary\u003e Działanie \u003c/summary\u003e\n   \nW folderze [srt/Komendy](srt/Komendy) znajdują się pliki Python z komendami. Każdy plik zawiera **funkcje** o takiej samej nazwie, które wykonują odpowiednią komendę.\n\n przykładowa komenda wyglada tak. \n ```python\n# srt/Komendy/hello_name.py\ndef hello_name(imie):\n    print(\"hello\", imie)\n```\n\nTakiej komendy możemy użyć w `szablon.py`, importując z `testy` funkcję `komenda` i przekazując w pierwszym argumencie nazwę komendy, a następnie kolejne argumenty.\n```python\n# ====================================================================================================\u003e\n# Zadanie 1\n# Wypisac swoje imie\n# ====================================================================================================\u003e\n\ndef Zadanie_1(): ...\n\nif __name__ == \"__main__\":\n    from testy01 import odpal_testy, komenda\n\n    komenda(\"hello_name\", \"kamil\")\n\n    # Zadanie_1()\n    # odpal_testy()\n```\n- w pliku `prototyp.py` importujemy z `Develop` funkcje komenda\n\nWynik odpalenia takiego programu będzie: `hello kamil`\n\nTaka funkcjonalność pozwala w prosty sposób rozszerzać projekt o nowe komendy, umożliwiając ulepszanie testów, na przykład poprzez dodawanie dodatkowych testów lub wariacji poprawnego wyniku, a także wprowadzanie własnych preferencji, takich jak dodatkowe zachowanie po przejsciu testów na szablonie.\n\n\u003c/details\u003e\n\n\u003cdetails  \u003e\n  \u003csummary\u003e\u003cstrong\u003e SPIS KOMEND \u003c/strong\u003e \u003c/summary\u003e\n\n### Legenda \n- `nazwaKomendy`, `mozliiwy do uzycia skrot`\n- w budowie oznacza, że nie chce mi sie jej robić\n- lokalna oznacza, że jej działanie nie moze wyjść poza lokalne repozytorium. By uniknąć przypadkow, że ktos nie spodziwal ze mu poleci [najlepsza  domyslna piosenka zwycieska](https://www.youtube.com/watch?v=CpeJiGDVMGo) po napisaniu szablonu\n- Zapis `link_do_muzyki=\"https://www.youtube.com/watch?v=CpeJiGDVMGo` oznacza ze zmienna `link_do_muzyki` jest opcjonalna i domyslnie uzyjemy `https://www.youtube.com/watch?v=CpeJiGDVMGo`\n\n\n\n### Spis \n  - `zmien_testy`\n    ```python\n    # tworzy na nowo zadanie na bazie szablonu jako prototyp\n    komenda(\"zmien_testy\", [funkcje], testy=\"domyslna\", rozwiazanie=\"domyslna\", szablon=\"domyslna\")\n     ```\n\n  \n  - `dodaj_testy`, `dt` - w budowie\n    ```python\n    # dodaje  dodatkowe testy \n    komenda(\"dodaj_testy\", funkcja, ilosci_dodatkowych_testow)\n     ```\n     \n  - `dodaj_wariancje`, `dw` - w budowie\n    ```python\n    # Do istniejacych juz wynikow testow funkcji dodaje kolejne mozliwe warienty na podstawie funkcji przeslanej\n    komenda(\"dodaj_wariancje\", funkcja)\n     ```\n  - `zwycieska_muzyka`,`zm` - w budowie, lokalna\n    ```python\n    # Do testow danego zadania dodaje muzyka po zaliczeniu testow w szablonie\n    # imo must have \n    komenda(\"zwycieska_muzyka\", link_do_muzyki=\"https://www.youtube.com/watch?v=CpeJiGDVMGo\" )\n     ```\n - `funkcja_input`,`fi` - w budowie\n    ```python\n    # szybkie testowanie funkcji na parametrach\n    # dopoki nie przerwiesz bedziesz wpisywac input a komenda uzyje jej na funkcji i wypisze output\n    komenda(\"szybka_funkcja\", funkcja )\n     ```\n    \n  - `StworzStruktureWDI`\n    ```python\n    # Nie bedzie wiecej uzywana i nawet nie da sie jej odpalic z poziomu plikow zadań - Takie zabezpieczenie\n    # Ale dodaje jako taka ciekawostka oraz na przyszlosci do tworzenia struktur innych zadan\n    komenda(\"StworzStruktureWDI\")\n     ```\n\n\u003c/details\u003e\n\n\u003cdetails  \u003e\n  \u003csummary\u003e Ogólne \u003c/summary\u003e\n   \n### Argumenty\nFunkcja `komenda` przyjmuje `\"nazwaKomendy\"`, `*args` oraz `**kwargs`, co pozwala na przesyłanie dowolnych argumentów zarówno w postaci argumentów pozycyjnych, jak i nazwanych. Aby ułatwić korzystanie, dodatkowo są dodawane dwa argumenty, jeśli komenda ich wymaga. Nie ma obowiązku ich podawania podczas wywołania komendy, są to: \n  - `nr_zadania`\n  - `sciezka`\nWięc komenda:\n ```python\n# srt/Komendy/hello_zadanie.py\ndef hello_zadanie(nr_zadania, sciezka):# trzeba pamietac by nazwac te argumenty dokladnie tak \n    print(\"hello\", nr_zadania, \"from \", sciezka)\n```\nMoże być wywołana w następujący sposób:\n ```python\n# prototyp01.py\nkomenda(\"hello_zadanie\")\n```\nWynik takiej komendy to:\n\n`hello 01 from  /Users/user/Desktop/projekty/WDI-RST/Zestaw_1:_Proste_programy_z_pętlami/prototyp01.py`\n\n\n\n### skroty \n\n   Jesli komenda jest czesto używana może miec swój skrót w pliku `_skroty.py`, który tylko importuje komendę i ją odpala.\n  ```python\n  def hz(nr_zadania, sciezka):\n    from hello_zadanie import hello_zadanie\n\n    hello_zadanie(nr_zadania, sciezka)\n   ```\n\n### Zasady komend\n\n- Każda ma mieć swój plik i ograniczać sie tylko do niego nawet jakby plik miałby mieć 20 linijek lub 100000 linijek.\n- Każda komenda musi być w pełni niezależna i działać poprawnie samodzielnie, ale może wywoływać inne komendy w ramach swoich działań [zgodnie z wzorcem łańcucha zobowiązań]( https://refactoring.guru/pl/design-patterns/chain-of-responsibility)\n\n\u003c/details\u003e\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkamilgie%2Fasrt-wdi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkamilgie%2Fasrt-wdi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkamilgie%2Fasrt-wdi/lists"}