feat(domain): add WrapUpReport model and supporting types
This commit is contained in:
@@ -19,6 +19,8 @@ pub use watchlist::{WatchlistEntry, WatchlistWithMovie};
|
|||||||
pub mod remote_watchlist;
|
pub mod remote_watchlist;
|
||||||
pub use remote_watchlist::RemoteWatchlistEntry;
|
pub use remote_watchlist::RemoteWatchlistEntry;
|
||||||
pub mod watch_event;
|
pub mod watch_event;
|
||||||
|
pub mod wrapup;
|
||||||
|
pub use wrapup::*;
|
||||||
pub use watch_event::{
|
pub use watch_event::{
|
||||||
ParsedPlaybackEvent, PersistedWatchEvent, WatchEvent, WatchEventSource, WatchEventStatus,
|
ParsedPlaybackEvent, PersistedWatchEvent, WatchEvent, WatchEventSource, WatchEventStatus,
|
||||||
WebhookToken,
|
WebhookToken,
|
||||||
|
|||||||
119
crates/domain/src/models/wrapup.rs
Normal file
119
crates/domain/src/models/wrapup.rs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
use chrono::NaiveDate;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct DateRange {
|
||||||
|
pub start: NaiveDate,
|
||||||
|
pub end: NaiveDate,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct MovieRef {
|
||||||
|
pub title: String,
|
||||||
|
pub year: u16,
|
||||||
|
pub runtime_minutes: Option<u32>,
|
||||||
|
pub poster_path: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct UserRef {
|
||||||
|
pub user_id: Uuid,
|
||||||
|
pub display_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct PersonStat {
|
||||||
|
pub name: String,
|
||||||
|
pub count: u32,
|
||||||
|
pub avg_rating: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct GenreStat {
|
||||||
|
pub genre: String,
|
||||||
|
pub count: u32,
|
||||||
|
pub avg_rating: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct KeywordStat {
|
||||||
|
pub keyword: String,
|
||||||
|
pub count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct LangStat {
|
||||||
|
pub language: String,
|
||||||
|
pub count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct MonthCount {
|
||||||
|
pub year_month: String,
|
||||||
|
pub label: String,
|
||||||
|
pub count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum WrapUpScope {
|
||||||
|
User(Uuid),
|
||||||
|
Global,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct WrapUpReport {
|
||||||
|
pub scope: WrapUpScope,
|
||||||
|
pub date_range: DateRange,
|
||||||
|
pub generated_at: chrono::DateTime<chrono::Utc>,
|
||||||
|
|
||||||
|
// Core viewing
|
||||||
|
pub total_movies: u32,
|
||||||
|
pub total_watch_time_minutes: u32,
|
||||||
|
pub movies_per_month: Vec<MonthCount>,
|
||||||
|
pub busiest_month: Option<String>,
|
||||||
|
pub busiest_day_of_week: Option<String>,
|
||||||
|
pub avg_rating: Option<f64>,
|
||||||
|
pub rating_distribution: [u32; 5],
|
||||||
|
pub longest_movie: Option<MovieRef>,
|
||||||
|
pub shortest_movie: Option<MovieRef>,
|
||||||
|
|
||||||
|
// People insights
|
||||||
|
pub top_directors: Vec<PersonStat>,
|
||||||
|
pub top_actors: Vec<PersonStat>,
|
||||||
|
pub director_diversity: u32,
|
||||||
|
pub actor_diversity: u32,
|
||||||
|
|
||||||
|
// Genre & taste
|
||||||
|
pub top_genres: Vec<GenreStat>,
|
||||||
|
pub genre_diversity: u32,
|
||||||
|
pub highest_rated_genre: Option<String>,
|
||||||
|
pub lowest_rated_genre: Option<String>,
|
||||||
|
pub top_keywords: Vec<KeywordStat>,
|
||||||
|
|
||||||
|
// Financial/production (None when data unavailable)
|
||||||
|
pub total_budget_watched: Option<i64>,
|
||||||
|
pub avg_budget: Option<i64>,
|
||||||
|
pub language_distribution: Vec<LangStat>,
|
||||||
|
pub oldest_movie: Option<MovieRef>,
|
||||||
|
pub newest_movie: Option<MovieRef>,
|
||||||
|
|
||||||
|
// Rewatch stats
|
||||||
|
pub total_rewatches: u32,
|
||||||
|
pub most_rewatched_movie: Option<MovieRef>,
|
||||||
|
pub avg_rating_change_on_rewatch: Option<f64>,
|
||||||
|
|
||||||
|
// Highlights
|
||||||
|
pub highest_rated_movie: Option<MovieRef>,
|
||||||
|
pub lowest_rated_movie: Option<MovieRef>,
|
||||||
|
pub first_movie_of_period: Option<MovieRef>,
|
||||||
|
pub last_movie_of_period: Option<MovieRef>,
|
||||||
|
|
||||||
|
// Global-only (None for per-user)
|
||||||
|
pub most_active_user: Option<UserRef>,
|
||||||
|
pub most_watched_movie_global: Option<MovieRef>,
|
||||||
|
pub total_users_active: Option<u32>,
|
||||||
|
|
||||||
|
// Asset references for renderers
|
||||||
|
pub poster_paths: Vec<String>,
|
||||||
|
pub top_cast_profile_paths: Vec<String>,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user