diff --git a/src/main/java/ru/com/practicum/filmorate/controller/FilmController.java b/src/main/java/ru/com/practicum/filmorate/controller/FilmController.java index e916472..c2fb094 100644 --- a/src/main/java/ru/com/practicum/filmorate/controller/FilmController.java +++ b/src/main/java/ru/com/practicum/filmorate/controller/FilmController.java @@ -9,6 +9,7 @@ import ru.com.practicum.filmorate.service.FeedService; import ru.com.practicum.filmorate.service.FilmService; +import javax.validation.constraints.Positive; import java.util.List; @@ -40,8 +41,8 @@ public Film update(@RequestBody Film film) throws ValidationException, NotFoundE } @PutMapping(value = "/films/{id}/like/{userId}") - public void addLike(@PathVariable Long id, @PathVariable Long userId) { - filmService.addLike(id, userId); + public void addLike(@PathVariable Long id, @PathVariable Long userId, @RequestParam @Positive int rating) { + filmService.addLike(id, userId, rating); Event event = Event.builder() .timestamp(System.currentTimeMillis()) .userId(userId) @@ -75,9 +76,7 @@ public List getTop(@RequestParam(defaultValue = "10", required = false) In } @GetMapping(value = "/films/common") - public List getCommonFilms( - @RequestParam long userId, - @RequestParam long friendId){ + public List getCommonFilms(@RequestParam long userId, @RequestParam long friendId) { return filmService.getCommonFilms(userId, friendId); } diff --git a/src/main/java/ru/com/practicum/filmorate/service/FilmService.java b/src/main/java/ru/com/practicum/filmorate/service/FilmService.java index 051f164..9920a83 100644 --- a/src/main/java/ru/com/practicum/filmorate/service/FilmService.java +++ b/src/main/java/ru/com/practicum/filmorate/service/FilmService.java @@ -54,9 +54,13 @@ public Film update(Film film) throws NotFoundException { return filmStorage.update(film); } - public void addLike(Long id, Long userId) throws NotFoundException { + public void addLike(Long id, Long userId, int rating) throws NotFoundException { Film film = filmStorage.getById(id); - filmStorage.addLike(id, userId); + + if (rating < 11) { + filmStorage.addLike(id, userId, rating); + } + log.info("Фильм с id={} лайкнул пользователь {}", film.getId(), userId); } @@ -72,7 +76,7 @@ public void removeLike(Long id, Long userId) throws NotFoundException { public List getTop(Integer count, Long genreId, Integer year) { return getFilterFilmsByGenreId(getFilterFilmsByYear(filmStorage.getAll().stream(), year), genreId) .sorted((f1, f2) -> - (dbFilmStorage.getFilmLikeId(f2.getId()) - dbFilmStorage.getFilmLikeId(f1.getId()))) + (int) (dbFilmStorage.getFilmRating(f2.getId()) - dbFilmStorage.getFilmRating(f1.getId()))) .limit(count) .collect(Collectors.toList()); } diff --git a/src/main/java/ru/com/practicum/filmorate/storage/film/DBFilmStorage.java b/src/main/java/ru/com/practicum/filmorate/storage/film/DBFilmStorage.java index 035d253..bfbb599 100644 --- a/src/main/java/ru/com/practicum/filmorate/storage/film/DBFilmStorage.java +++ b/src/main/java/ru/com/practicum/filmorate/storage/film/DBFilmStorage.java @@ -107,9 +107,9 @@ public void delete(Long filmId) { } @Override - public void addLike(Long id, Long userId) { - String sqlQuery = "INSERT INTO likes_list (user_id, film_id) VALUES (?, ?);"; - jdbcTemplate.update(sqlQuery, userId, id); + public void addLike(Long id, Long userId, int rating) { + String sqlQuery = "INSERT INTO likes_list (user_id, film_id, rating) VALUES (?, ?, ?);"; + jdbcTemplate.update(sqlQuery, userId, id, rating); } @Override @@ -155,7 +155,7 @@ public List getFilmsByDirectorId(Long id, SortingTypes sortBy) { "JOIN MPA_ratings AS m ON m.id = f.mpa_id " + "JOIN films AS f ON f.id = fd.film_id " + "LEFT JOIN (SELECT film_id, " + - "COUNT(user_id) rate " + + "AVG(rating) rate " + "FROM likes_list " + "GROUP BY film_id) r ON fd.id = r.film_id " + "WHERE fd.director_id = ?" + @@ -171,13 +171,16 @@ public List getFilmsByDirectorId(Long id, SortingTypes sortBy) { public List getRecommendations(Long userId) { List recommendations = new ArrayList<>(); - String similarUserQuery = "SELECT user_id, COUNT(film_id) as c " + + String similarUserQuery = "SELECT user_id, AVG(rating) as r " + "FROM likes_list " + "WHERE film_id IN (SELECT film_id " + "FROM likes_list " + "WHERE user_id = ?) AND user_id != ? " + + "AND rating IN (SELECT rating " + + "FROM likes_list " + + "WHERE user_id = ?) " + "GROUP BY user_id " + - "ORDER BY c DESC " + + "ORDER BY r DESC " + "LIMIT 1;"; String recommendedFilmsQuery = "SELECT f.id, " + @@ -192,9 +195,10 @@ public List getRecommendations(Long userId) { "JOIN MPA_ratings AS m ON m.id = f.mpa_id " + "WHERE l.film_id NOT IN (SELECT film_id " + "FROM likes_list " + - "WHERE user_id = ?) AND l.user_id = ? ;"; + "WHERE user_id = ?) AND l.user_id = ? " + + "AND l.rating > 5;"; - SqlRowSet rowSet = jdbcTemplate.queryForRowSet(similarUserQuery, userId, userId); + SqlRowSet rowSet = jdbcTemplate.queryForRowSet(similarUserQuery, userId, userId, userId); if (!rowSet.next()) { return recommendations; @@ -248,7 +252,7 @@ public List searchFilms(String directorSubstring, String titleSubstring) { "LEFT JOIN likes_list AS l ON f.id = l.film_id " + "WHERE (LOWER(d.name) LIKE ?) OR (LOWER(f.name) LIKE ?) " + "GROUP BY f.id " + - "ORDER BY COUNT(l.user_id) DESC;"; + "ORDER BY AVG(l.rating) DESC;"; return jdbcTemplate.query(sqlQuery, (rs, rowNum) -> makeFilm(rs, genreService, directorService), director, title); } @@ -269,14 +273,16 @@ private Film makeFilm(ResultSet rs, GenreService genreService, return new Film(id, name, description, releaseDate, duration, genres, mpa, directors); } - public int getFilmLikeId(long film) { - String sqlQuery = "SELECT user_id FROM likes_list WHERE film_id = ?"; - return jdbcTemplate.query(sqlQuery, this::createLikeId, film).size(); + public double getFilmRating(long film) { + String sqlQuery = "SELECT rating FROM likes_list WHERE film_id = ?"; + return jdbcTemplate.query(sqlQuery, this::createRating, film).stream() + .mapToInt(Math::toIntExact) + .average() + .getAsDouble(); } - private long createLikeId(ResultSet rs, int rowNum) throws SQLException { - String user_id = "user_id"; - return rs.getLong(user_id); + private long createRating(ResultSet rs, int rowNum) throws SQLException { + return rs.getInt("rating"); } } diff --git a/src/main/java/ru/com/practicum/filmorate/storage/film/FilmStorage.java b/src/main/java/ru/com/practicum/filmorate/storage/film/FilmStorage.java index 5b31091..ec4aa45 100644 --- a/src/main/java/ru/com/practicum/filmorate/storage/film/FilmStorage.java +++ b/src/main/java/ru/com/practicum/filmorate/storage/film/FilmStorage.java @@ -17,7 +17,7 @@ public interface FilmStorage { void delete(Long filmId); - void addLike(Long id, Long userId); + void addLike(Long id, Long userId, int rating); void removeLike(Long id, Long userId); diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index da00f5d..bbd832a 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -42,7 +42,8 @@ CREATE TABLE IF NOT EXISTS friendships ( CREATE TABLE IF NOT EXISTS likes_list ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, user_id BIGINT REFERENCES users (id) ON DELETE CASCADE, - film_id BIGINT REFERENCES films (id) ON DELETE CASCADE + film_id BIGINT REFERENCES films (id) ON DELETE CASCADE, + rating INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS directors (