6 Commits
40 changed files with 96 additions and 421 deletions
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="parallelModelFetch" value="true" />
</component>
</project>
+1
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
+28 -53
View File
@@ -121,64 +121,40 @@ Understanding: You must be able to explain your implementation
## Bonus Tasks ✒️
1. Fetch and display movie information using movie ID
In this section, you must implement the ability to search for a movie by its ID. The user enters an ID, and the program displays complete movie details.
Implement movie search by ID. User enters an ID, program displays complete movie details.
Movie Class Fields (already defined):
### ⚠️ First: Add Missing Fields to Movie Class
The API returns more data than your current class supports. Add these fields:
- `actors`, `awards`, `director`, `imdb_id`, `imdb_votes`, `metascore`, `plot`, `rated`, `released`, `runtime`, `type`, `writer`
- id (Long) - Movie identifier
### Implementation Steps:
- title (String) - Movie title
1. **Complete `getMovieById(movieId)`**
- Build request to: `https://api.meshcomp.ir/api/v1/movies/{movieId}`
- If status 200 → return JSON body, else → return null
- year (String) - Release year
2. **Complete `displayMovieDetails(movieId)`**
- Call `getMovieById()` → check for null
- Use Gson to parse JSON to Movie object (after adding fields above)
- Print formatted output (see example below)
- genres (List<Genre>) - List of genres
- images (String) - Poster image URL
- country (String) - Production country
- imdbRating (String) - IMDB rating
Implementation Steps:
- Build and Send Request (getMovieById method):
- Create HTTP request to: https://api.meshcomp.ir/api/v1/movies/{movieId}
- Replace {movieId} with the ID from user
- Send request and get response
- Handle Response (getMovieById method):
- If status code is 200, return JSON body
- Otherwise, print error and return null
- Parse JSON and Create Movie Object (displayMovieDetails method):
- Parse JSON response to JsonObject
- Extract all fields: id, title, year, poster, country, imdb_rating
- Parse "genres" array and convert each to Genre object
- Create a Movie object with all extracted data
- Display Results (displayMovieDetails method):
- Print all movie details in a clean format
2. Advanced search (title, genre, year, rating, etc.)
3. Sorting options for movies
4. Save/load favorite movies to/from a file
5. Improved console menu design
6. GUI version using JavaFX
### Example Output:
```
=======================================================================
THE SHAWSHANK REDEMPTION (1994)
=======================================================================
Rating: 9.3/10 | Votes: 1,738,596
Director: Frank Darabont
Cast: Tim Robbins, Morgan Freeman, Bob Gunton, William Sadler
Genre: Crime, Drama
Runtime: 142 min | Rated: R
Country: USA | Released: 14 Oct 1994
Plot: Two imprisoned men bond over a number of years, finding
solace and eventual redemption through acts of common decency.
Awards: Nominated for 7 Oscars. Another 19 wins & 30 nominations.
=======================================================================
```
---
## References 📚
@@ -202,4 +178,3 @@ Jackson Tutorial:
---
## Submission ⌛
Deadline: May 1st (11 Ordibehesht)
-10
View File
@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/HW-03-oop-and-api.iml" filepath="$PROJECT_DIR$/HW-03-oop-and-api.iml" />
</modules>
</component>
</project>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>
-10
View File
@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Rational.iml" filepath="$PROJECT_DIR$/Rational.iml" />
</modules>
</component>
</project>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
</component>
</project>
+12 -16
View File
@@ -52,48 +52,44 @@ public class Rational {
}
// TODO: Instance method - this - other
// Formula: a/b - c/d = (a*d - c*b) / (b*d)
public Rational subtract(Rational other) {
// YOUR CODE HERE
Rational r= new Rational(this.numerator, this.denominator);
other.numerator=-other.numerator;
return add(r, other);
return null; // Remove this line when implemented
}
// TODO: Static method - r1 - r2
public static Rational subtract(Rational r1, Rational r2) {
// YOUR CODE HERE
return r1.subtract(r2);
return null; // Remove this line when implemented
}
// TODO: Instance method - this * other
// Formula: (a/b) * (c/d) = (a*c) / (b*d)
public Rational multiply(Rational other) {
// YOUR CODE HERE
int newNumerator= this.numerator*other.numerator;
int newDenominator= this.denominator*other.denominator;
return new Rational(newNumerator, newDenominator);
return null; // Remove this line when implemented
}
// TODO: Static method - r1 * r2
public static Rational multiply(Rational r1, Rational r2) {
// YOUR CODE HERE
return r1.multiply(r2);
return null; // Remove this line when implemented
}
// TODO: Instance method - this / other
// Formula: (a/b) ÷ (c/d) = (a*d) / (b*c)
public Rational divide(Rational other) {
if (other.numerator == 0)
throw new IllegalArgumentException("Denominator cannot be zero");
int newNum= other.denominator;
int newDen= other.numerator;
Rational r1=new Rational(newNum, newDen);
Rational r2=new Rational(this.numerator, this.denominator);
return multiply(r2,r1);
// YOUR CODE HERE
// HINT: Division is multiplication by reciprocal
// Don't forget to check if other.numerator is zero!
return null; // Remove this line when implemented
}
// TODO: Static method - r1 / r2
public static Rational divide(Rational r1, Rational r2) {
// YOUR CODE HERE
return r1.divide(r2);
return null; // Remove this line when implemented
}
// PROVIDED - String representation
@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Rational.iml" filepath="$PROJECT_DIR$/Rational.iml" />
</modules>
</component>
</project>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
</component>
</project>
-10
View File
@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
-1
View File
@@ -1 +0,0 @@
MovieService.java
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="parallelModelFetch" value="true" />
</component>
</project>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/movie.iml" filepath="$PROJECT_DIR$/movie.iml" />
</modules>
</component>
</project>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
</component>
</project>
+1 -10
View File
@@ -9,7 +9,6 @@ public class Main {
public static void main(String[] args) {
System.out.println("\n=== MOVIE API CLIENT ===\n");
Scanner in = new Scanner(System.in);
boolean running = true;
while (running) {
@@ -23,21 +22,13 @@ public class Main {
case 2:
// TODO: Get genre ID and page from user, then call movieService.displayMoviesByGenre()
System.out.println("Enter genre ID:");
long genreID= in.nextLong();
System.out.println("Enter page:");
long page= in.nextLong();
movieService.displayMoviesByGenre(genreID, page);
break;
case 3:
// TODO (BONUS): Get movie ID from user, then call movieService.displayMovieDetails()
System.out.println("Enter genre ID:");
long ID= in.nextLong();
movieService.displayMovieDetails(ID);
break;
+3 -46
View File
@@ -10,58 +10,15 @@ public class Movie {
private Long id;
private String title;
private List<Genre> genres;
private String images;
private List<String> genres;
private List<String> images;
private String year;
private String imdbRating;
private String imdb_rating;
private String country;
// TODO: Create a constructor with all fields
public Movie(long id, String title, List<Genre> genres, String images, String year,String imdbRating, String country)
{
this.id=id;
this.country=country;
this.genres=genres;
this.images=images;
this.year=year;
this.title=title;
this.imdbRating=imdbRating;
}
// TODO: Create a simple constructor with id and title only
public Movie(long id, String title)
{
this.id=id;
this.title=title;
}
// TODO: Create getters and setters for all fields
public Long getId() {
return id;
}
public String getCountry() {
return country;
}
public String getImages() {
return images;
}
public String getImdbRating() {
return imdbRating;
}
public String getTitle() {
return title;
}
public String getYear() {
return year;
}
public List<Genre> getGenres() {
return genres;
}
}
+48 -63
View File
@@ -90,7 +90,8 @@ public class MovieService {
/**
* TODO 1: Display movies for a specific genre and page
*
* JSON format: { "movies": [ { "id": 1, "title": "Movie", "year": "1994" } ], "total": 177, "total_pages": 18 }
* Open this link in your browser (and check Pretty-print checkbox) to view json format:
* https://api.meshcomp.ir/api/v1/genres/1/movies
*
* Steps:
* - Call getMoviesByGenreList(genreId, page) to get JSON
@@ -105,12 +106,7 @@ public class MovieService {
// TODO: Write your code here
// All parsing code must be inside try-catch
try {
String json= getMoviesByGenreList(genreId, page);
if (json==null)
{
System.out.println("Failed to get movie details for ID: " + genreId);
return;
}
// Your code here
} catch (Exception e) {
System.err.println("ERROR: " + e.getMessage());
@@ -125,81 +121,70 @@ public class MovieService {
private String getMovieById(Long movieId) {
try {
// TODO: Complete this method
String url = MOVIE_BY_ID_URL + movieId;
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200)
return response.body();
else
{
System.out.println("error");
// String url = MOVIE_BY_ID_URL + movieId;
// HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build();
// HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// if (response.statusCode() == 200) return response.body();
return null;
}
} catch (Exception e) {
System.out.println("!!Exception : " + e.getMessage());
}
return null;
}
/**
* BONUS TODO: Display complete movie details for a given movie ID
*
* Expected JSON format from getMovieById():
* {
* "id": 1,
* "title": "The Shawshank Redemption",
* "year": "1994",
* "genres": ["Crime", "Drama"],
* "poster": "https://moviesapi.ir/images/tt0111161_poster.jpg",
* "country": "USA",
* "imdb_rating": "9.3"
* }
*
* INSTRUCTIONS:
* 1. Call getMovieById(movieId) to get the JSON response
* 2. Check if response is null (if yes, print error and return)
* 3. Parse the JSON string to JsonObject (inside try-catch)
* 4. Extract all fields: id, title, year, genres array, poster, country, imdb_rating
* 5. Convert genres array to comma-separated string
* 6. Print all movie details in a readable format
*
* PUT ALL PARSING CODE INSIDE THE EXISTING try-catch
*
* @param movieId The ID of the movie to display
/*
BONUS TODO: Display complete movie details for a given movie ID
Open this link in your browser (and check Pretty-print checkbox) to view json format:
https://api.meshcomp.ir/api/v1/movies/1
INSTRUCTIONS:
1. Call getMovieById(movieId) to get the JSON response string
2. Check if response is null (if yes, print error and return)
3. Parse the JSON string to JsonObject (inside try-catch)
4. Use Gson to extract all fields from the JSON and map them to your Movie class:
- Add missing JSON fields to your Movie class first (actors, awards, director,
imdb_id, imdb_votes, metascore, plot, rated, released, runtime, type, writer)
- Then use Gson to parse your json string
5. Print all movie details in a readable format
(PUT ALL PARSING CODE INSIDE THE EXISTING try-catch)
*/
/* EXAMPLE OUTPUT:
=======================================================================
THE SHAWSHANK REDEMPTION (1994)
=======================================================================
Rating: 9.3/10 | Votes: 1,738,596
Director: Frank Darabont
Cast: Tim Robbins, Morgan Freeman, Bob Gunton, William Sadler
Genre: Crime, Drama
Runtime: 142 min | Rated: R
Country: USA | Released: 14 Oct 1994
Plot: Two imprisoned men bond over a number of years, finding
solace and eventual redemption through acts of common decency.
Awards: Nominated for 7 Oscars. Another 19 wins & 30 nominations.
=======================================================================
*/
public void displayMovieDetails(Long movieId) {
// Step 1: Get JSON response from API
String jsonResponse = getMovieById(movieId);
// Step 2: Check if we got valid data
// Step 3-5: Parse JSON and display details (PUT YOUR CODE INSIDE try-catch)
if (jsonResponse == null) {
System.out.println("Failed to get movie details for ID: " + movieId);
return;
}
// Step 3-6: Parse JSON and display details (PUT YOUR CODE INSIDE try-catch)
try {
// TODO: Parse jsonResponse to JsonObject
JsonObject object= JsonParser.parseString(jsonResponse).getAsJsonObject();
// TODO: Extract id, title, year, genres array, poster, country, imdb_rating
int ID=object.get("id").getAsInt();
String title= object.get("title").getAsString();
String year= object.get("year").getAsString();
String poster= object.get("poster").getAsString();
String country= object.get("country").getAsString();
int imbd= object.get("imbd_rating").getAsInt();
JsonArray genreArray= object.getAsJsonArray("genres");
// TODO: Convert genres array to a readable string
// TODO: Print all movie details
System.out.println("title: "+ title+ "\nyear: "+ year+ "\ncountrey: "+ country+"\nIMBD: "+ imbd+ "\ngenres: ");
for (int i=0; i<genreArray.size(); i++)
{
System.out.print(genreArray.get(i)+" ");
}
// HINT: Use JsonParser.parseString(jsonResponse).getAsJsonObject()
// TODO: use Gson to parse the json
// Your code here:
} catch (Exception e) {
System.err.println("ERROR parsing movie details: " + e.getMessage());
}
@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Rational.iml" filepath="$PROJECT_DIR$/Rational.iml" />
</modules>
</component>
</project>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
</component>
</project>
@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Rational.iml" filepath="$PROJECT_DIR$/Rational.iml" />
</modules>
</component>
</project>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
</component>
</project>
@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="parallelModelFetch" value="true" />
</component>
</project>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/movie.iml" filepath="$PROJECT_DIR$/movie.iml" />
</modules>
</component>
</project>
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../../.." vcs="Git" />
</component>
</project>