@startuml
top to bottom direction

class Application {
}

class AdministratorsManager {
  + addAdministrator(administrator: EntityAdministrator): void
  + removeAdministrator(administrator: EntityAdministrator): void
  + getAdministrators(): List<EntityAdministrator>
  + getAdministratorByUsername(username: string): EntityAdministrator
  + verifyAdministratorCredobsials(username: string, password: string): int
  + verifyAdministratorByName(nickname: string): int
  + setAdministratorPassword(username: string, newPassword: string): void
}

class QuestionsManager {
  + addQuestion(question: EntityQuestion): void
  + removeQuestion(question: EntityQuestion): void
  + getQuestions(): List<EntityQuestion>
  + getQuestionsByChapterAndDifficulty(chapter: int, difficulty: int): List<EntityQuestion>
  + removeQuestionById(id: int): void
  + getQuestionById(id: int): EntityQuestion
  + updateQuestion(id: int, questionDataArray: EntityQuestion): void
  + updateNbFails(question: EntityQuestion): void
  + updateDifficulty(question: EntityQuestion): void
}

class AnswersManager {
  + addAnswer(answer: Answer): int
  + removeAnswer(answer: Answer): void
  + getAnswers(): List<Answer>
  + getAnswersByIdQuestions(idQuestion: int): List<Answer>
  + updateAnswer(answersId: int, answer: Answer): void
  + removeAnswerById(id: int): void
}

class LobbiesManager {
  + addLobby(lobby: EntityLobby): void
  + removeLobby(lobby: EntityLobby): void
  + getLobbies(): List<EntityLobby>
  + getLobbyById(lobbyId: int): EntityLobby
  + verifyLobbyPassword(lobbyId: int, password: string): boolean
  + setLobbyPassword(lobbyId: int, newPassword: string): void
}

class PlayersManager {
  + addPlayer(player: EntityPlayer): void
  + removePlayer(player: EntityPlayer): void
  + getPlayers(): List<EntityPlayer>
  + getPlayerById(playerId: int): EntityPlayer
  + getPlayerByNickname(nickname: string): EntityPlayer
  + getPlayersInLobby(lobbyId: int): List<EntityPlayer>
  + getPlayersMaxScore(playerId: int): int
  + verifyPlayerCredentials(nickname: string, password: string): int
  + verifyPlayerByName(nickname: string): int
  + setPlayerPassword(playerId: int, newPassword: string): void
}



class Lobbies <<Serializable>> {
  + addLobby(lobby : Lobby )
  + removeLobby(lobby : Lobby )
  + getLobbies(): List<Lobby>
}

class Lobby {
  - id: int
  - name: string
  - password: string
  - nbPlayers: int

  + getId(): int
  + getName(): string
  + getNbPlayers(): int
  + setNbPlayers(nbPlayers: int): void
}

Lobbies *-- Lobby : lobbies 

class Answers <<Serializable>> {
  + addAnswer(answer: Answer)
  + removeAnswer(answer: Answer)
  + getAnswers(): List<Answer>
}

class Answer {
  - id: int
  - content: string
  - idQuestion: int

  + Answer(id: int, content: string, idQuestion: int)
  + getId(): int
  + getContent()
  + getIdQuestion()
  + setContent(content: string): void
}

Answers *-- Answer : answers

class Administrators <<Serializable>> {
  + addAdministrator(administrator: Administrator)
  + removeAdministrator(administrator: Administrator)
  + getAdministrators(): List<Administrator>
}

class Administrator {
  - id: int
  - username: string
  - hashedPassword: string

  + Administrator(id: int, username: string, password: string)
  + getId(): int
  + getUsername()
  + getHashedPassword()
  + setHashedPassword(hashedPassword: string): void
}

Administrators *-- Administrator : administrators

class Questions <<Serializable>> {
  + addQuestion(question: Question)
  + removeQuestion(question: Question)
  + getQuestions(): List<Question>
}

class Question {
  - id: int
  - content: string
  - idChapter: int
  - idAnswerGood: int
  - difficulty: int
  - nbFails: int

  + Question(id: int, content: string, idChapter: int, idAnswerGood: int = -1, difficulty: int = 1, nbFails: int = 0)
  + getId(): int
  + getContent(): string
  + getIdChapter(): int
  + getIdAnswerGood(): int
  + getDifficulty(): int
  + getNbFails(): int
  + setContent(content: string): void
  + setIdAnswerGood(idAnswerGood: int): void
  + setDifficulty(difficulty: int): void
  + setNbFails(nbFails: int): void
}

Questions *-- Question : questions

class Chapters <<Serializable>> {
  + addChapter(chapter: Chapter)
  + removeChapter(chapter: Chapter)
  + getChapters(): List<Chapter>
}

class Chapter {
  - id: int
  - name: string

  + Chapter(id: int, name: string)
  + getId()
  + getName()
  + setName(name: string): void
}

Chapters *-- Chapter : chapters

class Players <<Serializable>> {
  + addPlayer(player: Player)
  + removePlayer(player: Player)
  + getPlayers(): List<Player>
}

class Player {
  - id: int
  - nickname: string
  - hashedPassword: string

  + Player(id: int, nickname: string, password: string)
  + getId(): int
  + getNickname(): string
  + getHashedPassword(): string
  + setHashedPassword(hashedPassword: string): void
}

Players *-- Player : players

entity EntityAnswer {
  - id: int
  - content: string
  - idQuestion: int
}

entity EntityLobby {
  - id: int
  - name: string
  - password: string
  - nbPlayers: int
  - idPlayerCreator: int
}

entity EntityAdministrator {
  - id: int
  - username: string
  - password: string
}

entity EntityQuestion {
  - id: int
  - content: string
  - difficulty: int
  - nbfails: int
  - idChapter: int
  - idAnswerGood: int
}

entity EntityChapter {
  - id: int
  - name: string
}

entity EntityPlayer {
  - id: int
  - nickname: string
  - password: string
}
class GatewayPlayer {
  + addPlayer(player: EntityPlayer)
  + removePlayer(player: EntityPlayer)
  + getPlayers(): List<EntityPlayer>
  + getPlayerById(playerId: int): EntityPlayer
  + getPlayerByNickname(nickname: string): EntityPlayer
  + getPlayersInLobby(lobbyId: int): List<EntityPlayer>
  + getPlayersMaxScore(playerId: int): int
  + verifyPlayerCredentials(nickname: string, password: string): int
  + verifyPlayerByName(nickname: string): int
  + setPlayerPassword(playerId: int, newPassword: string): void
}

class GatewayLobby {
  + addLobby(lobby: EntityLobby)
  + removeLobby(lobby: EntityLobby)
  + getLobbies(): List<EntityLobby>
  + getLobbyById(lobbyId: int): EntityLobby
  + verifyLobbyPassword(lobbyId: int, password: string): boolean
  + setLobbyPassword(lobbyId: int, newPassword: string): void
}

class GatewayChapter {
  + addChapter(chapter: EntityChapter)
  + removeChapter(chapter: EntityChapter)
  + getChapters(): List<EntityChapter>
  + getChapterById(chapterId: int): EntityChapter
}

class GatewayAnswer {
  + addAnswer(answer: Answer): int
  + getAnswerByID(id: int): Answer
  + getAnswersByIDQuestions(idQuestion: int): List<Answer>
  + updateAnswer(answersId: int, answer: Answer): void
  + removeAnswerByID(id: int): void
}

class GatewayQuestion {
  + getQuestions(): List<Question>
  + getQuestionsByChapterAndDifficulty(chapter: int, difficulty: int): List<Question>
  + removeQuestionByID(id: int): void
  + addQuestion(questionsDataArray: List<Question>): int
  + getQuestionByID(id: int): Question
  + updateQuestion(id: int, questionDataArray: Question): void
  + updateNbFails(question: Question): void
  + updateDifficulty(question: Question): void
}

class GatewayAdministrator {
  + addAdministrator(administrator: EntityAdministrator)
  + removeAdministrator(administrator: EntityAdministrator)
  + getAdministrators(): List<EntityAdministrator>
  + getAdministratorByUsername(username: string): EntityAdministrator
  + verifyAdministratorCredentials(username: string, password: string): int
  + verifyAdministratorByName(nickname: string): int
  + setAdministratorPassword(username: string, newPassword: string): void
}

Application --> AdministratorsManager : administratorsManager
Application --> QuestionsManager : questionsManager
Application --> AnswersManager : answersManager
Application --> LobbiesManager : lobbiesManager
Application --> PlayersManager : playersManager
Application --> ChaptersManager : chaptersManager

AdministratorsManager --> Administrators : administrators
QuestionsManager --> Questions : questions
AnswersManager --> Answers : answers
LobbiesManager --> Lobbies : lobbies
PlayersManager --> Players : players
ChaptersManager --> Chapters : chapters

AdministratorsManager -[dotted]-> Administrator
QuestionsManager -[dotted]-> Question
AnswersManager -[dotted]-> Answer
LobbiesManager -[dotted]-> Lobby
PlayersManager -[dotted]-> Player
ChaptersManager -[dotted]-> Chapter

AdministratorsManager --> EntityAdministrator : entAdministrator
QuestionsManager --> EntityQuestion : entQuestion
AnswersManager --> EntityAnswer : entAnswer
LobbiesManager --> EntityLobby : entLobby
PlayersManager --> EntityPlayer : entPlayer
ChaptersManager --> EntityChapter : entChapter

EntityAdministrator <-[dotted]- GatewayAdministrator
EntityQuestion <-[dotted]- GatewayQuestion
EntityAnswer <-[dotted]- GatewayAnswer
EntityLobby <-[dotted]- GatewayLobby
EntityPlayer <-[dotted]- GatewayPlayer
EntityChapter <-[dotted]- GatewayChapter

GatewayAdministrator <- AdministratorsObserver : gatewayAdministrator
GatewayAnswer <- AnswersObserver : gatewayAnswer
GatewayChapter <- ChaptersObserver : gatewayChapter
GatewayLobby <- LobbiesObserver : gatewayLobby
GatewayPlayer <- PlayersObserver : gatewayPlayer
GatewayQuestion <- QuestionsObserver : gatewayQuestion

AdministratorsManager --> AdministratorsObserver : obsAdministrator
QuestionsManager --> QuestionsObserver : obsQuestion
AnswersManager --> AnswersObserver : obsAnswer
LobbiesManager --> LobbiesObserver : obsLobby
PlayersManager --> PlayersObserver : obsPlayer
ChaptersManager --> ChaptersObserver : obsChapter

AnswersObserver -> Answers : subjectAnswers
LobbiesObserver -> Lobbies : subjectLobbies
PlayersObserver -> Players : subjectPlayers
ChaptersObserver -> Chapters : subjectChapters
QuestionsObserver -> Questions : subjectQuestions
AdministratorsObserver -> Administrators : subjectAdministrators

class AnswersObserver{
  +update()
}
class LobbiesObserver{
  +update()
}
class PlayersObserver{
  +update()
}
class ChaptersObserver{
  +update()
}
class QuestionsObserver{
  +update()
}
class AdministratorsObserver{
  +update()
}
@enduml