package models import ( "database/sql" "time" "github.com/google/uuid" "github.com/lib/pq" "gorm.io/gorm" ) // Contest représente un concours musical type Contest struct { ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"` Title string `json:"title" gorm:"not null"` Description string `json:"description" gorm:"not null"` Type string `json:"type" gorm:"not null;index"` // remix, production, sound_design, collaboration Status string `json:"status" gorm:"not null;default:'draft'"` // draft, active, voting, completed, cancelled CreatorID uuid.UUID `json:"creator_id" gorm:"type:uuid;not null;index"` OriginalTrackID *uuid.UUID `json:"original_track_id,omitempty" gorm:"type:uuid"` Genre sql.NullString `json:"genre,omitempty"` BPM sql.NullInt32 `json:"bpm,omitempty"` Key sql.NullString `json:"key,omitempty"` Requirements pq.StringArray `json:"requirements" gorm:"type:jsonb"` Rules pq.StringArray `json:"rules" gorm:"type:jsonb"` Timeline ContestTimeline `json:"timeline" gorm:"type:jsonb"` Prizes []ContestPrize `json:"prizes" gorm:"type:jsonb"` JudgingCriteria []JudgingCriterion `json:"judging_criteria" gorm:"type:jsonb"` Settings map[string]interface{} `json:"settings" gorm:"type:jsonb"` CoverImage sql.NullString `json:"cover_image,omitempty"` IsPublic bool `json:"is_public" gorm:"not null;default:true"` IsFeatured bool `json:"is_featured" gorm:"not null;default:false"` MaxParticipants sql.NullInt32 `json:"max_participants,omitempty"` EntryCount int64 `json:"entry_count" gorm:"not null;default:0"` ViewCount int64 `json:"view_count" gorm:"not null;default:0"` VoteCount int64 `json:"vote_count" gorm:"not null;default:0"` CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` // Relations Creator *User `json:"creator,omitempty"` OriginalTrack *SellableContent `json:"original_track,omitempty"` Entries []ContestEntry `json:"entries,omitempty"` Judges []ContestJudge `json:"judges,omitempty"` Sponsors []ContestSponsor `json:"sponsors,omitempty"` } // ContestTimeline représente la timeline d'un concours type ContestTimeline struct { StartDate time.Time `json:"start_date"` SubmissionDeadline time.Time `json:"submission_deadline"` VotingStart time.Time `json:"voting_start"` VotingEnd time.Time `json:"voting_end"` ResultsAnnouncement time.Time `json:"results_announcement"` } // ContestPrize représente un prix dans un concours type ContestPrize struct { Position int `json:"position"` Prize string `json:"prize"` Description string `json:"description"` CashAmount float64 `json:"cash_amount,omitempty"` Currency string `json:"currency,omitempty"` Badge string `json:"badge,omitempty"` Distribution string `json:"distribution,omitempty"` } // JudgingCriterion représente un critère de jugement type JudgingCriterion struct { Name string `json:"name"` Description string `json:"description"` Weight float64 `json:"weight"` MaxScore int `json:"max_score"` } // ContestEntry représente une participation à un concours type ContestEntry struct { ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"` ContestID uuid.UUID `json:"contest_id" gorm:"type:uuid;not null;index"` UserID uuid.UUID `json:"user_id" gorm:"type:uuid;not null;index"` Title string `json:"title" gorm:"not null"` Description string `json:"description"` AudioFile string `json:"audio_file" gorm:"not null"` Metadata map[string]interface{} `json:"metadata" gorm:"type:jsonb"` Status string `json:"status" gorm:"not null;default:'submitted'"` // submitted, approved, disqualified, winner Position sql.NullInt32 `json:"position,omitempty"` Score sql.NullFloat64 `json:"score,omitempty"` VoteCount int64 `json:"vote_count" gorm:"not null;default:0"` ViewCount int64 `json:"view_count" gorm:"not null;default:0"` CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` // Relations Contest *Contest `json:"contest,omitempty"` User *User `json:"user,omitempty"` Votes []ContestVote `json:"votes,omitempty"` } // ContestJudge représente un juge dans un concours type ContestJudge struct { ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"` ContestID uuid.UUID `json:"contest_id" gorm:"type:uuid;not null;index"` UserID uuid.UUID `json:"user_id" gorm:"type:uuid;not null;index"` Role string `json:"role" gorm:"not null"` // head_judge, expert_judge, community_judge Weight float64 `json:"weight" gorm:"not null;default:1.0"` Credentials sql.NullString `json:"credentials,omitempty"` IsActive bool `json:"is_active" gorm:"not null;default:true"` JoinedAt time.Time `json:"joined_at" gorm:"autoCreateTime"` CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` // Relations Contest *Contest `json:"contest,omitempty"` User *User `json:"user,omitempty"` } // ContestVote représente un vote dans un concours type ContestVote struct { ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"` ContestID uuid.UUID `json:"contest_id" gorm:"type:uuid;not null;index"` EntryID uuid.UUID `json:"entry_id" gorm:"type:uuid;not null;index"` UserID uuid.UUID `json:"user_id" gorm:"type:uuid;not null;index"` JudgeID *uuid.UUID `json:"judge_id,omitempty" gorm:"type:uuid"` VoteType string `json:"vote_type" gorm:"not null"` // expert, community Score float64 `json:"score" gorm:"not null"` Criteria map[string]float64 `json:"criteria" gorm:"type:jsonb"` Comment sql.NullString `json:"comment,omitempty"` IsValid bool `json:"is_valid" gorm:"not null;default:true"` CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` // Relations Contest *Contest `json:"contest,omitempty"` Entry *ContestEntry `json:"entry,omitempty"` User *User `json:"user,omitempty"` Judge *ContestJudge `json:"judge,omitempty"` } // ContestSponsor représente un sponsor d'un concours type ContestSponsor struct { ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"` ContestID uuid.UUID `json:"contest_id" gorm:"type:uuid;not null;index"` Name string `json:"name" gorm:"not null"` Description sql.NullString `json:"description,omitempty"` Logo sql.NullString `json:"logo,omitempty"` Website sql.NullString `json:"website,omitempty"` Contribution float64 `json:"contribution" gorm:"not null"` Currency string `json:"currency" gorm:"not null;default:'EUR'"` Benefits pq.StringArray `json:"benefits" gorm:"type:jsonb"` IsActive bool `json:"is_active" gorm:"not null;default:true"` CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` // Relations Contest *Contest `json:"contest,omitempty"` } // ContestStems représente les stems d'un concours (pour remix contests) type ContestStems struct { ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"` ContestID uuid.UUID `json:"contest_id" gorm:"type:uuid;not null;uniqueIndex"` VocalsPath string `json:"vocals_path" gorm:"not null"` DrumsPath string `json:"drums_path" gorm:"not null"` BassPath string `json:"bass_path" gorm:"not null"` OtherPath string `json:"other_path" gorm:"not null"` DownloadURL string `json:"download_url" gorm:"not null"` CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` // Relations Contest *Contest `json:"contest,omitempty"` } // ContestAnalytics représente les analytics d'un concours type ContestAnalytics struct { ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"` ContestID uuid.UUID `json:"contest_id" gorm:"type:uuid;not null;uniqueIndex"` TotalEntries int64 `json:"total_entries" gorm:"not null;default:0"` UniqueParticipants int64 `json:"unique_participants" gorm:"not null;default:0"` TotalVotes int64 `json:"total_votes" gorm:"not null;default:0"` UniqueVoters int64 `json:"unique_voters" gorm:"not null;default:0"` AverageScore float64 `json:"average_score" gorm:"not null;default:0"` CompletionRate float64 `json:"completion_rate" gorm:"not null;default:0"` EngagementRate float64 `json:"engagement_rate" gorm:"not null;default:0"` SocialShares int64 `json:"social_shares" gorm:"not null;default:0"` Comments int64 `json:"comments" gorm:"not null;default:0"` Countries int64 `json:"countries" gorm:"not null;default:0"` CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"` // Relations Contest *Contest `json:"contest,omitempty"` } // ContestBadge représente un badge de concours type ContestBadge struct { ID uuid.UUID `json:"id" gorm:"type:uuid;primaryKey"` ContestID uuid.UUID `json:"contest_id" gorm:"type:uuid;not null;index"` UserID uuid.UUID `json:"user_id" gorm:"type:uuid;not null;index"` BadgeType string `json:"badge_type" gorm:"not null"` // winner, participant, judge, sponsor Position sql.NullInt32 `json:"position,omitempty"` Description string `json:"description" gorm:"not null"` Icon string `json:"icon" gorm:"not null"` Rarity string `json:"rarity" gorm:"not null;default:'common'"` // common, rare, epic, legendary CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"` // Relations Contest *Contest `json:"contest,omitempty"` User *User `json:"user,omitempty"` } // TableName spécifie le nom de la table pour Contest func (Contest) TableName() string { return "contests" } // TableName spécifie le nom de la table pour ContestEntry func (ContestEntry) TableName() string { return "contest_entries" } // TableName spécifie le nom de la table pour ContestJudge func (ContestJudge) TableName() string { return "contest_judges" } // TableName spécifie le nom de la table pour ContestVote func (ContestVote) TableName() string { return "contest_votes" } // TableName spécifie le nom de la table pour ContestSponsor func (ContestSponsor) TableName() string { return "contest_sponsors" } // TableName spécifie le nom de la table pour ContestStems func (ContestStems) TableName() string { return "contest_stems" } // TableName spécifie le nom de la table pour ContestAnalytics func (ContestAnalytics) TableName() string { return "contest_analytics" } // TableName spécifie le nom de la table pour ContestBadge func (ContestBadge) TableName() string { return "contest_badges" } // BeforeCreate hook GORM pour générer UUID si non défini func (m *Contest) BeforeCreate(tx *gorm.DB) error { if m.ID == uuid.Nil { m.ID = uuid.New() } return nil } // BeforeCreate hook GORM pour générer UUID si non défini func (m *ContestEntry) BeforeCreate(tx *gorm.DB) error { if m.ID == uuid.Nil { m.ID = uuid.New() } return nil } // BeforeCreate hook GORM pour générer UUID si non défini func (m *ContestJudge) BeforeCreate(tx *gorm.DB) error { if m.ID == uuid.Nil { m.ID = uuid.New() } return nil } // BeforeCreate hook GORM pour générer UUID si non défini func (m *ContestVote) BeforeCreate(tx *gorm.DB) error { if m.ID == uuid.Nil { m.ID = uuid.New() } return nil } // BeforeCreate hook GORM pour générer UUID si non défini func (m *ContestSponsor) BeforeCreate(tx *gorm.DB) error { if m.ID == uuid.Nil { m.ID = uuid.New() } return nil } // BeforeCreate hook GORM pour générer UUID si non défini func (m *ContestStems) BeforeCreate(tx *gorm.DB) error { if m.ID == uuid.Nil { m.ID = uuid.New() } return nil } // BeforeCreate hook GORM pour générer UUID si non défini func (m *ContestAnalytics) BeforeCreate(tx *gorm.DB) error { if m.ID == uuid.Nil { m.ID = uuid.New() } return nil } // BeforeCreate hook GORM pour générer UUID si non défini func (m *ContestBadge) BeforeCreate(tx *gorm.DB) error { if m.ID == uuid.Nil { m.ID = uuid.New() } return nil }