Buduję aplikację do obstawiania wyników MŚ. Część 1

Buduję aplikację do obstawiania wyników MŚ. Część 1
Photo by Thomas Serer / Unsplash

Nocode poza sposobem pomagania founderom w ich pomysłach które zmienią świat oraz fantastyczną ścieżką kariery freelancerskiej jest też okazją do dobrej zabawy. W weekend gdy byłem na rodzinnym wyjeździe napisał do mnie przyjaciel z prośbą o polecenie kogoś kto napisałby prosty systemik do obstawianek na mistrzostwa - chyba każdy kiedyś bawił się w to.

No i BRAKING NEWS, w te Mistrzostwa to JA mogę to napisać. W parę godzin.

Aplikacje bez kodowania to nie aplikacje bez planowania

Dobre, nie? Wymyśliłem to na zajęciach które prowadzę w Liceum. Niemniej sam nie zawsze się trzymam tej zasady. W tym wypadku byłem na rodzinnym wyjeździe więc mogłem tylko teoretyzować bez komputera. Zawsze preferuję rozpoczynać planowanie od danych - struktura bazy danych pomaga mi szybko ustalić czego będę potrzebował oraz przejść do logiki. Interfejs zazwyczaj jest najprostszy i można go wielokrotnie iterować.

Założenia biznesowe

Chciałem by z tego narzędzia można było skorzystać w przyszłości, dlatego stworzyłem tabelę EVENT - na razie z jednym wpisem - World Cup 2022.

Skoro już robię aplikację, to chciałbym, by mogły z niej skorzystać różne "drużyny" - a nie tylko paczka mojego przyjaciela. Tak powstała tabela TEAM z polami Name oraz Owner. Zakładałem, że właściciel może np aktywować członków swojego zespołu. Z czasem też dodałem mapowanie na EVENT dla wygody dostępności danych - czyli jedna drużyna może obstawiać jedno wydarzenie. Ostatecznie stwierdziłem, że zespoły będą się formowały co wydarzenie sportowe.

MATCH - czyli konkretna gra zawiera wiele kluczowych pól: data wydarzenia, mapowanie na EVENT (każda gra należy do jakiegoś wydarzenia), nazwa drużyny gości, nazwa drużyny gospodarzy, wynik gości, wynik gospodarzy, numer meczu oraz VENUE czyli miejsce wydarzenia. Początkowo tekstowe, ale drugiego dnia chciałem wzbogacić apliakcję wizualnie i zmieniłem na odrębną tabelę.

Ważnym i czasochłonnym etapem było znalezienie listy meczów, przerobienie jej na CSV i wrzucenie do Bubble. To kręgosłup aplikacji.

VENUE - sama nazwa stadionu nie wystarczała mi, więc by zwiększyć elastyczność uznałem, że stworzę tabelę. Składa się ona tylko z nazwy i obrazka, ale jest to też wygodne rozwiązanie na przyszłość.

Zdecydowanie za dużo czasu spędziłem na wyszukiwaniu zdjęć stadionów, ale to moja słabość - chciałem ożywić ten interfejs.

Brakowało mi mapowania USER na TEAM. Jak może zwróciłaś/-eś uwagę, w TEAM nie zrobiłem listy członków, co byłoby jak najbardziej poprawne. Zdecydowałem się na odrębną tabelę MEMBERSHIP która zawiera pary User oraz Team. Być może wrócę do bardziej tradycyjnego rozwiązania. Generalnie jednak unikam list innych obiektów w Bubble ze względu na wydajność.

No i najważniejsze - BET - czyli obstawiony wynik. W tej tabeli dodałem pola: Match - czyli jakiego meczu dotyczy ten typ.  Guest team score, host team score - dzięki temu w późniejszych Workflows mogłem porównywać te wartości z analogicznymi wartościami danego MATCH. Później dodałem też Points - czyli efekt przeliczania punktacji. Na koniec dokleiłem jeszcze Team - chciałem bowiem, by jeden użytkownik mógł być w wielu drużynach - wtedy może wielokrotnie obstawić ten sam mecz.

USERS zawsze staram się pozostawić możliwie lekkie. Imię, avatar oraz Current Team - dzięki czemu aplikacja wie która drużynę pokazywać użytkownikowi.

Interfejs

Zawsze jeśli to możliwe robię strony Single Page App, czyli wszystko jest na jednej stronie a dynamicznie pokazuję i ukrywam grupy (a w zasadzie Reusable - bo pokochałem je jako kontenery logiczne). Na górze i na dole dwie Floating Groupy - MVP robie mobile first - może potem pobawię się z optymalizacją na desktop.

Strona główna pokazuje listę meczów z możliwością obstawiania wyniku oraz sekundowym odliczaniem do spotkania.

Następne ekrany miały być proste - Terminarz to lista spotkań z datą i wynikiem jeśli mecz się skończył. Moje typy to punktacja - tu mogę zobaczyć swoją historię obstawiania. Wyniki pokazuje wszystkich członków drużyny posortowanych po ich punktacji. W tym momencie zdecydowałem na stworzenie nowej tabeli SCOREBOARD gdzie zapisuje każdego użytkownika z polami Team, Score etc. W przeciwnym razie, gdy liczyłem punkty "w locie" (sumując wszystkie BETs danego użytkownika w ramach danego TEAMu) nie umiałem sortować Repeating Group.

Guziki które są na screenach służą mi do debugowania. Bo największym wyzwaniem jest prawidłowe stworzenie Backend workflows które przeliczają punkty. Pewnie można rozwiązać tę kwestie na wiele sposobów - ja zdecydowałem się stworzyć workflow który przelicza wszystkie BETs i przypisuje im punkty na podstawie wyniku meczu.

Konstrukcja backend workflows oraz debugowanie ich pozostawię na drugi wpis.

Warp up

Czekają mnie jeszcze testy by upewnić się, że wszystkie przypadki wyników dobrze przeliczają się na punkty dla użytkownika oraz przetestowanie generowania listy punktów (scoreboard) bo czuje tu intuicyjnie problem. Bubble, z tego co pamiętam, gdy tworzy listę kasuje z niej duplikaty. Więc gdy chcemy przesłać listę: 1, 1, 1, 3, 5; to otrzymamy tylko: 1, 3, 5; To będzie problem przy przeliczaniu punktów dla jednego użytkownika który jest w paru zespołach (jego ID będzie na liście parokrotnie).

Next steps?

  • przetestowanie punktacji
  • dodanie multitenantowości (chcę by użytkownik mógł być w różnych zespołach równolegle)
  • ekran rejestracji do drużyny (chcę by właściciel drużyny mógł wysłać link przez który znajomi mogą się rejestrować i od razu są w drużynie)
  • zapraszanie do drużyny via email
  • podstawowe zarządzanie drużyną przez właściciela - chciałbym by właściciel mógł kontrolować kto jest w drużynie; często zabawie towarzyszy zrzutka
  • prosty landing page i szybka promka przed startem MŚ!

Stworzenie apki do tego momentu zajęło mi 4-6 godzin pracy łącznie z przygotowywaniem bazy danych, ściąganiem zdjęć stadionów etc. I nie jest to oczywiście skomplikowany projekt ale cztery lata temu nawet bym nie śnił, że będę mogł coś takiego zbudować w dwa wieczory.