@startuml parisportif5

'plantuml
'Relations :
    User --|> Account
    BetCategory "1" <-- "0..*" Bet
    User "1" -- "0..*" Bet
    BetCategory "0..*" --> "1" AbstractSport
    AbstractSport "1..*" <--* "0..*" Competition
    Country "1..*" <--* "0..*" Competition
    Competition "1" o-- "0..*" Event
    Event "1" o-- "0..*" Run
    Run "1" -- "1" Location
    Team "1" o-- "0..*" AbstractScore
    Run "1" *--> "1..*" Team
    Team "1" *-- "1..*" Member
    Country "1" <-- "0..1" Team
    Competition "0..1" o--> "0..*" Team
    Event "0..1" o--> "0..*" Team
    AbstractSport "0..1" --> "1" Country
    Team "0..*" --> "1" AbstractSport
    Member "0..*" *--> "1..*" AbstractSport
    Member "0..*" *--> "1..*" Country
    Location "0..*" --> "1" Country
    User "1" -- "0..*" Billing
    BetTargetInterface <|.. Competition
    BetTargetInterface <|.. Event
    BetTargetInterface <|.. Run
    BetTargetInterface <|.. Team
    BetTargetInterface <|.. Member
    PointScoreInterface <|.. PointScore
    TimeScoreInterface <|.. TimeScore
    TimeScore --|> AbstractScore
    PointScore --|> AbstractScore
    TimeScore ..|> ScoreInterface
    PointScore ..|> ScoreInterface
    Football ..|> SportInterface
    Football ..|> SportInterface
    Handball ..|> SportInterface
    Tennis ..|> SportInterface
    FormulaOne  ..|> SportInterface
    TableTennis ..|> SportInterface
    Football --|> AbstractSport
    Handball --|> AbstractSport
    Tennis --|> AbstractSport
    FormulaOne --|> AbstractSport
    TableTennis --|> AbstractSport
    Football ..|> CollectiveSportInterface
    Handball ..|> CollectiveSportInterface
    Tennis ..|> IndividualSportInterface
    FormulaOne  ..|> IndividualSportInterface
    TableTennis ..|> CollectiveSportInterface
    TableTennis ..|> IndividualSportInterface
'Définitions des classes :
    'interface de généralisation pour les classes autorisé à être parié
    interface BetTargetInterface {
        +getOdds() : float
    }
    'Compte (sert à ce connecter)
    class Account {
        -identifier : int
        -validation : bool
        -password : string
        -emailAddress : string
        -status : bool
        +isValidate() : bool
    }
    'Utilisateur avec un compte
    class User {
        -identifier : int
        -name : string
        -lastName : string
        -billingAddress : string
        -billingPostCode : string
        -billingCountry : string
        -birthDate : DateTime
        -wallet : float
        -cart : Bet[*]
        -billings : Billing[*]
        -betList : Bet[*]
    }
    note left : Possible propriété mobile pour notification
    'Factures (type=débit ou crédit)
    class Billing {
        -identifier : int
        -orderNumber  : int
        -amount : float
        -currency : string
        -user : User
        -type : int
    }
    'Historique des factures (type=débit ou crédit)
    class BillingHistory {
        -identifier : int
        -name : string
        -lastName : string
        -billingAddress : string
        -billingPostCode : string
        -billingCountry : string
        -orderNumber  : int
        -amount : float
        -currency : string
        -type : int
    }
    'Un paris
    class Bet {
        -identifier : int
        -amount : float
        -state : BetState
        -user : User
        -category : BetCategory
        -odds : float
        -items : BetTargetInterface
    }
    'Catégorie de paris (ex: Paris sur la victoire du favoris)
    class BetCategory {
        -identifier : int
        -name : string
        -description : string
        -sport : SportInterface
    }
    'Lieu de la rencontre/course
    class Location {
        -identifier : int
        -place : string
        -timezoneLocal : DateTimeZone
        -country : Country
        -run : Run
    }
    'Sport pratiqué (runtype = fixture, race)
    abstract class AbstractSport {
        #identifier : int
        #name : string
        #numberOfCompetitor : int
        #runType : string
        #country : Country
    }
    'interface de généralisation pour un Sport
    interface SportInterface {
        +getClassName() : string
        +isIndividual() : bool
        +isCollective() : bool
    }
    'interface pour différencier sport individuel
    interface IndividualSportInterface
    'interface pour différencier sport collectif
    interface CollectiveSportInterface
    'Liste de sports
    class Football {
        +getClassName() : string
        +isIndividual() : bool
        +isCollective() : bool
    }
    class Handball {
        +getClassName() : string
        +isIndividual() : bool
        +isCollective() : bool
    }
    class Tennis {
        +getClassName() : string
        +isIndividual() : bool
        +isCollective() : bool
    }
    class FormulaOne {
        +getClassName() : string
        +isIndividual() : bool
        +isCollective() : bool
    }
    class TableTennis {
        +getClassName() : string
        +isIndividual() : bool
        +isCollective() : bool
    }
    'Pays du lieu de la rencontre/course
    class Country {
        -identifier : int
        -name : string
        -TimeZones : DateTimeZone[*]
        +getDefaultTimeZone() : DateTimeZone
        +getTimeZone(in string timezone) : DateTimeZone
    }
    'Compétition (JO, Ligue des Champions, F1 Championnat du monde)
    class Competition {
        -identifier : int
        -name : string
        -startDate : DateTime
        -endDate : DateTime
        -odds : float
        -sports : Sport[*]
        -teams : Team[*]
        -events : Event[*]
        -countries : Country[*]
        -winner : Team
        +getOdds() : float
    }
    'Événement de la compétition (poul de qualification, Circuit F1 de france)
    class Event {
        -identifier : int
        -name : string
        -startDate : DateTime
        -endDate : DateTime
        -odds : float
        -competition : Competition
        -teams : Team[*]
        -runs : Run[*]
        +getOdds() : float
    }
    'Classe mère global : Un match, une rencontre, une course
    class Run {
        -identifier : int
        -name : string
        -startDate : DateTime
        -endDate : DateTime
        -odds : float
        -location : Location
        -event : Event
        -teams : Team[*]
        -result : Team|null
        +getOdds() : float
    }
    note left of Run
    Extension possible en plus de Team : "Competitor".
    Futur amélioration possible de Result en un classement.
    end note
    'interface pour Score en temps
    interface TimeScoreInterface {
        +getTime() : float
    }
    'interface pour Score en points
    interface PointScoreInterface {
        +getPoint() : int
    }
    'interface de généralisation pour un Score
    interface ScoreInterface {
        +getScore() : float
    }
    'Score de l'équipe ou du membre de l'équipe
    abstract class AbstractScore {
        #identifier : int
        #type : string
        #team : Team
    }
    'Score en temps
    class TimeScore {
        #value : float
        +getTime() : float
        +getScore() : float
    }
    'Score en points
    class PointScore {
        #value : int
        +getPoint() : int
        +getScore() : float
    }
    'Joueur ou sportif ou pilote
    class Member {
        -identifier : int
        -name : string
        -firstName : string
        -status : MemberStatus
        -result : ResultType
        -role : MemberRole
        -odds : float
        -team : Team
        -sports : Sport[*]
        -teams : Team[*]
        -countries : Country[*]
        +getOdds() : float
    }
    'Équipes qui participe à une rencontre, à une course
    class Team {
        -identifier : int
        -name : string
        -odds : float
        -country : Country
        -sport : Sport
        -result : ResultType
        -scores : ScoreInterface[*]
        -members : Member[*]
        +getOdds() : float
    }
    note right: Peut implémenter une interface ContestantInterface

@enduml
