Edit
This commit is contained in:
@@ -13,5 +13,20 @@
|
||||
<maven.compiler.target>23</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- GSON: Google JSON parsing library -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson: Another JSON parsing library -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.17.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<Genre> 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
|
||||
}
|
||||
@@ -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<Movie> moviesList;
|
||||
private ArrayList<Genre> genresList;
|
||||
|
||||
private Map<Long, Movie> 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<String> 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<String> 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<ArrayList<Genre>>(){}.getType();
|
||||
Gson gson = new Gson();
|
||||
List<Genre> 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<Genre> 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user