Järjestelmä perustuu varsin aktiiviseen tietokannan käyttöön. Syyt tähän ovat toisaalta käyttäjien muokattavissa olevan tiedon runsaus, toisaalta taas WWW-ympäristön erityisvaatimukset. Tietokannan pääsisällön muodostavat erilaiset seikkailun juonta, paikkoja ja esineitä kuvaavat tiedot.
Tietokantapalvelimeksi on valittu korkeakoulukäytössä ilmainen mSQL (Mini SQL), joka sisältää osan SQL-standardin mukaisista ominaiskuuksista. mSQL on jatkuvan kehitystyön alla, ja se toimii useilla UNIX-alustoilla. mSQL:n ominaisuuksia ovat mm. keveys ja nopeus sekä suhteellinen yksinkertaisuus, mitkä sopivat yhteen projektin päämäärien kanssa. mSQL:stä tosin puuttuu monia ominaisuuksia, mitkä olisivat tehneet siitä miellyttävämmän työkalun.
Tietokannan liittymää ohjelmaan käsitellään erikseen luvussa Tietokantaliittymämoduuli.
Johtuen järjestelmän luonteesta (muokattava seikkailupeli) sekä järjestelmän toimintaympäristöstä (WWW) todettiin jo varhaisessa kehitysvaiheessa järjestelmän tietorakenteen monimutkaisuus. Syitä tähän ovat mm.:
Normaalin UNIX:in tiedostojärjestelmän käyttö tämän rakenteen ja toiminnallisuuden toteuttamiseksi olisi ollut suuritöinen ja toteutus ylläpidettävyydeltään heikko. Lisäksi projektiryhmän kokemus tietokannoista vaikutti päätökseen ottaa käyttöön tietokantaohjelmisto. Projektin alkuvaiheissa oli mSQL-niminen tietokanta ainoa vapaa (ilmainen) UNIX-SQL-tietokanta, joka oli aktiivisen kehityksen kohteena. mSQL:n valintaan vaikuttivat myöskin tietokannan väitetyt ominaisuudet, mm. keveys, helppo siirrettävyys eri ympäristöihin ja nopeus sekä muutamien mielenkiintoisten lisäosien saatavuus.
mSQL:n ominaisuuksien kehitys toivottavasti jo projektin ensimmäisen vuoden aikana tuo lisäominaisuuksia, jotka mahdollistavat tiettyjen toimintojen siirron suoraan tietokantamoottorille. Nykyhetken mSQL:n rajoituksia, jotka vaikeuttavat implementointia ovat mm.:
Jos tietokantaa vaihdetaan tai mSQL:stä tulee kehittyneempiä versioita, voidaan näistä ongelmista päästä eroon. Tietokantariippuvat kohdat ohjelmasta on pyritty erottamaan, jotta päivitys olisi helppo.
Tietokantamoottori muodostaa UNIX-koneessa oman prosessin, joka käynnistetään ajamalla mSQL:n bin-hakemiston msqld-ohjelma. Valittuun pid-nimiseen hakemistoon muodostuu silloin pid-niminen tiedosto, johon mSQL tallentaa prosessin id:n.
mSQL:ssä muodostetaan ja poistetaan tietokantoja msqladmin-ohjelmalla. Samalla ohjelmalla voidaan myös sulkea tietokantapalvelin. LAG käyttää yhtä tietokantaa, joka on nimetty LAG:ksi. Tietokanta sijaitsee tiedostorakenteessa mSQL:n databases-hakemistossa. Taulurakenne luodaan normaaleilla SQL:n CREATE TABLE -lauseilla. mSQL:ssä on msql-niminen terminal-ohjelma, jolla voidaan syöttää suoraan SQL-lauseita.
Yhteys LAG:sta tietokantapalvelimeen luodaan mSQL:n kuuluvalla C-funktiokirjastolla, joka muodostaa yhteyden /dev/msqld:n kautta. Saatavilla on myöskin Perl'illä sekä muutamilla muilla ohjelmointikielillä olevia kirjastoja. Se mitä lopullisessa versiossa tullaa käyttämään riippuu erilaisista tehokkuus, yhteensopivuus ym. kysymyksistä.
Taulukko tietokannan taulujen kenttien sisällöstä on liitteenä.
Tietorakenteen keskeisimmät entiteetit (ja tietokannan taulut) ovat:
Jokaisella näistä on primary keynä long integer -tyyppinen laskurikenttä (ID), jota käytetään identifiointiin eri relaatioissa ja tietojen etsinnässä.
N:N Relaatioita on:
E-R-Kaavio.
PostScript-versio:
Tietokannan implementaatio tauluineen, kenttineen ja relaatioineen.
- Käyttäjän nimi on unique
- Käyttäjäryhmän nimi on unique
- Seikkailun nimi on unique
- Paikkojen nimet yhdessä seikkailussa ovat unique
- Esineen nimi yhdessä seikkailussa on unique
- Ominaisuuden nimi yhdessä seikkailussa on unique
Tietokantaliittymämoduuli on ohjelmiston osa, jota kautta muut ohjelman osat kommunikoivat tietovaraston kanssa. Kaikki tietovarastossa oleva tieto kulkee tietokantaliittymän kautta.
Tietokantaliittymän antamia etuja ohjelmalle ovat mm.:
- Tietokantamoottori on helppo vaihtaa
- Myöskin ei-SQL -pohjainen tietokantamoottori mahdollinen
- Tietokannan taulujen, kenttien jne. nimet helppo vaihtaa
- Tietorakennetta voidaan muuttaa, jopa tauluja jakaa, yhdistää jne.
- Vähemmän virhemahdollisuuksia
Tietokantaliittymämoduulin eräänä tarkoituksena on tarjota muille ohjelman osille "käsitetason" liittymä tietokantaan. Tämä tarkoittaa sitä, että muu ohjelma kommunikoi tietovaraston kanssa tavalla, joka ei ota kantaa
Tässä luvussa kuvataan tietokantamoduulin rakennetta, keskeisiä suunnittelunäkökohtia sekä ongelmakohtia.
Yksinkertaiset hakuoperaatiot, jotka etsivät long int -tyyppisen pääavaimen mukaisesti halutun tyyppistä tietoa:
Muita hakufunktioita luodaan tarpeen mukaan, esim.
Tällä funktiolla voitaisiin esimerkiksi etsiä käyttäjän nimeä vastaava käyttäjän ID, jolloin kutsu olisi esim.
EntityName- (entiteetti) ja AttributeName- (attribuutti) parametrit voidaan muuntaa tietokannan tauluja ja kenttiä vastaaviksi erityisen muunnostaulukon kautta.
Tällä tavalla erilaisten tarvittavien proseduurien määrä ei nouse erityisen suureksi, sillä jokainen funktio on monikäyttöinen. Funktioita tarvitaan kuitenkin erilaisia riippuen mm. siitä, etsitäänkö pääavaimen perusteella, minkä tyyppisen arvon tai arvoja funktio palauttaa ja minkä tyyppinen on tai tyyppisiä ovat hakuarvot.
Tietojen päivitysoperaatiot (palauttavat muuttamiensa tietueiden lukumäärän), esim.:
Tietojen lisäysoperaatioiden funktiot joudutaan tekemään jokaiselle entiteettityypille erikseen. Esim.
Tietojen poisto-operaatioiden funktiot ovat kuten hakuoperaatioissa. Ne palauttavat kuitenkin poistamiensa tietueiden lukumäärän. Esim.
Tietojen päivittämisessä yleisin operaatio on jonkin tietyn entiteetin attribuutin muunto, mutta myös useiden entiteettien muutokset ovat mahdollisia. Entiteetin attribuuttia päivitettäessä täytyy tutkia, että eheys ja muut vaatimukset täyttyvät. Primary keytä ei voi päivittää.
Lisättäessä tietueita ainakin pakolliset attribuutit tulee täyttää. Tietokantaliittymämoduuli huolehtii itse perusentiteettien ID-kenttien laskurista. Perusentiteetin lisäys palauttaa uuden entiteetin ID-arvon onnistuessaan. Entiteettiä lisättäessä tarkistetaan myös haluttujen attribuuttien yksikäsitteisyys ja muita mahdollisesti asetettuja ehtoja.
Entiteettien poistossa yleisin operaatio on jonkin tietyn entiteetin poisto, mutta myös useiden entiteettien poistot ovat mahdollisia. Jokaisen poiston yhteydessä täytyy tarkistaa, ettei tietokannan eheys rikkoonnu. Toisin sanoen, kaikki taulut joista on relaatio poistettavan entiteetin tauluun, täytyy tutkia. Relaatiossa olevissa tauluissa ei saa olla relaatiota poistettavana olevaan entiteettiin.
Table | Field | Type | Size | Description |
ActionConditions | ID | Number (Long) | 4 | Unique identifier |
ActionConditions | Argument | Number (Long) | 4 | Numerical argument for user property tests |
ActionConditions | LocationID | Number (Long) | 4 | Meaning depends on action condition type |
ActionConditions | PropertyID | Number (Long) | 4 | Meaning depends on action condition type |
ActionConditions | ItemID | Number (Long) | 4 | Meaning depends on action condition type |
ActionConditions | Type | Number (Double) | 8 | Item carried, item not carried, property greater than etc. |
ActionConditions | ActionID | Number (Long) | 4 | Action ID of the condition (relation to Action) |
ActionParts | ID | Number (Long) | 4 | Unique identifier |
ActionParts | ItemID | Number (Long) | 4 | Relation to Items-table. Meaning depends on action part type |
ActionParts | Argument | Number (Double) | 8 | Numerical argument for user property using action parts |
ActionParts | LocationID | Number (Long) | 4 | Relation to Locations-table. Meaning depends on action part type |
ActionParts | PropertyID | Number (Long) | 4 | Relation to Properties-table. Meaning depends on action part type |
ActionParts | Type | Number (Long) | 4 | Type of the action: (MOVE, GET, DROP, SETPROP, INCPROP, DECPROP, MOVEITEM) |
ActionParts | ActionID | Number (Long) | 4 | |
Actions | ObstacleOptions | Text | 10 | Options for the obstacle |
Actions | SuccessMessage | Text | 255 | Message to the player, if the action was succesful |
Actions | BeforeMessage | Text | 255 | Message to the player, before the action is done (before obstacle!) |
Actions | ObstacleClass | Text | 10 | Type of the obstacle (0=none) |
Actions | Description | Text | 50 | Description of the action shown to players |
Actions | LocationID | Number (Long) | 4 | Location, at where the action is available |
Actions | ID | Number (Long) | 4 | ID of the Action |
Actions | Name | Text | 10 | Internal name of the action for the game writers |
ActionsDone | UserID | Number (Long) | 4 | |
ActionsDone | ActionID | Number (Long) | 4 | |
Adventures | Name | Text | 20 | Name of the adventure |
Adventures | ID | Number (Long) | 4 | |
Adventures | Description | Text | 255 | Description of the adventure |
Adventures | FirstLocationID | Number (Long) | 4 | First location of the adventure |
Groups | ID | Number (Long) | 4 | |
Groups | Name | Text | 20 | Name of the user group |
Groups | Permissions | Number (Long) | 4 | Permissions of users of this group (e.g. play/write/teacher/administrate) |
ItemLocations | LocationID | Number (Long) | 4 | |
ItemLocations | UserID | Number (Long) | 4 | |
ItemLocations | ItemID | Number (Long) | 4 | |
Items | DefaultLocationID | Number (Long) | 4 | Location of the item at the startup |
Items | ID | Number (Long) | 4 | ID of the Item |
Items | AdventureID | Number (Long) | 4 | Adventure to which the object belongs to |
Items | Name | Text | 20 | Name of the Item |
Items | PictureFile | Text | 20 | Picture file name of the Item (not necessary) |
Items | Description | Text | 255 | Description of the item |
Items | OwnerGroupID | Number (Long) | 4 | Group that has the modify permissions for this object |
Locations | AdventureID | Number (Long) | 4 | Adventure to which the location belongs |
Locations | ID | Number (Long) | 4 | ID of the Location (0=Nowhere, 1=Carried) |
Locations | Name | Text | 10 | Name of the location |
Locations | NoItemsText | Text | 255 | A text, that is displayed if there is no items in the location (e.g. The trashbin is empty) |
Locations | OwnerGroupID | Number (Long) | 4 | Group that has the modify permissions for this object |
Locations | Header | Text | 50 | Longer name of the location |
LocationsBeen | UserID | Number (Long) | 4 | |
LocationsBeen | LocationID | Number (Long) | 4 | |
Properties | PictureFile | Text | 20 | Picture file name of the property (not necessary) |
Properties | DefaultValue | Number (Long) | 4 | Default value of the property in the adventure |
Properties | OwnerGroupID | Number (Long) | 4 | |
Properties | Description | Text | 255 | Description of the property |
Properties | AdventureID | Number (Long) | 4 | Adventure to which the object belongs to |
Properties | ID | Number (Long) | 4 | ID of the property |
Properties | Name | Text | 20 | Name of the property |
PropertyValues | UserID | Number (Long) | 4 | |
PropertyValues | Value | Number (Long) | 4 | Current value of the property |
PropertyValues | PropertyID | Number (Long) | 4 | |
Users | GroupID | Number (Long) | 4 | ID of the User's group |
Users | LocationID | Number (Long) | 4 | Current location of the User |
Users | Password | Text | 10 | Password of the User (not crypted, since no need) |
Users | LastActionTime | Date/Time | 8 | Date/Time of the last action of the user |
Users | Name | Text | 20 | Name of the User |
Users | ID | Number (Long) | 4 | ID of the User |