Files
Cites_Plugins/docs/diagrams/features/team/team-class-diagram.puml
T
Antone Barbaud b02e532563 docs: organize diagrams to mirror code layout (util/ + features/)
Move flat docs/diagrams/*.puml into a hierarchy matching the source
package structure:

  docs/diagrams/
  ├── bootstrap-sequence.puml         (cross-cutting)
  ├── events-diagram.puml             (cross-feature)
  ├── util/
  │   ├── command-class-diagram.puml
  │   ├── database-diagram.puml
  │   ├── messages-class-diagram.puml
  │   ├── broadcasts-class-diagram.puml
  │   └── gui-class-diagram.puml
  └── features/
      ├── team/
      │   ├── team-class-diagram.puml
      │   ├── team-config-class-diagram.puml
      │   ├── builtin-commands-diagram.puml
      │   ├── team-create-sequence.puml
      │   ├── team-create-activity.puml
      │   └── team-join-sequence.puml
      ├── player/
      │   └── player-class-diagram.puml
      └── moderation/
          └── moderation-class-diagram.puml

README.md diagram index split into 4 sections (overview, util,
features/team, features/player, features/moderation) for readability;
all links updated. features.md auto-updated by sed for the new paths.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 13:58:48 +02:00

252 lines
6.4 KiB
Plaintext

@startuml team-class-diagram
title CR-Core — Team domain (class diagram)
skinparam classAttributeIconSize 0
hide empty members
' === Common abstractions ===
package "fr.luc.crcore.util.common" {
interface Identifiable {
+ getId(): UUID
}
interface Named {
+ getName(): String
}
interface ScoreHolder {
+ getScore(name): int
+ hasScore(name): boolean
+ getScores(): Map<String, Integer>
+ getTotalScore(): int
+ addScore(name, delta): int
+ setScore(name, value): int
+ resetScore(name): boolean
+ resetAllScores(): void
}
abstract class AbstractEntity {
- id: UUID
+ AbstractEntity(id: UUID)
+ getId(): UUID
+ equals(o: Object): boolean
+ hashCode(): int
}
interface "Repository<T extends Identifiable>" as Repository {
+ save(entity: T): T
+ findById(id: UUID): Optional<T>
+ findAll(): Collection<T>
+ delete(id: UUID): boolean
}
AbstractEntity ..|> Identifiable
}
' === Team domain ===
package "fr.luc.crcore.features.team" {
enum TeamRole {
LEADER
MEMBER
--
+ isLeader(): boolean
}
enum TeamVisibility {
PUBLIC
PRIVATE
--
+ isPublic(): boolean
+ isPrivate(): boolean
}
enum TeamColor {
RED
BLUE
GREEN
YELLOW
AQUA
LIGHT_PURPLE
GOLD
WHITE
BLACK
DARK_BLUE
DARK_GREEN
DARK_AQUA
DARK_RED
DARK_PURPLE
DARK_GRAY
GRAY
--
+ getChatColor(): ChatColor
+ getDyeColor(): DyeColor
+ getDisplayName(): String
}
class TeamMember {
- role: TeamRole
- joinedAt: Instant
+ getPlayerId(): UUID
+ getRole(): TeamRole
+ getJoinedAt(): Instant
+ isLeader(): boolean
+ withRole(role: TeamRole): TeamMember
}
class Team {
- name: String
- tag: String
- color: TeamColor
- leaderId: UUID *(nullable)*
- visibility: TeamVisibility
- members: Set<TeamMember>
- scores: Map<String, Integer>
- spawnPoint: Location
--
+ Team(id, name, tag, color) ' leaderless, PRIVATE
+ Team(id, name, tag, color, visibility) ' leaderless
+ Team(id, name, tag, color, leaderId) ' with leader, PRIVATE
+ Team(id, name, tag, color, leaderId, visibility)
--
+ getName(): String
+ getTag(): String
+ getColor(): TeamColor
+ getLeaderId(): Optional<UUID>
+ getLeader(): Optional<TeamMember>
+ hasLeader(): boolean
+ isLeader(playerId): boolean
+ getVisibility(): TeamVisibility
+ setVisibility(v): void
+ isPublic(): boolean
+ getMembers(): Set<TeamMember>
+ getMember(playerId): Optional<TeamMember>
+ hasMember(playerId): boolean
+ size(): int
+ addMember(playerId): TeamMember
+ removeMember(playerId): boolean
+ transferLeadership(newLeaderId): void ' strict: chef→chef
+ setLeader(newLeaderId): void ' permissive: assign
--
+ getScore(name): int
+ hasScore(name): boolean
+ getScores(): Map<String, Integer>
+ getTotalScore(): int
+ addScore(name, delta): int
+ setScore(name, value): int
+ resetScore(name): boolean
+ resetAllScores(): void
--
+ getSpawnPoint(): Optional<Location>
+ hasSpawnPoint(): boolean
+ setSpawnPoint(loc): void
+ clearSpawnPoint(): void
--
# newMember(playerId, role): TeamMember
}
class TeamRanking <<record>> {
+ rank: int
+ team: Team
+ score: int
}
interface TeamRepository {
+ findByName(name: String): Optional<Team>
+ findByTag(tag: String): Optional<Team>
+ findByMember(playerId: UUID): Optional<Team>
}
class InMemoryTeamRepository {
- teams: Map<UUID, Team>
}
interface TeamService {
+ createTeam(name, tag, color): Team ' leaderless, PRIVATE
+ createTeam(name, tag, color, visibility): Team ' leaderless
+ createTeam(name, tag, color, leaderId): Team
+ createTeam(name, tag, color, leaderId, visibility): Team
+ dissolveTeam(teamId): boolean
+ addMember(teamId, playerId): boolean
+ removeMember(teamId, playerId): boolean
+ joinTeam(teamId, playerId): boolean
+ transferLeadership(teamId, newLeaderId): boolean ' strict: chef→chef
+ setLeader(teamId, newLeaderId): boolean ' permissive (admin)
+ setVisibility(teamId, visibility): void
--
+ addScore(teamId, name, delta): int
+ setScore(teamId, name, value): int
+ getScore(teamId, name): int
+ resetScore(teamId, name): boolean
+ resetAllScores(teamId): void
--
+ getRankingByScore(name): List<TeamRanking>
+ getGlobalRanking(): List<TeamRanking>
+ getTopRankingByScore(name, limit): List<TeamRanking>
+ getTopGlobalRanking(limit): List<TeamRanking>
--
+ setSpawnPoint(teamId, loc): void
+ clearSpawnPoint(teamId): void
+ getSpawnPoint(teamId): Optional<Location>
--
+ getTeam / getTeamByName / getTeamByTag / getTeamOfPlayer
+ getAllTeams(): Collection<Team>
}
class TeamServiceImpl {
- repository: TeamRepository
--
# newTeam(...): Team
# newRanking(rank, team, score): TeamRanking
# rank(scoreFn): List<TeamRanking>
--
# validateName(name): void
# validateTag(tag): void
# validateLeader(leaderId): void
# validateJoinable(team, playerId): void
--
# onBeforeSave(team): void
# onAfterCreate(team): void
# onBeforeDissolve(team): void
# onAfterDissolve(team): void
# onMemberAdded(team, member): void
# onMemberRemoved(team, playerId): void
# onPlayerJoined(team, member): void
# onLeadershipTransferred(team, oldId, newId): void
# onVisibilityChanged(team, oldV, newV): void
# onScoreChanged(team, name, oldV, newV): void
# onSpawnPointChanged(team, oldLoc, newLoc): void
}
class TeamException
class TeamAlreadyExistsException
class TeamNotFoundException
class TeamAccessException
TeamMember --|> AbstractEntity
Team --|> AbstractEntity
Team ..|> Named
Team ..|> ScoreHolder
TeamRepository --|> Repository
InMemoryTeamRepository ..|> TeamRepository
TeamServiceImpl ..|> TeamService
Team "1" o-- "1..*" TeamMember : members
Team --> TeamColor : color
Team --> TeamVisibility : visibility
TeamMember --> TeamRole : role
TeamRanking --> Team
TeamServiceImpl o--> TeamRepository
TeamService ..> TeamRanking : produces
TeamException --|> RuntimeException
TeamAlreadyExistsException --|> TeamException
TeamNotFoundException --|> TeamException
TeamAccessException --|> TeamException
}
@enduml