diff --git a/bin/.gitignore b/bin/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..72227fa3833f2ca4b4db971bd41a9db4bf24ba63
--- /dev/null
+++ b/bin/.gitignore
@@ -0,0 +1,22 @@
+contracts/
+.classpath
+.project
+.history/
+.idea
+.jqwik-database
+.lib/
+.worksheet
+.settings/
+*.iml
+*.ipr
+*.iws
+*.log
+project/boot/
+project/plugins/project/
+project/project/
+project/*-shim.sbt
+project/target/
+target/
+openjfx/
+public/report.txt
+public/surefire-report.html
diff --git a/bin/.gitlab-ci.yml b/bin/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7a135ab03f7580d49516c31cbb747f4b554396ed
--- /dev/null
+++ b/bin/.gitlab-ci.yml
@@ -0,0 +1,36 @@
+image: maven:latest
+
+variables:
+  # This will supress any download for dependencies and plugins or upload messages which would clutter the console log.
+  # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
+  MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
+  MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version"
+  # -DinstallAtEnd=true -DdeployAtEnd=true"
+
+# Cache downloaded dependencies and plugins between builds.
+# To keep cache across branches add ''
+cache:
+  key: "$CI_JOB_NAME"
+  paths:
+    - .m2/repository
+
+build:
+  stage: build
+  script:
+    - mvn compile
+
+test:
+  stage: test
+  script:
+    - mvn test
+
+pages:
+  stage: deploy
+  script:
+    - ./report.sh || true
+  artifacts:
+    paths:
+      - public
+  only:
+    - master
+
diff --git a/bin/README.md b/bin/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4cb91b482b5985e5e57c33ae9fe9c3de10ec8c0a
--- /dev/null
+++ b/bin/README.md
@@ -0,0 +1,44 @@
+# DTEK0066 exercise 3 template
+
+## Tehtävänanto
+
+Tehtävänanto löytyy kurssiportaalista.
+
+## Workflow
+
+```bash
+$ git clone https://gitlab.utu.fi/tech/education/ooj/ooj2023-exercise3
+$ cd template-ooj
+
+< tee tehtävät >
+
+< editoi AUTHORS.TXT >
+
+$ git add -A
+$ git commit -m 'Add exercise implementations'
+$ git remote add oma https://gitlab.utu.fi/omatunnus/ooj2023-exercise3
+$ git push oma
+
+< korjaa/täydennä tehtäviä >
+
+$ git add -A
+$ git commit -m 'Fix the exercise task 3'
+$ git push oma
+```
+
+## Using Maven
+
+```bash
+$ mvn clean
+$ mvn compile
+$ mvn test
+$ mvn exec:java
+$ mvn javafx:run
+$ mvn surefire-report:report
+```
+
+## Online report
+
+See <https://gitlab.utu.fi/tech/education/ooj/ooj2023-exercise3/pages>
+
+Your version: https://USERNAME.utugit.fi/ooj2023-exercise3/
diff --git a/bin/Tehtavananto.md b/bin/Tehtavananto.md
new file mode 100644
index 0000000000000000000000000000000000000000..0cf486f1ccbbce67530f96fdd678a607a78f178a
--- /dev/null
+++ b/bin/Tehtavananto.md
@@ -0,0 +1,200 @@
+# Tehtävänanto - Harjoitustehtävät 3
+
+
+
+***Tehtävien pisteytys:***  
+Tehtävä 1: 4  
+Tehtävä 2: 8  
+Tehtävä 3: 5  
+Tehtävä 4: 9  
+Tehtävä 5: 4
+
+Yhteensä 30 pistettä
+
+Aloita tehtävien tekeminen forkkaamalla ja/tai kloonaamalla git-projekti 
+https://gitlab.utu.fi/tech/education/ooj/ooj2023-exercise3 
+
+Valmiit tehtävät palautetaan Moodleen. Paketoi zip-pakettiin koko projekti ja lataa se Moodleen. 
+
+
+***Mitä tarkoittaa määritys? Entä toteutus?***  
+Jos tehtävässä pyydetään määrittämään, se tarkoittaa luokan ja/tai rutiinin signatuurin, alku- ja 
+loppuehtojen sekä luokkainvariantin kirjoittamista eikä varsinaista työn tekevää rutiinin 
+koodia tarvitse toteuttaa. Jos puolestaan pyydetään toteuttamaan jotain, yleensä rutiini, pitää rutiini koodata 
+kokonaan valmiiksi. Vastaavasti, jos pyydetään määrittämää ja toteuttamaan, tehdään kaikki edellä mainittu.
+
+Määrittelyt saavat olla formaaleja, mutta ei-formaali sanallinen esitystapa hyväksytään myös.
+
+## Tehtävä 1
+
+Tehtäväsi on miettiä, miten luokat eroavat toisistaan ja mihin käyttötarkoitukseen luokkia voisi käyttää. Mitkä
+ovat seuraavien luokkien oleelliset erot?
+
+***A.*** Collection ja Map  
+***B.*** List, Set ja Queue  
+***C.*** ArrayList ja LinkedList  
+***D.*** HashSet ja TreeSet
+
+**Pisteytys**: 4 pistettä, 1 piste per kohta
+
+
+## Tehtävä 2
+
+Tutustu tehtäväpohjan luokkiin Kirjasto, KirjaKokoelma, Kirja ja Kirjantiedot. 
+
+Kirjasto-luokka kuvaa kirjaston toimipistettä. Kirjaston toimipisteellä voi olla sivukirjastoja, jotka niin ikään ovat 
+saman Kirjasto-luokan olioita. Myös sivukirjastolla voi olla sivukirjastoja. Kirjasto-luokalla on Set-tyyppinen 
+muuttuja sivukirjastot. Se jää tyhjäksi, jos kyseisellä kirjastolla ei ole sivukirjastoja.  
+
+Voimme esimerkiksi Turun seudulla ajatella, että Turun pääkirjasto on Kirjasto-olioista syntyvän puun juurisolmu. 
+Sen omat sivukirjastot ja naapurikuntien pääkirjastot ovat Turun pääkirjastoa kuvaavan olion sivukirjastoja. Naapurikuntien 
+pääkirjastoilla voi olla omia sivutoimipisteitä, jotka muodostavat puun kolmannen tason. Puun syvyyttä ei ole rajattu.
+
+Jokaisella kirjastolla on useita kirjakokoelmia, esim. erityyppisiä kirjoja (kaunokirjallisuus, tietokirjat, 
+lasten kirjat jne.). Jokaiseen kokoelmaan kuuluu puolestaan kirjoja. 
+
+***A.*** **Kloonaus.** Haluamme, että kuvatun luokkakokonaisuuden luokkien kloonauksessa syntyy aina syväkopio. Toteuta 
+luokkiin clone-rutiinit niin, että syväkopiointi toteutuu. Esimerkiksi pääkirjastona (puun juurisolmu) toimivan 
+clone-rutiinia kutsuttaessa haluamme saada kopiot kaikista olioista, joihin pääkirjaston oliosta on jotain reittiä 
+yhteys (viittauksia olioiden välillä).
+
+***B.*** **Merkkijonoesitys.** Toteuta luokkiin toString-rutiinit niin, että se palauttaa merkkijonoesityksenä luokan 
+jäsenmuuttujien nimet ja arvot. Jos jäsenmuuttuja on tyypiltään kokoelmaluokka, kutsutaan sen alkioiden toString-rutiineja. 
+Kiinnitä erityistä huomiota tekstin luettavuuteen. Esimerkiksi kutsumalla pääkirjastona (puun juurisolmu) 
+toString-rutiinia, saamme merkkijonoesityksen joka sisältää kaikki kirjastot, niiden kokoelman ja kokoelmien kirjat.
+
+
+***C.*** **Syväsamuus.** Toteuta luokkiin equals-rutiinit. Kaksi oliota ovat samat jos ja vain jos olioiden kaikkien 
+jäsenmuuttujien arvot ovat samat. Kokoelmatyyppisten jäsenmuuttujien sisältämien alkioiden tulee myös täsmätä, 
+mutta niiden järjestyksellä ei ole väliä. 
+
+***D.*** **Demonstrointi.** Edellä luotujen rutiinin toimintaa testataan käyttämällä niitä main-rutiinista käsin.
+- Tee Kirjasto-olio pääkirjasto ja talleta se muuttujaan
+- Lisää pääkirjastoon kaksi sivukirjastoa
+- Tee kaikille edellä mainituille kirjastoille kaksi kokoelmaa ts. yhteensä kuusi eri oliota
+- Lisää jokaiseen kokoelmaan vähintään kaksi kirjaa (yhteensä 12 eri oliota)
+- Tulosta listaus kaikista kirjastoista kokoelmineen ja kirjoineen kutsumalla pääkirjasto-olion toString-rutiinia 
+käyttäen 
+- Luo kopio pääkirjasto-oliosta kutsumalla sen clone-rutiinia ja talleta se muuttujaan
+- Vertaa alkuperäistä ja edellä tekemääsi kopiota equals-rutiinilla. Ovatko ne samat?
+
+
+**Pisteytys**: 8 pistettä
+- A-kohta 2 pistettä
+- B-kohta 2 pistettä
+- C-kohta 2 pistettä
+- D-kohta 2 pistettä
+
+
+## Tehtävä 3
+
+Toteuta Javan Map-rajapinnan ympärille geneerinen kääreluokka RandomMap, joka toimii Map-rajapinnan mukaisesti muuten kuten 
+olemassa oleva alkuperäinen Map-rajapinnan mukainen olio (eli delegoi toiminnot alkuperäiselle oliolle), mutta 
+palauttaa (get) satunnaisen arvon alkuperäisestä arvojoukosta, mikäli pyydettyä avainta ei löydy alkuperäisen 
+avainjoukosta. Käärittävä olio annetaan RandomMap-luokalle konstruktorin parametrina.
+
+Huomaa, että toteutuksen tulee *geneerisesti* sopia yhteen minkä tahansa jo olemassa olevan Map-muotoisen 
+olion kanssa. Lisäksi huomaa, että päätöksenteon pohjalla olevat arvo- ja avainjoukot voivat muuttua ohjelman 
+suorituksen edetessä ja kääreen tulisi mukautua tähän.
+
+Demonstroi toteuttamasi luokan käyttöä käärimällä jokin aiempi epätyhjä Map-olio ja nouda rajapinnan kautta 
+kokoelmasta löytyvä tai puuttuva arvo.
+
+Vinkki: IDE-ympäristö voi suureksi avuksi generoida alustavat versiot tarvittavista metodeista (esim. IDEA:ssa Ctrl-O ja Ctrl-I).
+
+**Pisteytys**: 5 pistettä
+- toimii pyydetyllä tavalla 2 pistettä
+- toteutus on geneerinen 1 piste
+- riippuu vain Map-rajapinnasta 1 piste
+- demonstrointi 1 piste
+
+
+## Tehtävä 4
+
+Kurssi materiaalissa on esitelty Map-rajapinta ja sen toteuttavia luokkia, kuten HashMap. Map tallettaa 
+avain-arvo-pareja. 
+
+Tässä tehtävässä teemme geneerisen luokan *Triplet*, joka tallettaa avaimen ja kaksi siihen liittyvää 
+arvoa ts. avain-arvo1-arvo2 -triplettejä. Avain ja arvot ovat geneeristä tyyppiä. Ne kaikki voivat olla eri 
+tyyppiä.
+
+Teemme myös rajapinnan *TripletMap*, joka määrittelee erilaisille tripletti toteutuksille yhteiset rutiinit.
+
+
+***A.*** Luo luokka Triplet. Suunnittele ja toteuta luokkamuuttujat, joihin tiedot talletetaan. Tee luokalle 
+konstruktori, joka alustaa tyhjän Triplet-olion. 
+
+***B.*** Tee rajapinta *TripletMap* ja määrittele siinä seuraavat rutiinit. Ryhmittely ei näy rajapinnassa vaan sen 
+osalta    
+Ryhmä 1:  
+- tripletin lisääminen: ```void put(K key, V value1, W value2)```
+- tripletin ensimmäisen arvon palautus: ```V getFirstValue(K key) ```
+- tripletin toisen arvon palautus: ```W getSecondValue(K key)```
+- tripletin poisto: ```void remove(K key)```
+- kaikkien triplettien poisto: ```void clear()```
+
+Ryhmä 2:
+- palauttaa kaikki avaimet: ```Set<K> keySet()```
+- palauttaa kaikki ensimmäiset arvot: ```Set<V>> firstValues()```
+- palauttaa kaikki toiset arvot: ```Set<W>> secondValues()```
+- testaa löytyykö määrätty avain; true, jos löytyy: ```boolean containsKey(Object key)```
+- testaa löytyykö määrätty arvopari; true, jos löytyy: ```boolean containsValue(Object value1, Object value2)```
+- testaa, onko triplettejä; true, jos löytyy: ```boolean isEmpty()```
+- montako triplettiä: ```int size()```
+
+
+***C.*** Implementoi tekemääsi Triplet-luokkaan TripletMap-rajapinta. Lisää kaikki vaaditut rutiinien 
+signatuurit Triplet-luokkaan.
+
+***D.*** Toteuta ryhmän 1 rutiinit.
+
+***E.*** Toteuta ryhmän 2 rutiinit.
+
+**Pisteytys**: 9 pistettä
+- A-kohta 2 pistettä
+- B-kohta 2 pistettä
+- C-kohta 1 pistettä
+- D-kohta 2 pistettä
+- E-kohta 2 pistettä
+
+
+## Tehtävä 5
+
+***A.*** Tutustu tehtäväpohjan luokkiin Ajoneuvo, HenkiloAuto ja KuormaAuto. Ajoneuvo-luokan geneerinen rutiini yhdista
+toteuttaa kahden yhdistämisen edellä kuvattujen luokkien kontekstissa:
+
+```Java
+   public static <X extends Z, Y extends Z, Z extends Ajoneuvo> Set<Z> yhdista(Set<X> xs, Set<Y> ys){
+        var tmp = new TreeSet<Z>();
+        for (var x : xs) tmp.add(x);
+        for (var y : ys) tmp.add(y);
+        return tmp;
+        }
+```
+
+Selitä, mitkä kaikki tyyppisignatuurit ovat yhteensopivia yhdistämisen tuloksena saadun listan kanssa. Luentomateriaalin
+osa 17 Geneerisyys ja varianssi (sivu 18) graafi auttaa ymmärtämään asiaa. 
+
+***B.*** Tutustu tehtäväpohjan luokkiin Ajoneuvo, HenkiloAuto ja KuormaAuto. Luokille on määritelty:
+```java
+abstract class Ajoneuvo {}
+class HenkiloAuto extends Ajoneuvo {}
+class KuormaAuto extends Ajoneuvo {}
+```
+
+Määritellään myös seuraavat joukot (Set):
+
+```java
+HashSet<Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>();
+HashSet<HenkiloAuto> henkiloautot = new HashSet<HenkiloAuto>();
+HashSet<KuormaAuto> kuormaautot = new HashSet<KuormaAuto>();
+```
+
+Selvitä, voidaanko listat henkiloautot ja kuormaautot lisätä listaan ajoneuvot (HashSet.addAll). Perustele geneerisyyteen, 
+varianssiin ja polymorfismiin nojaten, miksi lisäys onnistuu / ei onnistuu. Miksi listojen henkiloautot ja 
+kuormaautot viittausta ei voida kuitenkaan sijoittaa muuttujaan ajoneuvot? Miten määrittely tulisi 
+korjata, jotta sijoitus onnistuisi? Näytä ratkaisu koodina ja selosta myös, miksi ratkaisu toimii.
+
+**Pisteytys**: 4 pistettä  
+- A-kohta: 2 pistettä
+- B-kohta: 2 pistettä
diff --git a/bin/pom.xml b/bin/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8b003a2755e642ae52508738ed6dc2f9c121e09c
--- /dev/null
+++ b/bin/pom.xml
@@ -0,0 +1,348 @@
+<project>
+    <modelVersion>4.0.0</modelVersion>
+
+    <!--
+
+      Welcome!
+      This pom.xml is *THE* file that defines your Maven style Java project.
+
+      Eclipse, IDEA and other development environments with Maven support
+      or plugins can *import* this project by reading this file.
+
+      It usually contains tons of barely readable configuration. Luckily
+      this basic pom.xml is somewhat readable. All necessary configuration
+      for customizing your project if located here on top before the
+      'END OF SIMPLE CONFIGURATION' line below.
+
+    -->
+
+    <!-- ==== START OF SIMPLE CONFIGURATION ==== -->
+
+    <!-- The three parts of the artifact name -->
+    <groupId>fi.utu.tech</groupId>
+    <artifactId>ooj-exercise2</artifactId>
+    <version>1.0.0</version>
+
+    <!-- Additional information about the project -->
+    <name>DTEK0066 exercise set 2</name>
+    <url>https://gitlab.utu.fi/tech/education/ooj/ooj2023-exercise2</url>
+
+    <!-- We want to generate a jar. Don't change. -->
+    <packaging>jar</packaging>
+
+    <properties>
+        <!-- Configures the main class for this project (i.e. what to launch) -->
+        <project.mainclass>fi.utu.tech.ooj.exercise3.Main</project.mainclass>
+        <project.mainmodule>fi.utu.tech.ooj.exercise3</project.mainmodule>
+        <project.launcher>myapp</project.launcher>
+
+        <!-- The source encoding should always be utf-8. Don't change. -->
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
+        <!-- Version numbers for various modules -->
+        <jdk.version>17</jdk.version>
+        <jqwik.version>1.7.1</jqwik.version>
+        <junit.version>5.9.1</junit.version>
+        <junitplatform.version>1.9.1</junitplatform.version>
+    </properties>
+
+    <!-- ==== END OF SIMPLE CONFIGURATION ==== -->
+
+    <repositories>
+        <!-- https://search.maven.org/ -->
+        <repository>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <id>central</id>
+            <name>Central Repository</name>
+            <url>https://repo.maven.apache.org/maven2</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <version>${junit.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>${junit.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
+            <version>${junit.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-commons</artifactId>
+            <version>${junitplatform.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.jqwik</groupId>
+            <artifactId>jqwik</artifactId>
+            <version>${jqwik.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+              <groupId>com.diffplug.spotless</groupId>
+              <artifactId>spotless-maven-plugin</artifactId>
+              <version>2.29.0</version>
+              <configuration>
+                <formats>
+                    <format>
+                        <includes>src/**/*.java</includes>
+                        <prettier>
+                            <devDependencies>
+                                <prettier>2.8.1</prettier>
+                                <prettier-plugin-java>2.0.0</prettier-plugin-java>
+                            </devDependencies>
+                            <config>
+                                <tabWidth>4</tabWidth>
+                                <parser>java</parser>
+                            </config>
+                        </prettier>
+                    </format>
+                    <format>
+                        <includes>
+                            <include>pom.xml</include>
+                        </includes>
+                        <prettier>
+                            <devDependencyProperties>
+                                <property>
+                                    <name>prettier</name>
+                                    <value>2.8.1</value>
+                                </property>
+                                <property>
+                                    <name>@prettier/plugin-xml</name>
+                                    <value>2.2.0</value>
+                                </property>
+                            </devDependencyProperties>
+                            <config>
+                                <tabWidth>4</tabWidth>
+                                <printWidth>100</printWidth>
+                                <parser>xml</parser>
+                            </config>
+                        </prettier>
+                    </format>
+                  <format>
+                    <includes>
+                      <include>*.md</include>
+                      <include>.gitignore</include>
+                    </includes>
+                    <trimTrailingWhitespace />
+                    <endWithNewline />
+                    <indent>
+                      <spaces>true</spaces>
+                      <spacesPerTab>4</spacesPerTab>
+                    </indent>
+                  </format>
+                </formats>
+                <java>
+                    <includes>
+                      <include>src/**/*.java</include>
+                    </includes>
+                    <trimTrailingWhitespace />
+                    <endWithNewline />
+                    <indent>
+                        <spaces>true</spaces>
+                        <spacesPerTab>4</spacesPerTab>
+                    </indent>
+                  <importOrder />
+                  <removeUnusedImports />
+                  <googleJavaFormat>
+                    <version>1.15.0</version>
+                    <style>AOSP</style>
+                  </googleJavaFormat>
+                </java>
+              </configuration>
+            </plugin>
+
+            <!-- Run this app with exec:java -->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>3.1.0</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>java</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <mainClass>${project.mainclass}</mainClass>
+                </configuration>
+            </plugin>
+
+            <!-- Make the packaged jar executable -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.3.0</version>
+                <configuration>
+                  <!-- DO NOT include log4j.properties file in your Jar -->
+                  <excludes>
+                    <exclude>**/log4j.properties</exclude>
+                  </excludes>
+                  <archive>
+                    <manifest>
+                        <!-- Jar file entry point -->
+                        <mainClass>${project.mainclass}</mainClass>
+                    </manifest>
+                  </archive>
+                </configuration>
+            </plugin>
+
+
+            <!-- JDK source/target versions -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.10.1</version>
+
+                <configuration>
+                    <compilerArgument>-Xlint:unchecked</compilerArgument>
+                    <source>${jdk.version}</source>
+                    <target>${jdk.version}</target>
+                </configuration>
+            </plugin>
+
+            <!-- Also create a jar of the sources -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>3.2.1</version>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- JShell (jshell:run) -->
+            <plugin>
+                <groupId>com.github.johnpoth</groupId>
+                <artifactId>jshell-maven-plugin</artifactId>
+                <version>1.3</version>
+            </plugin>
+
+            <!-- UTU DbC Javadoc annotations -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>3.4.1</version>
+                <executions>
+                    <execution>
+                    <id>attach-javadocs</id>
+                    <goals>
+                        <goal>jar</goal>
+                    </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <tags>
+                        <tag>
+                            <name>toDo</name>
+                            <placement>a</placement>
+                            <head>To do:</head>
+                        </tag>
+                        <tag>
+                            <name>classInvariant</name>
+                            <placement>t</placement>
+                            <head>Class invariant:</head>
+                        </tag>
+                        <tag>
+                            <name>classInvariantProtected</name>
+                            <placement>t</placement>
+                            <head>Protected class invariant:</head>
+                        </tag>
+                        <tag>
+                            <name>classInvariantPrivate</name>
+                            <placement>t</placement>
+                            <head>Private class invariant:</head>
+                        </tag>
+                        <tag>
+                            <name>abstractionFunction</name>
+                            <placement>t</placement>
+                            <head>Abstraction function:</head>
+                        </tag>
+                        <tag>
+                            <name>pre</name>
+                            <placement>cm</placement>
+                            <head>Precondition:</head>
+                        </tag>
+                        <tag>
+                            <name>post</name>
+                            <placement>cm</placement>
+                            <head>Postcondition:</head>
+                        </tag>
+                        <tag>
+                            <name>postProtected</name>
+                            <placement>cm</placement>
+                            <head>Protected postcondition:</head>
+                        </tag>
+                        <tag>
+                            <name>postPrivate</name>
+                            <placement>cm</placement>
+                            <head>Private postcondition:</head>
+                        </tag>
+                        <tag>
+                            <name>time</name>
+                            <placement>cmf</placement>
+                            <head>Time complexity:</head>
+                        </tag>
+                        <tag>
+                            <name>space</name>
+                            <placement>cmf</placement>
+                            <head>Space complexity:</head>
+                        </tag>
+                        <tag>
+                            <name>correspondence</name>
+                            <placement>a</placement>
+                            <head>Correspondence:</head>
+                        </tag>
+                        <tag>
+                            <name>download</name>
+                            <placement>a</placement>
+                            <head>Download:</head>
+                        </tag>
+                    </tags>
+                    <show>protected</show>
+                    <failOnError>false</failOnError>
+                    <sourceFileExcludes>
+                        <sourceFileExclude>**/module-info.java</sourceFileExclude>
+                    </sourceFileExcludes>
+                </configuration>
+            </plugin>
+
+            <!-- JUnit & JQwik test integration -->
+
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.0.0-M7</version>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>3.0.0-M7</version>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/bin/public/favicon-32x32.png b/bin/public/favicon-32x32.png
new file mode 100644
index 0000000000000000000000000000000000000000..21764803741ed6b43008ed7494d0049764e8f42a
Binary files /dev/null and b/bin/public/favicon-32x32.png differ
diff --git a/bin/public/index.html b/bin/public/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..b998eb03fd45085ea30d07ae194b252530bb8d1c
--- /dev/null
+++ b/bin/public/index.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charSet="utf-8"/>
+<link rel="icon" href="favicon-32x32.png" type="image/png"/>
+<link rel="stylesheet" href="style.css">
+<title>UTU / OOJ project report</title>
+</head>
+<body>
+  <div class="layout">
+    <div class="layout-container">
+        <header>
+            <div class="header">
+                <div class="header-content">
+                    <a href="https://www.utu.fi">
+                      <img class="sitebranding" alt="University of Turku" src="utulogo.png" />
+                    </a>
+                    <nav>
+                        <ul>
+                        <li class="active"><a href="/">Report</a></li>
+                        </ul>
+                    </nav>
+                </div>
+            </div>
+        </header>
+      <div class="main-content">
+        <h2>Project report</h2>
+      </div>
+      <div class="main-content">
+        <iframe src="report.txt" title="Build"></iframe> 
+      </div>
+      <div class="main-content">
+        <iframe src="surefire-report.html" title="Surefire report"></iframe> 
+      </div>
+      <footer>
+        <div class="footer">
+            <div class="footer-content">
+                <a href="https://www.utu.fi">
+                  <img class="sitebranding" alt="University of Turku" src="utulogow.png"/>
+                </a>
+                <nav>
+                    <ul>
+                    <li>© 2019 <a href="https://soft.utu.fi/">Software engineering</a></li>
+                    </ul>
+                </nav>
+            </div>
+        </div>
+      </footer>
+    </div>
+  </div>
+</body>
+</html>
diff --git a/bin/public/style.css b/bin/public/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..7c9950b2e790b5966266508d7e888adb7dfa189c
--- /dev/null
+++ b/bin/public/style.css
@@ -0,0 +1,954 @@
+@font-face {
+  font-family: "brother-1816";
+  src: url("https://use.typekit.net/af/e4f93d/00000000000000003b9b03cb/27/l?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=i3&v=3") format("woff2"), url("https://use.typekit.net/af/e4f93d/00000000000000003b9b03cb/27/d?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=i3&v=3") format("woff"), url("https://use.typekit.net/af/e4f93d/00000000000000003b9b03cb/27/a?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=i3&v=3") format("opentype");
+  font-style: italic;
+  font-weight: 300;
+  font-display: auto;
+}
+
+@font-face {
+  font-family: "brother-1816";
+  src: url("https://use.typekit.net/af/deeb73/00000000000000003b9b03d0/27/l?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=n5&v=3") format("woff2"), url("https://use.typekit.net/af/deeb73/00000000000000003b9b03d0/27/d?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=n5&v=3") format("woff"), url("https://use.typekit.net/af/deeb73/00000000000000003b9b03d0/27/a?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=n5&v=3") format("opentype");
+  font-style: normal;
+  font-weight: 500;
+  font-display: auto;
+}
+
+@font-face {
+  font-family: "brother-1816";
+  src: url("https://use.typekit.net/af/f5cf85/00000000000000003b9b03d2/27/l?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=n7&v=3") format("woff2"), url("https://use.typekit.net/af/f5cf85/00000000000000003b9b03d2/27/d?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=n7&v=3") format("woff"), url("https://use.typekit.net/af/f5cf85/00000000000000003b9b03d2/27/a?primer=8c6cdece1802ac03951c30593622b1b6185a07621a4f8858e37fe29080c384e2&fvd=n7&v=3") format("opentype");
+  font-style: normal;
+  font-weight: 700;
+  font-display: auto;
+}
+
+:root {
+  --pageWidth: 894px;
+  --backgroundColor: #fff;
+  --colorUtu1: #8b5dcb;
+  --colorUtu2: #78c8d2;
+  --colorUtu3: #f8485e;
+  --colorUtu4: #adcb00;
+  --colorUtu5: #000;
+  --colorUtu6: #868686;
+  --colorUtu7: #b1b1b0;
+  --colorUtu8: #d9d9d9;
+  --colorUtu9: #ffffff;
+}
+
+html {
+    font: 120% brother-1816, sans-serif;
+    box-sizing: border-box;
+    overflow-y: scroll;
+    -ms-text-size-adjust: 100%;
+    -webkit-text-size-adjust: 100%;
+    margin: 0;
+    padding: 0;
+}
+
+.layout {
+    background-color: var(--colorUtu8);
+    padding-right:0;
+    padding-left:0;
+}
+
+.layout-container {
+    background-color: var(--colorUtu9);
+    margin: 0 auto;
+    max-width:100rem;
+}
+
+.main-content {
+    display: flex;
+    align-items: flex-start;
+    align-content: space-between;
+    flex-wrap: wrap;
+}
+
+.toc-container {
+    margin-left: -5em;
+    margin-right: 1em;
+    width: 20%;
+    flex-grow: 1;
+    position: sticky;
+    display: block;
+    border-radius: 15px;
+    padding: 0.5em;
+    padding-top: 2em;
+    padding-bottom: 2em;
+    background: var(--colorUtu8);
+    border: 2px solid var(--colorUtu5);
+}
+
+.toc-container a {
+    color: var(--colorUtu5);
+    text-decoration: none;
+}
+
+.toc-container a:hover {
+    color: var(--colorUtu5);
+    text-decoration: underline solid var(--colorUtu5);
+}
+
+.header a:hover {
+    color: var(--colorUtu5);
+    text-decoration: underline solid var(--colorUtu5);
+}
+
+.main-header {
+}
+
+.main-lecture {
+    max-width: 80%;
+}
+
+.main-content  {
+    flex-grow: 1;
+}
+
+@media (max-width:60em) {
+    .main-content {
+        display: block;
+    }
+    .main-lecture {
+        max-width: 100%;
+    }
+    .toc-container {
+        margin: 1em auto 1em auto;
+        padding: 0.5em;
+        width: 90%;
+    }
+}
+
+.lecture-grid-container {
+    display: grid;
+    grid-template-columns: auto auto;
+    border-top: 1px solid var(--colorUtu5);
+    border-bottom: 1px solid var(--colorUtu5);
+    padding: 2px;
+    align-items: center;
+    width: 100%;
+}
+
+.lecture-grid-container2 {
+    display: grid;
+    grid-template-columns: auto;
+    border-top: 1px solid var(--colorUtu5);
+    border-bottom: 1px solid var(--colorUtu5);
+    padding: 2px;
+    align-items: center;
+    width: 100%;
+}
+
+.lecture-grid-item {
+    border: 0;
+    padding: 10px;
+    font-size: 16px;
+    text-align: center;
+    max-width: 100%;
+    margin: 0 auto;
+}
+
+.controls-right button {
+  margin-left: 0.5em;
+}
+
+.controls-left button {
+  margin-right: 0.5em;
+}
+
+
+.lecture-grid-item2:first-child {
+    border-right: 2px solid var(--colorUtu8);
+}
+
+@media (min-width:50em) {
+    .layout {
+        padding-right: 2em;
+        padding-left: 2em;
+    }
+    .main-content {
+        padding-right: 2.5em;
+        padding-left: 2.5em;
+        padding-bottom: 2.5em;
+    }
+}
+
+@media (min-width:60em) {
+    .layout {
+        padding-right: 3em;
+        padding-left: 3em;
+    }
+    .main-content {
+        padding-right: 3.25em;
+        padding-left: 3.25em;
+        padding-bottom: 3.25em;
+    }
+}
+
+@media (min-width:80em) {
+    .layout {
+        padding-right: 4em;
+        padding-left: 4em;
+    }
+    .main-content {
+        padding-right: 4em;
+        padding-left: 4em;
+        padding-bottom: 4em;
+    }
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+main,
+menu,
+nav,
+section,
+summary {
+  display: block;
+}
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+}
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+progress {
+  vertical-align: baseline;
+}
+[hidden],
+template {
+  display: none;
+}
+a {
+  background-color: transparent;
+  -webkit-text-decoration-skip: objects;
+}
+a:active,
+a:hover {
+  outline-width: 0;
+}
+abbr[title] {
+  border-bottom: none;
+  text-decoration: underline;
+  text-decoration: underline dotted;
+}
+b,
+strong {
+  font-weight: inherit;
+  font-weight: bolder;
+}
+dfn {
+  font-style: italic;
+}
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+mark {
+  background-color: #ff0;
+  color: #000;
+}
+small {
+  font-size: 80%;
+}
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+sub {
+  bottom: -0.25em;
+}
+sup {
+  top: -0.5em;
+}
+img {
+  border-style: none;
+}
+svg:not(:root) {
+  overflow: hidden;
+}
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+figure {
+  margin: 1em 40px;
+}
+hr {
+  box-sizing: content-box;
+  height: 0;
+  overflow: visible;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+  font: inherit;
+  margin: 0;
+}
+optgroup {
+  font-weight: 700;
+}
+button,
+input {
+  overflow: visible;
+}
+button,
+select {
+  text-transform: none;
+}
+[type="reset"],
+[type="submit"],
+button,
+html [type="button"] {
+  -webkit-appearance: button;
+}
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner,
+button::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring,
+button:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+fieldset {
+  border: 1px solid silver;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+legend {
+  box-sizing: border-box;
+  color: inherit;
+  display: table;
+  max-width: 100%;
+  padding: 0;
+  white-space: normal;
+}
+textarea {
+  overflow: auto;
+}
+[type="checkbox"],
+[type="radio"] {
+  box-sizing: border-box;
+  padding: 0;
+}
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+[type="search"] {
+  -webkit-appearance: textfield;
+  outline-offset: -2px;
+}
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.54;
+}
+::-webkit-file-upload-button {
+  -webkit-appearance: button;
+  font: inherit;
+}
+* {
+  box-sizing: inherit;
+}
+*:before {
+  box-sizing: inherit;
+}
+*:after {
+  box-sizing: inherit;
+}
+body {
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+    margin: 0;
+    padding: 0;
+    color: hsla(0, 0%, 0%, 0.8);
+    font-weight: normal;
+    word-wrap: break-word;
+    font-kerning: normal;
+    -moz-font-feature-settings: "kern", "liga", "clig", "calt";
+    -ms-font-feature-settings: "kern", "liga", "clig", "calt";
+    -webkit-font-feature-settings: "kern", "liga", "clig", "calt";
+    font-feature-settings: "kern", "liga", "clig", "calt";
+}
+img {
+  max-width: 100%;
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+h1 {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  color: inherit;
+  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+  font-weight: bold;
+  text-rendering: optimizeLegibility;
+  font-size: 2.25rem;
+  line-height: 1.1;
+}
+h2 {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  color: inherit;
+  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+  font-weight: bold;
+  text-rendering: optimizeLegibility;
+  font-size: 1.62671rem;
+  line-height: 1.1;
+}
+h3 {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  color: inherit;
+  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+  font-weight: bold;
+  text-rendering: optimizeLegibility;
+  font-size: 1.38316rem;
+  line-height: 1.1;
+}
+h4 {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  color: inherit;
+  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+  font-weight: bold;
+  text-rendering: optimizeLegibility;
+  font-size: 1rem;
+  line-height: 1.1;
+}
+h5 {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  color: inherit;
+  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+  font-weight: bold;
+  text-rendering: optimizeLegibility;
+  font-size: 0.85028rem;
+  line-height: 1.1;
+}
+h6 {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  color: inherit;
+  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+  font-weight: bold;
+  text-rendering: optimizeLegibility;
+  font-size: 0.78405rem;
+  line-height: 1.1;
+}
+hgroup {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+ul {
+  margin-left: 1.45rem;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  list-style-position: outside;
+  list-style-image: none;
+}
+ol {
+  margin-left: 1.45rem;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  list-style-position: outside;
+  list-style-image: none;
+}
+dl {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+dd {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+p {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+figure {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+pre {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  margin-bottom: 1.45rem;
+  font-size: 0.85rem;
+  line-height: 1.42;
+  background: hsla(0, 0%, 0%, 0.04);
+  border-radius: 3px;
+  overflow: auto;
+  word-wrap: normal;
+  padding: 1.45rem;
+}
+table {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  font-size: 1rem;
+  line-height: 1.45rem;
+  border-collapse: collapse;
+  width: 100%;
+}
+fieldset {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+blockquote {
+  margin-left: 1.45rem;
+  margin-right: 1.45rem;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+form {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+noscript {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+iframe {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+  width: 100%;
+  min-height: 90vh;
+}
+hr {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: calc(1.45rem - 1px);
+  background: hsla(0, 0%, 0%, 0.2);
+  border: none;
+  height: 1px;
+}
+address {
+  margin-left: 0;
+  margin-right: 0;
+  margin-top: 0;
+  padding-bottom: 0;
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  margin-bottom: 1.45rem;
+}
+b {
+  font-weight: bold;
+}
+strong {
+  font-weight: bold;
+}
+dt {
+  font-weight: bold;
+}
+th {
+  font-weight: bold;
+}
+li {
+  margin-bottom: calc(1.45rem / 2);
+}
+ol li {
+  padding-left: 0;
+}
+ul li {
+  padding-left: 0;
+}
+li > ol {
+  margin-left: 1.45rem;
+  margin-bottom: calc(1.45rem / 2);
+  margin-top: calc(1.45rem / 2);
+}
+li > ul {
+  margin-left: 1.45rem;
+  margin-bottom: calc(1.45rem / 2);
+  margin-top: calc(1.45rem / 2);
+}
+blockquote *:last-child {
+  margin-bottom: 0;
+}
+li *:last-child {
+  margin-bottom: 0;
+}
+p *:last-child {
+  margin-bottom: 0;
+}
+li > p {
+  margin-bottom: calc(1.45rem / 2);
+}
+code {
+  font-size: 0.85rem;
+  line-height: 1.45rem;
+}
+kbd {
+  font-size: 0.85rem;
+  line-height: 1.45rem;
+}
+samp {
+  font-size: 0.85rem;
+  line-height: 1.45rem;
+}
+abbr {
+  border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
+  cursor: help;
+}
+acronym {
+  border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
+  cursor: help;
+}
+abbr[title] {
+  border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
+  cursor: help;
+  text-decoration: none;
+}
+thead {
+  text-align: left;
+}
+td,
+th {
+  text-align: left;
+  border-bottom: 1px solid hsla(0, 0%, 0%, 0.12);
+  font-feature-settings: "tnum";
+  -moz-font-feature-settings: "tnum";
+  -ms-font-feature-settings: "tnum";
+  -webkit-font-feature-settings: "tnum";
+  padding-left: 0.96667rem;
+  padding-right: 0.96667rem;
+  padding-top: 0.725rem;
+  padding-bottom: calc(0.725rem - 1px);
+}
+th:first-child,
+td:first-child {
+  padding-left: 0;
+}
+th:last-child,
+td:last-child {
+  padding-right: 0;
+}
+tt,
+code {
+  background-color: hsla(0, 0%, 0%, 0.04);
+  border-radius: 3px;
+  font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono",
+    "Liberation Mono", Menlo, Courier, monospace;
+  padding: 0;
+  padding-top: 0.2em;
+  padding-bottom: 0.2em;
+}
+pre code {
+  background: none;
+  line-height: 1.42;
+}
+code:before,
+code:after,
+tt:before,
+tt:after {
+  letter-spacing: -0.2em;
+  content: " ";
+}
+pre code:before,
+pre code:after,
+pre tt:before,
+pre tt:after {
+  content: "";
+}
+@media only screen and (max-width: 480px) {
+  html {
+    font-size: 100%;
+  }
+}
+
+
+header, footer {
+    padding-top: 0.6rem;
+    padding-bottom: 0.6rem;
+}
+
+footer {
+    background: var(--colorUtu5);
+    color: var(--colorUtu9);
+}
+
+.header, .footer {
+    font-size: 87.4975%;
+    padding-left: 3.25rem;
+    padding-bottom: 0.875rem;
+    padding-right: 3.25rem;
+    padding-top: 0.875rem;
+}
+
+.header-content {
+    width: 100%;
+    border-bottom: 1px solid var(--colorUtu8);
+    display: flex;
+    flex-wrap: wrap;
+    align-items: flex-end;
+    justify-content: space-between;
+}
+
+.footer-content {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    align-items: flex-start;
+    justify-content: space-between;
+}
+
+.header nav, .footer nav {
+    display: block;
+    flex: 1 0 auto;
+    padding-bottom: 0.5em;
+}
+
+.footer nav {
+    display: block;
+    flex: 1 0 auto;
+    padding-top: 0.5em;
+    padding-bottom: 0;
+}
+
+.header ul, .footer ul {
+    float: right;
+    margin: 0 -0.5em;
+    padding: 0;
+    display: flex;
+}
+
+.header li, .footer li {
+    list-style: none;
+    padding: 0;
+    margin: 0 1em;
+    text-transform: uppercase;
+    font-weight: bold;
+}
+
+.header a {
+    color: var(--colorUtu5);
+    text-decoration: none;
+}
+
+.footer a {
+    color: var(--colorUtu9);
+    text-decoration: none;
+}
+
+.header a:hover {
+    color: var(--colorUtu5);
+    text-decoration: underline solid var(--colorUtu5);
+}
+.header .active {
+    color: var(--colorUtu5);
+    text-decoration: underline solid var(--colorUtu5);
+}
+
+.footer a:hover {
+    color: var(--colorUtu9);
+    text-decoration: underline solid var(--colorUtu9);
+}
+
+.sitebranding {
+    width: 14.040rem;
+    height: 3.967rem;
+    flex: 0 0 auto;
+    flex-shrink: 0;
+    margin: 0;
+    margin-bottom: 1em;
+}
+
+@media (min-width:50em) {
+    .header, .footer {
+        font-size: 91.665%;
+        padding-left: 3.1rem;
+        padding-bottom: 0.94rem;
+        padding-right: 3.1rem;
+        padding-top: 0.94rem;
+    }
+
+    .sitebranding {
+        width: 15.100rem;
+        height: 4.267rem;
+    }
+}
+
+@media (min-width:60em) {
+    .header, .footer {
+        font-size: 87.4975%;
+        padding-left: 4rem;
+        padding-bottom: 1.1rem;
+        padding-right: 4rem;
+        padding-top: 1.1rem;
+    }
+
+    .sitebranding {
+        width: 16.400rem;
+        height: 4.634rem;
+    }
+}
+
+@media (min-width:80em) {
+    .header, .footer {
+        font-size: 83.33%;
+        padding-left: 5rem;
+        padding-bottom: 1.25rem;
+        padding-right: 5rem;
+        padding-top: 1.25rem;
+    }
+
+    .sitebranding {
+        width: 17.700rem;
+        height: 5.002rem;
+    }
+}
diff --git a/bin/public/utulogo.png b/bin/public/utulogo.png
new file mode 100644
index 0000000000000000000000000000000000000000..494f01eb239e7e41aed7e816ebdb377e6e4774ac
Binary files /dev/null and b/bin/public/utulogo.png differ
diff --git a/bin/public/utulogow.png b/bin/public/utulogow.png
new file mode 100644
index 0000000000000000000000000000000000000000..f0af24f59fcf77e473d30a16218bde35e5d1dca7
Binary files /dev/null and b/bin/public/utulogow.png differ
diff --git a/bin/report.sh b/bin/report.sh
new file mode 100644
index 0000000000000000000000000000000000000000..38d80d1aef9b992054770be0b90243771fc2350d
--- /dev/null
+++ b/bin/report.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+find src > public/report.txt
+mvn clean test 2>&1 >> public/report.txt
+mvn surefire-report:report
+cp target/site/surefire-report.html public/
diff --git a/bin/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.class b/bin/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.class
new file mode 100644
index 0000000000000000000000000000000000000000..f67d82390b3b5d27a5b95d40314d025e587a27fb
Binary files /dev/null and b/bin/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.class differ
diff --git a/bin/src/main/java/fi/utu/tech/ooj/exercise3/HenkiloAuto.class b/bin/src/main/java/fi/utu/tech/ooj/exercise3/HenkiloAuto.class
new file mode 100644
index 0000000000000000000000000000000000000000..384762e1746ab2f8a9d221649609c80ba3eefa53
Binary files /dev/null and b/bin/src/main/java/fi/utu/tech/ooj/exercise3/HenkiloAuto.class differ
diff --git a/bin/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.class b/bin/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.class
new file mode 100644
index 0000000000000000000000000000000000000000..2b1da5a35a4f936c7c00ec398d90122284c616a3
Binary files /dev/null and b/bin/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.class differ
diff --git a/bin/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.class b/bin/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.class
new file mode 100644
index 0000000000000000000000000000000000000000..89c029f6040cf337f914c53a88f4622105a1c073
Binary files /dev/null and b/bin/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.class differ
diff --git a/bin/src/main/java/fi/utu/tech/ooj/exercise3/KirjanTiedot.class b/bin/src/main/java/fi/utu/tech/ooj/exercise3/KirjanTiedot.class
new file mode 100644
index 0000000000000000000000000000000000000000..0c91773e27150269f30e58e78435fe60266a8002
Binary files /dev/null and b/bin/src/main/java/fi/utu/tech/ooj/exercise3/KirjanTiedot.class differ
diff --git a/bin/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.class b/bin/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.class
new file mode 100644
index 0000000000000000000000000000000000000000..4876d6260a323b57bbab9354c689834a4aa69ceb
Binary files /dev/null and b/bin/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.class differ
diff --git a/bin/src/main/java/fi/utu/tech/ooj/exercise3/KuormaAuto.class b/bin/src/main/java/fi/utu/tech/ooj/exercise3/KuormaAuto.class
new file mode 100644
index 0000000000000000000000000000000000000000..ecc9f6b531eba826ee8bb3ae8e1f53ac8643f834
Binary files /dev/null and b/bin/src/main/java/fi/utu/tech/ooj/exercise3/KuormaAuto.class differ
diff --git a/bin/src/main/java/fi/utu/tech/ooj/exercise3/Main.class b/bin/src/main/java/fi/utu/tech/ooj/exercise3/Main.class
new file mode 100644
index 0000000000000000000000000000000000000000..0bd414f726473f1fa33edf038a2ab89a13131f1f
Binary files /dev/null and b/bin/src/main/java/fi/utu/tech/ooj/exercise3/Main.class differ
diff --git a/bin/src/test/resources/jqwik.properties b/bin/src/test/resources/jqwik.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java b/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java
deleted file mode 100644
index 285fd40c2145f3fa3ce10f18412afb657fe48f5e..0000000000000000000000000000000000000000
--- a/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package fi.utu.tech.ooj.exercise3;
-
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.List;
-
-public class KirjaKokoelma {
-
-    private String kokoelmanNimi;
-    private  ArrayList<Kirja>kirjaListaus;
-
-    public KirjaKokoelma(String kokoelmanNimi) {
-        this.kokoelmanNimi = kokoelmanNimi;
-        this.kirjaListaus = new ArrayList<>();
-    }
-
-    public String getkokoelmanNimi() {
-        return kokoelmanNimi;
-    }
-
-    public void setkokoelmanNimi(String kokoelmanOmistaja) {
-        this.kokoelmanNimi = kokoelmanNimi;
-    }
-
-    public ArrayList<Kirja> getKirjaListaus() {
-        return kirjaListaus;
-    }
-
-    public void lisaaKirja(Kirja teos) {
-        kirjaListaus.add(teos);
-    }
-
-}
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Main.java b/src/main/java/fi/utu/tech/ooj/exercise3/Main.java
index 0c5fb2a608860ddf2225d92690eafd616fb4c96c..6bda83503086fd20f2ceb49a6214fc906ec80d1c 100644
--- a/src/main/java/fi/utu/tech/ooj/exercise3/Main.java
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/Main.java
@@ -1,28 +1,5 @@
 package fi.utu.tech.ooj.exercise3;
 
-
-import java.util.HashMap;
-import java.util.HashSet;
-
 public class Main {
-
-
-    /**
-     * Main class.
-     *
-     * @param args Command line arguments
-     */
-
-
-    public static void main(String[] args) {
-        /*
-         * Testin jälkeen alla olevan rivin voi joko kommentoida tai poistaa.
-         */
-        System.out.println("*** Harjoitustyöpohja käynnistyy ***");
-
-        HashSet<Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>();
-        HashSet<HenkiloAuto> henkiloautot = new HashSet<HenkiloAuto>();
-        HashSet<KuormaAuto> kuormaautot = new HashSet<KuormaAuto>();
-
-    }
+	
 }
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1/tehtava1 b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1/tehtava1
new file mode 100644
index 0000000000000000000000000000000000000000..37e1930d5cdfed8b9d042c5c1d534c3755ffc271
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava1/tehtava1
@@ -0,0 +1,19 @@
+Tehtävä 1
+
+A. Molempia käytetään arvojen säilyttämiseen. Collection säilyttää arvoja peräkkäin, jossa jokaisella on oma indeksi.
+Map sen sijaan säilöö arvoja avain/arvo pareina. Silloin jokaiselle arvolle voidaan itse määrittää sitä vastaava avain
+
+B. List, Set ja Queue ovat kaikki muodoltaan collectioneita. List voi sisältää duplikaatti arvoja ja sillä on useita
+rutiineita, jolla voidaan tietorakennetta voidaan manipuloida. Set on lähes kuin List, mutta Set ei voi sisältää
+duplikaatteja. Queue käsitellään yleensä FIFO periatteella ja täten sillä on omia lisättyjä rutiineita, jotka noudattavat
+FIFO periaatetta.
+
+C. ArrayList ja LinkedList ovat molemmat List tyylisiä, mutta ne kuitenkin eroavat sillä miten ne tallentavat tietonsa.
+ArrayList käyttää elementtien tallentamiseen dynamic arrayta, mutta LinkedList tallentaa elementit käyttäen
+doubly linked list rakennetta. Rakenteet eroavat siten, että jos esimerkiksi ArrayListista halutaan poistaa alkio
+pitää kaikki muut alkiot liikuttaa yhden muistipaikan joko eteen tai taakse. Kun taas LinkedList voi suorittaa vastaavan
+operaation siten, että muita elementtejä ei tarvitse siirtää, koska vain viittaus voidaan siirtää joko edelliseen tai
+seuraavaan alkioon.
+
+D. HashSet ja TreeSet ovat molemmat Collectioneita, mutta niiden ero on se, että HashSet on järjestämätön ja TreeSet
+on järjestetty.
\ No newline at end of file
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Kirja.java
similarity index 50%
rename from src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java
rename to src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Kirja.java
index 13d735cebecb2492da4cdc2f967aed46ea347313..0151196e19228be11991dc330abe1dc374bf4f12 100644
--- a/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Kirja.java
@@ -1,4 +1,6 @@
-package fi.utu.tech.ooj.exercise3;
+package fi.utu.tech.ooj.exercise3.tehtava2;
+
+import java.util.Objects;
 
 public class Kirja {
     private String kirjanNimi;
@@ -35,5 +37,32 @@ public class Kirja {
         this.julkaisuVuosi = julkaisuVuosi;
     }
 
-
+    public Kirja clone() {
+    	return new Kirja(kirjanNimi, kirjailijanNimi, julkaisuVuosi);
+    }
+    
+    @Override
+    public String toString() {
+    	return "Kirjan nimi: " + kirjanNimi + "\n Kirjailijan nimi: " + kirjailijanNimi + "\n Julkaisuvuosi: " + julkaisuVuosi;
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+    	if (this == o) {
+    		return true;
+    	}
+    	
+    	if (this == null || getClass() != o.getClass()) {
+    		return false;
+    	}
+    	
+    	Kirja kirja = (Kirja) o;
+    	
+    	return kirjanNimi.equals(kirja.kirjanNimi) && kirjailijanNimi.equals(kirja.kirjailijanNimi) && julkaisuVuosi == kirja.julkaisuVuosi;
+    }
+    
+    @Override
+    public int hashCode() {
+    	return Objects.hash(kirjanNimi, kirjailijanNimi, julkaisuVuosi);
+    }
 }
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/KirjaKokoelma.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/KirjaKokoelma.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f31c86242caa92ad9f9d25a07a9318a4aa70079
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/KirjaKokoelma.java
@@ -0,0 +1,68 @@
+package fi.utu.tech.ooj.exercise3.tehtava2;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class KirjaKokoelma {
+
+    private String kokoelmanNimi;
+    private  ArrayList<Kirja>kirjaListaus;
+
+    public KirjaKokoelma(String kokoelmanNimi) {
+        this.kokoelmanNimi = kokoelmanNimi;
+        this.kirjaListaus = new ArrayList<>();
+    }
+
+    public String getkokoelmanNimi() {
+        return kokoelmanNimi;
+    }
+
+    public void setkokoelmanNimi(String kokoelmanOmistaja) {
+        this.kokoelmanNimi = kokoelmanNimi;
+    }
+
+    public ArrayList<Kirja> getKirjaListaus() {
+        return kirjaListaus;
+    }
+
+    public void lisaaKirja(Kirja teos) {
+        kirjaListaus.add(teos);
+    }
+
+    public KirjaKokoelma clone() {
+    	KirjaKokoelma uusi = new KirjaKokoelma(kokoelmanNimi);
+    	
+    	for(Kirja kirja : kirjaListaus) {
+    		uusi.lisaaKirja(kirja);
+    	}
+    	
+    	return uusi;
+    }
+    
+    @Override
+    public String toString() {
+    	return "Kokoelman nimi: " + kokoelmanNimi + "\n Kirjalistaus: " + kirjaListaus.toString();
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+    	if (this == o) {
+    		return true;
+    	}
+    	
+    	if (this == null || getClass() != o.getClass()) {
+    		return false;
+    	}
+    	
+    	KirjaKokoelma kokoelma = (KirjaKokoelma) o;
+    	
+    	return kokoelmanNimi.equals(kokoelma.kokoelmanNimi) && kirjaListaus.equals(kokoelma.kirjaListaus);
+    }
+    
+    @Override
+    public int hashCode() {
+    	return Objects.hash(kokoelmanNimi, kirjaListaus);
+    }
+}
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/KirjanTiedot.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/KirjanTiedot.java
similarity index 76%
rename from src/main/java/fi/utu/tech/ooj/exercise3/KirjanTiedot.java
rename to src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/KirjanTiedot.java
index 7cb6187acaf11e16827a0f54879459fd484dda94..fb86242df3720b5cc43ca5ae2f229e4e8a09dbba 100644
--- a/src/main/java/fi/utu/tech/ooj/exercise3/KirjanTiedot.java
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/KirjanTiedot.java
@@ -1,4 +1,4 @@
-package fi.utu.tech.ooj.exercise3;
+package fi.utu.tech.ooj.exercise3.tehtava2;
 
 /*
  * Literaaliluokka, joka listaa kirjaa liittyvät tietokentät
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Kirjasto.java
similarity index 58%
rename from src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java
rename to src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Kirjasto.java
index 2478ff6351648daef8b963f175230b13d1aa3569..9d3cbf8063ac2b80b9a5326a74866a96e8e9629e 100644
--- a/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Kirjasto.java
@@ -1,8 +1,9 @@
-package fi.utu.tech.ooj.exercise3;
+package fi.utu.tech.ooj.exercise3.tehtava2;
 
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 public class Kirjasto {
@@ -57,5 +58,42 @@ public class Kirjasto {
         sivukirjastot.add(input);
     }
 
-
+    public Kirjasto clone() {
+    	Kirjasto uusi = new Kirjasto(kirjastonNimi, osoite);
+    	
+    	for(Kirjasto kirjasto : sivukirjastot) {
+    		uusi.lisaaSivukirjasto(kirjasto.clone());
+    	}
+    	
+    	for(KirjaKokoelma kokoelma : kokoelmat) {
+    		uusi.lisaaKokoelma(kokoelma.clone());
+    	}
+    	
+    	return uusi;
+    }
+    
+    @Override
+    public String toString() {
+    	return "Kirjaston nimi: " + kirjastonNimi + "\n Osoite: " + osoite + "\n Kokoelmat: " + kokoelmat.toString() + "\n Sivukirjastot: " + sivukirjastot.toString();
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+    	if (this == o) {
+    		return true;
+    	}
+    	
+    	if (this == null || getClass() != o.getClass()) {
+    		return false;
+    	}
+    	
+    	Kirjasto kirjasto = (Kirjasto) o;
+    	
+    	return kirjastonNimi.equals(kirjasto.kirjastonNimi) && osoite.equals(kirjasto.osoite) && kokoelmat.equals(kirjasto.kokoelmat) && sivukirjastot.equals(kirjasto.sivukirjastot);
+    }
+    
+    @Override
+    public int hashCode() {
+    	return Objects.hash(kirjastonNimi, osoite, kokoelmat, sivukirjastot);
+    }
 }
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Main.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..cfac1c19ec95fc25df442d03995740ffdaac6259
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Main.java
@@ -0,0 +1,80 @@
+package fi.utu.tech.ooj.exercise3.tehtava2;
+
+public class Main {
+	public static void main(String[] args) {
+		Kirjasto paaKirjasto = new Kirjasto("Pääkirjasto", "Kirkkotie 2");
+		
+		Kirjasto sivuKirjasto1 = new Kirjasto("Sivukirjasto 1", "Sivukirjastontie 1");
+		
+		Kirjasto sivuKirjasto2 = new Kirjasto("Sivukirjasto 2", "Sivukirjastontie 2");
+		
+		KirjaKokoelma kokoelma1 = new KirjaKokoelma("Kokoelma 1");
+		
+		KirjaKokoelma kokoelma2 = new KirjaKokoelma("Kokoelma 2");
+		
+		KirjaKokoelma kokoelma3 = new KirjaKokoelma("Kokoelma 3");
+		
+		KirjaKokoelma kokoelma4 = new KirjaKokoelma("Kokoelma 4");
+		
+		KirjaKokoelma kokoelma5 = new KirjaKokoelma("Kokoelma 5");
+		
+		KirjaKokoelma kokoelma6 = new KirjaKokoelma("Kokoelma 6");
+		
+		Kirja kirja1 = new Kirja("Kirja 1", "Kirjailija", 2023);
+		
+		Kirja kirja2 = new Kirja("Kirja 2", "Kirjailija", 2023);
+		
+		Kirja kirja3 = new Kirja("Kirja 3", "Kirjailija", 2023);
+		
+		Kirja kirja4 = new Kirja("Kirja 4", "Kirjailija", 2023);
+		
+		Kirja kirja5 = new Kirja("Kirja 5", "Kirjailija", 2023);
+		
+		Kirja kirja6 = new Kirja("Kirja 6", "Kirjailija", 2023);
+		
+		Kirja kirja7 = new Kirja("Kirja 7", "Kirjailija", 2023);
+		
+		Kirja kirja8 = new Kirja("Kirja 8", "Kirjailija", 2023);
+		
+		Kirja kirja9 = new Kirja("Kirja 9", "Kirjailija", 2023);
+		
+		Kirja kirja10 = new Kirja("Kirja 10", "Kirjailija", 2023);
+		
+		Kirja kirja11 = new Kirja("Kirja 11", "Kirjailija", 2023);
+		
+		Kirja kirja12 = new Kirja("Kirja 12", "Kirjailija", 2023);
+		
+		kokoelma1.lisaaKirja(kirja1);
+		kokoelma1.lisaaKirja(kirja2);
+		
+		kokoelma2.lisaaKirja(kirja3);
+		kokoelma2.lisaaKirja(kirja4);
+		
+		kokoelma3.lisaaKirja(kirja5);
+		kokoelma3.lisaaKirja(kirja6);
+		
+		kokoelma4.lisaaKirja(kirja7);
+		kokoelma4.lisaaKirja(kirja8);
+		
+		kokoelma5.lisaaKirja(kirja9);
+		kokoelma5.lisaaKirja(kirja10);
+		
+		kokoelma6.lisaaKirja(kirja11);
+		kokoelma6.lisaaKirja(kirja12);
+		
+		paaKirjasto.lisaaKokoelma(kokoelma1);
+		paaKirjasto.lisaaKokoelma(kokoelma2);
+		
+		sivuKirjasto1.lisaaKokoelma(kokoelma3);
+		sivuKirjasto1.lisaaKokoelma(kokoelma4);
+		
+		sivuKirjasto2.lisaaKokoelma(kokoelma5);
+		sivuKirjasto2.lisaaKokoelma(kokoelma6);
+		
+		paaKirjasto.lisaaSivukirjasto(sivuKirjasto1);
+		paaKirjasto.lisaaSivukirjasto(sivuKirjasto2);
+		
+		System.out.println(paaKirjasto.toString());
+		System.out.println(paaKirjasto.equals(paaKirjasto.clone()));
+	}
+}
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava3/Main.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava3/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..b5a49c6ecad8475dcae01be7a6a97846d80e1c2d
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava3/Main.java
@@ -0,0 +1,19 @@
+package fi.utu.tech.ooj.exercise3.tehtava3;
+
+import java.util.HashMap;
+
+public class Main {
+	public static void main(String[] args) {
+		RandomMap rmap = new RandomMap<String, String>(new HashMap<String, String>());
+		
+		rmap.put("eka", "first");
+		rmap.put("toka", "second");
+		rmap.put("kolmas", "third");
+		rmap.put("neljäs", "fourth");
+		
+		System.out.println(rmap.get("toka"));
+		
+		System.out.println(rmap.get("viides"));
+		System.out.println(rmap.get("viides"));
+	}
+}
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava3/RandomMap.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava3/RandomMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..bba49e79dcc30d6d32ed201aed8b320006b4dac5
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava3/RandomMap.java
@@ -0,0 +1,83 @@
+package fi.utu.tech.ooj.exercise3.tehtava3;
+import java.util.*;
+
+public class RandomMap<K, V> implements Map<K, V> {
+	private Map<K, V> map;
+	
+	public RandomMap(Map<K, V> map) {
+		this.map = map;
+	}
+
+	@Override
+	public int size() {
+		return map.size();
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return map.isEmpty();
+	}
+
+	@Override
+	public boolean containsKey(Object key) {
+		return map.containsKey(key);
+	}
+
+	@Override
+	public boolean containsValue(Object value) {
+		return map.containsValue(value);
+	}
+
+	@Override
+	public V get(Object key) {
+		if (map.containsKey(key)) {
+			return map.get(key);
+		}
+		
+		ArrayList<V> values = new ArrayList<>(map.values());
+		
+		if (values.isEmpty()) {
+			return null;
+		}
+		
+		Random r = new Random();
+		int i = r.nextInt(values.size());
+		
+		return values.get(i);
+	}
+
+	@Override
+	public V put(K key, V value) {
+		return map.put(key, value);
+	}
+
+	@Override
+	public V remove(Object key) {
+		return map.remove(key);
+	}
+
+	@Override
+	public void putAll(Map<? extends K, ? extends V> m) {
+		map.putAll(m);
+	}
+
+	@Override
+	public void clear() {
+		map.clear();
+	}
+
+	@Override
+	public Set<K> keySet() {
+		return map.keySet();
+	}
+
+	@Override
+	public Collection<V> values() {
+		return map.values();
+	}
+
+	@Override
+	public Set<Entry<K, V>> entrySet() {
+		return map.entrySet();
+	}
+}
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava4/Triplet.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava4/Triplet.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e1d306bcd40178c8db43062f2d0112ef475afad
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava4/Triplet.java
@@ -0,0 +1,106 @@
+package fi.utu.tech.ooj.exercise3.tehtava4;
+
+import java.util.*;
+
+public class Triplet<K, V, W> implements TripletMap<K, V, W> {
+
+	private Map<K, Pair<V, W>> map;
+	
+	public Triplet() {
+		this.map = new HashMap<>();
+	}
+	
+	@Override
+	public void put(K key, V value1, W value2) {
+		this.map.put(key, new Pair<V, W>(value1, value2));
+	}
+
+	@Override
+	public V getFirstValue(K key) {
+		Pair<V, W> pair = this.map.get(key);
+		
+		if (pair != null) {
+			return pair.first();
+		}
+		
+		return null;
+	}
+
+	@Override
+	public W getSecondValue(K key) {
+		Pair<V, W> pair = this.map.get(key);
+		
+		if (pair != null) {
+			return pair.second();
+		}
+		
+		return null;
+	}
+
+	@Override
+	public void remove(K key) {
+		this.map.remove(key);
+	}
+
+	@Override
+	public void clear() {
+		this.map.clear();
+	}
+
+	@Override
+	public Set<K> keySet() {
+		return this.map.keySet();
+	}
+
+	@Override
+	public Set<V> firstValues() {
+		Set<V> firstValues = new HashSet<>();
+		
+		for (Pair<V, W> pair : this.map.values()) {
+			firstValues.add(pair.first());
+		}
+		
+		return firstValues;
+	}
+
+	@Override
+	public Set<W> secondValues() {
+		Set<W> secondValues = new HashSet<>();
+		
+		for (Pair<V, W> pair : this.map.values()) {
+			secondValues.add(pair.second());
+		}
+		
+		return secondValues;
+	}
+
+	@Override
+	public boolean containsKey(Object key) {
+		return this.map.containsKey(key);
+	}
+
+	@Override
+	public boolean containsValue(Object value1, Object value2) {
+		for (Pair<V, W> pair : this.map.values()) {
+			if (pair.first().equals(value1) && pair.second().equals(value2)) {
+				return true;
+			}
+		}
+		
+		return false;
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return this.map.isEmpty();
+	}
+
+	@Override
+	public int size() {
+		return this.map.size();
+	}
+	
+	private record Pair<X, Y>(X first, Y second) {
+		
+	}
+}
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava4/TripletMap.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava4/TripletMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e5d7e4a3afe9967ebb376062d98a05d5ab337b7
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava4/TripletMap.java
@@ -0,0 +1,21 @@
+package fi.utu.tech.ooj.exercise3.tehtava4;
+
+import java.util.Set;
+
+public interface TripletMap<K, V, W> {
+	// Ryhmä 1
+	void put(K key, V value1, W value2);
+	V getFirstValue(K key);
+	W getSecondValue(K key);
+	void remove(K key);
+	void clear();
+	
+	// Ryhmä 2
+	Set<K> keySet();
+	Set<V> firstValues();
+	Set<W> secondValues();
+	boolean containsKey(Object key);
+	boolean containsValue(Object value1, Object value2);
+	boolean isEmpty();
+	int size();
+}
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Ajoneuvo.java
similarity index 95%
rename from src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.java
rename to src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Ajoneuvo.java
index 7eaa5d5ac226a452d030d2eabf191911e7637d7e..e140541357cc9f9af984671f0367219ea3abb9ca 100644
--- a/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.java
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Ajoneuvo.java
@@ -1,4 +1,4 @@
-package fi.utu.tech.ooj.exercise3;
+package fi.utu.tech.ooj.exercise3.tehtava5;
 
 import java.util.Set;
 import java.util.TreeSet;
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/HenkiloAuto.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/HenkiloAuto.java
similarity index 90%
rename from src/main/java/fi/utu/tech/ooj/exercise3/HenkiloAuto.java
rename to src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/HenkiloAuto.java
index e76a125a7c0e0897c5e88358c40519039616d7bd..65264e9f01472c7006b03aa8ae2cfd7111e89096 100644
--- a/src/main/java/fi/utu/tech/ooj/exercise3/HenkiloAuto.java
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/HenkiloAuto.java
@@ -1,4 +1,4 @@
-package fi.utu.tech.ooj.exercise3;
+package fi.utu.tech.ooj.exercise3.tehtava5;
 
 public class HenkiloAuto extends Ajoneuvo{
 
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/KuormaAuto.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/KuormaAuto.java
similarity index 83%
rename from src/main/java/fi/utu/tech/ooj/exercise3/KuormaAuto.java
rename to src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/KuormaAuto.java
index 761f6b31ca9f278bd8236d6ccbc78b824f69d57c..38025c732d93b88c54092c8806b08f675482eb0b 100644
--- a/src/main/java/fi/utu/tech/ooj/exercise3/KuormaAuto.java
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/KuormaAuto.java
@@ -1,4 +1,4 @@
-package fi.utu.tech.ooj.exercise3;
+package fi.utu.tech.ooj.exercise3.tehtava5;
 
 public class KuormaAuto extends Ajoneuvo{
     private int kantavuus;
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Main.java b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..9296b0c59dc16ce7e245dca77d7f78086cb3be34
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Main.java
@@ -0,0 +1,42 @@
+package fi.utu.tech.ooj.exercise3.tehtava5;
+
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+import fi.utu.tech.ooj.exercise3.tehtava5.Ajoneuvo;
+import fi.utu.tech.ooj.exercise3.tehtava5.HenkiloAuto;
+import fi.utu.tech.ooj.exercise3.tehtava5.KuormaAuto;
+
+public class Main {
+
+
+    /**
+     * Main class.
+     *
+     * @param args Command line arguments
+     */
+
+
+    public static void main(String[] args) {
+        /*
+         * Testin jälkeen alla olevan rivin voi joko kommentoida tai poistaa.
+         */
+        System.out.println("*** Harjoitustyöpohja käynnistyy ***");
+
+        // B-kohdan koodi
+        
+        HashSet<Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>();
+        HashSet<HenkiloAuto> henkiloautot = new HashSet<HenkiloAuto>();
+        HashSet<KuormaAuto> kuormaautot = new HashSet<KuormaAuto>();
+
+        ajoneuvot.addAll(henkiloautot);
+        ajoneuvot.addAll(kuormaautot);
+        
+        // Ei ole mahdollista
+        // ajoneuvot = henkiloautot;
+        
+        // Ajoneuvot määrittelun muutos
+        // HashSet<? extends Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>();
+    }
+}
diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Vastaukset b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Vastaukset
new file mode 100644
index 0000000000000000000000000000000000000000..40c0bd9cb783b66e10e149010fb085da56dac937
--- /dev/null
+++ b/src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Vastaukset
@@ -0,0 +1,12 @@
+Tehtävä 5 vastaukset
+
+A. Metodi palauttaa listan, jonka tyyppi on Set<Z>, tämä on kuitenkin perii Ajoneuvon, jolloin
+kaikki Ajoneuvo-luokan alatyypit sopivat yhteen Z kanssa. Täten sisi Set<KuormaAuto>, Set<Ajoneuvo> ja Set<Henkilöauto>
+ovat yhteensopivia
+
+B. Kaikki henkilöautot sekä kuorma-autot voidaan lisätä listaan, koska ne perivät luokan Ajoneuvo
+
+Listaan ajoneuvot ei ole mahdollista tallentaa viittausta listaan henkilöautot, koska ajoneuvot tyypityksiä ei ole
+määritelty polymorfisesti yläluokkaa vastaan. Jotta tämä olisi mahdollista pitäisi ajonauvot määrittelyä muokata
+
+B-kohdan koodi esimerkit löytyvät Main-luokasta
\ No newline at end of file