Initial commit

This commit is contained in:
Oystein Kristoffer Tveit 2021-03-23 22:54:32 +01:00
commit b41d133be1
106 changed files with 5423 additions and 0 deletions

44
.classpath Normal file
View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-15">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
target

34
.project Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ovinger</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
<filteredResources>
<filter>
<id>1615901682313</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

View File

@ -0,0 +1,45 @@
@startuml LineEditor
skinparam DefaultFontName Fira Code
!definelong obj(id, txt, i)
object "~#1:LineEditor" as id
id : text = txt
id : insertionIndex = i
!enddefinelong
!define to(id1, id2, txt) id1 ..> id2 : txt
!define self(id, txt) id ..> id : "txt"
obj(A, '""', 0)
obj(B, "test", 0)
obj(C, "test", 1)
obj(D, "test", 0)
obj(E, "test", 2)
obj(F, "tet", 2)
obj(G, "tt", 1)
obj(H, "text", 3)
to(A, B, setText("test"))
self(B, 'getText() => "|test"')
to(B, C, "left()")
self(C, 'getText() => "t|est"')
to(C,D,"right()")
self(D, 'getText() => "|test"')
to(D,E,"setInsertionIndex(2)")
self(E, 'getText() => "te|st"')
to(E,F,"deleteRight()")
self(F, 'getText() => "te|t"')
to(F,G,"deleteLeft()")
self(G, 'getText() => "t|t"')
to(G,H,'insertString("ex")')
self(H, 'getText() => "tex|t"')
@enduml

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2021-01-27T08:11:51.105Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.141 Electron/11.2.1 Safari/537.36" etag="YUmG1z7LbtLWfXLD1xFS" version="14.1.8" type="device"><diagram id="9T-pDAsRX8DZ6PBZXNOD" name="Page-1">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</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

View File

@ -0,0 +1,32 @@
@startuml Rectangle
skinparam DefaultFontName Fira Code
!definelong obj1(id, max, min)
object "~#1:Rectangle" as id
id : maxpoint = max
id : minpoint = min
!enddefinelong
!definelong obj2(id, max, min)
object "~#2:Rectangle" as id
id : maxpoint = max
id : minpoint = min
!enddefinelong
!define to(id1, id2, txt) id1 ..> id2 : txt
!define self(id, txt) id ..> id : "txt"
obj1(A, "[]", "[]")
obj1(B, "[1,2]", "[1,2]")
obj2(C, "[3,10]", "[-1,8]")
obj1(D, "[3,10]", "[-1,2]")
to(A,B,"add(1,2)")
self(B, "contains(1,2) => false")
to(B,D,"add(~#2)")
self(D, "contains(1,2) => true")
@enduml

View File

@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2021-01-26T13:33:14.506Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" etag="gUni9gv5qTJosgkG4kGU" version="14.2.7" type="device"><diagram id="9T-pDAsRX8DZ6PBZXNOD" name="Page-1">7Vptc+I2EP41zLQfYGwZG/MxwHGZzrRzbabT3n3pKLYAzckWlQUx9+u7QvKbwImT8nK5hMkQtNqVVtLus48MPW+a5B8FXq9+5TFhPeTEec+b9RByhwj11J8T77RkFBjBUtDYKFWCO/qNGKFjpBsak6yhKDlnkq6bwoinKYlkQ4aF4A9NtQVnzVnXeEkOBHcRZofSv2gsV1oaolElvyV0uTIzDx3jd4ILXSPIVjjmDzWR96HnTQXnUn9K8ilhau+KbdF285be0i9BUtnF4PcvD0F2f/vLl+zP0adcbO5++4f1zShbzDZmvT0UMBhvslYuy53ZhuDfjfJzkmCxpGnPu4FeZ53DOwj3q1XyvuRr3Tes9UmSyz5mdGnsInCYiGZ3TCIusKTc6GzSmAhGU1JNDZ+W5v/ewftK4Llg9QecPk6XjBQKsBX3thHI1rZsJWzJi9bOyELqzlB12m4nOP/EKRyVMpupd3/S82flakonEpo+pthcAWp4irZESAqxe6N3e7Y/j4nZ+5n2cMJBa8H2obigECLeZMFTaTLPRaY9xwllKmdvCdsSNaraKpkwpaR0wHTKGRf7mb3FYoGiCOSZFPwrqfXM5w68yp4iiVDpv3Ka5K1R7Za5AhhDeEKk2IGKMQhNdu2K9NPNhypV3cDIVrU0HRkZNuiwLAeuMgg+mCR6RkJ5RxLKOqRoI7YkNttI0vhGoRQ0I4azjEbNbY5xtiqV7T0PI/LEnuvJSXyAcdb+goN8IyLyNFRIiHYin9I7PK/aifhHDqSQCcIABrZNd4+dkpmhSJUiflAzHtyhddB6mcaqjpb2QKPmQGNrHL0NB+PAWeJdTW2tFLJ2f+34HY8e9cpW90MrYPX8VfiWB/DyiPZbS4SCCVVScdQEyjkVGORT4AJ1HHRiLHFfGfUzETUsVlKqcn6jloLmSiUbLDkHMMdrmg0inoA4ykBlvihwSc8ysWfRyAhsQGKaZj9BBMGyHfRzAacBThQmGvwE51lWrxh6TS3wqkpVMz0LaDU1zZvYCJzQOFbmE0Ey+g3f74dSmWkiA8bV8A5jbSTPDAqfBhxR6DfCJfAP0TE8kozoXOgYvNONK9KNIhc6044jBt8L/TgkE88nJKenH2XVuBr/GD3NP2qUI+UpeYRvwCaI3d8KsAZ+0fxc75vlBs10a1e0ciprZtD6XOupjFSjsGkek3HshPQleA30pbz1mnhCL6UvKLACsyN/ORVpCM9Jgy9Cd7vGS3DVeBk6g2DolC+3GT1oOBiH4+r1wlgaWrEU+gPHrQ0bXoQaq9X4h9N2pcrK63bz81Dn8Q9NnaXYvBnm7I6PUOfRJalzURk6Vvb/g6JtZb8q9MfL/gnRt+vDhquir2sXWfdU1dqmh2eu1m77Y+DvGKhwHO8xSgHUj4lC9kMo1zu8XlwWhFBroLxf4M9/gfd0RQaY6XqD779f4Z95hffca1/h3WPfIbzCJENvLcnC9yRrSzLfvkNe/UGZO7wYnz4hL+78FAtdlRjbvMUmJJ2JsdMcqOvXcCcjxq/yyy9FjBX+vhleXN6fTs+LoVn9REeHVfU7J+/Dfw==</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 KiB

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2021-01-29T09:28:07.693Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.141 Electron/11.2.1 Safari/537.36" etag="ipHiC1TG13N0dEeqCm6r" version="14.1.8" type="device"><diagram id="9T-pDAsRX8DZ6PBZXNOD" name="Page-1">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</diagram></mxfile>

View File

@ -0,0 +1,13 @@
@startuml RNPCalc
scale 2
class encapsulation.RPNCalc {
-stack: Stack
+push(double num): void
+pop(): double
+getSize(): int
+peek(int i): double
+performOperation(char op): void
}
@enduml

23
diagrammer/ex4/Person.wsd Normal file
View File

@ -0,0 +1,23 @@
@startuml Person
class objectstructures.Person {
-name: String
-gender: char
-children: List<Person>
-mother: Optional<Person>
-father: Optional<Person>
+getGender(): char
+getChildren(): Collection
+getChildCount(): int
+getChild(int n): Person
+getMother(): Person
+getFather(): Person
+addChild(Person child): void
+setFather(Person father): void
+setMother(Person mother): void
+removeChild(Person child): void
+getName(): String
-setParent(Person newParent, Optional<Person> currentParent, char gender): void
}
@enduml

View File

@ -0,0 +1,31 @@
@startuml StringMergingIterator
actor Actor as a
participant StringMergingIterator as smi
entity Iterator1 as i1
entity Iterator2 as i2
a -> smi : next()
smi -> i1 : hasNext()
i1 -> smi : true
smi -> i2 : hasNext()
i2 -> smi : true
smi -> i1 : next()
i1 -> smi : next value
smi -> a : next value
a -> smi : next()
smi -> i1 : hasNext()
i1 -> smi : true
smi -> i2 : hasNext()
i2 -> smi : true
smi -> i2 : next()
i2 -> smi : next value
smi -> a : next value
a -> smi : next()
smi -> i1 : hasNext()
i1 -> smi : false
smi -> i2 : next()
i2 -> smi : next value
smi -> a : next value
@enduml

13
oppgavetekster/README.md Normal file
View File

@ -0,0 +1,13 @@
# Øvingstekster
Denne mappen inneholder øvingstekster for TDT4100 - Objektorientert programmering våren 2021. Tabellen under inneholder linker til hver enkelt oppgavetekst og tema for øvingen. Linker vil bli oppdatert underveis.
| Øving | Tema |
| ----------------- | ---------------------------------------- |
| [Øving 1](oving1/README.md) | Tilstand og oppførsel |
| Øving 2 | Innkapsling og validering |
| Øving 3 | Klasser og testing |
| Øving 4 | Objektstrukturer |
| Øving 5 | Grensesnitt |
| Øving 6 | Observatør-observert og delegering |
| Øving 7 | Arv og abstrakte klasser |

View File

@ -0,0 +1,27 @@
# Tilstand og oppførsel Account
Oppgaven handler om en `Account`-klasse, som håndterer data i en konto.
Tilstanden i `Account`-objekter er som følger:
- `balance` - et desimaltall som angir beløpet som er på kontoen
- `interestRate` - et desimaltall som angir rentefot som prosentpoeng.
`Account`-klassen har fem metoder, med følgende oppførsel:
- `deposit(double)` - øker konto-beløpet med den angitte argument-verdien (et desimaltall), men kun dersom det er positivt
- `addInterest()` - beregner renta og legger det til konto-beløpet
- `getBalance()` - returnerer beløpet som er på kontoen.
- `getInterestRate()` - returnerer rentefoten
- `setInterestRate(double)` - oppdaterer renten til å være den nye verdien
## Del 1 - Tilstandsdiagram
Tegn et objekttilstandsdiagram for en tenkt bruk av `Account`-klassen. Velg selv en passende start-tilstand for `Account`-objektet og sekvens av kall.
## Del 2 - Java-kode
Skriv Java-kode for `Account`-klassen med oppførsel som er beskrevet over.
Lag en passende `toString()`-metode og en `main`-metode, slik at du kan sjekke at oppførselen stemmer med tilstandsdiagrammet (bruk samme start-tilstand og sekvens av kall)
Testkode for denne oppgaven finner du her: [src/test/java/stateandbehavior/AccountTest.java](../../src/test/java/stateandbehavior/AccountTest.java).

View File

@ -0,0 +1,32 @@
# Tilstand og oppførsel Digit
Oppgaven handler om en `Digit`-klasse, som representerer ett siffer i et gitt tallsystem.
Tilstanden i `Digit`-objekter er todelt:
- en `int` som angir tallsystemet, f.eks. 10 for titallssystemet, som oppgis i konstruktøren
- en `int`-verdi, som representerer siffer-verdien i det angitt tallsystem og må være fra og med 0 til (men ikke med) tallsystem-verdien
Konstruktøren tar inn en `int`, som initialiserer tallsystem-verdien, mens siffer-verdien settes til 0.
`Digit`-tilstanden leses og oppdateres med følgende metoder:
- `int getValue()` - returnerer siffer-verdien
- `boolean increment()` - øker siffer-verdien med én. Dersom den da når tallsystem-verdien, så (re)settes den til 0 og metoden returnerer `true`, ellers returnerer den `false`.
- `int getBase()` - returnerer tallsystemet.
## Del 1 - Tilstandsdiagram
Tegn et objekttilstandsdiagram for en tenkt bruk av `Digit`-klassen. Sekvensen av kall må illustrere hele oppførselen til `increment()`-metoden.
## Del 2 - Java-kode
Skriv Java-kode for `Digit`-klassen med oppførsel som er beskrevet over. Lag også en `toString()`-metode som returnerer siffer-verdien som en `String`, hvor sifrene 0-9 etterfølges av A-Z. F.eks. skal siffer-verdien 10 i sekstentallssystemet gi "A" som returverdi.
Lag en `main`-metode, slik at du kan sjekke at oppførselen stemmer med tilstandsdiagrammet (bruk samme sekvens av kall).
Testkode for denne oppgaven finner du her: [src/test/java/stateandbehavior/DigitTest.java](../../src/test/java/stateandbehavior/DigitTest.java).
## Ekstraoppgave
La hovedprogrammet opprette tre `Digit`-objekter, som fungerer som sifre i et tre-sifret tall. Lag en løkke som teller fra 0 til høyest mulig verdi som kan representeres i tallsystemet. Legg så til 1 så verdien av det tre-sifrede tallet igjen blir 0.

View File

@ -0,0 +1,42 @@
# Tilstand og oppførsel LineEditor
Oppgaven omhandler en `LineEditor`-klasse, som håndterer data for redigering av en linje med tekst (altså tekst uten linjeskift).
`LineEditor`-klassen holder rede på en `String`-verdi og en tekstinnsettingsposisjon og har metoder for å redigere teksten. Tekstinnsettingsposisjonen er et heltall som angir hvor endringer skjer, tilsvarende en (blinkende) cursor som står mellom tegn. Verdien $`0`$ tilsvarer foran første tegn, og høyeste mulige verdi er lengden på teksten, som tilsvarer at cursoren står bak siste tegn. Tilstanden er altså som følger:
- `text` (en `String`-verdi) - teksten
- `insertionIndex` - heltall som angir hvor i teksten redigeringer vil skje
Klassen har metoder med følgende oppførsel:
- `void left()` - flytter tekstinnsettingsposisjonen ett tegn til venstre (tilsvarende bruk av venstre piltast)
- `void right()` - flytter tekstinnsettingsposisjonen ett tegn til høyre (tilsvarende bruk av høyre piltast)
- `void insertString(String s)` - skyter teksten angitt av argumentet `s` inn i teksten på tekstinnsettingsposisjonen og forskyver tekstinnsettingsposisjonen mot høyre tilsvarende
- `void deleteLeft()` - fjerner tegnet til venstre for tekstinnsettingsposisjonen
- `void deleteRight()` - fjerner tegnet til høyre for tekstinnsettingsposisjonen
- `String getText()` - Returnerer teksten
- `void setText(String)` - oppdaterer teksten til å være den nye teksten
- `int getInsertionIndex` - returnerer hvor i teksten redigeringer nå skjer
- `void setInsertionIndex(int)` - oppdaterer hvor i teksten redigeringer skal skje
## Del 1 - Objekttilstandsdiagram
Tegn et objekttilstandsdiagram for en tenkt bruk av `LineEditor`-klassen, som dekker bruk av alle metodene.
For alle metodene bør du tenke på hva som er fornuftig oppførsel for spesielle tilfeller, f.eks. når tekstinnsettingsposisjonen er helt til venstre eller høyre. Tenk også på hva som bør skje med tekstinnsettingsposisjonen når teksten endres.
## Del 2 - Java-kode
Skriv Java-kode for `LineEditor`-klassen med oppførsel som beskrevet over.
Lag en `toString()`-metode som viser teksten med tegnet `'|'` skutt inn på tekstinnsettingsposisjonen. Lag så en `main`-metode, slik at du kan sjekke at oppførselen stemmer med tilstandsdiagrammet (bruk samme start-tilstand og sekvens av kall).
Testkode for oppgaven finner du her: [src/test/java/stateandbehavior/LineEditorTest.java](../../src/test/java/stateandbehavior/LineEditorTest.java).
## Ekstraoppgave - frivillige utvidelser
- Legg til metoden `void insert(Object o)`, som skyter inn en tekstlig representasjon av objektet `o` som gis som argument.
- Legg til metoden `void left(int n)`, som flytter tekstinnsettingsposisjonen $`n`$ tegn til venstre, og skriv om `left()` til å bruke denne. Hva bør skje dersom tekstinnsettingsposisjonen er mindre enn $`n`$?
- Legg til metoden `right(int n)`, som flytter tekstinnsettingsposisjonen $`n`$ tegn til høyre, og skriv om `right()` til å bruke denne. Hva bør skje dersom det er færre enn $`n`$ tegn til høyre for tekstinnsettingsposisjonen?
- Utvid tilstanden og legg til metoder for å håndtere markering av region, tilsvarende bruk av shift og piltaster i en vanlig teksteditor. Husk at også de eksisterende metodene må endres til å håndtere dette riktig.

View File

@ -0,0 +1,27 @@
# Tilstand og oppførsel Location
Oppgaven handler om en `Location`-klasse, som holder rede på $`(x,y)`$-posisjonen til en figur som beveger seg i et rutenett.
`Location`-klassen har følgende metoder:
- `up()` - beveger figuren en rute opp
- `down()` - beveger figuren en rute ned
- `left()` - beveger figuren en rute til venstre
- `right()` - beveger figuren en rute til høyre
- `getX()` - returnerer x-posisjonen til figuren
- `getY()` - returnerer y-posisjonen til figuren
Merk at konvensjonen innen datagrafikk og rutenettbaserte spill er at $`x`$ øker mot høyre (som i matte) og $`y`$ nedover (altså motsatt av i matte).
## Del 1 - Tilstandsdiagram
Tegn et tilstandsdiagram for en tenkt bruk av Location-klassen. Velg selv passende tilstandsvariable for $`(x,y)`$-posisjonen.
## Del 2 - Java-kode
Skriv Java-kode for `Location`-klassen med oppførsel som beskrevet over.
Lag en passende `toString()`-metode og en `main`-metode, slik at du kan sjekke at oppførselen stemmer med tilstandsdiagrammet (bruk samme start-tilstand og sekvens av kall).
Testkode for oppgaven finner du her: [src/test/java/stateandbehavior/LocationTest.java](../../src/test/java/stateandbehavior/LocationTest.java).

View File

@ -0,0 +1,47 @@
# Øving 1: Objekter og klasser, tilstand og oppførsel
__Øvingsmål__:
- Bli kjent med Java-syntaks og bruk av Eclipse
- Lære (enkel) objektorientert tankegang
- Lære å lage enkle Java-klasser og -programmer
__Øvingskrav__:
- Kunne tegne enkle tilstandsdiagrammer
- Kunne deklarere klasser, med data og kode, iht. oppgavespesifikasjon
- Kunne skrive main-metoder for å teste objekter
- Kunne bruke standardtyper og -metoder (e.g. toString()-metoden)
## NB: Viktig beskjed!
For å få testene og eventuell kode til øvingene lokalt brukes systemet git. I Eclipse kan du klikke på Git --> Pull i menylinja for å hente den nye øvingen ved hjelp av dette. Om du ikke har denne i menylinjen, er det også mulig å høyreklikke på en av prosjektmappene og velge Team --> Pull.
## Dette må du gjøre
Oppgavene for denne øvingenskal du lagre i `ovinger/src/main/java/stateandbehavior`. Test-filene som kjøres for å versifisere ligger i `ovinger/src/test/java/stateandbehavior`.
Hvis du ikke allerede har gjort det, må du installere Eclipse med det ferdigkonfigurerte oppsettet for TDT4100. Se [denne](https://www.ntnu.no/wiki/display/tdt4100/Installasjon+av+Eclipse) wikisiden.
Du skal velge og gjennomføre minst tre av de følgende oppgavene angående [Tilstand og oppførsel](https://www.ntnu.no/wiki/pages/viewpage.action?pageId=65937373).
- [Account (Lett)](./Account.md)
- [Location (Lett)](./Location.md)
- [Digit (Lett)](./Digit.md)
- [UpOrDownCounter (Medium)](./UpOrDownCounter.md)
- [LineEditor (Vanskelig)](LineEditor.md)
- [Stopwatch (Vanskelig)](Stopwatch.md)
- [Rectangle (Vanskelig)](Rectangle.md)
Oppgavene er merket med en vanskelighetsgrad relativt til hverandre. Det er en god idé å begynne med de lettere oppgavene dersom du ikke er komfortabel med pensum så langt, men det er anbefalt å prøve seg på de vanskeligere oppgavene om du synes de første oppgavene er uproblematiske. Dersom du allerede føler deg trygg på punktene i øvingskravene kan du forsøke å gå rett på de vanskeligere oppgavene. Du er selvfølgelig velkommen til å løse flere oppgaver enn minstekravet, hvilket lurt gjøres med tanke på eksamen og et langt liv som programmerende.
Før du setter i gang kan det vært lurt å lese wiki-siden om [Tilstand og oppførsel](https://www.ntnu.no/wiki/pages/viewpage.action?pageId=65937373) nøye, samt ta en titt på det tilhørende `Counter`-eksempelet. Forelesningene og tilhørende øvingsforelesning er selvsagt også lure å få med seg
Det finnes også masse ressurser på [wikien](https://www.ntnu.no/wiki/display/tdt4100/Faginnhold) om hvordan ulike metoder skal fungere. F.eks `toString`-metoden og metoder for teksthåndtering. Naviger deg litt rundt om du lurer på noe.
### Hjelp/Mistanke om bugs
Ved spørsmål eller behov for hjelp konsulter studassen din i saltiden hans / hennes. Du kan også oppsøke andre studasser på sal eller legge ut et innlegg på Piazza.
### Godkjenning
Last opp kildekode på Blackboard innen den angitte innleveringsfristen. Innlevert kode skal demonstreres for stud.ass innen én uke etter innleveringsfrist. Se for øvrig Blackboard-sidene for informasjon rundt organisering av øvingsopplegget og det tilhørende øvingsreglementet.

View File

@ -0,0 +1,65 @@
# Tilstand og oppførsel Rectangle
Oppgaven handler om en `Rectangle`-klasse, som håndterer et firkantet område i et koordinatsystem, med sider parallelle med koordinataksene.
Tilstanden i `Rectangle`-objekter er ikke spesifisert eksplisitt, men må velges slik at metodene nedenfor kan implementerers. Merk at alle metodene jobber med heltallsstørrelser.
`Rectangle`-klassen har metoder for å spørre om tilstanden og endre tilstanden. Spørremetodene dekker høyde og bredde og koordinatene til øverste venstre og nederste høyre hjørne og om rektanglet inneholder spesifikke punkt(er). Endringsmetodene dekker utviding ved å legge til punkter.
**Merk**: `Rectangle`-klassen fungerer som om du krysser ut et rutenett, altså at et punkt ("kryss") har en lengde og bredde på 1, ikke som i matematikk der punkter ikke har størrelser. Bildeserien under viser et eksempel på hvordan bredde og høyde endres når man legger til punkter i rektangelet.
<img alt="Tomt rektangel" src="fig/rectangle/step1.png" width="500px" />
<br />
<img alt="Rektangel med et punkt" src="fig/rectangle/step2.png" width="500px" />
<br />
<img alt="Rektangel steg 3" src="fig/rectangle/step3.png" width="500px" />
<br />
<img alt="Rektangel steg 4" src="fig/rectangle/step4.png" width="500px" />
<br />
Logikken til metodene må tilfredsstille følgende krav:
- et `Rectangle`-objekt er tomt i starten
- et tomt `Rectangle`-objekt skal returnere $`0`$ for alle `get`-metodene (`minX`, `minY`, `maxX`, `maxY`), `true` for `isEmpty` og `false` for `contains`-metodene.
- et punkt har bredde og høyde lik $`1`$, så dersom en legger punktet $`(x,y)`$ til et tomt `Rectangle`-objekt, så skal `getMinX` og `getMaxX` returnere $`x`$, `getMinY` og `getMaxY` skal returnere $`y`$ og `getWidth` og `getHeight` skal returnere $`1`$.
- når en utvider et `Rectangle`-objekt med en av `add`-metodene, så skal ikke rektanglet bli større enn nødvendig.
Spørremetoder:
- `int getMinX()` og `int getMinY()` - returnerer henholdsvis $`x`$- og $`y`$-koordinatene til punktet med lavest $`(x,y)`$-verdier som er inneholdt i dette rektanglet. Dersom dette rektanglet er tomt, så skal $`0`$ returneres.
- `int getMaxX()` og `int getMaxY()` - returnerer henholdsvis $`x`$- og $`y`$-koordinatene til punktet med høyest $`(x,y)`$-verdier som er inneholdt i dette rektanglet. Dersom dette rektanglet er tomt, så skal $`0`$ returneres.
- `int getWidth()` og `int getHeight()` - returnerer henholdsvis bredden og høyden til rektanglet. Begge skal returnere $`0`$, dersom dette rektanglet er tomt.
- `boolean isEmpty()` - returnerer `true` om rektanglet er tomt, dvs. om bredden og/eller høyden er $`0`$.
- `boolean contains(int x, int y)` - returnerer `true` om punktet $`(x,y)`$ er inneholdt i dette rektanglet, og `false` ellers.
- `boolean contains(Rectangle rect)` - returnerer `true` om hele `rect`, dvs. alle punktene i `rect`, er inneholdt i dette rektanglet, og false ellers. Dersom `rect` er tomt, så skal `false` returneres.
Endringsmetoder:
- `boolean add(int x, int y)` - utvider (om nødvendig) dette rektanglet slik at det (akkurat) inneholder punktet $`(x,y)`$. Etter kallet skal altså `contains(x, y)` returnere `true`. Returnerer `true` om dette rektanglet faktisk ble endret, ellers `false`.
- `boolean add(Rectangle rect)` - utvider (om nødvendig) dette rektanglet slik at det (akkurat) inneholder hele `rect`-argumentet. Returnerer `true` om dette rektanglet faktisk ble endret, ellers `false`. Dersom `rect` er tomt, så skal dette rektanglet ikke endres.
Andre metoder:
- `Rectangle union(Rectangle rect)` - returnerer et nytt `Rectangle`-objekt som tilsvarer kombisjonen av dette rektanglet og `rect`-argumentet. Alle punktene som finnes i ett av rektanglene skal altså være inneholdt i rektanglet som returneres.
## Del 1 - Tilstandsdiagram
Tegn et objekttilstandsdiagram for en tenkt bruk av `Rectangle`-klassen. Velg en sekvens av kall som bruker alle fire endringsmetoder.
## Del 2 - Java-kode
Skriv Java-kode for `Rectangle`-klassen med oppførsel som er beskrevet over.
Lag en passende `toString()`-metode og et hovedprogram, slik at du kan sjekke at oppførselen stemmer med tilstandsdiagrammet (bruk samme sekvens av kall).
Testkode for denne oppgaven finner du her: [src/test/java/stateandbehavior/RectangleTest.java](../../src/test/java/stateandbehavior/RectangleTest.java).
## Ekstraoppgave
Implementer følgende metoder:
- `Rectangle intersection(Rectangle rect)` - returnerer et nytt `Rectangle`-objekt som tilsvarer overlappet mellom dette rektanglet og `rect`-argumentet. Alle punktene som finnes i begge rektanglene skal altså være inneholdt i rektanglet som returneres.
- `boolean intersects(Rectangle rect)` - returnerer `true` om dette rektanglet og `rect`-argumentet overlapper, dvs. om det finnes ett eller flere punkter som er inneholdt i begge disse rektanglene.

View File

@ -0,0 +1,48 @@
# Tilstand og oppførsel Stopwatch
Oppgaven handler om en `StopWatch`-klasse, som implementerer en stoppeklokke med funksjoner for å starte, ta rundetider og stoppe.
Klassen skal implementere logikken ofte funnet på stoppeklokker på smarttelefoner.
<img alt="Stopwatch" src="fig/stopwatch.gif" width="250px" style="float: right" />
For å holde styr på tiden som går vil `StopWatch`-klassen bli kalt utenfra (altså noe du slipper å implementere i denne oppgaven) på en `tick(int)`-metode. I dataverdenen er et tick (tikk på norsk) minste målbare diskret tidsenhet. I denne oppgaven er 1 tikk = 1 millisekund. F.eks. vil et kall `tick(3)` fortelle en `StopWatch`-instans at $`3`$ tikk har gått siden sist gang `tick()` ble kalt.
StopWatch skal fungere på følgende måte:
- Klokken startes når man ønsker å starte tidtakningen.
- Alle tikk etter at klokken har blitt startet skal medregnes i tidtakningen.
- Klokken stoppes når man ønsker å stoppe tidtakningen. Da er tidtakningen helt ferdig. Det er ikke en pause i tidtakningen - klokken skal ikke startes igjen.
- Det skal være mulig å ta rundetider.
- Første rundetid startes når klokken starter.
- Under tidtakningen kan man starte en ny rundetid, og dermed implisitt avslutte den nåværende.
- Siste rundetid avsluttes når klokken stoppes.
`StopWatch`-klassen må ha metoder for å spørre om tilstanden og metoder for å endre tilstanden.
Klassen skal ha følgende spørremetoder:
- `boolean isStarted()` - returnerer `true` om klokken har blitt startet eller `false` om den ikke har blitt startet
- `boolean isStopped()` - returnerer `true` om klokken har blitt stoppet eller `false` om den ikke har blitt stoppet. Merk at her snakker vi om at klokken har blitt stoppet, ikke om klokken går eller ikke.
- `int getTicks()` - returnerer det totale antall tikk (millisekunder) som har gått i levetiden til klokken uavhengig om klokken har vært startet eller stoppet.
- `int getTime()` - returnerer antall tikk som har gått under tidtakningen. Hvis tidtakningen ikke har startet returner $`-1`$. Merk at hvis klokken er startet, men ikke stoppet, skal metoden returnere antall tikk som har gått siden klokken ble startet til nå. Hvis klokken er stoppet skal metoden returnere antall tikk som har gått fra klokken ble startet til klokken ble stoppet.
- `int getLapTime()` - returnerer antall tikk som har gått under nåværende rundetid til nå. Hvis tidtakningen ikke har startet returner $`-1`$.
- `int getLastLapTime()` - returnerer lengden på forrige avsluttede rundetid. Hvis det ikke er noen tidligere rundetider returner $`-1`$.
Klassen skal ha følgende metoder for å endre tilstanden:
- `void tick(int ticks)` - forteller klokken at `ticks` antall tikk har gått.
- `void start()` - starter klokken.
- `void lap()` - avslutter nåværende rundetid og starter en ny.
- `void stop()` - stopper klokken.
## Del 1 - Tilstandsdiagram
Tegn et objekttilstandsdiagram for en tenkt bruk av `StopWatch`-klassen. Velg en sekvens av kall som både starter klokken, tar rundetider og stopper klokken.
## Del 2 - Java-kode
Skriv Java-kode for `StopWatch`-klassen med oppførsel som er beskrevet over.
Lag en passende `toString()`-metode og en `main`-metode, slik at du kan sjekke at oppførselen stemmer med tilstandsdiagrammet (bruk samme sekvens av kall).
Testkode for denne oppgaven finner du her: [src/test/java/stateandbehavior/StopWatchTest.java](../../src/test/java/stateandbehavior/StopWatchTest.java).

View File

@ -0,0 +1,14 @@
# Tilstand og oppførsel  UpOrDownCounter
I denne oppgaven skal du programmere en teller, ikke ulik den som er beskrevet i [Tilstand og oppførsel](https://www.ntnu.no/wiki/pages/viewpage.action?pageId=65937373) og kodet i [Tilstand og oppførsel - Java-kode for Counter-eksempel](https://www.ntnu.no/wiki/pages/viewpage.action?pageId=65937823), som også skal håndtere tilfellet hvor slutt-verdien er lavere enn start-verdien ved å telle nedover.
## Del 1 - Java-kode
`UpOrDownCounter`-klassen skal altså ha de samme konstruktørene/metodene:
- `UpOrDownCounter(int start, int end)` - initialiserer objektet med angitte start- og slutt-verdier, hvor altså slutt kan være større eller mindre enn start, slik at telleren teller henholdsvis opp eller ned. Lik start og slutt-verdi skal utløse unntak av typen `IllegalArgumentException` (se [Koding av valideringsmetoder](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+valideringsmetoder)).
- `int getCounter()` - returnerer telleren
- `boolean count()` - beveger telleren i retning av slutt-verdien og returnerer true så lenge den ikke har nådd den, altså om telleren har mer igjen, og false ellers.
Testkode for oppgaven finner du her: [src/test/java/stateandbehavior/UpOrDownCounterTest.java](../../src/test/java/stateandbehavior/UpOrDownCounterTest.java)

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -0,0 +1,36 @@
# Innkapsling - Account-oppgave
Oppgaven er en innkapslet og litt utvidet variant av [Account-oppgaven](../oving1/Account.md) under temaet [Tilstand og oppførsel](https://www.ntnu.no/wiki/pages/viewpage.action?pageId=65937373), og stiller bl.a. større krav til validering.
Et `Account`-objekt inneholder data om beløpet som står på kontoen og rentefoten (prosentpoeng).
Begge verdiene skal oppgis og settes når objektet opprettes og ingen av verdiene kan være negative.
`Account`-klassen har metoder for å sette inn og ta ut beløp, og legge til påløpte renter, i tillegg til en konstruktør for å initialisere en ny konto. Alle disse skal utløse unntak av typen `IllegalArgumentException`, dersom et argument ikke tilfredstiller kravene som angis.
- `Account(double, double)` - Konstruktøren skal ta inn startbeløpet og rentefoten (prosentpoeng). Ingen av disse kan være negative.
- `double getBalance()` - Returnerer beløpet som står på kontoen.
- `double getInterestRate()` - Returnerer renten på kontoen.
- `void setInterestRate(double)` - Denne metoden tar inn en ikke-negativ verdi og setter renten til denne verdien.
- `void deposit(double)` - Denne metoden tar inn et ikke-negativt beløp og øker konto-beløpet tilsvarende.
- `void withdraw(double)` - Denne metoden tar inn et ikke-negativt beløp og minsker konto-beløpet tilsvarende. Dersom det nye konto-beløpet er negativt, så skal tilstanden ikke endre, og det skal utløses et unntak av typen `IllegalArgumentException`.
- `void addInterest()` - beregner renta og legger det til konto-beløpet.
__Leseliste__
- [Gyldig tilstand](https://www.ntnu.no/wiki/display/tdt4100/Gyldig+tilstand) - Tilstanden til et objekt er verdien av alle attributtene. En viktig del av [oppførselen til et objekt](https://www.ntnu.no/wiki/pages/viewpage.action?pageId=65937373) er å sikre at tilstanden til objektet alltid er *gyldig*, dvs. at alle attributtene har gyldige/konsistente verdier.
- [Innkapsling](https://www.ntnu.no/wiki/display/tdt4100/Innkapsling) - Innkapsling er en programmeringsteknikk som har som formål å hindre direkte tilgang til tilstanden til et objekt fra objekter av andre klasser.
- [Koding av valideringsmetoder](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+valideringsmetoder) - En valideringsmetode har som formål å sjekke om en eller flere verdier er gyldige, slik at dette kan sjekkes av f.eks. setter-metoder før tilsvarende attributter evt. settes.
## Del 1: Innkapsling og validering - Teori
Ta utgangspunkt i koden fra [Account](../oving1/Account.md)-klassen og besvar følgende spørsmål:
- Forklar hvorfor metodene over kan sies å være en komplett innkapsling av tilstanden?
- Er denne klassen data-orientert eller tjeneste-orientert? Begrunn svaret!
## Del 2 - Java-kode
Implementer endringene fra [Account](../oving1/Account.md)-klassen i den nye `Account`-klassen med oppførsel som beskrevet over.
Testkode for denne oppgaven finner du i [encapsulation/AccountTest.java](../../src/test/java/encapsulation/AccountTest.java).

View File

@ -0,0 +1,39 @@
# Innkapsling og gyldig tilstand - Oppgave om innkapsling og validering av klasser
I denne oppgaven skal du velge tre oppgaver som du har gjort i øving 1 fra listen nedenfor, og innkapsle og validere disse klassene.
Skriv svar (stikkord/få, korte setninger) på spørsmål 1-4 (fra del 1 nedenfor) som kommentarer i koden din.
__Oppgaver__:
- [Digit-oppgave](../oving1/Digit.md) (Lett)
- [UpOrDownCounter-oppgave](../oving1/UpOrDownCounter.md) (Lett)
- [Location-oppgave](../oving1/Location.md) (Lett)
- [StopWatch-oppgave](../oving1/Stopwatch.md) (Medium)
- [Rectangle-oppgave](../oving1/Rectangle.md) (Vanskelig)
- [LineEditor-oppgave med fri peker](LineEditor.md) (Vanskelig)
Merk at spesifikasjonen for [LineEditor](../oving1/LineEditor.md) er litt utvidet for denne oppgaven. Se [LineEditor-oppgave med fri peker](LineEditor.md).
## Del 1: Innkapsling og validering - Teori
Ta utgangspunkt i (koden for) den originale klassen og besvar følgende spørsmål:
- Hvordan skal private og public brukes for at denne klassen skal være korrekt innkapslet?
- Hva slags validering bør legges til for å sikre gyldig tilstand?
- Hvilke metoder må evt. legges til?
- Vil du karakterisere denne klassen som data-orientert eller tjeneste-orientert. Begrunn svaret!
## Del 2: Java-kode
Implementer endringene foreslått i punktene 1-3 og prøv ut klassene.
Testkoder for denne oppgaven finner du her:
- [encapsulation/DigitTest.java](../../src/test/java/encapsulation/DigitTest.java)
- [encapsulation/LineEditorTest.java](../../src/test/java/encapsulation/LineEditorTest.java)
- [encapsulation/RectangleTest.java](../../src/test/java/encapsulation/RectangleTest.java)
- [encapsulation/UpOrDownCounterTest.java](../../src/test/java/encapsulation/UpOrDownCounterTest.java)
- [encapsulation/StopWatchTest.java](../../src/test/java/encapsulation/StopWatchTest.java)
Testkodene viser om du har innkapslet på samme måte som fagstaben har gjort. Din kode kan fungere selv om testene feiler, dersom du har valgt en løsere/strammere innkapsling iht. argumentasjonen i 1-3. Er du enig med hvordan fagstaben har gjort det?

View File

@ -0,0 +1,9 @@
# Gyldig tilstand - LineEditor-oppgave med fri peker
Oppgaven utvider [Tilstand og oppførsel - LineEditor-oppgave](../oving1/LineEditor.md) med validering.
Denne oppgaven tar utgangspunkt i [Tilstand og oppførsel - LineEditor-oppgave](../oving1/LineEditor.md) og utvider `LineEditor`-klassen med metoder for å endre teksten og tekstinnsettingsposisjonen direkte, så det blir enklere å gjøre om tilstanden til objektet. Når teksten endres skal tekstinnsettingsposisjonen settes til å være bak teksten.
Hvordan vil du implementere dette med én eller flere metoder, inkludert valideringsmetode(r), slik at en er sikret at `LineEditor`-objekter aldri blir ugyldige?
JExercise-testkode for denne oppgaven finner du her: [tests/encapsulation/LineEditorTest.java](../../tests/encapsulation/LineEditorTest.java).

View File

@ -0,0 +1,59 @@
# Innkapsling - Person-oppgave
Oppgaven handler om en `Person`-klasse, som håndterer informasjon om en person (navn, e-post, fødselsdato og kjønn) og implementerer innkapslingsmetoder med validering.
Et `Person`-objekt inneholder *navn* (både fornavn og etternavn), *e-post*, *fødselsdag* og *kjønn*:
- Navnet inneholder både fornavn og etternavn (og ingen mellomnavn), som begge må være på minst to bokstaver langt, navnene må være skilt med ett mellomrom og kun inneholde bokstaver.
- E-post-adressen (hvis den ikke er `null`) må være på formen `fornavn.etternavn@domene.landskode`, f.eks. `hallvard.trætteberg@ntnu.no` (en liste over landskoder finner du [her](http://pastebin.com/chG6WLWF)).
- Fødselsdagen skal være et dato-objekt (java.util.Date) og kan ikke være frem i tid.
- En persons kjønn skal kunne returneres som `'M'`, `'F'` eller `'\0'` (null-tegnet).
`Person`-klassen har tilgangsmetoder for å hente og sette tilstandene. Dersom et argument er ugyldig i seg selv, så skal unntaket `IllegalArgumentException` utløses.
- `setName(String)` - oppdaterer navnet (fornavn og etternavn med mellomrom mellom), dersom det er gyldig i henhold til kravene over. Det er greit om navnet som settes, ikke stemmer med e-post-adressen.
- `setEmail(String)` - oppdaterer e-post-adressen, etter å ha sjekket at den stemmer med navnet.
- `setBirthday(Date)` - oppdaterer fødselsdatoen
- `setGender(char)` - oppdaterer kjønnet
I tillegg til disse såkalte *setter*-metodene, så må `Person`-klassen ha tilsvarende *getter*-metoder.
__Leseliste__
- [Gyldig tilstand](https://www.ntnu.no/wiki/display/tdt4100/Gyldig+tilstand) - Tilstanden til et objekt er verdien av alle attributtene. En viktig del av [oppførselen til et objekt](https://www.ntnu.no/wiki/pages/viewpage.action?pageId=65937373) er å sikre at tilstanden til objektet alltid er *gyldig*, dvs. at alle attributtene har gyldige/konsistente verdier.
- [Innkapsling](https://www.ntnu.no/wiki/display/tdt4100/Innkapsling) - Innkapsling er en programmeringsteknikk som har som formål å hindre direkte tilgang til tilstanden til et objekt fra objekter av andre klasser.
- [Koding av valideringsmetoder](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+valideringsmetoder) - En valideringsmetode har som formål å sjekke om en eller flere verdier er gyldige, slik at dette kan sjekkes av f.eks. setter-metoder før tilsvarende attributter evt. settes.
- [String-klassen](https://www.ntnu.no/wiki/display/tdt4100/java.lang.String) - Siden gir en innføring i String-klassen og en oversikt over nyttig String-metoder.
## Del 1 Java-kode
Implementer `Person`-klassen med stram innkapsling. Eventuelle hjelpemetoder for validering bør også ha stram innkapsling. Det kan være lurt å lese om [String-klassen](https://www.ntnu.no/wiki/display/tdt4100/java.lang.String) og dens metoder før du setter i gang.
Testkode for denne oppgaven finner du i [encapsulation/PersonTest.java](../../src/test/java/encapsulation/PersonTest.java).
Merk at din implementasjon må ligge i en pakke med samme navn som testkodens pakke. Pass derfor på at Person-klassen ligger i pakken `encapsulation`.
## Del 2 - Spørsmål om innkapsling
- Foreslå en alternativ innkapsling av navnet. Hint: del opp.
- Foreslå *to* alternative strategier for å kapsle inn tilstand som er koblet slik navn og e-post er. Hint: 1) samtidig og 2) dekoble.
## Ekstraoppgave - Personnummer
Utvid klassen med en persons personnummer. Personnummeret kan ikke settes før kjønn og fødselsdag er satt.
Et personnummer består grovt sett av fødselsdatoen, et (vilkårlig) løpenummer og to kontrollsifre. Kontrollsifrene gjør det enklere å sjekke om et personnummer er ekte. Mer spesifikt er reglene for personnummer som følger:
- Et personnummer består av 11 siffer, med følgende struktur: **D1D2**M1M2**Y1Y2**N1N2N3**K1K2** (fet skrift for lesbarhet).
- De seks første sifrene, **D1D2**M1M2**Y1Y2**, tilsvarer fødselsdatoens dag (1-31), måned (1-12) og år (0-99).
- De tre neste sifrene, N1N2N3, kan antas å være vilkårlige, men N3 må være partall for kvinner og oddetall for menn.
- De to siste sifrene, K1K2, er kontrollsifre, som hver for seg beregnes ut fra de foregående sifrene. Formelen for dem begge er `11 (VS % 11)`, hvor VS (veid sum) for `K1` er `D1*F1 + D2*F2 + … + N2*F8 + N3*F9` og `VS` for `K2` er `D1*G1 + D2*G2 + … + N3*G9 + K1*G10`. Fene og Gene er oppgitt i tabellen under. Dersom formelen gir tallet 11 så skal verdien 0 brukes isteden. Om både K1 og K2 stemmer med kontrollsifferne generert basert på formlene over, så er kontrollsifferne i personnummeret gyldig.
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| F | 3 | 7 | 6 | 1 | 8 | 9 | 4 | 5 | 2 |
| G | 5 | 4 | 3 | 2 | 7 | 6 | 5 | 4 | 3 | 2 |
Implementer kode for å sette (med metoden `setSSN(String)` og validere et gyldig personnummer.
Testkode for denne oppgaven finner du i [encapsulation/PersonTest2.java](../../src/test/java/encapsulation/PersonTest2.java).

View File

@ -0,0 +1,49 @@
# Øving 2: Innkapsling og validering
__Øvingsmål__:
- Lære å innkapsle klasser og metoder etter god programmeringsskikk
- Lære å validere argumenter for å sikre gyldig tilstand
__Øvingskrav__:
- Kunne forstå og implementere hvordan en klasse best bør innkapsles
- Kunne skrive kode for å validere argumenter for å sikre gyldig tilstand
- Kunne utløse exceptions ved ugyldige argumenter i en metode
## NB: Viktig beskjed!
Etter at du har hentet ned/pullet denne øvingen, **må** du høyreklikke på prosjektet og kjøre *Maven -> Update Project*. Vi har fikset problemet med *.classpath*-filene, og det er veldig viktig at dette blir gjort for at prosjektet fortsatt skal funke! Hvis du har gjort endringer i en *.classpath*-fil vil du få en merge-conflict når du puller øvingen. Løsning på dette problemet finner du [her.](../classpath_fix/README.md)
## Dette må du gjøre
__Del 1: Teori__
Les [wikisiden om innkapsling](https://www.ntnu.no/wiki/display/tdt4100/Innkapsling) og svar på følgende:
- Hva er en **synlighetsmodifikator**?
- Hva er forskjellen på **private** og **public** og når brukes de?
Teori-oppgavene besvares i en tekstfil eller på papir, og gjennomgås med studass ved godkjenning.
__Del 2: Programmering__
Velg minst 2 av følgende oppgaver:
- [Innkapsling og validering av 3 eksisterende klasser](./Encapsulation.md) (Varierende)
- [Account](./Account.md) (Lett)
- [Person](./Person.md) (Medium)
- [Vehicle](./Vehicle.md) (Medium)
Oppgavene for denne delen skal du lagre i `ovinger/src/main/java/encapsulation`. Test-filene for å verifisere korrekt implementasjon ligger i `ovinger/src/test/java/encapsulation`.
Oppgavene er markert med en vanskeliggrad relativt til hverandre. Det er en god idé å begynne med de lettere oppgavene dersom du ikke er komfortabel med pensum så langt, men det er anbefalt å prøve seg på de vanskeligere oppgavene om du synes de første oppgavene er uproblematiske. Dersom du allerede føler deg trygg på punktene i øvingskravene kan du forsøke å gå rett på de vanskeligere oppgavene. Du er selvfølgelig velkommen til å løse flere oppgaver enn minstekravet, hvilket lurt gjøres med tanke på eksamen og et langt liv som programmerende.
Før du setter i gang kan det vært lurt å lese nevnte [wikiside om innkapsling](https://www.ntnu.no/wiki/display/tdt4100/Innkapsling) nøye. Forelesningene og tilhørende øvingsforelesning er selvsagt også lure å få med seg.
### Hjelp / mistanke om bugs
Ved spørsmål eller behov for hjelp konsulter studassen din i saltiden hans / hennes. Du kan også oppsøke andre studasser på sal eller legge ut et innlegg på Piazza.
### Godkjenning
Last opp kildekode på Blackboard innen den angitte innleveringsfristen. Innlevert kode skal demonstreres for stud.ass innen én uke etter innleveringsfrist. Se for øvrig Blackboard-sidene for informasjon rundt organisering av øvingsopplegget og det tilhørende øvingsreglementet.

View File

@ -0,0 +1,30 @@
# Innkapsling - Vehicle-oppgave
Oppgaven handler om en `Vehicle`-klasse, som håndterer informasjon om et kjøretøy og implementerer innkapslingsmetoder med validering.
Et `Vehicle`-objekt inneholder type *kjøretøy*, *drivstoffet* det bruker og *registreringsnummer*:
- Typen kan være enten motorsykkel eller bil.
- Drivstoffet kan være enten hydrogen, elektrisitet, diesel eller bensin. Kun biler kan gå på hydrogen.
- Gyldige registreringsnummeret avhenger av typen kjøretøy og drivstoff etter følgende regler:
- Kjøretøy som går på elektrisitet skal ha registreringsnummer som starter med bokstavene `"EL"` eller `"EK"`
- Hydrogenbilene har registreringsnummer som begynner med bokstavene `"HY"`
- Dieselkjøretøy og bensinkjøretøy har registreringsnummer som begynner på to bokstaver. De kan ikke være `"EK"`, `"EL"` eller `"HY"`. Bokstavene Æ, Ø og Å skal ikke brukes.
- For alle drivstoff gjelder det at det skal være brukt store bokstaver.
- Ellers så gjelder det at motorsykler har 4 sifre etter bokstavene, mens biler har 5.
Følgende metoder må implementeres:
- `Vehicle(char, char, String)` - Konstruktør der argument-rekkefølgen må være kjøretøystype, drivstofftype og registreringsnummer. Ved ugyldige argumenter utløses unntak av typen `IllegalArgumentException`.
- `getFuelType()` - returnerer type drivstoff som følgende: `'H'` for hydrogen, `'E'` for elektrisitet, `'D'` for diesel eller `'G'` for bensin.
- `getRegistrationNumber()` - returnerer registreringsnummeret
- `setRegistrationNumber(String)` - endrer registreringsnummeret dersom det er gyldig i henhold til kravene over, og utløser unntak av typen `IllegalArgumentException` dersom det ikke er gyldig.
- `getVehicleType()` - returnerer kjøretøystype: `'M'` for motosykkel, `'C'` for bil.
## Del 1 Java-kode
Implementer `Vehicle`-klassen som beskrevet over med stram innkapsling. Eventuelle hjelpemetoder for validering bør også ha stram innkapsling. Det kan være lurt å lese om [String-klassen](https://www.ntnu.no/wiki/display/tdt4100/java.lang.String) og dens metoder før du setter i gang.
Testkode for denne oppgaven finner du i [encapsulation/VehicleTest.java](../../src/test/java/encapsulation/VehicleTest.java).
Merk at din implementasjon må ligge i en pakke med samme navn som testkodens pakke. Pass derfor på at Vehicle-klassen ligger i pakken `encapsulation`.

View File

@ -0,0 +1,33 @@
# Innkapsling - Card-oppgave
Denne oppgaven handler om to klasser for kortspill: `Card` (kort) og `CardDeck` (kortstokk), der den siste inneholder ett eller flere `Card`-objekter.
I mange sammenhenger vil objekter av en klasse inneholde eller "eie" objekter av andre klasser. Når en klasse er assosiert med én instans av en (annen) klasse er dette en [1-1-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-1-assosiasjoner) og når en klasse er assosiert med flere instanser av en annen klasse er dette en [1-n-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-n-assosiasjoner). I denne oppgaven skal du implementere logikk for en kortstokk som inneholder kort. Nedenfor beskrives begge klassene og metodene disse skal inneholde.
`Card`-klassen er en såkalt *verdiklasse*, som kodes slik at objektene ikke kan endres etter at de er opprettet. Et `Card`-objekt har en *kortfarge*, som er en av bokstavene `'S'` (for spades), `'H'` (for hearts), `'D'` (for diamonds) og `'C'` (for clubs), og *tallverdi*, som er et heltall mellom 1 (ess) og 13 (konge). Følgende metoder må implementeres:
- `Card(char, int)` - konstruktøren initialiserer kortfarge og tallverdi med henholdsvis første og andre argument. Konstruktøren må utløse unntak av typen `IllegalArgumentException` hvis en (eller begge) av disse verdiene er ugyldige.
- `getSuit()` - returnerer kortfargen som en char, en av `'S'`, `'H'`, `'D'` eller `'C'`.
- `getFace()` - returnerer tallverdien som en int mellom 1 og 13 (inklusive).
- `toString()` - returnerer en streng som består av `<suit><face>` e.g. for spar ess skal `"S1"` returneres.
`CardDeck`-objekter inneholder initielt et visst antall kort av de fire kortfargene `'S'`, `'H'`, `'D'` og `'C'`. Klassen inneholder standardmetoder for å lese hvor mange og hvilke kort, og en metode for å endre tilstand.
Konstruktør:
- `CardDeck(int n)` - fyller kortstokken med de `n` første kortene av hver kortfarge, totalt `n*4` kort, med spar 1 som første kort (indeks nr. 0), spar 2 som andre (nr. 1), spar 3 som tredje (nr. 2), spar 4 som fjerde (nr. 3), ..., hjerter 1 som fjortende (nr. 13), hjerter 2 som femtende (nr. 4) osv. i.e. først alle spar, så hjerter, så ruter og så kløver, alle i stigende rekkefølge.
Lesemetoder:
- `getCardCount()` - returnerer hvor mange Card-objekter som `CardDeck`-objektet inneholder.
- `getCard(int n)` - returnerer kort nr. `n` eller utløser et `IllegalArgumentException` hvis `n` ikke er gyldig. Kort nr. 0 er det første kortet i kortstokken.
Endringsmetode:
- `shufflePerfectly()` - stokker kortstokken ved å dele den i to like store deler og flette de to delene perfekt, slik at kortet på toppen forblir på toppen og kortet på bunnen forblir på bunnen (se [http://en.wikipedia.org/wiki/Out_shuffle](http://en.wikipedia.org/wiki/Out_shuffle)).
## Oppgave: Java-kode
Skriv `Card`- og `CardDeck`-klassene, slik at de har ønsket oppførsel og er skikkelig innkapslet.
Testkode for denne oppgaven finner du i [encapsulation/CardDeckTest.java](../../src/test/java/encapsulation/CardDeckTest.java) og [encapsulation/CardTest.java](../../src/test/java/encapsulation/CardTest.java).

View File

@ -0,0 +1,37 @@
# Debugging - CoffeeCup-oppgave
Oppgaven handler om feilsøking i en **CoffeeCup**- og en **CoffeeCupProgram**-klasse ved bruk av [debuggeren](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse) i Eclipse.
Et **CoffeeCup**-objekt inneholder kapasitet og nåværende volum av kaffe.
- Kapasitet må være et ikke-negativt flyttall, som til enhver tid må være større enn nåværende volum av kaffe.
- Nåværende volum av kaffe er et ikke-negativt flyttall som til enhver tid må være mindre enn kapasiteten til koppen.
**CoffeeCup**-klassen har følgende metoder og konstruktører:
- `void drinkCoffee(double)` og `void fillCoffee(double)`, hvor man henholdsvis drikker og fyller koppen med kaffe. Om man prøver å drikke mer enn det finnes i koppen, eller fyller for mye i koppen blir en `IllegalArgumentException` utløst.
- `void increaseCupSize(double)`, som øker størrelsen på koppen. Om man prøver å gjøre koppen mindre skjer ingenting.
- `CoffeeCup()`, en konstruktør som setter standard initialverdier til 0.0 kapasitet og 0.0 nåværende kaffe i koppen.
- `CoffeeCup(double, double)`, en konstruktør som setter initialverdier til de oppgitte verdiene.
- I tillegg har klassen noen private hjelpefunksjoner som man kan identifisere selv.
**CoffeeCupProgram**-klassen er en hovedprogramklasse som oppretter en instans av **CoffeeCup**, og utfører en sekvens av kall til koppens ulike metoder.
I denne oppgaven blir en implementasjon av **CoffeeCup** sammen med et hovedprogram utdelt, men i implementasjonen av hovedprogrammet har vi plantet noen feil. Det er to oppgaver som må løses.
CoffeeCup-koden finner du i [debugging/CoffeeCup.Java](../../src/main/java/debugging/CoffeeCup.java). CoffeeCupProgram finner du i [debugging/CoffeeCupProgram.java](../../src/main/java/debugging/CoffeeCupProgram.java).
### Leseliste
- [Debugging i Eclipse](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse) - Debuggeren er et verktøy som brukes til å analysere kjørende kode, noe som kan være svært nyttig når man vil forstå og evt. rette feil i et program.
- [Hovedprogramklasser](https://www.ntnu.no/wiki/display/tdt4100/Hovedprogramklasser) - Hovedprogramklasser er klasser som aktiveres når programmer starter opp og som initialiserer og kontrollerer/koordinerer de andre objekter i applikasjonen.
- [java.util.Random](https://docs.oracle.com/javase/8/docs/api/java/util/Random.html) - En pseudotilfeldig nummergenerator i Java.
### Oppgave 1
Målet for oppgaven er å finne en feil i funksjonen `part1()` ved hjelp av debuggeren i Eclipse. Kjør hovedprogrammet i debug-modus, og bruk dette til å finne hva kapasiteten og nåværende volum av kaffe er like før programmet utløser et unntak.
Finn også ut hvilken metode i **CoffeeCup** som utløser unntaket.
### Oppgave 2
Du fant feilen i oppgave 1, bra! Kommentér ut kallet til `part1()` i hovedprogrammet, så slipper vi å ha mer med det å gjøre.
Du skal nå finne ut hvordan nåverende volum av kaffe endrer seg i `part2()`, før programmet utløser et unntak. Lag en liste over hvilke verdier nivået har. Hvilken metode i **CoffeeCup** utløser et unntak denne gangen? Hvilken type unntak blir utløst?

View File

@ -0,0 +1,25 @@
# Innkapsling - Nim-oppgave
Denne oppgaven handler om en `Nim`-klasse, som implementerer en variant av spillet [Nim](https://en.wikipedia.org/wiki/Nim).
Spillet Nim består av **tre** hauger med brikker. To spillere velger på tur én av haugene, og fjerner så mange brikker som ønskelig, men minimum én brikke. Spillet er over når en av haugene er helt tom for brikker.
`Nim`-klassen har enkel tilstand: En spillomgang består av tre hauger med et antall brikker. `Nim`-klassen må dermed kunne representere hvor mange brikker som er i hver haug, og oppdatere dette ettersom det fjernes brikker. Hvordan dette gjøres er åpent, så lenge det er tilstrekkelig for å oppfylle oppførselen definert for klassen.
`Nim`-klassen har følgende metoder:
- `void removePieces(int number, int targetPile)` - fjerner `number` (>= 1) antall brikker fra haugen `targetPile`. `IllegalArgumentException` utløses hvis targetPile eller number er ugyldig. Siden man ikke kan gjøre trekk etter at spillet er over, må `IllegalStateException` utløses dersom metoden kalles etter det.
- `boolean isValidMove(int number, int targetPile)` - returnerer `true` dersom argumentene representerer et lovlig trekk, og `false` dersom argumentene ikke ville ført til et lovlig trekk. Her skal man kun sjekke om et trekk er lovlig å utføre, ikke faktisk endre på tilstanden. **PS**: Husk at å flytte når et spill er over ikke er et lovlig trekk.
- `boolean isGameOver()` - returnerer `true` dersom en av haugene har 0 brikker.
- `int getPile(int targetPile)` - returnerer antall brikker i haugen targetPile.
- `String toString()` - returnerer en tekststreng som oppsummerer spillets tilstand
Haugene skal identifiseres ved tall, altså at gyldige verdier for `targetPile` er 0, 1 og 2.
`Nim`-klassen skal ha en [konstruktør](https://www.ntnu.no/wiki/display/tdt4100/Klasser+i+java#Klasserijava-constructor) `Nim(int pileSize)` som lar en bestemme hvor mange brikker som skal være i hver haug, og i tillegg en tom konstruktør som initialiserer `Nim`-objektet til å ha 10 brikker i hver haug.
## Oppgave: Java-kode
Skriv `Nim`-klassen, slik at den har ønsket oppførsel og er skikkelig innkapslet.
Testkode for denne oppgaven finner du i [encapsulation/NimTest.java](../../src/test/java/encapsulation/NimTest.java).

View File

@ -0,0 +1,43 @@
# Øving 3: Klasser og testing
__Øvingsmål__:
- Lære å lage enkle Java-klasser og -programmer
- Lære å bruke debuggeren i Eclipse
__Øvingskrav__:
- Kunne tegne enkle klassediagrammer
- Kunne deklarere klasser og metoder ihht. oppgavespesifikasjon
## Dette må du gjøre
__Del 1: Programmering__
Velg minst én av oppgavene under. Merk at *Card*-oppgaven bygges videre på i både øving 5 og 6, og kan derfor være lur å gjøre, slik at man har flere oppgaver å velge mellom senere.
- [Nim](./Nim.md) (Lett)
- [Card-oppgave](./Card.md) (Medium)
- [RPN-kalkulator](./RPN.md) (Vanskelig)
Oppgavene for denne øvingen skal du lagre i `ovinger/src/main/java/encapsulation`. Test-filene ligger i `ovinger/src/test/java/encapsulation`.
__Del 2: Klassediagram__
Tegn et [klassediagram](https://www.ntnu.no/wiki/display/tdt4100/Klassediagrammer) for oppgaven du velger i del 1. Klassediagrammet kan for eksempel skrives på papir eller tegnes i et valgfritt program. Diagrammet skal demonstrerer på sal, men det er ikke nødvendig å levere det på Blackboard.
__Del 3: Debugger__
I tillegg skal en kort oppgave som omhandler bruk av [debuggeren i Eclipse](https://www.ntnu.no/wiki/display/tdt4100/Bruk+av+debuggeren+i+Eclipse) løses. Oppgaven skal demonstreres for en læringsassistent på sal:
- [CoffeeCup](./CoffeeCup.md) (Lett/Medium)
Oppgavene er merket med en vanskelighetsgrad relativt til hverandre. Det er en god idè å begynne med de lettere oppgavene dersom du ikke er komfortabel med pensum så langt, men det er anbefalt å prøve seg på de vanskeligere oppgavene om du synes de første oppgavene er uproblematiske. Dersom du allerede føler deg trygg på punktene i øvingskravene kan du forsøke å gå rett på de vanskeligere oppgavene. Du er selvfølgelig velkommen til å løse flere oppgaver enn minstekravet, noe som er lurt med tanke på eksamen og et langt liv som programmerer.
### Hjelp / mistanke om bugs
Ved spørsmål eller behov for hjelp konsulter studassen din i saltiden hans / hennes. Du kan også oppsøke andre studasser på sal eller legge ut et innlegg på Piazza.
### Godkjenning
Last opp kildekode på Blackboard innen den angitte innleveringsfristen. Innlevert kode skal demonstreres for en læringsassistent innen én uke etter innleveringsfrist. Se for øvrig Blackboard-sidene for informasjon rundt organisering av øvingsopplegget og det tilhørende øvingsreglementet.

View File

@ -0,0 +1,70 @@
# Innkapsling - RPN-kalkulator-oppgave
Oppgaven handler om å lage en RPN-kalkulator (RPN = Reverse Polish Notation). I denne oppgaven kommer du til å ta i bruk en *stack*, og utføre matematiske operasjoner.
Her er en forklaring av hvordan en RPN-kalkulator fungerer:
> The RPN calculator differs from a normal calculator in that its syntax is completely different: It uses postfix notation instead of infix notation.
>
> Reverse polish notation, or postfix notation, is a notation where the operators (+, -, \*, /, ...) appear after the operands (1.0, 3.14, 2.187, 42, …). As an example, consider the expressions `2 1` and `9 + 3*4`. In RPN, this would be `2 1 -` and `9 3 4 * +`, as the operator shall appear after the operands. If the last example is confusing, think of it as `9 (3 4 *) +` instead.
>
> The main advantage of this is notation is that we can avoid parentheses and avoid determining which calculation to perform first. In infix, operator precedence is a problem: In the expression `9 + 3*4`, we first have to multiply, even though the plus operator appears first. In RPN, we simply take the first operator we see and apply it on the last two numbers we've seen, and replace the operator and operands with the result. For the multiplication and addition example:
>
> `9 3 4 * +` - the first operator we see is *, so we apply that to the two last seen values, 3 and 4, and replace those elements with the result, 12
>
> `9 12 +` - the next operator we see is +, so we apply that to 9 and 12
>
> `21` - We are finished, as there are no more operators in the expression
>
>For the more complex expression `(9 + 7) / (5 3)`, this will be written as `9 7 + 5 3 - /` in RPN. Notice how we can avoid parentheses and still calculate what we want without any issues:
>
> `9 7 + 5 3 - /` - the first operator is +, so we perform `9 + 7` and replace those elements with the result
>
> `16 5 3 - /` - the next operator is -, so we perform the operation `5 3`, as those are the last two elements
>
> `16 2 /` - we perform the last operation, division:
>
> `8` - We are done, as there are no more operators left.
>
> Most RPN calculators have a stack of numbers, giving them control over which numbers to do operations on when they see the next operand. Whenever they see an operand, they push it on the stack. If they see an operator, they pop off the numbers required, perform the operation, and push the result on top of the stack again.
>
> As an example of how this will work, consider the example `9 3 4 * +` once more. Here, an RPN calculator will first push 9, 3 and 4 on the stack. The stack will now look like this: [9, 3, 4], where 4 is the top of the stack. Then, when the calculator see the operator *, it then pops 4 off the stack, pops 3 off the stack, and pushes 3 * 4 on top of the stack. The stack which now contains [9, 12]. Then, when the RPN calculator sees the operator *, it pops off 12 and 9 off the stack, and performs the operation 9 + 12, and pushes it back on top of the (now empty) stack. The stack will now contain [21].
Tilstanden i `RPNCalc`-objekter velger du selv, men det er naturlig å bruke en `Stack` eller `ArrayList` med `Double`-objekter.
`RPNCalc`-klassen skal ha følgende metoder:
- `void push(double)` - legg argumentet på toppen av stacken.
- `double pop()` - returner verdien på toppen av stacken. Verdien skal også fjernes fra stacken. Dersom stacken er tom, så skal `Double.NaN` returneres.
- `double peek(int)` - returner verdien i stacken som står på plassen gitt i argumentet, telt fra toppen. Det vil si, `peek(0)` skal returnere verdien på toppen av stacken, `peek(1)` skal returnere verdien nest øverst i stacken osv. Verdien skal ikke fjernes av stacken. Dersom det er for få elementer på stacken, så skal `Double.NaN` returneres.
- `int getSize()` - returner antallet elementer i stacken.
- `void performOperation(char)` - utfør den angitte operasjonen på de to øverste verdiene i stacken. De to verdiene skal fjernes fra stacken og resultatet skal legges øverst. Bruk eksisterende metoder for å utføre dette der det er mulig. Metoden må støtte '+' (pluss), '-' (minus), '*' (multiplikasjon) og '/' (divisjon), men kan også støtte andre operatorer, f.eks. '~' (swap) for å bytte de to øverste operandene, 'p' eller 'π' (pi) for å legge pi på stacken (bruker ingen operander), '|' (absolutt-verdi, bruker én operand). Prøv å håndtere manglende operander på en måte som gir mening for operasjonen.
__Del 1 - Tilstandsdiagram__
Tegn [objekttilstandsdiagram](https://www.ntnu.no/wiki/display/tdt4100/Objekttilstandsdiagrammer) for en tenkt bruk av `RPNCalc`-klassen. Velg selv passende start-tilstand og sekvens av kall.
__Del 2 - Java-kode__
Skriv Java-kode for `RPNCalc`-klassen med oppførsel som er beskrevet over. Du skal bruke synlighetsmodifikatorer på metoder og felt for å gjøre innkapslingen "vanntett".
Lag en [main-metode](https://www.ntnu.no/wiki/display/tdt4100/Main-metoden), hvor du tester sekvenser av operander og operatorer, og kaller henholdsvis `push` og `performOperation`-metodene på et `RPNCalc`-objekt og skriver ut stacken. Test `RPNCalc`-klassen og sjekk at oppførselen stemmer med tilstandsdiagrammet.
__Del 3 - Teori__
Til nå har det blitt spesifisert at `peek()` og `pop()`-metodene skal returnere `Double.NaN` hvis stacken er tom. Alternativet er å utløse et unntak.
Svar på følgende:
- Hvilken type unntak vil det være naturlig å bruke?
- Hvilke fordeler og ulemper ser du for dette alternativet?
Det er også spesifisert at en skal "håndtere manglende operander på en måte som gir mening for operasjonen". Hvis `+`-operasjonen ble utført på kun én operand, så kan en f.eks. velge å la den manglende operanden være 0.
Svar på følgende:
- Hva vil tilsvarende verdi for manglende operand for `*`-operasjonen (multiplikasjon) være? Hva med for `/` (divisjon)?
- Hvordan kan du endre (evt. har du endret) grensesnittet for stack-operasjonene for å gjøre implementasjonen av disse enklere?
- Også her er et alternativ å utløse unntak. Hva tror du om det?
Testkode for denne oppgaven finner du i [encapsulation/RPNCalcTest.java](../../src/test/java/encapsulation/RPNCalcTest.java).

View File

@ -0,0 +1,24 @@
# Objektstrukturer - Card-oppgave del 2
Denne oppgaven handler om klasser for kortspill: `Card` (kort), `CardDeck` (kortstokk) og `CardHand` (korthånd), hvorav de to siste inneholder én eller flere `Card`-objekter. Oppgaven bygger på `Card` og `CardDeck` i [Innkapsling - Card-oppgave](../oving3/Card.md).
**Merk**: Om du ikke har gjort `Card`-oppgaven allerede, kan du bruke løsningsforslaget som er lagt ut under `lf/src/main/java/encapsulation`.
I mange sammenhenger vil objekter av en klasse inneholde eller "eie" objekter av andre klasser, og de underordnede objektene vil kunne flyttes/overføres mellom de overordnede. Når en klasse er assosiert med én instans av en (annen) klasse er dette en [1-1-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-1-assosiasjoner) og når en klasse er assosiert med flere instanser av en annen klasse er dette en [1-n-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-n-assosiasjoner). Et eksempel er kortspill, hvor kortene starter i kortstokken, fordeles på korthender og til slutt ender i en kortbunke. Et kort kan bare være ett sted om gangen, og må overføres fra ett sted til et annet, f.eks. fra kortstokk til korthender i utdelingsfasen. I [Innkapsling - Card-oppgave](../oving3/Card.md) ble det lagd logikk for kortstokk og enkeltkort. I denne oppgaven skal du implementere logikk for korthender, og utvide kortstokkens logikk litt.
`Card`-klassen har du allerede implementert, men du må sannsynligvis kopiere koden over fra `encapsulation` til `objectstructures`. Her er det enklest å lage en ny `Card`-klasse i `objectstructures` og så lime inn innholdet fra den gamle.
`CardDeck`-klassen har du også implementert, og denne må også flyttes på samme måte som Card. Denne klassen skal utvides:
- `deal(CardHand, int n)` - flytter n kort fra kortstokken (`CardDeck`-objektet) til korthånda (`CardHand`-objektet, som er første argument), ved å ta ett og ett kort med høyeste gyldige indeks, fjerne det fra `CardDeck`-objektet og legge det til `CardHand`-objektet.
`CardHand` er en ny klasse som skal implementeres. `CardHand`-objekter inneholder initielt ingen kort, og klassen inneholder de samme standardmetodene som `CardDeck`, altså `getCardCount()` og `getCard(int)`, for å lese hvor mange og hvilke kort den inneholder. I tillegg har den to metoder for å endre tilstand:
- `addCard(Card)` - legger argumentet til dette `CardHand`-objektet
- `play(int n)` - returnerer og fjerner kort nr. n (første kort har nr. 0) fra dette `CardHand`-objektet (som om det ble spilt ut)
**Java-kode**
Utvid `CardDeck` og lag `CardHand` som beskrevet over. Test klassene med selvlagde main-metoder og ved å kjøre JUnit-testene.
Testkode for denne oppgaven finner du her: [CardTest.java](../../src/test/java/objectstructures/CardTest.java), [CardDeckTest.java](../../src/test/java/objectstructures/CardDeckTest.java), [CardHandTest.java](../../src/test/java/objectstructures/CardHandTest.java).

View File

@ -0,0 +1,70 @@
# Objektstrukturer - Partner-oppgave
Denne oppgaven handler om en `Partner`-klasse med en [1-1-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-1-assosiasjoner)
kalt partner tilbake til samme klasse (altså kjønnsnøytralt partnerskap)
og det å sikre konsistens, slik at Partner-objekter er parvis knyttet sammen.
En viktig del av det å implementere assosiasjoner er å sikre konsistens, dvs. at objekter i hver ende av en kobling refererer korrekt til
hverandre. Et eksempel på dette for [1-1-assosiasjoner](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-1-assosiasjoner) er
(kjønnsnøytralt) partnerskap, hvor to partnere er koblet til hverandre når partnerskap
inngås og kobles fra hverandre ved en evt. skillsmisse. I denne oppgaven skal en `Partner`-klasse implementeres og ulike situasjoner håndteres
korrekt, som illustrert nedenfor.
`Partner`-klassen skal inneholde informasjon om *navn* (en String), som bare skal kunne settes i konstruktøren, og *partneren*, som er et annet
Partner-objekt. Navnet er ikke viktig for oppførselen, men er grei å ha med i en `toString()`-metode, for å skille Partner-objektene fra
hverandre. `Partner`-klassen skal ha følgende metoder for å lese tilstanden:
* `getName()` - returnerer navnet knyttet til dette Partner-objektet
* `getPartner()` - returnerer Partner-objektet som er knyttet til dette Partner-objektet, evt. null, hvis partnerskap ikke er inngått
`Partner`-klassen har kun én endringsmetode, `setPartner(Partner)`, som brukes både for å inngå partnerskap, når argumentet er et Partner-objekt,
og oppløse det, når argumentet er null. List og figurene under illustrerer de tre tilfellene som må kunne håndteres, og som JUnit-testene sjekker.
### 1. Inngåelse av partnerskap:
**Kall**: p1.setPartner(p2)
**Beskrivlse**: Partner-objektene p1 og p2 kobles sammen med ett kall til setPartner. Før kallet er p1 og p2 ikke koblet sammen,
og etter kallet er det koblet sammen.
**Før kall**:
![](img/partner1.png)
**Etter kall**:
![](img/partner2.png)
### 2. Oppløsning av partnerskap:
**Kall**: p1.setPartner(null)
**Beskrivlse**: Partner-objektene p1 og p2 kobles fra hverandre med ett kall til setPartner med null som argument.
Før kallet er p1 og p2 koblet sammen, og etter kallet er det ikke lenger koblet sammen.
**Før kall**:
![](img/partner2.png)
**Etter kall**:
![](img/partner1.png)
### 3. Oppløsning og inngåelse av partnerskap i ett:
**Kall**: p1.setPartner(p3)
**Beskrivlse**: Partner-objektene p1, p2, p3 og p4 er parvis koblet sammen, før ett kall til setPartner kobler
sammen p1 og p3, mens p2 og p4 kobles fra deres tidligere partnere.
**Før kall**:
![](img/partner3.png)
**Etter kall**:
![](img/partner4.png)
## Gjøremål
Oppgaven er (enkelt og greit) å implementere `Partner`-klassen og sjekke (f.eks. med en `main`-metode) at Partner-objektene oppfører seg som de skal.
Testkode for denne oppgaven finner du her: [objectstructures/PartnerTest.java](../../src/test/java/objectstructures/PartnerTest.java).

View File

@ -0,0 +1,149 @@
# Objektstrukturer - Person-oppgave
Denne oppgaven handler om en `Person`-klasse med en [1-n-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-n-assosiasjoner)
med rollene *children* og *mother*/*father* til samme klasse (altså barn-mor/far-forhold) og det å sikre konsistens, slik at foreldre og barn
er korrekt knyttet sammen.
En viktig del av det å implementere assosiasjoner er å sikre konsistens, dvs. at objekter i hver ende av en kobling refererer korrekt
til hverandre. Et eksempel på dette for [1-n-assosiasjoner](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-n-assosiasjoner) er
foreldreskap, hvor foreldre og barn er koblet til samme i et slektstre. I denne oppgaven skal en `Person`-klasse implementeres og det å
legge til (og fjerne) barn håndteres korrekt, som illustrert nedenfor.
`Person`-klassen skal inneholde informasjon om *navn* (en String) og *kjønn* (en char, 'F' eller 'M'), som bare skal kunne settes i
konstruktøren, og *mor*, *far* og *barn*, som er andre Person-objekter. Navnet er ikke viktig for oppførselen, men er grei å ha med
i en `toString()`-metode, for å skille Person-objektene fra hverandre. `Person`-klassen skal ha følgende metoder for å lese tilstanden:
* `getName()` - returnerer navnet knyttet til dette Person-objektet
* `getGender()` - returnerer tegnet som representerer kjønnet, enten 'F' eller 'M'
* `getMother()` - returnerer Person-objektet som er moren, evt. `null`
* `getFather()` - returnerer Person-objektet som er faren, evt. `null`
* `getChildCount()` - returnerer antall barn dette Person-objektet har
* `getChild(int n)` - returnerer barn nr. n (altså et Person-objekt), evt. utløser (et passende) unntak om `n` er for stor (eller liten)
`Person`-klassen har to sett med endringsmetoder, knyttet til de to rollene i hver ende av *children*-*mother*/*father*-assosiasjonen.
Fra *children*-perspektivet har vi følgende to metoder:
* `addChild(Person)` - oppretter en kobling til et barn (et annet Person-objekt). Dersom Person-objektet som metoden kalles på, er
en *kvinne*, så skal denne bli barnets *mor*, og motsatt, dersom Person-objektet som metoden kalles på, er en *mann*, så skal denne
bli barnets *far*.
* `removeChild(Person)` - fjerner en kobling til et barn (et annet Person-objekt). Dersom Person-objektet som metoden kalles på, er *moren*
til argumentet, så skal *mother*-koblingen fjernes, og motsatt, dersom Person-objektet som metoden kalles på, er argumentets *far*, så skal
*father*-koblingen fjernes.
Fra *mother*/*father*-perspektivet har vi følgende to metoder:
* `setMother(Person)` - setter argumentet (en kvinne) som *moren* til Person-objektet som metoden kalles på. Argumentet får samtidig
registrert Person-objektet som metoden kalles på, som sitt *barn*.
* `setFather(Person)` - setter argumentet (en mann) som *faren* til Person-objektet som metoden kalles på. Argumentet får samtidig
registrert Person-objektet som metoden kalles på, som sitt *barn*.
Det som er verd å merke seg er at begge sett med metoder, `addChild`/`removeChild` og `setMother`/`setFather`, må ha logikk
som håndterer koblingen den andre veien, så `addChild`/`removeChild` må kalle `setMother`/`setFather` og omvendt, eller ha kode
med tilsvarende effekt. Dette kan være nokså fiklete, fordi en både må sikre konsistens og unngå uendelig nøstede kall
(inntil du får StackOverflowException).
Listen og figurene under illustrerer de fem tilfellene som må kunne håndteres, og som testes av testene det er lenket til.
### 1. Opprettelse av koblinger med `addChild`
**Kall**:
marit.addChild(jens)
hallvard.addChild(jens)
(Dette har samme effekt som kallene under punkt 2.)
**Før kall**:
![](img/person1.png)
**Etter kall**:
![](img/person2.png)
### 2. Opprettelse av koblinger med `setMother` og `setFather`
**Kall**:
jens.setMother(marit)
jens.setFather(hallvard)
(Dette har samme effekt som kallene under punkt 1.)
**Før kall**:
![](img/person1.png)
**Etter kall**:
![](img/person2.png)
### 3. Fjerning av koblinger med `removeChild`
**Kall**:
marit.removeChild(jens)
hallvard.removeChild(jens)
(Dette har samme effekt som kallene under punkt 4.)
**Før kall**:
![](img/person2.png)
**Etter kall**:
![](img/person1.png)
### 4. Fjerning av koblinger med `setMother` og `setFather`
**Kall**:
jens.setMother(null)
jens.setFather(null)
(Dette har samme effekt som kallene under punkt 3.)
**Før kall**:
![](img/person2.png)
**Etter kall**:
![](img/person1.png)
### 5. Fjerning og oppretting av kobling med `setMother` og `setFather`, en slags "adoption"
**Kall**:
jens.setFather(torkel)
jens.setMother(jorunn)
**Før kall**:
![](img/person3.png)
**Etter kall**:
![](img/person4.png)
## Oppgaven
Oppgaven er delt i to trinn, den første håndterer *children*- og *mother*/*father*-rollen isolert og uten krav om konsistens,
mens det andre skal sikre konsistens.
### Del 1
* Implementer `addChild`- og `removeChild`-metodene slik at `getChildCount`- og `getChild`-metodene virker som forventet.
Disse metodene håndterer altså kun *children*-rollen.
* Implementer `setMother`- og `setFather`-metodene slik at `getMother`- og `getFather`-metodene virker som forventet.
Disse metodene håndteres altså kun *mother*/*father*-rollen.
Test metodene ved å koble opp Person-objekter tilsvarende din egen familie. Du blir nødt til å bruke de tre metodene `addChild`, `setMother`
og `setFather`. Prøv å få med minst tre generasjoner.
### Del 2
Utvid metodene til å sikre konsistens. Test at det fortsatt virker å koble opp din egen familie, denne gangen ved å bare bruke
`addChild` og ved å bare bruke `setMother` og `setFather`. Kjør JUnit-testene som hører til oppgaven.
Testkode for denne oppgaven finner du her: [objectstructures/PersonTest.java](../../src/test/java/objectstructures/PersonTest.java).

View File

@ -0,0 +1,62 @@
# Øving 4: Objektstrukturer
**Øvingsmål**
- Lære hva assosiasjoner er og hvordan dette brukes i OO
- Lære hvordan man sikrer konsistent oppførsel mellom assosierte objekter
**Øvingskrav**
- Kunne implementere klasser som har assosiasjoner til én eller flere andre klasser
- Kunne sikre at disse assosiasjon er konsistente i enkle objektstrukturer
- Kunne implementere metoder som oppretter, oppdaterer og fjerner slike assosiasjoner
## Dette må du gjøre
### Del 1: Programmering
I denne øvingen skal du velge og gjennomføre ENTEN både Partner- og Card del 2-oppgavene ELLER minst én av Twitter-, Stopwatch- og Person-oppgavene.
Merk at **noen av oppgavene i neste øving (øving 6), bygger videre på noen av oppgavene under**, disse er uthevet med **fet skrift**.
Det er ikke et krav at man gjør de uthevede oppgavene, men de gir flere oppgaver å velge mellom i øving 6.
**Gjør enten _begge_ disse:**
- [Partner](./Partner.md) (lett)
- **[Card del 2](./Card.md)** (lett)
**Eller _minst én_ av følgende oppgaver:**
- **[Twitter](./Twitter.md)** (medium, men lang)
- [Stopwatch](./Stopwatch.md) (medium)
- [Person](./Person.md) (medium/vanskelig)
Oppgavene for denne øvingen skal du lagre i `ovinger/src/main/java/objectstructures`. Test-filene ligger i `ovinger/src/test/java/objectstructures`.
Alle oppgavene ovenfor er høyst eksamensrelevante og det anbefales følgelig å ta en titt på alle sammen.
### Del 2: Klassediagram
- Lag et [klassediagram](https://www.ntnu.no/wiki/display/tdt4100/Klassediagrammer) for oppgaven(e) du velger.
Diagrammet kan for eksempel skrives på papir eller tegnes/lages i et valgfritt program. Du trenger ikke levere inn diagrammene, men de skal vises til studass under godkjenning av øvingen.
### Del 3: Testing
Skriv kode som tester oppførselen til `CoffeeCup`-klassen, dvs. at du skal teste om metodene i listen under har rett oppførsel og returnerer det de skal, i tillegg til at du skal teste konstruktørene. Det er ikke nødvendig å teste absolutt alle mulige tilfeller, men det kreves at du tester den grunnleggende funksjonaliteten.
* `getCapacity`
* `getCurrentVolume`
* `increaseCupSize`
* `drinkCoffee`
* `fillCoffee`
Du finner `CoffeeCup`-klassen under `ovinger/src/main/java/objectstructures`.
Her er det anbefalt å bruke [JUnit](https://www.ntnu.no/wiki/display/tdt4100/Enhetstesting+med+JUnit),
men det er lov å teste vha. main-metoden også.
### Hjelp / mistanke om bugs
Ved spørsmål eller behov for hjelp konsulter studassen din i saltiden hans / hennes. Du kan også oppsøke andre studasser på sal eller legge ut et innlegg på [Piazza](https://piazza.com/).
### Godkjenning
Last opp kildekode på Blackboard innen den angitte innleveringsfristen. Innlevert kode skal demonstreres for en læringsassistent innen én uke etter innleveringsfrist. Se for øvrig Blackboard-sidene for informasjon rundt organisering av øvingsopplegget og det tilhørende øvingsreglementet.

View File

@ -0,0 +1,31 @@
# Objektstrukturer - StopWatchManager-oppgave
Denne oppgaven handler om en `StopWatchManager`-klasse som inneholder flere `StopWatch`-objekter. Oppgaven bygger på klassen lagd i [StopWatch-oppgaven](../oving1/Stopwatch.md) fra "tilstand og oppførsel".
I mange sammenhenger vil objekter av en klasse inneholde eller "eie" objekter av andre klasser. Når en klasse er assosiert med én instans av en (annen) klasse er dette en [1-1-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-1-assosiasjoner) og når en klasse er assosiert med flere instanser av en annen klasse er dette en [1-n-assosiasjon](https://www.ntnu.no/wiki/display/tdt4100/Koding+av+1-n-assosiasjoner).
I denne oppgaven skal du implementere en `StopWatchManager`-klasse som kan holde styr på flere stoppeklokker. Ved hjelp av `StopWatchManager` skal man enkelt kunne holde styr på flere stoppeklokker og sørge for at alle stoppeklokker får beskjed om tiden som går. Dette kan være nyttig hvis man f.eks. ønsker å holde styr på flere løpere i et skirenn der ikke alle starter og fullfører samtidig, men hvor allikevel klokken må gå for alle.
Det skal være mulig å opprette nye stoppeklokker med et tilhørende navn (streng). Navnet skal man senere kunne bruke til å hente stoppeklokken igjen eller fjerne stoppeklokken fra `StopWatchManager`. For å få til dette kan det være lurt å se litt på `Map` fra [Collection-rammeverket](https://www.ntnu.no/wiki/display/tdt4100/Collection-rammeverket).
`StopWatchManager` skal ha følgende endringsmetoder:
- `StopWatch newStopWatch(String name)` - Oppretter en ny stoppeklokke knyttet til navnet `name`. Returnerer den nye stoppeklokken.
- `void removeStopWatch(String name)` - Fjerner stoppeklokken tilknyttet navnet `name`.
- `void tick(int ticks)` - Informerer alle stoppeklokkene om at ticks tikk har gått.
`StopWatchManager` skal ha følgende lesemetoder:
- `StopWatch getStopWatch(String name)` - returnerer stoppeklokken tilknyttet navnet `name`.
- `Collection<StopWatch> getAllWatches()` - returnerer alle stoppeklokkene.
- `Collection<StopWatch> getStartedWatches()` - returnerer alle stoppeklokkene som er startet.
- `Collection<StopWatch> getStoppedWatches()` - returnerer alle stoppeklokkene som er stoppet.
**Merk**: Det er viktig at de metodene som returnerer en samling av stoppeklokker returnerer nye samlinger. De som får en samling må kunne endre på den (f.eks. fjerne elementer) uten at dette forstyrrer `StopWatchManager` eller andre som har fått samlinger tidligere.
**Java-kode**
Kopier `StopWatch` fra `encapsulation`-pakken og lag `StopWatchManager` som beskrevet over. Test klassen med selvlagde main-metoder og ved å kjøre JUnit-testene.
Testkode for denne oppgaven finner du her: [objectstructures/StopWatchTest.java](../../src/test/java/objectstructures/StopWatchTest.java) og [objectstructures/StopWatchManagerTest.java](../../src/test/java/objectstructures/StopWatchManagerTest.java).

View File

@ -0,0 +1,73 @@
# Objektstrukturer - Twitter-oppgave
Denne oppgaven handler om en begrenset klone av `Twitter`, med to klasser, `TwitterAccount` og `Tweet`.
En Twitter-konto kan følge andre Twitter-kontoer og motsatt: en Twitter-konto kan bli fulgt av andre Twitter-kontoer.
Dette er altså en gjensidig kobling: Hvis konto A følger konto B, så er konto B fulgt av konto A. En kan selvsagt ikke følge seg selv.
I tillegg har hver Twitter-konto en mengde *tweets*, som er små, korte tekster. En tweet hører til den kontoen den ble sendt fra.
Hvis noen finner en annen sin tweet interessant har man muligheten til å retweete denne. Da lager man en tweet som refererer til originalen,
og (implisitt) få original-tweeten sin tekst. Merk at i en kjede av retweets, så vil alle referere til samme original-tweet. Mao.,
hvis tweet B er en retweet av A og tweet C er en retweet av B, vil både tweet B og C ha A som original-tweet, slik det er vist under.
**Riktig objektstrutur**, når B er en retweet av A og C er en retweet av B:
![](img/twitter1.png)
**Feil objektstrutur**, når B er en retweet av A og C er en retweet av B:
![](img/twitter2.png)
## Tweet-klassen
`Tweet` skal ha to konstruktører, en for hver måte å tweete på:
* `Tweet(TwitterAccount, String)` - En ny original-tweet
* `Tweet(TwitterAccount, Tweet)` - En retweet av Tweet-argumentet. Utløser et passende unntak, hvis original-tweeten er fra samme konto.
`Tweet` skal ha metodene:
* `String getText()` - returnerer teksten til en tweet
* `TwitterAccount getOwner()` - returnerer kontoen som tweeten kom fra
* `Tweet getOriginalTweet()` - returnerer original-tweeten, hvis den er en retweet, ellers null
* `int getRetweetCount()` - returnerer antall ganger denne tweeten har blitt retweetet
## TwitterAccount-klassen
`TwitterAccount` skal ha konstruktøren:
* `TwitterAccount(String)` - som tar inn brukernavnet
`TwitterAccount` skal ha metodene:
* `String getUserName()` - returnerer brukernavnet
* `void follow(TwitterAccount account)` - denne (this) kontoen starter å følge account
* `void unfollow(TwitterAccount account)` - slutt å følge account
* `boolean isFollowing(TwitterAccount account)` - returnerer om denne kontoen følger account
* `boolean isFollowedBy(TwitterAccount account)` - returnerer om account følger denne kontoen
* `void tweet(String)` - lager en ny tweet for denne kontoen
* `void retweet(Tweet tweet)` - retweeter tweet fra denne kontoen
* `Tweet getTweet(int i)` - returner tweet nummer i, der 1 er den nyeste, 2 den nest nyeste, … (merk rekkefølgen!)
* `int getTweetCount()` - returner antall tweets til kontoen
* `int getRetweetCount()` - returner antall retweets av tweets fra denne kontoen
## Del 1
* Implementer `Tweet`-klassen.
* For å teste klassen må du sende inn TwitterAccount-objekter i konstruktøren. Lag en forenklet versjon av `TwitterAccount`-klassen
for dette formålet, der du kun implementerer konstruktøren og evt. en passende toString(). Dette gjør det mulig å teste `Tweet`-klassen
din uten at du må implementere hele `TwitterAccount`-klassen først.
## Del 2
* Implementer `TwitterAccount`-klassen.
* Test klassen og dens samspill med `Tweet`-klassen ved å lage Twitter-konto for deg selv og noen av vennene dine.
La noen av kontoene følge hverandre, tweete og retweete.
Testkode for denne oppgaven finner du her: [objectstructures/TweetTest.java](../../src/test/java/objectstructures/TweetTest.java) og [TwitterAccountTest.java](../../src/test/java/objectstructures/TwitterAccountTest.java).
## Frivillig utvidelse
På Twitter kan man markere en annen sin tweet som en favoritt. Implementer passende metoder for å kunne gjøre dette.
En konto må ha oversikt over hvilke tweets den har markert som favoritter, og en tweet må vite hvem og hvor mange som har markert den
som favoritt. Hva synes du burde skje hvis man markerer en retweet som en favoritt?

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB