diff --git "a/Teht\303\244v\303\244 1" "b/Teht\303\244v\303\244 1" new file mode 100644 index 0000000000000000000000000000000000000000..c740ab0e5266f73cf4ad689c7bdacf36ab4a694b --- /dev/null +++ "b/Teht\303\244v\303\244 1" @@ -0,0 +1,48 @@ +A. +Collection niputtaa arvot yhdeksi kokonaisuudeksi, josta eri arvoja voidaan hakea indeksin perusteella. +Tietyt collectionin alarajapinnat rajaavat duplikaattioliot pois, mutta itse collections hyväksyy myös +duplikaatit. +Map käyttää (avain, arvo) -pareja, jolloin oliota voidaan hakea siihen liitetyn arvon perusteella. Arvot +voivat olla samoja, mutta avainten on oltava uniikkeja. + +Map sopii parhaiten käyttötarkoitukseen, jossa halutaan hakea tiettyjä arvoja, esimerkiksi vaikka +luettelo jääkiekon maailmanmestareista, joissa avaimeksi on annettu voittovuosi. Collection sopii +tilanteisiin, joissa koko joukolle objekteja halutaan tehdä jotain, vaikka sitten printata ne listana. + +B. +List: +Pysyy lisäysjärjestyksessä, voi olla duplikaatteja. Kun halutaan vaan simppeli lista, joka kirjaa +ylös siihen lisätyt elementit tekemättä mitään sen kummempaa ja alkiohin halutaan päästä käsiksi +muutenkin kuin vain listan ensimmäiseen ja viimeiseen. Vaikkapa lista käyttäjän klikkaamista +vastauksista gallupiin, missä vastausvaihtoehdot voivat olla samoja eri kysymysten kohdalla. + +Set: +Ei järjestyksessä, ei duplikaatteja. Käytetään, kun datan järjestyksellä ei ole väliä ja halutaan esim. +muistinsäästösyistä ettei duplikaatteja tallenneta. Esim. setti joka pitää kirjaa siitä mitkä +uniikit keräilytavarat on jo hankittu. + +Queue: järjestyksessä, lisäys voi tapahtua vain jonon perään ja poisto jonon alusta. Esim. tehtävien +jonottaminen ohjelmalle. + +C. +ArrayList: +Implementoi vain Listan, joten voi toimia vain listana. Voidaan viitata indeksillä johonkin tiettyyn alkioon. +Hyvä tiedon tallennukseen ja yksittäisten alkioiden hakemiseen indeksin avulla. Esim tulosten tallennus +paremmuusjärjestykseen, missä paras sijoitus on ensimmäisenä. Jos halutaan nähdä kuka oli 13. voidaan hakea +suoraan indeksillä. + +LinkedList: +Implementoi Listan ja Dequen, joten voi toimia listana ja jonona. Pointerit edelliseen ja seuraavaan alkioon +ja niiden takia listan järjestyksen manipulointi on nopeampaa. Voidaan käyttää esim tehtäväjonona, jossa +halutaan priorisoida jotain tärkeämpiä mutta myöhemmin saapuvia tehtäviä. + +D. +HashSet: +Ei järjestetty, voi olla null arvo. Nopeampi kuin TreeSet ja sallii useamman luokan käytön alkioissa. +Käytetään, kun datan järjestyksellä ei ole väliä ja halutaan välttää duplikaatteja ja toisaalta myös +hakea yksittäisiä olioita niin, että siihen kuluva aika on vakio. + +TreeSet: +Järjestetty, ei salli null -arvoja eikä useita eri luokkia alkioina. Kätevä, jos halutaan järjestetty lista, +mistä on helppo tehdä osajoukkoja, vaikkapa kaikki ne treesettiin tallennetut numerot jotka ovat int alkion +10 ja 200 välissä. \ No newline at end of file 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/Kirja.java b/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java index 13d735cebecb2492da4cdc2f967aed46ea347313..03f3b3685a2d6ede6bd9e521e3d2c0bcc4977983 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Kirja.java @@ -34,6 +34,33 @@ public class Kirja { public void setJulkaisuVuosi(int julkaisuVuosi) { this.julkaisuVuosi = julkaisuVuosi; } + public static Kirja clone(Kirja alkup) { + Kirja kopio = new Kirja(alkup.getKirjanNimi(), alkup.getKirjailijanNimi(), alkup.getJulkaisuVuosi()); + return kopio; + } + /* + * Palauttaa String muuttujan, joka on muotoa + * "- Kirjan nimi + * - Kirjailijan nimi + * - Julkaisuvuosi + * " + */ + + @Override + public String toString() { + String kirjatiedot = new String(); + kirjatiedot = kirjatiedot.concat("- Nimi: " + this.getKirjanNimi() + "\n"); + kirjatiedot = kirjatiedot.concat("- Kirjailija: " + this.getKirjailijanNimi() + "\n"); + kirjatiedot = kirjatiedot.concat("- Julkaisuvuosi: " + this.getJulkaisuVuosi() + "\n"); + return kirjatiedot; + } + + + public static boolean equals(Kirja yksi, Kirja kaksi) { + if (yksi.getKirjanNimi().equals(kaksi.getKirjanNimi()) && yksi.getKirjailijanNimi().equals(kaksi.getKirjailijanNimi()) && yksi.getJulkaisuVuosi() == kaksi.getJulkaisuVuosi()) { + return true; + } else { return false; } + } } diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java b/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java index 285fd40c2145f3fa3ce10f18412afb657fe48f5e..62965ac1f29e0f334e07677db95a9afd8d3aac41 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/KirjaKokoelma.java @@ -29,5 +29,61 @@ public class KirjaKokoelma { public void lisaaKirja(Kirja teos) { kirjaListaus.add(teos); } + + public static KirjaKokoelma clone(KirjaKokoelma kokoelma) { + KirjaKokoelma kopio = new KirjaKokoelma(kokoelma.getkokoelmanNimi()); + for (int i = 0; i < kokoelma.getKirjaListaus().size(); i++) { + kopio.lisaaKirja(Kirja.clone(kokoelma.getKirjaListaus().get(i))); + + } + return kopio; + } + + /* + * Palauttaa String muuttujan, joka on muotoa + * "Kirjakokoelma [kokoelman nimi]: + * + * [Kirjan nimi] + * [Kirjailijan nimi] + * [Julkaisuvuosi] + * + * [Kirjan nimi] + * [Kirjailijan nimi] + * [Julkaisuvuosi] + * + * ... + * " + */ + @Override + public String toString() { + String palautus = new String(this.getkokoelmanNimi() + ": \n\n"); + for(int i = 0; i < this.getKirjaListaus().size(); i++) { + palautus = palautus.concat(this.getKirjaListaus().get(i).toString() + "\n"); + } + palautus = palautus.concat("\n"); + return palautus; + } + + /* + * Testaa, onko annetut kirjalistaukset saman kokoisia. Tämän jälkeen testaa, löytyykö indeksissä i yksi -kirjalistauksessa + * oleva kirja myös kaksi -kirjalistauksesta. Jos tämä toteutuu, tallennetaan indeksi indeksi-muuttujaan ja testataan + * kirjojen yhtäläisyys Kirja.equals() -metodilla. Jos kirjat ovat samat, palautusarvo muutetaan trueksi. Muuten palautus + * muutetaan falseksi ja for loop päättyy ja palautetaan false. + */ + public static boolean equals(KirjaKokoelma yksi, KirjaKokoelma kaksi) { + boolean palautus = false; + int indeksi = 0; + int koko1 = yksi.getKirjaListaus().size(); + if (koko1 == kaksi.getKirjaListaus().size()) { + for (int i = 0; i < koko1; i++) { + if (kaksi.getKirjaListaus().contains(yksi.getKirjaListaus().get(i))) { + indeksi = kaksi.getKirjaListaus().indexOf(yksi.getKirjaListaus().get(i)); + Kirja.equals(yksi.getKirjaListaus().get(i), kaksi.getKirjaListaus().get(indeksi)); + palautus = true; + } else { palautus = false; break; } + } + } + return palautus; + } } diff --git a/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java b/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java index 2478ff6351648daef8b963f175230b13d1aa3569..b47b61d60b11917a2eba26f908a4b4a5f89016f5 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Kirjasto.java @@ -56,6 +56,81 @@ public class Kirjasto { } sivukirjastot.add(input); } + + public static Kirjasto clone(Kirjasto kirjasto) { + Kirjasto kopio = new Kirjasto(kirjasto.getKirjastonNimi(), kirjasto.getOsoite()); + for (int i = 0; i < kirjasto.getKokoelmat().size(); i++) { + kopio.lisaaKokoelma(KirjaKokoelma.clone(kirjasto.getKokoelmat().get(i))); + } + for (Kirjasto i : kirjasto.getSivukirjastot()) { + kopio.lisaaSivukirjasto(clone(i)); + } + return kopio; + } + + /* + * Palauttaa String muuttujan, joka on muotoa + * "Kirjasto [kirjaston nimi] + * + * Sivukirjastot: + * [sivukirjaston nimi] + * [sivukirjaston nimi] + * [sivukirjaston nimi] + * ... + * + * Kokoelmat: + * "Kirjakokoelma [kokoelman nimi]: + * + * [Kirjan nimi] + * [Kirjailijan nimi] + * [Julkaisuvuosi] + * + * [Kirjan nimi] + * [Kirjailijan nimi] + * [Julkaisuvuosi] + * + * Kirjakokoelma [kokoelman nimi]: + * ... + */ + public String toString() { + String palautus = new String("Kirjasto: " + this.getKirjastonNimi() + "\n\n" + "Sivukirjastot:\n"); + for(Kirjasto i : this.getSivukirjastot()) { + palautus = palautus.concat(i.getKirjastonNimi() + "\n"); + } + palautus = palautus.concat("\n*******************\n" + this.kirjastonNimi +"n kokoelmat: \n\n"); + for(int i = 0; i < this.getKokoelmat().size(); i++) { + palautus = palautus.concat(this.getKokoelmat().get(i).toString()); + } + palautus = palautus.concat("*******************\nSivukirjastojen kokoelmat: \n\n"); + for(Kirjasto i : this.sivukirjastot) { + palautus = palautus.concat(i.getKirjastonNimi() + "n kokoelmat: \n\n"); + for(int a = 0; a < i.getKokoelmat().size(); a++) { + palautus = palautus.concat(i.getKokoelmat().get(a).toString()); + } + } + return palautus; + } + + /* + * Testaa, onko kokoelmien nimet ja osoitteet samat ja onko niillä samat sivukirjastot. Tämän jälkeen käy läpi + * yksi-Kirjaston kokoelmat ja katsoo löytyykö ne myös kaksi-kirjastosta. Jos kaksi kokoelmaa on samat, tallentaa + * palautus-muuttujaan true, muuten false ja lopettaa for loopin. + */ + public static boolean equals(Kirjasto yksi, Kirjasto kaksi) { + boolean palautus = false; + int indeksi = 0; + if(yksi.getKirjastonNimi().equals(kaksi.getKirjastonNimi()) && yksi.getOsoite().equals(kaksi.getOsoite()) && yksi.getSivukirjastot().equals(kaksi.getSivukirjastot())){ + for(int i = 0; i < yksi.getKokoelmat().size(); i++) { + if(kaksi.getKokoelmat().contains(yksi.getKokoelmat().get(i))) { + indeksi = kaksi.getKokoelmat().indexOf(yksi.getKokoelmat().get(i)); + if(KirjaKokoelma.equals(yksi.getKokoelmat().get(i), kaksi.getKokoelmat().get(indeksi))) { + palautus = true; + } else { palautus = false; break; } + } + } + } + return palautus; + } } 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..e465e18cdb6f160892c89c737ba0872f47ae2e24 100644 --- a/src/main/java/fi/utu/tech/ooj/exercise3/Main.java +++ b/src/main/java/fi/utu/tech/ooj/exercise3/Main.java @@ -1,8 +1,10 @@ package fi.utu.tech.ooj.exercise3; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; public class Main { @@ -15,14 +17,48 @@ public class Main { 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>(); + + Kirjasto pääkirjasto = new Kirjasto("Pääkirjasto", "kirjastontie 1"); + Kirjasto sivukirjasto1 = new Kirjasto("Sivutien kirjasto", "sivutie 2"); + Kirjasto sivukirjasto2 = new Kirjasto("Toisaalan kirjasto", "toisaalankatu 3"); + pääkirjasto.lisaaSivukirjasto(sivukirjasto1); + pääkirjasto.lisaaSivukirjasto(sivukirjasto2); + + List<Kirja> kirjat = new ArrayList<Kirja>(); + List<KirjaKokoelma> kokoelma = new ArrayList<KirjaKokoelma>(); + + for (int i = 1; i < 13; i++) { + Kirja kirja = new Kirja("Kirja " + i, "Kirjailija " + i, 1900+i); + kirjat.add(kirja); + } + + for (int i = 1; i < 7; i++) { + KirjaKokoelma uusi = new KirjaKokoelma("Kokoelma numero " + i); + uusi.lisaaKirja(kirjat.get(0)); + uusi.lisaaKirja(kirjat.get(1)); + kirjat.remove(0); + kirjat.remove(0); + kokoelma.add(uusi); + } + + pääkirjasto.lisaaKokoelma(kokoelma.get(0)); + pääkirjasto.lisaaKokoelma(kokoelma.get(1)); + sivukirjasto1.lisaaKokoelma(kokoelma.get(2)); + sivukirjasto1.lisaaKokoelma(kokoelma.get(3)); + sivukirjasto2.lisaaKokoelma(kokoelma.get(4)); + sivukirjasto2.lisaaKokoelma(kokoelma.get(5)); + + System.out.println(pääkirjasto.toString()); + + Kirjasto klooni = Kirjasto.clone(pääkirjasto); + System.out.println("Onko identtiset: " + Kirjasto.equals(pääkirjasto, klooni)); //Tästä tulee false ilmeisesti koska sivukirjastot eivät ole samassa järjestyksessä? + + + + +// HashSet<Ajoneuvo> ajoneuvot = new HashSet<Ajoneuvo>(); +// HashSet<HenkiloAuto> henkiloautot = new HashSet<HenkiloAuto>(); +// HashSet<KuormaAuto> kuormaautot = new HashSet<KuormaAuto>(); } }