Compare commits
15 Commits
f2db063e5c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
3f7ea46a2f
|
|||
|
fd661adfc5
|
|||
|
fe2266656f
|
|||
| c79555e133 | |||
| 285b61aa02 | |||
|
|
2d0a64006f | ||
|
|
daa94740c8 | ||
|
|
2cc172d1f6 | ||
|
|
18bc153848 | ||
|
|
1deb0cc650 | ||
| 04a598a5fa | |||
| 341848f3e8 | |||
| 00f8009e0d | |||
| 0dfde2ddfb | |||
| 86a691b044 |
@@ -11,3 +11,4 @@ Denne mappen inneholder øvingstekster for TDT4100 - Objektorientert programmeri
|
||||
| [Øving 4](./oppgavetekster/oving4/README.md) | Objektstrukturer |
|
||||
| [Øving 5](./oppgavetekster/oving5/README.md) | Grensesnitt |
|
||||
| [Øving 6](./oppgavetekster/oving6/README.md) | Observatør-observert og delegering |
|
||||
| [Øving 7](./oppgavetekster/oving7/README.md) | Arv og abstrakte klasser |
|
||||
|
||||
41
oppgavetekster/oving7/AbstractAccount.md
Normal file
41
oppgavetekster/oving7/AbstractAccount.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Arv - AbstractAccount-oppgave
|
||||
|
||||
Denne oppgaven handler om å lage en felles abstrakt superklasse `AbstractAccount` for `CreditAccount`, `DebitAccount`- og `SavingsAccount2`-klassene.
|
||||
|
||||
Denne oppgaven er en annen variant av [SavingsAccount](./SavingsAccount.md)-oppgaven, med fokus på bruk av abstrakte klasser og arv.
|
||||
|
||||
Denne oppgaven er på likt format som dere møtte i [Øving 3 - Card-oppgaven](../oving3/Card.md), der det ikke blir oppgitt en detaljert beskrivelse av klassene her i `README`-filen, men heller gjennom Javadoc-dokumentasjonen. Dette er igjen for å gi dere øving i å lese og forstå dokumentasjon, som er et vanlig format å bli gitt oppgaver på eksamen.
|
||||
|
||||
> Kjapt tips: Hold musen over metoden/klassen for å lese Javadoc-dokumentasjonen på et fint format.
|
||||
|
||||
Filene i denne oppgaven skal legges i [oving7/abstractaccount](../../src/main/java/oving7/abstractaccount).
|
||||
|
||||
## Del 1 - Abstrakt klasse AbstractAccount
|
||||
|
||||
En bank består av mange ulike type kontoer: sparekontoer, brukskontoer, depositumskontoer, støttekontoer, osv. Siden disse har mye felles, f.eks. har alle en balanse, så er det praktisk å samle så mye som mulig av den felles logikken i en superklasse, som alle kan arve fra. Denne superklassen er imidlertid ikke noen egen type konto, og derfor gjør vi den abstrakt, slik at den ikke kan instansieres. De konkrete konto-klassene som arver fra den, må selvsagt være instansierbare.
|
||||
|
||||
Vær oppmerksom på at du fra og med [del 2](#del-2---debitaccount-extends-abstractaccount) skal lage subklasser av `AbstractAccount` og at du ved å bruke rett innkapsling (hint: `protected`-modifikatoren) skal la *subklassene* nyttiggjøre seg *superklassen* i størst mulig grad.
|
||||
|
||||
Skjelletet til `AbstractAccount`-klassen finner du i [oving7/abstractaccount/AbstractAccount.java](../../src/main/java/oving7/abstractaccount/AbstractAccount.java).
|
||||
|
||||
Det er ingen spesifikke tester for denne klassen, siden abstrakte klasser ikke kan instansieres.
|
||||
|
||||
## Del 2 - DebitAccount extends AbstractAccount
|
||||
|
||||
Skjelettet til `DebitAccount`-klassen finner du i [oving7/abstractaccount/DebitAccount.java](../../src/main/java/oving7/abstractaccount/DebitAccount.java).
|
||||
|
||||
Testkode for oppgavene finner du her: [oving7/abstractaccount/DebitAccountTest.java](../../src/test/java/oving7/abstractaccount/DebitAccountTest.java).
|
||||
|
||||
## Del 3 - CreditAccount extends AbstractAccount
|
||||
|
||||
Skjelettet til `CreditAccount`-klassen finner du i [oving7/abstractaccount/CreditAccount.java](../../src/main/java/oving7/abstractaccount/CreditAccount.java).
|
||||
|
||||
Testkode for oppgavene finner du her: [oving7/abstractaccount/CreditAccountTest.java](../../src/test/java/oving7/abstractaccount/CreditAccountTest.java).
|
||||
|
||||
## Del 4 - SavingsAccount extends AbstractAccount
|
||||
|
||||
> Merk at denne klassen har samme navn som den fra [SavingsAccount-oppgaven](./SavingsAccount.md), men at dette er uproblematisk siden de befinner seg i forskjellige mapper.
|
||||
|
||||
Skjelettet til `SavingsAccount`-klassen finner du i [oving7/abstractaccount/SavingsAccount.java](../../src/main/java/oving7/abstractaccount/SavingsAccount.java).
|
||||
|
||||
Testkode for oppgavene finner du her: [oving7/abstractaccount/SavingsAccountTest.java](../../src/test/java/oving7/abstractaccount/SavingsAccountTest.java).
|
||||
21
oppgavetekster/oving7/CardContainerImpl.md
Normal file
21
oppgavetekster/oving7/CardContainerImpl.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Arv - CardContainerImpl-oppgave
|
||||
|
||||
Denne oppgaven handler om å lage en felles superklasse `CardContainerImpl` for `CardDeck`- og `CardHand`-klassene, laget i [Card-oppgaven](../oving4/Card.md) og [CardContainer-oppgaven](../oving5/CardContainer.md). Dersom du ikke har gjort `Card`-oppgavene allerede, bør du gjøre disse først. Hvis du ikke har gjort det, kan du kopiere koden fra [løsningsforslaget](https://git.ntnu.no/tdt4100/tdt4100-lf-25/blob/main/src/main/java/oving5/card), som kommer til å være tilgjengelig etter siste demonstrasjonsfrist for øving 5.
|
||||
|
||||
Filene i denne oppgaven skal legges i [oving7/card](../../src/main/java/oving7/card).
|
||||
|
||||
## Del 1 - Superklassen CardContainerImpl
|
||||
|
||||
Lag en `CardContainerImpl`-superklasse, som implementerer grensesnittet `CardContainer` (se [CardContainer-oppgaven](../oving5/CardContainer.md)) og inneholder koden som er felles for `CardDeck` og `CardHand`.
|
||||
|
||||
La `CardDeck` og `CardHand` arve `CardContainerImpl` og gjør nødvendige endringer i disse klassene, slik at totaloppførselen er som før. F.eks. skal `CardDeck`-objektet ha samme konstruktør som før, som skal sikre samme initielle tilstand (men ikke nødvendigvis med samme konstruktør-kode).
|
||||
|
||||
Merk at målet er at mest mulig kode skal flyttes til _superklassen_ og gjenbrukes i _subklassene_. Det er viktig å bruke innkapsling rett (hint: `protected`-modifikatoren) for å nyttiggjøre seg superklassen i størst mulig grad.
|
||||
|
||||
## Del 2 - Regler for maksimalt antall kort
|
||||
|
||||
Anta at en ønsker å unngå at instanser av `CardContainerImpl` (eller av en av subklassene) inneholder for mange kort. Legg til et _privat_ `maxCardCount`-felt i `CardContainerImpl`, en konstruktør som _initialiserer_ feltet og en _getter_ for å lese verdien. Legg så til evt. endre kode i `CardContainerImpl` som sikrer at antall kort ikke overstiger dette tallet og at subklassene ikke kan omgå denne valideringen.
|
||||
|
||||
`CardContainerImpl`-subklassene `CardDeck` og `CardHand` skal sette maks-antallet som følger: `CardDeck` skal sette makstallet til _52_ og `CardHand` skal ta inn maks-antallet i _sin_ konstruktør. Hvis man forsøker å legge til flere kort enn hva som er tillatt i `CardHand`, skal det utløses en `IllegalStateException`.
|
||||
|
||||
Testkode for oppgavene finner du her: [oving7/card/CardDeckTest.java](../../src/test/java/oving7/card/CardDeckTest.java) og [oving7/card/CardHandTest.java](../../src/test/java/oving7/card/CardHandTest.java).
|
||||
65
oppgavetekster/oving7/ObservableList.md
Normal file
65
oppgavetekster/oving7/ObservableList.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Observatør-observert-teknikken og arv - HighscoreList-oppgave med ObservableList
|
||||
|
||||
Denne oppgaven handler om å bruke observatør-observert-teknikken for å bli informert om endringer i en highscore-liste. Vi bruker også arv for å skille ut gjenbrukbar kode for en generell, observerbar liste.
|
||||
|
||||
Observatør-observert-teknikken går ut på at det observerte objektet sier ifra til en eller flere observatører om at tilstanden er endret. I denne oppgaven skal vi lage en `HighscoreList` som kan si fra til lyttere av typen `ListListener` når nye resultater blir registrert. En hovedprogramklasse kalt `HighscoreProgram` vil bli brukt til å sjekke at det virker. Denne klassen oppretter en `HighscoreList`-instans, legger inn resultater (tall) fra konsollet som legges til listen og skriver ut listen hver gang et nytt resultat faktisk blir lagt til.
|
||||
|
||||
Klassene skal legges i [`src/main/java/oving7/observablelist`](../../src/main/java/oving7/observablelist) og tilhørende tester ligger i [`src/test/java/oving7/observablelist`](../../src/test/java/oving7/observablelist).
|
||||
|
||||
## Del 1: Implementasjon av ObservableList og ObservableHighscoreList
|
||||
|
||||
En `ObservableHighscoreList` skal holde styr på heltallsresultater (av typen `int`/`Integer`). Listen skal være _observerbar_ ved at den kan registrere lyttere (`ObservableListListener`-instanser) og si fra til dem når listen blir endret. Listen skal ha en maksimal lengde, som settes i _konstruktøren_, f.eks. skal en topp $10$-liste kunne opprettes med `new ObservableHighscoreList(10)`. Nye resultater registreres med metoden `addResult(int)`, som skal finne riktig posisjon og legge resultatet inn (dersom det er godt nok). Dersom listen er for lang, så skal det dårligste resultatet fjernes. NB: _Lavest verdi er best_, f.eks. antall sekunder på en oppgave eller antall flytt i Sokoban.
|
||||
|
||||
`ObservableListListener`-grensesnittet er vist i klassediagrammet nedenfor og må implementers av alle klasser som ønsker å fungere som lyttere for `ObservableHighscoreList`-instanser. Lyttere registrerer seg med `ObservableHighscoreList` sin `addObservableListListener`-metode og vil siden få beskjed om nye resultater ved at `listChanged`-metoden kalles. Argumentene som tas inn er `ObservableHighscoreList`-objektet som ble endret og _posisjonen_ i listen der endringen skjedde.
|
||||
|
||||
Merk at første argument til `listChanged`-metoden er av typen `ObservableList`. Dette er en abstrakt superklasse for `ObservableHighscoreList`, som først brukes i [del 3](#del-3-observablelist) og som da skal holde orden på listen. `ObservableList` vil ha en del generelle metoder som `ObservableHighscoreList` arver og kan bruke. For å kunne kjøre testene for `ObservableHighscoreList` allerede her i [del 1](#del-1-implementasjon-av-observablelist-og-observablehighscorelist), så må `ObservableList` være definert fra starten. Lag derfor en tom `ObservableList`-klasse og bruk denne som superklasse for `ObservableHighscoreList`.
|
||||
|
||||
Her er en oversikt over metoden som må implementeres:
|
||||
|
||||
- `ObservableHighscoreList(int maxSize)` - konstruktøren tar inn _maks antall_ resultater som listen skal kunne holde. Denne verdien må brukes av `addResult`, slik at resultater som er for dårlige kastes.
|
||||
- `int size()` - returnerer antall elementer i listen, som altså aldri skal overstige maks-antallet.
|
||||
- `int getElement(int)` - returnerer resultatet i posisjonen angitt av argumentet.
|
||||
- `void addResult(int)` - registrere et nytt resultat, og dersom resultatet er godt nok til å komme med på listen, så legges det inn på riktig plass. Dersom listen blir for lang, så må dårligste resultat kastes. Alle registrerte lyttere må få beskjed om en evt. endring av listen, inkludert hvilken posisjon som ble endret.
|
||||
- `void addObservableListListener(ObservableListListener)` - registrerer en ny lytter.
|
||||
- `void removeObservableListListener(ObservableListListener)` - fjerner en tidligere registrert lytter.
|
||||
|
||||
Klassediagram for `HighscoreList`, `ListListener` og `ObservableList`:
|
||||
|
||||

|
||||
|
||||
Testkode for denne oppgaven finner du her: [oving7/observablelist/ObservableHighscoreListTest.java](../../src/test/java/oving7/observablelist/ObservableHighscoreListTest.java).
|
||||
|
||||
## Del 2: Hovedprogram ObservableHighscoreListProgram
|
||||
|
||||
Lag en hovedprogramklasse kalt `ObservableHighscoreListProgram`, som tester at `ObservableHighscoreList`-klassen din virker som den skal. La den opprette en `ObservableHighscoreList`-instans, lese inn tall fra konsollet (f.eks. med en `Scanner` og `nextInt`-metoden) og legge disse inn i listen. Sørg for at `ObservableHighscoreListProgram` implementerer `ObservableListListener`-grensesnittet og registrerer seg som lytter på `HighscoreList`-instansen. La lyttermetoden `listChanged` skrive ut informasjon og resultatene i `HighscoreList`-instansen og posisjonsargumentet, slik at du ser at alt virker som det skal.
|
||||
|
||||
Vi foreslår følgende metoder og oppførsel:
|
||||
|
||||
- `void init()` - oppretter en ny `ObservableHighscoreList` og registrerer seg selv (altså `ObservableHighscoreListProgram`-instansen) som lytter.
|
||||
- `void run()` - leser inn tall (resultater) fra konsollet og legger dem til i listen.
|
||||
- `void listChanged(ObservableList, int)` - observerer endringer i `ObservableHighscoreList`-instansen og skriver ut posisjonsargumentet, samt selve listen, til konsollet.
|
||||
|
||||
Klassediagrammet viser hvordan klassene henger sammen, og vårt forslag til metoder:
|
||||
|
||||

|
||||
|
||||
## Del 3: ObservableList
|
||||
|
||||
Den abstrakte superklassen `ObservableList` skal legges til som en generell superklasse for observerbare lister, som `ObservableHighscoreList` skal arve fra. Denne klassen skal både holde en liste med objekter (`Object`) og håndtere registrering av lyttere, altså en liste med `ObservableListListener`-instanse, som får beskjed om endringer i listen (slik at listen dermed er _observerbar_). Dette betyr at `ObservableList` overtar håndtering av både resultater og lyttere fra `ObservableHighscoreList`-klassen. For å gjøre `ObservableList` mer generell og gjenbrukbar, så lar vi den håndtere `Object`-instanser (heller enn `Integer`). Samtidig deklarerer den en _abstrakt_ metode `acceptsElement`, som subklasser må _redefinere_ for å bestemme hva slags objekter det skal være lov å legge inn. `ObservableHighscoreList` vil f.eks. måtte redefinere den slik at bare `Integer`-objekter aksepteres.
|
||||
|
||||
`ObservableList` skal ha følgende metoder (noen er altså overtatt fra `ObservableHighscoreList`):
|
||||
|
||||
- `int size()` - returnerer antall elementer i listen.
|
||||
- `Object getElement(int)` - returnerer elementet i posisjonen angitt av argumentet.
|
||||
- `abstract boolean acceptsElement(Object)` - returnerer hvorvidt _subklassen_ aksepterer at objektet legges inn i listen (f.eks. aksepterer `HighscoreList` kun `Integer`-objekter).
|
||||
- `void addElement(int, Object)` - legger til et element på posisjonen angitt av argumentet, men bare dersom det _aksepteres_ som element. Dersom elementet ikke aksepteres, så skal `IllegalArgumentException` utløses. Dersom posisjonen er ulovlig så skal `IndexOutOfBoundsException` utløses.
|
||||
- `void addElement(Object)` - legger til et element bakerst i listen, men bare dersom det _aksepteres_ som element. Dersom elementet ikke aksepteres, så skal `IllegalArgumentException` utløses.
|
||||
- `void removeElement(int)` - fjerner elementet på posisjonen angitt av argumentet. Dersom posisjonen er ulovlig så skal `IndexOutOfBoundsException` utløses.
|
||||
|
||||
`ObservableHighscoreList` skal endres slik at den i størst mulig grad bruker metodene som arves fra `ObservableList`, men forøvrig ikke endrer oppførsel. Kjør hovedprogramklassen `ObservableHighscoreListProgram` for å sjekke at dette faktisk stemmer.
|
||||
|
||||
Klassediagrammet viser hvordan klassene henger sammen, og hvor metodene nå er deklarert/implementert. Merk at `addElement`- og `removeElement`-metodene er angitt som `protected` (ruter-symbolet), slik at kun subklasser skal kunne bruke dem.
|
||||
|
||||

|
||||
|
||||
Testkode for denne oppgaven finner du her: [oving7/observablelist/ObservableListTest.java](../../src/test/java/oving7/observablelist/ObservableListTest.java).
|
||||
46
oppgavetekster/oving7/README.md
Normal file
46
oppgavetekster/oving7/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Øving 07: Arv og abstrakte klasser
|
||||
|
||||
## Øvingsmål
|
||||
|
||||
- Lære hvordan arv-mekansimen brukes i OO
|
||||
- Lære om instanser, typer, deklarasjoner og tilordninger
|
||||
- Lære om sub- og superklasser samt om synlighetsmodifikatorer som brukes ved arv
|
||||
- Lære om abstrakte klasser, deres bruksområder og fordeler
|
||||
|
||||
## Øvingskrav
|
||||
|
||||
- Kunne bruke arv til å modellerere enkle(re) objektstrukturer- og relasjoner i Java
|
||||
- Kunne la flere subklasser bruke funksjonalitet definert i samme superklasse
|
||||
- Kunne la en subklasse redefinere metoder definert i en superklasse
|
||||
- Kunne samle felles oppførsel til to eller flere subklasser i en felles abstrakt klasse
|
||||
|
||||
## Dette må du gjøre
|
||||
|
||||
Oppgavene skal lagres i [`src/main/java/oving7`](../../src/main/java/oving7).
|
||||
|
||||
I begge delene er antageligvis vanskelighetsgraden stigende. Alle er høyst eksamensrelevante og det anbefales følgelig å ta en titt på samtlige.
|
||||
|
||||
For å få 2 poeng på øvingen må det gjennomføres til sammen *4* valgfrie oppgaver fra [del 1](#del-1-arv) og [del 2](#del-2-abstrakte-klasser-og-arv).
|
||||
|
||||
### Del 1: Arv
|
||||
|
||||
Velg og gjennomfør *minst én* av oppgavene om arv:
|
||||
|
||||
- [CardContainerImpl](./CardContainerImpl.md) (Lett) (Anbefalt)
|
||||
- [Train](./Train.md) (Lett)
|
||||
- [SavingsAccount](./SavingsAccount.md) (Middels)
|
||||
|
||||
### Del 2: Abstrakte klasser og arv
|
||||
|
||||
Velg og gjennomfør *minst én* av oppgavene om abstrakte klasser og arv:
|
||||
|
||||
- [AbstractAccount](./AbstractAccount.md) (Middels) (Anbefalt)
|
||||
- [ObservableList](./ObservableList.md) (Vanskelig)
|
||||
|
||||
## 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/ntnu.no/spring2025/tdt4100).
|
||||
|
||||
## 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.
|
||||
63
oppgavetekster/oving7/SavingsAccount.md
Normal file
63
oppgavetekster/oving7/SavingsAccount.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Arv - SavingsAccount-oppgave
|
||||
|
||||
Denne oppgaven handler om å lage en felles superklasse `SavingsAccount` for `BSU`- og `ForeldreSpar`-klassene. `SavingsAccount` skal dessuten implementere `Account`-grensesnittet.
|
||||
|
||||
Denne oppgaven bygger videre på `Account`-oppgaven fra [øving 2](../oving2/Account.md).
|
||||
|
||||
Filene i denne oppgaven skal legges i [oving7/savingsaccount](../../src/main/java/oving7/savingsaccount).
|
||||
|
||||
## Del 1 - SavingsAccount implements Account
|
||||
|
||||
En bank består av mange ulike type kontoer: sparekontoer, brukskontoer, depositumskontoer, støttekontoer, osv. Felles for alle kontoer er `Account`-grensesnittet, som er definert under:
|
||||
|
||||
```java
|
||||
package oving7.savingsaccount;
|
||||
|
||||
public interface Account {
|
||||
|
||||
void deposit(double amount);
|
||||
|
||||
void withdraw(double amount);
|
||||
|
||||
double getBalance();
|
||||
}
|
||||
```
|
||||
|
||||
Vi skal i denne oppgaven fokusere på sparekontoer og du skal nå lage en `SavingsAccount`-superklasse, som implementerer `Account`-grensesnittet. Funksjonaliteten som hver av metodene definert i grensesnittet over skal støtte er:
|
||||
|
||||
- `void deposit(double)` - øker kontobalansen med innskutt beløp. Merk at det innskutte beløpet må være positivt. Ved ulovlig innskudd skal en `IllegalArgumentException` utløses.
|
||||
- `void withdraw(double)` - minsker kontobalansen med beløpet som blir tatt ut. Merk at uttaksbeløpet må være positivt, ellers skal et unntak av typen `IllegalArgumentException` utløses. Dersom det ikke er dekning på kontoen (en `SavingsAccount` kan ikke ha negativ balanse) skal et unntak av typen `IllegalStateException` utløses.
|
||||
- `double getbalance()` - returnerer kontobalansen.
|
||||
|
||||
I tillegg til å støtte `Account`-grensesnittet over, som er felles for alle kontoer, skal sparekontoer ha en rentefot og en metode som forrenter kontoen. Denne kalles av bankene for hver sparekonto på slutten av året slik at alle dets kunder opptjener renter (ikke tenk på at banker egentlig holder styr på hvor stor balansen har vært gjennom hele året eller forrenter kontoen kontinuerlig - her skal vi bare anta at innestående kontobalanse ved årsslutt forrentes i sin helhet) - derfor heter metoden `endYearUpdate()`. I tillegg skal `SavingsAccount`-klassen ha en konstruktør som tvinger alle objekter av denne typen til å bli instansiert med en rentefot. Dette er oppsummert her:
|
||||
|
||||
- `SavingsAccount(double)` - konstruktør som tar inn rentefoten på kontoen (et desimaltall, f.eks. `0.05` tilsvarer en rente på $5%$). Åpningsbalansen skal være `0.0`.
|
||||
- `void endYearUpdate()` - forrenter kontobalansen basert på rentefoten. Vi tenker oss at denne kalles av kode utenfor denne klassen, f.eks. resten av et tenkt banksystem ved årsoppgjør, som et signal på at nå er et nytt år over.
|
||||
|
||||
Vær oppmerksom på at du i [del 2](#del-2---bsu-extends-savingsaccount) og [del 3](#del-3---foreldrespar-extends-savingsaccount) skal lage _subklasser_ av `SavingsAccount` og at du ved å bruke rett innkapsling (hint: `protected`-modifikatoren) kan la _subklassene_ nyttiggjøre seg _superklassen_ i størst mulig grad.
|
||||
|
||||
> Merk at denne klassen har samme navn som den fra [AbstractAccount-oppgaven](./AbstractAccount.md), men at dette er uproblematisk siden de befinner seg i forskjellige mapper.
|
||||
|
||||
Testkode for oppgavene finner du her: [oving7/savingsaccount/SavingsAccountTest.java](../../src/test/java/oving7/savingsaccount/SavingsAccountTest.java).
|
||||
|
||||
## Del 2 - BSU extends SavingsAccount
|
||||
|
||||
I tillegg til generelle sparekontoer finnes det en spesiell type sparekonto som heter BSU. Du skal nå lage en `BSU`-klasse som arver fra `SavingsAccount`-superklassen. Her er målet at du skal gjenbruke mest mulig av _superklassen_ og samtidig støtte BSU-spesifikk oppførsel. En BSU-konto er, i tillegg til å være en sparekonto, spesiell i den forstand at det kun er lovlig å sette inn inntil et forhåndsbestemt beløp per år (den gamle regjeringen fastslo at BSU-kontoer i 2014 skulle ha en innskuddsgrense på kr $25 000$, men din kode skal ha støtte for å ha en vilkårlig grense) og at det kun er lovlig å ta ut av det beløpet som er satt inn siste år. Med andre ord vil en ved årsskifte få mulighet til å sette inn nye innskudd innenfor innskuddsgrensen, men en har ikke lenger mulighet til å ta ut hele balansen (innskudd fra tidligere år låses). Dessuten gir en vanlig BSU-konto $20%$ skattefradrag for årets innskudd.
|
||||
|
||||
Du må selv avgjøre hvilke felt som må legges til for å støtte den beskrevne oppførsel. I tillegg stilles følgende krav til klassen:
|
||||
|
||||
- `BSU(double, double)` - konstruktør som tar inn rentefoten på kontoen og et desimaltall som angir hvor mye det er tillatt å sette inn på kontoen per år.
|
||||
- `double getTaxDeduction()` - returnerer skattefradrag for inneværende år. Dette vil være $20%$ av innskutt(e) beløp siste år.
|
||||
|
||||
Testkode for oppgavene finner du her: [oving7/savingsaccount/BSUTest.java](../../src/test/java/oving7/savingsaccount/BSUTest.java).
|
||||
|
||||
## Del 3 - ForeldreSpar extends SavingsAccount
|
||||
|
||||
En annen spesiell type sparekonto, her kalt ForeldreSpar, har et begrenset antall lovlige uttak per år (ofte i bytte mot en høyere rente). Du skal nå lage en slik `ForeldreSpar`-klasse som arver fra `SavingsAccount`-superklassen. Her er igjen målet at du skal gjenbruke mest mulig av _superklassen_ og samtidig støtte ForeldreSpar-spesifikk oppførsel. Denne klassen skal sikre at kun det lovlige antallet uttak gjøres i løpet av et år.
|
||||
|
||||
Du må selv avgjøre hvilke felt som må legges til før å støtte den beskrevne oppførsel. I tillegg stilles følgende krav til klassen:
|
||||
|
||||
- `ForeldreSpar(double, int)` - konstruktør som tar inn rentefoten på kontoen og et heltall som angir antall lovlige uttak per år.
|
||||
- `int getRemainingWithdrawals()` - returnerer antall gjenstående uttak fra sparekontoen.
|
||||
|
||||
Testkode for oppgavene finner du her: [oving7/savingsaccount/ForeldreSparTest.java](../../src/test/java/oving7/savingsaccount/ForeldreSparTest.java).
|
||||
51
oppgavetekster/oving7/Train.md
Normal file
51
oppgavetekster/oving7/Train.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Arv - Train-oppgave
|
||||
|
||||
I denne oppgaven skal vi modellere to typer togvogner og bruke dem i et tog. Vi vil bruke arv og samle det som er felles for togvognene i en _superklasse_.
|
||||
|
||||
Denne oppgaven er på likt format som dere møtte i [Øving 3 - Card-oppgaven](../oving3/Card.md), der det ikke blir oppgitt en detaljert beskrivelse av klassene her i `README`-filen, men heller gjennom Javadoc-dokumentasjonen. Dette er igjen for å gi dere øving i å lese og forstå dokumentasjon, som er et vanlig format å bli gitt oppgaver på eksamen.
|
||||
|
||||
> Kjapt tips: Hold musen over metoden/klassen for å lese Javadoc-dokumentasjonen på et fint format.
|
||||
|
||||
Filene i denne oppgaven skal legges i [oving7/train](../../src/main/java/oving7/train).
|
||||
|
||||
## Del 1 - TrainCar
|
||||
|
||||

|
||||
|
||||
I denne delen skal du lage en klasse kalt `TrainCar` for en enkel og generell togvogn, med følgende funksjonalitet som beskrevet i Javadoc-dokumentasjonen i klassen. Se også diagrammet over.
|
||||
|
||||
Skjellet for klassen finner du i [oving7/train/TrainCar.java](../../src/main/java/oving7/train/TrainCar.java).
|
||||
|
||||
Testkode for oppgaven finner du her: [oving7/train/TrainCarTest.java](../../src/test/java/oving7/train/TrainCarTest.java).
|
||||
|
||||
## Del 2 - CargoCar og PassengerCar
|
||||
|
||||

|
||||
|
||||
I denne delen skal du lage to forskjellige typer togvogner som er spesialiserte for sitt bruk. Begge arver fra `TrainCar`.
|
||||
|
||||
### CargoCar extends TrainCar
|
||||
|
||||
Denne klassen skal gjenspeile en lastevogn som frakter diverse ting og tang. Funksjonalitet skal være som beskrevet i dokumentasjonen. Se også diagrammet over.
|
||||
|
||||
Skjellet for klassen finner du i [oving7/train/CargoCar.java](../../src/main/java/oving7/train/CargoCar.java).
|
||||
|
||||
Testkode for oppgaven finner du her: [oving7/train/CargoCarTest.java](../../src/test/java/oving7/train/CargoCarTest.java).
|
||||
|
||||
### PassengerCar extends TrainCar
|
||||
|
||||
Denne klassen gjenspeiler en passasjervogn. Metodene skal være som beskrevet i dokumentasjonen. Se også diagrammet over.
|
||||
|
||||
Legg merke til at for å beregne totalvekta, så kan du anta at en gjennomsnittspassasjer veier 80 kg.
|
||||
|
||||
Skjellet for klassen finner du i [oving7/train/PassengerCar.java](../../src/main/java/oving7/train/PassengerCar.java).
|
||||
|
||||
Testkode for oppgaven finner du her: [oving7/train/PassengerCarTest.java](../../src/test/java/oving7/train/PassengerCarTest.java).
|
||||
|
||||
## Del 3 - Train
|
||||
|
||||

|
||||
|
||||
Klassen `Train` skal forestille et tog bestående av et sett vogner. Klassen skal ha metoder som beskrevet i dokumentasjonen. Se også diagrammet over.
|
||||
|
||||
Testkode for oppgaven finner du her: [oving7/train/TrainTest.java](../../src/test/java/oving7/train/TrainTest.java).
|
||||
BIN
oppgavetekster/oving7/img/observablelist_del1.png
Normal file
BIN
oppgavetekster/oving7/img/observablelist_del1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 179 KiB |
26
oppgavetekster/oving7/img/observablelist_del1.puml
Normal file
26
oppgavetekster/oving7/img/observablelist_del1.puml
Normal file
@@ -0,0 +1,26 @@
|
||||
@startuml observablelist_del1
|
||||
|
||||
skinparam dpi 400
|
||||
|
||||
class ObservableList
|
||||
|
||||
class ObservableHighscoreList {
|
||||
- int maxSize
|
||||
- List<Integer> results
|
||||
|
||||
+ ObservableHighscoreList(int)
|
||||
+ int size()
|
||||
+ int getElement(int)
|
||||
+ void addResult(int)
|
||||
+ void addObservableListListener(ObservableListListener)
|
||||
+ void removeObservableListListener(ObservableListListener)
|
||||
}
|
||||
|
||||
interface ObservableListListener {
|
||||
void listChanged(ObservableList)
|
||||
}
|
||||
|
||||
ObservableHighscoreList --u|> ObservableList
|
||||
ObservableHighscoreList --> "observableListListeners: *" ObservableListListener
|
||||
|
||||
@enduml
|
||||
BIN
oppgavetekster/oving7/img/observablelist_del2.png
Normal file
BIN
oppgavetekster/oving7/img/observablelist_del2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 245 KiB |
34
oppgavetekster/oving7/img/observablelist_del2.puml
Normal file
34
oppgavetekster/oving7/img/observablelist_del2.puml
Normal file
@@ -0,0 +1,34 @@
|
||||
@startuml observablelist_del2
|
||||
|
||||
skinparam dpi 400
|
||||
|
||||
class ObservableList
|
||||
|
||||
class ObservableHighscoreList {
|
||||
- int maxSize
|
||||
- List<Integer> results
|
||||
|
||||
+ ObservableHighscoreList(int)
|
||||
+ int size()
|
||||
+ int getElement(int)
|
||||
+ void addResult(int)
|
||||
+ void addObservableListListener(ObservableListListener)
|
||||
+ void removeObservableListListener(ObservableListListener)
|
||||
}
|
||||
|
||||
interface ObservableListListener {
|
||||
void listChanged(ObservableList)
|
||||
}
|
||||
|
||||
class ObservableHighscoreListProgram {
|
||||
- ObservableHighscoreList observableHighscoreList
|
||||
|
||||
+ void init()
|
||||
+ void run()
|
||||
}
|
||||
|
||||
ObservableHighscoreList --l|> ObservableList : "\t\t"
|
||||
ObservableHighscoreList --> "observableListListeners: *" ObservableListListener
|
||||
ObservableHighscoreListProgram ..r|> ObservableListListener : "\t\t"
|
||||
|
||||
@enduml
|
||||
BIN
oppgavetekster/oving7/img/observablelist_del3.png
Normal file
BIN
oppgavetekster/oving7/img/observablelist_del3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 343 KiB |
44
oppgavetekster/oving7/img/observablelist_del3.puml
Normal file
44
oppgavetekster/oving7/img/observablelist_del3.puml
Normal file
@@ -0,0 +1,44 @@
|
||||
@startuml observablelist_del3
|
||||
|
||||
skinparam dpi 400
|
||||
|
||||
abstract class ObservableList {
|
||||
- List<Object> elements
|
||||
|
||||
+ int size()
|
||||
+ void addObservableListListener(ObservableListListener)
|
||||
+ void removeObservableListListener(ObservableListListener)
|
||||
+ Object getElement(int)
|
||||
# {abstract} boolean acceptsElement(Object)
|
||||
# void addElement(Object)
|
||||
# void removeElement(Object)
|
||||
}
|
||||
|
||||
class ObservableHighscoreList {
|
||||
- int maxSize
|
||||
- List<Integer> results
|
||||
|
||||
+ ObservableHighscoreList(int)
|
||||
+ int size()
|
||||
+ int getElement(int)
|
||||
+ void addResult(int)
|
||||
+ void addObservableListListener(ObservableListListener)
|
||||
+ void removeObservableListListener(ObservableListListener)
|
||||
}
|
||||
|
||||
interface ObservableListListener {
|
||||
void listChanged(ObservableList)
|
||||
}
|
||||
|
||||
class ObservableHighscoreListProgram {
|
||||
- ObservableHighscoreList observableHighscoreList
|
||||
|
||||
+ void init()
|
||||
+ void run()
|
||||
}
|
||||
|
||||
ObservableHighscoreList --l|> ObservableList : "\t\t"
|
||||
ObservableHighscoreList --> "observableListListeners: *" ObservableListListener
|
||||
ObservableHighscoreListProgram ..r|> ObservableListListener : "\t\t"
|
||||
|
||||
@enduml
|
||||
BIN
oppgavetekster/oving7/img/train_del1.png
Normal file
BIN
oppgavetekster/oving7/img/train_del1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
14
oppgavetekster/oving7/img/train_del1.puml
Normal file
14
oppgavetekster/oving7/img/train_del1.puml
Normal file
@@ -0,0 +1,14 @@
|
||||
@startuml train_del1
|
||||
|
||||
skinparam dpi 400
|
||||
|
||||
class TrainCar {
|
||||
- int deadWeight
|
||||
|
||||
+ int getTotalWeight()
|
||||
+ void setDeadWeight(int)
|
||||
+ int getDeadWeight()
|
||||
+ String toString()
|
||||
}
|
||||
|
||||
@enduml
|
||||
BIN
oppgavetekster/oving7/img/train_del2.png
Normal file
BIN
oppgavetekster/oving7/img/train_del2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 KiB |
33
oppgavetekster/oving7/img/train_del2.puml
Normal file
33
oppgavetekster/oving7/img/train_del2.puml
Normal file
@@ -0,0 +1,33 @@
|
||||
@startuml train_del2
|
||||
|
||||
skinparam dpi 400
|
||||
|
||||
class TrainCar {
|
||||
- int deadWeight
|
||||
|
||||
+ int getTotalWeight()
|
||||
+ void setDeadWeight(int)
|
||||
+ int getDeadWeight()
|
||||
+ String toString()
|
||||
}
|
||||
|
||||
class CargoCar {
|
||||
- int cargoWeight
|
||||
|
||||
+ CargoCar(int, int)
|
||||
+ void setCargoWeight(int)
|
||||
+ int getCargoWeight()
|
||||
}
|
||||
|
||||
class PassengerCar {
|
||||
- int passengerCount
|
||||
|
||||
+ PassengerCar(int, int)
|
||||
+ void setPassengerCount(int)
|
||||
+ int getPassengerCount()
|
||||
}
|
||||
|
||||
CargoCar --u|> TrainCar
|
||||
PassengerCar --u|> TrainCar
|
||||
|
||||
@enduml
|
||||
BIN
oppgavetekster/oving7/img/train_del3.png
Normal file
BIN
oppgavetekster/oving7/img/train_del3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 287 KiB |
44
oppgavetekster/oving7/img/train_del3.puml
Normal file
44
oppgavetekster/oving7/img/train_del3.puml
Normal file
@@ -0,0 +1,44 @@
|
||||
@startuml train_del3
|
||||
|
||||
skinparam dpi 400
|
||||
|
||||
class TrainCar {
|
||||
- int deadWeight
|
||||
|
||||
+ int getTotalWeight()
|
||||
+ void setDeadWeight(int)
|
||||
+ int getDeadWeight()
|
||||
+ String toString()
|
||||
}
|
||||
|
||||
class CargoCar {
|
||||
- int cargoWeight
|
||||
|
||||
+ CargoCar(int, int)
|
||||
+ void setCargoWeight(int)
|
||||
+ int getCargoWeight()
|
||||
+ String toString()
|
||||
}
|
||||
|
||||
class PassengerCar {
|
||||
- int passengerCount
|
||||
|
||||
+ PassengerCar(int, int)
|
||||
+ void setPassengerCount(int)
|
||||
+ int getPassengerCount()
|
||||
}
|
||||
|
||||
class Train {
|
||||
+ void addTrainCar(TrainCar)
|
||||
+ boolean contains(TrainCar)
|
||||
+ int getTotalWeight()
|
||||
+ int getPassengerCount()
|
||||
+ int getCargoWeight()
|
||||
+ String toString()
|
||||
}
|
||||
|
||||
CargoCar --u|> TrainCar
|
||||
PassengerCar --u|> TrainCar
|
||||
Train --> "trainCars: *" TrainCar
|
||||
|
||||
@enduml
|
||||
1
pom.xml
1
pom.xml
@@ -11,6 +11,7 @@
|
||||
<properties>
|
||||
<maven.compiler.source>25</maven.compiler.source>
|
||||
<maven.compiler.target>25</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -7,6 +7,5 @@ open module ovinger {
|
||||
requires javafx.controls;
|
||||
requires javafx.fxml;
|
||||
requires javafx.graphics;
|
||||
requires org.junit.jupiter.api;
|
||||
requires com.google.common;
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package oving4.testing;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class CoffeeCupTest {
|
||||
|
||||
private CoffeeCup coffee;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
coffee = new CoffeeCup();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructor")
|
||||
public void testConstructor() {
|
||||
assertEquals(0, coffee.getCapacity());
|
||||
assertEquals(0, coffee.getCurrentVolume());
|
||||
coffee.increaseCupSize(10);
|
||||
assertEquals(10, coffee.getCapacity());
|
||||
coffee.fillCoffee(10);
|
||||
assertEquals(10, coffee.getCurrentVolume());
|
||||
coffee.drinkCoffee(10);
|
||||
assertEquals(0, coffee.getCurrentVolume());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("volume cannot be null")
|
||||
public void testAddChildException() {
|
||||
}
|
||||
|
||||
}
|
||||
66
src/main/java/oving5/BinaryComputingIterator.java
Normal file
66
src/main/java/oving5/BinaryComputingIterator.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package oving5;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.function.BinaryOperator;
|
||||
|
||||
public class BinaryComputingIterator {
|
||||
private Iterator<Double> iterator1;
|
||||
private Iterator<Double> iterator2;
|
||||
|
||||
private Double default1;
|
||||
private Double default2;
|
||||
|
||||
private BinaryOperator<Double> operator;
|
||||
|
||||
BinaryComputingIterator(Iterator<Double> iterator1, Iterator<Double> iterator2, BinaryOperator<Double> operator) {
|
||||
if (iterator1 == null || iterator2 == null || operator == null) {
|
||||
throw new IllegalArgumentException("argument cannot be null");
|
||||
}
|
||||
this.iterator1 = iterator1;
|
||||
this.iterator2 = iterator2;
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
BinaryComputingIterator(Iterator<Double> iterator1, Iterator<Double> iterator2, Double default1, Double default2,
|
||||
BinaryOperator<Double> operator) {
|
||||
if (iterator1 == null || iterator2 == null || operator == null) {
|
||||
throw new IllegalArgumentException("argument cannot be null");
|
||||
}
|
||||
this.iterator1 = iterator1;
|
||||
this.iterator2 = iterator2;
|
||||
this.operator = operator;
|
||||
this.default1 = default1;
|
||||
this.default2 = default2;
|
||||
}
|
||||
|
||||
boolean hasNext() {
|
||||
if (!iterator1.hasNext() && !iterator2.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
if ((iterator1.hasNext() || default1 != null) && (iterator2.hasNext() || default2 != null)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Double next() {
|
||||
if (hasNext()) {
|
||||
Double a = 0.0;
|
||||
if (iterator1.hasNext()) {
|
||||
a = iterator1.next();
|
||||
} else {
|
||||
a = default1;
|
||||
}
|
||||
|
||||
Double b = 0.0;
|
||||
if (iterator2.hasNext()) {
|
||||
b = iterator2.next();
|
||||
} else {
|
||||
b = default2;
|
||||
}
|
||||
|
||||
return operator.apply(a, b);
|
||||
}
|
||||
throw new IllegalArgumentException("empty things");
|
||||
}
|
||||
}
|
||||
65
src/main/java/oving5/RPNCalc.java
Normal file
65
src/main/java/oving5/RPNCalc.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package oving5;
|
||||
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.Stack;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class RPNCalc {
|
||||
private HashMap<Character, BinaryOperator<Double>> ops = new HashMap<Character, BinaryOperator<Double>>();
|
||||
private Stack<Double> stack = new Stack<>();
|
||||
|
||||
RPNCalc() {
|
||||
}
|
||||
|
||||
boolean addOperator(char op, BinaryOperator<Double> f) {
|
||||
if (ops.containsKey(op) || f == null) {
|
||||
return false;
|
||||
}
|
||||
ops.put(op, f);
|
||||
return true;
|
||||
}
|
||||
|
||||
void push(double n) {
|
||||
stack.push(n);
|
||||
}
|
||||
|
||||
double pop() {
|
||||
if (stack.isEmpty()) {
|
||||
return Double.NaN;
|
||||
}
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
double peek(int i) {
|
||||
int id = stack.size() - i;
|
||||
if (id < 0 || id >= stack.size()) {
|
||||
return Double.NaN;
|
||||
}
|
||||
return stack.get(id);
|
||||
}
|
||||
|
||||
int getSize() {
|
||||
return stack.size();
|
||||
}
|
||||
|
||||
void performOperation(char c) {
|
||||
BinaryOperator<Double> op = ops.get(c);
|
||||
|
||||
if (op == null) {
|
||||
throw new UnsupportedOperationException("Invalid operator: " + c);
|
||||
}
|
||||
|
||||
if (stack.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
double a = stack.pop();
|
||||
double b = stack.pop();
|
||||
|
||||
stack.push(op.apply(b, a));
|
||||
}
|
||||
|
||||
void removeOperator(char c) {
|
||||
ops.remove(c);
|
||||
}
|
||||
|
||||
}
|
||||
10
src/main/java/oving5/card/Card.java
Normal file
10
src/main/java/oving5/card/Card.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package oving5.card;
|
||||
|
||||
public class Card {
|
||||
Card(char suit, int card) {
|
||||
}
|
||||
|
||||
char getSuit() {
|
||||
return 'A';
|
||||
}
|
||||
}
|
||||
@@ -27,18 +27,17 @@ public class StringMergingIterator implements Iterator<String> {
|
||||
|
||||
String result = null;
|
||||
|
||||
if (!this.first.hasNext()) {
|
||||
if (this.turnSwitch && this.first.hasNext()) {
|
||||
result = this.first.next();
|
||||
} else if (!this.second.hasNext()) {
|
||||
} else if (!this.turnSwitch && this.second.hasNext()) {
|
||||
result = this.second.next();
|
||||
} else {
|
||||
if (this.turnSwitch) {
|
||||
if (this.first.hasNext()) {
|
||||
result = this.first.next();
|
||||
this.turnSwitch = false;
|
||||
}
|
||||
if (!this.turnSwitch) {
|
||||
} else if (this.second.hasNext()) {
|
||||
result = this.second.next();
|
||||
this.turnSwitch = true;
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
10
src/main/java/oving5/named/Named.java
Normal file
10
src/main/java/oving5/named/Named.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package oving5.named;
|
||||
|
||||
public interface Named {
|
||||
String getFullName();
|
||||
String getFamilyName();
|
||||
String getGivenName();
|
||||
void setGivenName(String name);
|
||||
void setFamilyName(String name);
|
||||
void setFullName(String name);
|
||||
}
|
||||
14
src/main/java/oving5/named/NamedComparator.java
Normal file
14
src/main/java/oving5/named/NamedComparator.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package oving5.named;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class NamedComparator implements Comparator<Named> {
|
||||
@Override
|
||||
public int compare(Named named1, Named named2) {
|
||||
int a = named1.getFamilyName().compareTo(named2.getFamilyName());
|
||||
if (a == 0) {
|
||||
return named1.getGivenName().compareTo(named2.getGivenName());
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
43
src/main/java/oving5/named/Person1.java
Normal file
43
src/main/java/oving5/named/Person1.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package oving5.named;
|
||||
|
||||
public class Person1 implements Named {
|
||||
private String givenName;
|
||||
private String familyName;
|
||||
private String fullName;
|
||||
|
||||
Person1(String givenName, String familyName) {
|
||||
setFullName(givenName + " " + familyName);
|
||||
setGivenName(givenName);
|
||||
setFamilyName(familyName);
|
||||
}
|
||||
|
||||
public void setFullName(String fullName) {
|
||||
this.fullName = fullName;
|
||||
String[] l = fullName.split(" ");
|
||||
givenName = (l[0]);
|
||||
familyName = (l[1]);
|
||||
}
|
||||
|
||||
public void setFamilyName(String familyName) {
|
||||
this.familyName = familyName;
|
||||
setFullName(givenName + " " + familyName);
|
||||
}
|
||||
|
||||
public void setGivenName(String givenName) {
|
||||
this.givenName = givenName;
|
||||
setFullName(givenName + " " + familyName);
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public String getFamilyName() {
|
||||
return familyName;
|
||||
}
|
||||
|
||||
public String getGivenName() {
|
||||
return givenName;
|
||||
}
|
||||
|
||||
}
|
||||
41
src/main/java/oving5/named/Person2.java
Normal file
41
src/main/java/oving5/named/Person2.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package oving5.named;
|
||||
|
||||
public class Person2 implements Named {
|
||||
private String fullName;
|
||||
private String familyName;
|
||||
private String givenName;
|
||||
|
||||
Person2(String fullName) {
|
||||
setFullName(fullName);
|
||||
}
|
||||
|
||||
public void setFullName(String fullName) {
|
||||
this.fullName = fullName;
|
||||
String[] l = fullName.split(" ");
|
||||
givenName = l[0];
|
||||
familyName = l[1];
|
||||
}
|
||||
|
||||
public void setFamilyName(String familyName) {
|
||||
this.familyName = familyName;
|
||||
fullName = givenName + " " + familyName;
|
||||
}
|
||||
|
||||
public void setGivenName(String givenName) {
|
||||
this.givenName = givenName;
|
||||
fullName = givenName + " " + familyName;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public String getFamilyName() {
|
||||
return familyName;
|
||||
}
|
||||
|
||||
public String getGivenName() {
|
||||
return givenName;
|
||||
}
|
||||
|
||||
}
|
||||
23
src/main/java/oving5/stringgrid/StringGrid.java
Normal file
23
src/main/java/oving5/stringgrid/StringGrid.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package oving5.stringgrid;
|
||||
|
||||
/**
|
||||
* An interface with methods for managing the content of a String grid. The grid has a number of
|
||||
* rows (the grid's height) and columns (the grid's width). In each cell in the grid there is a
|
||||
* String that can be set with the setElement method and read with the getElement method.
|
||||
*/
|
||||
public interface StringGrid {
|
||||
|
||||
// Returns the number of rows in this StringGrid
|
||||
int getRowCount();
|
||||
|
||||
// Returns the number of columns in this StringGrid
|
||||
int getColumnCount();
|
||||
|
||||
// Returns the String at the given row and column. Throws an IllegalArgumentException if the
|
||||
// row or column is out of range
|
||||
String getElement(int row, int column);
|
||||
|
||||
// Sets the String at the given row and column. Throws an IllegalArgumentException if the row
|
||||
// or column is out of range
|
||||
void setElement(int row, int column, String element);
|
||||
}
|
||||
55
src/main/java/oving5/stringgrid/StringGridImpl.java
Normal file
55
src/main/java/oving5/stringgrid/StringGridImpl.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package oving5.stringgrid;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public class StringGridImpl implements StringGrid {
|
||||
private ArrayList<String> grid;
|
||||
private int rows;
|
||||
private int columns;
|
||||
|
||||
StringGridImpl(int rows, int columns) {
|
||||
grid = new ArrayList<String>(Collections.nCopies(rows * columns, ""));
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public String getElement(int row, int column) {
|
||||
if (row < 0 || row >= rows || column < 0 || column >= columns) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid value for row or column, got row: " + row + ", and column: " + column);
|
||||
}
|
||||
return grid.get(row * columns + column);
|
||||
}
|
||||
|
||||
public void setElement(int row, int column, String element) {
|
||||
if (row < 0 || row >= rows || column < 0 || column >= columns) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid value for row or column, got row: " + row + ", and column: " + column);
|
||||
}
|
||||
grid.set(row * columns + column, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String r = "";
|
||||
for (int y = 0; y < rows; y++) {
|
||||
for (int x = 0; x < columns; x++) {
|
||||
r += grid.get(y * columns + x);
|
||||
if (x < columns - 1) {
|
||||
r += " | ";
|
||||
}
|
||||
}
|
||||
r += "\n";
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
35
src/main/java/oving5/stringgrid/StringGridIterator.java
Normal file
35
src/main/java/oving5/stringgrid/StringGridIterator.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package oving5.stringgrid;
|
||||
|
||||
public class StringGridIterator {
|
||||
private StringGrid grid;
|
||||
private boolean rowMajor;
|
||||
private int i = -1;
|
||||
|
||||
public StringGridIterator(StringGrid grid, boolean rowMajor) {
|
||||
this.grid = grid;
|
||||
this.rowMajor = rowMajor;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return (i + 1) < (grid.getRowCount() * grid.getColumnCount());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String next() {
|
||||
if (hasNext()) {
|
||||
i += 1;
|
||||
if (rowMajor) {
|
||||
return grid.getElement(i / grid.getColumnCount(), i % grid.getColumnCount());
|
||||
} else {
|
||||
return grid.getElement(i % grid.getRowCount(), i / grid.getRowCount());
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
12
src/main/java/oving5/ticket/PeriodTicket.java
Normal file
12
src/main/java/oving5/ticket/PeriodTicket.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package oving5.ticket;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class PeriodTicket {
|
||||
PeriodTicket(LocalDateTime start, LocalDateTime end) {
|
||||
}
|
||||
|
||||
public boolean scan() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
6
src/main/java/oving5/ticket/SingleTicket.java
Normal file
6
src/main/java/oving5/ticket/SingleTicket.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package oving5.ticket;
|
||||
|
||||
public class SingleTicket {
|
||||
SingleTicket() {
|
||||
}
|
||||
}
|
||||
10
src/main/java/oving5/twitter/FollowersCountComparator.java
Normal file
10
src/main/java/oving5/twitter/FollowersCountComparator.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package oving5.twitter;
|
||||
|
||||
public class FollowersCountComparator {
|
||||
FollowersCountComparator() {
|
||||
}
|
||||
|
||||
int compare(TwitterAccount a, TwitterAccount b) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
10
src/main/java/oving5/twitter/TweetsCountComparator.java
Normal file
10
src/main/java/oving5/twitter/TweetsCountComparator.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package oving5.twitter;
|
||||
|
||||
public class TweetsCountComparator {
|
||||
TweetsCountComparator() {
|
||||
}
|
||||
|
||||
public int compare(TwitterAccount a, TwitterAccount b) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
50
src/main/java/oving5/twitter/TwitterAccount.java
Normal file
50
src/main/java/oving5/twitter/TwitterAccount.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package oving5.twitter;
|
||||
|
||||
public class TwitterAccount {
|
||||
TwitterAccount(String s) {
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void tweet(String s) {
|
||||
}
|
||||
|
||||
public TwitterAccount getTweet(int i) {
|
||||
return new TwitterAccount("");
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public int getTweetCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void retweet(TwitterAccount s) {
|
||||
}
|
||||
|
||||
public int getRetweetCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public TwitterAccount getOriginalTweet() {
|
||||
return new TwitterAccount("");
|
||||
}
|
||||
|
||||
public void unfollow(TwitterAccount a) {
|
||||
}
|
||||
|
||||
public void follow(TwitterAccount a) {
|
||||
}
|
||||
|
||||
public boolean isFollowedBy(TwitterAccount a) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFollowing(TwitterAccount a) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
7
src/main/java/oving5/twitter/UserNameComparator.java
Normal file
7
src/main/java/oving5/twitter/UserNameComparator.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package oving5.twitter;
|
||||
|
||||
public class UserNameComparator {
|
||||
public int compare(TwitterAccount a, TwitterAccount b) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
79
src/main/java/oving6/highscorelist/HighscoreList.java
Normal file
79
src/main/java/oving6/highscorelist/HighscoreList.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package oving6.highscorelist;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public class HighscoreList {
|
||||
private int maxSize = 0;
|
||||
private List<Integer> results = new ArrayList<Integer>();
|
||||
private ArrayList<HighscoreListListener> highscoreListListeners = new ArrayList<HighscoreListListener>();
|
||||
|
||||
HighscoreList(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return results.size();
|
||||
}
|
||||
|
||||
public int getElement(int i) {
|
||||
if (i < 0 || i >= results.size()) {
|
||||
throw new IllegalArgumentException("Invalid value for i");
|
||||
}
|
||||
return results.get(i);
|
||||
}
|
||||
|
||||
public void addResult(int r) {
|
||||
if (maxSize <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = results.size();
|
||||
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
if (r < results.get(i)) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (results.size() < maxSize || idx < results.size()) {
|
||||
results.add(r);
|
||||
Collections.sort(results);
|
||||
while (results.size() > maxSize) {
|
||||
results.removeLast();
|
||||
}
|
||||
sendHighscoreEvent(idx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void addHighscoreListListener(HighscoreListListener listener) {
|
||||
highscoreListListeners.add(listener);
|
||||
|
||||
}
|
||||
|
||||
public void removeHighscoreListListener(HighscoreListListener listener) {
|
||||
highscoreListListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void sendHighscoreEvent(int i) {
|
||||
for (HighscoreListListener listener : highscoreListListeners) {
|
||||
listener.listChanged(this, i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String s = "[";
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
s += results.get(i);
|
||||
if (i < results.size() - 1) {
|
||||
s += ",";
|
||||
}
|
||||
}
|
||||
s += "]";
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package oving6.highscorelist;
|
||||
|
||||
public interface HighscoreListListener {
|
||||
void listChanged(HighscoreList l, int i);
|
||||
}
|
||||
35
src/main/java/oving6/highscorelist/HighscoreProgram.java
Normal file
35
src/main/java/oving6/highscorelist/HighscoreProgram.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package oving6.highscorelist;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
public class HighscoreProgram implements HighscoreListListener {
|
||||
HighscoreList highscoreList;
|
||||
|
||||
void main() {
|
||||
init();
|
||||
run();
|
||||
}
|
||||
|
||||
void init() {
|
||||
highscoreList = new HighscoreList(10);
|
||||
highscoreList.addHighscoreListListener(this);
|
||||
}
|
||||
|
||||
void run() {
|
||||
System.out.println("Starting listener:");
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
while (true) {
|
||||
if (scanner.hasNextInt()) {
|
||||
highscoreList.addResult(scanner.nextInt());
|
||||
} else {
|
||||
scanner.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listChanged(HighscoreList l, int i) {
|
||||
System.out.println("List[" + i + "]: " + l.toString());
|
||||
}
|
||||
|
||||
}
|
||||
48
src/main/java/oving6/logger/DistributingLogger.java
Normal file
48
src/main/java/oving6/logger/DistributingLogger.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package oving6.logger;
|
||||
|
||||
public class DistributingLogger implements ILogger {
|
||||
ILogger errorLogger;
|
||||
ILogger warningLogger;
|
||||
ILogger infoLogger;
|
||||
|
||||
DistributingLogger(ILogger errorLogger, ILogger warningLogger, ILogger infoLogger) {
|
||||
this.errorLogger = errorLogger;
|
||||
this.warningLogger = warningLogger;
|
||||
this.infoLogger = infoLogger;
|
||||
}
|
||||
|
||||
void setLogger(String severity, ILogger logger) {
|
||||
switch (severity) {
|
||||
case "error":
|
||||
errorLogger = logger;
|
||||
break;
|
||||
case "warning":
|
||||
warningLogger = logger;
|
||||
break;
|
||||
case "info":
|
||||
infoLogger = logger;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid severity level for logger");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String severity, String message, Exception exception) {
|
||||
switch (severity) {
|
||||
case "error":
|
||||
errorLogger.log(severity, message, exception);
|
||||
break;
|
||||
case "warning":
|
||||
warningLogger.log(severity, message, exception);
|
||||
break;
|
||||
case "info":
|
||||
infoLogger.log(severity, message, exception);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid severity level for logger");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
29
src/main/java/oving6/logger/FilteringLogger.java
Normal file
29
src/main/java/oving6/logger/FilteringLogger.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package oving6.logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class FilteringLogger {
|
||||
private ILogger logger;
|
||||
private HashMap<String, Boolean> logging = new HashMap<String, Boolean>();
|
||||
|
||||
FilteringLogger(ILogger logger, String... severities) {
|
||||
this.logger = logger;
|
||||
for (String severity : severities) {
|
||||
logging.put(severity, true);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isLogging(String severity) {
|
||||
return logging.getOrDefault(severity, false);
|
||||
}
|
||||
|
||||
void setIsLogging(String severity, boolean value) {
|
||||
logging.put(severity, value);
|
||||
}
|
||||
|
||||
void log(String severity, String message, Exception exception) {
|
||||
if (isLogging(severity)) {
|
||||
logger.log(severity, message, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
src/main/java/oving6/logger/ILogger.java
Normal file
9
src/main/java/oving6/logger/ILogger.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package oving6.logger;
|
||||
|
||||
public interface ILogger {
|
||||
String ERROR = "error";
|
||||
String WARNING = "warning";
|
||||
String INFO = "info";
|
||||
|
||||
void log(String severity, String message, Exception exception);
|
||||
}
|
||||
31
src/main/java/oving6/logger/StreamLogger.java
Normal file
31
src/main/java/oving6/logger/StreamLogger.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package oving6.logger;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class StreamLogger implements ILogger {
|
||||
private OutputStream stream;
|
||||
private String formatString = "%s: %s (%s)";
|
||||
|
||||
StreamLogger(OutputStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String severity, String message, Exception exception) {
|
||||
try {
|
||||
String logMessage = String.format(formatString, severity, message, exception) + "\n";
|
||||
stream.write(logMessage.getBytes());
|
||||
stream.flush();
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setFormatString(String formatString) {
|
||||
if (formatString == null) {
|
||||
throw new IllegalArgumentException("formatString cannot be null");
|
||||
}
|
||||
this.formatString = formatString;
|
||||
}
|
||||
}
|
||||
77
src/main/java/oving7/abstractaccount/AbstractAccount.java
Normal file
77
src/main/java/oving7/abstractaccount/AbstractAccount.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package oving7.abstractaccount;
|
||||
|
||||
/**
|
||||
* A bank consists of many different types of accounts: credit accounts, debit
|
||||
* accounts, savings
|
||||
* accounts, etc. Since these have a lot in common, e.g. all have a balance, it
|
||||
* is practical to
|
||||
* collect as much of the common logic as possible in a superclass, which all
|
||||
* can inherit from.
|
||||
* However, this superclass is not a type of account in itself, and therefore we
|
||||
* make it
|
||||
* {@code abstract}, so that it cannot be instantiated. The concrete account
|
||||
* classes that inherit
|
||||
* from it, must of course be instantiable. The methods defined in the
|
||||
* {@code AbstractAccount} class
|
||||
* is similar to that of the Account interface in the SavingsAccount task.
|
||||
*/
|
||||
public abstract class AbstractAccount {
|
||||
|
||||
// AbstractAccount has a state {@code balance} for the account balance. The
|
||||
// balance should
|
||||
// either be set to 0.0 by default or in the constructor
|
||||
|
||||
// TODO: Add fields and potentially a constructor here
|
||||
|
||||
protected double balance = 0.0;
|
||||
|
||||
/**
|
||||
* Decreases the account balance by the specified amount. Note that the rules
|
||||
* for withdrawals
|
||||
* are different for the classes that implement {@code AbstractAccount}, and
|
||||
* must therefore be
|
||||
* implemented in each class.
|
||||
*
|
||||
* @param amount the amount to withdraw
|
||||
* @throws IllegalArgumentException if the amount cannot be withdrawn
|
||||
*/
|
||||
// TODO: Define abstract method {@code void internalWithdraw} here
|
||||
|
||||
protected abstract void internalWithdraw(double amount);
|
||||
|
||||
/**
|
||||
* Increases the account balance by the specified amount.
|
||||
*
|
||||
* @param amount the amount to deposit
|
||||
* @throws IllegalArgumentException if the amount is not positive
|
||||
*/
|
||||
public void deposit(double amount) {
|
||||
if (amount < 0.0) {
|
||||
throw new IllegalArgumentException("cannot deposit amount less than zero");
|
||||
}
|
||||
balance += amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method calls the {@link #internalWithdraw()} method, which is
|
||||
* implemented in each
|
||||
* subclass.
|
||||
*
|
||||
* @param amount the amount to withdraw
|
||||
* @throws IllegalArgumentException if the amount is not positive
|
||||
*/
|
||||
public void withdraw(double amount) {
|
||||
// TODO: Implement this method
|
||||
if (amount < 0.0) {
|
||||
throw new IllegalArgumentException("withdrawal amount cannot be less than zero");
|
||||
}
|
||||
internalWithdraw(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current balance of the account
|
||||
*/
|
||||
public double getBalance() {
|
||||
return balance;
|
||||
}
|
||||
}
|
||||
65
src/main/java/oving7/abstractaccount/CreditAccount.java
Normal file
65
src/main/java/oving7/abstractaccount/CreditAccount.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package oving7.abstractaccount;
|
||||
|
||||
/**
|
||||
* A {@code CreditAccount} has in addition to {@code balance} a state for
|
||||
* {@code creditLine}, i.e.
|
||||
* available credit on the account. This credit line allows the account to be
|
||||
* overdrawn (that the
|
||||
* balance is negative) within the credit line. If {@link #internalWithdraw()}
|
||||
* tries to withdraw
|
||||
* more money than is available, taking the credit line into account, an
|
||||
* {@code IllegalArgumentException} should be thrown.
|
||||
*
|
||||
* @see AbstractAccount
|
||||
*/
|
||||
public class CreditAccount extends AbstractAccount {
|
||||
|
||||
private double creditLine;
|
||||
|
||||
/**
|
||||
* Initializes a new {@code CreditAccount} with the specified credit line.
|
||||
*
|
||||
* @param creditLine the credit line
|
||||
* @throws IllegalArgumentException if the credit line is negative
|
||||
*/
|
||||
public CreditAccount(double creditLine) {
|
||||
this.creditLine = creditLine;
|
||||
}
|
||||
|
||||
protected void internalWithdraw(double amount) {
|
||||
if (amount > (balance + creditLine)) {
|
||||
throw new IllegalArgumentException("cannot withdraw more than balance plus creditLine");
|
||||
}
|
||||
balance -= amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the credit line
|
||||
*
|
||||
* @see CreditAccountTest#testCreditLine()
|
||||
*/
|
||||
public double getCreditLine() {
|
||||
return creditLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the credit line.
|
||||
*
|
||||
* @param creditLine the credit line
|
||||
* @throws IllegalArgumentException if the credit line is negative
|
||||
* @throws IllegalStateException if the new credit line does not cover the
|
||||
* existing balance
|
||||
*
|
||||
* @see CreditAccountTest#testCreditLine()
|
||||
*/
|
||||
public void setCreditLine(double creditLine) {
|
||||
if (creditLine < 0.0) {
|
||||
throw new IllegalArgumentException("credit line cannot be less than zero");
|
||||
}
|
||||
if (creditLine + balance < 0.0) {
|
||||
throw new IllegalStateException("credit line plus balance must be greater than or equal to zero");
|
||||
}
|
||||
|
||||
this.creditLine = creditLine;
|
||||
}
|
||||
}
|
||||
25
src/main/java/oving7/abstractaccount/DebitAccount.java
Normal file
25
src/main/java/oving7/abstractaccount/DebitAccount.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package oving7.abstractaccount;
|
||||
|
||||
/**
|
||||
* A debit account is the simplest form of account, where the only requirement
|
||||
* is that the balance
|
||||
* at any time must be greater than or equal to {@code 0.0}.
|
||||
* {@code DebitAccount} extends (inherits
|
||||
* from) {@link AbstractAccount} and ensure that the balance never falls below
|
||||
* {@code 0.0}. If an
|
||||
* attempt is made to withdraw more money than is available, an
|
||||
* {@code IllegalArgumentException}
|
||||
* should be thrown.
|
||||
*
|
||||
* @see AbstractAccount
|
||||
*/
|
||||
public class DebitAccount extends AbstractAccount {
|
||||
|
||||
@Override
|
||||
protected void internalWithdraw(double amount) {
|
||||
if (balance < amount) {
|
||||
throw new IllegalArgumentException("cannot withdraw amount greater than balance for debit account");
|
||||
}
|
||||
balance -= amount;
|
||||
}
|
||||
}
|
||||
49
src/main/java/oving7/abstractaccount/SavingsAccount.java
Normal file
49
src/main/java/oving7/abstractaccount/SavingsAccount.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package oving7.abstractaccount;
|
||||
|
||||
/**
|
||||
* A {@code SavingsAccount} can only have a positive balance. In addition, the
|
||||
* account has
|
||||
* withdrawal restrictions. A {@code SavingsAccount} has {@code x} number of
|
||||
* {@code withdrawals}. If
|
||||
* you want to withdraw money after all withdrawals have been used up, the
|
||||
* balance should be charged
|
||||
* a {@code fee}. If the balance is too low to cover the fee, an
|
||||
* {@code IllegalArgumentException}
|
||||
* should be thrown.
|
||||
*
|
||||
* @see AbstractAccount
|
||||
*/
|
||||
public class SavingsAccount extends AbstractAccount {
|
||||
|
||||
private int withdrawals;
|
||||
private double fee;
|
||||
|
||||
/**
|
||||
* Initializes a new {@code SavingsAccount} with the specified number of
|
||||
* withdrawals and fee.
|
||||
*
|
||||
* @param withdrawals the number of withdrawals
|
||||
* @param fee the fee
|
||||
* @throws IllegalArgumentException if the number of withdrawals or the fee is
|
||||
* negative
|
||||
*/
|
||||
public SavingsAccount(int withdrawals, double fee) {
|
||||
if (withdrawals < 0 || fee < 0.0) {
|
||||
throw new IllegalArgumentException("cannot have less than zero withdrawals or fee of less than zero");
|
||||
}
|
||||
this.withdrawals = withdrawals;
|
||||
this.fee = fee;
|
||||
}
|
||||
|
||||
protected void internalWithdraw(double amount) {
|
||||
withdrawals -= 1;
|
||||
double s = amount;
|
||||
if (withdrawals < 0) {
|
||||
s += fee;
|
||||
}
|
||||
if (balance < s) {
|
||||
throw new IllegalArgumentException("balance not great enough to cover fees");
|
||||
}
|
||||
balance -= s;
|
||||
}
|
||||
}
|
||||
0
src/main/java/oving7/card/.gitkeep
Normal file
0
src/main/java/oving7/card/.gitkeep
Normal file
0
src/main/java/oving7/observablelist/.gitkeep
Normal file
0
src/main/java/oving7/observablelist/.gitkeep
Normal file
0
src/main/java/oving7/savingsaccount/.gitkeep
Normal file
0
src/main/java/oving7/savingsaccount/.gitkeep
Normal file
9
src/main/java/oving7/savingsaccount/Account.java
Normal file
9
src/main/java/oving7/savingsaccount/Account.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package oving7.savingsaccount;
|
||||
|
||||
public interface Account {
|
||||
void deposit(double amount);
|
||||
|
||||
void withdraw(double amount);
|
||||
|
||||
double getBalance();
|
||||
}
|
||||
41
src/main/java/oving7/savingsaccount/BSU.java
Normal file
41
src/main/java/oving7/savingsaccount/BSU.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package oving7.savingsaccount;
|
||||
|
||||
public class BSU extends SavingsAccount {
|
||||
private double depositedThisYear = 0.0;
|
||||
private double depositMax;
|
||||
|
||||
BSU(double interestRate, double depositMax) {
|
||||
super(interestRate);
|
||||
this.depositMax = depositMax;
|
||||
}
|
||||
|
||||
public double getTaxDeduction() {
|
||||
return depositedThisYear * 0.2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deposit(double amount) {
|
||||
if ((depositedThisYear + amount) > depositMax) {
|
||||
throw new IllegalStateException(
|
||||
"cannot deposit more than the maximum deposit, which has a value of " + depositMax);
|
||||
}
|
||||
super.deposit(amount);
|
||||
depositedThisYear += amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void withdraw(double amount) {
|
||||
if (amount > depositedThisYear) {
|
||||
throw new IllegalStateException(
|
||||
"cannot withdraw more than has been deposited this year, which has a value of "
|
||||
+ depositedThisYear);
|
||||
}
|
||||
super.withdraw(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endYearUpdate() {
|
||||
super.endYearUpdate();
|
||||
depositedThisYear = 0.0;
|
||||
}
|
||||
}
|
||||
31
src/main/java/oving7/savingsaccount/ForeldreSpar.java
Normal file
31
src/main/java/oving7/savingsaccount/ForeldreSpar.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package oving7.savingsaccount;
|
||||
|
||||
public class ForeldreSpar extends SavingsAccount {
|
||||
private int withdrawalsMax;
|
||||
private int remainingWithdrawals;
|
||||
|
||||
ForeldreSpar(double interestRate, int withdrawalsMax) {
|
||||
super(interestRate);
|
||||
this.withdrawalsMax = withdrawalsMax;
|
||||
remainingWithdrawals = withdrawalsMax;
|
||||
}
|
||||
|
||||
int getRemainingWithdrawals() {
|
||||
return remainingWithdrawals;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void withdraw(double amount) {
|
||||
if (remainingWithdrawals <= 0) {
|
||||
throw new IllegalStateException("Cannot withdraw more than " + withdrawalsMax + " times a year");
|
||||
}
|
||||
super.withdraw(amount);
|
||||
remainingWithdrawals -= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endYearUpdate() {
|
||||
super.endYearUpdate();
|
||||
remainingWithdrawals = withdrawalsMax;
|
||||
}
|
||||
}
|
||||
35
src/main/java/oving7/savingsaccount/SavingsAccount.java
Normal file
35
src/main/java/oving7/savingsaccount/SavingsAccount.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package oving7.savingsaccount;
|
||||
|
||||
public class SavingsAccount implements Account {
|
||||
private double balance = 0.0;
|
||||
private double interestRate;
|
||||
|
||||
SavingsAccount(double interestRate) {
|
||||
this.interestRate = interestRate;
|
||||
}
|
||||
|
||||
public void deposit(double amount) {
|
||||
if (amount <= 0) {
|
||||
throw new IllegalArgumentException("deposit must be greater than zero");
|
||||
}
|
||||
balance += amount;
|
||||
}
|
||||
|
||||
public void withdraw(double amount) {
|
||||
if (amount <= 0) {
|
||||
throw new IllegalArgumentException("withdraw must be greater than zero");
|
||||
}
|
||||
if (amount > balance) {
|
||||
throw new IllegalStateException("cannot withdraw more than current balance");
|
||||
}
|
||||
balance -= amount;
|
||||
}
|
||||
|
||||
public double getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
public void endYearUpdate() {
|
||||
balance += balance * interestRate;
|
||||
}
|
||||
}
|
||||
63
src/main/java/oving7/train/CargoCar.java
Normal file
63
src/main/java/oving7/train/CargoCar.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package oving7.train;
|
||||
|
||||
/**
|
||||
* One of two different types of train cars, both specialized versions for different purposes. A
|
||||
* {@code CargoCar} represents a cargo car that transports various things and stuff.
|
||||
*
|
||||
* @see TrainCar
|
||||
* @see PassengerCar
|
||||
*/
|
||||
public class CargoCar extends TrainCar {
|
||||
|
||||
private int cargoWeight;
|
||||
|
||||
/**
|
||||
* Constructor for the cargo car.
|
||||
*
|
||||
* @param deadWeight the weight of an empty cargo car
|
||||
* @param cargoWeight the weight of the cargo in the cargo car
|
||||
* @throws IllegalArgumentException if either deadWeight or cargoWeight is negative
|
||||
*
|
||||
* @see CargoCarTest#testWeight()
|
||||
*/
|
||||
public CargoCar(int deadWeight, int cargoWeight) {
|
||||
super(deadWeight);
|
||||
this.cargoWeight = cargoWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the weight of the cargo in the cargo car
|
||||
*
|
||||
* @see CargoCarTest#testWeight()
|
||||
*/
|
||||
public int getCargoWeight() {
|
||||
return cargoWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cargoWeight the weight of the cargo in the cargo car
|
||||
* @throws IllegalArgumentException if cargoWeight is negative
|
||||
*
|
||||
* @see CargoCarTest#testWeight()
|
||||
*/
|
||||
public void setCargoWeight(int cargoWeight) {
|
||||
if (cargoWeight < 0) {
|
||||
throw new IllegalArgumentException("cargo weight cannot be less than zero");
|
||||
}
|
||||
this.cargoWeight = cargoWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalWeight() {
|
||||
return cargoWeight + super.getDeadWeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CargoCar";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
65
src/main/java/oving7/train/PassengerCar.java
Normal file
65
src/main/java/oving7/train/PassengerCar.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package oving7.train;
|
||||
|
||||
/**
|
||||
* One of two different types of train cars, both specialized versions for different purposes. A
|
||||
* {@code PassengerCar} represents a passenger car that transports passengers.
|
||||
*
|
||||
* @see TrainCar
|
||||
* @see CargoCar
|
||||
*/
|
||||
public class PassengerCar extends TrainCar {
|
||||
|
||||
private int passengerCount;
|
||||
|
||||
/**
|
||||
* Constructor for the passenger car.
|
||||
*
|
||||
* @param deadWeight the weight of an empty passenger car
|
||||
* @param passengerCount the number of passengers in the passenger car
|
||||
* @throws IllegalArgumentException if either deadWeight or passengerCount is negative
|
||||
*
|
||||
* @see PassengerCarTest#testWeight()
|
||||
*/
|
||||
public PassengerCar(int deadWeight, int passengerCount) {
|
||||
this.passengerCount = passengerCount;
|
||||
super(deadWeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of passengers in the passenger car
|
||||
*
|
||||
* @see PassengerCarTest#testWeight()
|
||||
*/
|
||||
public int getPassengerCount() {
|
||||
return passengerCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param passengerCount the number of passengers in the passenger car
|
||||
* @throws IllegalArgumentException if passengerCount is negative
|
||||
*
|
||||
* @see PassengerCarTest#testWeight()
|
||||
*/
|
||||
public void setPassengerCount(int passengerCount) {
|
||||
if (passengerCount < 0) {
|
||||
throw new IllegalArgumentException("passenger count cannot be less than zero");
|
||||
}
|
||||
this.passengerCount = passengerCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalWeight() {
|
||||
// To calculate the total weight of the passenger car, you can assume that an average
|
||||
// passenger weighs 80 kg
|
||||
return super.getDeadWeight() + passengerCount * 80;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PassengerCar";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
96
src/main/java/oving7/train/Train.java
Normal file
96
src/main/java/oving7/train/Train.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package oving7.train;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* The class {@code Train} represents a train that consists of one or more train cars.
|
||||
*
|
||||
* @see TrainCar
|
||||
* @see CargoCar
|
||||
* @see PassengerCar
|
||||
*/
|
||||
public class Train {
|
||||
|
||||
private ArrayList<TrainCar> trainCars = new ArrayList<TrainCar>();
|
||||
|
||||
/**
|
||||
* @param trainCar the train car to check for
|
||||
* @return {@code true} if the train contains the train car, {@code false} otherwise
|
||||
*
|
||||
* @see TrainTest#testAddCarToTrain()
|
||||
*/
|
||||
public boolean contains(TrainCar trainCar) {
|
||||
return trainCars.contains(trainCar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a train car to the train.
|
||||
*
|
||||
* @param trainCar the train car to add
|
||||
* @throws IllegalArgumentException if the train car is {@code null}
|
||||
*
|
||||
* @see TrainTest#testAddCarToTrain()
|
||||
*/
|
||||
public void addTrainCar(TrainCar trainCar) {
|
||||
if (trainCar == null) {
|
||||
throw new IllegalArgumentException("train car cannot be null");
|
||||
}
|
||||
trainCars.add(trainCar);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sum of the total weight of all the train cars in the train. There is no need to
|
||||
* take the weight of the locomotive into account
|
||||
*
|
||||
* @see TrainTest#testTotalTrainWeight()
|
||||
*/
|
||||
public int getTotalWeight() {
|
||||
return trainCars.stream()
|
||||
.mapToInt(car -> car.getTotalWeight())
|
||||
.sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return similar to {@link PassengerCar#getPassengerCount()}, but for the entire train
|
||||
*
|
||||
* @see TrainTest#testPassengerCount()
|
||||
*/
|
||||
public int getPassengerCount() {
|
||||
return trainCars.stream()
|
||||
.filter(car -> car instanceof PassengerCar)
|
||||
.map(car -> (PassengerCar) car)
|
||||
.mapToInt(car -> car.getPassengerCount())
|
||||
.sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return similar to {@link CargoCar#getCargoWeight()}, but for the entire train
|
||||
*
|
||||
* @see TrainTest#testCargoWeight()
|
||||
*/
|
||||
public int getCargoWeight() {
|
||||
return trainCars.stream()
|
||||
.filter(car -> car instanceof CargoCar)
|
||||
.map(car -> (CargoCar) car)
|
||||
.mapToInt(car -> car.getCargoWeight())
|
||||
.sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string representation of the train. The string should consist of the
|
||||
* {@link #toString()}s of all train cars in the train
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return trainCars.stream()
|
||||
.map(car -> car.toString())
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
// TODO: Write a main method to test the class
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
74
src/main/java/oving7/train/TrainCar.java
Normal file
74
src/main/java/oving7/train/TrainCar.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package oving7.train;
|
||||
|
||||
/**
|
||||
* The class {@code TrainCar} represents a simple and general train car.
|
||||
*/
|
||||
public class TrainCar {
|
||||
|
||||
private int deadWeight;
|
||||
|
||||
/**
|
||||
* Constructor for a train car.
|
||||
*
|
||||
* @param deadWeight the weight of an empty train car
|
||||
* @throws IllegalArgumentException if deadWeight is negative
|
||||
*
|
||||
* @see TrainCarTest#testDeadWeight()
|
||||
*/
|
||||
public TrainCar(int deadWeight) {
|
||||
if (deadWeight < 0) {
|
||||
throw new IllegalArgumentException("dead weight cannot be less than zero");
|
||||
}
|
||||
this.deadWeight = deadWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param deadWeight the weight of an empty train car. In other words, the weight of only the
|
||||
* carriage, without passengers and cargo
|
||||
* @throws IllegalArgumentException if deadWeight is negative
|
||||
*
|
||||
* @see TrainCarTest#testDeadWeight()
|
||||
*/
|
||||
public void setDeadWeight(int deadWeight) {
|
||||
if (deadWeight < 0) {
|
||||
throw new IllegalArgumentException("dead weight cannot be less than zero");
|
||||
}
|
||||
this.deadWeight = deadWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the weight of an empty train car. In other words, the weight of only the carriage,
|
||||
* without passengers and cargo
|
||||
*
|
||||
* @see TrainCarTest#testDeadWeight()
|
||||
*/
|
||||
public int getDeadWeight() {
|
||||
return deadWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the total weight of the train car. Note that this method should also be callable on
|
||||
* subclasses and still return the total weight of the train car (keyword:
|
||||
* redefinition).
|
||||
*
|
||||
* @see TrainCarTest#testDeadWeight()
|
||||
*/
|
||||
public int getTotalWeight() {
|
||||
return deadWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string representation of the train car. The string should contain the type of the
|
||||
* train car and the total weight of the train car. For {@link PassengerCar}, the number
|
||||
* of passengers should also be included. For {@link CargoCar}, the weight of the cargo
|
||||
* should also be included.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TrainCar";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user