perjantai 5. helmikuuta 2016

Racket - osio Koodiaapinen MOOC (beta)

Vedin Koodiaapinen MOOC:in Racket osuuden viime syksynä. Toimiminen MOOC-opettajana oli hieno kokemus, mutta näin jälkikäteen ajateltuna, aivan liian suuri ponnistus yhdelle ihmiselle. Koska olin vasta kehittelemässä Racket-opetusmateriaalia, kurssin alkaessa valmiina oli vasta ensimmäisen viikon materiaali ja näin ollen jouduin kehittelemään kurssimateriaalit (videot, tehtävät, Power Pointit, nettisivuston) sitä mukaa kun kurssi eteni. Tämä ei ollut paras mahdollinen tilanne luoda toimiva kurssimateriaali, mutta pienistä aikatauluongelmista huolimatta, kurssi saatiin kuitenkin päätökseen aikataulussa.

Ideoita kurssin toteutukseen sain viime kesänän käymältäni EdX kurssilta Systematic Program Design, jossa ohjelmointikielenä käytetiin myös Racket BSL:ää. Toteutin videotutoriaalit samaan tyyliin kuin tuolla kurssilla, demot itse koodaten ja esittelyvideot kameralle puhuen. Samoin harjoitustehtävät malliratkaisuineen toteutin samalla tavalla. Myös ensimmäisen viikon kuvatehtävä oli samanlainen kuin kuin EdX:n kurssilla, mutta seuraavat viikot toteutin eri tavalla. EdX käytti kurssin arviointikriteerinä monivalintatehtäviä, näitä ei Koodiaapinen MOOC:issa käytetty ollenkaan, sen sijaan Padlet-seinät ja toisille jakaminen oli isossa roolissa. EdX päättyi laajemman harjoitustyön koodaamiseen ja sen vertaisarviointiin, Koodiaapinen MOOC päättyi pedagogiseen "diplomityöhön".

Syksyn kurssia lähdettiin tekemään "beta" nimellä, koska ymmärsimme, että tyhjästä on äärimmäisen vaikea pystyttää mitään täydellistä ja virheetöntä. Pyysimme kurssilaisilta järjestelmällisesti viikkopalautteita (N=855) materiaalin jatkokehittämisen tueksi, tässä tiivistelmää niistä.

Taustatietoja

Tyypillisin Racket-kurssilainen oli 45-55-vuotias, vakituisessa työsuhteessa oleva, yläkoulun matemaattisten aiheiden (mafykeat) opettajanainen Uudeltamaalta. Vajaa puolet seurasi samalla myös Koodiaapisen muita linjoja (Scratch ja/tai ScratchJr) vähintään "jonkin verran".

Kurssimateriaalin teossa pyrittiin siihen, että kurssin voisi suorittaa käyttämällä opiskelemiseen noin 2h viikossa. Viikon opetusvideoiden kesto yritettiin pitää alle 30 min, varsinaisia pakollisia harjoitustehtäviä ei ollut, mutta niitä suositeltiin tehtäväksi n. 3 per viikko ennen varsinaisen ohjelmoitavan viikkoharjoituksen palautusta. Palautteen perusteella kurssilaiset käyttivät opiskeluun selvästi arvioitua enemmän aikaa viikossa. Hieman alle puolet kurssilaista käytti siihen aikaa 2-4h viikossa kun taas kolmasosa käytti siihen yli 4 tuntia.     

Viikko  1.

Ensimmäisen viikon tarkoitus oli tutustua Racket kieleen ja sen ohjelmointiympäristöön DrRacket:iin kuvien koodaamisen kautta. Laskennallisen ajattelun taitona tällä viikolla oli "ongelman jakaminen osiin" (kuvan jakaminen osiin).

Materiaali tuntui toimivalta ja porukka oli innostunutta. Padlet - seinälle kasaantui kokonaista 369 erilaista Racket:llä koodattua kuvaa (lippuja, logoja yms.)


Palaute teoriasta:
  • videot tekivät teoriasta selkeän, oli helppo kokeilla samalla kun seurasi videoita
  • hauskoja tehtäviä, sopivan haastavia
  • kuvien kautta pääsi hyvin perille Racketin syntaksista, toimisi oppilaillakin
  • aivan liikaa asioita ensimmäiselle viikolle
  • paljon käsitteitä, ne pitäisi selittää selkokielellä (ihminen joka ei ole koskaan ohjelmoinut kauhistuu) 
  • funktiot olisi hyvä kerätä yhteen paikkaan (joutui hakemaan paljon)
  • malliratkaisut olivat hyviä
  • Padlet oli hyvä lisä
  • dioihin enemmän esimerkkejä
  • hankalaa kun materiaalia oli monessa paikassa (monta välilehteä auki)
  • parempi materiaalin esittely alkuun (mikä on racket.koodiaapinen.fi, Eliademy jne.)
  • opettaja oletti oppilaiden tason olevan korkeampi 
  • vaikea löytää videolta jälkikäteen oikeaa kohtaa (dia-esityksiin tiivistelmä videoita)
  • pedagogiikkaa heti alkuun, "miten opettaisit oppilaille tämän"
Palaute tehtävistä:
  • oma kuvallinen aihe oli kiinnostava aloitus kurssille
  • hyvä että sai valita kuvan vaikeustason itse
  • harjoitukset olivat sopivan haastavia aloittelijalle, niiden vaikeustaso nousi sopivasti
  • harjoitustehtävät olivat sopivia yläkoulun aloitteleville oppilaille
  • tehtävät innostivat tutustumaan uuteen työkaluun
  • peruskuvat riittäisivät hyvin ensimmäiselle kerralle 
  • ilman harjoitustehtäviä olisi ollut mahdoton tehdä viikkotehtävää
  • en olisi oppinut ellen olis joutunut koodaamaan itse
Mitä opin:
  • voisin jo ensimmäisen viikon jälkeen suunnitella yksinkertaisia harjoituksia oppilaille
  • innostuin koodauksesta
  • opin, että koodaaminen on monimutkaista ja pikkutarkkaa hommaa
  • sain pienen käsityksen siitä miten laaja ohjelma DrRacket on verrattuna Scratch:iin
  • idea on yksinkertainen vaikka erilaisia funktioita tuntuu olevan loputon määrä
  • peilaamaan, kiertämään, ottamaan osia kuviosta, sijoittelemaan niitä haluamaani paikkoihin
  • opin hyviä koodauskäytänteitä (ei kirjoiteta turhaa koodia)
  • huomasin, että matematiikan ja Racketin funktiot ovat samankaltaisia 
  • Racket-koodaus tuntuu ihan oikealta koodaukselta (verrattuna Scratch:iin)
  • opin käyttämään Koodarin käsikirjaa ja luottamaan itseeni
  • funktionaalinen ohjelmointi on kivaa

Viikko 2.

Toisen viikon tavoite oli opetella funktion käsite, ja jatkaa ongelman jakamista osiin funktioiden kautta. Tällä viikolla tuli paljon asiaa: mikä on funktio, miten se suunnitellaan, määritellään ja  testataan. Kävimme läpi myös funktion suunnittelupohtaat menetelmän. Laskennallisen ajattelun taitona oli tällä viikolla abstraktio eli erikoistapausten muuttaminen yleiseksi ratkaisuksi muuttujien ja funktioiden avulla. Edelleen jaoimme ongelmaa osiin, nyt pienempiin funktioihin. Hyviä ohjelmointikäytänteitä edusti funktion suunnittelu (testitapausten ohjelmointi) ennen sen koodaamista.  

Tällä viikolla viikkotehtävän sai palautettua 211 kurssilaista. Padlet - seinälle piti palauttaa itse suunnittelemansa funktio tai kaksi. 



Palaute teoriasta:
  • check-expect:in käytön hyöty ei auennut, ei selitetty tarpeeksi, että se on funktion testausta
  • videon koodi pitäisi olla saatavilla myös tiedostona
  • stub:in käyttö ei valjennut, olisi hyvä esitellä paremmmin jokainen uusi asia joka kurssilla tulee
  • hyvä, että koodi alkaa "puhtaalta pöydältä" [videoissa]
  • teoriaosio kattava ja laaja
  • funktio oli helppo mutta check-expect vaikea
  • portaat hyvä juttu, funktion suunnitteluprosessi tuli selväksi, kiva että se oli esitetty sekä visuaalisesti että esimerkein
  • selkeämmät ohjeet milloin puolipiste, milloin välilyönti
  • string-append tuli ihan puskista, olisi hyvä että selitettäisiin miten merkkijonoja muokataan Racket:illä
  • matemaattispainotteiset esimerkit tuovat lisäpaineita
Palaute tehtävistä:
  • tätä voi hyvin käyttää 9.lk matikassa
  • pinta-alatehtävät ok, kuvatehtävät liian vaikeita 
  • onnistui kun rohkeni kysyä apua, verkkokurssilla haastavaa yrittää yksin
  • hyödyllisempi tehtävä kuin viikolla 1.
  • tehtävä jossa piti täydentää valmista koodia oli hyvä formaatti
  • kurssilaisten erilainen lähtötaso ja Padlet-seinälle jako kuohutti (ei kehdannut laittaa mitä tahansa)
  • vaikea keksiä funktiota josta olisi hyötyä
  • tällä viikolla olisi ollut parempi antaa valmiiksi määritelty tehtävä, huomio olisi kiinnittynyt oikeisiin asioihin 
  • kului paljon aikaa ymmärtää miten numeroista saadaan tekstiä
  • vaikea keksiä mitään koodattavaa kun ei ole if-lausetta
  • ilman kuvafunktioitakin tälle viikolle olisi ollut tarpeeksi asiaa
Mitä opin
  • opin tekemään funktioita ja kiinnittämään huomiota siihen, että nimeän funktiot ja muuttujat mielekkäästi
  • asian paloittelu loogisesti ei ole ihan helppoa
  • merkkijonojen käsittelyä Racket:issä 
  • opin tekemään yhden "monimutkaisen" funktion apufunktioiden avulla
  • ymmärsin lopulta funktion suunniteluportaat, stubin idean ja testauksen
  • monimutkaisten funktioiden omaksuminen vaatii paljon toistoa, tarkkuutta ja ohjelmointikielen hyvää ymmärtämistä
  • tällä hetkellä tuntuu, että Racket:illä saa tehtyä vaikka mitä

Viikko 3 ja 4 

Viikko 3 ja 4 sulautuivat yhteen aivan siitä syytä, että viikon 3 materiaalin tekeminen venyi liian pitkäksi enkä ehtinyt tehdä uusia tehtäviä viikolle 4. Tämä ei ollut ollenkaan huono asia, sillä moni kurssilainen piti siitä, että tehtävien tekemiseen oli varattu enemmän aikaa. Tavoite oli oppia tekemään haarautuvaa koodia, eli kävimme läpi totuusarvot, vertailuoperaattorit, predikaatit, Boolean operattorit (and, or, not) sekä ehto- ja valintalauseen. Lisäksi tuli vielä sovellukset, eli käyttäjän antaman syötteen käsittely, animaation pyörittäminen ja hiiren liikkeiden rekisteröinti. Ja kaiken kukkuraksi palautettava työ piti palauttaa WeSchemen kautta. Laskennallisen ajattelun teemana tällä viikolla oli algoritmit sekä logiikka.

Tällä viikolla tehtävän palautti Padlet-seinälle 151 kurssilaista.


Palaute teoriasta: 
  • esimerkit selkeitä, harjoitustehtävät vaikeita ja niitä oli paljon
  • paljon materiaalia, harmittaa kun ei ehdi käydä kaikkea
  • valmiit muokattavat koodit hyviä
  • hyvä, että aikaa 2 viikkoa
  • if ja cond esittiin hyvin, interaktiiviset ohjelmat vaikeita
  • liikaa asiaa, videoiden katselu puudutti
  • videot todella hyviä ja niitä oli helppo seurata
  • pikanäppäimistä ei ollut yhteenvetoa
  • sisäkkäiset if-lauseet jäivät käymättä
  • peliesimerkissä olisi voinut tehdä enemmän kysymyksiä, että olisi selvinnyt miten useamman kysymyksen pelin saa tehtyä
  • tuntuu liian haastavalta materiaalilta yläkoululaisille
  • hyvä idea muuttaa materiaalia ei-matikisteille sopivammaksi
  • tässä olisi voinut tulla jo silmukoita
Palaute tehtävistä:
  • ei ole aikaa olla luova, olisi parempi antaa selkeä tehtävä: "koodaa laskin, koodaa joulukuusi"
  • vaikea mutta valmiita ratkaisuja katsoessa tehtävä aukeni ja sitä voi jopa käyttää omassa työssä
  • tehtävät eivät olleet niin raskaita kun oli valmis pohja
  • jakaisin tämän kahdelle eri viikolle: sovellukset erikseen
  • ehdottomasti hyödylllinen, aion koodata oppilailleni pelin
  • ehto- ja valintalauseet ovat helpompia kuin funktio 
  • yllättävää kuinka paljon voi saada aikaan jo näin vähillä taidoilla
  • monet sisäkkäiset funktiokutsut aiheuttivat ongelmia (sulkuja puuttui)
  • sain apua keskustelupalstalta
  • hyvä ettei tarvitse tehdä kaikkia harjoituksia
Mitä opin:
  • ehtolauseita, käyttäjän antaman vastauksen lukemista
  • hakemaan ohjelmiin tiedostosta tallennettua materiaalia (kuvia)
  • tekemään oppilaille harjoitustehtävän
  • Racket on yllättävän monipuolinen kieli
  • löysin koodausinnostuksen uudelleen kun tajusin tehneeni pedagogisesti käyttökelpoisen sovelluksen, jota voin hyödyntää omien oppilaideni kanssa
  • opin, että tietokoneen kellon ja hiiren toiminta voidaan "liimata" koodiin
  • tekemään animaatioita Racket:illä
  • syötteen tarkistuksen ja syötteen käyttämisen osana ohjelmaa
  • oppilaan pitää koodauksen aikana saada joka kerta positiivisia kokemuksia
  • opin, että kannattaa kysyä muilta apua kun on pulassa 
 

Viikko 5. 

Viides viikko ei mennyt aivan suunnitelmien mukaan, koska neljännelle viikolle suunnittelemani rekursio (silmukat), jouduttiin pudottamaan pois ja hyppäsin suoraan Racket Turtle - kuvioiden piirtelyyn. Silmukat otin mukaan map, range ja foldl:n kautta, koska se tuntui  lyhyemmältä ja suoraviivaisemmalta tavalta tehdä monimutkaisempia Turtle kuvia. Tällä viikolla laitoimme myös aivot hieman narikkaan ja tehtävänä oli "leikkiä" koodilla, kokeilla mitä se tekee, kun muuttaa eri asioita.

Tämän viikon tehtävän, silmukan avulla piirretun kuvion, palautti Padlet-seinälle 144 kurssilaista.


Palaute teoriasta: 
  • Turtle oli todella selkeä, map/foldl ei oikein auennut
  • haluaisin skrollata videota, että näkisi mitä on koodattu
  • videoissa olisi voinut olla enemmänkin esimerkkejä
  • valmiit ratkaisumallit auttoivat eteenpäin
  • videot jäivät pinnallisiksi, ei selvinnyt mitä näillä voidaan tehdä
  • silmukan koodin teko oli vaikeaa enkä hahmottanut miten sitä voisi muuttaa haluamakseen
  • aloittelevana koodaajana mallikoodin muokkaaminen on helpompaa kuin tyhjältä pöydältä lähteminen
  • materiaalin opiskelujärjestys pitäisi ilmoittaa selvästi
Palaute tehtävästä:
  • tehtävät olivat innostavia, mukavaa että oli tällaista kokeilua
  • piirtämällä koodaaminen on aina PALJON mielenkiintoisempaa
  • nyt tuntuu siltä, että tätä mä luulinkin, että koodaus on (Turtlea vastaavia graafisia ohjelmia on tehty oppilaiden kanssa)
  • listojen käytöstä olisin kaivannut lisätietoa (miten listasta poimitaan tietty alkio ja miten listaan lisätään alkoita)
  • en ymmärtänyt milloin oma funktio tuotti kuvan ja milloin funktion
  • olisin oppinut enemmän, jos tehtävä olisi ollut sidotumpi
  • voisi vinkata että ympyrä on monikulmio, jossa on 360 kulmaa (tai 72 kulmaa)
Mitä opin
  • opin leikkimään Racket:illä
  • Turtle-kirjaston käyttöä ja silmukoiden tekoa
  • piirtämään hienoja kuvioita, epäkeskoja ja spiraaleja, listat, silmukat, käännökset, random, värivaihtelut...
  • en halua käyttää koodaamisen opetteluun 10 000 tuntia, jonka se opettelu näyttää minulta vaativan (minulla on elämä, koodarilla ei)
  • pääsin tutustumaan kilpikonnan ajatusmaailmaan
  • rekursiivisen toiston
  • opin Racket Turtlen tarjoamia mahdollisuuksia, tai ennemminkin sen, että siellä on mahdollisuuksia vaikka kuinka paljon, kunhan vaan pääsee hommaan sisälle
  • vaikeaa oli mutta koukuttavaa

Viikko 6. 

Viimeisellä viikolla ei tullut enää uusia ohjelmointiasioita vaan keskityimme pedagogiaan ja sen miettimiseen miten tätä kaikkea voisi hyödyntää opetuksessa. Materiaalina oli johdantovideo sekä Power Point -diat, tehtävänä tehdä teksti tai harjoitustehtävä ja jakaa sen pilvipalvelun kautta.

Tämän diplomityön palautti 137 kurssilaista. Yleistä pohdintaa OPS:ista, ohjelmoinnista sekä siitä miten ohjelmoinnin voi integroida opetukseen pohti noin 50 kurssilaista (A vaihtoehto), oman uuden Racket harjoitustehtävän laati noin 40 kurssilaista (B vaihtoehto) ja tuntisuunnitelman teki myös noin 40 kurssilaista (vaihtoehto C).

Palaute teoriasta:
  • oli hyvä, että kurssi loppui oman opetuksen suunnitteluun 
  • oli hyvä käydä läpi OPS
  • tarvitsisin selkeät ohjeet, että tee näin ja näin, en osaa opettaa hyviä ohjelmointikäytänteitä tai algoritmista ajattelua vain "hauskaa leikkimistä"
  • materiaalissa oli hyvä lista erilaisia pedagogisia malleja
  • OPS, koodaus ja koulu, ei auennut mikä yhteys näillä on
  • OPS:ia voisi käydä läpi myös alussa orientoivana
Palaute tehtävistä:
  • vaativa ja innostava tehtävä
  • tehtävä hyödyllinen ja sopivan vaikea, että jotain oppi, pääsi käyttämään teoriaa hyödyksi
  • tavallaan kaikkein vaikein, mutta myös hyödyllisin kaikessa "ärsyttävyydessään", oli pakko yrittää saada kaikki sirpaleinen tieto päässään jokinlaiseksi konkreettiseksi kokonaisuudeksi
  • suurin anti oli ehdottomasti se, että kurssilaisten suunnitelmat kertyvät valtavaksi ideapankiksi
  • nyt vasta ymmärrän viikkojen 2 ja 3 materiaalin tärkeyden, silloin se tuntui aika ylivoimaiselta ymmärtää
  • tuntui, että nyt ollaan asian ytimessä eli miettimässä miten oikeasti voisi edistää asian (tasogeometria) oppimista Racketin avulla, koodaus tuo varmasti mukavaa vaihtelua matematiikan tunneille ja toivottavasti auttaa ja innostaa myös oppimaan
  • teki hyvää pohtia ja vetää kulunutta kuutta viikkoa yhteen, opin varmaan koodaamisesta tällä viikolla eniten, vaikka en koodannut ollenkaan
Mitä opin:
  • koodauksen opettaminen tulee vaatimaan paljon aikaa ja harjoittelua, minusta tuntuu helpommalta soveltaa koodausta geometrian opetukseen
  • lähdin tälle kurssille, että saisin ideoita ohjelmoinnin opettamiseen ja kyllähän niitä sainkin
  • suunnittelemaan harjoitustehtävän matematiikan aihealueesta
  • luotan siihen, että selviän ensimmäisistä koodaustunneistani, kunhan pidän opetettavan asian riittävän yksinkertaisena
  • opin, että koodaus on käyttökelpoinen ja oikeasti liitettävissä osaksi opetusta, mutta aika paljon työtä suunnittelu vaatii, kiitoksena toivonmukaan motivoituneempia ja osaavampia oppilaita
  • Racket vaikuttaisi hyvältä ympäristöltä alkaa harjoittelemaan ohjelmoinnin perusteita ja algoritmista ajattelua

Kehittämiskohteita

Selvästi vaikein viikko (ajan käyttö mittarina) oli viikko 2. Viikon teema funktiot, käytiin perusteellisesti ja se saattoi olla hieman liikaa aloittelevalle ohjelmoijalle. Lisäksi avoin viikkotehtävänanto teki tehtävästä vaikeamman kuin oli tarkoitus. Myös lasku- ja kuvafunktioiden käsitteleminen saman viikon aikana lisäsi kompleksisuutta turhaan. Tämän viikon sisällöt tullaan jatkossa jakamaan useampaan osaan.

Toinen ongelmallinen viikko oli viikot 3 ja 4, joissa oli myös liikaa sisältöjä. Logiikka on vaikea aihepiiri ja lisäksi mukana oli monenlaisia sovelluksia, jotka toimivat eri logiikoilla (eri kirjastot). Tämänkin paketin sisällöt tullaan jatkossa hajauttamaan useammalle viikolle.

Tästä ensimmäisestä toteutuksesta ajanpuutteen vuoksi pudotettu rekursion käsittely otetaan mukaan keväällä, samoin listojen parempi käsittely.

Kaiken kaikkiaan kurssi tullaan siis jakamaan viiden viikon sijaan seitsemään (tai kahdeksaan) jaksoon. Sisällöt jaetaan myös niin, että joka viikko otetaan hieman lisää funktioita, logiikkaa, silmukoita sekä hyviä ohjelmointikäytänteitä. Myös tehtäviä yritetään ohjeistaa paremmin ja palautettavaa viikkotehtävää rajata niin, ettei aloittelija yritä tietämättään haukata liian isoa palaa, kuten syksyn kurssitoteutuksessa usein kävi.

Tästä toteutuksesta säilytetään hyväksi kehuttu jakaminen (Padlet, WeScheme) sekä matematiikan soveltaminen harjoituksissa. Myös materiaalin rakenne (videot, PowerPoint, harjoitustehtävät + malliratkaisut, viikkotehtävä ja diplomitehtävä) säilytetään. Uutena lisänä kokeillaan vertaispalautteen antamista jollakin viikolla.  

Yhteenveto

Kurssin suoritti 141 opettajaa, jotka lopussa pystyivät jopa kehittelemään omia ohjelmointiharjoitustehtäviä sekä suunnittelemaan ohjelmointiopintokokonaisuuksia oman oppiaineen sisältöihin liittyen. Tämä kertoo siitä, että kurssi tarjosi riittävät tiedot ja taidot ohjelmoinnista. Tämä tukee kokemustani siitä, että muutaman tunnin tai yhden päivän kestävät ohjelmointikoulutukset eivät anna riittävän tukevaa pohjaa toimia ohjelmoinnin opettajana, ainakaan kun kyseessä on lausekielinen ohjelmointi.

Kurssin loppukyselyn mukaan (N=42), yli puolet aikoo ottaa kurssilla oppimaansa käyttöön vuoden sisällä. Kyselyn mukaan (asteikolla 0-5) kurssi tarjosi menetelmiä ohjelmoinnin opettamiseen (4,14), lisäsi ohjelmoinnin opettamisessa tarvittavia tietoja (4,52) ja antoi konkreettisia vinkkejä omaan opetystyöhön (3,93). Lisäksi kyselyyn vastanneiden mukaan kurssilla käytetyt opetusmetelmät edistivät oppimista (4,29), MOOC-muotoinen koulutus soveltuu hyvin asian oppimiseen (4,4) ja se soveltuu hyvin täydennyskoulutukseen (4,45). Kaiken kaikkiaan kurssi vastasi suurinpiirtein  odotuksia (3,69).

 
Loppukyselyyn vastanneiden mukaan ohjelmointi voi lisäksi edistää matemaattisen ajattelun kehittymistä (4,19). Koodausta kouluun materiaali arvioitiin soveltuvaksi yläkoulun matematiikan opetukseen keskiarvolla (3,69).    

Kaiken kaikkiaan kurssi oli siis melko onnistunut, toki parannettavaakin siitä löytyy. Kurssia kehitellään eteenpäin kevään toteutuksessa ja olisin erittäin iloinen, jos Koodiaapinen MOOC:in Racket-osion kehittäjä- ja kouluttajakunta laajenisi, koska tällaisen kurssin vetäminen tuntuu tärkeältä työltä, mutta se ei voi pidemmän päälle jatkua vain yhden ihmisen voimin oman päivätyön ohessa. Kurssia voisi jatkokehittää niin, että se soveltuisi myös osaksi matematiikan opettajien perusopintoja.

Ei kommentteja:

Lähetä kommentti