10.6 Noslēguma projekts: Highscore datubāze
Stundas uzdevums: Apvienot visas tēmas prasmes - projektēt, izveidot un Python kodā lietot pilnvērtīgu datubāzi spēļu rezultātu glabāšanai un statistikai.
70 min plāns: Ievads un kritēriju pārruna (~10 min) · 1. uzdevums (~15 min) - izveido trīs tabulu shēmu · 2. uzdevums (~25 min) - uzraksti Python funkcijas rezultātu pievienošanai · 3. uzdevums (~20 min) - izveido TOP sarakstu un statistiku. Papildu uzdevumu sāc tikai tad, ja pārējie trīs ir gatavi.
Pirms sāc: šis ir 10. tēmas noslēguma projekts. Vajadzēs PostgreSQL un psycopg2. Sāc ar shēmu README.md failā vai diagrammu rīkā, pirms raksti SQL.
Teorija: Spēles apraksts un arhitektūra
Tavs uzdevums ir izveidot pilnvērtīgu Highscore datubāzi - Python lietotnes, kas:
- Pieņem spēles rezultātus no jebkuras spēles (caur funkciju izsaukumu).
- Glabā tos PostgreSQL datubāzē ar pareizām attiecībām.
- Atgriež filtrētus TOP saraksti (pēc spēles, pēc datumu intervāla).
- Aprēķina statistiku (vidējais, rekords, spēļu skaits).
Datu modelis (3 tabulas):
speletaji (id, vards, izveidots)
speles_veidi (id, nosaukums)
rezultati (id, speletajs_id, speles_veids_id, punkti, spelets)
Praktiskie uzdevumi
1. uzdevums -
Izveido trīs tabulu shēmu
Beigās tavā datubāzē būs pareizi saistītas trīs tabulas.
- Izveido failu
schema.sql. - Uzraksti tabulu
speletajiaridun unikāluvards. - Uzraksti tabulu
speles_veidiaridun unikālunosaukums. - Uzraksti tabulu
rezultatiar ārējām atslēgām uz abām iepriekšējām. - Pievieno
rezultatitabulaipunktiarCHECKundatums. - Izpildi skriptu un pārbaudi visas trīs tabulas.
Gatavs, kad: visas trīs tabulas eksistē, un rezultati nevar ievadīt bez esoša spēlētāja un spēles veida.
2. uzdevums -
Uzraksti Python funkcijas rezultātu pievienošanai
Beigās jebkura tava spēle varēs saglabāt rezultātu ar vienu izsaukumu.
- Izveido failu
highscore.py. - Uzraksti funkciju
def pievieno_rezultatu(vards, speles_veids, punkti):. - Atrodi vai izveido spēlētāju un atgriez viņa
id. - Atrodi vai izveido spēles veidu un atgriez tā
id. - Ievadi rezultātu, izmantojot
%svietturus. - Izsauc funkciju piecas reizes ar dažādiem datiem.
- Pārbaudi datubāzē, ka spēlētāji nedublējas.
Gatavs, kad: pēc pieciem izsaukumiem tabulā rezultati ir 5 rindas, bet katrs spēlētājs ir tikai vienreiz.
3. uzdevums -
Izveido TOP sarakstu un statistiku
Beigās tava programma atgriezīs gatavu rezultātu tabulu.
- Uzraksti funkciju
def top_saraksts(speles_veids, limits=5):. - Izmanto tajā
JOINstarp visām trim tabulām. - Pievieno
WHEREpēc spēles veida unORDER BYpēc punktiem. - Uzraksti otru funkciju, kas atgriež vidējo, rekordu un spēļu skaitu.
- Izdrukā abu funkciju rezultātus glītā tabulā.
- Veic commit ar ziņu
Pievieno highscore datubaziun push. - Iesniedz krātuves saiti skolotājam.
Gatavs, kad: TOP saraksts atgriež tieši norādītās spēles rezultātus, sakārtotus no labākā.
Papildu uzdevums - Filtrē pēc datumu intervāla
Ja pamatdarbs ir gatavs, ļauj skatīt tikai šīs nedēļas rezultātus.
- Pievieno funkcijai parametrus
no_datumaunlidz_datumam. - Papildini vaicājumu ar
WHERE datums BETWEEN %s AND %s. - Izsauc funkciju ar pēdējo septiņu dienu intervālu.
- Pārbaudi, ka vecāki rezultāti neparādās.
- Pārbaudi, ka tukšs intervāls neizraisa kļūdu.
Gatavs, kad: vaicājums atgriež tikai norādītā intervāla rezultātus, un tukšs intervāls dod tukšu sarakstu.
Biežākās kļūdas
- ON CONFLICT vajadzīgs UNIQUE: Lai
INSERT ... ON CONFLICT (vards) DO NOTHINGstrādātu, laukam jābūt UNIQUE. - Datu izmaiņas neredz: Aizmirsi
conn.commit(). - JOIN neatgriež datus: Pārbaudi, vai FK norāda uz pareizu PK un dati ir saglabāti pareizās tabulās.
Koda piemērs
-- Pilna shēma + 1 testa rezultāts
CREATE TABLE speletaji (
id SERIAL PRIMARY KEY,
vards TEXT NOT NULL UNIQUE
);
CREATE TABLE speles_veidi (
id SERIAL PRIMARY KEY,
nosaukums TEXT NOT NULL UNIQUE
);
CREATE TABLE rezultati (
id SERIAL PRIMARY KEY,
speletajs_id INTEGER REFERENCES speletaji(id) ON DELETE CASCADE,
speles_veids_id INTEGER REFERENCES speles_veidi(id),
punkti INTEGER NOT NULL CHECK (punkti >= 0),
spelets TIMESTAMP DEFAULT NOW()
);
INSERT INTO speletaji (vards) VALUES ('Anna');
INSERT INTO speles_veidi (nosaukums) VALUES ('Skaitļu minētājs');
INSERT INTO rezultati (speletajs_id, speles_veids_id, punkti) VALUES (1, 1, 95);
SELECT s.vards, sv.nosaukums, r.punkti
FROM rezultati r
JOIN speletaji s ON s.id = r.speletajs_id
JOIN speles_veidi sv ON sv.id = r.speles_veids_id;
------|-------------------|-------
Anna | Skaitļu minētājs | 95