diff --git a/pom.xml b/pom.xml index 0c428fa..4f7f5f6 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,7 @@ org.projectlombok lombok + 1.18.30 true @@ -81,6 +82,7 @@ org.projectlombok lombok + 1.18.30 diff --git a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java index 79be9ce..5fdc2e3 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/yandex/practicum/filmorate/controller/FilmController.java @@ -63,8 +63,10 @@ public void deleteLikeToFilm(@PathVariable long filmId, @PathVariable long userI } @GetMapping("/popular") - public List getTopFilms(@RequestParam(defaultValue = "10") @Positive(message = "Count must be positive") int count) { - log.info("Received GET /films/popular?count={} request", count); - return filmService.getTopFilms(count); + public List getTopFilms(@RequestParam(defaultValue = "10") @Positive(message = "Count must be positive") int count, + @RequestParam(defaultValue = "-1") int genreId, + @RequestParam(defaultValue = "-1") int year) { + log.info("Received GET /films/popular?count={}&genreId={}&year={} request", count, genreId, year); + return filmService.getTopFilms(count, genreId, year); } } \ No newline at end of file diff --git a/src/main/java/ru/yandex/practicum/filmorate/dal/FilmRepository.java b/src/main/java/ru/yandex/practicum/filmorate/dal/FilmRepository.java index 4adda28..0ddf60e 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/dal/FilmRepository.java +++ b/src/main/java/ru/yandex/practicum/filmorate/dal/FilmRepository.java @@ -93,7 +93,7 @@ public Optional findById(long id) { if (films.isEmpty()) { return Optional.empty(); } else { - Film film = films.get(0); + Film film = films.getFirst(); setGenresForFilms(List.of(film)); return Optional.of(film); } @@ -206,4 +206,32 @@ public void addLike(long filmId, long userId) { public void removeLike(long filmId, long userId) { jdbc.update(REMOVE_LIKE_QUERY, filmId, userId); } -} \ No newline at end of file + + public List getTopFilms(int count, Integer genreId, Integer year) { + + StringBuilder queryBuilder = new StringBuilder("SELECT f.*, r.rating_id AS mpa_id, r.rating_name AS mpa_name " + + "FROM films AS f JOIN rating AS r on f.rating_id = r.rating_id " + + "JOIN film_genre AS fg ON f.id = fg.film_id " + + "JOIN likes AS l ON f.id = l.film_id WHERE 1=1"); + + List filterParams = new ArrayList<>(); + + if (genreId != -1) { + queryBuilder.append(" AND fg.genre_id = ?"); + filterParams.add(genreId); + } + + if (year != -1) { + queryBuilder.append(" AND EXTRACT(YEAR FROM f.release_date) = ?"); + filterParams.add(year); + } + + queryBuilder.append(" GROUP BY f.id, r.rating_id, r.rating_name ORDER BY COUNT(l.user_id) DESC LIMIT ?;"); + filterParams.add(count); + + List films = jdbc.query(queryBuilder.toString(), filmWithRatingMapper, filterParams.toArray()); + setGenresForFilms(films); + return films; + } + +} diff --git a/src/main/java/ru/yandex/practicum/filmorate/service/film/FilmService.java b/src/main/java/ru/yandex/practicum/filmorate/service/film/FilmService.java index 4f83d6e..39d8629 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/service/film/FilmService.java +++ b/src/main/java/ru/yandex/practicum/filmorate/service/film/FilmService.java @@ -22,7 +22,6 @@ import java.time.LocalDate; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -89,23 +88,19 @@ public void deleteLikeToFilm(long filmId, long userId) { log.info("Like removed successfully"); } - public List getTopFilms(int count) { - log.info("Getting top {} popular films", count); + public List getTopFilms(int count, int genreId, int year) { + log.info("Getting top {} popular films with genreId = {} and release year = {}", count, genreId, year); if (count <= 0) { throw new ValidationException("Count parameter must be positive."); } - Collection allFilms = filmStorage.getFilms(); - return allFilms.stream() + return filmStorage.getTopFilms(count, genreId, year) + .stream() .map(film -> { Set likes = filmStorage.getLikes(film.getId()); - return Map.entry(film, likes.size()); + return FilmMapper.mapToFilmDto(film, likes); }) - .sorted(Map.Entry.comparingByValue().reversed()) - .limit(count) - .map(Map.Entry::getKey) - .map(film -> FilmMapper.mapToFilmDto(film, filmStorage.getLikes(film.getId()))) - .collect(Collectors.toList()); + .toList(); } public Collection getGenres() { diff --git a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java index 5cb7f56..a654a66 100644 --- a/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java +++ b/src/main/java/ru/yandex/practicum/filmorate/storage/film/FilmDbStorage.java @@ -92,6 +92,10 @@ public Rating getRatingById(int id) { .orElseThrow(() -> new NotFoundException("Rating with id " + id + " not found")); } + public List getTopFilms(int count, int genreId, int year) { + return filmRepository.getTopFilms(count, genreId, year); + } + private void validateRatingExists(Rating mpa) { if (mpa == null || mpa.getId() == 0) { throw new IllegalArgumentException("Film Rating (MPA) is required."); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1730186..73fd17b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,7 @@ -logging.level.org.zalando.logbook:ERROR \ No newline at end of file +logging.level.org.zalando.logbook=TRACE +logging.level.ru.yandex.practicum.filmorate=INFO +spring.sql.init.mode=always +spring.datasource.url=jdbc:h2:file:./db/filmorate +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password \ No newline at end of file