1 Commits
Author SHA1 Message Date
neda 253afe8097 3oop 2026-07-19 05:33:55 +03:30
5 changed files with 398 additions and 127 deletions
+53 -28
View File
@@ -121,40 +121,64 @@ Understanding: You must be able to explain your implementation
## Bonus Tasks ✒️ ## Bonus Tasks ✒️
1. Fetch and display movie information using movie ID 1. Fetch and display movie information using movie ID
Implement movie search by ID. User enters an ID, program displays complete movie details. 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.
### ⚠️ First: Add Missing Fields to Movie Class Movie Class Fields (already defined):
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`
### Implementation Steps: - id (Long) - Movie identifier
1. **Complete `getMovieById(movieId)`** - title (String) - Movie title
- Build request to: `https://api.meshcomp.ir/api/v1/movies/{movieId}`
- If status 200 → return JSON body, else → return null
2. **Complete `displayMovieDetails(movieId)`** - year (String) - Release year
- Call `getMovieById()` → check for null
- Use Gson to parse JSON to Movie object (after adding fields above)
- Print formatted output (see example below)
### Example Output: - genres (List<Genre>) - List of genres
```
======================================================================= - images (String) - Poster image URL
THE SHAWSHANK REDEMPTION (1994)
======================================================================= - country (String) - Production country
Rating: 9.3/10 | Votes: 1,738,596
Director: Frank Darabont - imdbRating (String) - IMDB rating
Cast: Tim Robbins, Morgan Freeman, Bob Gunton, William Sadler
Genre: Crime, Drama Implementation Steps:
Runtime: 142 min | Rated: R
Country: USA | Released: 14 Oct 1994 - Build and Send Request (getMovieById method):
Plot: Two imprisoned men bond over a number of years, finding
solace and eventual redemption through acts of common decency. - Create HTTP request to: https://api.meshcomp.ir/api/v1/movies/{movieId}
Awards: Nominated for 7 Oscars. Another 19 wins & 30 nominations.
======================================================================= - 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
```
--- ---
## References 📚 ## References 📚
@@ -178,3 +202,4 @@ Jackson Tutorial:
--- ---
## Submission ⌛ ## Submission ⌛
Deadline: May 1st (11 Ordibehesht) Deadline: May 1st (11 Ordibehesht)
+24 -23
View File
@@ -51,45 +51,46 @@ public class Rational {
return r1.add(r2); return r1.add(r2);
} }
// TODO: Instance method - this - other
// Formula: a/b - c/d = (a*d - c*b) / (b*d)
public Rational subtract(Rational other) { public Rational subtract(Rational other) {
// YOUR CODE HERE int newNumerator = this.numerator * other.denominator
return null; // Remove this line when implemented - other.numerator * this.denominator;
int newDenominator = this.denominator * other.denominator;
return new Rational(newNumerator, newDenominator);
} }
// TODO: Static method - r1 - r2
public static Rational subtract(Rational r1, Rational 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) { public Rational multiply(Rational other) {
// YOUR CODE HERE int newNumerator = this.numerator * other.numerator;
return null; // Remove this line when implemented int newDenominator = this.denominator * other.denominator;
return new Rational(newNumerator, newDenominator);
} }
// TODO: Static method - r1 * r2
public static Rational multiply(Rational r1, Rational 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) { public Rational divide(Rational other) {
// YOUR CODE HERE
// HINT: Division is multiplication by reciprocal if (other.numerator == 0) {
// Don't forget to check if other.numerator is zero! throw new ArithmeticException("Cannot divide by zero");
return null; // Remove this line when implemented }
int newNumerator = this.numerator * other.denominator;
int newDenominator = this.denominator * other.numerator;
return new Rational(newNumerator, newDenominator);
} }
// TODO: Static method - r1 / r2
public static Rational divide(Rational r1, Rational 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 // PROVIDED - String representation
+19 -2
View File
@@ -21,17 +21,34 @@ public class Main {
break; break;
case 2: case 2:
// TODO: Get genre ID and page from user, then call movieService.displayMoviesByGenre()
Long genreId =
getLongInput("Enter genre ID: ");
Long page =
getLongInput("Enter page number: ");
movieService.displayMoviesByGenre(
genreId,
page
);
break; break;
case 3: case 3:
// TODO (BONUS): Get movie ID from user, then call movieService.displayMovieDetails()
Long movieId =
getLongInput("Enter movie ID: ");
movieService.displayMovieDetails(movieId);
break; break;
case 0: case 0:
running = false; running = false;
System.out.println("Goodbye!"); System.out.println("Goodbye!");
+100 -10
View File
@@ -2,23 +2,113 @@ package movie.apis;
import java.util.List; import java.util.List;
/**
* Model class representing a movie
* Fields: id, title, genres, images
*/
public class Movie { public class Movie {
private Long id; private Long id;
private String title; private String title;
private List<String> genres; private List<Genre> genres;
private List<String> images; private String images;
private String year; private String year;
private String imdb_rating; private String imdbRating;
private String country; private String country;
// TODO: Create a constructor with all fields
// TODO: Create a simple constructor with id and title only public Movie(Long id, String title, List<Genre> genres,
String images, String year,
String imdbRating, String country) {
// TODO: Create getters and setters for all fields this.id = id;
this.title = title;
this.genres = genres;
this.images = images;
this.year = year;
this.imdbRating = imdbRating;
this.country = country;
}
public Movie(Long id, String title) {
this.id = id;
this.title = title;
}
public Movie() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<Genre> getGenres() {
return genres;
}
public void setGenres(List<Genre> genres) {
this.genres = genres;
}
public String getImages() {
return images;
}
public void setImages(String images) {
this.images = images;
}
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getImdbRating() {
return imdbRating;
}
public void setImdbRating(String imdbRating) {
this.imdbRating = imdbRating;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString() {
return id + ". " + title + " (" + year + ")";
}
} }
+199 -61
View File
@@ -61,7 +61,6 @@ public class MovieService {
} }
public void displayGenres() { public void displayGenres() {
String jsonResponse = getGenresList(); String jsonResponse = getGenresList();
@@ -73,7 +72,8 @@ public class MovieService {
try { try {
JsonObject rootObject = JsonParser.parseString(jsonResponse).getAsJsonObject(); JsonObject rootObject = JsonParser.parseString(jsonResponse).getAsJsonObject();
JsonArray genresArray = rootObject.getAsJsonArray("genres"); JsonArray genresArray = rootObject.getAsJsonArray("genres");
Type genreListType = new TypeToken<ArrayList<Genre>>(){}.getType(); Type genreListType = new TypeToken<ArrayList<Genre>>() {
}.getType();
Gson gson = new Gson(); Gson gson = new Gson();
List<Genre> genres = gson.fromJson(genresArray, genreListType); List<Genre> genres = gson.fromJson(genresArray, genreListType);
@@ -89,27 +89,86 @@ public class MovieService {
/** /**
* TODO 1: Display movies for a specific genre and page * TODO 1: Display movies for a specific genre and page
* * <p>
* Open this link in your browser (and check Pretty-print checkbox) to view json format: * JSON format: { "movies": [ { "id": 1, "title": "Movie", "year": "1994" } ], "total": 177, "total_pages": 18 }
* https://api.meshcomp.ir/api/v1/genres/1/movies * <p>
*
* Steps: * Steps:
* - Call getMoviesByGenreList(genreId, page) to get JSON * - Call getMoviesByGenreList(genreId, page) to get JSON
* - Parse JSON to JsonObject * - Parse JSON to JsonObject
* - Get "movies" array (NOT "data") * - Get "movies" array (NOT "data")
* - Loop through array and print: "ID: {id} | {title} ({year})" * - Loop through array and print: "ID: {id} | {title} ({year})"
* - Also print total and total_pages * - Also print total and total_pages
* * <p>
* PUT ALL PARSING CODE INSIDE try-catch * PUT ALL PARSING CODE INSIDE try-catch
*/ */
public void displayMoviesByGenre(Long genreId, Long page) { public void displayMoviesByGenre(Long genreId, Long page) {
// TODO: Write your code here
// All parsing code must be inside try-catch String jsonResponse = getMoviesByGenreList(genreId, page);
if (jsonResponse == null) {
System.out.println("Failed to get movies");
return;
}
try { try {
// Your code here
JsonObject rootObject =
JsonParser.parseString(jsonResponse)
.getAsJsonObject();
JsonArray moviesArray =
rootObject.getAsJsonArray("movies");
System.out.println("\nMOVIES:");
for (JsonElement element : moviesArray) {
JsonObject movie =
element.getAsJsonObject();
Long id =
movie.get("id").getAsLong();
String title =
movie.get("title").getAsString();
String year =
movie.has("year")
? movie.get("year").getAsString()
: "Unknown";
System.out.println(
"ID: " + id +
" | " + title +
" (" + year + ")"
);
}
System.out.println(
"\nTotal movies: "
+ rootObject.get("total").getAsInt()
);
System.out.println(
"Total pages: "
+ rootObject.get("total_pages").getAsInt()
);
} catch (Exception e) { } catch (Exception e) {
System.err.println("ERROR: " + e.getMessage());
System.err.println(
"ERROR: " + e.getMessage()
);
} }
} }
@@ -119,74 +178,153 @@ public class MovieService {
* URL format: https://api.meshcomp.ir/api/v1/movies/{movieId} * URL format: https://api.meshcomp.ir/api/v1/movies/{movieId}
*/ */
private String getMovieById(Long movieId) { 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();
return null; try {
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(
"HTTP error: "
+ response.statusCode()
);
}
} catch (Exception e) { } catch (Exception e) {
System.out.println("!!Exception : " + e.getMessage());
System.out.println(
"!!Exception : "
+ e.getMessage()
);
} }
return null; return null;
} }
/* /**
BONUS TODO: Display complete movie details for a given movie ID * BONUS TODO: Display complete movie details for a given movie ID
* <p>
Open this link in your browser (and check Pretty-print checkbox) to view json format: * Expected JSON format from getMovieById():
https://api.meshcomp.ir/api/v1/movies/1 * {
* "id": 1,
INSTRUCTIONS: * "title": "The Shawshank Redemption",
1. Call getMovieById(movieId) to get the JSON response string * "year": "1994",
2. Check if response is null (if yes, print error and return) * "genres": ["Crime", "Drama"],
3. Parse the JSON string to JsonObject (inside try-catch) * "poster": "https://moviesapi.ir/images/tt0111161_poster.jpg",
4. Use Gson to extract all fields from the JSON and map them to your Movie class: * "country": "USA",
- Add missing JSON fields to your Movie class first (actors, awards, director, * "imdb_rating": "9.3"
imdb_id, imdb_votes, metascore, plot, rated, released, runtime, type, writer) * }
- Then use Gson to parse your json string * <p>
5. Print all movie details in a readable format * INSTRUCTIONS:
* 1. Call getMovieById(movieId) to get the JSON response
(PUT ALL PARSING CODE INSIDE THE EXISTING try-catch) * 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
* <p>
* PUT ALL PARSING CODE INSIDE THE EXISTING try-catch
*
* @param movieId The ID of the movie to display
*/ */
/* 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) { public void displayMovieDetails(Long movieId) {
// Step 1: Get JSON response from API // Step 1: Get JSON response from API
String jsonResponse = getMovieById(movieId); String jsonResponse = getMovieById(movieId);
// Step 2: Check if we got valid data // 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) { if (jsonResponse == null) {
System.out.println("Failed to get movie details for ID: " + movieId); System.out.println("Failed to get movie details for ID: " + movieId);
return; return;
} }
// Step 3-6: Parse JSON and display details (PUT YOUR CODE INSIDE try-catch)
try { try {
// TODO: Parse jsonResponse to JsonObject
// HINT: Use JsonParser.parseString(jsonResponse).getAsJsonObject() JsonObject movie =
// TODO: use Gson to parse the json JsonParser.parseString(jsonResponse)
// Your code here: .getAsJsonObject();
Long id =
movie.get("id").getAsLong();
String title =
movie.get("title").getAsString();
String year =
movie.get("year").getAsString();
String poster =
movie.get("poster").getAsString();
String country =
movie.get("country").getAsString();
String rating =
movie.get("imdb_rating").getAsString();
JsonArray genres =
movie.getAsJsonArray("genres");
StringBuilder genreText =
new StringBuilder();
for (JsonElement g : genres) {
if (genreText.length() > 0)
genreText.append(", ");
genreText.append(g.getAsString());
}
System.out.println("\n========== MOVIE DETAILS ==========");
System.out.println("ID: " + id);
System.out.println("Title: " + title);
System.out.println("Year: " + year);
System.out.println("Genres: " + genreText);
System.out.println("Poster: " + poster);
System.out.println("Country: " + country);
System.out.println("IMDB Rating: " + rating);
System.out.println("===================================");
} catch (Exception e) { } catch (Exception e) {
System.err.println("ERROR parsing movie details: " + e.getMessage());
System.err.println(
"ERROR parsing movie details: "
+ e.getMessage()
);
} }
} }
} }