---
# System prepended metadata

title: 'Web-ohjelmointi, syksy 2023'

---

# Web-ohjelmointi, syksy 2023
## **KEHITYSBLOGI**
---
### Tekijä: Paula-Riitta Huttunen
---

[ToC]

## Viikko 1
### Mitä opin tällä viikolla?
Aloitusviikolla sain palauteltua mieleen, kuinka Visual Studio Code toimii ja liityin kurssin Slack-ryhmään. Päivittelin ohjelmistoja koneeseeni ja latasin Node.js:n uusiksi. En oikeastaan oppinut vielä mitään uutta, lähinnä tuli vanhan kertausta, mikä oli toki ihan tarpeellista.

### Mitä harjoituksia tein?
En vielä mitään (eipä tainnut edes olla mitään harjoituksia, vain sinne Slackiin rekisteröityminen), aika meni ihan puhtaasti luentojen kuunteluun ja perehtyen kurssimateriaaleihin sekä palauttaen mieleen kuinka VS Code ynnä sen yhteydessä tarvittavat lisäosat toimivat. Koitin myös hiukan palautella mieleen HMTL:n perusteita.


---


## Viikko 2
### Mitä opin tällä viikolla?
Tällä viikolla latasin ja konfiguroin Git:in ja perehdyin GitHubiin. Lisäksi palauttelin mieleen HTML:n perusteita. Git:iin uudelleen perehtymiseen ja gitin käyttövalmiiksi saattamiseen meni jonkun verran aikaa. Vaikka olin edellisessä työpaikassani käyttänyt gittiä, en kuitenkaan koskaan ollut aivan ymmärtänyt sen toimintaperiaatetta. Töissä ollessani oli Git käytännössä asennettu koneelleni puolestani ja minun tarvitsi vain osata käyttää graafistakäyttöliittymää (Git Extensions), jonka avulla tiedostoja "pullattiin", "pushattiin" ja "commitettiin", eikä minun tarvinnut ymmärtää mitä taustalla tapahtui. Nyt kun parin vuoden tauon jälkeen piti yrittää muistaa, mikä oli Git:in toimintalogiikka ja kuinka sillä operoitiin niin meni kyllä sormi suuhun. 

Git:iä asentaessa en meinannut ymmärtää kuinka luon SSH-avaimen ja yhdistän sen GitLabiin niin uppouduin sitten lukemaan Git:in opaskirjaa ja GitLabin ohjeita. -Osaan nyt luoda yksityisen ja julkisen SSH-avaimen (sekä komentokehotteen kautta OpenSSH:ta käyttäen että PuttyGen-ohjelman avulla) ja tiedän, että RSA:n sijaan kannattaa käyttää ed25519-salausta, ja että jos OpenSSH:sta on vanha versio niin tulee avainta luodessa käyttää "-o" -komentoa (selvisi, että minulla sittenkin oli OpenSSH, jota Windowseissa ei kuulema ole automaattisesti ja versioni oli riittävän tuore jottei tarvinnutkaan kikkailla). Opettajan ohjeisiin laittama linkki GitHubin sivuille ei toiminut niin en vielä saanut laitettua luomaani avainta sinne, mutta toivon osaavani laittaa sen sinne kunhan linkki päivitetään.

Tällä viikolla opin myös paljon erilaisia käskyjä, joilla voi operoida Git Bash:issa ja luulen nyt ymmärtäväni aiempaa perusteellisemmin gitin toimintaperiaatetta. En usko enää palaavani käyttämään sitä graafistakäyttöliittymää, jota käytin töissä, koska sain nyt tietää sen olevan vajavaisempi toimintaominaisuuksiltansa verrattuna siihen, että syöttää käskyt suoraan komentokehotteeseen.


### Mitä harjoituksia tein?
Tällä viikolla leijonan osan ajasta vei TRA1-kurssin tehtävät ja Git:in kanssa säätäminen, että olin siksi jäljessä luentojen kuuntelusta ja jälkijunassa tullessani missasin ensimmäisen harjoituksen palautuksen :( Haluan kuitenkin vielä tehdä sen, koska tarvitsen kertausta HTML:ään liittyvissä asioissa. Toivottavasti tehtävän saa vielä palauttaa myöhässäkin, vaikka en oleta saavani siitä enää mitään pisteitä.

#### Harjoitus 1

Tämä oli HTML:ään liittyvä tehtävä, kopion opettajan pohjan ja tein siihen päälle omat muokkaukseni. Lopuksi ajoin HTML ja CSS-koodit validaattorissa. En löytänyt kuin yhden virheen, joka oli helppo korjata. Tehtävä näytti aluksi vaikeammalta kuin mitä se loppupelissä oli.

---

## Viikko 3
### Mitä opin tällä viikolla?

Ensimmäisenä opiskeluvuotenani aloitimme ohjelmoinnin perusteet TypeScriptillä, joten JavaScript oli toimintaperiaatteeltansa tuttu kieli, joskin pitkän tauon jälkeen tuntuu, että pitää jälleen aloittaa melkeinpä ihan perusteista. Viimeaikainen Javan kanssa operoiminen on onneksi helpottanut tiedon nopeaa omaksumista ja nyt hahmotan olioiden mekaniikkaa paremmin kuin aiemmin.

### Mitä harjoituksia tein?
Tällä viikolla perehdyin vielä lisää JavaScriptiin ja tein kummatkin JS-aiheiset ohjelmointitehtävät; "*Javascript -perusteet, teht 1*" & "*Javascript -perusteet, teht 2*". Ne sujuivat odotettua mukavammin, mutta kyllä niissä silti riitti haasteita. Olin tyytyväinen, että sain kummatkin algoritmit lopulta toimimaan :)

#### Harjoitus 2 
##### Javascript -perusteet, teht 1
Aloitin palindromifunktio-tehtävästä, joka sujuikin yllättävän hyvin, kun lopulta keksin miten vertaan taulukoiden alkioita keskenään. Jonkun verran meni aikaa palautellessa mieleen ihan ohjelmoinnin perustaitoja, kuten ehtolauseita sekä luuppien toimintaa. Onneksi meneillään olevan TRA1-kurssin Java-taitojen opettelun ohella on tullut kerrattua ihan ohjelmoinnin perusteitakin niin ei aivan nollasta ole tarvinnut aloittaa JS:n kanssa, ja asioiden omaksuminen on nopeampaa, kun on joku vertailukohta.

Tässä tehtävässä palautui hyvin mieleen, kuinka sijoitetaan dataa listoihin ja verrataan keskenään listojen alkioita toisiinsa.

```javascript=16
function palindromi() {
  // kysytään syöte
  var input = require("readline-sync");
  var nimi = input.question("Anna sana: ");
  

  // taulukoiden luonti
  const talsi = [];
  const kaannos = [];
  // muuttujien alustus
  let i = 0;
  let vastaus;

  // merkit syötetystä sanasta talteen
  for (i = 0; i < nimi.length; i++) {
    talsi.push(nimi[i]);
    // testitulostus
    //console.log("talsin testitulostus: " + talsi);
  }
  // sijoitetaan talsi-taulukon merkit lopusta alkuun kaannos-taulukkoon
  for (i = 0; i < talsi.length; i++) {
    kaannos[i] = talsi[talsi.length - 1 - i];
    // testitulostus
    //console.log("käännoksen testitulostus: " + kaannos);
  }
  // taulukoiden vertaus loopin avulla
  for (i = 0; i < talsi.length; i++) {
    if (kaannos[i] == talsi[i]) {
      vastaus = true;
    }
    if (kaannos[i] != talsi[i]) {
      vastaus = false;
    }
  }
  return vastaus;
}

console.log("Annettu sana on palindromi: " + palindromi());

```
---


#### Harjoitus 3
##### Javascript -perusteet, teht 2
Harjoitus 3:ssa opettelin luomaan oliota sekä sijoittamaan luodut oliot taulukkoon. Aluksi oli hieman vaikeuksia saada luotua uusia olioita, mutta lopulta muistin miten JavaScriptissä käytetään luokkaa ja sen konstruktoria. 


Toisessa osassa tehtävää oli luotava funktio, joka etsii käyttäjän aiemmassa vaiheessa luotujen henkilöiden syötettyjä puhelinnumeroita aiemmin luodusta puhelinluettelosta. Toteutin tämän niin, että käyttäjältä jatkuvasti kysytään minkä toiminnon tämä haluaa suorittaa ja sitten toimintavaihtoehdot on listattu switch-rakenteeseen, jossa kutsutaan funktiota, joka joko suorittaa lisäyksen tai hakemisen tai sitten lopettaa ohjelman suorittamisen.

```javascript=16
/* Tee puhelinluettelo. 
Puhelinluetteloon lisäät taulukkoon objekteja (eli henkilöitä joilla nimi 
ja puhelinnumero). 
Käyttäjältä kysytään henkilön nimi ja puhelinnumero. 
Henkilön poisto -toimintoa ei tarvitse tässä versiossa olla. 
Tee hakutoiminto jossa haet nimen perusteella puhelinnumeron. 
Tee puhelinnumeron haku funktioksi. Funktion parametrina on taulukko josta 
haetaan henkilön nimi. Funktio palauttaa puhelinnumeron. 
Kutsu funktiota.

Käyttöliittymän voit tehdä millaiseksi haluat 
(komentokehoite -pohjainen kuitenkin) */

// lukijan määrittäminen
const lukija = require("readline-sync");

// muuttujan alustus
var jatka = true;

// luodaan puhelinluettelo-taulukko
let puhelinluettelo = [];

// Henkilo-luokan kontruktori
class Henkilo {
  constructor(nimi, numero) {
    this.nimi = nimi; // uudelle oliolle olion parametrina nimi
    this.numero = numero;
  }
}

// funktio, joka kysyy käyttäjän tiedot ja luo niiden pohjalta henkilön, joka lisätään puhelinluetteloon
function lisaaHenkilo() {
  let nimi = lukija.question("Anna nimi: ");
  let numero = lukija.question("Anna puhelinnumero: ");
  let henkilo = new Henkilo(nimi, numero); // luodaan uusi Henkilo-olio
  puhelinluettelo.push(henkilo); // lisätään luotu olio puhelinluetteloon
}

// funktio, jolla etsitään numero nimen perusteella
function haeNumero() {
  let haettavaNimi = lukija.question("Anna haettavan nimi: ");
  for (let i = 0; i < puhelinluettelo.length; i++) {
    // käydään läpi puhelinluettelon oliot
    let henkilo = puhelinluettelo[i];
    // jos arvot ja tyypit ovat samoja
    if (henkilo.nimi === haettavaNimi) {
      return henkilo.numero; // mikäli vastaavuus löytyi, palautetaan haettavan numero
    }
  }
  // muussa tapauksessa
  return "Etsittyä henkilöä ei löytynyt";
}

// kysytään jatkuvasti mitä käyttäjä haluaa tehdä
while (jatka) {
  let toiminto = lukija.question("Valitse toiminto (lisaa/hae/lopeta): ");

  // switch-rakenteella jatkotoimien selvittäminen
  switch (toiminto) {
    case "lisaa":
      lisaaHenkilo(); // lisätään Henkilo-olio puhelinluettelo-taulukkoon
      break;
    case "hae":
      console.log(haeNumero()); // haetaan numeroa nimen perusteella
      break;
    case "lopeta":
      jatka = false; // lopettaa ohjelman suorituksen
      break;
    default:
      console.log("Tuntematon toiminto.");
  }
}

```
---
## Viikko 4
### Mitä opin tällä viikolla?

Luokkien kanssa operointia; olioiden luomista luokasta ja luokan periytymistä. Luokat ja periytyminen on jo Java:sta tuttua, mutta se vaati vähän mieleen palauttelua. Luulin jo, että gitin kanssa operoiminen sujuisi kun olen sitä aiemminkin käyttänyt, mutta edellisestä kerrasta olikin sen verran aikaa, että sen kanssa vänkäämiseen kuluikin aika paljon aikaa. Toivon, että palautukseni onnistui ja palauttamani osoite päästää opettajan katsomaan ohjelmakoodiani. 

### Mitä harjoituksia tein?
#### Harjoitus 3

Suurimmat vaikeudet ovat tosiaan olleet git:in kanssa, en jostain syystä millään meinannut keksiä syytä siihen, miksi en saanut pushattua tiedostoa GitHubin repositoryyn. Terminaaliin tuli jatkuvasti jonkinlainen virheilmoitus, ilmeisesti liittyen johonkin merge-ongelmaan. En kyllä ymmärrä miten se oli mahdollista, kun repositorio oli olevinaan tyhjä, kun sinne yritin lisätä. No, oli siellä se README-tiedosto sekä lisenssi, olisivatko ne jotenkin voineet sekoittaa hommia...? Lopulta kuitenkin sain ongelman ratkaistuksi, en oikeastaan ole edes varma miksi onnistuin loppujen lopuksi. Pääasia on, että Henkilo.js -tiedoto on nyt Githubissa kansiossa Teht3. Toivon, että jatkossa gitin käyttö ei ole yhtä sekavaa ja hommat luistaa huomattavasti paremmin. 

Itse ohjelman kanssa ei ollut juuri ongelmia. Hieman päänvaivaa aiheutti Date()-metodin ymmärtäminen, jouduin siitä lukemaan jonkun verran ennen kuin ymmärsin sen toimintalogiikan.

Huom! Harjoitus oli alunperin palautettu GitHubiin erilliseen repositoryyn (Henkilo.js, jossa oli kansio nimeltä Teht3, jossa oli tiedosto Henkilo.js), mutta kopioin kansion ja nimesin sen uudestaan tehtävänannon mukaisesti "Urheilija1" ja siirsin sen REST1-repostoryyn, jonne olen jakanut muutkin harjoitukset, jotka piti jakaa GitHubissa.

```javascript=16

/* Kehitystehtävänä on määritellä olio-ohjelmointikielille ominainen luokkamäärittely 
ja periytyminen JavaScript-kielellä.

Määrittele yliluokka Henkilo, joka sisältää ihmisen henkilötietoja: etunimet, sukunimi, 
kutsumanimi, syntymävuosi. 

Määrittele luokka Urheilija, joka perii Henkilo-luokan ja toteuttaa lisäksi 
saantifunktiot (get- ja set-) Urheilija-luokalle merkityksellisiin attribuutteihin. 
Lisää Urheilija luokkaan seuraavat ominaisuudet: linkki kuvaan, omapaino, laji, 
saavutukset. Kirjoita nämä vaatimukset toteuttava koodi joka toimii node.js-tulkissa.

Toteuta koodi. Lisää koodiin esimerkkejä Urheilija –olioista.
Talleta toteutuksesi gitlab (tai github) -ympäristöön omaan projektiisi hakemistoon: 
Urheilu1

Kirjoita tehtävästä kommentointi ja huomioita kehittäjän blogiin (hackmd.io). */

class Henkilo {
  // alustetaan Henkilo-luokan omat yksityiset muuttujat
  #etunimi;
  #sukunimi;
  #kutsumanimi;
  #syntymaVuosi;

  // konstruktori Henkilo-luokalle
  constructor(etunimi, sukunimi, kutsumanimi, syntymaVuosi) {
    this.#etunimi = etunimi;
    this.#sukunimi = sukunimi;
    this.#kutsumanimi = kutsumanimi;
    this.#syntymaVuosi = new Date(syntymaVuosi, 0, 1); // asettaa päivämääräksi 1. tammikuuta parametrsissa saatuna vuonna
  }

  // **** getterit ****

  // getteri joka palauttaa syntymävuoden Date-objektin getFullYear()-metodilla
  get syntymaVuosi() {
    return this.#syntymaVuosi.getFullYear();
  }

  get etunimi() {
    return this.#etunimi;
  }

  get sukunimi() {
    return this.#sukunimi;
  }

  get kutsumanimi() {
    return this.#kutsumanimi;
  }

  get syntymaVuosi() {
    return this.#syntymaVuosi.getFullYear();
  }

  // *** setterit ***

  set etunimi(etunimi) {
    this.#etunimi = etunimi;
  }

  set sukunimi(sukunimi) {
    this.#sukunimi = sukunimi;
  }

  set kutsumanimi(kutsumanimi) {
    this.#kutsumanimi = kutsumanimi;
  }

  set syntymaVuosi(syntymaVuosi) {
    this.#syntymaVuosi = new Date(syntymaVuosi, 0, 1);
  }
}

// Urheilija-luokka laajentaa Henkilo-luokkaa (eli perii Henkilon ominaisuudet)
class Urheilija extends Henkilo {
  // alustetaan Urheilija-olion omat yksityiset muuttujat
  #linkki_kuvaan;
  #omapaino;
  #laji;
  #saavutukset;

  // Urheilija-luokan konstruktori olion luomiseksi
  constructor(
    etunimi,
    sukunimi,
    kutsumanimi,
    syntymaVuosi,
    linkki_kuvaan,
    omapaino,
    laji,
    saavutukset
  ) {
    super(etunimi, sukunimi, kutsumanimi, syntymaVuosi);
    this.#linkki_kuvaan = linkki_kuvaan;
    this.#omapaino = omapaino;
    this.#laji = laji;
    this.#saavutukset = saavutukset;
  }

  // **** getterit ****

  get linkki_kuvaan() {
    return this.#linkki_kuvaan;
  }

  get omapaino() {
    return this.#omapaino;
  }

  get laji() {
    return this.#laji;
  }

  get saavutukset() {
    return this.#saavutukset;
  }

  // **** setterit ****

  set linkki_kuvaan(linkki_kuvaan) {
    this.#linkki_kuvaan = linkki_kuvaan;
  }

  set omapaino(omapaino) {
    this.#omapaino = omapaino;
  }

  set laji(laji) {
    this.#laji = laji;
  }

  set saavutukset(saavutukset) {
    this.#saavutukset = saavutukset;
  }
}

// Luodaan uusia Urheilija-olioita
const Maija = new Urheilija(
  "Maija",
  "Meikäläinen",
  "Maija",
  1990,
  "link_to_image",
  60,
  "Jalkapallo",
  "SM-mitali 2019"
);
const Matti = new Urheilija(
  "Matti",
  "Meikäläinen",
  "Matti",
  1992,
  "link_to_image",
  80,
  "Jääkiekko",
  "SM-mitali 2020"
);
const Megan = new Urheilija(
  "Megan",
  "Rapinoe",
  "Megan",
  1985,
  "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Megancoupe2019.jpg/640px-Megancoupe2019.jpg",
  60,
  "Jalkapallo",
  "Voittava maali vuonna 2008 sekä vuonna 2012 olympialaisten kultamitaliotteluissa"
);

const Alexia = new Urheilija(
  "Alexia",
  "Putellas",
  "Alexia",
  1994,
  "https://en.wikipedia.org/wiki/Alexia_Putellas#/media/File:Barcelona_femen%C3%AD_Medalla_d'Honor_del_Parlament_de_Catalunya_02_(Putellas_1).jpg",
  56,
  "Jalkapallo",
  "FIFA Best Women’s Player -palkinnon voittaja vuonna 2022"
);

const Mia = new Urheilija(
  "Mia",
  "Hamm",
  "Mia",
  1972,
  "https://upload.wikimedia.org/wikipedia/commons/3/3e/Mia_Hamm_corner_%28cropped%29.jpg",
  58,
  "Jalkapallo",
  "Kaksinkertainen olympiakultamitalisti, kaksinkertainen FIFA Naisten maailmancupin mestari"
);

// Tulostetaan olioiden tiedot
console.log(
  "Henkilön tiedot: " +
    Megan.etunimi +
    " " +
    Megan.sukunimi +
    " " +
    Megan.omapaino +
    " , " +
    "Saavutukset: " +
    Megan.saavutukset +
    " " +
    "Linkki kuvaan: " +
    " " +
    Megan.linkki_kuvaan
);

console.log(" ");
console.log("***********************");

console.log(
  "Henkilön tiedot: " +
    Alexia.etunimi +
    " " +
    Alexia.sukunimi +
    " " +
    Alexia.omapaino +
    " , " +
    "Saavutukset: " +
    Alexia.saavutukset +
    " " +
    "Linkki kuvaan: " +
    " " +
    Alexia.linkki_kuvaan
);

console.log(" ");
console.log("***********************");

console.log(
  "Henkilön tiedot: " +
    Mia.etunimi +
    " " +
    Mia.sukunimi +
    " " +
    Mia.omapaino +
    " , " +
    "Saavutukset: " +
    Mia.saavutukset +
    " " +
    "Linkki kuvaan: " +
    " " +
    Mia.linkki_kuvaan
);

console.log(" ");
console.log("***********************");
console.log("");

```
---
## Viikko 5 ja 6
### Mitä opin näillä viikoilla?

Viikkojen 5 ja 6 aikana perehdyttiin REST:iin ja RESTful API:ien luomiseen. Opettelimme myös AJAX:in, JQueryn ja Expressin käyttöä ja asensimme CORS-selainlaajennuksen sekä Postman-ohjelman, jonka avulla testasimme API-pyyntöjä. Käytin aika paljon aikaa näinä kahtena viikkona ymmärtääkseni mikä oikeastaan on API ja REST. Kävin lukuisia keskusteluja ChatGPT:n kanssa näiden kahden viikkojen aiheista, koska tunneilla tuli niin paljon asiaa niin lyhyen ajan sisällä, ettei sitä informaatiomäärää oikein pystynyt mitenkään käsittelemään ja tuntui, että kaikki käsitteet menivät sekaisin. Nyt koen, että ymmärrän paremmin, mutta luulen, että pitää vieläkin selkeyttää AJAX:in ja JQueryn toimintaperiaatteita, vaikka harjoituksissa 4a ja 4b harjoittelinkin niiden käyttöä.

### Mitä harjoituksia tein?
Tein kummatkin harjoitustehtävät, jotka oli ajoitettu näille kahdelle viikolle. Harjoituksessa 4a oli tarkoitus luoda REST API sanakirjaa varten ja harjoituksessa 4b oli tarkoitus luoda tuohon luotuun sanakirja REST API:in käyttöliittymä. Eniten aikaa kului jälkimmäiseen tehtävään, yritin pitkään saada haluamani toiminnalisuudet toimimaan yhden index.html-dokumentin avulla, mutta lopulta päädyin jakamaan eri toiminnallisuudet omiksi .html-dokumenteiksi.

#### Harjoitus 4a 
##### REST API sanakirjaa varten

Tässä harjoituksessa ei ollut juuri vaikeuksia, kun lopulta ymmärsin miten se REST-puoli tähän sanakirja API:iin toteutetaan. Toteutukseni on synkroninen, koska koin sen olevan helpompi toteuttaa (en tiedä olisiko se asynkroninen toteutus ollut juuri vaikeampi, mutta koin tämän tavan suoraviivaisemmaksi). Päätin tehdä sanankirjan luomiselle oman funktion, jota kutsutaan suorituksen alussa ja sitten siihen vain viitataan API-pyynnöissä. 

```javascript=16
/* 
=> Luo REST API sanakirjaa varten.
Sanakirjassa (tieto tiedostossa - esim. sanakirja.txt) on taulukossa eri riveillä sana suomeksi 
ja englanniksi; esim. auto car talo house. Tarvitset API:a varten luoda hakua varten metodin 
(toteuta GET metodi) sekä sanojen lisäystä varten metodin (toteuta POST metodi). Tiedonhaussa 
parametrina on suomenkielinen sana. Haku palauttaa englannin kielisen sanan vastineen.
Tiedonlisäyksessä tallennetaan suomenkielinen sana ja vastaava englanninkielinen sana uudelle 
riville (tekstitiedostoa kasvatetaan uudella rivillä). Tiedoston käsittelyä varten tarvitset 
fs moduulin ( require("fs")). Em. moduulista löytyy esim. metodi writeFileSync kirjoitusta 
varten ja readFileSync lukemista varten. (Tiedoston käsittely voi olla synkroninen tai 
asynkroninen  - saa valita). 
=> Talleta toteutuksesi gitlab (tai github) -ympäristöön omaan projektiisi hakemistoon: "REST1" 
=> Kirjoita tehtävästä kommentointi ja huomioita kehittäjän blogiin (hackmd.io). 
*/

const fs = require("fs");
const express = require("express");

var app = express(); // tehdään sovellus-olio express-kirjaston kautta

app.use(express.json()); // käytetään json-muotoista dataa
app.use(express.urlencoded({ extended: true })); // käytetään tiedonsiirrossa laajennettua muotoa, UTF8-merkistö

// ***** (MITÄ SALLITAAN RESTapissa käytettävän) ******

// esiasetusten määrittely, CORS-määrittely

// Add headers
app.use(function (req, res, next) {
  // Website you wish to allow to connect
  res.setHeader("Access-Control-Allow-Origin", "*");

  // Request methods you wish to allow
  res.setHeader(
    "Access-Control-Allow-Methods",
    "GET, POST, OPTIONS, PUT, PATCH, DELETE"
  );

  // Request headers you wish to allow
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token"
  );

  // Set to true if you need the website to include cookies in the requests sent
  // to the API (e.g. in case you use sessions)
  res.setHeader("Access-Control-Allow-Credentials", true);
  res.setHeader("Content-type", "application/json");

  // Pass to next layer of middleware
  next();
});

// *****************************************

/* luodaan funktio sanakirjan luomiseksi, jolla sanakirja 
voidaan ladata ilman, että täytyy jokaisessa vaiheessa 
luoda sanakirja uudestaan */

function lataaSanakirja() {
  const data = fs.readFileSync("./sanakirja.txt", {
    // luetaan data tekstitiedostosta
    encoding: "utf8",
    flag: "r", // määritellään, että tiedosto avataan lukemista varten
  });
  const splitLines = data.split(/\r?\n/); // pilkkoo datan rivinvaihtomerkkien perusteella eri riveihin
  const sanakirja = []; // luodaan sanakirja-taulukko
  splitLines.forEach((line) => {
    // jokaisella rivillä...
    const sanat = line.split(" "); // split-metodin avulla annetaan sanat-muuttujalle arvoksi taulukko, jonka alkioiksi laitetaan jaettu rivi
    const sanapari = { fin: sanat[0], eng: sanat[1] }; // luodaan sanapari-objekti, jonka avain-arvo pareina on suomenkielinen sana (avain) ja englanninkielinen sana (arvo)
    sanakirja.push(sanapari); // sijoitetaan sanapari-objekti sanakirja-taulukkoon
  });
  return sanakirja;
}

// ladataan sanakirja muistiin sovelluksen käynnistyessä
let sanakirja = lataaSanakirja();

// *********************************************************************

// GET
// näyttää sanakirjan
app.get("/sanakirja", (req, res) => {
  res.json(sanakirja); // sanakirjan palautus
});

// *********************************************************

// GET
// sanojen etsiminen
app.get("/searchword/:fin", (req, res) => {
  const fin = req.params.fin; // haetaan 'fin' parametrin arvo URL-osoitteesta
  const eng = sanakirja.find((sanapari) => sanapari.fin === fin); // etsii sanakirjasta syötettyä sanaa ja palauttaa englanninkielisen version
  res.json(eng ? { eng: eng.eng } : { message: "ei löydy!" }); // tämä on ehtolause ("ternary operator") lähettämään JSON-muotoinen vastaus HTTP-pyyntöön, mikäli englannin kielistä sanaa ei löydy
});

// *************************************************

// POST
// sanaparin lisääminen sanakirjaan
app.post("/addword", (req, res) => {
  if (!req.body.fin || !req.body.eng) {
    // tarkistetaan, etteivät kentät ole tyhjiä ja että ne ovat ylippätänsä mukana
    res.status(400).json({ message: "Virheellinen pyyntö" }); // jos kentät ovat tyhjiä, nulleja tai määrittelemättömiä lähetetään virheilmoitus
    return;
  }
  const sanapari = req.body; // otetaan rungosta fin- ja eng-kentät ja sijoitetaan ne sanapari-objektiin
  sanakirja.push(sanapari); // lisätään sanapari sanakirja-taulukkoon
  fs.writeFileSync(
    "./sanakirja.txt",
    sanakirja.map((sanapari) => `${sanapari.fin} ${sanapari.eng}`).join("\n"), // lisätään sanapari halutussa muodossa tekstitiedostoon
    { encoding: "utf8", flag: "w" } // tiedostoon kirjoittamisen asetusten määrittäminen, w = write
  );
  res.json(sanakirja); // vastauksena sanakirja JSON-muodossa HTTP-pyyntöön
});

// ***************************************************

// käynnistetään express-palvelin ja kuunnellaan porttia 3000
app.listen(3000, () => {
  console.log(`Serveri kuuntelee portissa 3000`);
});
```

### Harjoitus 4b 
##### REST APIiin käyttöliittymä, jonka avulla voi lisätä ja hakea sanoja

Tässä harjoituksessa toteutin käyttöliittymän sanakirjalle. Tein html-pohjaisen käyttöliittymän, jossa jokainen toiminnallisuus (sanakirjan katsominen, sanaparin lisääminen ja sanan hakeminen) on toteutettu omana sivuna (omissa .html-tiedostoissa). Gittiin palautin myös alkuperäisen suunnitelmani käyttöliittymästä (sanakirjaUI.html), jota en kuitenkaan saanut toimimaan, ja tästä syystä päädyin tekemään omat sivut jokaiselle eri toiminnolle.

Varsinaiseen ratkaisuuni kuuluvat siis seuraavat tiedostot:

1) index.html
2) view.html
3) add.html
4) search.html
5) sanakirja.txt

Laitan tähän esimerkiksi vain index.html-tiedoston:

```javascript=16
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Sanakirjan pääsivu</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
      $(document).ready(function () {
        // Siirry "Näytä sanakirja" -sivulle
        $("#viewButton").click(function () {
          window.location.href = "view.html";
        });

        // Siirry "Lisää sana" -sivulle
        $("#addButton").click(function () {
          window.location.href = "add.html";
        });

        // Siirry "Hae sanaa" -sivulle
        $("#searchButton").click(function () {
          window.location.href = "search.html";
        });
      });
    </script>
    <style>
      body {
        font-family: Arial, sans-serif;
        text-align: center;
        margin-top: 50px;
        background-color: #daa982;
      }

      button {
        padding: 10px 20px;
        margin: 10px;
        font-size: 16px;
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    <h1>Sanakirja</h1>
    <button id="viewButton">Näytä sanakirja</button>
    <button id="addButton">Lisää sana</button>
    <button id="searchButton">Hae sanaa</button>
  </body>
</html>
```
Tässä linkki GitHubiin, jonne tehtävä on palautettu: https://github.com/PaulaRii/REST1.git 

---
## Viikko 7
### Mitä opin tällä viikoilla?

Viikon 7 aikana mm. perehdyimme tietokantojen toimintaan, Javascriptiin ja sen synkroniseen ja asynkroniseen suoritukseen, AJAX:iin sekä MVC:hen. Rinnakkaisuus sekä lupaukset käsitteenä olivat jo tuttuja Hajautetut järjestelmät -kurssilta, joskin niiden käyttäminen ei ollut itselle kovin selkeää, joten oli hyvä että niitä opeteltiin vielä tälläkin kurssilla. Generators, jolla kutsutaan useita alkioita kerralla ei sen sijaan ollut tuttu käsite. AJAX:iin perehtyminen vaati vielä omaa perehtymistä, koska se ei oikein kunnolla auennut luentojen aikana. 

### Mitä harjoituksia tein?
Tällä viikolla ei ollut palautettavaa harjoitusta.


---
## Viikko 8 ja 9
### Mitä opin näillä viikoilla?

Viikon 8 (luento 2.11.) aikana opettelimme tietokantasovelluksen tekoa. Teimme tunnilla yhdessä vanhan harjoitustehtävän, jossa luotiin tietokantasovellus. Asensimme MariaDB-ohjelman (minulla oli se jo valmiina, mutta olin unohtanut salasanani niin jouduin aika pitkään säätämään, ennen kuin sain HeidiSQL:ssä tietokannan auki. Onnistuin lopulta komentokehotteen kautta vaihtamaan uuden salasanan, kiitos ChatGPT:n ohjeiden!). Palauttelin mieleen miten SQL:n kanssa operoitiin ja miten HeidiSQL toimii. Viikolla 9 (luento 9.11.) käsittelimme REACT:ia, funktionaalisia komponentteja sekä tapahtumankäsitteliöitä (hooks). Opin ymmärtämään paremmin mitä tarkoittaa REACT ja miten tapahtumankäsittelijöillä operoidaan.

### Mitä harjoituksia tein?

Tein harjoituksen 5, palautin sen paljon yli deadlinen (jäin useamman viikon jälkeen sairastelun takia), mutta sain tehtävän lopulta tehtyä ja palautin sen GitHubiin REST1-repositoryyn, johon olen jakanut oikeudet opettajalle. Yllättävän paljon aikaa meni pelkästään pohjakoodin luomiseen, vaikka seurasin huolellisesti opetusvideon ohjeistusta. Kuitenkin ilmeni erilaisia ongelmia, joiden ratkaisemiseen meni aika paljon aikaa. Lopulta kun olin saanut pohjan valmiiksi niin varsinaisen tehtävän tekemiseen (metodien lisäämisen REST APIin) ei kulunut kovin paljon aikaa. Testasin Postmanilla, että ratkaisuni varmasti toimii ja hyvinhän se toimi :)

#### Harjoitus 5

En lisää tähän kaikkia tehtävään toteuttamiseen vaadittavaia koodejani, koska pitäisi lisätä useita tiedostoja, mutta listaan mihin kaikkiin tiedostoihin tein muutoksia/lisäyksiä, jotta sain PUT- ja DELETE-operaatiot toimimaan, ja laitan esimerkiksi pyyntöjen käsittelyyn tekemäni koodin tähän alle. 

Seuraavissa tiedostoissa on merkitty kommenteilla ne kohdat, joissa on omat lisäykseni:

1) controllers/postControllers.js
2) models/Post.js
3) routes/postRoutes.js:

```javascript=16
const express = require("express");
const postControllers = require("../controllers/postControllers");
const router = express.Router();

// @route GET && POST - /posts/
router
  .route("/")
  .get(postControllers.getAllPosts)
  .post(postControllers.createNewPost);

// ************************** OMA OSUUS ********************************

// käsitellään GET, PUT ja DELETE -pyynnöt polussa /posts/:id
router
  .route("/:id")
  .get(postControllers.getPostById)
  .put(postControllers.updateById)
  .delete(postControllers.deleteById);

// ************************** OMA OSUUS LOPPUU ***************************

module.exports = router;

```
Tässä vielä linkki GitHubiin, jonne tehtävä on palautettu: https://github.com/PaulaRii/REST1.git 

---

## Viikko 10
### Mitä opin tällä viikoilla?

Viikon 10 aikana (luento 16.11.) opettelimme REACT:in käyttöä. Tällä viikolla oli suuria vaikuksia pysyä luennosta kärryillä ja palasin tallenteessa takaisin monia kertoja, kun en saanut toistettua omalla koneella stä mitä luennoitsija teki luennon aikana. Opin tällä viikolla lisää JSX:stä, webhookeista ja stateista.

### Mitä harjoituksia tein?
Kävimme tunnilla läpi edellisen harjoitustehtävän, tällä viikolla ei ollut vielä uutta harjoitusta.

---
## Viikko 11
### Mitä opin tällä viikoilla?

Viikon 11 aikana (luento 23.11.) opeteltiin lisää hookkien käyttöä. Teimme tunnilla aiemmin tehdylle puhelinluettelolle Reactilla käyttöliittymän ja perehdyimme vähän myös Boostrappiin, jolla saa valmiita layoutteja. Vaikka koodin sai valmiiksi niin oli suuria ongelmia saada käyttöliittymä toimimaan, koska valmiissa pohjassa käytettiin vanhempaa react-route-versiota, minkä seurauksena jouduin aika paljon päivittämään pohjakoodia, jotta sain sen edes jotenkuten toimivaksi. Tuli jälleen kerrattua tietokannan luontia ja täytyi myös perehtyä reitittämiseen, joka yhä edelleen tuntuu aika monimutkaiselta aihekokonaisuudelta. Luennon lopuksi esiteltiin vähän Context API:a, jota on tarkoitus hyödyntää harjoitus 6:ssa, mutta minulle ei kyllä vielä yhtään auennut mikä se edes on. Täytynee pyytää ChatGPT:tä selittämään vähän tarkemmin, kun tunnilla konseptia ei juuri avattu. Toinen asia, johon olisin toivonut lisäopastusta tunneilla on Axios. Se mainittiin muutaman kerran, mutta sen toimintaa tai tarpeellisuutta ei oikeastaan ollenkaan selitetty. 

### Mitä harjoituksia tein?
Tälle viikolle ei ollut uutta harjoitusta, mutta meni aika paljon aikaa toteuttaamaan tunnilla yhdessä tehtyjä harjoituksia. Myös perehdyimme seuraaviin harjoitustehtäviin luomalla puhelinluettelo API:lle käyttölittymän Reactilla hyödyntäen Context API:a ja Bootstrappiä.

---
## Viikko 12
### Mitä opin tällä viikoilla?

Teimme luennolla yhdessä harjoitus 6:sta, jäin ihmettelemään miksi opettajalla ohjelma automaattisesti ehdottaa toista porttia, jos ehdotettu on toisessa käytössä, koska minulla se se ei ehdottanut. Jotta sain ohjelman toimimaan piti minun manuaalisesti muokata koodiini toinen portti (3001). Tällä viikolla en varsinaisesti oppinut mitään uutta, mutta syvennyin aiemmin opeteltuihin asioihin, kuten tietokantayhteyden toteuttamiseen, REST API:n luomiseen, Reactiin ja Context API:iin, joita nyt ymmärrän paremmin. Meni hyvin monta tuntia perehtyessä siihen miten toteutan harjoitus 6:sen.

### Mitä harjoituksia tein?

Tein harjoituksen 6, ja käytin siihen varmasti enemmän aikaa kuin sen tekemiseen oli tarkoitettu käytettävän aikaa. Oli suuria ongelmia ymmärtää Context API:n käyttöä enkä meinannut saada Lisää, Muokkaa ja Poista -toiminnallisuuksia toimimaan, vaikka palvelimen puolella ne toimivat. Lopulta keksin, että minulla oli turhaan GlobalState.js-tiedosto sekoittamassa kuvioita ja kun poistin sen ja siihen kuuluvat context-tiedostot ja jätin vain PelaajatContext.js-tiedoston niin hommat ryhtyivät toimimaan paremmin. Ongelmia oli yhä poiston ja lisäyksen kanssa. Useiden tuntien ihmettelyn ja tuskailun jälkeen löysin virheen; olin palvelimen puolelle merkannut osoitteeksi "...urheilija/:id" ja käyttöliittymän puolelle "...urheilijat/:id". Useamman illan tuskailu ratkesi siis yhden kirjaimen poistamisella... Lopulta siis kaikki vaadittavat toiminnallisuudet toimivat. Kuvia en yrityksestäni huolimatta valitettavasti saanut näkymään urheilija-näkymässä.

Käyttöliittymäni idea on siis siinä, että taulukkoon voi lisätä urheilijoita painamalla etusivulla olevaa "Lisää urheilija"-painiketta ja urheilijoiden tietoja pääsee katsomaan ja muokkaamaan klikkaamalla urheilijan sukunimeä. Tällöin aukeaa näkymä sivun alareunaan. Näkymässä voi myös poistaa urheilijan. Muokkaus-painikkeella pääsee samanlaiseen ikkunaan kuin lisäys-painikkeella. Taulukon otsikko päivittyy sitä mukaan kun tietuemäärä taulussa muuttuu.

Käytin ratkaisussani sekä Context API:a komponenttien kanssa että Bootstrappia muotoiluun (taulukko, painikkeet, näkymä ja lisäys- sekä muokkaussivu).

#### Harjoitus 
Tässä linkki GitHubiin, jonne tehtävä on palautettu: https://github.com/PaulaRii/REST1.git 

**Huom!** Tietokannan luontiskripti on Urheilija2/serveri-kansion sisällä tekstitiedostona.

---
## Viikko 13
### Mitä opin tällä viikoilla?

Tällä viikolla perehdyimme automatisoituun testaamiseen. Mieleeni jäi erityisesti yksikkötestaaminen.

### Mitä harjoituksia tein?
Tein viimeisen harjoituksen (harjoitus 7) kevään aikana. Sen kanssa ei ollut suuresti ongelmia, sen tekeminen vain vei paljon aikaa. Yksi ärsyttävä ongelma oli kylläkin käytttämässäni valmiissa bootstrap-pohjassa; siinä oli jokin .pug-tiedosto, jollaisesta ei oltu mielestäni puhuttu kurssin aikana. Se aiheutti ongelmia, koska index.html-tiedostoon koostamani sivunrakenne piti muuttaa tuohon pug-tiedoston muotoon tai muuten muutokset eivät tallentuneet jostain käsittämättömästä syystä. Kerran jo menetin tekemäni koodin ja minun piti aloittaa alusta. Jostain syystä kun projektin avaa uudestaan sen kerran suljettua niin index.html muuttuu index.pug-tiedoston mukaiseksi. Onneksi ChatGPT osasi auttaa sen index.pug-tiedoston luomisessa, koska sen käytön opetteluun ei ollut enää aikaa. Nyt jälkiviisaana tuli mieleen, että sen index.pug-tiedoston olisi varmaan vaan voinut poistaa koko projektista...?

#### Harjoitus 

```javascript=16
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1, shrink-to-fit=no"
        />
        <meta name="description" content="" />
        <meta name="author" content="" />
        <title>Portfolio - Harjoitus 7</title>
        <link
            rel="icon"
            type="image/x-icon"
            href="assets/img/profiilikuva_uusi2.jpg"
        />
        <!-- Font Awesome icons (free version)-->
        <script
            src="https://use.fontawesome.com/releases/v6.3.0/js/all.js"
            crossorigin="anonymous"
        ></script>
        <!-- Google fonts-->
        <link
            href="https://fonts.googleapis.com/css?family=Saira+Extra+Condensed:500,700"
            rel="stylesheet"
            type="text/css"
        />
        <link
            href="https://fonts.googleapis.com/css?family=Muli:400,400i,800,800i"
            rel="stylesheet"
            type="text/css"
        />
        <!-- Core theme CSS (includes Bootstrap)-->
        <link href="css/styles.css" rel="stylesheet" />
    </head>

    <body id="page-top">
        <!-- Navigation-->
        <nav
            class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top"
            id="sideNav"
        >
            <a class="navbar-brand js-scroll-trigger" href="#page-top">
                <span class="d-block d-lg-none">Paula-Riitta Huttunen</span>
                <span class="d-none d-lg-block">
                    <img
                        class="img-fluid img-profile rounded-circle mx-auto mb-2"
                        src="assets/img/profiilikuva_uusi2.jpg"
                        alt="Profiilikuva"
                    />
                </span>
            </a>
            <button
                class="navbar-toggler"
                type="button"
                data-bs-toggle="collapse"
                data-bs-target="#navbarResponsive"
                aria-controls="navbarResponsive"
                aria-expanded="false"
                aria-label="Toggle navigation"
            >
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarResponsive">
                <ul class="navbar-nav">
                    <li class="nav-item">
                        <a class="nav-link js-scroll-trigger" href="#about"
                            >Home</a
                        >
                    </li>
                    <li class="nav-item">
                        <a class="nav-link js-scroll-trigger" href="#experience"
                            >Harjoitukset</a
                        >
                        <ul>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-0"
                                    >Harjoitus 0</a
                                >
                            </li>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-1"
                                    >Harjoitus 1</a
                                >
                            </li>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-2"
                                    >Harjoitus 2</a
                                >
                            </li>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-3"
                                    >Harjoitus 3</a
                                >
                            </li>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-4a"
                                    >Harjoitus 4a</a
                                >
                            </li>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-4b"
                                    >Harjoitus 4b</a
                                >
                            </li>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-5"
                                    >Harjoitus 5</a
                                >
                            </li>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-6"
                                    >Harjoitus 6</a
                                >
                            </li>
                            <li>
                                <a
                                    class="nav-link js-scroll-trigger"
                                    href="#harjoitus-7"
                                    >Harjoitus 7</a
                                >
                            </li>
                        </ul>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link js-scroll-trigger" href="#education"
                            >Palauteosio</a
                        >
                    </li>
                </ul>
            </div>
        </nav>
        <!-- Page Content-->
        <div class="container-fluid p-0">
            <!-- About-->
            <section class="resume-section" id="about">
                <div class="resume-section-content">
                    <h1 class="mb-0">
                        Paula-Riitta
                        <span class="text-primary">Huttunen</span>
                    </h1>
                    <div class="subheading mb-5">
                        Itä-Suomen Yliopisto · tietojenkäsittelytiede ·
                        <a href="mailto:paularii@uef.fi">paularii@uef.fi</a>
                    </div>
                    <p class="lead mb-5">
                        Tämä on Web-ohjelmoinnin kurssia varten tehty portfolio,
                        johon koostettu kuvaukset kurssilla tekemistäni
                        harjoitustöistä ja lisäksi siihen on sisällytetty
                        palauteosio.
                    </p>
                    <div class="social-icons">
                        <a
                            class="social-icon"
                            href="https://www.linkedin.com/in/paula-riitta-huttunen/"
                        >
                            <i class="fab fa-linkedin-in"></i>
                        </a>
                        <a
                            class="social-icon"
                            href="https://github.com/PaulaRii"
                        >
                            <i class="fab fa-github"></i>
                        </a>
                        <a
                            class="social-icon"
                            href="https://twitter.com/Lydiitti"
                        >
                            <i class="fab fa-twitter"></i>
                        </a>
                    </div>
                </div>
            </section>
            <hr class="m-0" />
            <!-- Experience-->
            <section class="resume-section" id="experience">
                <div class="resume-section-content">
                    <h2 class="mb-5">Harjoitukset</h2>
                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-0"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 0</h3>
                            <div class="subheading mb-3">
                                HTML-koodin korjaaminen
                            </div>
                            <p>
                                Tämä oli HTML:ään liittyvä tehtävä, jossa kopion
                                opettajan pohjan ja tein siihen päälle omat
                                muokkaukseni. Lopuksi ajoin HTML ja CSS-koodit
                                validaattorissa. En löytänyt kuin yhden virheen,
                                joka oli helppo korjata. Tehtävä näytti aluksi
                                vaikeammalta kuin mitä se loppupelissä oli.
                            </p>
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Viikko 2</span>
                        </div>
                    </div>
                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-1"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 1</h3>
                            <div class="subheading mb-3">
                                Javascript -perusteet 1
                            </div>
                            <p>
                                Harjoituksessa 1 toteutin palindromifunktion,
                                joka tarkistaa, onko annettu merkkijono
                                palindromi. Käytin JavaScriptin listoja ja
                                luuppeja sekä ehtolauseita vertaillakseni
                                merkkijonon alkioita toisiinsa. Koodi koostui
                                seuraavista vaiheista:
                            </p>
                            <p>
                                1. Syötteen kysyminen käyttäjältä readline-sync
                                -kirjastolla.<br />
                                2. Merkkien tallentaminen syötetystä sanasta
                                taulukkoon.<br />
                                3. Taulukon kääntäminen sijoittamalla
                                alkuperäisen taulukon merkit lopusta alkuun
                                uuteen taulukkoon.<br />
                                4. Alkuperäisen ja käännetyn taulukon merkkien
                                vertailu toisiinsa luupin avulla.<br />
                                5. Vertailun tuloksen palauttaminen
                                totuusarvona.
                            </p>
                            <p>
                                Harjoituksen tavoitteena oli harjoitella
                                ohjelmoinnin perusteita, erityisesti
                                ehtolauseiden ja luuppien käyttöä, sekä
                                vahvistaa JavaScript-osaamistani. Tämä harjoitus
                                oli hyvä kertausharjoitus, joka auttoi
                                palauttamaan mieleen ohjelmoinnin perustaitoja.
                            </p>
                            <p>
                                Harjoituksen aikana palautui hyvin mieleen,
                                kuinka sijoitetaan dataa listoihin ja verrataan
                                keskenään listojen alkioita toisiinsa. Opin myös
                                paremmin käsittelemään merkkijonoja sekä listoja
                                JavaScriptissä. Vaikka tämä harjoitus auttoikin
                                kertaamaan perusasioita, koen, että
                                lisäharjoitus olisi ehkä tarpeen, erityisesti
                                monimutkaisempien algoritmien ja
                                tietorakenteiden osalta.
                            </p>
                            <p>
                                Mielestäni onnistuin harjoituksessa ihan hyvin,
                                sillä sain palindromifunktion toimimaan. Jos
                                tekisin tehtävän uudelleen, kiinnittäisin
                                enemmän huomiota tarkemmin tehtävänantoon (jotta
                                teen juuri sitä mitä pyydettiin) sekä koodin
                                optimointiin ja tehokkuuteen, esimerkiksi
                                käyttämällä jotain tehokkaampia vertailu- ja
                                käsittelytapoja.
                            </p>
                            <p>Linkki vastaukseen HackMD:ssä:</p>
                            <a href="https://hackmd.io/@PaulaH/SsH20JNSf411"
                                >https://hackmd.io/@PaulaH/SsH20JNSf411</a
                            >
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Viikko 3</span>
                        </div>
                    </div>
                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-2"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 2</h3>
                            <div class="subheading mb-3">
                                Javascript -perusteet 2
                            </div>
                            <p>
                                Harjoituksessa 2 opettelin luomaan oliota sekä
                                sijoittamaan luodut oliot taulukkoon. Aluksi oli
                                hieman vaikeuksia saada luotua uusia olioita,
                                mutta lopulta muistin miten JavaScriptissä
                                käytetään luokkaa ja sen konstruktoria.
                            </p>
                            <p>
                                Toisessa osassa harjoitusta oli luotava funktio,
                                joka etsii käyttäjän aiemmassa vaiheessa
                                luotujen henkilöiden syötettyjä puhelinnumeroita
                                aiemmin luodusta puhelinluettelosta. Toteutin
                                tämän niin, että käyttäjältä jatkuvasti kysytään
                                minkä toiminnon tämä haluaa suorittaa ja sitten
                                toimintavaihtoehdot on listattu
                                switch-rakenteeseen, jossa kutsutaan funktiota,
                                joka joko suorittaa lisäyksen tai hakemisen tai
                                sitten lopettaa ohjelman suorittamisen.
                            </p>
                            <p>
                                Harjoituksessa 2 toteutin
                                puhelinluettelo-ohjelman, jossa käyttäjä voi
                                lisätä henkilöitä nimellä ja puhelinnumerolla,
                                sekä hakea henkilöiden puhelinnumeroita nimellä.
                                Koodi koostui seuraavista vaiheista:
                            </p>
                            <p>
                                1. Syötteen kysyminen käyttäjältä readline-sync
                                -kirjastolla.<br />
                                2. Henkilön tietojen tallentaminen oliona
                                puhelinluettelo-taulukkoon.<br />
                                3. Olion luominen Henkilo-luokasta käyttäen sen
                                konstruktoria.<br />
                                4. Olioiden lisääminen
                                puhelinluettelo-taulukkoon.<br />
                                5. Funktio, joka hakee puhelinnumeron syötetyn
                                nimen perusteella.<br />
                                6. Käyttäjän jatkuva syötteen kysyminen ja
                                toiminnan suorittaminen switch-rakenteen avulla.
                            </p>
                            <p>
                                Harjoitusen tavoitteena oli harjoitella
                                oliopohjaista ohjelmointia JavaScriptissä,
                                erityisesti luokkien ja konstruktorien käyttöä,
                                sekä vahvistaa taitoja käsitellä taulukoita ja
                                funktioita. Tämä harjoitus auttoi ymmärtämään
                                ohjelmoinnin peruskonsepteja ja oli hyvää
                                kertausta olio-ohjelmoinnin perusteista.
                            </p>
                            <p>
                                Harjoituksen aikana kertasin kuinka luodaan ja
                                käytetään olioita sekä operoidaan taulukoiden ja
                                merkkijonojen kanssa JavaScriptissä. Harjoitus
                                auttoi myös ymmärtämään paremmin funktioiden
                                käyttöä ja niiden parametrisointia.
                            </p>
                            <p>
                                Mielestäni onnistuin harjoituksessa hyvin, sillä
                                sain puhelinluettelo-ohjelman toimimaan oikein
                                ja kaikki vaaditut toiminnallisuudet
                                toteutettua. Ei tule mieleen mitä olisi
                                kannattanut tehdä toisin.
                            </p>
                            <p>Linkki vastaukseen HackMD:ssä:</p>
                            <a href="https://hackmd.io/@PaulaH/SsH20JNSf411"
                                >https://hackmd.io/@PaulaH/SsH20JNSf411</a
                            >
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Viikko 3</span>
                        </div>
                    </div>
                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-3"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 3</h3>
                            <div class="subheading mb-3">
                                JavaScript -perusteet 3: Luokat ja periytyminen
                            </div>
                            <p>
                                Harjoituksessa 3 opettelin luokkien määrittelyä
                                ja periytymistä JavaScriptissä. Vaikka konsepti
                                oli ennestään tuttu Java-kielestä, tarvitsin
                                hieman kertausta.
                            </p>
                            <p>
                                Suurin haaste oli Git-versionhallinnan kanssa.
                                Yritin pushata tiedostoa GitHub-repositorioon,
                                mutta kohtasin jatkuvasti virheilmoituksia,
                                jotka liittyivät mahdollisesti merge-ongelmiin.
                                Lopulta sain ongelman ratkaistua, vaikka en
                                olekaan ihan varma, mikä lopulta auttoi
                                ratkaisemaan ongelman.
                            </p>
                            <p>
                                Itse ohjelmointitehtävässä ei ollut suurempia
                                ongelmia, mutta Date-metodin toimintalogiikan
                                ymmärtäminen vaati hieman lisäopiskelua.
                            </p>
                            <p>
                                Harjoituksessa 3 toteutin Henkilo-luokan ja
                                siitä periytyvän Urheilija-luokan.
                                Urheilija-luokassa määriteltiin get- ja
                                set-funktiot erityisille attribuuteille. Koodi
                                koostui seuraavista vaiheista:
                            </p>
                            <p>
                                1. Henkilo-luokan määrittely ja konstruktorin
                                luominen.<br />
                                2. Henkilo-luokan getter- ja setter-metodien
                                määrittely.<br />
                                3. Urheilija-luokan määrittely, joka perii
                                Henkilo-luokan.<br />
                                4. Urheilija-luokan omien ominaisuuksien ja
                                metodien määrittely.<br />
                                5. Urheilija-olioiden luominen ja niiden
                                tietojen tulostaminen.
                            </p>
                            <p>
                                Harjoitusta tehdessä syvensin ymmärrystäni
                                olio-ohjelmoinnista, erityisesti luokkien ja
                                periytymisen osalta. Tämä harjoitus vahvisti
                                lisää JavaScript-taitojani ja oli hyvää
                                kertausta olio-ohjelmoinnin perusteista.
                            </p>
                            <p>
                                Harjoituksen aikana opin lisää luokkien
                                määrittelystä ja periytymisestä JavaScriptissä.
                                Tämä harjoitus auttoi myös ymmärtämään paremmin
                                getter- ja setter-metodien käyttöä. Ei tule
                                mieleen mitä jäi oppimatta.
                            </p>

                            <p>
                                Mielestäni onnistuin tehtävässä ihan hyvin,
                                sillä sain toteutettua kaikki vaaditut
                                toiminnallisuudet ja koodini toimii oikein. Jos
                                tekisin tehtävän uudelleen, kiinnittäisin
                                enemmän huomiota Git-versionhallinnan käyttöön,
                                ettei olisi niin paljon ongelmia sen kanssa.
                            </p>
                            <p>
                                <strong>Huom! </strong>Harjoitus oli alunperin
                                palautettu GitHubiin erilliseen repositoryyn
                                (Henkilo.js, jossa oli kansio nimeltä Teht3,
                                jossa oli tiedosto Henkilo.js), mutta kopioin
                                kansion ja nimesin sen uudestaan tehtävänannon
                                mukaisesti "Urheilija1" ja siirsin sen
                                REST1-repostoryyn, jonne olen jakanut muutkin
                                harjoitukset, jotka piti jakaa GitHubissa. Tässä
                                linkki päivitettyyn sijaintiin
                                REST1-repositoryyn:
                            </p>
                            <a href="https://github.com/PaulaRii/REST1.git"
                                >https://github.com/PaulaRii/REST1.git</a
                            >
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Viikko 4</span>
                        </div>
                    </div>
                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-4a"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 4a</h3>
                            <div class="subheading mb-3">
                                Sanakirja REST API
                            </div>
                            <p>
                                Harjoituksessa 4a luotiin REST API sanakirjaa
                                varten. Sanakirjassa jokainen rivi sisältää
                                suomenkielisen sanan ja sen englanninkielisen
                                vastineen. Toteutin tehtävän synkronisena, koska
                                koin sen olevan helpompi toteuttaa.
                            </p>
                            <p>
                                REST API:n toteutus koostui seuraavista
                                vaiheista:
                            </p>
                            <p>
                                1. Express-sovellusolion luominen.<br />
                                2. CORS- ja esiasetusten määrittely
                                API-pyynnöille.<br />
                                3. Sanakirjan lataaminen tekstitiedostosta
                                sovelluksen käynnistyessä.<br />
                                4. GET-metodin toteutus koko sanakirjan
                                palauttamiseksi.<br />
                                5. GET-metodin toteutus sanojen etsimiseksi
                                suomenkielisen sanan perusteella.<br />
                                6. POST-metodin toteutus uusien sanaparien
                                lisäämiseksi sanakirjaan ja tekstitiedostoon.
                            </p>
                            <p>
                                Harjoituksen tavoitteena oli syventää ymmärrystä
                                REST API:n toiminnasta ja Expressin käytöstä.
                                Tämä harjoitus auttoi hahmottamaan paremmin,
                                miten API-pyyntöjä käsitellään ja miten
                                tiedostoja käsitellään Node.js:ssä.
                            </p>
                            <p>
                                Tehtävän aikana opin enemmän REST API:sta ja
                                Expressin käytöstä, sekä tiedostojen
                                käsittelystä Node.js:ssä. Tämä harjoitus oli
                                hyödyllinen johdatus API-kehitykseen ja auttoi
                                ymmärtämään REST-arkkitehtuurin periaatteita.
                            </p>
                            <p>
                                Harjoitus onnistui hyvin, sillä sain API:n
                                toimimaan oikein ja kaikki vaaditut
                                toiminnallisuudet toteutettua. Jos tekisin
                                tehtävän uudelleen, harkitsisin asynkronisen
                                toteutuksen käyttämistä parantaakseni
                                sovelluksen suorituskykyä.
                            </p>
                            <p>Linkki vastaukseen GitHubissa:</p>
                            <a href="https://github.com/PaulaRii/REST1"
                                >https://github.com/PaulaRii/REST1</a
                            >
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Viikko 5</span>
                        </div>
                    </div>
                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-4b"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 4b</h3>
                            <div class="subheading mb-3">
                                Sanakirja REST API -käyttöliittymä
                            </div>
                            <p>
                                Harjoituksessa 4b luotiin käyttöliittymä aiemmin
                                toteutettuun sanakirja REST APIin.
                                Käyttöliittymän avulla voi lisätä ja hakea
                                sanoja. Toteutin käyttöliittymän HTML:n ja
                                jQueryn avulla, ja jaoin toiminnallisuudet eri
                                sivuille.
                            </p>
                            <p>
                                Käyttöliittymän toteutus koostui seuraavista
                                vaiheista:
                            </p>
                            <p>
                                1. HTML-sivujen luominen eri
                                toiminnallisuuksille:
                                <strong
                                    >index.html, view.html, add.html,
                                    search.html</strong
                                >.<br />
                                2. jQueryn käyttö lomakkeiden käsittelyyn ja
                                API-pyyntöjen lähettämiseen.<br />
                                3. CORS-otsikoiden lisääminen REST APIin, jotta
                                käyttöliittymä voi tehdä pyyntöjä
                                palvelimelle.<br />
                                4. Sanakirjan tietojen hakeminen ja näyttäminen
                                <strong>view.html</strong>-sivulla.<br />
                                5. Uuden sanaparin lisääminen
                                <strong>add.html</strong>-sivun lomakkeella.<br />
                                6. Suomenkielisen sanan hakeminen ja sen
                                englanninkielisen vastineen näyttäminen
                                <strong>search.html</strong>-sivulla.
                            </p>
                            <p>
                                Harjoituksen tavoitteena oli syventää ymmärrystä
                                käyttöliittymien luomisesta REST API:a
                                hyödyntäen. Tämä harjoitus auttoi ymmärtämään
                                paremmin jQueryn käyttöä ja API-pyyntöjen
                                käsittelyä.
                            </p>
                            <p>
                                Harjoitusta tehdessä opin jQueryn käyttöä ja
                                ymmärsin paremmin REST API -käyttöliittymien
                                toteuttamista. Tämä harjoitus oli hyödyllinen
                                johdatus API-kehitykseen ja auttoi ymmärtämään,
                                miten käyttöliittymä ja API kommunikoivat
                                keskenään.
                            </p>
                            <p>
                                Harjoitus onnistui ihan hyvin, sain
                                käyttöliittymän toimimaan ja kaikki vaaditut
                                toiminnallisuudet toteutettua. Jos tekisin
                                tehtävän uudelleen, toteuttaisin ehkä
                                käyttöliittymän yksinkertaisemmin yhdelle
                                sivulle, jotta käytettävyys olisi selkempää.
                            </p>
                            <p>Linkki vastaukseen GitHubissa:</p>
                            <a href="https://github.com/PaulaRii/REST1"
                                >https://github.com/PaulaRii/REST1</a
                            >
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Viikko 5 ja 6</span>
                        </div>
                    </div>
                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-5"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 5</h3>
                            <div class="subheading mb-3">
                                Node-Express-starter
                            </div>
                            <p>
                                Harjoituksessa 5 luotiin Node.js REST API, joka
                                käyttää Expressiä ja MariaDB:tä. Tavoitteena oli
                                lisätä pohjakoodiin REST-rajapinnan mukaiset
                                metodit PUT ja DELETE tietyn id:n perusteella
                                kenttien "title" ja "body" päivittämiseksi ja
                                tietueen poistamiseksi.
                            </p>
                            <p>
                                REST API:n toteutus koostui seuraavista
                                vaiheista:
                            </p>
                            <p>
                                1. MariaDB:n kanssa taistelu ja tietokannan
                                luominen.<br />
                                2. Pohjakoodin kopioiminen.<br />
                                3. PUT- ja DELETE-metodien lisääminen REST
                                API:iin pohjakoodin mukaisesti.<br />
                                4. API:n testaaminen Postmanilla kaikkien
                                operaatioiden varmistamiseksi (GET, POST, PUT,
                                DELETE).
                            </p>
                            <p>
                                Seuraavissa tiedostoissa tein muutoksia PUT- ja
                                DELETE-metodien lisäämiseksi:
                            </p>
                            <ul>
                                <li>controllers/postControllers.js</li>
                                <li>models/Post.js</li>
                                <li>routes/postRoutes.js</li>
                            </ul>
                            <p>
                                Tämä harjoitus auttoi ymmärtämään paremmin
                                Node.js:n ja MariaDB:n käyttöä REST API:n
                                kanssa. Opin erityisesti, miten tietokannan
                                operaatioita (kuten haku, lisäys, päivitys ja
                                poisto) voidaan toteuttaa API:n kautta ja miten
                                testata niitä Postmanilla.
                            </p>
                            <p>
                                Alkuvaikeuksista huolimatta harjoitus onnistui
                                lopulta hyvin, sillä sain kaikki vaaditut
                                toiminnallisuudet toimimaan. Varmasti tämän
                                olisi voinut tehdä jotenkin paremminkin, mutta
                                en tiedä mitä tekisin toisin, jos tekisin
                                harjoituksen uudestaan.
                            </p>
                            <p>Linkki vastaukseen GitHubissa:</p>
                            <a href="https://github.com/PaulaRii/REST1"
                                >https://github.com/PaulaRii/REST1</a
                            >
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Joulukuu</span>
                        </div>
                    </div>

                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-6"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 6</h3>
                            <div class="subheading mb-3">
                                Urheilija II (REST API & React-sovellus)
                            </div>
                            <p>
                                Harjoituksessa 6 toteutettiin
                                JavaScript-palvelinsovellus, joka tarjoaa
                                REST-rajapinnan kautta tiedon urheilijoista.
                                Tavoitteena oli toteuttaa datan haku, lisäys,
                                poisto ja päivitys MariaDB-tietokantaan sekä
                                luoda React-käyttöliittymä, jonka avulla näitä
                                operaatioita voi suorittaa.
                            </p>
                            <p>
                                REST API:n ja React-käyttöliittymän toteutus
                                koostui seuraavista vaiheista:
                            </p>
                            <p>
                                1. Tietokannan luominen MariaDB:llä.<br />
                                2. REST-rajapinnan toteuttaminen Expressin
                                avulla.<br />
                                3. CRUD (Create, Read, Update, Delete)
                                -operaatioiden toteutus tietokantaan.<br />
                                4. React-sovelluksen luominen ja Context API:n
                                hyödyntäminen datan hallinnassa.<br />
                                5. Bootstrapin käyttö käyttöliittymän
                                muotoilussa.
                            </p>
                            <p>
                                Palvelinpuolen koodissa hyödynsin seuraavia
                                tiedostoja:
                            </p>
                            <ul>
                                <li>index.js</li>
                            </ul>
                            <p>React-käyttöliittymän tärkeimmät komponentit:</p>
                            <ul>
                                <li>App.js</li>
                                <li>PelaajaContext.js</li>
                                <li>PelaajaLista.js</li>
                                <li>LisaaPelaaja.js</li>
                                <li>MuokkaaPelaaja.js</li>
                                <li>PelaajaTiedotNakyma.js</li>
                                <li>PoistaPelaaja.js</li>
                            </ul>
                            <p>
                                Tämä harjoitus syvensi ymmärrystäni REST API:n
                                luomisesta ja Reactin käytöstä
                                tietokantasovelluksen rakentamisessa.
                                Pitkällisen selvittelyn jälkeen koin myös
                                oppivani Context API:n hyödyntämistä datan
                                hallinnassa.
                            </p>
                            <p>
                                Harjoitus onnistui lopulta melko hyvin, vaikka
                                kohtasin aluksi paljon haasteita, erityisesti
                                Context API:n käytössä ja React-komponenttien
                                hallinnassa. Lopputuloksena oli kuitenkin
                                toimiva sovellus, joka mahdollistaa
                                urheilijoiden tietojen hallinnan (lisäys,
                                tarkastelu, muookaus ja poisto). Jostain syystä
                                en saanut kuvia näkymään ja pitkän ja
                                piinallisen yrittämisen jälkeen luovuin kuvien
                                lisäämisestä. Jos tekisin harjoituksen
                                uudelleen, selvittäisin miten kuvat saa
                                näkymään. Perehtyisin myös vielä lisää siihen
                                Context API:n toimintaan.
                            </p>
                            <p>Linkki vastaukseen GitHubissa:</p>
                            <a href="https://github.com/PaulaRii/REST1"
                                >https://github.com/PaulaRii/REST1</a
                            >
                            <p>
                                <strong>Huom!</strong> Tietokannan luontiskripti
                                on Urheilija2/serveri-kansion sisällä
                                tekstitiedostona.
                            </p>
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Joulukuu</span>
                        </div>
                    </div>
                    <div
                        class="d-flex flex-column flex-md-row justify-content-between mb-5"
                        id="harjoitus-7"
                    >
                        <div class="flex-grow-1">
                            <h3 class="mb-0">Harjoitus 7</h3>
                            <div class="subheading mb-3">e-Portfolio</div>
                            <p>
                                Viimeisessä harjoituksessa koostin e-portfolion,
                                jossa on mahdollista navigoida aiemmin
                                toteuttamieni tehtävien sisällä. Käytin
                                erityisesti Bootstrap-komponentteja
                                hyödyntämällä valmista Bootstrap-pohjaa, mikä
                                helpotti rakenteen luomista ja sisällön
                                lisäämistä.
                            </p>
                            <p>
                                Vaikka harjoitus ei ollut erityisen vaikea, se
                                vei aikaa. Ainoa varsinainen haaste oli
                                valmiissa Bootstrap-pohjassa ollut
                                .pug-tiedosto, joka aiheutti harmaita hiuksia,
                                koska muutokset index.html-tiedostoon eivät
                                jostain syystä tallentuneet oikein ilman sen
                                muokkaamista. Onneksi ChatGPT auttoi
                                .pug-tiedoston luomisessa, vaikka näin
                                jälkikäteen ajateltuna sen poistaminen olisi
                                voinut olla helpompi ratkaisu.
                            </p>
                            <p>
                                Harjoituksen tavoitteena oli koota aiemmat
                                tehtävät selkeästi navigoitavaksi portfolioksi
                                ja harjoitella Bootstrapin käyttöä web-sivuston
                                rakentamisessa. Tämä auttoi ymmärtämään paremmin
                                Bootstrap-komponenttien hyödyntämistä ja
                                sivuston rakenteen suunnittelua.
                            </p>
                            <p>
                                Opin paljon Bootstrapin käytöstä ja sen
                                tarjoamista valmiista komponenteista, jotka
                                helpottivat sivuston rakenteen luomista. Sain
                                myös kokemusta siitä, kuinka valmiita pohjia
                                voidaan mukauttaa omiin tarpeisiin sopiviksi.
                                Vaikka .pug-tiedoston käsittely aiheutti
                                haasteita, onnistuin lopulta luomaan toimivan
                                portfolion.
                            </p>
                            <p>
                                Mielestäni onnistuin e-portfolion
                                toteuttamisessa hyvin, sillä lopullinen
                                portfolio on selkeä ja toimiva. Jos tekisin
                                harjoituksen uudelleen, poistaisin
                                .pug-tiedoston kokonaan välttääkseni sen
                                aiheuttamat ongelmat ja keskittyisin pelkästään
                                index.html-tiedoston muokkaamiseen.
                            </p>
                            <p>Linkki harjoitukseen GitHubissa:</p>
                            <a href="https://github.com/PaulaRii/REST1"
                                >https://github.com/PaulaRii/REST1</a
                            >
                        </div>
                        <div class="flex-shrink-0">
                            <span class="text-primary">Toukokuu</span>
                        </div>
                    </div>
                </div>
            </section>
            <hr class="m-0" />
            <!-- Education-->
            <section class="resume-section" id="education">
                <div class="resume-section-content">
                    <h2 class="mb-5">Palauteosio</h2>

                    <div class="mb-4">
                        <strong>Alkutilanne:</strong>
                        <p>
                            Ennen kurssia tietoni ja taitoni web-ohjelmoinnista
                            olivat lähes alkeelliset.
                        </p>
                    </div>

                    <div class="mb-4">
                        <strong>Nykytilanne:</strong>
                        <p>
                            Koen nyt osaavani käyttää Bootstrappiä, ja luoda
                            ainakin jokseenkin toimivia web-sivuja sekä uskon
                            ymmärtäväni pääperiaatteet REST API:sta ja Reactin
                            käytöstä. Lisäksi hahmotan nyt paremmin
                            tietokantaohjelmointia ja siten miten websivuihin
                            saa tehtyä AJAX:illa asynkronisia kutsuja. Myös tuli
                            palauteltua mieleen Javascriptin sekä Git:in
                            käyttöä.
                        </p>
                    </div>

                    <div class="mb-4">
                        <strong>Ajankäyttö:</strong>
                        <p>
                            En tajunnut kurssilla ottaa käyttöön Clockifyitä
                            seuraamaan ajankäyttöäni (tähän olisi hyvä
                            muistuttaa opiskelijoita), joten en ole aivan
                            kärryillä siitä kuinka monta tuntia olen kurssin
                            suorittamiseen käyttänyt. Kuitenkin tuntuu, että
                            lähes jokaiseen tehtävään (ensimmäisiä tehtäviä
                            lukuunottamatta) tarvitsin enemmän aikaa kuin ehkä
                            oli tarkoitettu niihin käytettäväksi. Uskon, että
                            käytin lopulta aikaa huomattavasti enemmän kuin mitä
                            oli laskettu kurssin suorittamiseen.
                        </p>
                    </div>

                    <div class="mb-4">
                        <strong>Tukevat tekijät:</strong>
                        <p>
                            Luennoilla sai mukavasti tukea tehtävien tekemiseen.
                            Oli hyvä, että niiden alkuun saattamiseen käytettiin
                            aikaa luennolla. ChatGPT:n kanssa keskustelu kurssin
                            teemoista on ollut myös erittäin hyvä tuki, niin
                            virheiden löytämiseen koodista kuin myös avaamaan
                            hankalia käsitteitä, joihin ei mielestäni tunnilla
                            käytetty tarpeeksi aikaa, ja joiden opiskelu
                            jätettiinkin enemmän opiskelijan oman aktiivisuuden
                            varaan. Muistan keskustelleeni erityisen paljon REST
                            API:in liittyvistä asioista ChatGPT:n kanssa.
                            Luennoilla tuli aina hirmuisen paljon informaatiota
                            lyhyessä ajassa, ja sitä informaatiotulvaa on ollut
                            hyvä avata tekoälyn kanssa.
                        </p>
                    </div>

                    <div class="mb-4">
                        <strong>Häiritsevät tekijät:</strong>
                        <p>
                            Mielestäni olisi ollut parempi jakaa luennot kahteen
                            kertaan viikossa. Luennot olivat hyvin raskaita, ja
                            kun koko viikon käsiteltävät asiat ahdetaan yhteen
                            sessioon niin ei siinä oikein pysty sulattelemaan
                            kaikkea kuulemaansa ja tulee sellainen
                            informaatioähky ja tuntuu, ettei tunnilla käsitellyt
                            asiat oikein tahdo jäädä päähän. Positiivista oli
                            se, että oli kaksi viikkoa aikaa sulatella saatua
                            informaatiota ja paneutua harjoitustehtävien
                            tekemiseen.
                        </p>
                    </div>

                    <div class="mb-4">
                        <strong>Ohjaus ja apu:</strong>
                        <p>
                            Luennoilla sai hyvin ohjausta, siitä kiitos
                            luennoitsijalle. Arvostan sitä, että aina
                            varmistettiin, että ovathan kaikki yhä kelkassa
                            mukana (vaikka lopulta itse putosinkin kelkasta ja
                            kurssin suorittaminen pääsi venymään...).
                        </p>
                    </div>

                    <div class="mb-4">
                        <strong>Kohokohdat ja toiveet:</strong>
                        <p>
                            Oli hieno fiilis, kun pitkän taistelun jälkeen sai
                            tehtävän toimimaan. Erityisen suuria haasteita oli
                            harjoitus 6:sen kanssa, mutta kun sain sen lopulta
                            valmiiksi, oli aika voittajafiilis. Toiveena olisi,
                            että opitut asiat säilyvät muistissa ja niitä
                            kykenesi jatkossa hyödyntämään.
                        </p>
                    </div>

                    <div class="mb-4">
                        <strong>Tulevaisuuden suunnitelmat:</strong>
                        <p>
                            Haluan suunnitella omat nettisivut ja sitä varten
                            tulen varmaankin hyödyntämään kurssilla opittuja
                            asioita. Muutoin web-ohjelmointi ei ole ollut
                            itselläni suuren kiinnostuksen kohteena, joskin
                            kuitenkin päädyin työskentelemään GenAI-hankkeessa
                            web-selaimessa toimivan platformer-pelin kanssa,
                            joten jonkun verran näitä asioita on tullut
                            kuitenkin vastaan tässä kevään aikana jo.
                        </p>
                    </div>
                </div>
            </section>

            <hr class="m-0" />
        </div>
        <!-- Bootstrap core JS-->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
        <!-- Core theme JS-->
        <script src="js/scripts.js"></script>
    </body>
</html>

```



