This project is for the capstone project in SW Engineering (CSE364) at UNIST, developed by Yeongjun Kwak, Sanghun Lee and Yujin Lee. This will be further inplemented as a movie recommendation system. Currently under the development···
CSE364_Project/
├── data/ # Source data
├── scripts/ # Documentation files
├── src/ # Source files
│ ├── main/
│ │ └── java/
│ │ └── group11/
│ │ │ └── restservice/
│ │ └── resources/
│ └── test/
│ ├── java/
│ │ └── group11/
│ └── resources/
├── target/ # Generated when mvn install
│ └── site/
│ └── jacoco/
│ └── index.html # JaCoCo Code Coverage Report
├── pom.xml # Maven configuration
├── mvnw # Maven configuration
├── mvnw.cmd # Maven configuration
└── README.md
Instructions for setting up the project locally.
git clone
, the user should be registered as a Contributo or Collaborator of this git project. (Unless you have the OAuth access token.)dockerfile
and run.sh
in the same directory.$ docker build -t new_image_name /path/to/dockerfile
$ docker run -it new_image_name
. run.sh
root@containerID:~/project# . run.sh
Goal : Environment setup, data loading, data preprocessing
On Milestone 1, the code calculates and returns the average rating from ratings data for specified occupation and genre.
Continued from Installation steps.
root@containerID:~/project# java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project InputStr1 InputStr2
When valid inputs are passed, the output message will look like this :
// Input
java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project Adventure Educator
// Output
3.42
// Input
java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project Animation Doctor
// Output
3.68
Genre | total:18 | ||
---|---|---|---|
Action | Crime | Horror | Thriller |
Adventure | Documentary | Musical | War |
Animation | Drama | Mystery | Western |
Children's | Fantasy | Romance | |
Comedy | Film-Noir | Sci-Fi |
Occupation | total : 21 | ||
---|---|---|---|
Academic (Educator) | Executive (Managerial) | Programmer | Technician (Engineer) |
Artist | Farmer | Retired | Tradesman (Craftsman) |
Clerical (Admin) | Homemaker | Sales (Marketing) | Unemployed |
Collegestudent (College, Grad, Gradstudent) | K-12student | Scientist | Writer |
Customerservice | Lawyer | Self-employed | Other |
Doctor (Healthcare) |
Action // Supported
Accion // X
Action // Supported
action // Supported
ACTION // Supported
aCtIOn // Supported
Gradstudent // Supported
Grad student // X
Sci-Fi // Supported
SciFi // X
Action|Adventure // X
"Action|Adventure|" // X (Pipeline should be between words)
"Action|Adventure" // Supported
"Action|Adventure|Animation" // Supported
"Action|Adventure"
, the movies that fall into both Action and Adventure category are used for the calculation.Possible errors thrown by invalid user input.
Error | Code | Message | Description |
---|---|---|---|
InputEmptyError |
1 | No argument has passed. 2 arguments are required. (InputStr1 InputStr2) | Thrown when no input has entered. |
InputNumError |
2 | Only 1 input has passed. 2 arguments are required. | Thrown when only 1 input has entered. |
InputNumError |
3 | More than 2 arguments have passed. 2 arguments are required. | Thrown when more than 2 inputs have entered. |
InputInvalidError |
4 | Entered genre input is invalid | Thrown when the entered genre (combination) is invalid. |
InputInvalidError |
5 | Entered genre (inputString) doesn't exist. ( Invalid word : input_string ) | Thrown when the word in the entered genre (OR the word in genre combination) is invalid. |
Warning | Code | Message | Description |
---|---|---|---|
InputInvalidWarning |
6 | Entered occupation doesn't exist. Rating by 'other' is shown instead. | Thrown when the 2nd input is invalid. |
Error | Code | Message | Description |
---|---|---|---|
NoDBError |
7 | Rating data matching the input pair doesn't exist. | Thrown when there's no available Rating data for the genre-occupation pair OR When there's no Movie data matching the entered genre (combination). |
1
.% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project
InputEmptyError : No argument has passed. 2 arguments are required. (InputStr1 InputStr2)
Error code: 1
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project Drama
InputNumError : Only 1 input has passed. 2 arguments are required.
Error code: 2
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project Drama Scientist Scientist
InputNumError : More than 2 arguments have passed. 2 arguments are required.
Error code: 3
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project "|Adventure|Action" Scientist
InputInvalidError : Entered genre input is invalid.
Error code: 4
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project "Adventure|Action|" Scientist
InputInvalidError : Entered genre input is invalid.
Error code: 4
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project "Adventure|Action|Horrrror" Scientist
InputInvalidError : Entered genre (horrrror) doesn't exist.
Error code: 5
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project Adventure Librarian
InputInvalidWarning : Entered occupation doesn't exist. Rating by 'other' is shown instead.
The rating of adventure rated by other : 3.43
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project "War|Crime" Academic
NoDBError : Rating data matching the input pair doesn't exist.
Error code: 7
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.project "Action|Animation|Children's|Sci-Fi|Thriller|War" retired
NoDBError : Rating data matching the input pair doesn't exist.
Error code: 7
"War|Crime" Academic
: Example for No Movie data matching the entered genre (combination)."Action|Animation|Children's|Sci-Fi|Thriller|War" retired
: Example for No available Rating data for the genre-occupation input pair.The Junit test (and regarding csv test resources) for Milestone 1 has been moved to scripts/
.
For more information, please refer to this issue #20
Area | Contribution |
---|---|
Setting up a Git Repository | Yeongjun Kwak |
Environment Setup | dockerfile, pom.xml Yujin Lee |
Java Implementation | Models and Data Structures 👑 Yeongjun Kwak Exception Handling 👑 Sanghun Lee, Yeongjun Kwak Unit Test Building Yujin Lee Final Reviewer Sanghun Lee, Yeongjun Kwak |
Documentation | README.md 👑 Yujin Lee, Sanghun Lee |
Goal : Implement Top 10 Movies Recommendation Features
On Milestone 2, the code returns the recommendation of Top 10 movies for specified gender, age, occupation or genre(s). First, to recommend 'relevant' movies, the code makes use of 1) Bayesian Estimate, which is used to calculate Top 250 movies by IMDB as well, when calculating and comparing the ratings of movies. Also, to set the 'similar' users (in case there aren't enough ratings that match gender, age and occupation), we have set 2) Priority rule for including similar users.
To briefly explain how the algorithm works :
valid_user_list
) of users that matches the inputs from users.dat
.ratings.dat
and movies.dat
using valid_user_list
.100
movies) for specified user data OR when m
is too small for the movie candidates (On here, it is set to 10
votes),
If the conditions are not met -> 4.
If all the conditions are met -> 5.valid_user_list
in order of precedence (priority) by function make_intersection_list_macro
.
After adding the similar users, it will repeat the steps from 2 with added valid_user_list
again (Until the conditions on Step 3 is met).Bayesian Estimate is an estimator that can help minimizing the risk of including that minimizes the posterior expected value of a loss function.
By making use of Bayesian Estimate, the algorithm calculates Weighted Rating (W
) and arranges movies with W
.
In this way, the movies with very few ratings or below-average ratings will have comparably light weight.
In Detail, the calculation of Weighted Rating(W
) is implemented by
classified_table
) by selecting the object with more than m
votes from movie_data_table
.The original reference for Baysian Estimate can be found here. However, in this project, the estimation method and variables has been set differently to adjust the differences in requirements.
W = (vR+mC)/(v+m)
Variables | Explanation |
---|---|
W | Weighted rating |
v | Total number of ratings for the movie = (votes) |
m | Minimum number of ratings required to be listed in the Top 10 |
R | Average rating for the movie as a number from 0 to 5 (mean) |
C | Average rating across all the movies |
v
and R
v
and R
are obtained by making use of Movie_data_node
. m
: Minimum Number of Ratings
m
is obtained by the percentile
function. The function returns the number of votes of the movie that corresponds to (1-p
)*100 % .
static int percentile(ArrayList<Movie_data_node> movie_rating_matrix, double p)
p
is differently set for number of movies by set_p
function ; so that the validity of the weighted rating can be enhanced.
static double set_p(int size){
if(size<100){
return 0.5;
}
else if(size<200){
return 0.6;
}
else if(size<500){
return 0.7;
}
else{
return 0.8;
}
}
e.g If there are 1000 movies with average ratings, the function will return the number of ratings of 200th-highest movie.
C
: Average rating across all the movies
C
is obtained by the total_average_rating
function.
static double total_average_rating(ArrayList<Movie_data_node> movie_rating_matrix)
The algorithm firstly makes the ArrayList(valid_user_list
) of users that matches the inputs from users.dat
.
And then, this list is used to extract the ratings information and movie data from ratings.dat
and movies.dat
.
However,
100 movies
) for specified user data,m
is small for the movie candidates. (On here, it is set to 10
votes).
valid_user_list
in order of precedence (priority) by function make_intersection_list_macro
, until the number of movie candidates gets bigger than 100
and m
gets bigger than 10.The similar users with priority are the users with :
The priority has set as above to give a more weighting on Occupation, and less on Gender and Age Range.
Continued from Installation steps.
root@containerID:~/project# java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 InputStr1 InputStr2 InputStr3 InputStr4
mvn install
or mvn test
) might take up to a minute. When valid inputs are passed, the output message will look like this :
// Input
java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 "F" "25" "Gradstudent"
// Output
Sixth Sense, The (1999) (http://www.imdb.com/title/tt0167404)
Matrix, The (1999) (http://www.imdb.com/title/tt0133093)
Shawshank Redemption, The (1994) (http://www.imdb.com/title/tt0111161)
Usual Suspects, The (1995) (http://www.imdb.com/title/tt0114814)
Silence of the Lambs, The (1991) (http://www.imdb.com/title/tt0102926)
Close Shave, A (1995) (http://www.imdb.com/title/tt0112691)
Wrong Trousers, The (1993) (http://www.imdb.com/title/tt0108598)
Cinema Paradiso (1988) (http://www.imdb.com/title/tt0095765)
American Beauty (1999) (http://www.imdb.com/title/tt0169547)
Raiders of the Lost Ark (1981) (http://www.imdb.com/title/tt0082971)
// Input
java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 "F" "25" "Gradstudent" "Action|Comedy"
// Output
Matrix, The (1999) (http://www.imdb.com/title/tt0133093)
Close Shave, A (1995) (http://www.imdb.com/title/tt0112691)
Wrong Trousers, The (1993) (http://www.imdb.com/title/tt0108598)
American Beauty (1999) (http://www.imdb.com/title/tt0169547)
Shakespeare in Love (1998) (http://www.imdb.com/title/tt0138097)
Raiders of the Lost Ark (1981) (http://www.imdb.com/title/tt0082971)
Cinema Paradiso (1988) (http://www.imdb.com/title/tt0095765)
Eat Drink Man Woman (1994) (http://www.imdb.com/title/tt0111797)
Raising Arizona (1987) (http://www.imdb.com/title/tt0093822)
Breakfast Club, The (1985) (http://www.imdb.com/title/tt0088847)
InputStr1 | InputStr2 | InputStr3 | (InputStr4) |
---|---|---|---|
Gender | Age | Occupation | (Genre) |
Common Rules for the inputs
""
).Gender
F
", "f
", "M
", "m
".""
"F" // Supported
"Female" // X
(nothing) // X (must be replaced by "")
"" // Supported
Age
""
"35" // Supported
"35.5" // X
"-23" // X
"Thirty-five" // X
(nothing) // X (must be replaced by "")
"" // Supported
Occupation
""
"k-12student" // Supported
"K12student" // X (The hyphens must not be omitted.)
"Gradstudent" // Supported
"Grad student" // Supported (Was not supported from Milestone 1)
(nothing) // X (must be replaced by "")
"" // Supported
Genre (When testing with 4 inputs)
|
) here is uesd to link OR conditions, not AND.Adventure|Animation
includes all the movies that are categorized as Adventure OR Animation to candidates for Top 10 movies."Film-noir" // Supported
"Filmnoir" // X (The hyphens must not be omitted.)
Action|Adventure // X (Must be enclosed by pipeline)
"Action|Adventure|" // X (Pipeline should be between words)
"" // The genre must not be left empty.
// Examples of Supported Inputs
“F” “25” “Gradstudent”
“M” “30” “Athletes”
“F” “” “retired”
“” “15” “”
“” “” “”
// Examples of Wrong Inputs
"F" "25" // Empty part must be explicitly specified by ""
"25" "Gradstudent" // Empty part must be explicitly specified by ""
// Examples of Supported Inputs
“F” “25” “Grad student” “Action|Comedy”
“M” “30” “Athletes” “Children’s”
“F” “” “retired” “Animation|Drama|Fantasy”
“” “15” “” “Sci-Fi”
“” “” “” “Romance|Comedy”
// Examples of Wrong Inputs
“F” “25” “Grad student” “” // The genre must not be left empty.
“F” “25” “Grad student” “Action|Comedy” "Drama" // Extra arguments are not allowed.
Possible errors thrown by invalid input.
Error | Message | Description |
---|---|---|
InputNumError |
The input must be in this format : "gender" "age" "occupation" "genre" (genre is optional). | Thrown when the number of argument is not 3 or 4. |
InputInvalidError |
Entered gender input is invalid. | Thrown when the entered gender is invalid. |
InputInvalidError |
Entered age input is invalid. Age must be a natural number. | Thrown when the entered age is invalid. |
InputInvalidError |
Entered occupation (inputString) doesn't exist. | Thrown when the entered occupation is invalid. |
InputInvalidError |
Entered genre input is invalid. | Thrown when the entered genre is invalid. (e.g. Location of pipeline | ) |
InputInvalidError |
Entered genre (inputString) doesn't exist. | Thrown when the entered genre is invalid. |
InputEmptyError |
Genre input hasn't passed. Genre must not be empty | Thrown when the "" is passed for the genre input. |
Error | Message | Description |
---|---|---|
NoDBError |
There are no movie available for more than m votes | Thrown when there's no available movie list. This error is not likely to happen but implemented to prevent any error. |
NoDBError |
There are no movie available for specified inputs. | Thrown when there's no available movie list or there exist movie(s) with no votes only. This error is not likely to happen but implemented to prevent any error. |
1
.% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2
InputNumError: The input must be in this format : "gender" "age" "occupation" "genre" (genre is optional).
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 "Female" "25" "Gradstudent"
InputInvalidError : Entered gender input is invalid.
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 "F" "12.5" "Gradstudent"
InputInvalidError : Entered age input is invalid. Age must be a natural number.
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 "F" "25" "Lizard"
InputInvalidError : Entered occupation (Lizard) doesn't exist.
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 "F" "25" "Gradstudent" "Action|Adventure|"
InputInvalidError : Entered genre input is invalid.
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 "F" "25" "Gradstudent" "ACCCCCTION"
InputInvalidError : Entered genre (accccction) doesn't exist.
% java -cp target/cse364-project-1.0-SNAPSHOT-jar-with-dependencies.jar group11.milestone2 "F" "25" "Gradstudent" ""
InputEmptyError : Genre input hasn't passed. Genre must not be empty
The JaCoCO plugin (ver : 0.8.2
) is used for this JUnit Test to generate the code coverage report.
The Code coverage goal for this project has been set to 0.9
(90%).
The code coverage report index.html
can be found in target/site/jacoco/
directory and viewed with chrome or other extensions.
Area | Contribution |
---|---|
Java Implementation | Models and Data Structures 👑 Yeongjun Kwak Exception Handling 👑 Sanghun Lee, Yeongjun Kwak Unit Test Building 👑 Yujin Lee |
Documentation | README.md 👑 Yujin Lee |
Goal :
- Implement RESTful web service
- Movies Recommendation Feature based on the Movie title (and limit).
On Milestone 3, the new feature has added to provide movies recommendation from the Movie title input.
The code returns the input-specified numbers(limit
, default = 10) of movies for the specified movie title.
The algorithm is built based on the two concepts below : 1) Item-based Collaborative Filtering 2) Genre-based Recommendation
Collaborative Filtering recommends movies by calculating the similarity between the specified movie (input) and the others. Collaborative Filtering are subdivided to two methods ; User-based and Item-based. ([reference](Recommender Systems — User-Based and Item-Based Collaborative Filtering))
This program uses Item-based Collaborative Filtering. i.e. if a user group who highly rated Movie A have rated Movie B highly, the Movie A and Movie B are considered to be similar.
First, to measure the similarity between movies, Pearson correlation coefficient has used.
The details for Pearson correlation coefficient can be found here.
The formula to get Pearson correlation coefficient is as below :
The method in program (milestone3.java
) that implements the Pearson correlation coefficient is as below :
static double get_pearson_similarity(HashMap<String, Integer> rating, HashMap<String, Integer> rating_of_input, double mean_rating_of_input, double distance_of_input)
After getting the similarity between movies by Pearson correlation coefficient, the movies are sorted by decreasing similarity order.
When the sorting has finished, the program adds (1.5 * limit) numbers of items from this list to ArrayList<Movie_data_node> movie_data_table
.
(If the input was "Superman (1978)", it excludes the same movie when adding as the same movie as input should be excluded in the recommendation result.)
After then, the program calculates the Weighted Rating by adding Pearson correlation coefficient and IMDB Weighted Rating. (The IMDB weighted rating here is same from milestone2.)
W = (vR+mC)/(v+m)
Variables | Explanation |
---|---|
W | Weighted rating |
v | Total number of ratings for the movie = (votes) |
m | Minimum number of ratings required to be listed in the Top 10 |
R | Average rating for the movie as a number from 0 to 5 (mean) |
C | Average rating across all the movies |
The reason of adding Pearson correlation coefficient and IMDB Weighted Rating is that it can give more weight on the movies with higher similarity.
For example, when the input is "Superman (1978)
, the movies "Superman II (1980)" and "Superman III (1983)" get to have high similarity with the input from the method above.
However, these movies have comparably low average rating (from users). To give more weight on these movies (high similarity but low rating), Pearson correlation coefficient and IMDB Weighted Rating has added.
The value of v
and R
above can be easily calculated from Movie_data_node
.
And the value of m
and C
can be calculated from the methods each below :
static int percentile(ArrayList<Movie_data_node> movie_rating_matrix, double p)
static double total_average_rating(ArrayList<Movie_data_node> movie_rating_matrix)
The two methods above are imported from the milestone2.
And the value of p
in Percentile
method is set to 0 (zero) here. (If p > 0, the movies with high similarity can be ignored)
Lastly, the classified_table
(ArrayList) are made by selecting the items with more than m
vote counts from movie_data_table
.
And then, the program sorts the list with decreasing Weighted Rating value and prints out the upper limit
number of movies.
The Genre-based Recommendation has implemented to complement the weakness of Item-based Collaborative Filtering. The weaknesses of Item-based Collaborative Filtering are :
In these cases, the recommendation output is not reliable or cannot be calculated. To complement this weaknesses, when the number of ratings for the movie input is less than 100, Genre-based recommendation is used.
Genre-based recommendation generates movie recommendation by calculating the similarity between the genre(s) of input movie's and others'.
First, To measure the similarity, the algorithm uses Jaccard similarity.
The formula to get Jaccard similarity is as below :
The method in program (milestone3.java) that implements the Pearson correlation coefficient is as below :
static double get_jaccard_similarity(ArrayList<String> movie_data ,ArrayList<String> genre_of_input_list)
After getting the similarity between movies by Jaccard similarity, the movies are sorted by decreasing similarity order. On here, there's 3 cases regarding the similarity and number of movies to recommend (limit).
ArrayList<Movie_data_node> movie_data_table
.
In this case, the length of List is bigger than (limit*1.5) as the movies with similarity A are also added.ArrayList<Movie_data_node> movie_data_table
.
In this case, the length of List is bigger than (limit) and smaller than (limit1.5) as the movies with similarity B are also added.ArrayList<Movie_data_node> movie_data_table
.
Calculate the IMDB weighted rating for the movies with zero similarity and Add (limit - listlength) number of movies to movie_data_table
.
The same movie with the movie input is excluded for the recommendation when adding movies to movie_data_table
.After then, the program calculates the Weighted Rating (in IMDB weighted rating way)
The value of p
here in Percentile
method is calculated from the method below :
static double get_ratio(int a, int b)
Lastly, the classified_table
(ArrayList) are made by selecting the items with more than m
vote counts from movie_data_table
.
And then, the program sorts the list with decreasing Weighted Rating value and prints out the upper limit
number of movies.
When the Item-based collaborative filtering is used,
the program sorts the movies in decreasing similarity order and rank the 1 ~ (limit*1.5)th movies with altered IMDB weighted rating.
However, this rank gets differ greatly depends on the size of limit
.
limit
is small enough (e.g. limit
is 10 or 20)
The dataset that is used for ranking has high similarity, making the output (recommended movies) having high similarity.limit
is too big (e.g. limit
is 1000)
The similarity of the output gets low but the movies with high ratings get priority for the recommendation.
i.e. it's hard to find the movies with high similarity among the highly placed movies in output.If there's movie A and movie B, as limit
gets bigger and bigger, the highly placed movies in output gets similar.
Continued from Installation steps.
./mvnw spring-boot:run
root@containerID:~/project# ./mvnw spring-boot:run
// sample command
curl -X GET 'http://localhost:8080/movies/recommendations' \
-H 'Content-type: application/json' \
-d '{ "title": "Toy Story (1995)", "limit": 3 }'
To access the docker that is running on #1,
On another terminal, use docker ps
to get the running container's ID and
type docker exec -it (containerID) (your_own_bash_command)
.
i.e. you can put the curl command on the your_own_bash_command
field above.
When valid inputs are passed, the output message will look like this :
[ {
"title" : "Toy Story 2 (1999)",
"genre" : "Animation|Children's|Comedy",
"imdb" : "http://www.imdb.com/title/tt0120363"
}, {
"title" : "Bug's Life, A (1998)",
"genre" : "Animation|Children's|Comedy",
"imdb" : "http://www.imdb.com/title/tt0120623"
}, {
"title" : "Beauty and the Beast (1991)",
"genre" : "Animation|Children's|Musical",
"imdb" : "http://www.imdb.com/title/tt0101414"
} ]
Movie recommendation based on gender / age / occupation / genre
Below is curl command example for GET requests passing the user input in JSON type Test with different json body parts as your need.
// Input
curl -X GET 'http://localhost:8080/users/recommendations' \
-H 'Content-type: application/json' \
-d '{"gender":"F", "age":"25", "occupation":"Grad student", "genre":"Action"}'
// Output - Top 10 movies are returned.
[ {
"title" : "Princess Bride, The (1987)",
"genre" : "action|adventure|comedy|romance",
"imdb" : "http://www.imdb.com/title/tt0093779"
}, {
"title" : "Matrix, The (1999)",
"genre" : "action|sci-fi|thriller",
"imdb" : "http://www.imdb.com/title/tt0133093"
}, {
"title" : "Raiders of the Lost Ark (1981)",
"genre" : "action|adventure",
"imdb" : "http://www.imdb.com/title/tt0082971"
},
...
Movie recommendation based on the movie title / limit
Below is curl command example for GET requests passing the movie input in JSON type Test with different json body parts as your need.
// Input
curl -X GET 'http://localhost:8080/movies/recommendations' \
-H 'Content-type: application/json' \
-d '{ "title": "Toy Story (1995)", "limit": 3 }'
// Output - (limit) number of movies are returned.
// (when limit is not specified, 10 movies are returned.)
[ {
"title" : "Toy Story 2 (1999)",
"genre" : "Animation|Children's|Comedy",
"imdb" : "http://www.imdb.com/title/tt0120363"
}, {
"title" : "Bug's Life, A (1998)",
"genre" : "Animation|Children's|Comedy",
"imdb" : "http://www.imdb.com/title/tt0120623"
}, {
"title" : "Beauty and the Beast (1991)",
"genre" : "Animation|Children's|Musical",
"imdb" : "http://www.imdb.com/title/tt0101414"
} ]%
The field name must match exactly to "gender", "age", "occupation", "genre" and should be in the lower-case.
For the gender, age, occupation, and genre inputs, the same rules from Milestone2 are applied here as well.
However, each of the fields can be left empty.
When the field(s) are missing OR the wrong field name has passed, for that field, the web service makes a get request with default value ""
.
Please note that genre(singular) is used, not genres (plurar).
Examples
// Example 1 - Field name wrong.
// "" "25" "Grad" "Action" is passed to program instead.
{
"Gender": "F",
"age": "25",
"occupation": "Grad",
"genre": "Action"
}
// Example 2 - Missing field.
// "" "" "" "" is passed to program instead.
{
}
// Example 3 - It should be genre, not genres.
// "F" "25" "Grad" "" is passed to program instead.
{
"gender": "F",
"age": "25",
"occupation": "Grad",
"genres": "Action"
}
The field name must match exactly to "title", "limit" and should be in the lower-case.
For the title, the title should be the existing name in the movies.dat
.
For the limit, it should be int value with 0 < limit <= 2000
However, each of the fields can be left empty.
When the field(s) are missing OR the wrong field name has passed, for that field, the web service makes a get request with default value ""
.
Examples
// Example 1 - Field name wrong.
// This is invalid input.
{
"Title": "Toy Story (1995)",
"limit": -5
}
// Example 2 - Missing field.
// "Toy Story (1995)" "" is passed to program instead.
{
"title": "Toy Story (1995)"
}
Possible errors thrown by invalid json body input.
When invalid input is put, the web service returns the error message (json body) with Http Status code 400
(Bad Request)
Input (json body)
{
"gender": "ABCD",
"age": "EFG",
"occupation": "HIJK",
"genre": "LMN|OP"
}
Output (json body) - Status code 400 Bad Request
{
"error": "InputInvalidError",
"message": [
"Entered gender input (ABCD) is invalid.",
" Entered age input (EFG) is invalid.",
" Entered occupation input (HIJK) is invalid.",
" Entered genre input (LMN|OP) is invalid."
]
}
Input (json body)
{
"title": "Toy Story",
"limit": -5
}
Output (json body) - Status code 400 Bad Request
{
"error": "InputInvalidError",
"message": [
"Entered title input (Toy Story) is invalid.",
" Entered limit input (-5) is invalid."
]
}
The JaCoCO plugin (ver : 0.8.2
) is used for this JUnit Test to generate the code coverage report.
The Code coverage goal for this project has been set to 0.9
(90%).
The code coverage report index.html
can be found in target/site/jacoco/
directory and viewed with chrome or other extensions.
(Below example is from Milestone 2)
Area | Contribution |
---|---|
Java Implementation | Models and Data Structures 👑 Yeongjun Kwak Exception Handling 👑 Sanghun Lee, Yeongjun Kwak Unit Test Building 👑 Yujin Lee |
REST service Implementation & Dependancy management | 👑 Yujin Lee |
Documentation | README.md 👑 Yujin Lee |
This part contains User Documentation denoted for regular end-users and is focused on endpoints for those users.
AnOtterMovie is a Robust, Scalable, and user-centered movie recommendation engine and a user can get movie recommendation results by putting his demographic profile (gender, age, occupation, and genre preference) or movie metadata (movie title).
AnOtterMovie is based on Microservice architeture, which is an architectural style that structures an application as a collection of services that are. (Microservices - Wikipedia)
The detailed system architecture is as above, and
are used respectively.
dockerfile
, run.sh
, and *.war file
in the same directory. dockerfile
, run.sh
and *.war file
can be downloaded from here.$ docker build -t image_name /location/of/dockerfile
$ docker run -it -p 8080:8080 image_name bash
. run.sh
root@containerID:~/project# . run.sh
$ docker build -t image_name /location/of/dockerfile
$ docker run -d -p 8080:8080 image_name
After the installation, to use a service, either 1) URL (Website) or 2) CURL Command can be used.
In this documentation, the method using URL (Website) will be explicitly guided (as this documentation is for general users).
Depending on the Installation steps you took above
If you see the main page as above, you successfully finished your installation steps.
You are able to toggle between User-based recommendtation and Movie-based recommendtation by using the User-based button and Movie-based button below the logo.
For User-based recommendation, there are shown 4 fields ; Gender, Age, Occupation, Genre.
Those 4 fields are all not required to fill in.
For Movie-based recommendation, there are shown 2 fields ; Title, Limit.
Title field is required to fill in, and Limit isn't (Limit will set to 10 when not specified).
Then next, press the Submit button.
If you typed wrong input (or didn't fill in the title for Movie-based), you will get error messages via tooltip or alert as can be seen above.
On the Result pages, you are also allowed to make another request using the fields on the header.
For User-based recommendation, you will get recommendation of 10 movies as can be seen above.
For Movie-based recommendation, you will get recommendation of Limit (if not specified, 10) movies as can be seen above.
The system might take a bit of time when there are much data to process (especially when inputs are not specified in User-based mode).
When the system is under the process, you will see an awesome-otter-spinning-loader, so please take your time :)