From cd3513cd1416e681889ec4f2eb563b9b69bfc08d Mon Sep 17 00:00:00 2001 From: AkJkSenpai <aku.paananen100@gmail.com> Date: Sun, 21 May 2023 15:22:36 +0300 Subject: [PATCH] Add exercise implementations --- bin/.gitignore | 22 + bin/.gitlab-ci.yml | 36 + bin/README.md | 44 + bin/Tehtavananto.md | 200 ++++ bin/pom.xml | 348 +++++++ bin/public/favicon-32x32.png | Bin 0 -> 1647 bytes bin/public/index.html | 52 + bin/public/style.css | 954 ++++++++++++++++++ bin/public/utulogo.png | Bin 0 -> 13307 bytes bin/public/utulogow.png | Bin 0 -> 20156 bytes bin/report.sh | 5 + .../fi/utu/tech/ooj/exercise3/Ajoneuvo.class | Bin 0 -> 2463 bytes .../utu/tech/ooj/exercise3/HenkiloAuto.class | Bin 0 -> 963 bytes .../fi/utu/tech/ooj/exercise3/Kirja.class | Bin 0 -> 1991 bytes .../tech/ooj/exercise3/KirjaKokoelma.class | Bin 0 -> 2482 bytes .../utu/tech/ooj/exercise3/KirjanTiedot.class | Bin 0 -> 1035 bytes .../fi/utu/tech/ooj/exercise3/Kirjasto.class | Bin 0 -> 5025 bytes .../utu/tech/ooj/exercise3/KuormaAuto.class | Bin 0 -> 737 bytes .../java/fi/utu/tech/ooj/exercise3/Main.class | Bin 0 -> 1467 bytes bin/src/test/resources/jqwik.properties | 0 .../utu/tech/ooj/exercise3/KirjaKokoelma.java | 33 - .../java/fi/utu/tech/ooj/exercise3/Main.java | 25 +- .../utu/tech/ooj/exercise3/tehtava1/tehtava1 | 19 + .../ooj/exercise3/{ => tehtava2}/Kirja.java | 33 +- .../ooj/exercise3/tehtava2/KirjaKokoelma.java | 68 ++ .../{ => tehtava2}/KirjanTiedot.java | 2 +- .../exercise3/{ => tehtava2}/Kirjasto.java | 42 +- .../utu/tech/ooj/exercise3/tehtava2/Main.java | 80 ++ .../utu/tech/ooj/exercise3/tehtava3/Main.java | 19 + .../ooj/exercise3/tehtava3/RandomMap.java | 83 ++ .../tech/ooj/exercise3/tehtava4/Triplet.java | 106 ++ .../ooj/exercise3/tehtava4/TripletMap.java | 21 + .../exercise3/{ => tehtava5}/Ajoneuvo.java | 2 +- .../exercise3/{ => tehtava5}/HenkiloAuto.java | 2 +- .../exercise3/{ => tehtava5}/KuormaAuto.java | 2 +- .../utu/tech/ooj/exercise3/tehtava5/Main.java | 42 + .../tech/ooj/exercise3/tehtava5/Vastaukset | 12 + 37 files changed, 2187 insertions(+), 65 deletions(-) create mode 100644 bin/.gitignore create mode 100644 bin/.gitlab-ci.yml create mode 100644 bin/README.md create mode 100644 bin/Tehtavananto.md create mode 100644 bin/pom.xml create mode 100644 bin/public/favicon-32x32.png create mode 100644 bin/public/index.html create mode 100644 bin/public/style.css create mode 100644 bin/public/utulogo.png create mode 100644 bin/public/utulogow.png create mode 100644 bin/report.sh create mode 100644 bin/src/main/java/fi/utu/tech/ooj/exercise3/Ajoneuvo.class create mode 100644 bin/src/main/java/fi/utu/tech/ooj/exercise3/HenkiloAuto.class create mode 100644 bin/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.class create mode 100644 bin/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.class create mode 100644 bin/src/main/java/fi/utu/tech/ooj/exercise3/KirjanTiedot.class create mode 100644 bin/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.class create mode 100644 bin/src/main/java/fi/utu/tech/ooj/exercise3/KuormaAuto.class create mode 100644 bin/src/main/java/fi/utu/tech/ooj/exercise3/Main.class create mode 100644 bin/src/test/resources/jqwik.properties delete mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava1/tehtava1 rename src/main/java/fi/utu/tech/ooj/exercise3/{ => tehtava2}/Kirja.java (50%) create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/KirjaKokoelma.java rename src/main/java/fi/utu/tech/ooj/exercise3/{ => tehtava2}/KirjanTiedot.java (76%) rename src/main/java/fi/utu/tech/ooj/exercise3/{ => tehtava2}/Kirjasto.java (58%) create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava2/Main.java create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava3/Main.java create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava3/RandomMap.java create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava4/Triplet.java create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava4/TripletMap.java rename src/main/java/fi/utu/tech/ooj/exercise3/{ => tehtava5}/Ajoneuvo.java (95%) rename src/main/java/fi/utu/tech/ooj/exercise3/{ => tehtava5}/HenkiloAuto.java (90%) rename src/main/java/fi/utu/tech/ooj/exercise3/{ => tehtava5}/KuormaAuto.java (83%) create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Main.java create mode 100644 src/main/java/fi/utu/tech/ooj/exercise3/tehtava5/Vastaukset diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..72227fa --- /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 0000000..7a135ab --- /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 0000000..4cb91b4 --- /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 0000000..0cf486f --- /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 0000000..8b003a2 --- /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 GIT binary patch literal 1647 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4rT@h2A3sW#~2uxIs$w`T-^(Nl;ssh5$!@i zMM05vh7YL8)b!WgQe#;L28Qb;L4Lsu&AXcznU{Ah>tkYR+%R>5KxxC|b8}XAbjP)e zaIjtHQ;K-9@Wk3h8>8#fraYW^v~$(sYpne90@$nWm53@Yz0FxD=rw;c*WTHaHtnhX zJ^jPWiR->yZMpD^XG>H<@8Og+>)-buJaaclRy_V<b&jUx3M=8qZxnXvFfQ=8)0TdA zZpN3_+qUNO{&+iUM)HoV8i~_kd9OSx9({~lvU7jgyPhK_Z~Xb}$8D&$Qa`o0Kt@jb zuY6LgMv=Pf6$9<Bb-@pE8TVNqJ8$>gG4{}{`~H~+0)JkXDi06+r*-_c?S6j-2B!U< zE{-7*lC=k!qwg>>us^u}v3}d<r@L})Z_8b)Yra%BXJ&M6=C<71JJxT`dcAU6`uBYi z;ioP64jla}5q2d~I$2xX)_$$P2ZJ(e#RNtbUH=2e)O7rdS6<^YFv_%goXa2<D=oQ| zTl&Vng|dr&WYk{Rq%6^Sz;5&NDJ9*Xb=G80K2kEP?Kl6y>3&<ZjW4XwGnl_ed*$I> zr(ebvwz(YA<@i41qfh*U!t_<)e(z+<|0F7lid#L=3cB-9(`<`|<nhyYJAEI;9lFAj zedA}8d!1<KK^fQLc@qSFCOD}sUUI^CYi&ev^|k~}t>ssj*b5z;)V5Lmyh5nY<<N`4 zUmTLxyn3Gy@Wz?__8fj`j^wSk{+cBoPCID$<omUsC&M>r-L6}6W!ir4UH7NRs_l|^ zz4m?Lyg3%9wp>;bxqrBeXI}8Di8aglkAD2>P~3b=e8<EbOQ-S@1<RE@3@lIUbV~fJ zjQ(0#F=$+u_{HFsCM2v@u4uQ{nt{Rh<pQOy8IM!s8o2(OFfyng-)<AVOevj3o9V>H z)>)O2*MjXBY!BacV{nSo<n~fqE|!|ZaAj|glI4BBo$hYT+pPKDGu!MEF{||noft0` z7OTGh<8vYQ&Trlh7nc9zdGM<5AiGQ2%J3_eYjz#rU1)LZeaNI_Ij8eGk8qgmTsrk| zAa{0m?(L1s%xc~-oV;}G*T3Bh*LxSAp3iK0y=sz0f0eHE$7t4O&ApoaTTVr5*!`;g z_~HB(FKxq#Lh5{i5BTQ?n6~dRHqK7?>7F_3<MuZ;>lV$P;!u9nDs1NVBmH*C?z5K4 zCT$7OD7?e5?(fY6Ewd}ePpmE4m0V^#Y|fXSw`!SzU!w7<eamm3T*55;pwMB)<h$Fh zN<7flbG*7dHB4dOgM@6~1=`a87j0ts_27%bnW<h!>qFnS<{e^u;j&qEtHbo7^;)(s loRYg%Tv)k@C;BhbtP|_`)sL@LVPIfj@O1TaS?83{1OO1$C3OG* literal 0 HcmV?d00001 diff --git a/bin/public/index.html b/bin/public/index.html new file mode 100644 index 0000000..b998eb0 --- /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 0000000..7c9950b --- /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 GIT binary patch literal 13307 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 a{~5a{A7MQ3ui^%1FNUY9pUXO@geCwbCB_o~ literal 0 HcmV?d00001 diff --git a/bin/public/utulogow.png b/bin/public/utulogow.png new file mode 100644 index 0000000000000000000000000000000000000000..f0af24f59fcf77e473d30a16218bde35e5d1dca7 GIT binary patch literal 20156 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 M)78&qol`;+0K|~Tr2qf` literal 0 HcmV?d00001 diff --git a/bin/report.sh b/bin/report.sh new file mode 100644 index 0000000..38d80d1 --- /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 GIT binary patch literal 2463 zcmX^0Z`VEs1_oOOZFUAGMh1i8qGbKt#LPVXti-ZJ{j^N|(vnjBlGNl3{rvna{nU!o zqU6ltRAYU|to*#x(z1MZ1{OvJ0kGnn#JqHU|D>$c<Pt^({-V_E%;J*NqD;Ti+|;6c zMg|U_;F6-uymV_u29EsP%;J*7tVBizHk-`6%o00B24M}DJdD;1V`N})&QD2YXW(IE z;78cuT2z!@#KFMF$l?{6SCm?upHr5aqL7@QTacNPSdy8ar%+IopOllDTWqDk#Tk;3 zs!&o{kg5POKo8_dJ%}R}k`wdt@=FwwQWao^=qY%XC}b8ZWag!07NsVa<WwpYrKY78 zrRF84rYNKp<>x9Cr52WE7Nw>r=q2YQ78fg|W#*(7Lu^S&P0mRKNfjg}XD6noDk!C8 z>Xnw1>Vd*fFF!v^4<3F>3Mu)i#R?$na}!IFGZacPQWa7w3R06xQd1P*`iqN_^+2(q z2X;Gd(;)U|<`(1^l|cMiT9TQA#e*a$gv1sWGZael6%xTg%Ed{PBG24{oXq6R5{2T@ zg47~~<ovwilA_Y&lKdhCNK9yGf&#rXFC{fCGcPqoPr<jexC9g&U~M^-3YmFj`Pr!o ziFx@Y8K@=@=>($OIjV@b_@rVurIrv%U{p{MQk0q+OvoHA25trc9tI8uK}H5q4Ifa3 z(+3q6`Vik*gGwWQpUk{eztY^K)S{5Yq?}Yn1|gsP<iwn?#G*_PA1cUFl95@=$YA6{ zYGG>4$RL!SS`vg_baH8E!U{zW21!PS93qN6h_eZWF1SR-uZWRBs2GczxZ&kBC}g<P zQ%n5eg*taJGLOA7BL!64GcpKj_ynhxSc3^oFv-Zk8JwA(msnC-l*-7EU=v{#5@j6; zBBHEF4?a7v`8FXD)^=b^Y(gTf?X1Bz*@Q${+gWokC^IswBPR3+B^OSD35p06L?ui{ z2Cm@z(xT*4w@grq<Av3{;5vbwL7kC-IXJb1ok5e4fejMrj0`-!nZ?DKdFdgQ1*yd> z3Ji=4%nS?+Obkp6tPE^m7CV?`V_;<9VBln6WZ+_8U@&1|2CL)R&A=Tg#Jin=e?M5Q z5Ca1PNF@UUBZDvl0|O5OBLf2i7lR0cC<91Lj6od91h5>~1PLrA2x2usia{F51SXK_ zI86}6YJv<2Zji)kf-DJcki}vGCxaY=JOdMh0yxYR!6B-}z|4T~jS`mdPz0L<Qp3cc R0@kU@pal+ZCI&SI4FLH1!x;bo literal 0 HcmV?d00001 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 GIT binary patch literal 963 zcmX^0Z`VEs1_oOO1$G7|Mh4^JqGbKt#LPVXti-ZJ{j^N|(vnjBlGNl3{rvna{nU!o zqU6ltRAYUQ)V%D>oP5X9l6-as7DfgGVl_Hu<>#fAmgO@t@MJ*D@J&oCN@QeU^kigU zv&qcMEU{x`5Yg}nE-A{)OSgv6o|<8d3@pz1DXHuX+>8wTVE5%D=B4Yq78T_eaWL>Q zGQ0`RD@rZS&nZhyQAp0uEy&DCEXmBzQz$6PPs&NnEw)nN;ta`1RY*xq&PgmvO;IRF zOwLYBPgPJ#%hW3^Db)jcR4+e2OAqc*C54py)MACa{1S!S#FFF;g_4X^h180I)Z`Lm z{l!JedZ1v_1360%w`p9Q5N|0YC+307OiERNySOA@AyJ{EvLKZ>MO+MA4E#I{><j{o z45Au7AdB_E;Q_J18WdjqKACx`ex<odsYM})Nja&E3_?En$%#2(iA9+pK2(sUBqOt! zk-^l5*hoZ*eQQPr{`Axms0cJJnKd*$IT$1u85Hryh?N2tBLjaix^@-~aBOo0=a&{G zr@Cc=94-L00hHpvq0G)8$H>42@hl?)k8fsiab{k6NM%84F@qulBLg!70|O%i69X#) z8v_FaGXo<7I|By;BLgP`1A_?zGXo0)0|VD?2ChgUp6v{L`xzJ*m>2{Z7#P?X7{NM) z7#J9Mz-%rCVFnSfm?(o7k_jMn5EI0)n83||%>+pXDI^n^;BLTX0zVcLm>8tNE|p=B NXJBApVPIsC1pplJ^{fB@ literal 0 HcmV?d00001 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 GIT binary patch literal 1991 zcmX^0Z`VEs1_oOOZFUAGMh4yDqGbKt#LPVXti-ZJ{j^N|(vnjBlGNl3{rvna{nU!o zqU6ltRAYVb%%ZGBb_Nzk1_7|joW#6zegCAa)Z`LI2Ci(7Y@T0cZYCoGhfi=xQD$Dc zH6sH*SUfW)Gb<4)$(vQ0lbx7ZTpCuIU!2Lv!05@yz-E(~msw)R$RMHt(+Z<KHNzMg zSe)}yQrQ{!7#a8xR=XAz<ri@<2rx3Uh2|Bd7U$=brKTt(=jRq=<|LM6=I1FC6y+!7 zq~;b|DR6OyWTYyjq$cMi7Nw>r6eK2RC#I(=D5YiUm6nw1fqbi%pP!`%_pOpbN`7jw zLSBA}LT+M7a)v@lMyf(;ML}wE39|m;qGUZ#*y(|srH9)zE>1{@C?qH5fy_)wRe-y= zBwry>p`@}Pl}JUNxdl0y$(bbz#ia$QMGDFJdBr6~rO74vMGBDE(9l%KELJGZOG!=3 z%u7wtQ}8V<E&(|ntSzTfAv3QmKRZ<+F)zO)1Jwi~oj^U$jG9Efl)=To%OJ$Vz{McU z$RMiW14@$m;7ke$WNT1P;`hnSOZ6+wO-d~aNleN~Wn>WY$xlwq2}>->1o5GQEF~G4 z#f%L4J|q<m){G3i>8T~)f&!Y`ximCkIhlh&nvo%gh^z{6E)}v0BLi<Ss&lyE<qIe< zgkX+EE}w*8T95?=(o;*kP|Gc54NXrD24zMDMf_f}Qs81_5Gcmb&!Pb?+PH%AON)|I z-7-OO!37RFaACsEpvlO<1_=sA1|Hwc;^NG_^pMJe)M5rj21W*E1_lOZ1||kp1~vu; z1||k}D9ypZ$-uzC&cMjP#lX$L$iTzEz+l3_%)r9Hz`(Vefj3f!e>;QVey|=91_lN; z21W)321W)^1_lNmFq?}(j6obMCcz+yWCBPX!~`iUCh%c3L54vV$pj|28?c!mgw+H& z65Jq$)dYDG+#rS31O;%2!$J}f4oX<UK@O`4Dh#Sv!vUKKN?1%_Vo(Fem^y<N0|NsK I10#b50ENm36951J literal 0 HcmV?d00001 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 GIT binary patch literal 2482 zcmX^0Z`VEs1_oOO19k=`Mh4U3qGbKt#LPVXti-ZJ{j^N|(vnjBlGNl3{rvna{nU!o zqU6ltRAYVb%%ZGB@BHli)STQzb_Nzk1_7{+oW#6zegCAa)Z`LI2HtF_f;_*>+)PFW z4xiwXqRhN>Yeoj1Y>)vynZ+fErNxX4+&+#)MTwOlzBMBQXK-eEUSdgUQ7R*Y4MN7o zha}fo+gUR*u-RnhWtP}6GH`3aEY}QUWMFa5Pf2BG;AdpuM>yNHs3^aPgF%pyd17c@ zQEG91PFZS-LUMj?L1s>3NoIbYLP1e}Qch}av6TWBXGlh>LP~0KPGV7Nib6qRa&}^R zs)ABlre0}DsU9fA^z!qw^xz?;q>z%ITC9+lU!stkSdyHfP?C|VkXliYnp}dczqlw_ z4;21-AZO{}HVtBbW^O@#QHcUrZDzhga$+9H{G?O`nCmf>m6l}YP^J(Phgi%|D9Kky zR4Az|Naf;$M<)Swp1B1%naP<Y3dN-bsYMFO`FX`9MWx9l`9%tlRHUJ)kXfuynwOHA zmYJ8DqNm_nT3iAOIIy;yN`=h4vi$5+g~Yu4k_=Q6xHyS&Dp87v^$)S?h_ZArDk9c{ zR945uz{eoW!@$iT!pI=1;R8zX`rxt#5=PdbOwI3;nV0HUnwykb6q1;flgh{-<ddJA zm=l&*lnLTP1zAcmGK(1*%t<RvU}c>(BZEMCY6)7&#-*VND_%GlWEdH8h$uiHE+>#b zh*8AIAW)3vA`S+5Mh0R^F=EW8UN&N6;7?C20oNU%q8?oI^J-`!ig;^A20LUv=|w&V zg9;-<5fQ;p<pj#ez?G9(oR|pq93z8~25HI5S~HA;L4%RO6Tizr6%UaPXJp_C&Mz%W zPIb!!X9cjsV5t~fy|6RrFft%YYIX)aMg}%Wf?#Ce@y#qQ&df^>sVqn>W>92cWMF1s zU|?ckVqj%p1GCr}I2afiIKgZ#237_}25tr(21W*61_lNb24)5(1_lPM-3)w@LIT?v zg!Y5gi83%SurV+)FfcGOh%qpL)iW?~F^DrrfW;&kq>xMise_mxjl~2(tR~2U&BSzr z92OHqv6`U3pvb@k^_LRdHwd>VV=+k*t4XR1YDm68goip76XdX%z{H>l4mB+XeQ>xj JF=#XB0sy9++Pwe( literal 0 HcmV?d00001 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 GIT binary patch literal 1035 zcmX^0Z`VEs1_oOO8FmIHMh27OqGbKt#LPVXti-ZJ{j^N|(vnjBlGNl3{rvna{nU!o zqU6ltRAYVb%%ZHsypYV)l>8EQ1{OvJ0kDRg#JqHU|D>$c<Pt^(7C%p4PeukaA94(} zW@O;<_6+iJ^z`xca%5!S^$PXzcJvGm4GZ-T_GDyWv&qcMEU{x`5YzBMSRGtal$n=q z?Wq~Y$iU*9pOVVXz{|+Mk5J%RRFq%D!NAYR_#`y1D7830rz|x^Avr&{ATuYiBr`ux zp`a)~DJM0z*h+zmGbAHbp`@}PRRLsx9>{Zgu6d=o3dxCidHE#@NvR4jBlHwJOB6DT z6*BWuGK*4^OL8g|ic-^3i&FEFQ&SYuit=+6ic$+pGmBDF6!emF5{ru!(lT>Wi?P}P z@dedwNl8u4Nd!5dATc>RF+Ej5DJ@g4w4_uI6u)};`B{4K_*GI!$xkg-0C_Suu_QS| zp(G<!A+@3)HMt};MFFnAxF}f<lv?z_;e*>WE>6$ff}G6c%o2s-(t^|?h2;Fa;*z4$ z<dXa%1yG1;K)kG@keOGa2@1#3yp+_m%sf!o<rgWWq^2d7=9D07(^K#*EiM7cWagzR zB<6u!2eARkY%VSa9tJ@k22KVcMg~zV2?dl+_<b_-QvFJElTwR95|eUL85x9p@{<#D z!V-%zL42qnOG!p%F(U(4aDHh~a;jS<NTDEdHUI|#BZH`C9>@im#U-hEB_5fnMTtep z8I|k|Qj83IpkUGmB_n;1rx_V|d^3xSGxO3zDhpDJ9Sj*58JHOu7?>R-8CV(E7#JKR z8Q7sT2Z&~1WME?8WZ+_8WZ-6CU@&1|2CL`V&A<~W#J8P6U_S!`0~3QV0|Nsa10w?i m10#b70|NsOn9ao?3O0k8K@6-)oI!#C1f&@l7+4q>86*LX>op_* literal 0 HcmV?d00001 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 GIT binary patch literal 5025 zcmX^0Z`VEs1_oOOXLbfAMh1i8qGbKt#LPVXti-ZJ{j^N|(vnjBlGNl3{rvna{nU!o zqU6ltRAYVb%%ZHs;*xxJ1{OvJ0kGnn#JqHU|D>$c<Pt^(-fXCXJipA`OhyI{pWu?B z%)E4KMh3S0;{42#R7M8Q?ELKf)STSJ5=I6#AD_(P5^F{V&fv`Syu^~yqEto(d$6F5 z4@r*lh8k*ZXU)jKTbx-|3Uf*cBLk~Xa4N_aOAt+>!Nn!{U^CflGV?M^>=+q@HDI2C z(VAh53@pz1DXHuX!i)_3h+uIoD#|b7U=U?w{}P&4lv<phQ<j>dker`ekeQQMl9`{U zP*9Ygl#`lUY^A`(8IqBzkdm65lUS6RqEL{SoSm4Ss-TpXsaIN3st1Y;z5M(vJ$Pg& zDWv457AxfCmnh^WmLz8=lw_nTq*fH9CYK=VFD^>f14XSK$XR;0O@r8<nOl%wRH6V@ zTUwHtqmZ1K2eKh4RRQMy0aXY|PFP%}P?E2Zs8CW_kjlkLlp;{VBVdkWQBh(g5$b|d zO9+_ckyxBTSe0jPK~83JW{E;^X+dg{LUMjyaY<2Wa!G!X0wjZJXewkDE0pG?q^4!& zrKad9_?8xzfZ`miEvHf;Gp{T^J5?buFTW%M)dV6#g{YvTq9TGJM>y1|=o)ZYMIb7N ztaU^rWFnM!=H#TNC+0X7rI+TW=9RcsB&QaDOES!Y0y#^9%C_9pl8pQmh4j=CSPcNK zB{Vb@(u(qP!NnIS|0;kh8CZF)P?VaMT2u@&3sk=4W)>G`=B0x(x&kCBAmtIw3@6jW z^a@IFU=^3-;|a>*l6=xb(H~q}V~-oM3>?G`B{PZ%7EN3XLJZ<O4Ezidj0~b0KA=if zAKYAmBwTAyyMf;)GcVPzG&d==C?qi{CzX*w$R|HJF()jsC=<ko3bK@BWEL|r7?IW} z0<~Qj83fW(OM+1wMC=-xpr(*DBZD=BMOLGTgF%szA&rQZ4Z)D&B&Y)74U|O0$iM}1 zJh;%d=3r1|WXK`LEnxLjDC8L#1d3Bj&|Jg~ZybUmmoq)J1d@>$890j(Y@YPg5?BFO z!pOj(p$TsCS~D^@LYXAS2h1>QJ8KRGJw}EMA_9Vl5{j@AMh4!T%;LmEm;)FYtTaeV zqcEM|+`t8|Pm0+Yj2RguaAi#n22)1HTq1ml%K!oiV6?u1c2*G0YDNY@a8x4~C5#NF zBt|!=NYV`BV6bFlVxd>`q2y62R%wu|O+^C-u|vtsM?{qCT*3LJMaijdnV`y#7ZwEI z?kYQjEh7U9s1#ynuxDgo4o)p$XK-X>V1rbkj0`-!koI6mWkG5&gCYYX12Y2y0}BHa z11kd?0|NsS13Q%FVBln6WZ(jeaWgP6@G$Vg`FvnGeg**sMg~C!1_l!bX0SP2yBUNc zg+#V9i0udKlVo6EU}IopU|?WmkYZq9-~qF_7^E3wz+$otatusRJLKUefz(4xQov%8 z2v(Dn7?hFRf-pe^iwTlgO;BS{M>2tlfq?<y25ctCVl_d71UD#RH9?aEH>hGYL5o2f z9-=x}LR1$^cxYlZNuR-hfr-HooH`g8jNoP=LdFD(S-M!wGGj0&V3q|IvrMp<#l&C* WPFdCrPM{cKU|}#~uwk%cZ~y@G-vS^2 literal 0 HcmV?d00001 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 GIT binary patch literal 737 zcmX^0Z`VEs1_oOODRu@XMh2teqGbKt#LPVXti-ZJ{j^N|(vnjBlGNl3{rvna{nU!o zqU6ltRAYVb()^;_M90#Se0ByFMg{|7^*Ltc=cSgG<ufvHW+&#AB$kzy7Bez1dNMMw z*<|Krme?^eh-ml(mlS2@rCY;jPt7n!1{UZ1lvH*GZbk-vu-kGH^V0QQi;D7#I2d>t z8Qz5E6{QyE=ai+UC?x0S7G&lmmSpDVDHIgtC*`E(7F#KBafW21Dx{<)=Oh-TrYIC7 zCTAz6rz$9=W$Kldl<I*zsh6Lhr3d$<l0r&;YOz9Ieu+YEVo7p_LP<udLTW`pYH|s( z{^Fu!Jy4M8ft;m>+cYjth_@7y6Z1f3CZ#ICU0jl{kf=~nS&&McA}$6l27Vp}b_M}P z22l+kkj47o@POE04GJ%QpUk{eztY^K)S{5Yq?}Yn1|gsP<iwn?#G*_PA1cUFl95@= z$YA0_Yz!h|-kOntD>%QjC^^+F6J$O=LJAxf><ki&3~Uf5F*5M@W)>G`=B0;J7Niz4 zC^9fIFf%YPFfuSPurjcLS&R(q3>*xM44e!M3?>ZB3@i)`3|zYzxFUskwlnbUXJBAp qVi06tU|?fl1gjTfU|`?@v$+_A8AQPHqF_>tL6U)ifrWvQK^y>UQ_<7_ literal 0 HcmV?d00001 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 GIT binary patch literal 1467 zcmX^0Z`VEs1_oOO8FmIHMh2bYqGbKt#LPVXti-ZJ{j^N|(vnjBlGNl3{rvna{nU!o zqU6ltRAYVL#LPT)1{OvJ0kFcH#JqHU|D>$c<Pt^(Hk-`6%o00B24)S-Fh&Lz=lqmZ zb_PyH27ZKE*P^2QA`S*_MyB@AyrR_N{G77X6ousc+=9%U#FEVXJcWXy{G^=J++r&Q zF3ymQRE3n(<ebE!)D(q+#N_P6^i&0<v`oFyl2Sd8>-6&Tv-IGuQ&LFDPc2r+%P&#L zO)N>yP$<brRY<KUNKGz5)?ZwdtOxR|9>`gGxJ`rDpP5^bUsR$1R$E$<nWK=Lm<O^U zDOCaHei9UV<`(2+CTEr?6qgpH7AYj>=M|R}l_r<u7b!r3QA1N9vsj@tFC{fCGcPqo zAuYd1Atf~}u{5UyS+$;mZ)tG}NG3BcRUt7C<V}ddNJesT2A33N=A~nCvO-C|LZU)R zWkD(zXK-b4Nop<@MO>U7iNzVgsU=wCkPR5ps<;?97<hRYSQ+>j8ALUFK=G^(PS%jH zvj!z)exJ;|RKL>Pq|~C2#H5^5Mg}3D{N%)(u*9NF5FaYYQj(Eb%*deULrQM4W@KOi zrA9^u9*t-pxTPEnVvLM#MC1{O4gxVWvZI)hfh#z_v?w{%EfW-XoS;GsocY-qq!=04 zAR)-ez~h@)T%4Jg9#UD5TFjuxz{tSN00K-5j0~&{Yz&MH><kPHCJf9Bj0_A6T)P=K zB89lNGw|$ZU|?Wk;Ada}t6^YZWDsCrVBmqMVi05yVqjq4WDsT$ftsL&VuC0Z69mB~ VFoDe#2a^&E(hLj?EDVeck^n1>!SDb8 literal 0 HcmV?d00001 diff --git a/bin/src/test/resources/jqwik.properties b/bin/src/test/resources/jqwik.properties new file mode 100644 index 0000000..e69de29 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 285fd40..0000000 --- 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 0c5fb2a..6bda835 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 0000000..37e1930 --- /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 13d735c..0151196 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 0000000..0f31c86 --- /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 7cb6187..fb86242 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 2478ff6..9d3cbf8 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 0000000..cfac1c1 --- /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 0000000..b5a49c6 --- /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 0000000..bba49e7 --- /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 0000000..7e1d306 --- /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 0000000..4e5d7e4 --- /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 7eaa5d5..e140541 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 e76a125..65264e9 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 761f6b3..38025c7 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 0000000..9296b0c --- /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 0000000..40c0bd9 --- /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 -- GitLab