diff --git a/pom.xml b/pom.xml
index 83eed8e..111501f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,5 +13,20 @@
23
UTF-8
+
+
+
+ com.google.code.gson
+ gson
+ 2.11.0
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.17.2
+
+
\ No newline at end of file
diff --git a/src/main/java/Rational/RationalTest.java b/src/main/java/Rational/RationalTest.java
new file mode 100644
index 0000000..32df336
--- /dev/null
+++ b/src/main/java/Rational/RationalTest.java
@@ -0,0 +1,108 @@
+package Rational;
+
+public class RationalTest {
+ public static void main(String[] args) {
+ System.out.println("=== Testing Rational Operations ===\n");
+
+ // Create some rational numbers
+ Rational r1 = new Rational(1, 2); // 1/2
+ Rational r2 = new Rational(1, 3); // 1/3
+ Rational r3 = new Rational(3, 4); // 3/4
+ Rational r4 = new Rational(2, 5); // 2/5
+ Rational r5 = new Rational(5, 1); // 5 (integer)
+
+ System.out.println("Created rational numbers:");
+ System.out.println("r1 = " + r1);
+ System.out.println("r2 = " + r2);
+ System.out.println("r3 = " + r3);
+ System.out.println("r4 = " + r4);
+ System.out.println("r5 = " + r5);
+ System.out.println();
+
+ // Test ADDITION
+ System.out.println("=== ADDITION ===");
+ System.out.println("Instance method - r1 + r2 = " + r1.add(r2));
+ System.out.println("Static method - Rational.add(r1, r2) = " + Rational.add(r1, r2));
+ System.out.println("Expected: 1/2 + 1/3 = 5/6");
+ System.out.println("Decimal: " + r1.add(r2).toDouble());
+ System.out.println();
+
+ // Test SUBTRACTION
+ System.out.println("=== SUBTRACTION ===");
+ System.out.println("Instance method - r1 - r2 = " + r1.subtract(r2));
+ System.out.println("Static method - Rational.subtract(r1, r2) = " + Rational.subtract(r1, r2));
+ System.out.println("Expected: 1/2 - 1/3 = 1/6");
+ System.out.println("Decimal: " + r1.subtract(r2).toDouble());
+ System.out.println();
+
+ // Test MULTIPLICATION
+ System.out.println("=== MULTIPLICATION ===");
+ System.out.println("Instance method - r1 * r3 = " + r1.multiply(r3));
+ System.out.println("Static method - Rational.multiply(r1, r3) = " + Rational.multiply(r1, r3));
+ System.out.println("Expected: 1/2 * 3/4 = 3/8");
+ System.out.println("Decimal: " + r1.multiply(r3).toDouble());
+ System.out.println();
+
+ // Test DIVISION
+ System.out.println("=== DIVISION ===");
+ System.out.println("Instance method - r1 ÷ r2 = " + r1.divide(r2));
+ System.out.println("Static method - Rational.divide(r1, r2) = " + Rational.divide(r1, r2));
+ System.out.println("Expected: 1/2 ÷ 1/3 = 3/2");
+ System.out.println("Decimal: " + r1.divide(r2).toDouble());
+ System.out.println();
+
+ // Test with negative numbers
+ System.out.println("=== NEGATIVE NUMBERS ===");
+ Rational neg1 = new Rational(-2, 3);
+ Rational neg2 = new Rational(4, -5);
+ System.out.println("neg1 = " + neg1); // Should show -2/3
+ System.out.println("neg2 = " + neg2); // Should show -4/5
+ System.out.println("neg1 + neg2 = " + neg1.add(neg2));
+ System.out.println("-2/3 + -4/5 = (-10/15 + -12/15) = -22/15");
+ System.out.println("neg1 * neg2 = " + neg1.multiply(neg2));
+ System.out.println("(-2/3) * (-4/5) = 8/15");
+ System.out.println();
+
+ // Test simplification
+ System.out.println("=== SIMPLIFICATION ===");
+ Rational r6 = new Rational(6, 8);
+ Rational r7 = new Rational(10, 25);
+ Rational r8 = new Rational(18, -24);
+ System.out.println("6/8 simplified = " + r6);
+ System.out.println("10/25 simplified = " + r7);
+ System.out.println("18/-24 simplified = " + r8);
+ System.out.println();
+
+ // Test chaining operations
+ System.out.println("=== CHAINING OPERATIONS ===");
+ Rational result = r1.add(r2).multiply(r3).divide(r4);
+ System.out.println("((r1 + r2) * r3) ÷ r4 = " + result);
+ System.out.println("((1/2 + 1/3) * 3/4) ÷ 2/5 = (5/6 * 3/4) ÷ 2/5 = (15/24) ÷ 2/5 = 15/24 * 5/2 = 75/48 = 25/16");
+ System.out.println("Decimal: " + result.toDouble());
+ System.out.println();
+
+ // Test integer handling
+ System.out.println("=== INTEGER HANDLING ===");
+ System.out.println("r5 = " + r5); // Should show 5, not 5/1
+ System.out.println("r5 + r1 = " + r5.add(r1));
+ System.out.println("5 + 1/2 = 11/2");
+ System.out.println("r1 * r5 = " + r1.multiply(r5));
+ System.out.println("1/2 * 5 = 5/2");
+ System.out.println();
+
+ // Test exception handling
+ System.out.println("=== EXCEPTION TEST ===");
+ try {
+ Rational invalid = new Rational(1, 0);
+ } catch (IllegalArgumentException e) {
+ System.out.println("Caught exception: " + e.getMessage());
+ }
+
+ try {
+ Rational zero = new Rational(0, 1);
+ Rational divisionByZero = r1.divide(zero);
+ } catch (ArithmeticException e) {
+ System.out.println("Caught division by zero: " + e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/movie/apis/Genre.java b/src/main/java/movie/apis/Genre.java
index b5c94b7..8560f7f 100644
--- a/src/main/java/movie/apis/Genre.java
+++ b/src/main/java/movie/apis/Genre.java
@@ -1,5 +1,35 @@
package movie.apis;
public class Genre {
- //TODO
-}
+ private Long id;
+ private String name;
+
+ public Genre(Long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public Genre() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return id + ". " + name;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/movie/apis/Main.java b/src/main/java/movie/apis/Main.java
index 090334a..babf179 100644
--- a/src/main/java/movie/apis/Main.java
+++ b/src/main/java/movie/apis/Main.java
@@ -1,7 +1,91 @@
package movie.apis;
+import java.util.Scanner;
+
public class Main {
+
+ private static final MovieService movieService = new MovieService();
+ private static final Scanner scanner = new Scanner(System.in);
+
public static void main(String[] args) {
- // TODO: Receive your data from here
+ System.out.println("\n=== MOVIE API CLIENT ===\n");
+
+ boolean running = true;
+ while (running) {
+ displayMenu();
+ int choice = getIntInput("Enter your choice: ");
+
+ switch (choice) {
+ case 1:
+ movieService.displayGenres();
+ break;
+
+ case 2:
+ // TODO: Get genre ID and page from user, then call movieService.displayMoviesByGenre()
+
+ break;
+
+ case 3:
+ // TODO: Get page number from user, then call movieService.displayAllMovies()
+ break;
+
+ case 4:
+ // TODO (BONUS): Get movie ID from user, then call movieService.displayMovieDetails()
+
+
+ break;
+
+ case 0:
+ running = false;
+ System.out.println("Goodbye!");
+
+ break;
+
+ default:
+ System.out.println("Invalid choice! Please enter 0-4");
+ }
+
+ if (running) {
+ System.out.println("\nPress Enter to continue...");
+ scanner.nextLine();
+ scanner.nextLine();
+ }
+ }
+
+ scanner.close();
}
-}
+
+ private static void displayMenu() {
+ System.out.println("\n================================");
+ System.out.println(" MENU");
+ System.out.println("================================");
+ System.out.println("1. Get all genres");
+ System.out.println("2. Get movies by genre ID");
+ System.out.println("3. Get all movies");
+ System.out.println("4. Get movie details by ID");
+ System.out.println("0. Exit");
+ System.out.println("================================");
+ }
+
+ private static int getIntInput(String prompt) {
+ System.out.print(prompt);
+ while (!scanner.hasNextInt()) {
+ System.out.print("Invalid input. " + prompt);
+ scanner.next();
+ }
+ int input = scanner.nextInt();
+ scanner.nextLine();
+ return input;
+ }
+
+ private static Long getLongInput(String prompt) {
+ System.out.print(prompt);
+ while (!scanner.hasNextLong()) {
+ System.out.print("Invalid input. " + prompt);
+ scanner.next();
+ }
+ Long input = scanner.nextLong();
+ scanner.nextLine();
+ return input;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/movie/apis/Movie.java b/src/main/java/movie/apis/Movie.java
index e7fb1e1..c8cc4e2 100644
--- a/src/main/java/movie/apis/Movie.java
+++ b/src/main/java/movie/apis/Movie.java
@@ -1,5 +1,24 @@
package movie.apis;
+import java.util.List;
+
+/**
+ * Model class representing a movie
+ * Fields: id, title, genres, images
+ */
public class Movie {
- //TODO
-}
+
+ private Long id;
+ private String title;
+ private List genres;
+ private String images;
+ private String year;
+ private String imdbRating;
+ private String country;
+
+ // TODO: Create a constructor with all fields
+
+ // TODO: Create a simple constructor with id and title only
+
+ // TODO: Create getters and setters for all fields
+}
\ No newline at end of file
diff --git a/src/main/java/movie/apis/MovieService.java b/src/main/java/movie/apis/MovieService.java
index da23371..7ceef15 100644
--- a/src/main/java/movie/apis/MovieService.java
+++ b/src/main/java/movie/apis/MovieService.java
@@ -1,25 +1,31 @@
package movie.apis;
+import com.google.gson.*;
+import com.google.gson.reflect.TypeToken;
+
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
+import java.lang.reflect.Type;
import java.util.ArrayList;
+import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
public class MovieService {
- private final static String GENRES_URL = "https://moviesapi.ir/api/v1/genres";
- private static String MOVIES_BY_GENRE_URL = "https://moviesapi.ir/api/v1/genres/";
- private final static String MOVIE_INFO = "https://moviesapi.ir/api/v1/movies/{movie_id}";
+ private final static String GENRES_URL = "https://api.meshcomp.ir/api/v1/genres";
private final static HttpClient client = HttpClient.newHttpClient();
- private ArrayList moviesList;
- private ArrayList genresList;
+ private Map moviesCache = new HashMap<>();
+ private boolean isMoviesLoaded = false;
+ private int totalMovies = 0;
+ private int totalPages = 0;
private String getGenresList() {
try {
-
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(GENRES_URL))
.build();
@@ -40,31 +46,7 @@ public class MovieService {
private String getMoviesByGenreList(Long genreId, Long page) {
try {
-
- MOVIES_BY_GENRE_URL = MOVIES_BY_GENRE_URL + genreId + "/movies?page=" + page;
-
- HttpRequest request = HttpRequest.newBuilder()
- .uri(URI.create(MOVIES_BY_GENRE_URL))
- .build();
-
- HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
-
- if (response.statusCode() == 200) {
- System.out.println("Movies By Genre received successfully");
- return response.body();
- } else {
- throw new IOException("HTTP error code: " + response.statusCode());
- }
- } catch (Exception e) {
- System.out.println("!!Exception : " + e.getMessage());
- }
- return null;
- }
-
- private String getMovieInfo(Long movieId) {
- try {
-
- String url = MOVIE_INFO.replace("{movie_id}", movieId.toString());
+ String url = "https://api.meshcomp.ir/api/v1/genres/" + genreId + "/movies?page=" + page;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
@@ -73,23 +55,150 @@ public class MovieService {
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
- System.out.println("Movie Info received successfully");
return response.body();
} else {
- throw new IOException("HTTP error code: " + response.statusCode());
+ System.out.println("HTTP error code: " + response.statusCode());
+ return null;
}
-
} catch (Exception e) {
System.out.println("!!Exception : " + e.getMessage());
}
-
return null;
}
-// TODO: Write a method that parses the JSON returned by getGenresList() into a list of Genre objects.
-// TODO: Write a method that displays the list of genres.
-// TODO: Write a method whose inputs are genreId and page, and returns a list of movies for that genre and page.
-// TODO: Write a method that displays the genres of a specific movie.
+ public void displayGenres() {
+ String jsonResponse = getGenresList();
+ if (jsonResponse == null) {
+ System.out.println("Failed to get genres");
+ return;
+ }
+
+ try {
+ JsonObject rootObject = JsonParser.parseString(jsonResponse).getAsJsonObject();
+ JsonArray genresArray = rootObject.getAsJsonArray("genres");
+ Type genreListType = new TypeToken>(){}.getType();
+ Gson gson = new Gson();
+ List genres = gson.fromJson(genresArray, genreListType);
+
+ System.out.println("\nALL GENRES:");
+ for (Genre genre : genres) {
+ System.out.println(genre.getId() + ". " + genre.getName());
+ }
+ System.out.println();
+ } catch (Exception e) {
+ System.err.println("ERROR parsing genres: " + e.getMessage());
+ }
+ }
+
+
+ /**
+ * TODO 1: Display movies for a specific genre and page
+ *
+ * JSON format: { "movies": [ { "id": 1, "title": "Movie", "year": "1994" } ], "total": 177, "total_pages": 18 }
+ *
+ * Steps:
+ * - Call getMoviesByGenreList(genreId, page) to get JSON
+ * - Parse JSON to JsonObject
+ * - Get "movies" array (NOT "data")
+ * - Loop through array and print: "ID: {id} | {title} ({year})"
+ * - Also print total and total_pages
+ *
+ * PUT ALL PARSING CODE INSIDE try-catch
+ */
+ public void displayMoviesByGenre(Long genreId, Long page) {
+ // TODO: Write your code here
+ // All parsing code must be inside try-catch
+ try {
+ // Your code here
+
+ } catch (Exception e) {
+ System.err.println("ERROR: " + e.getMessage());
+ }
+ }
+
+
+ /**
+ * TODO 2: Load all movies into cache (called automatically when needed)
+ *
+ * Steps:
+ * - if (isMoviesLoaded) return; (already loaded)
+ * - Clear moviesCache
+ * - Get first page of genre 2 (Drama) to find total_pages
+ * - Loop through all pages (1 to total_pages)
+ * - For each page, get "movies" array
+ * - Extract: id, title, year, poster, genres array
+ * - For genres, loop and convert each string to Genre object
+ * - Store in moviesCache using id as key
+ * - Set isMoviesLoaded = true
+ *
+ * PUT ALL PARSING CODE INSIDE try-catch
+ */
+ private void loadAllMovies() {
+ // TODO: Write your code here
+ // All parsing code must be inside try-catch
+ try {
+ // Your code here
+
+ } catch (Exception e) {
+ System.err.println("ERROR loading movies: " + e.getMessage());
+ }
+ }
+
+
+ /**
+ * TODO 3: Display all movies with pagination
+ *
+ * Steps:
+ * - Call loadAllMovies() first
+ * - Calculate total pages: (totalMovies + 9) / 10
+ * - Validate page number (1 to totalPages)
+ * - Calculate start and end index
+ * - Convert moviesCache.values() to List
+ * - Loop from start to end and display: "ID: {id} | {title} ({year})"
+ *
+ * loadAllMovies() already has try-catch inside
+ */
+ public void displayAllMovies(int page) {
+ // TODO: Write your code here
+ // loadAllMovies() already has try-catch
+ // Your display logic here
+ }
+
+
+ /**
+ * TODO 4 (BONUS): Display movie details by ID
+ *
+ * Steps:
+ * - Call loadAllMovies() first
+ * - Get movie from moviesCache using movieId
+ * - If movie is null, print "Movie not found"
+ * - Otherwise print: ID, Title, Year, Genres, Poster
+ *
+ * loadAllMovies() already has try-catch inside
+ */
+ public void displayMovieDetails(Long movieId) {
+ // TODO: Write your code here (BONUS)
+ // loadAllMovies() already has try-catch
+ // Your display logic here
+ }
+
+ private String getGenresString(List genres) {
+ if (genres == null || genres.isEmpty()) {
+ return "No genres";
+ }
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < genres.size(); i++) {
+ sb.append(genres.get(i).getName());
+ if (i < genres.size() - 1) {
+ sb.append(", ");
+ }
+ }
+ return sb.toString();
+ }
+
+ public int getTotalMovies() {
+ return totalMovies;
+ }
}
\ No newline at end of file