From bb356120fa0d999d794dcaca41600d068e5fc616 Mon Sep 17 00:00:00 2001 From: daniel-michel <65034538+daniel-michel@users.noreply.github.com> Date: Sat, 11 Nov 2023 14:50:20 +0100 Subject: [PATCH] feature: add precision for release dates also include movies from the last week --- lib/api/movie_api.dart | 2 +- lib/api/wikidata_movie_api.dart | 34 ++++++++++++++++++++++++++------- lib/model/movie.dart | 32 ++++++++++++++++++++++++++++--- lib/model/movie_manager.dart | 3 ++- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/lib/api/movie_api.dart b/lib/api/movie_api.dart index 03d9b83..3d088b5 100644 --- a/lib/api/movie_api.dart +++ b/lib/api/movie_api.dart @@ -1,7 +1,7 @@ import 'package:release_schedule/model/movie.dart'; abstract class MovieApi { - Future> getUpcomingMovies([int count]); + Future> getUpcomingMovies(DateTime startDate, [int count]); Future> searchForMovies(String searchTerm); Future addMovieDetails(List movies); } diff --git a/lib/api/wikidata_movie_api.dart b/lib/api/wikidata_movie_api.dart index 7b6bf63..97b9c0a 100644 --- a/lib/api/wikidata_movie_api.dart +++ b/lib/api/wikidata_movie_api.dart @@ -1,14 +1,16 @@ import 'dart:convert'; import 'package:http/http.dart'; +import 'package:intl/intl.dart'; import 'package:release_schedule/api/api_manager.dart'; import 'package:release_schedule/api/movie_api.dart'; import 'package:release_schedule/model/movie.dart'; class WikidataMovieData extends MovieData { int entityId; - WikidataMovieData(String title, DateTime releaseDate, this.entityId) - : super(title, releaseDate); + WikidataMovieData(String title, DateTime releaseDate, + DatePrecision releaseDatePrecision, this.entityId) + : super(title, releaseDate, releaseDatePrecision); WikidataMovieData.fromEncodable(Map encodable) : entityId = encodable["entityId"], @@ -25,17 +27,22 @@ class WikidataMovieData extends MovieData { } } -String createUpcomingMovieQuery(int limit) { +String createUpcomingMovieQuery(DateTime startDate, int limit) { + String date = DateFormat("yyyy-MM-dd").format(startDate); return """ SELECT ?movie ?movieLabel (MIN(?releaseDate) as ?minReleaseDate) + (SAMPLE(?precision) as ?datePrecision) WHERE { ?movie wdt:P31 wd:Q11424; # Q11424 is the item for "film" wdt:P577 ?releaseDate; # P577 is the "publication date" property wdt:P1476 ?title. - FILTER (xsd:date(?releaseDate) >= xsd:date(NOW())) + OPTIONAL { + ?movie p:P577/psv:P577/wikibase:timePrecision ?precision. + } + FILTER (xsd:date(?releaseDate) >= xsd:date("$date"^^xsd:dateTime)) SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } } @@ -44,6 +51,17 @@ ORDER BY ?minReleaseDate LIMIT $limit"""; } +DatePrecision precisionFromWikidata(int precision) { + return switch (precision) { + >= 11 => DatePrecision.day, + 10 => DatePrecision.month, + 9 => DatePrecision.year, + 8 => DatePrecision.decade, + < 8 => throw Exception("The precision was too low, value: $precision"), + _ => throw Exception("Unexpected precision value: $precision"), + }; +} + class WikidataMovieApi implements MovieApi { ApiManager searchApi = ApiManager("https://www.wikidata.org/w/api.php"); ApiManager queryApi = @@ -56,9 +74,10 @@ class WikidataMovieApi implements MovieApi { } @override - Future> getUpcomingMovies([int count = 100]) async { - Response response = await queryApi - .get("&query=${Uri.encodeComponent(createUpcomingMovieQuery(count))}"); + Future> getUpcomingMovies(DateTime startDate, + [int count = 100]) async { + Response response = await queryApi.get( + "&query=${Uri.encodeComponent(createUpcomingMovieQuery(startDate, count))}"); if (response.statusCode != 200) { throw Exception( "The Wikidata request for upcoming movies failed with status ${response.statusCode} ${response.reasonPhrase}"); @@ -72,6 +91,7 @@ class WikidataMovieApi implements MovieApi { movies.add(WikidataMovieData( entry["movieLabel"]["value"] as String, DateTime.parse(entry["minReleaseDate"]["value"] as String), + precisionFromWikidata(int.parse(entry["datePrecision"]["value"])), int.parse(identifier.substring(1)))); } return movies; diff --git a/lib/model/movie.dart b/lib/model/movie.dart index 3e5fbab..384d2fc 100644 --- a/lib/model/movie.dart +++ b/lib/model/movie.dart @@ -26,9 +26,13 @@ class Review { typedef ReleaseDateInCountry = (String country, DateTime date); typedef TitleInCountry = (String country, String title); +enum DatePrecision { decade, year, month, day, hour, minute } + class MovieData extends ChangeNotifier { String _title; DateTime _releaseDate; + DatePrecision _releaseDatePrecision; + bool _hasDetails = false; List? _releaseDates; List? _genres; @@ -43,6 +47,10 @@ class MovieData extends ChangeNotifier { return _releaseDate; } + DatePrecision get releaseDatePrecision { + return _releaseDatePrecision; + } + List? get releaseDates { return _releaseDates; } @@ -65,6 +73,9 @@ class MovieData extends ChangeNotifier { void updateWithNew(MovieData movie) { setDetails( + title: movie.title, + releaseDate: movie.releaseDate, + releaseDatePrecision: movie.releaseDatePrecision, releaseDates: movie.releaseDates, genres: movie.genres, titles: movie.titles, @@ -72,10 +83,22 @@ class MovieData extends ChangeNotifier { } void setDetails( - {List? releaseDates, + {String? title, + DateTime? releaseDate, + DatePrecision? releaseDatePrecision, + List? releaseDates, List? genres, List? titles, List? reviews}) { + if (title != null) { + _title = title; + } + if (releaseDate != null) { + _releaseDate = releaseDate; + } + if (releaseDatePrecision != null) { + _releaseDatePrecision = releaseDatePrecision; + } if (releaseDates != null) { _releaseDates = releaseDates; } @@ -104,6 +127,7 @@ class MovieData extends ChangeNotifier { return { "title": title, "releaseDate": releaseDate.toIso8601String(), + "releaseDatePrecision": _releaseDatePrecision.name, "releaseDates": releaseDatesByCountry, "genres": genres, "titles": titlesByCountry, @@ -115,11 +139,13 @@ class MovieData extends ChangeNotifier { return title == other.title && releaseDate == other.releaseDate; } - MovieData(this._title, this._releaseDate); + MovieData(this._title, this._releaseDate, this._releaseDatePrecision); MovieData.fromJsonEncodable(Map json) : _title = json["title"], - _releaseDate = DateTime.parse(json["releaseDate"]) { + _releaseDate = DateTime.parse(json["releaseDate"]), + _releaseDatePrecision = DatePrecision.values.firstWhere( + (element) => element.name == json["releaseDatePrecision"]) { setDetails( genres: json["genres"], releaseDates: json["releaseDates"] != null diff --git a/lib/model/movie_manager.dart b/lib/model/movie_manager.dart index ebf3f2e..6ba44ce 100644 --- a/lib/model/movie_manager.dart +++ b/lib/model/movie_manager.dart @@ -136,7 +136,8 @@ class MovieManager extends ChangeNotifier { try { loading = true; notifyListeners(); - List movies = await api.getUpcomingMovies(); + List movies = await api + .getUpcomingMovies(DateTime.now().subtract(const Duration(days: 7))); addMovies(movies); } finally { loading = false;