This document describes the data architecture of the Team RoboGo project, including database entity models, API data transfer objects (DTOs), and their relationships.
- Table:
competition - Description: Represents a competition event
- Fields:
id(Long): Primary keyinternal_id(UUID): Internal unique identifiername(String): Competition name
- Relationships:
- One-to-Many:
SlideDeck(slideDecks) - One-to-Many:
Category(categories)
- One-to-Many:
- Table:
slide_deck - Description: Represents a group of slides for display on screens
- Fields:
id(Long): Primary keyname(String): Slide deck nametransition_time(int): Slide transition time (milliseconds)version(int): Version number for synchronizationlast_update(LocalDateTime): Last update time for multi-screen synchronizationcompetition_id(Long): Foreign key, references competition
- Relationships:
- Many-to-One:
Competition(competition) - One-to-Many:
Slide(slides)
- Many-to-One:
- Table:
slide - Description: Abstract base class for slides, using single table inheritance strategy
- Fields:
id(Long): Primary keyname(String): Slide nameindex(Integer): Index position in slide deckslidedeck_id(Long): Foreign key, references slide decktype(String): Discriminator field, identifies slide type
- Inheritance Types:
IMAGE: ImageSlideSCORE: ScoreSlide
- Inherits from:
Slide - Description: Slide for displaying images
- Fields:
image_id(Long): Foreign key, references image metadata
- Relationships:
- Many-to-One:
SlideImageMeta(imageMeta)
- Many-to-One:
- Inherits from:
Slide - Description: Slide for displaying team scores
- Fields:
category_id(Long): Foreign key, references category
- Relationships:
- Many-to-One:
Category(category)
- Many-to-One:
- Table:
category - Description: Team categories
- Fields:
id(Long): Primary keyname(String): Category namecompetition_id(Long): Foreign key, references competition
- Relationships:
- Many-to-One:
Competition(competition) - One-to-Many:
Team(teams)
- Many-to-One:
- Table:
team - Description: Participating teams
- Fields:
id(Long): Primary keyname(String): Team namecategory_id(Long): Foreign key, references category
- Relationships:
- Many-to-One:
Category(category) - One-to-One:
Score(score)
- Many-to-One:
- Table:
score - Description: Team score records
- Fields:
id(Long): Primary keypoints(double): Score pointstime(int): Completion time (seconds)team_id(Long): Foreign key, references team
- Relationships:
- One-to-One:
Team(team)
- One-to-One:
- Table:
screen - Description: Display screens
- Fields:
id(Long): Primary keyname(String): Screen namestatus(ScreenStatus): Screen status enumslide_deck_id(Long): Foreign key, references slide deck
- Relationships:
- Many-to-One:
SlideDeck(slideDeck)
- Many-to-One:
- Table:
slide_image_meta - Description: Image file metadata information
- Fields:
id(Long): Primary keyname(String): Image namecontent_type(String): Content type (MIME)
- Relationships:
- One-to-One:
SlideImageContent(content)
- One-to-One:
- Table:
slide_image_content - Description: Binary content of image files
- Fields:
id(Long): Primary keycontent(byte[]): Image binary dataimage_id(Long): Foreign key, references image metadata
- Relationships:
- One-to-One:
SlideImageMeta(meta)
- One-to-One:
- Table:
users - Description: System users
- Fields:
id(Long): Primary keyusername(String): Username (unique)password(String): Password
IMAGE: Image slidesSCORE: Score slides
- Screen status enum (specific values need to be checked in code)
{
"id": Long,
"name": String,
"transitionTime": int,
"version": int,
"competitionId": Long,
"slides": List<SlideDTO>,
"lastUpdate": LocalDateTime
}{
"id": Long,
"name": String,
"index": int,
"type": String // "IMAGE" or "SCORE"
}{
"id": Long,
"name": String,
"index": int,
"type": "IMAGE",
"imageMeta": ImageSlideMetaDTO
}{
"id": Long,
"name": String,
"index": int,
"type": "SCORE",
"category": CategoryDTO
}{
"id": Long,
"name": String
}{
"id": Long,
"name": String
}{
"id": Long,
"points": double,
"time": int
}{
"id": Long,
"name": String,
"contentType": String
}{
"id": Long,
"name": String
}{
"username": String,
"password": String
}{
"token": String,
"user": UserDTO
}{
"id": Long,
"username": String
}{
"valid": boolean,
"user": UserDTO
}{
"slideDeckId": Long,
"version": int
}{
"slideDeck": SlideDeckDTO,
"hasChanges": boolean
}The following diagram shows the complete data model relationships:
Competition (1) ──── (N) SlideDeck (1) ──── (N) Slide
│ │
│ │
│ (1) ──── (N) Category (1) ──── (N) Team (1) ──── (1) Score
│
└─── (1) ──── (N) Screen (N) ──── (1) SlideDeck
SlideImageMeta (1) ──── (1) SlideImageContent
│
└─── (1) ──── (N) ImageSlide
Slideuses single table inheritance strategy, distinguished bytypefield- Supports
IMAGEandSCOREslide types
SlideDeckusesversionfield for version controllastUpdatefield for multi-screen synchronization- Clients can determine if reload is needed by comparing versions
Real-time Synchronization Design: The version control system enables real-time synchronization across all frontend screens:
- Polling Mechanism: Frontend screens periodically poll the backend with their current version
- Change Detection: Backend compares client version with server version
- Efficient Updates: Only sends data when changes are detected, reducing network traffic
- Multi-screen Sync: All screens automatically stay synchronized without manual intervention
- Conflict Prevention: Optimistic locking prevents concurrent update conflicts
Sync Flow:
Frontend → Poll with version → Backend → Compare versions → Return changes if needed → Update all screens
This design ensures that all display screens show the same content simultaneously while minimizing resource usage.
- Image metadata and content are stored separately
SlideImageMetastores metadata informationSlideImageContentstores binary content- Supports different content types (MIME)
- Each team corresponds to one score record
- Scores include points and completion time
- Supports sorting by score and time
- Uses Jackson's polymorphic serialization feature
SlideDTOautomatically selects correct subtype based ontypefield
slide_deck_id+index: Ensures unique slide index within deckteam_id: Ensures each team has only one score recordusername: Ensures unique usernamesinternal_id: Ensures unique competition internal ID
- All association fields have corresponding foreign key constraints
- Cascade delete configuration ensures data consistency
- RESTful Design: Follows REST API design principles
- Version Control: Implements optimistic locking through version fields
- Synchronization Mechanism: Supports real-time data synchronization
- Polymorphic Support: Supports different slide types
- Authentication & Authorization: Complete user authentication system
The system implements a sophisticated real-time synchronization mechanism:
Frontend Polling Strategy:
- Screens periodically poll the backend (typically every 5-10 seconds)
- Each poll includes the current slide deck version
- Backend responds with changes only when version differs
- All connected screens receive updates simultaneously
Benefits:
- Efficiency: Minimal network traffic by only transferring changed data
- Reliability: Automatic conflict resolution through version control
- Scalability: Supports multiple screens without performance degradation
- User Experience: Seamless real-time updates across all displays
Implementation Details:
- Version increments on every slide deck modification
- Timestamp tracking for change detection
- Optimistic locking prevents concurrent modification conflicts
- Graceful handling of network interruptions
- Slide Types: New slide types can be easily added
- Scoring System: Can be extended with more complex scoring rules
- Media Support: Can be extended to support video, audio, and other media types
- Internationalization: Supports internationalization extensions
- Permission System: Can be extended with more granular permission controls