Skip to content

Instantly share code, notes, and snippets.

@juvuorin
Last active March 21, 2021 09:40
Show Gist options
  • Save juvuorin/5c76a6da5541cc7484143d58d279e128 to your computer and use it in GitHub Desktop.
Save juvuorin/5c76a6da5541cc7484143d58d279e128 to your computer and use it in GitHub Desktop.
koiramainenOhjelmointikisa2020
/*
Ohjelma on toteutettu ajettavaksi terminalissa. Sen voi ajaa node.js:llä komennolla 'node kisa.js'
Ohjelma on suunniteltu niin, että se lukee sisään kerrallaan vain yhden oppilaan nimen ja arvosanat ja tulostaa oppilaalle todistuksen.
Aineet on listattu oliotaulukkoon ja selkeyden vuoksi toteutin sen niin, että vaikka kategoriat on listattu omaan taulukkoonsa, niin ne
näkyvät myös selkokielisinä aineet-taulukon olioissa. Tämä myös mahdollistaa helpomman muokattavuuden ja lisäyksen tietoihin.
Juurikin tietojen helpon lukemisen vuoksi päädyin valitsemaan oliotaulukon sen sijaan, että olisin laittainut kaikki yksittäiset tiedot omiin taulukkoihinsa.
Pyrin välttämään tehtävässä välttämään for-looppeja ja käyttämään sen sijaan mm. filter, map ja forEach -funktioita, jotta koodi pysyy selkeämpänä ja
koodin määrä vähenee. Tämä myös helpottaa debuggausta, jos sovellusta vielä tästä laajentaisi.
Tietojen sisäänlukemisessa käytetään Node.js:n readline-kirjastoa ja sain sen parhaiten toimimaan arvosanojen kanssa switch - case -rakenteen kanssa,
joten tämän vuoksi sitä on käytetty.
*/
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
let x = 0;
let oppilaanNimi = ""
let kategoriat = ["Metsästys","Pihatyöt","Muut"]
let aineet = [
{
nimi: "Pupun jäljestys",
kategoria: "Metsästys"
},
{
nimi: "Hirven jäljestys",
kategoria: "Metsästys"
},
{
nimi: "Linnun noutaminen",
kategoria: "Metsästys"
},
{
nimi: "Lumen pöllyytys",
kategoria: "Pihatyöt"
},
{
nimi: "Kukkapenkkien kaivaminen",
kategoria: "Pihatyöt"
},
{
nimi: "Parvekkeen vahtiminen",
kategoria: "Muut"
},
{
nimi: "Piilotetun luun löytäminen",
kategoria: "Muut"
},
{
nimi: "Oman hännän jahtaaminen",
kategoria: "Muut"
},
{
nimi: "Kuun ulvonta",
kategoria: "Muut"
}
]
const summa = (kategoria) => {
// Huom! Pitäisikö "kat, summa" olla järjestyksessä "summa, kat", kts. JavaScript reduce määritelmä!
// Lopputulos on sama, sillä + funktio on kommutatiivinen eli a+b on b+a. Eli summa ensin ja käsiteltävä arvo kakkoseksi.
return (((aineet.filter(k => k.kategoria===kategoria)).map(a => a.arvosana)).reduce((kat,summa) => {return (kat+summa)},0))
/* Menisikö pelkällä reducella helpommin näin?
----------------------------------------------
return aineet.reduce((summa,aine) => {
if (aine.kategoria===kategoria)
return (aine.arvosana+summa)
else
return summa
},0)
*/
}
const tulostaTodistus = (oppilas) => {
const kategoriaSummat = kategoriat.map(kNimi => ({kategoria: kNimi,summa: summa(kNimi)}))
let lisäTeksti = (oppilaanNimi === "Selma" || oppilaanNimi === "Lady") ? "(arvosanoissa vain VÄHÄN huijattu)" : ""
console.log(`\n- - - - - - - - - - - - - -\n${oppilaanNimi}-koiran todistus`+lisäTeksti+`:\n- - - - - - - - - - - - - -\n`)
kategoriaSummat.forEach(x => console.log(x.kategoria, x.summa))
}
const kysyNimi = () => {
rl.question(`Anna arvosteltavan koiran nimi: `, (vastaus) => {
oppilaanNimi=vastaus
switch (oppilaanNimi){
//Nää oli tosi hauskat!!!!!!!!!!!!!!!
case "Selma":
console.log(`\nTurha koittaa, Selma voittaa! Täydellisyyttä hipoen hän linnun noutaa, myös omaa häntää täysillä hän jahtaa!\n`)
break;
case "Lady":
console.log(`\nTurha haastaa, Lady valloittaa! Urheilullisesti hän luun löytää, karvameren peräänsä hän imurille jättää!\n`)
break;
default:
console.log(`\n${oppilaanNimi} on ihan kiva nimi koiralle\n`)
break;
}
kysyArvosanat()
})
}
const kysyArvosanat = () => {
rl.question(`Syötä ${oppilaanNimi}-koiran arvosana (4-10) aineelle "${aineet[x].nimi}": `
, (vastaus) => {
// Voisiko tässä määritellä arvovälin, switch - case -rakenteen sijaan? Hyvin toimii näinkin! :)
// Ehkä pitää varmistua, että tieto on "lukutyyppistä", jotta lukujen suuruuksia voi vertailla.
// Hyvä ratkaisu tämäkin, kun lukuja oli näin vähän!
switch (vastaus){
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
//Tämä oli hauska!!!!!
case "10":
aineet[x].oppilas = oppilaanNimi
aineet[x].arvosana = (oppilaanNimi === "Selma" || oppilaanNimi === "Lady") ? 10 : parseInt(vastaus) //jos koiran nimi on Selma tai Lady, niin automaattisesti annetaan arvosanaksi aina 10 riippumatta syötteestä.
x++
break;
default:
console.log("Syötä arvosana numeroina väliltä 4 - 10")
}
if (x === aineet.length) {
tulostaTodistus()
return rl.close()
}
kysyArvosanat(); //Kutsutaan funktiota uudestaan ja kysytään seuraava arvosana
})
}
kysyNimi()
@juvuorin
Copy link
Author

juvuorin commented Apr 24, 2020

Tässä on käytetty näpprästi JavaScriptin oliomallia, jossa olioon voidaan lisätä "lennossa" eli ohjelman suorituksen aikana uusia kenttiä.

Huumorintajuisesta ratkaisusta, jossa Selma ja Lady saavat täydet kympit annetaan ilman muuta tekijälle lisäpisteitä :)

Kehitysajatuksia

Laitoin summa-funktioon ja kysyArvosanat funktioon pari kommenttia. Niitä voisi pohtia.

Se, että alussa tietorakenteeseen määritellään vai kategoria ja oppiaine, voi aiheuttaa pienen luettavuusongelman, sillä ei nähdä, että samaan rakenteeseen lisätään myöhemmin tietyn aineen arvosana. Tämä on tosin JavaScriptin yleinen ongelma, sillä kieli ohjaa helposti ko. valintoihin, joissa kenttiä lisätään objekteihin "matkan varrella".

Joissain ratkaisuissa oli annettu myös "arvosana" kenttä samaan tietorakenteeseen, joten se oli koodin lukijan nähtävissä jo tietorakenteen määrittelyhetkellä. Kenttä oli tyypillisesti alustettu arvoon 0.

"Aineet on listattu oliotaulukkoon ja selkeyden vuoksi toteutin sen niin, että vaikka kategoriat on listattu omaan taulukkoonsa, niin ne
näkyvät myös selkokielisinä aineet-taulukon olioissa." Tämä on erinomainen kommentti, koska siinä on ajatellut koodin lukijaa.

Kategorioiden listaus lisää luettavuutta, vaikka tieto onkin olemassa myös aineet-taulukossa. Tässä voi pohtia haluaako "luoda" kategoriat etsimällä aineet-taulukosta erilaiset kategorian arvot ja luoda niistä erillisen listan/taulukon. Dokumentoituvuuden kannalta lienee parempi, että kategoriat ovat omassa taulukossaan.

Kuitenkin, kategoriat olisi ehkä hyvä määritellä vain yhdessä paikassa ja varmistaa, että aineet-listan kategoriatieto löytyy aina kategorioiden määrittelystä, miten se ikinä onkaan toteutettu.

Tsemppiä ohjelmointihommiin!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment