Blogi 1.9.2016

Kikkeritulosten kirjausjärjestelmä

Kiva kun löysit tämän artikkelin! Se sisältää varmasti hyvää tietoa, mutta pidäthän mielessä, että se on kirjoitettu 8 vuotta sitten.

Mikä ihmeen kikkeri?

Pöytäjalkapallo, tuttavallisemmin kikkeri, vakiintui ensimmäisten pöytien saapumisen jälkeen nopeasti Goforen ”kansallispeliksi”. Kikkeripöydän iloista rätkettä saatiin ensin kuunnella vain Helsingin toimistolla, kunnes uuden, brändätyn ja messukelpoisen, pöydän hankinnan myötä Tampereen toimisto peri Helsingin pöydän.
Ensimmäisen kikkeriturnauksen järjestämiseen ei kulunut kauaakaan. Turnauksista on sittemmin muodostunut kahdesti vuodessa tapahtuva perinne sekä Tampereen että Helsingin toimistoilla ja pöytä raahataan mukaan pikkujouluille ja kesäjuhlille toimistojenvälisten otteluiden järjestämiseksi.
Tampereen Kikkeri perustettiin pian Gerhojen lanseerauksen jälkeen 29.4.2015 järjestämään turnauksia, huolehtimaan pelivälineistöstä ja pitämään yllä aktiivista kikkeritunnelmaa.

Kirjausjärjestelmä

Puheet jonkinlaisesta tulosjärjestelmästä alkoivat melko aikaisessa vaiheessa. Visioissa järjestelmästä oli seurantaa, tilastointia ja tunnuslukuja. Analyysin osalta ongelman muodostivat toimistojen erilaiset pelityylit. Helsingissä pelataan tyypillisesti yksi erä kun Tampereella pelataan kaksi. Joskus pelit jäävät kesken projektikiireiden vuoksi, joskus pelataan tarkoituksella pikapeli viiteen maaliin. Pelaajiakin voi olla kummallakin puolella yhdestä neljään, eikä aina yhtä montaa. Kirjausjärjestelmän pitäisi vastata näihin haasteisiin, tarjota rajapinnat jo puheissa olleille IoT-integraatioille sekä tarjota miellyttävä, toiminnallinen käyttöliittymä niin kännyköille kuin isommillekin ruuduille.
Aloitin kirjausjärjestelmän toteuttamisen lokakuussa 2014. Tarkoituksena oli saada Minimum Viable Product nopeasti käyttökuntoon, jotta kirjaaminen voitaisiin aloittaa mahdollisimman aikaisin. Kerättävällä datalla oli kuitenkin tarkoitus tehdä tilastollista analyysia, joten mitä pidemmältä aikaväliltä kirjauksia olisi sitä parempi. Tietomalliksi valitsin hyvin geneerisen ”pelillä on aikaleima sekä joukkueita, joilla on jokin pistemäärä sekä joukko pelaajia”-mallin. Teknologioiksi valikoituivat LiveScript, MongoDB, Mongoose, Node.js, Express, Gulp, SCSS ja Jade. Sovelluksen ensimmäinen julkaistu versio oli päivässä tehty HTML-lomake ilman edes CSS-tyylejä, joka toteutti ainoastaan järjestelmän ensisijaisen tarkoituksen, tulosten kirjaamisen. Laitoin sovelluksen ajoon ”itsenäisen osaamisen kehittämisen tuella” hankitulle palvelimelle. Tulosten kirjaaminen alkoi seuraavana päivänä 17.10.2014 pelillä ”08:58 JariV vs JuusoL | 10 – 5”.
 

Tuloskirjausnäkymä
Tuloskirjausnäkymä

Kehitys jatkui nopeana ja jo viikon jälkeen sovelluksessa oli pelien muokkaustyökalut sekä haku useilla kriteereillä, tagit ja erilaisia d3.js:llä toteutettuja analyysityökaluja yksinkertaisista pelimäärien pylväsdiagrammeista laskennallisiin ”menestysindekseihin” ja voittosuhdegraafeihin. Näitä seurasivat käyttöliittymän kasvojenkohotus purecss:llä, taulukkomallinen analyysityökalu ja olemassaolevien toiminnallisuuksien viilausta. Palvelinsovellus oppi myös keskustelemaan Slack-ryhmächattiin, joten keskustelukanavat #kikkeri-tre ja #kikkeri-hki saavat omista peleistään tiedotukset.
Turnausjärjestelmä valmistui syyskuussa 2015 sopivasti vuoden syysturnausta varten. Aiemmin turnauksen rakennetta oli ylläpidetty vuosittain luotavalla confluence-sivulla, mutta nyt kaikki tilastointi onnistui samalla järjestelmällä.
Tampereen menestysindeksi 2016
Tampereen menestysindeksi 2016

Tekninen toteutus

Rakenteellisesti sovellus on hyvin pelkistetty. Palvelinpuoli on Node.js:llä ajettava Express-sovellus, joka tallentaa pelien tuloksia ja oheistietoa MongoDB-tietokantaan. Toiminta tietokannan kanssa hoidetaan Mongoose-scheman läpi, joka helpottaa tietokannan määrämuotoisuuden säilyttämistä. Isommat loogiset toiminnallisuudet on jaettu pienempiin moduuleihin tarpeen mukaan. Ylisuunnittelun välttämisellä näin pieni sovellus pysyy yksinkertaisena kehittää ja suoraviivaisena ylläpitää.
Sama nykystandardeilla askeettinen lähestymistapa jatkuu selainsovelluksen puolella. Jade-pohjista ja SCSS-tyylitiedostoista palvelimella koostettavat näkymät sisältävät vain välttämättömän määrän toiminnallisuutta. Taulukoita voi järjestää kevyellä tablesort-kirjastolla ja graafeja piirtää D3.js:llä, mutta muuten sivut ovat lomakekäsittelyä lukuunottamatta staattisia HTML+CSS-sivuja.
Kokonaisuutta hallitaan Gulpilla, jossa on pysyttäydytty vain valittujen komponenttien kannalta välttämättömissä livescript- ja sass-plugineissa. Kehityksen helpottamiseksi mukaan on lisäksi otettu nodemon.

Voittosuhdegraafi Oskarin näkökulmasta 2016
Voittosuhdegraafi Oskarin näkökulmasta 2016

Sovelluksen lähdekoodi löytyy GitHubista.

LiveScript

Kaikki sovelluksen oma koodi on niin selain- kuin palvelinpuolellakin kirjoitettu JavaScriptiksi kääntyvällä LiveScriptillä. Kyseessä ei ole kovin laajalle levinnyt kieli, mutta sillä on oma vankka kannattajakuntansa. Itse pidän erityisesti kielen Haskellin inspiroimista funktionaalisista ominaisuuksista, erityisesti prelude.ls-peruskirjastoon yhdistettynä. LiveScriptillä on miellyttävää käsitellä tietoa monimutkaisissakin tapauksissa ja lopputulos on kieleen tottumisen jälkeen luettavaa. Kieli on rakennettu nykyään hieman parjatunkin CoffeeScriptin pohjalle, ja juuret näkyvät paikoitellen. Mielestäni LiveScript on silti miellyttävämpi käyttää kielen monipuolisempien elämää helpottavien ominaisuuksien johdosta.
Alla esimerkki kohtalaisen monimutkaisen, geneerisen tiedonkäsittelyalgoritmin toteuttamisesta LiveScriptillä. Algoritmia käytetään sovelluksessa turnauksen alkusarjan otteluiden järjestämiseen mahdollisimman reiluun järjestykseen.

Joustava hakutoiminnallisuus koosteoperaatioilla

Monessa sovelluksen toiminnossa, kuten pelihaku, tilastojen muodostus ja turnaukset, tarvitaan käyttäjän antaman rajauksen perusteella muodostettavaa pelijoukkoa. Rajausehtoja ovat esimerkiksi tiettyjen pelaajien osallistuminen tai osallistumattomuus peliin, tagit, aikaväli ja pelaajien lukumäärä. Koska rajausehtoja lisätään todennäköisesti jatkossa, tarvittiin joustava järjestelmä sopivan kyselyn muodostamiseksi MongoDB:lle käyttäjän lähettämien parametrien perusteella.
Muutamien ensimmäisten normaaleilla MongoDB-kyselyillä toimivien versioiden jälkeen siirryin kokeilemaan MongoDB:n koosteoperaatioita (aggregate operation), joilla haun suorittaminen sarjana peräkkäisiä suodattimia osoittautui erinomaiseksi valinnaksi. Kukin hakutoiminnallisuuden suodatin muodostaa yksittäisistä suodatusoperaatioista koostuvan listan, jotka yhdistetään muodostamaan varsinainen hakukoosteoperaatio. Koska suodattimet ovat täysin erillisiä, uusien suodattimien lisääminen ei vaaranna aiempien toimintaa. Jos käyttäjän pyyntö ei vaadi suodattimelta toimenpiteitä, suodatinfunktio palauttaa tyhjän listan, eikä siten vaikuta koosteoperaation suoritukseen.

Turnaustoiminnallisuus

Turnausominaisuus on hyvä esimerkkitapaus sovelluksen toiminnasta. Saapuessaan turnaussivulle käyttäjä syöttää turnauksen pelit yksilöivät hakuehdot, esimerkiksi aikavälin 2016-2017 ja tagit ”tre, turnaus, kevät”. Lisäksi tarvitaan turnauksen vaiheisiin liittyvien erityistagien nimet, joilla yksilöidään puolivälierien, välierien, finaalin ja pronssiottelun pelit alkusarjan peleistä.
Vastaanottaessaan lomakkeen tiedot palvelin käyttää yllämainittua yleistä pelirajaustoiminnallisuutta muodostaakseen turnauksen peleistä koostuvan joukon. Tämä pelijoukko turnauksen erityistagien kanssa välitetään turnausfunktiolle, joka selvittää turnauksen alkusarjan tilanteen ja muodostaa näiden perusteella pudotuspelipareja niin pitkälle, kun saatavilla olevan tiedon perusteella on mahdollista.
Määritettyään koko turnauksen rakenteen ja muutamia tunnuslukuja funktio palauttaa tuloksen tietorakenteena, jonka perusteella jade-pohja muodostaa turnauksen visuaalisen esityksen. Turnauksen metatietoja ei siis tallenneta sovellukseen, vaan kaikki päätellään ja lasketaan tarvittaessa. Tietomalli sisältää vain välttämättömät tiedot joustavan geneerisessä muodossa.

Tampereen kevätturnaus 2015
Tampereen kevätturnaus 2015

Lue lisää kikkerikirjauslaitteesta blogisarjan toisesta osasta!

d3js

expressjs

foosball

Gulp

jade

kehtaaminen

kikkeri

kulttuuri

livescript

mongodb

mongoose

node

nodejs

pöytäfutis

pöytäjalkapallo

sass

scss

Takaisin ylös