release_schedule/lib/model/movie.dart

292 lines
7.8 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
2023-11-16 12:51:45 +01:00
import 'package:intl/intl.dart';
class MovieData extends ChangeNotifier {
2023-11-08 14:43:59 +01:00
String _title;
2023-11-16 12:51:45 +01:00
DateWithPrecisionAndCountry _releaseDate;
2024-01-08 12:57:36 +01:00
bool _bookmarked = false;
bool _hasDetails = false;
2023-11-16 12:51:45 +01:00
List<DateWithPrecisionAndCountry>? _releaseDates;
2023-11-08 14:43:59 +01:00
List<String>? _genres;
2023-11-16 12:51:45 +01:00
List<TitleInLanguage>? _titles;
2023-11-08 14:43:59 +01:00
List<Review>? _reviews;
2023-11-16 12:51:45 +01:00
MovieData(this._title, this._releaseDate);
2023-11-11 15:05:11 +01:00
2023-11-08 14:43:59 +01:00
String get title {
return _title;
}
2023-11-16 12:51:45 +01:00
DateWithPrecisionAndCountry get releaseDate {
2023-11-08 14:43:59 +01:00
return _releaseDate;
}
2024-01-08 12:57:36 +01:00
bool get bookmarked {
return _bookmarked;
}
2023-11-16 12:51:45 +01:00
List<DateWithPrecisionAndCountry>? get releaseDates {
return _releaseDates;
}
List<String>? get genres {
return _genres;
}
2023-11-16 12:51:45 +01:00
List<TitleInLanguage>? get titles {
return _titles;
}
List<Review>? get reviews {
return _reviews;
}
bool get hasDetails {
return _hasDetails;
}
2024-01-08 12:57:36 +01:00
/// Updates the information with that of a new version of the movie
/// but ignores fields that are user controlled, like whether the movie was bookmarked.
void updateWithNewIgnoringUserControlled(MovieData movie) {
2023-11-08 14:43:59 +01:00
setDetails(
title: movie.title,
releaseDate: movie.releaseDate,
2023-11-08 14:43:59 +01:00
releaseDates: movie.releaseDates,
genres: movie.genres,
titles: movie.titles,
reviews: movie.reviews);
}
void setDetails(
{String? title,
2023-11-16 12:51:45 +01:00
DateWithPrecisionAndCountry? releaseDate,
2024-01-08 12:57:36 +01:00
bool? bookmarked,
2023-11-16 12:51:45 +01:00
List<DateWithPrecisionAndCountry>? releaseDates,
List<String>? genres,
2023-11-16 12:51:45 +01:00
List<TitleInLanguage>? titles,
List<Review>? reviews}) {
if (title != null) {
_title = title;
}
if (releaseDate != null) {
_releaseDate = releaseDate;
}
2024-01-08 12:57:36 +01:00
if (bookmarked != null) {
_bookmarked = bookmarked;
}
if (releaseDates != null) {
_releaseDates = releaseDates;
}
if (genres != null) {
_genres = genres;
}
if (titles != null) {
_titles = titles;
}
if (reviews != null) {
_reviews = reviews;
}
_hasDetails = true;
notifyListeners();
}
@override
String toString() {
2023-11-16 12:51:45 +01:00
return "$title (${_releaseDate.toString()}${_genres?.isNotEmpty ?? true ? "; ${_genres?.join(", ")}" : ""})";
2023-11-08 14:43:59 +01:00
}
2024-01-08 12:57:36 +01:00
bool same(MovieData other) {
2024-01-09 14:48:36 +01:00
return title == other.title &&
releaseDate.dateWithPrecision == other.releaseDate.dateWithPrecision;
2024-01-08 12:57:36 +01:00
}
2023-11-08 14:43:59 +01:00
Map toJsonEncodable() {
List? releaseDatesByCountry =
2023-11-16 12:51:45 +01:00
_releaseDates?.map((e) => e.toJsonEncodable()).toList();
List? titlesByCountry = _titles?.map((e) => [e.title, e.language]).toList();
2023-11-08 14:43:59 +01:00
return {
"title": title,
2023-11-16 12:51:45 +01:00
"releaseDate": _releaseDate.toJsonEncodable(),
2024-01-08 12:57:36 +01:00
"bookmarked": _bookmarked,
2023-11-08 14:43:59 +01:00
"releaseDates": releaseDatesByCountry,
"genres": genres,
"titles": titlesByCountry,
2023-11-16 14:38:33 +01:00
"reviews": reviews?.map((review) => review.toJsonEncodable()).toList(),
2023-11-08 14:43:59 +01:00
};
}
2023-11-08 14:43:59 +01:00
MovieData.fromJsonEncodable(Map json)
: _title = json["title"],
2023-11-16 12:51:45 +01:00
_releaseDate =
DateWithPrecisionAndCountry.fromJsonEncodable(json["releaseDate"]) {
2023-11-08 14:43:59 +01:00
setDetails(
2024-01-08 12:57:36 +01:00
bookmarked: json["bookmarked"] as bool,
2023-11-16 12:51:45 +01:00
genres: (json["genres"] as List<dynamic>?)
?.map((genre) => genre as String)
.toList(),
2023-11-08 14:43:59 +01:00
releaseDates: json["releaseDates"] != null
2023-11-16 14:38:33 +01:00
? (json["releaseDates"] as List<dynamic>)
2023-11-16 12:51:45 +01:00
.map((release) =>
DateWithPrecisionAndCountry.fromJsonEncodable(release))
2023-11-08 14:43:59 +01:00
.toList()
: null,
reviews: json["reviews"] != null
2023-11-16 14:38:33 +01:00
? (json["reviews"] as List<dynamic>)
2023-11-08 14:43:59 +01:00
.map((review) => Review.fromJsonEncodable(review))
.toList()
: null,
titles: json["titles"] != null
? (json["titles"] as List<dynamic>)
2023-11-16 12:51:45 +01:00
.map((title) =>
(title: title[0], language: title[1]) as TitleInLanguage)
2023-11-08 14:43:59 +01:00
.toList()
: null);
}
}
enum DatePrecision { decade, year, month, day, hour, minute }
extension DatePrecisionComparison on DatePrecision {
bool operator <(DatePrecision other) {
return index < other.index;
}
bool operator <=(DatePrecision other) {
return index <= other.index;
}
bool operator >(DatePrecision other) {
return index > other.index;
}
bool operator >=(DatePrecision other) {
return index >= other.index;
}
}
typedef TitleInLanguage = ({String title, String language});
2024-01-09 14:48:36 +01:00
class DateWithPrecision implements Comparable<DateWithPrecision> {
DateTime date;
DatePrecision precision;
2024-01-09 14:48:36 +01:00
DateWithPrecision(this.date, this.precision);
2024-01-09 14:48:36 +01:00
DateWithPrecision.fromJsonEncodable(List<dynamic> json)
: date = DateTime.parse(json[0]),
precision = DatePrecision.values
2024-01-09 14:48:36 +01:00
.firstWhere((element) => element.name == json[1]);
2024-01-09 14:48:36 +01:00
List<dynamic> toJsonEncodable() {
return [date.toIso8601String(), precision.name];
}
@override
String toString() {
return switch (precision) {
2023-11-16 14:38:33 +01:00
DatePrecision.decade =>
"${DateFormat("yyyy").format(date).substring(0, 3)}0s",
DatePrecision.year => DateFormat.y().format(date),
DatePrecision.month => DateFormat.yMMMM().format(date),
DatePrecision.day => DateFormat.yMMMMd().format(date),
DatePrecision.hour => DateFormat("MMMM d, yyyy, HH").format(date),
DatePrecision.minute => DateFormat("MMMM d, yyyy, HH:mm").format(date)
};
}
2024-01-09 14:48:36 +01:00
@override
int compareTo(DateWithPrecision other) {
if (date.isBefore(other.date)) {
return -1;
} else if (date.isAfter(other.date)) {
return 1;
} else {
return precision.index - other.precision.index;
}
}
@override
bool operator ==(Object other) {
return other is DateWithPrecision &&
date == other.date &&
precision == other.precision;
}
@override
int get hashCode {
return date.hashCode ^ precision.hashCode;
}
bool includes(DateTime date) {
switch (precision) {
case DatePrecision.decade:
return this.date.year ~/ 10 == date.year ~/ 10;
case DatePrecision.year:
return this.date.year == date.year;
case DatePrecision.month:
return this.date.year == date.year && this.date.month == date.month;
case DatePrecision.day:
return this.date.year == date.year &&
this.date.month == date.month &&
this.date.day == date.day;
case DatePrecision.hour:
return this.date.year == date.year &&
this.date.month == date.month &&
this.date.day == date.day &&
this.date.hour == date.hour;
case DatePrecision.minute:
return this.date.year == date.year &&
this.date.month == date.month &&
this.date.day == date.day &&
this.date.hour == date.hour &&
this.date.minute == date.minute;
}
}
}
class DateWithPrecisionAndCountry {
final DateWithPrecision dateWithPrecision;
final String country;
DateWithPrecisionAndCountry(
DateTime date, DatePrecision precision, this.country)
: dateWithPrecision = DateWithPrecision(date, precision);
DateWithPrecisionAndCountry.fromJsonEncodable(List<dynamic> json)
: dateWithPrecision = DateWithPrecision.fromJsonEncodable(json),
country = json[2];
toJsonEncodable() {
return dateWithPrecision.toJsonEncodable() + [country];
}
@override
String toString() {
return "${dateWithPrecision.toString()} ($country)";
}
}
class Review {
String score;
String by;
DateTime asOf;
int count;
Review(this.score, this.by, this.asOf, this.count);
Review.fromJsonEncodable(Map json)
: score = json["score"],
by = json["by"],
asOf = DateTime.parse(json["asOf"]),
count = json["count"];
Map toJsonEncodable() {
return {
"score": score,
"by": by,
"asOf": asOf.toIso8601String(),
"count": count,
};
}
}