---
# System prepended metadata

title: Wardrobe prosjekt

---

[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.stud.ntnu.no/#https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146)

# Wardrobe prosjekt
Prosjektet er et utviklingsprosjekt i faget IT1901.

I dette prosjektet utvikler vi en app som forestiller en gardrobe hvor en bruker har mulighet til å legge til plagg etter eget ønske. Hensikten med prosjektet er at brukeren skal få oversikt over eget klesskap for å kunne planlegge antrekk på en enkel måte.

## Bygging og kjøring av prosjektet

Dette prosjektet både bygges og kjøres ved bruk av maven.

For å bygge prosjektet, kjør `mvn install` i terminal fra rot-prosjektet (**wardrobe**-mappen). Dette vil kjøre alle tester og kvalitetssjekker. Merk at dette må gjøres for at prosjektet skal kunne kjøres.

Prosjektet må kjøres fra **ui**-modulen ved enten
```
$ mvn javafx:run -f ui/pom.xml
```
eller 

```
$ cd ui
$ mvn javafx:run
```

## Arbeidsrutiner 

### Milestones
For hver release har vi brukt milestones i GitLab for å organisere og spore issues og merge requests. 

### Issues
For bedre arbeidsflyt har vi for hver release brukt issues til å planlegge arbeid. Hvert issue har en beskrivelse av hva som er tenkt skal gjøres konkret for det issuet. Videre har vi opprettet branches ut ifra hvert enkelt issue. 

### Commit-meldinger 
For å opprettholde gode arbeidsrutiner valgte vi å sette en felles standard på formatet til commit-meldingene i relase 3. 

Tidligere var formatet på denne måten:

**Eksempel:** #21 Endret metode i Wardrobe

Vi valgte å endre dette formatet for å oppnå en mer beskrivende struktur på meldingene. Commit-meldingsformatet ble derfor endret til "type endringer i meldingen: hvilke endringer som hadde blitt gjort og (#hvilket issue)". 

**Eksempel:** Test: Lagde tester for LoginPageController (#35)

## Kodekvalitet
For å oppnå god kodekvalitet har vi benyttet oss av følgende verkøty:
- Checkstyle: for å de tekstmessige egenskapene i koden
- Spotbugs: for å oppdage typiske feil i koden
- Jacoco: for å samle inn informasjon og tekstdekningsgrad

## Arkitektur - wardrobe
Mappen i kodelageret som utgjør kodingsprosjektet ligger inne i mappen [wardrobe](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/tree/master/wardrobe). I wardrobe ligger mappene core, restapi og ui, som inneholder henholdsvis kjernelogikk, server og brukergrensesnitt.
Ved å skille kjernelogikken, REST-apiet og ui-et fra hverandre opprettholder vi en full tre-lags arkitektur. 

### Klassediagram for hele applikasjonen
Under vises et overordnet klassediagram for hele applikasjonen. Her mangler noen detaljer, slik som relasjon mellom WardrobeAppController og User. Mer detaljer om relasjonene kan sees i de mer spesifikke klassediagrammene som ligger i README-ene for de ulike modulene. 

Klassediagrammet er todelt fordi ApiCalls og REST-apiet bindes sammen av HTTP. 

```plantuml
class RestapiService {
	~WardrobePersistence wp
	-ArrayList<User> users
	-User user
	-ArrayList<User> stringToUser()
	+ArrayList<User> getAllUsers()
	+User getUser(String username)
	+Wardrobe getWardrobe(String username)
	+String createUser(User user)
	-int getUserIndex(String username)
	+String addWardrobeItem(WardrobeItem wardrobeItem, String username)
	+String removeWardrobeItem(String wardrobeItem, String username)
	+void autoSaveWardrobe(User user)
}

class RestapiController {
	- RestapiService service
	+ @GetMapping()
	+ @PostMapping()
	+ @PutMapping()
}

class User {
	-Wardrobe wardrobe
	-String username
	+User(String username)
	+User()
	+void setUsername(String username)
	+String getUsername()
	+void setWardrobe(Wardrobe wardrobe)
	+Wardrobe getWardrobe()
	+String toString()
} 
class Wardrobe {
	-List<WardrobeItem> wardrobe
	+Wardrobe(WardrobeItem[] items)
	+List<WardrobeItem> getWardobe()
	+int getSize()
	+String getWardrobeItem(WardrobeItem item)
	+void addWardrobeItem(WardrobeItem item)
	+void removeWardrobeItem(WardrobeItem item)
	+List<String> getWardrobeNames()
	+List<String> getWardrobeNames(String type)
	+List<String> getWardrobeType(String type)
} 
class WardrobeItem {
	-String name
	-String type
	-String color
	-{static}List<String> validTypes
	+WardrobeItem(String name, String type, String color)
	+boolean validType(String type)
	+String getName()
	+String getType()
	+String getColor()
	+void setColor(String color)
	+void setName(String name)
	+void setType(String type)
}

class LoginPageController {
	~TextField username
	~Text feedback
	~Button logIn
	+void run()
	-boolean checkValidUsername(String name)
}
class WardrobeAppController {
	-WardrobePersistence WP
	-User user
	-ApiCalls apicalls
	- OutfitPageController
	#void onLoad(String username)
	-String capitalize(String text)
	-void createItem()
	-Image getIconForType(String type)
	-void validUser()
	-Wardrobe getWardrobe()
	+void setUsername(String name)
	+String getUsername()
	+boolean setUser(String username)
	+User getUser()
	-void addItem()
	-void deleteItem()
	+void updateView(Wardrobe wr)
	-void onView(String type)
	-void onAllView()
	-void onDressView()
	-void onPantsView()
	-void onSweaterView()
	-void onTshirtView()
	-void onSkirtView()
	-void pressedButton(Button b)
	-void createComboboxTypes()
	-void setFacts()
	-void runOutfitPage()
}

class OutfitPageController {
	-User user
	-Wardrobe wardrobe
	-List<WardrobeItem> tops
	-List<WardrobeItem> bottoms
	#{static}void loadOutfitPage()
	+void setUser(User user)
	+void setWardrobe(Wardrobe wardrobe)
	+void setTopList()
	+void setBottomList()
	-Image getIconForType(String type)
	+User getUser()
	+Wardrobe getWardrobe()
	+List<WardrobeItem> getBottoms()
	+List<WardrobeItem> getTops()
	+void generateOutfit()
	+void setCombinationText()
	+void runWardrobeApp()
}

class ApiCalls  {
	-ObjectMapper mapper
	+ApiCalls()
	+List<User> getAllUsers()
	+User getSingleUser(String username)
	+User createUser(User user)
	+String addWardrobeItem(WardrobeItem item, String username)
	+String deleteWardrobeItem(WardrobeItem item, String username)
}

WardrobeAppController -- LoginPageController
WardrobeAppController -- OutfitPageController
RestapiService -- RestapiController
RestapiService -- User 
ApiCalls -- WardrobeAppController
User *-- "1" Wardrobe
Wardrobe *-- "*" WardrobeItem
```
(trykk på bildeikonet for å åpne diagrammet)

### core
core inneholder domenelogikken og datalagringen. For mer om core-modulen, se [core](wardrobe/core/README.md).


### restapi
restapi-modulen består av alle klassene som håndterer REST-apiet. Mer om REST-api under og i [restapi](wardrobe/restapi/README.md).

### ui
ui består av alle klassene som håndterer kommunikasjon mellom programmet og brukeren. For mer om ui-modulen, se [ui](wardrobe/ui/README.md).

## Oppsett

### Moduler
Maven-moduler er en måte å organisere prosjektet i flere delprosjekter/moduler, som hver vil produsere en artefakt. Med maven kan versjonene og avhengighetene i modulene kontrolleres mellom disse modulene. Java-moduler er en måte å kapsle inn disse klassene sterkt på. 

### Module-info
Maven kan ikke generere module-info.java-filer automatisk, og vi har derfor lagt inn dette i hver modul.


### Avhengigheter
I prosjektet har vi implementert Jackson-biblioteket for å gjennomføre fillagring med JSON. Vi har også brukt dependency-en Javafx, for å kunne bruke Java-bibliotekene for en visuell fremstilling av applikasjonen. 

I tillegg bruker vi JUnit-påbygget tesfx for å teste Javafx-baserte GUI, da i hovedsak WardrobeAppController. Vi benytter oss av de tre eksterne java-bibliotekene for å bruke TestFX. Vi bruker testfx-core versjon 4.0, hamcrest-all version 2.2.

Det er to tilnærminger til testing av kontrollerern, isolert testing og ende-til-ende-testing. Vi har valgt å bruke ende-til-ende-testing. Her simulerers brukerinput og effekten i brukergrensesnittet sjekkes. For eksempel sjekker vi at når brukeren trykker på "Sweaters", så blir listen med "Sweaters" valgt og synlig for bruker. 

Vi bruker testrammeverket JUnit for enhetstesting i java-klasser. Dette er for å teste at metodene i en klasse implementerer ønsket oppførsel og øke kvaliteten på koden.

### Gitpodifisering
Prosjektet utvikles i hovedsak i lokal IDE, men det skal alltid være mulig å anvende Gitpod. Dette ser vi til at er mulig ved å gjøre gitpod tilgjengelig direkte fra gitlab-repoet til prosjektet, både gjennom knapp i gitlab og en oppdatert link å følge fra denne README-filen.

### Byggetillegg 
Byggingen til prosjektet styres av maven og vi har derfor implementert ulike maven plugins.

### Maven
Prosjektet baserer seg på Maven som byggesystem. I første omgang er en enkel maven-implementasjon så lang vi valgte å gå, da dette var nytt for alle gruppens medlemmer. Dette er satt opp gjennom å først installere Maven, og deretter sette opp prosjektet etter en enkel modul-mal gitt av prosjektinstruktør.

### Fillagring med JSON
JSON er et åpent standard filformat med fordeling av data, som bruker lesbar tekst for lagring og overføring av data. JSON filer lagres med .json-forlengelse og krever mindre formatering enn for eksmpel XML. For å håndtere konvertering av string til .json og .json til string har vi brukt biblioteket Jackson.

Vi har anvendt JSON for lagring av Wardrobe som fil, og har gjennom dette implementert serialisering og deserialiseringsklasser som ligger inne ved core i en egen mappe [json](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/tree/master/wardrobe/core/src/main/java/wardrobe/json). Inne i [json](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/tree/master/wardrobe/core/src/main/java/wardrobe/json) finner vi [internal](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/tree/master/wardrobe/core/src/main/java/wardrobe/json/internal) mappe som inneholder alle serialiserings og deserialiseringsklassene, og [WardrobeModule](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/internal/WardrobeModule.java). Serialiserings og deserialiseringsklassene vi har er [UserSerializer](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/internal/UserSerializer.java), [UserDeserializer](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/internal/UserDeserializer.java), [WardrobeDeserializer](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/internal/WardrobeDeserializer.java), [WardrobeSerializer](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/internal/WardrobeSerializer.java), [WardrobeItemDeserializer](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/internal/WardrobeItemDeserializer.java) og [WardrobeItemSerializer](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/internal/WardrobeItemSerializer.java). I [json](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/tree/master/wardrobe/core/src/main/java/wardrobe/json) finner vi [WardrobePresistence](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/WardrobePersistence.java) som inneholder metoder for å kunne skrive og lese fra fil. 

Et Wardrobe-objekt med wardrobeItems er knyttet til et brukernavn. Vi har valgt å ikke gi hvert wardrobeItem i garderoben en unik ID, da vi ikke så det hensiktsmessig å ta høyde for duplikater. Dette er fordi en bruker kan ha flere like plagg. En bruker har et klesskap, Wardrobe, som er mulig å lagre og hente. Det er mulig å lagre flere brukere, men en bruker kan kun ha en Wardrobe. Lagringen vil fungere ved at flere brukere blir lagret i en fil som blir lagret i en final filsti [getPathforSaveFile](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/blob/master/wardrobe/core/src/main/java/wardrobe/json/WardrobePersistence.java/getPathforSaveFile). 

### REST-api
Applikasjonen benytter et REST-api som er bygget på Spring Boot. Et REST-api er et applikasjonsprogrammeringsgrensesnitt som tillater interaksjon med en RESTful webtjener (her: Spring Boot).

Spring Boot lar utviklere lage "stand-alone" applikasjoner som kjører på egen hånd, uten å måtte stole på en ekstern webserver ved å bygge inn en webserver under intialiseringsprosessen. REST-apiet er bygget rundt kjernelogikken i core gjennom å bruke metodene i klassene i denne moduelen.

REST-apiet er bygget inn i prosjektet i en egen [restapi](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/tree/master/wardrobe/restapi) modul. Serveren bruker maven for oppstart og kjøres ved å skrive inn følgende kommando i terminalen:
 
```
$ cd restapi
$ mvn spring-boot:run
```

For mer om REST-api; [release3](https://gitlab.stud.idi.ntnu.no/it1901/groups-2021/gr2146/gr2146/-/tree/master/docs/release3)

### Brukergrensesnitt
I designprosessen av brukergrensesnittet har vi lagt vekt på et simpelt og brukervennlig design. I utviklingsprosessen av applikasjonen har vi for hver release forbedret designet og kommet frem til et design som vi føler er tilfredstillene for applikasjonens funksjonaliteter. Vi har flere fxml filer og kontrollere som tilsammen utgjør brukergrensesnittet. Dette er for å unngå at kontrollerklassene blir for store og komplekse. 

### Testing
Det er satt opp tester for alle modulene. Kjernelogikken testes med JUnit-tester, restapi med integrasjonstester og enhetstester og ui-klassene ved TestFX og JUnit.
Testene kjøres med maven ved å  skrive inn kommandoen (`mvn test`) i terminalen i rett mappe (wardrobe.core, wardrobe.ui eller wardrobe.restapi). 

Gitpod er tregere enn lokal IDE på å skrive til applikasjon under testene. Dette gjør at den iblant kan gå videre til neste test før et felt er fylt ut, og dermed vil returnere feilmeldinger og feilkjøre testene. Vi har implementert ventefunksjoner for hver av testmetodene som skriver til applikasjonen, og dette skal hindre testen i å gå videre før den har fylt ut feltene korrekt. Om det allikevel skulle skje må man bare kjøre testene om igjen.

### Konfigurasjon for shippable product med jlink og jpackage

Under følger instruksjoner for å lage shippable product 

```
$ cd restapi

$ mvn clean package spring-boot:repackage

$ cd target

$java -jar restapi-0.0.1-SNAPSHOT.jar
```
Videre for å lage desktop applikasjon
```
$ cd ui

$ mvn clean compile javafx:jlink jpackage:jpackage
```

### Skjermbilde av prosjekt
![wardrobe](./docs/release2/images/mainpage.png)


