Projekt "Qwins!" wciąż się rozwija i dziś przedstawię Wam, w jaki sposób utworzyłem bazę danych, która zostanie wykorzystana do zbudowania gry. Jej budowa może jeszcze się nieco zmienić, ale na tym etapie możemy sobie na to pozwolić. Obecnie nie przewidujemy kont użytkowników, jednak nie będzie to problemem, żeby dodać tę tabelę dopiero później.
Okay, na sam początek trochę o tym, czego używam. Korzystam z narzędzia phpMyAdmin, przez który zarządzam bazą danych MySQL. Projekt wykonuję na localhoście, po czym później będę wykonywał aktualizacje na wykupionym hostingu, abyście mogli obejrzeć projekt na żywo. Na sam początek wyjaśnię, jaki był pomysł na bazę, a następnie przedstawię odpowiednie polecenia SQL, za pomocą których możemy utworzyć odpowiednie tabele, wraz z wyjaśnieniem, dlaczego akurat tak jest to zrobione.
Dla tych, którzy nie śledzą mojego projektu: "Qwins!", to prosta gra w quiz pozwalająca na rozgrywkę za pomocą smartphone'ów. Będzie zawierała zestawy różnych quizów, na przykład quizy wiedzy z danych kategorii, czy quizy językowe.
Skoro już to wiemy, to wiemy też, że bazę wykorzystamy do przechowywania pytań z odpowiedziami. Jest kilka sposobów na podejście do tego tematu – my wybierzemy jednak to, które będzie nam łatwo rozbudować. Najpierw stworzymy tabelę, w której będą kategorie quizów. W grze będzie można wybierać, które zestawy pytań (jeden lub więcej) będą brane pod uwagę podczas losowania zadań. Ta tabela została wykonana tak:
CREATE TABLE IF NOT EXISTS `qwins_category` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(125) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Na początek mamy proste polecenie "CREATE TABLE IF NOT EXISTS", które po prostu oznacza utworzenie nowej tabeli w bazie, jeśli o takiej nazwie nie istnieje. W nawiasie natomiast mamy podane pola wraz z ich właściwościami. Tworzymy w tabeli pole "id", któremu dodaliśmy atrybut "unsigned" – dzięki niemu mamy większy limit, ponieważ liczby przechowywane w tym polu będą nieujemne. To pole nie może być puste oraz ma wzrastać z każdym kolejnym rekordem – jest to typowe pole identyfikatora tabeli. Dodatkowo na to pole został nałożony klucz podstawowy ("PRIMARY KEY"). Nasze następnie, oraz ostatnie już pole, to "name", czyli nazwa kategorii, która ma limit znaków do 125 oraz nie może być pusta. Dodatkowo zakładamy, że nazwy kategorii nie będą się powtarzać, dlatego dodajemy klucz unikalny (UNIQUE KEY) na to pole. I to w zasadzie tyle podstaw.
Powyższa tabela jest bardzo prosta. Moglibyśmy dołożyć do niej sporo innych informacji, jednak zrobimy to nieco później, kiedy będziemy mieli już trochę projektu zrobione i zauważymy, że coś należy w samej bazie zmienić (uzupełniać bazę pytaniami i wszystkim będziemy dopiero pod koniec, więc na pustej możemy zmieniać strukturę do woli).
Następnie zabieramy się za tabelę z pytaniami. No i tutaj mamy kilka rozwiązań. Jedno z prostszych polegałoby na utworzeniu pól z odpowiedziami (jedna poprawna, trzy błędne) w rekordach z pytaniem. Mamy wtedy wszystko w jednej tabeli, ale... niesie też za sobą minusy. My utworzymy dwie tabele – jedna z pytaniami, druga z odpowiedziami na nie. Dlaczego tak? Po pierwsze dlatego, że pytanie dzięki temu rozwiązaniu będzie mogło mieć więcej niż 4 odpowiedzi. Wtedy podczas losowania, pobierana będzie prawidłowa odpowiedź oraz losowane 3, które są błędne, jednak z puli większej niż jest wymagana. Dzięki temu odpowiedzi na pytania nie będą takie "powtarzalne", choć i tak ta możliwość nie będzie raczej wykorzystywana w przypadku każdego pytania. Po drugie, będzie nam łatwiej zarządzać odpowiedziami na pytania. Tworzymy więc taką tabelę:
CREATE TABLE IF NOT EXISTS `qwins_question` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `category_id` int(11) unsigned NOT NULL, `content` varchar(150) NOT NULL, `difficulty` tinyint(4) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Ponownie tworzymy tabelę pod warunkiem, że ta nie istnieje, tak samo dodajemy pole "id" z takimi samymi właściwościami jak w tabeli poprzedniej. Tutaj jednak pojawia nam się coś takiego jak "category_id" i poza kluczem głównym oraz "AUTO_INCREMENT", których nie posiada, nie różni się niczym od pozostałych "id". W tym polu będziemy przechowywać identyfikator kategorii, do której pytanie należy. Dzięki temu będziemy wiedzieć, które pytania wchodzą w skład danej kategorii (i po tym też będziemy je losować). Następnie mamy kolejne dwa pola: "content", limitowane do 150 znaków, w którym przechowywana będzie treść pytania, oraz "difficulty", które będzie liczbowo pokazywało, na jakim poziomie trudności jest pytanie. Nad tym ostatnim możemy się jeszcze zastanowić, czy nie rozwiązać tego w inny sposób – na początek jednak pozostawimy to tak.
Została nam już do utworzenia ostatnia tabela, która będzie zawierać odpowiedzi na pytania. Każda odpowiedź będzie osobnym rekordem, dzięki czemu będzie można je łatwo usuwać czy edytować. Nasza ostatnia tabela także nie będzie zbyt skomplikowana:
CREATE TABLE IF NOT EXISTS `qwins_answer` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `question_id` int(10) unsigned NOT NULL, `content` varchar(150) NOT NULL, `correct` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 - wrong;1 - correct', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
W zasadzie... nie ma tutaj nic nowego, co wymagałoby wyjaśnienia. Po raz trzeci tworzymy pole pod identyfikator, pod id pytania (mamy podpięcie "kategoria <- pytanie <- odpowiedź"), oraz dla treści odpowiedzi (także z limitem 150 znaków). Ostatnie pole będzie przechowywało jedną cyfrę, którą będzie albo jeden, albo zero. Specjalnie dla tego pola dodałem komentarz, który jest jego "legendą" – 0 będzie oznaczało złą odpowiedź, natomiast 1 – prawidłową.
Na obecnym etapie utworzyliśmy trzy proste tabele w bazie. Myślę, że będą później konieczne w niej zmiany, ale póki nie zaczęliśmy jej zapełniać danymi, możemy jeszcze coś z tym kombinować. Wrócimy jednak do tego po przygotowaniu części serwisu, ponieważ okazało się, że lepiej będzie jednak najpierw zrobić jakiś panel do zarządzania pytaniami i odpowiedziami, aby można było łatwo wszystkie utworzyć i do siebie dopasować.