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