System zarządzania magazynem obejmujący kompletny cykl życia przyjęcie → składowanie → wydanie: dane podstawowe produktów i lokalizacji, śledzenie partii/dat ważności, wielowymiarową pojemność lokalizacji, planowane odkładanie i kompletację, niezmienialny rejestr ruchów magazynowych oraz pulpit analityczny.
Backend to interfejs Web API oparty na ASP.NET Core (.NET 10), zbudowany w czystej, warstwowej architekturze. Frontend to aplikacja jednostronicowa (SPA) we Vue 3. Dane są przechowywane w PostgreSQL.
| Live demo: | https://ambitious-wave-066504303.7.azurestaticapps.net/ |
| Login: | demo@wms.local |
| Hasło: | 1wFWvd8zrS7! |
Storage / Quarantine / Returns), strefa temperaturowa (Ambient / Chilled / Frozen), wielowymiarowa pojemność (jednostki / masa / objętość — każda ograniczana niezależnie, decyduje najbardziej restrykcyjna), reguły mieszania SKU / mieszania partii, stany aktywny i zablokowany oraz preferowane produkty dla danej lokalizacji.Draft → Putaway → Completed (możliwość anulowania ze stanu Draft lub Putaway).PreferredLocation, ConsolidateSameLot, ConsolidateSameSku, Proximity, NearestEmpty, NearestAvailable.Draft → Picking → Completed (z możliwością anulowania).FEFO (najpierw najkrótszy termin ważności), FIFO, LIFO, LeastQuantity oraz nadpisanie Manual.StockMovement, tworzony jako efekt uboczny poprzez zdarzenia domenowe — kompletna, tylko dopisywalna ścieżka audytu.Admin, Manager, Worker. Wszystkie punkty końcowe domyślnie wymagają uwierzytelnienia; operacje zapisu wymagają roli Admin/Manager.Agregator ogłoszeń o pracę w Belgii: zestaw scraperów zbiera oferty z pięciu portali, zapisuje je do wspólnej bazy z deduplikacją i udostępnia w jednym panelu z filtrami. Przebiegi startują automatycznie według harmonogramu ustawianego z poziomu aplikacji albo ręcznie, jednym przyciskiem.
Projekt zrealizowany na zlecenie firmy — wdrażany na serwerze klienta (w chmurze OVHCloud) jako zestaw kontenerów Docker.
Backend to FastAPI (SQLAlchemy + Pydantic, SQLite, migracje Alembic). Frontend to aplikacja jednostronicowa (SPA) we Vue 3 z TypeScriptem i PrimeVue.
źródło:identyfikator z indeksem UNIQUE — powtórne przebiegi dopisują wyłącznie nowe ogłoszenia.docker compose up; baza i słownik stanowisk żyją w wolumenie, więc przebudowa obrazów ich nie narusza. Schemat bazy tworzą migracje wykonywane przy starcie.Szablon strony portfolio zbudowany w oparciu o framework Angular. Aplikacja nie posiada backendu — cała treść pochodzi z plików w katalogu public/assets, więc stworzenie własnego portfolio sprowadza się do ich podmiany, bez ingerencji w kod źródłowy. Całość budowana jest jako strona statyczna (SSG): każda podstrona, w każdej wersji językowej, trafia do gotowego HTML-a w czasie budowania i może być serwowana z CDN-u, bez żadnego serwera aplikacyjnego.
Dane strukturalne (profil, doświadczenie, projekty, technologie, ustawienia strony) opisane są w plikach JSON, a dłuższe opisy miejsc pracy i projektów — w języku znaczników Markdown, w osobnym pliku dla każdego języka.
outputMode: static generuje statyczny HTML dla każdej trasy i każdego języka. Wyszukiwarki i podglądy linków dostają gotową treść zamiast pustego <app-root>, a w przeglądarce strona hydratuje się do pełnej aplikacji SPA. Dane JSON i opisy Markdown pobrane w czasie budowania są osadzane w wynikowym HTML-u, więc przeglądarka nie pobiera ich po raz drugi./pl, /en), a każda wersja językowa ma własny, prerenderowany HTML. Teksty interfejsu pochodzą z plików tłumaczeń (@ngx-translate), a lista dostępnych języków z konfiguracji strony. Przy wejściu na adres główny język dobierany jest z wcześniejszego wyboru użytkownika, a w razie jego braku z preferencji przeglądarki. Przełącznik w pasku nawigacji zmienia język, pozostając na tej samej podstronie i bez przeładowania.canonical oraz komplet odnośników hreflang do swoich odpowiedników językowych (wraz z x-default), a atrybut lang w znaczniku <html> odpowiada wyświetlanej treści. Strona pobierania CV jest wyłączona z indeksowania.body, z płynnym przejściem kolorów. Wybór jest zapamiętywany i nakładany jeszcze przed pierwszym malowaniem strony, więc przy wejściu nie widać mignięcia drugiego motywu.tools/generate-thumbnails.py (Pillow, OpenCV) tworzy zoptymalizowane miniatury JPEG dla obrazów oraz z pierwszej klatki wideo, zgodnie z konwencją nazw thumb_<nazwa>.jpg.technologies.json; etykiety bez wpisu otrzymują kolor domyślny.IntersectionObserver; każdy element animuje się jednorazowo.Aplikacja desktopowa do zaawansowanego monitorowania czatu w grze Metin2. Czat odczytywany jest wyłącznie z obrazu — okno gry przechwytywane jest co 100 ms, a tekst rozpoznawany autorskim algorytmem OCR działającym na pikselach. Aplikacja nie ingeruje w proces gry: nie modyfikuje plików klienta, nie czyta pamięci i nie wstrzykuje kodu.
Klient to Blazor Hybrid (.NET MAUI, .NET 10) z interfejsem opartym o MudBlazor; przechwytywanie ekranu jest zaimplementowane dla Windows (P/Invoke user32/gdi32: GetDC + BitBlt na obszarze klienta wskazanego okna). Backendem jest ASP.NET Core Web API z bazą PostgreSQL.
[nazwa]) jako osobnych obiektów w wiadomościZamiast gotowego silnika OCR zastosowano dopasowanie wzorców bitowych, dobrze sprawdzające się przy stałej, rastrowej czcionce gry:
charset.bmp + lista znaków w charset.txt) jest skanowana kolumnami; każdy glif kodowany jest jako maska UInt128 i zapisywany w słowniku w obie strony (maska <-> znak).UInt128 (|= z przesunięciem bitowym); pusta kolumna kończy znak i wyzwala odpytanie słownika.Serwery prywatne różnią się czcionką, kolorami czatu, formatem komunikatów, liczbą kanałów, godziną startu serwera oraz listą bossów (nazwa, liczba sztuk, czas respawnu).
{Channel}, {Player}, {Boss} i kompilowane do wyrażeń regularnych z grupami nazwanymi, z których wyłuskiwane są dane o zabójstwie.Minimal API na ASP.NET Core (.NET 10), EF Core + PostgreSQL, walidacja przez FluentValidation.
Silnik do tworzenia gier 2D napisany w C++ z edytorem graficznym: renderer OpenGL, Entity Component System (EnTT), symulacja fizyki (Box2D), natywne skryptowanie oraz autorski moduł sieciowy oparty o GameNetworkingSockets.
Rdzeń architektury bazuje na otwartoźródłowej wersji silnika Hazel, jednak wprowadzono w nim szereg modyfikacji i autorskich rozwiązań — największym z nich jest w pełni własny moduł sieciowy. Jest to projekt hobbystyczny na wczesnym etapie rozwoju, nieprzeznaczony do produkcji komercyjnych gier; rozwój jest obecnie wstrzymany.
W ramach pracy magisterskiej silnik został rozszerzony o moduł sieciowy, który następnie poddano analizie pod kątem wpływu opóźnień sieciowych na jakość symulacji rozgrywki. W szczególności zbadano, jak różne wartości parametrów algorytmu predykcji po stronie klienta oddziałują na częstotliwość występowania oraz skalę desynchronizacji.
Projekt konfigurowany jest przez Premake5 (Windows, Visual Studio) i budowany w trzech konfiguracjach: Debug, Release (z edytorem) oraz Distribution — wersja dystrybucyjna bez edytora, stanowiąca runtime gry.
Silnik powstawał wcześniej pod nazwą Proton2D — cała historia gita znajduje się w starym repozytorium https://github.com/Damian-Zuk/proton2d.
TextureAtlas, Sprite), skalowanie techniką 9-slice, animacje oparte na atlasie.Scene opakowuje rejestr EnTT; Entity to para identyfikatora i wskaźnika na scenę, z UUID nadawanym każdemu obiektowi.AppScript > GameScript > EntityScript (logika aplikacji, trybu gry i pojedynczego obiektu), fabryka skryptów tworząca instancje po nazwie klasy oraz makro rejestrujące.REGISTER_FIELD) trafiają do inspektora i są serializowane wraz ze sceną; obsługiwane typy to wartości skalarne, wektory, tekst i dowolne dane trywialnie kopiowalne.REPLICATED_FIELD) jest automatycznie synchronizowane po sieci, opcjonalnie z funkcją wywoływaną po odebraniu nowej wartości.Ciała sztywne, kolidery prostokątne i okrągłe wraz z parametrami materiału i filtrami kolizji, sensory, nasłuchiwanie kontaktów z wywołaniem zwrotnym w skrypcie oraz złączenia obrotowe (przypięcie obiektu do rodzica).
Architektura klient-serwer z w pełni autorytatywnym serwerem, w trybie listen server, dedykowanym lub klienta. Cała komunikacja odbywa się na własnym binarnym strumieniu (zapis nagłówka wstecz po wyliczeniu rozmiaru ładunku), a każda odczytana wartość jest walidowana względem pozostałego rozmiaru bufora — niespójny pakiet kończy się rozłączeniem klienta zamiast odczytu poza zakres.
PositionX, PositionY, ScaleX, ScaleY, Rotation), a zmiany pól skryptów wykrywane sumą kontrolną CRC32 liczoną per klient. Obiekt, dla którego nic się nie zmieniło, jest wycofywany ze strumienia.Metoda synchronizacji ustawiana jest per obiekt w inspektorze, wraz z progami rekoncyliacji, teleportacji i czasem jej trwania:
Narzędzie CLI w Pythonie generujące raport podatności (CVE) dla urządzeń IoT. Na wejściu przyjmuje ręcznie zdefiniowaną listę urządzeń w formacie JSON (model, wersja firmware'u, adres MAC) i/lub skany sieci wykonane narzędziem Nmap (XML). Dla każdego zidentyfikowanego elementu oprogramowania — firmware'u, usług na otwartych portach oraz systemu operacyjnego — skrypt odpytuje bazę National Institute of Standards and Technology National Vulnerability Database (NIST NVD) i dołącza znalezione podatności do raportu wyjściowego.
Projekt zrealizowany w ramach przedmiotu „Bezpieczeństwo systemów IoT" na Politechnice Rzeszowskiej.
devices.json) — dane wpisane ręcznie stanowią bazę raportu i mają pierwszeństwo przed danymi ze skanów.nmap -A -oX) — hosty dopasowywane są do urządzeń z listy po adresie MAC; nieznane hosty trafiają do raportu jako nowe wpisy. Wyłuskiwane są: adres IPv4, producent (z MAC), wyłącznie porty w stanie open wraz z usługami oraz wynik detekcji systemu operacyjnego.model + wersja, produkt + wersja, nazwa OS + rodzina + wersja). Identyfikatory w starszym formacie CPE 2.2 są normalizowane do CPE 2.3.cpeName; gdy dla urządzenia nie udało się ustalić CPE, wykonywane jest wyszukiwanie po słowach kluczowych, a CPE jest uzupełniane na podstawie pierwszej dopasowanej podatności.vulnerabilities.Raport to tablica urządzeń; każdy wpis zawiera:
firmware, service (klucz: produkt wersja) i os (klucz: rodzina wersja). Każda kategoria zawiera łączną liczbę znalezionych CVE oraz ich listę, a pojedynczy wpis: identyfikator CVE, datę publikacji, opis, użytą metrykę CVSS, wynik punktowy i poziom istotności (LOW / MEDIUM / HIGH / CRITICAL).config.ini)linux, android), dla których liczba trafień jest zbyt duża, by wynik był użyteczny; w raporcie zapisywana jest wtedy adnotacja o pominięciu.Statyczna strona report-viewer.html (bez backendu i zależności) — plik JSON wczytywany jest metodą przeciągnij i upuść. Urządzenia prezentowane są jako rozwijane panele, poziomy istotności wyróżnione kolorem, a identyfikatory CVE i CPE linkują bezpośrednio do odpowiednich stron NVD. Ten sam widok obsługuje plik wejściowy z listą urządzeń, ponieważ ma on identyczną strukturę.
versionEndIncluding) nie są analizowane, więc podatność opisana zakresem może nie zostać wykryta.Projekt studencki z wykorzystaniem narzędzia Ansible do automatyzacji zarządzania konfiguracją maszyn wirtualnych, instalacji pakietów systemowych oraz wdrożenia prostej aplikacji w technologii LAMP.
Całość zrealizowana została w chmurze AWS — na osobnych instancjach uruchomiono węzeł zarządzający oraz zarządzane serwery webowe. Playbooki wykonywane są przez Ansible Semaphore, czyli graficzny interfejs dla Ansible, który udostępnia uruchamianie zadań z poziomu przeglądarki, harmonogramy, magazyn kluczy dostępowych oraz historię i logi wykonania.
Zasadniczą częścią projektu było udokumentowanie konfiguracji całego rozwiązania — od przygotowania instancji i dostępu SSH, przez instalację i konfigurację Semaphore, po opis działania poszczególnych ról. W repozytorium znajdują się wyłącznie pliki Ansible: playbooki, role oraz inwentarz.
admin (z określonym UID i opisem).authorized_keys./etc/sudoers.memory_limit na 256 MB./var/www.config.php na podstawie szablonu Jinja2.Aplikacja internetowa do tworzenia prostych ankiet jednopytaniowych i głosowania, inspirowana platformą StrawPoll.com.
Backend to REST API na FastAPI (SQLAlchemy ORM, PostgreSQL, walidacja przez Pydantic) z Redisem pełniącym rolę magazynu stanu sesji i licznika limitów zapytań. Frontend to aplikacja jednostronicowa w React + TypeScript (Vite, Bootstrap). Całość uruchamiana jest przez Docker Compose, a dokumentacja API generowana automatycznie (Swagger).
Zamiast prostego wystawiania tokenów napisałem osobny moduł zarządzania sesjami (fastapi_jwt_redis), integrujący się z systemem zależności FastAPI:
jti, czasem ważności i czasem rozpoczęcia ważności.Aplikacja React z routingiem po stronie klienta i cyklicznym odświeżaniem sesji w tle (token dostępowy wymieniany zanim wygaśnie). Widok pojedynczej ankiety pod własnym adresem umożliwia jej udostępnianie, a lista głosów oddanych przez zalogowanego użytkownika pobierana jest jednym zapytaniem zbiorczym dla wszystkich widocznych ankiet.
Aplikacja sklepu internetowego do sprzedaży części samochodowych. Stworzona została w grupie 5-osobowej we współpracy z grupą wydziału zarządzania w metodyce Scrum. Aplikacja zrealizowana została w ramach zajęć projektowych na studiach z przedmiotu „Inżynieria Oprogramowania i Baz Danych”.
Zbudowana w Django (Python) z bazą PostgreSQL, szablonami po stronie serwera i interfejsem opartym o Bootstrap. Aplikacja jest wielojęzycznie skonfigurowana pod rynek polski, działa jako PWA i została wdrożona na Heroku (gunicorn, whitenoise).
Mój zakres prac obejmował katalog produktów i warstwę prezentacji: filtrowanie oraz sortowanie listy produktów, podział asortymentu na sekcje i kategorie wraz z paskiem nawigacji, paginację, obsługę cen promocyjnych z widokiem wyprzedaży i sekcją ofert specjalnych, a także wydzielenie zapytań widoku głównego do osobnej warstwy serwisowej. Po stronie interfejsu przygotowałem m.in. responsywny pasek nawigacji, pływający koszyk oraz szablony strony produktu, listy produktów, logowania i rejestracji oraz podsumowania zamówienia.
Zbudowana na otwartoźródłowym module dla Django (lista porównywanych pozycji trzymana w sesji, dodawanie i usuwanie przez AJAX), rozszerzonym o zestawienie parametrów z pola JSON: atrybuty wszystkich porównywanych produktów są scalane w jeden zbiór i układane w tabelę wiersz po wierszu, a brakujące wartości oznaczane myślnikiem. Porównywanie odbywa się w obrębie jednej kategorii.
Gra logiczna wzorowana na klasycznym Sokobanie — celem jest wepchnięcie wszystkich skrzynek na wyznaczone pola. Napisana w C++17 z użyciem biblioteki SFML, bez gotowego silnika: pętla gry, system stanów, encje, animacje oraz kontrolki interfejsu zostały zaimplementowane od zera. Interfejs gry jest w języku polskim.
Projekt budowany jest przez CMake i przeznaczony na platformę Win32 (x86), zgodnie z dołączoną wersją SFML.
Nagłówek (18 bajtów): wymiary planszy, pozycja startowa gracza i liczba skrzynek. Dalej tablica pozycji pól docelowych (po 8 bajtów) oraz siatka kafli zapisana po jednym bajcie na pole (brak kafla / podłoga / ściana / skrzynka).
Wariant tekstury podłogi i ściany losowany jest z ziarna wyliczonego z wymiarów poziomu, dzięki czemu plansza wygląda różnorodnie, a jednocześnie identycznie przy każdym wczytaniu.
Konsolowy komunikator internetowy klient-serwer na platformę Windows, napisany w C++ na gniazdach Winsock (TCP), bez zewnętrznych bibliotek. Serwer i klient to dwie osobne aplikacje uruchamiane z linii poleceń; cała logika — konta, rangi, uprawnienia, bany — znajduje się po stronie serwera, a klient odpowiada wyłącznie za wyświetlanie i przekazywanie tego, co wpisze użytkownik.
Wczesny projekt hobbystyczny, powstały z chęci poznania programowania sieciowego i wielowątkowości.
srand zainicjowany kolejnymi znakami klucza i mieszanym z danymi operacją XOR.GUEST (niezarejestrowany), USER, VIP (kolory w wiadomościach), MOD i ADMIN, porównywane liczbowo — komenda wymaga rangi nie niższej niż jej próg.7d, 12h, 30m), a termin wygaśnięcia zapisywany jest jako znacznik czasu; po jego minięciu wpis przestaje obowiązywać, a pozostały czas prezentowany jest w czytelnej postaci.Zwykła konsola nie nadaje się do czatu: tekst przychodzący z sieci rozbija linię, którą użytkownik właśnie pisze. Na potrzeby projektu powstał osobny komponent rozwiązujący ten problem:
{numer} osadzanymi bezpośrednio w treści — ten sam ciąg może zostać wypisany z kolorami albo oczyszczony ze znaczników, co jest wykorzystywane m.in. przy wiadomościach użytkowników rangi VIP.Klon gry Flappy Bird napisany w Pythonie z użyciem biblioteki Pygame. Pygame odpowiada wyłącznie za okno, rysowanie i zdarzenia wejścia — warstwa gry (obiekty, sceny, zasoby, pętla aktualizacji) została zbudowana od zera.
z_index, co ustala kolejność warstw.tap (ekran startowy), playing, died i died_new_best. Zmiana stanu gry sprowadza się do włączenia jednej sceny i wyłączenia pozostałych, zamiast ręcznego ukrywania pojedynczych elementów.Prędkość opadania narasta do wartości granicznej, a przyspieszenie zależy od fazy lotu — wznoszenie hamowane jest mocniej niż swobodny spadek, co daje charakterystyczny łuk skoku. Po zderzeniu ptak przechodzi w osobny tryb upadku z większym przyspieszeniem i wyższą prędkością graniczną, zatrzymywany dopiero na poziomie ziemi, a ekran końcowy pojawia się z krótkim opóźnieniem.
Rekord przechowywany jest w pliku binarnym poprzedzonym skrótem SHA-256 liczonym z wyniku i stałego ciągu wpisanego w kod. Przy wczytywaniu skrót jest przeliczany ponownie i porównywany z zapisanym — niezgodność (czyli ręczna edycja pliku) lub jego uszkodzenie powoduje odrzucenie rekordu i rozpoczęcie liczenia od zera.
Gra platformowa 2D napisana w C++ na bibliotece SDL2, która odpowiada wyłącznie za okno, rysowanie tekstur i odczyt klawiatury — pętla gry, obiekty, fizyka, kamera i wczytywanie map zostały napisane od zera.
Kolizje nie polegają na cofaniu obiektu po wykryciu przenikania. Dla każdej osi z osobna przeszukiwane są wszystkie obiekty leżące na drodze ruchu i wyznaczana jest najbliższa blokująca krawędź w kierunku prędkości, a nowa pozycja przycinana jest do niej. Dzięki temu obiekt nie przeskakuje przez przeszkodę nawet przy dużej prędkości, a granice mapy działają jak naturalne ograniczenie.
Grawitacja narasta wraz z masą obiektu do ustalonej prędkości granicznej, a kontakt z podłożem i sufitem zeruje prędkość pionową i aktualizuje informację o tym, czy obiekt znajduje się w powietrzu — z tego korzysta skok, wykonalny wyłącznie przy kontakcie z podłożem.
Ruch w poziomie rozpędza się od prędkości początkowej do maksymalnej, przy czym przyspieszenie w powietrzu jest niższe niż na ziemi, a maksymalna prędkość lotu nieco wyższa — daje to wyczuwalną różnicę między bieganiem a manewrowaniem w skoku. Zmiana kierunku w locie lekko koryguje prędkość pionową, a osobny klawisz przenosi gracza z powrotem na punkt startowy.
Symulator ruletki zainspirowany platformą CSGODouble, działający w całości w przeglądarce — bez backendu, na czystym JavaScripcie z jQuery i Bootstrapem. Wczesny projekt z 2017 roku, powstały podczas nauki podstaw JavaScriptu i tworzenia stron internetowych.
Koło ma 15 pól, a zakład stawia się na jeden z trzech kolorów:
Algorytm odtwarza schemat „provably fair" stosowany na platformach tego typu — wynik jest ustalony jeszcze przed rozpoczęciem losowania i możliwy do zweryfikowania po fakcie. Wygrywająca liczba wyliczana jest z trzech wartości:
seed — sekretny ciąg znaków, udostępniany dnia następnego, aby można było zweryfikować prawidłowość losowań z dnia poprzedniego (generowany jako skrót losowego ciągu o długości 48–64 znaków),public — wartość publiczna, którą jest data bieżącego dnia w formacie rok-miesiąc-dzień,round — numer rundy w ramach danego dnia.Wartości łączone są w jeden ciąg i przepuszczane przez funkcję skrótu SHA-256. Pierwsze osiem znaków wyniku odczytywane jest jako liczba szesnastkowa, a reszta z jej dzielenia przez 15 wyznacza wygrywające pole. Z kolejnych znaków tego samego skrótu wyliczane jest również przesunięcie w obrębie pola, dzięki czemu wskaźnik zatrzymuje się za każdym razem w innym miejscu tego samego pola — również w sposób weryfikowalny.
Pola ułożone są na zapętlonej taśmie w kolejności naprzemiennej (czerwone i czarne po obu stronach zera), a losowanie polega na przesuwaniu tła o wyliczony dystans. Ruch wyhamowuje wykładniczo — w każdym kroku pokonywana jest część pozostałej odległości, więc koło zwalnia tym wolniej, im bliżej jest celu. Dystans startowy obejmuje kilka pełnych obrotów powiększonych o drogę do wylosowanego pola, a tempo wyhamowania jest regulowane suwakiem prędkości.
Osobny panel pozwala samodzielnie sprawdzić działanie generatora: ręcznie ustawić lub wylosować ponownie seed, public i round, wyłączyć automatyczne zwiększanie numeru rundy, zmienić długość odliczania i prędkość animacji, znieść limit darmowych żetonów, a także uruchomić losowanie natychmiast, bez czekania na koniec odliczania. Wpisując te same trzy wartości, można odtworzyć dowolne wcześniejsze losowanie i potwierdzić, że wynik nie został zmieniony w trakcie.