Kun kaksi itselle tärkeää harrastusta yhdistyy

Tässä artikkelissa kerron, miten rakensin itselleni kauan haaveilemani salisovelluksen, jolla pystyn seuraamaan treenituloksiani. Lisäksi pystyn tällä sovelluksella kirjaamaan muistiinpanoja treeneistä, treeniliikkeistä ja -suunnitelmista.

Sisällysluettelo

Taustaa

Kun aloitin kuntosaliharrastukseni kohta 15 vuotta sitten, minulla oli silloin jo tapana kirjata treenituloksiani varsin perinteisellä kynä ja paperi menetelmällä. Tämä tapa antoi minulle järjestelmällisyyttä seurata kehittymistäni ja pystyin helposti tarkastamaan vihkon edellisiltä sivuilta, että minkäslainen se minun treeniohjelma onkaan ja millä painolla olen tehnyt parhaimmillaan minkäkin verran toistoja. Kuntosaliharrastus on kulkenut minun mukana säännöllisenä rutiinina vuodesta toiseen. Yksi vuosi oli poikkeus, kun sain viettää aikaani varusmiespalveluksessa.

Useamman vihkon täyteen kirjoittamisen jälkeen ja älypuhelinten ilmestyessä maailmaan, pohdin, että voisiko teknologia avustaa minua hieman tässä, että ei tarvitsisi välttämättä kuluttaa kirjoituspaperia muistiinpanojeni tuottamiseen. Testailin lukuisia eri treenisovelluksia huomatakseni, että kaikki soveltuivat tarpeisiini vain osittain. Strong App -sovellusta käytin noin parin vuoden ajan ja se oli varsin toimiva. Ongelmana sen käytössä oli kuitenkin se, että minulla ei ollut mahdollisuutta kehittää sitä omien halujeni mukaisesti ja esimerkiksi erilaisten dashboardien rakentaminen oli vain kyseisen sovelluksen kehittäjien varassa. Olin useampia vuosia sitten haaveillut tekeväni oman sovelluksen tähän tarkoitukseen, mutta silloin minulla ei ollut vielä tähän tarvittavaa kyvykkyyttä.

Kipinä sovelluksen kehittämiselle heräsi vuoden 2021 lopussa, kun analysoin Strong App -sovelluksessa kerryttämääni dataa Pythonilla. Tästä pari esimerkkiä alla.

				
					# Lisätään tarvittavat kirjastot

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import pylab
import dateutil
import matplotlib.dates as mdates

# Luetaan sovelluksesta haettu treenidata käyttäen pandas-kirjastoa
data = pd.read_excel('Salidata.xlsx')

# Poistetaan turhat sarakkeet
del data['Distance']
del data['Distance Unit']
del data['Seconds']
del data['RPE']

# Katsotaan miltä käsiteltävä data näyttää
data
				
			

Alla näkyy Pythonilla muodostettu kuvaaja, miten treenisarjojen määrä on kasvanut vuositasolla. Vuosi 2019 näkyy siitä syystä vähäisempänä, että otin Strong Appin silloin käyttöön ja treenit ei tullut kirjattua koko vuoden ajalta.

				
					treeniLiikkeidenMaara = pd.DataFrame({'Date': data.loc[:,'Date'], 'Määrä': 1})
treeniLiikkeidenMaara['Date'] = pd.to_datetime(treeniLiikkeidenMaara.Date, format='%Y-%m-%d %H:%M:%S')
treeniLiikkeidenMaara['Date'] = treeniLiikkeidenMaara["Date"].dt.strftime("%Y")
treeniLiikkeidenMaara = treeniLiikkeidenMaara.groupby('Date').size()

x = treeniLiikkeidenMaara.index
y = treeniLiikkeidenMaara

plt.figure(figsize=(16,10))
plt.plot(x,y)
plt.xticks()
plt.title('Salilla tehtyjen treenisarjojen määrä vuosittain', size=20)
plt.xlabel('Vuosi', size=20)
plt.ylabel('Salilla tehtyjen treenisarjojen määrä', size=20)

for i in range(len(treeniLiikkeidenMaara.index)):
    plt.text(i-0.05,treeniLiikkeidenMaara[i]+20,str(treeniLiikkeidenMaara[i]))
				
			

Alla puolestaan muodostettu kuvaaja sarjojen määristä kautta aikain eri treeniliikkeissä.

				
					treeniSarjojenJakauma = data.groupby(['Exercise Name'])['Exercise Name'].count()
treeniSarjojenJakauma = treeniSarjojenJakauma.sort_values()
treeniSarjojenJakauma = treeniSarjojenJakauma[treeniSarjojenJakauma > 195]

plt.figure(figsize=(16,10))
treeniSarjojenJakauma.plot.barh()

plt.ylabel('Treeniliike', size=20)
plt.xlabel('Sarjojen määrä', size=20)
plt.title('Eri treeniliikkeiden sarjojen määrät kautta aikain', size=20)

for i in range(len(treeniSarjojenJakauma.index)):
    plt.text(treeniSarjojenJakauma[i]+4,(i-0.1),str(treeniSarjojenJakauma[i]), size=15)
				
			

Kuvaajasta voidaan nähdä, että penkkipunnerrus on ollut suosituin liike, joka ei liene yllättävää, koska peruskysymys saliharrastajallehan on ”paljo penkki” ja sitä varten täytyy treenata.

emoji, happy, smiley-5449648.jpg

Totesin näitä ylläkuvattuja analyysejä tehdessä, että en haluaisi aina tehdä sitä prosessia, että lataan treenisovelluksesta csv-tiedoston ulos ja suoritan analyysin Pythonilla. Pohdin, että huomattavasti mielekkäämpää olisi, että pystyisin jatkuvasti seuraamaan minua kiinnostavia asioita suoraan sovelluksessa. Olin joskus aiemmin harjoitellut mobiilisovelluksien tekoa Androidille käyttämällä Android Studioa. En ollut tätä ennen kuitenkaan koskaan saanut kovin toimivaa sovellusta aikaiseksi. Olin joskus aiemmin kuullut joitain asioita Flutteriin liittyen, että sen avulla pystyy sovelluksia kehittää niin Androidille, iOS:lle kuin Webbiinkin. Niinpä lähdin aikalailla puhtaalta pöydältä tutustumaan tähän teknologiaan ja olin tällöin jo päättänyt, että nyt tai ei koskaan tämä pitää toteuttaa.

Flutter

Flutter on Googlen kehittämä avoimeen lähdekoodin perustuva alustariippumaton ohjelmistokehys. Sen avulla pystyy luomaan sovelluksia muun muassa mobiiliin Androidille ja iOS:lle. Tämän lisäksi ohjelmistokehittäjät voivat hyödyntää tätä työkalua myös työpöytä- ja selainpohjaisten sovellusten tekoon. (Flutter – Build Apps for Any Screen, 2022)

Googlen tietojen mukaan Flutter on saanut kehittäjien keskuudessa jo varsin mukavasti menestystä, kun sillä on julkaisuvuodesta 2017 lähtien kehitetty yli 350 000 sovellusta ja kehittäjiä uskotaan olevan yli 2 miljoonaa. Erilaisia kirjastoja Flutterille ja Dartille, jota käytetään Flutterin yhteydessä ohjelmointikielenä, löytyy jo yli 19 000. Nämä tekevät ohjelmistokehityksestä huomattavasti nopeampaa ja eteenkin, jos kirjastot ovat hyvin dokumentoituja, kuten tässä tapauksessa voidaan todeta. (Braken, 2022 ja Flutter Ecosystem, 2022)

Toteutus

Kuten totesin ylempänä, minulla ei ollut aikaisempaa kokemusta Flutterista ollenkaan. Tästä syystä alkuun pääseminen oli melkoisen hidasta. Flutterin asentaminen ja käyttöönotto Android Studion yhteydessä oli vaivatonta, mutta kesti hetken aikaa, että ymmärsin Dartin rakenteen sekä eri funktioiden toimintaperiaatteen.

Ensin minun oli pohdittava, että mitä käyttäisin sovellukseni taustajärjestelmänä. Minulla oli tiedossa, että hallussani oli Excel-tiedosto, joka sisälsi aiemmin Strong App -sovelluksessa kerryttämäni datan. Internetin syövereistä havaitsin, että Dartille löytyi valmis kirjasto Google Sheetsiin. (Gsheets | Dart Package, 2022) Koska tarkoitukseni oli rakentaa omiin tarpeisiini sovellus, totesin pääseväni nopeiten eteenpäin, kun valikoin Google Sheetsin taustajärjestelmäksi. Google Sheets on ilmainen selainpohjainen laskentataulukkotyökalu, jossa on lähes samat ominaisuudet, mitä Microsoft Excel:ssä. (Google Sheets: Free Online Spreadsheet Editor | Google Workspace, 2022)

Tämän jälkeen lähdin tutustumaan, että millä tavalla mobiilisovelluksen käyttöliittymä Androidille luodaan. Päätin, että luon ainakin tässä ensi vaiheessa sovellukseeni neljä pääsivua. Etusivulla näkyisi kojelauta (Dashboard), jossa olisi mielenkiintoisia mittareita datasta. Toisella sivulla tulisi olemaan treenihistoria, jossa pystyisin katsomaan jokaisen treenin yksityiskohdat. Kolmannella sivulla puolestaan olisi treeniliikkeet ja niihin liittyvät muistiinpanot. Viimeisellä sivulla olisi toiminnallisuus, jota ilman sovellus oli täysin turha, eli treenin kirjaus.

Treeniliikkeet ja niiden muistiinpanot

Treeniliikelistauksen sain datasta, jota olin kerryttänyt Strong App -sovelluksen kautta. Pohdin, että rakentaisinko sovellukseen muistiinpanotoiminnallisuuden, johon pystyisi lisäämään niin sanottua ”rikasta tekstiä”. Eli pelkkä tekstilaatikko, johon voisi syöttää normaalia tekstiä, ei kelvannut minulle. Selvittelyn tuloksena en kuitenkaan löytänyt sopivaa kirjastoa, joka olisi antanut minulle mahdollisuudet rikkaan tekstin muistiinpanoihin. Päätin hyödyntää minulla jo ennestään aktiivikäytössä olevaa muistiinpanosovellus Roam Researchia ja Flutterin WebViewiä. WebView antaa näkyvyyden verkkosivustolle mobiilisovelluksen sisällä. (Webview_flutter | Flutter Package, 2022) 

Oheisessa kuvassa voidaan nähdä Treeniliikkeet -sivun listanäkymä, josta kutakin korttia klikkaamalla aukeaa kyseisen liikkeen muistiinpanosivu.

Oheisessa kuvassa näkyy puolestaan muistiinpanonäkymä, johon on helppo kirjata asioita joko treenin aikana tai ulkopuolella.

Kuten ylläolevasta kuvasta nähdään. Muistiinpanoihin pystyy linkittämään myös mielenkiintoisia YouTube-videoita. Lisäksi hashtagia käyttämällä saa muistiinpanosivut linkitettyä keskenään.

Uusi treeni -toiminnallisuus

Että pystytään seuraamaan tuloksia erilaisten kuvaajien ja analyysien avulla ja että voidaan tarkastella treenihistoriaa, täytyy olla mahdollisuudet kirjata treenitulokset. Hahmottelin ”Uusi treeni” -sivulle lomakkeen, johon pystyy kirjaamaan seuraavat asiat:

  • Treenin nimi tai otsikko
  • Päivämäärä ja aika
  • Treeniliikkeet, joita pystyy lisäämään haluttu määrä ”Lisää treeniliike” -painikkeen avulla
  • Muistiinpanot liikekohtaisesti
  • Liikkeen sarjojen paino ja toistot, joita pystyy lisäämään haluttu määrä ”Lisää sarja” -painikkeen avulla
  • Toistot -kentän oikealla puolella olevaan laatikkoon pystyy myös kuittaamaan, että tuliko sarja valmiiksi, eli tämä on niin sanottu ”Checkbox”
Esimerkki tästä kuvatusta sivusta löytyy alta.

Kuten ylläolevasta kuvasta nähdään, sivun yläosassa on painikkeet ”Suunnitelmat”, ”Liikkeet” ja ”Tallenna”. Suunnitelmat -painikkeen avulla voi treenin kirjauksen aikana tarkastaa, että ”mikäs se tämän hetkinen treenisuunnitelma olikaan ja mitä liikkeitä se sisältää”. Tarkastelun jälkeen on helpompi ohjautua kuntosalilla oikean harjoitteen pariin ja myöskin kirjata se sovellukseen. Liikkeet -painikkeen avulla puolestaan voidaan tarkastaa, jos esimerkiksi takakyykystä olisi joitain sellaisia muistiinpanoja kirjattuna, jotka on hyvä salitreenin aikana huomioida. Tallenna -painikkeen avulla arvatenkin saadaan kirjatut tulokset kirjautumaan taustajärjestelmään.

Treenihistoria

Treenihistoria -sivun kautta päästään näkymään, josta löytyy kaikki sovellukseen kirjatut treenit. Haluttua treeniä klikkaamalla päästään tarkastelemaan tarkemmin treenin sarjoja, että mitä liikkeitä tuli tehtyä ja minkälaisia sarjoja. Tästä sivusta esimerkki alla.

Seuraavaksi alla puolestaan kuvattuna yksittäisen treenin tulosnäkymä. Listauksesta löytyy jokainen sarja liikkeittäin järjestettynä.

Treenisovelluksen kojelauta (dashboard)

Viimeisimpänä rakennettuna sivuna voisi mainita treenisovelluksen kojelaudan tai toisin sanottuna etusivun. Tämä sivu kokoaa visualisoinnit halutuista seurattavista asioista. Tiedetään, että kehitystä tapahtuu ainoastaan toistojen kautta, niin treenimäärien seuraaminen on itselleni ainakin mielenkiintoista. Ohessa näkyvässä esimerkissä on treenimääriä viikoittain ja lisäksi liikkeiden sarjamääriä kuluvan vuoden puolelta. Lisäksi treenimääriä pystyy seuraamaan tällä hetkellä myös vuositasolla.


Yhteenveto ja jatkokehitys

Aloitin Flutterin opiskelun joululomallani ja lopulta sain tässä artikkelissa kuvatun sovelluksen niin sanottuun tuotantokäyttöön helmikuun puolessa välissä. Alkuun riitti haasteita ja ihmettelyä, mutta yllättävän nopeasti pääsin asioissa etenemään. Se on kyllä Flutterin erinomaisen dokumentaation ja yhteisön ansiota. Jos virallisesta dokumentaatiosta ei jotain tarvittavaa tietoa löytynyt, niin yhteisön keskusteluista ongelman ratkaisu viimeistään selvisi. Sovelluksen analytiikkaa tulen kehittämään siten, että pystyn seuraamaan kuvaajien avulla kehitystäni treeniliikekohtaisesti. Järjestelmäkehitystyöstäni olen oppinut, että ei kannata odottaa käyttöönottoa siihen asti, että varmasti kaikki ideat on toteutettu, koska sitten se luultavasti ei tule käyttöön koskaan. 

Olen varsin tyytyväinen, että vuosia haaveenani ollut oman salisovelluksen rakentaminen on nyt ensimmäisen version osalta valmis ja kovassa käytössä. Täytyy sanoa, että Flutter sovelluskehitystyökaluna jätti erityisen positiivisen kuvan ja olen varma, että aion hyödyntää tätä myös jatkossa. Itseasiassa seuraavan sovelluksen toiseen aihepiiriin liittyen olen aikeissa rakentaa siten, että taustajärjestelmänä toimii Firebase. Tästä kirjoitan lisää, kun kerrottavaa löytyy.