@startuml
'https://plantuml.com/class-diagram

enum Categorie
{
    ELECTRONIQUE,
    BAGAGES & SACS,
    EFFETS PERSONNELS, /' Clés, ...'/
    PAPIERS & DOCUMENTS OFFICIELS,
    PORTEFEUILLE & CB,
    DIVERS,
}

class Position
{
    - double longitude
    - double latitude
    + this(longitude : double, latitude : double): Position
}

interface Localisation
{
}

class LocalisationPrecise
{
    +this(position : Position): LocalisationPrecise
}

class LocalisationFloue
{
    +this(position : Position, rayon : double): LocalisationFloue
}

/' Ajouter un setUser() ????'/
interface BuilderObjet{
    +setLocalisation(localisation: Localisation): BuilderObjet
    +setCategorie(categorie: Categorie): BuilderObjet
    +setDescription(description: string): BuilderObjet
    +setIntitule(intitule: string): BuilderObjet
    +setDate(date: Date):BuilderObjet
}

class BuilderObjetPerdu{
    +setLocalisation(localisation: Localisation): BuilderObjet
    +setCategorie(categorie: Categorie): BuilderObjet
    +setDescription(description: string): BuilderObjet
    +setIntitule(intitule: string): BuilderObjet
    +setDate(date: Date):BuilderObjet

}

class BuilderObjetTrouve{
    +setLocalisation(localisation: Localisation): BuilderObjet
    +setCategorie(categorie: Categorie): BuilderObjet
    +setDescription(description: string): BuilderObjet
    +setIntitule(intitule: string): BuilderObjet
    +setDate(date: Date):BuilderObjet
}

class ObjetTrouve{
    +getDistance(localisationUser: LocalisationPrecise, localisationObjet: LocalisationPrecise): double
}

class ObjetPerdu{
    +getDistance(localisationUser: LocalisationPrecise, localisationObjet: LocalisationFloue): double
}

/' Director de patron builder '/
/' Client de patron state '/
/' Client créé un matcher ??? '/
class Utilisateur{
    -nom: string
    -email: string
    -password: string
    +this(nom: string, email: string, password: string): Utilisateur
    +createObjetTrouve(builder: BuilderObjet):
    +createObjetPerdu(builder: BuilderObjet):
}

class SCalculatorPrecis{
    -{static} instance: SCalculatorPrecis
    -this(): void
    +{static} getInstance(): SCalculatorPrecis
    +getDistance(localisationUser: LocalisationPrecise, localisationObjet: LocalisationPrecise): double
}

class SCalculatorFlou{
    -{static} instance: SCalculatorFlou
    -SCalculatorFlou()
    +{static} getInstance(): SCalculatorFlou
    +getDistance(localisationUser: LocalisationPrecise, localisationObjet: LocalisationFloue): double
}

/' SINGLETON ??? '/
class SRecherche{

}

/' Context du patron state '/
class Matcher{
    +setMatcher(matcher: Matcher): void
}

/' Interface ou abstract class?? '/
/' Qu'est ce qu'on fait dans les méthodes on set un boolean ??? '/
abstract class State{
    +this(matcher: Matcher): State
    +possible(valeur: boolean): void
    /' La méthode valide() supprime les objets perdus et trouvés concernés par le matching '/
    +valide(valeur: boolean): void
}

class Possible{
    +this(matcher: Matcher): Possible
    +possible(valeur: boolean): void
    +valide(valeur: boolean): void
}

class Valide{
    +this(matcher: Matcher): Valide
    +possible(valeur: boolean): void
    +valide(valeur: boolean): void
}

BuilderObjet <|.. BuilderObjetPerdu
BuilderObjet <|.. BuilderObjetTrouve
BuilderObjet <-- Utilisateur
ObjetTrouve <-- BuilderObjetTrouve
ObjetPerdu <-- BuilderObjetPerdu

BuilderObjetPerdu ..> Categorie
BuilderObjetTrouve ..> Categorie

BuilderObjetPerdu ..> Localisation
BuilderObjetTrouve ..> Localisation

ObjetPerdu --> SCalculatorFlou
ObjetTrouve --> SCalculatorPrecis

ObjetTrouve <-- SRecherche

Localisation <|.. LocalisationPrecise
Localisation <|.. LocalisationFloue

Position "1" <-- Localisation

Valide ..|> State
Possible ..|> State
Utilisateur ..> Valide
Utilisateur ..> Possible
Utilisateur --> Matcher
Matcher o--> State
Valide --> Matcher
Possible --> Matcher

@enduml