From 7cdb4af4a67341d26f14e4a71f70683cda5107c5 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Tue, 21 Apr 2026 20:11:02 +0330 Subject: [PATCH 01/31] Setup --- HW03/.gitignore | 38 ++++++++++++++++++++++++++++++++++++++ HW03/.idea/.gitignore | 3 +++ HW03/.idea/misc.xml | 14 ++++++++++++++ HW03/.idea/vcs.xml | 6 ++++++ HW03/pom.xml | 17 +++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 HW03/.gitignore create mode 100644 HW03/.idea/.gitignore create mode 100644 HW03/.idea/misc.xml create mode 100644 HW03/.idea/vcs.xml create mode 100644 HW03/pom.xml diff --git a/HW03/.gitignore b/HW03/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/HW03/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/HW03/.idea/.gitignore b/HW03/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/HW03/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/HW03/.idea/misc.xml b/HW03/.idea/misc.xml new file mode 100644 index 0000000..001e756 --- /dev/null +++ b/HW03/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/HW03/.idea/vcs.xml b/HW03/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/HW03/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/HW03/pom.xml b/HW03/pom.xml new file mode 100644 index 0000000..83eed8e --- /dev/null +++ b/HW03/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + org.to + HW03 + 1.0-SNAPSHOT + + + 23 + 23 + UTF-8 + + + \ No newline at end of file From f936064eca442aa167be8a3a80d5fca07126f81a Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Tue, 21 Apr 2026 23:26:30 +0330 Subject: [PATCH 02/31] Move files from HW03 to root directory --- HW03/.gitignore => .gitignore | 0 {HW03/.idea => .idea}/.gitignore | 0 {HW03/.idea => .idea}/misc.xml | 0 {HW03/.idea => .idea}/vcs.xml | 0 HW03/pom.xml => pom.xml | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename HW03/.gitignore => .gitignore (100%) rename {HW03/.idea => .idea}/.gitignore (100%) rename {HW03/.idea => .idea}/misc.xml (100%) rename {HW03/.idea => .idea}/vcs.xml (100%) rename HW03/pom.xml => pom.xml (100%) diff --git a/HW03/.gitignore b/.gitignore similarity index 100% rename from HW03/.gitignore rename to .gitignore diff --git a/HW03/.idea/.gitignore b/.idea/.gitignore similarity index 100% rename from HW03/.idea/.gitignore rename to .idea/.gitignore diff --git a/HW03/.idea/misc.xml b/.idea/misc.xml similarity index 100% rename from HW03/.idea/misc.xml rename to .idea/misc.xml diff --git a/HW03/.idea/vcs.xml b/.idea/vcs.xml similarity index 100% rename from HW03/.idea/vcs.xml rename to .idea/vcs.xml diff --git a/HW03/pom.xml b/pom.xml similarity index 100% rename from HW03/pom.xml rename to pom.xml From 61b14e35b22a6c7befbd77252277295cd8d25987 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Wed, 22 Apr 2026 21:09:21 +0000 Subject: [PATCH 03/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fe8e02b..139597f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# Second-Assignment-Movie-App + From d7712e36a32737b4e62add492e67aac194cf3e87 Mon Sep 17 00:00:00 2001 From: Reyhane Noroozi Date: Thu, 23 Apr 2026 00:40:59 +0330 Subject: [PATCH 04/31] init(entities): register two additional entities for API integration --- src/movie/apis/Movie.java | 5 +++ src/movie/apis/MovieService.java | 70 ++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 src/movie/apis/Movie.java create mode 100644 src/movie/apis/MovieService.java diff --git a/src/movie/apis/Movie.java b/src/movie/apis/Movie.java new file mode 100644 index 0000000..e7fb1e1 --- /dev/null +++ b/src/movie/apis/Movie.java @@ -0,0 +1,5 @@ +package movie.apis; + +public class Movie { + //TODO +} diff --git a/src/movie/apis/MovieService.java b/src/movie/apis/MovieService.java new file mode 100644 index 0000000..0f5015c --- /dev/null +++ b/src/movie/apis/MovieService.java @@ -0,0 +1,70 @@ +package movie.apis; + +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.util.ArrayList; + +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}";//todo fazel + private final static HttpClient client = HttpClient.newHttpClient(); + private ArrayList moviesList; + private ArrayList genresList; + + + private String getGenresList() { + try { + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(GENRES_URL)) + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + if (response.statusCode() == 200) { + System.out.println("Genres List 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 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; + } + +// 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. + +} \ No newline at end of file From 697091e45ebb64eb75e8133549a44f79a8855728 Mon Sep 17 00:00:00 2001 From: Reyhane Noroozi Date: Thu, 23 Apr 2026 00:44:11 +0330 Subject: [PATCH 05/31] init(main): register main and Genre --- src/movie/apis/Genre.java | 5 +++++ src/movie/apis/Main.java | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100644 src/movie/apis/Genre.java create mode 100644 src/movie/apis/Main.java diff --git a/src/movie/apis/Genre.java b/src/movie/apis/Genre.java new file mode 100644 index 0000000..b5c94b7 --- /dev/null +++ b/src/movie/apis/Genre.java @@ -0,0 +1,5 @@ +package movie.apis; + +public class Genre { + //TODO +} diff --git a/src/movie/apis/Main.java b/src/movie/apis/Main.java new file mode 100644 index 0000000..090334a --- /dev/null +++ b/src/movie/apis/Main.java @@ -0,0 +1,7 @@ +package movie.apis; + +public class Main { + public static void main(String[] args) { + // TODO: Receive your data from here + } +} From e3d18097cd5ccc9bf195b81a7da99cd1a755954f Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 01:32:34 +0330 Subject: [PATCH 06/31] add Rational --- .idea/encodings.xml | 7 ++ src/main/java/MathMethods/Rational.java | 108 ++++++++++++++++++ src/{ => main/java}/movie/apis/Genre.java | 0 src/{ => main/java}/movie/apis/Main.java | 0 src/{ => main/java}/movie/apis/Movie.java | 0 .../java}/movie/apis/MovieService.java | 0 6 files changed, 115 insertions(+) create mode 100644 .idea/encodings.xml create mode 100644 src/main/java/MathMethods/Rational.java rename src/{ => main/java}/movie/apis/Genre.java (100%) rename src/{ => main/java}/movie/apis/Main.java (100%) rename src/{ => main/java}/movie/apis/Movie.java (100%) rename src/{ => main/java}/movie/apis/MovieService.java (100%) diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/MathMethods/Rational.java b/src/main/java/MathMethods/Rational.java new file mode 100644 index 0000000..3791373 --- /dev/null +++ b/src/main/java/MathMethods/Rational.java @@ -0,0 +1,108 @@ +package MathMethods; + +public class Rational { + private int numerator; + private int denominator; + + // Constructor + public Rational(int numerator, int denominator) { + if (denominator == 0) { + throw new IllegalArgumentException("Denominator cannot be zero"); + } + this.numerator = numerator; + this.denominator = denominator; + simplify(); + } + + // GCD helper for simplification + private int gcd(int a, int b) { + a = Math.abs(a); + b = Math.abs(b); + while (b != 0) { + int temp = b; + b = a % b; + a = temp; + } + return a; + } + + // Simplify the fraction + private void simplify() { + int gcd = gcd(numerator, denominator); + numerator /= gcd; + denominator /= gcd; + + // Keep denominator positive + if (denominator < 0) { + numerator = -numerator; + denominator = -denominator; + } + } + + // ✅ COMPLETED - Instance method: this + other + public Rational add(Rational other) { + int newNumerator = this.numerator * other.denominator + other.numerator * this.denominator; + int newDenominator = this.denominator * other.denominator; + return new Rational(newNumerator, newDenominator); + } + + // ✅ COMPLETED - Static method: r1 + r2 + public static Rational add(Rational r1, Rational 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) { + // YOUR CODE HERE + return null; // Remove this line when implemented + } + + // TODO: Static method - r1 - r2 + public static Rational subtract(Rational r1, Rational r2) { + // YOUR CODE HERE + 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 + return null; // Remove this line when implemented + } + + // TODO: Static method - r1 * r2 + public static Rational multiply(Rational r1, Rational r2) { + // YOUR CODE HERE + 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) { + // 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 null; // Remove this line when implemented + } + + // ✅ PROVIDED - String representation + @Override + public String toString() { + if (denominator == 1) { + return numerator + ""; + } + return numerator + "/" + denominator; + } + + // ✅ PROVIDED - Decimal value + public double toDouble() { + return (double) numerator / denominator; + } +} diff --git a/src/movie/apis/Genre.java b/src/main/java/movie/apis/Genre.java similarity index 100% rename from src/movie/apis/Genre.java rename to src/main/java/movie/apis/Genre.java diff --git a/src/movie/apis/Main.java b/src/main/java/movie/apis/Main.java similarity index 100% rename from src/movie/apis/Main.java rename to src/main/java/movie/apis/Main.java diff --git a/src/movie/apis/Movie.java b/src/main/java/movie/apis/Movie.java similarity index 100% rename from src/movie/apis/Movie.java rename to src/main/java/movie/apis/Movie.java diff --git a/src/movie/apis/MovieService.java b/src/main/java/movie/apis/MovieService.java similarity index 100% rename from src/movie/apis/MovieService.java rename to src/main/java/movie/apis/MovieService.java From 3f09793bdfad3b76797fd0cd824d2da8f6426495 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 01:44:38 +0330 Subject: [PATCH 07/31] change the package name --- src/main/java/{MathMethods => Rational}/Rational.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/{MathMethods => Rational}/Rational.java (99%) diff --git a/src/main/java/MathMethods/Rational.java b/src/main/java/Rational/Rational.java similarity index 99% rename from src/main/java/MathMethods/Rational.java rename to src/main/java/Rational/Rational.java index 3791373..7fa04fa 100644 --- a/src/main/java/MathMethods/Rational.java +++ b/src/main/java/Rational/Rational.java @@ -1,4 +1,4 @@ -package MathMethods; +package Rational; public class Rational { private int numerator; From 5704749daeaa3791927eafded86d26302231bbb8 Mon Sep 17 00:00:00 2001 From: Sadeghizad Date: Thu, 23 Apr 2026 09:46:06 +0330 Subject: [PATCH 08/31] (feat): add method for get movie info --- src/main/java/movie/apis/MovieService.java | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/movie/apis/MovieService.java b/src/main/java/movie/apis/MovieService.java index 0f5015c..da23371 100644 --- a/src/main/java/movie/apis/MovieService.java +++ b/src/main/java/movie/apis/MovieService.java @@ -11,7 +11,7 @@ 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}";//todo fazel + private final static String MOVIE_INFO = "https://moviesapi.ir/api/v1/movies/{movie_id}"; private final static HttpClient client = HttpClient.newHttpClient(); private ArrayList moviesList; private ArrayList genresList; @@ -61,6 +61,31 @@ public class MovieService { return null; } + private String getMovieInfo(Long movieId) { + try { + + String url = MOVIE_INFO.replace("{movie_id}", movieId.toString()); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(url)) + .build(); + + 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()); + } + + } 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. From 0bd31c6f76ecf5587fe76cc3cd0057275fe1a144 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 08:49:20 +0000 Subject: [PATCH 09/31] Update src/main/java/Rational/Rational.java --- src/main/java/Rational/Rational.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/Rational/Rational.java b/src/main/java/Rational/Rational.java index 7fa04fa..7bd840e 100644 --- a/src/main/java/Rational/Rational.java +++ b/src/main/java/Rational/Rational.java @@ -39,14 +39,14 @@ public class Rational { } } - // ✅ COMPLETED - Instance method: this + other + // COMPLETED - Instance method: this + other public Rational add(Rational other) { int newNumerator = this.numerator * other.denominator + other.numerator * this.denominator; int newDenominator = this.denominator * other.denominator; return new Rational(newNumerator, newDenominator); } - // ✅ COMPLETED - Static method: r1 + r2 + // COMPLETED - Static method: r1 + r2 public static Rational add(Rational r1, Rational r2) { return r1.add(r2); } @@ -92,7 +92,7 @@ public class Rational { return null; // Remove this line when implemented } - // ✅ PROVIDED - String representation + // PROVIDED - String representation @Override public String toString() { if (denominator == 1) { @@ -101,7 +101,7 @@ public class Rational { return numerator + "/" + denominator; } - // ✅ PROVIDED - Decimal value + // PROVIDED - Decimal value public double toDouble() { return (double) numerator / denominator; } From 821190d9bdc932740d2e87633c4dfbd536d0c72c Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 09:13:46 +0000 Subject: [PATCH 10/31] Update README.md --- README.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/README.md b/README.md index 139597f..5f0ccbf 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,106 @@ +## Third Assignment: Movie Explorer 🎬 + Rational Calculator 🧮 +--- +Welcome to Your Third Assignment in the Advanced Programming Course! +This assignment consists of two separate parts. You must complete both parts. +--- + +## Part 1: Rational Class (Rational Numbers) +In this part, you will implement a Rational class that supports basic mathematical operations. + +Tasks: +Define fields for numerator and denominator + +Implement a constructor and a reduce() method for simplification + +Implement addition, subtraction, multiplication, and division as instance methods + +Implement addition, subtraction, multiplication, and division as static methods + +# Note: Detailed TODO comments are provided inside Rational.java. +--- +## Part 2: Movie Explorer 🎬 (Using API) +In this part, you will develop a Java application that fetches movie data from an API and allows users to browse and search movies. + +Files Provided: +Movie.java + +Genre.java + +MovieService.java + +Main.java + +Tasks: +Complete the Movie class (fields, constructor, getters/setters) + +Complete the Genre class (fields, constructor, getters/setters) + +Parse JSON data from getGenresList() into a list of Genre objects + +Display the list of genres to the user + +Fetch and return a list of movies by genreId and page number + +Display the genres of a specific movie + +Implement a console menu in Main to receive user input and display data + +# Note: Detailed TODO comments are provided inside each of the above source files. +--- +## Objectives ✏️ +By completing this assignment, you will: + +Reinforce OOP concepts: class design, constructors, encapsulation, collections + +Practice instance methods vs. static methods + +Work with JSON parsing and REST APIs + +Design a simple console-based menu + +Improve Git workflow and project management +---- +## Prerequisites ✅ +Git + +Java (version 23 or 25) + +API key for movie database (e.g., TMDB) +--- +## Tasks Summary 📝 +Fork the repository and clone it locally + +Create and switch to a development branch + +Complete Part 1 (Rational.java) following the TODO comments + +Complete Part 2 (Movie.java, Genre.java, MovieService.java, Main.java) following the TODO comments + +Ensure the code compiles and runs correctly + +Commit and push regularly + +Submit a pull request from development to main +--- +## Evaluation Criteria ⚖️ +Functionality: Code compiles and runs without errors; all features work correctly + +Code Quality: Clean, readable, well-structured code with proper naming + +Understanding: You must be able to explain your implementation +--- +## Bonus Tasks ✒️ +Advanced search (title, genre, year, rating, etc.) + +Sorting options for movies + +Save/load favorite movies to/from a file + +Improved console menu design + +GUI version using JavaFX +--- +## Submission ⌛ +Deadline: May 1st (11 Ordibehesht) From a9d4b6d74733ba3f5f6e49c041efc8c255d5a318 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 09:15:01 +0000 Subject: [PATCH 11/31] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f0ccbf..fd82983 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Implement addition, subtraction, multiplication, and division as instance method Implement addition, subtraction, multiplication, and division as static methods -# Note: Detailed TODO comments are provided inside Rational.java. +Note: Detailed TODO comments are provided inside Rational.java. --- ## Part 2: Movie Explorer 🎬 (Using API) In this part, you will develop a Java application that fetches movie data from an API and allows users to browse and search movies. @@ -46,7 +46,7 @@ Display the genres of a specific movie Implement a console menu in Main to receive user input and display data -# Note: Detailed TODO comments are provided inside each of the above source files. +Note: Detailed TODO comments are provided inside each of the above source files. --- ## Objectives ✏️ By completing this assignment, you will: From d2425a625ad8d98819acafc335a1ea4fc09a076c Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 09:16:44 +0000 Subject: [PATCH 12/31] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index fd82983..975922b 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,8 @@ Git Java (version 23 or 25) +Maven as a package manager + API key for movie database (e.g., TMDB) --- ## Tasks Summary 📝 From 75be64dc32a1b1a03c53ef7f26cdef3aedb0fd6d Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 09:18:30 +0000 Subject: [PATCH 13/31] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 975922b..912bb93 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,6 @@ In this part, you will implement a Rational class that supports basic mathematic Tasks: Define fields for numerator and denominator -Implement a constructor and a reduce() method for simplification - Implement addition, subtraction, multiplication, and division as instance methods Implement addition, subtraction, multiplication, and division as static methods From b3778400a367f9400b6f1c3a40569e80e7453c44 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 09:42:06 +0000 Subject: [PATCH 14/31] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 912bb93..f2cca2f 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ Java (version 23 or 25) Maven as a package manager -API key for movie database (e.g., TMDB) --- ## Tasks Summary 📝 Fork the repository and clone it locally From 1c0ce2ba1171cc673073f72c81b519979a0f2743 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 12:17:56 +0330 Subject: [PATCH 15/31] edit --- src/main/java/Rational/Rational.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/Rational/Rational.java b/src/main/java/Rational/Rational.java index 7fa04fa..7bd840e 100644 --- a/src/main/java/Rational/Rational.java +++ b/src/main/java/Rational/Rational.java @@ -39,14 +39,14 @@ public class Rational { } } - // ✅ COMPLETED - Instance method: this + other + // COMPLETED - Instance method: this + other public Rational add(Rational other) { int newNumerator = this.numerator * other.denominator + other.numerator * this.denominator; int newDenominator = this.denominator * other.denominator; return new Rational(newNumerator, newDenominator); } - // ✅ COMPLETED - Static method: r1 + r2 + // COMPLETED - Static method: r1 + r2 public static Rational add(Rational r1, Rational r2) { return r1.add(r2); } @@ -92,7 +92,7 @@ public class Rational { return null; // Remove this line when implemented } - // ✅ PROVIDED - String representation + // PROVIDED - String representation @Override public String toString() { if (denominator == 1) { @@ -101,7 +101,7 @@ public class Rational { return numerator + "/" + denominator; } - // ✅ PROVIDED - Decimal value + // PROVIDED - Decimal value public double toDouble() { return (double) numerator / denominator; } From 4c75b310f61d7fec51cd6940c589c3acfa5e8c44 Mon Sep 17 00:00:00 2001 From: Reyhane Noroozi Date: Thu, 23 Apr 2026 13:43:14 +0330 Subject: [PATCH 16/31] Update README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f2cca2f..45ccefc 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,8 @@ Code Quality: Clean, readable, well-structured code with proper naming Understanding: You must be able to explain your implementation --- ## Bonus Tasks ✒️ +Parse the JSON returned by the `getMovieInfo` method into a MovieInfo entity, and then present the structured movie details based on the user‑provided movie ID. + Advanced search (title, genre, year, rating, etc.) Sorting options for movies From a61780dfc340fdc36796638c2eba22858afa6c73 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 10:37:17 +0000 Subject: [PATCH 17/31] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 45ccefc..f4dac4b 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ Save/load favorite movies to/from a file Improved console menu design GUI version using JavaFX + --- ## Submission ⌛ Deadline: May 1st (11 Ordibehesht) From cc9ad9520c2556b386a05e6772e5970afbc51257 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 23 Apr 2026 10:37:58 +0000 Subject: [PATCH 18/31] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index f4dac4b..f6daf33 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ ## Third Assignment: Movie Explorer 🎬 + Rational Calculator 🧮 --- + Welcome to Your Third Assignment in the Advanced Programming Course! This assignment consists of two separate parts. You must complete both parts. + --- ## Part 1: Rational Class (Rational Numbers) @@ -16,6 +18,7 @@ Implement addition, subtraction, multiplication, and division as instance method Implement addition, subtraction, multiplication, and division as static methods Note: Detailed TODO comments are provided inside Rational.java. + --- ## Part 2: Movie Explorer 🎬 (Using API) In this part, you will develop a Java application that fetches movie data from an API and allows users to browse and search movies. @@ -45,6 +48,7 @@ Display the genres of a specific movie Implement a console menu in Main to receive user input and display data Note: Detailed TODO comments are provided inside each of the above source files. + --- ## Objectives ✏️ By completing this assignment, you will: @@ -58,6 +62,7 @@ Work with JSON parsing and REST APIs Design a simple console-based menu Improve Git workflow and project management + ---- ## Prerequisites ✅ Git @@ -81,6 +86,7 @@ Ensure the code compiles and runs correctly Commit and push regularly Submit a pull request from development to main + --- ## Evaluation Criteria ⚖️ Functionality: Code compiles and runs without errors; all features work correctly @@ -88,6 +94,7 @@ Functionality: Code compiles and runs without errors; all features work correctl Code Quality: Clean, readable, well-structured code with proper naming Understanding: You must be able to explain your implementation + --- ## Bonus Tasks ✒️ Parse the JSON returned by the `getMovieInfo` method into a MovieInfo entity, and then present the structured movie details based on the user‑provided movie ID. From e7fce5efe84d10df45c6d6d8b46e9ef08f6e1c54 Mon Sep 17 00:00:00 2001 From: Reyhane Noroozi Date: Fri, 24 Apr 2026 14:23:38 +0330 Subject: [PATCH 19/31] Update README --- README.md | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f6daf33..e54e0e5 100644 --- a/README.md +++ b/README.md @@ -23,31 +23,40 @@ Note: Detailed TODO comments are provided inside Rational.java. ## Part 2: Movie Explorer 🎬 (Using API) In this part, you will develop a Java application that fetches movie data from an API and allows users to browse and search movies. -Files Provided: -Movie.java +### Files Provided +- `Movie.java` +- `Genre.java` +- `MovieService.java` +- `Main.java` -Genre.java +We have already implemented two methods that call the API and return the raw JSON response as a `String`: -MovieService.java +- `getGenresList()` → calls the API and returns the list of genres in JSON format. +- `getMoviesByGenreList(Long genreId, Long page)` → calls the API and returns the list of movies for a specific genre and page in JSON format. -Main.java -Tasks: -Complete the Movie class (fields, constructor, getters/setters) +### Your Tasks -Complete the Genre class (fields, constructor, getters/setters) +1. Complete the `Genre` class (fields, constructor, getters, and setters). -Parse JSON data from getGenresList() into a list of Genre objects +2. Complete the `Movie` class (fields, constructor, getters, and setters). -Display the list of genres to the user +3. Write a method that receives the JSON string returned by `getGenresList()` and converts it into a `List`. -Fetch and return a list of movies by genreId and page number +4. Write another method that prints the list of genres in a clean and readable format for the user. -Display the genres of a specific movie +5. Write a method that receives the JSON string returned by `getMoviesByGenreList()` and converts it into a `List`. -Implement a console menu in Main to receive user input and display data +6. Write another method that displays the list of movies in a clean and readable format. -Note: Detailed TODO comments are provided inside each of the above source files. +7. Implement a console menu in `Main` that allows the user to: + - View the list of genres + - Select a genre + - View movies for the selected genre (with pagination) + +### Note + +To understand what fields should exist in the `Genre` and `Movie` classes, it is recommended that you first call the two API methods once and inspect the raw JSON response. This will help you determine the exact structure of the data and define the appropriate class fields. --- ## Objectives ✏️ From 158a504a3303643caa170de15f6d96ce060048d6 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Fri, 24 Apr 2026 15:43:05 +0330 Subject: [PATCH 20/31] Edit --- pom.xml | 15 ++ src/main/java/Rational/RationalTest.java | 108 ++++++++++++ src/main/java/movie/apis/Genre.java | 34 +++- src/main/java/movie/apis/Main.java | 88 +++++++++- src/main/java/movie/apis/Movie.java | 23 ++- src/main/java/movie/apis/MovieService.java | 187 ++++++++++++++++----- 6 files changed, 410 insertions(+), 45 deletions(-) create mode 100644 src/main/java/Rational/RationalTest.java 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 From fe4f3a5e95927133e30352004017211e8e275cfc Mon Sep 17 00:00:00 2001 From: Mehrdad Shirvani Date: Fri, 24 Apr 2026 15:59:27 +0330 Subject: [PATCH 21/31] chore: jdk --- .idea/misc.xml | 2 +- .idea/vcs.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 001e756..5274667 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file From ba0dd474c23f6622a17d712351103fe2fd3792d2 Mon Sep 17 00:00:00 2001 From: Mohammadfazel Date: Fri, 24 Apr 2026 12:44:37 +0000 Subject: [PATCH 22/31] (fix): Readme updated based on comments --- README.md | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e54e0e5..47e937f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ This assignment consists of two separate parts. You must complete both parts. ## Part 1: Rational Class (Rational Numbers) In this part, you will implement a Rational class that supports basic mathematical operations. +A `RationalTest` class is provided. ++You can run it to verify that your implementation works correctly. ++Use it to test your logic before submitting. + Tasks: Define fields for numerator and denominator @@ -18,6 +22,8 @@ Implement addition, subtraction, multiplication, and division as instance method Implement addition, subtraction, multiplication, and division as static methods Note: Detailed TODO comments are provided inside Rational.java. +Do NOT modify the constructor, simplify logic, or completed methods. +Only complete the TODO methods. --- ## Part 2: Movie Explorer 🎬 (Using API) @@ -29,11 +35,20 @@ In this part, you will develop a Java application that fetches movie data from a - `MovieService.java` - `Main.java` +The `Genre` class is already implemented as a sample. +You must design and implement the `Movie` class yourself (fields, constructors, getters, setters, toString if needed). + We have already implemented two methods that call the API and return the raw JSON response as a `String`: - `getGenresList()` → calls the API and returns the list of genres in JSON format. - `getMoviesByGenreList(Long genreId, Long page)` → calls the API and returns the list of movies for a specific genre and page in JSON format. +Do NOT modify: + API URLs + `getGenresList()` + `getMoviesByGenreList()` + +Only complete the TODO methods. ### Your Tasks @@ -53,10 +68,14 @@ We have already implemented two methods that call the API and return the raw JSO - View the list of genres - Select a genre - View movies for the selected genre (with pagination) - +After completing `MovieService`, you must also complete the `Main` class +so the menu works correctly. ### Note To understand what fields should exist in the `Genre` and `Movie` classes, it is recommended that you first call the two API methods once and inspect the raw JSON response. This will help you determine the exact structure of the data and define the appropriate class fields. +We implemented JSON parsing using **Gson** in the project. +However, the **Jackson dependency is also included**. +If you prefer, you are allowed to use Jackson instead of Gson. --- ## Objectives ✏️ @@ -106,7 +125,7 @@ Understanding: You must be able to explain your implementation --- ## Bonus Tasks ✒️ -Parse the JSON returned by the `getMovieInfo` method into a MovieInfo entity, and then present the structured movie details based on the user‑provided movie ID. +Parse the JSON returned by `getMovieInfo` into a `MovieInfo` entity and display structured movie details based on user-provided movie ID. Advanced search (title, genre, year, rating, etc.) @@ -118,6 +137,23 @@ Improved console menu design GUI version using JavaFX +--- +## References 📚 + +API Base: + https://api.meshcomp.ir/api/v1/genres + +Video Tutorials (compressed versions): + https://drive.meshcomp.ir/d/a29a5f6ea6484834bcf0/ + +Gson Tutorial: +(Gson) Reading and Parsing Data from a JSONObject + https://drive.meshcomp.ir/f/e8dea01f31b24cbca152/ + +Jackson Tutorial: +(Jackson) Parsing Json in Java Tutorial - Part 1 Jackson and Simple Objects + https://drive.meshcomp.ir/f/005d8f8fc19a44f4927b/ + --- ## Submission ⌛ Deadline: May 1st (11 Ordibehesht) From d302541508904cecbc1075034eadf5b5c29b5399 Mon Sep 17 00:00:00 2001 From: MehrdadShirvani Date: Fri, 24 Apr 2026 12:54:17 +0000 Subject: [PATCH 23/31] Update README.md --- README.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 47e937f..aeadf9c 100644 --- a/README.md +++ b/README.md @@ -140,19 +140,22 @@ GUI version using JavaFX --- ## References 📚 -API Base: - https://api.meshcomp.ir/api/v1/genres +API : + - genres: https://api.meshcomp.ir/api/v1/genres + - movies: https://api.meshcomp.ir/api/v1/movies + - movies (specifying the page): https://api.meshcomp.ir/api/v1/movies?page={pageId} + - movies by genres: https://api.meshcomp.ir/api/v1/genres/{genreId}/movies?page={pageId} + - details of a specific movie: https://api.meshcomp.ir/api/v1/movies/{movieId} -Video Tutorials (compressed versions): - https://drive.meshcomp.ir/d/a29a5f6ea6484834bcf0/ +Video Tutorials (watch before starting the assignment): + (link)[https://drive.meshcomp.ir/d/a29a5f6ea6484834bcf0/] Gson Tutorial: -(Gson) Reading and Parsing Data from a JSONObject - https://drive.meshcomp.ir/f/e8dea01f31b24cbca152/ +(`Gson` Reading and Parsing Data from a JSONObject)[https://drive.meshcomp.ir/f/e8dea01f31b24cbca152/] + Jackson Tutorial: -(Jackson) Parsing Json in Java Tutorial - Part 1 Jackson and Simple Objects - https://drive.meshcomp.ir/f/005d8f8fc19a44f4927b/ +(`Jackson` Parsing Json in Java Tutorial - Part 1 Jackson and Simple Objects)[https://drive.meshcomp.ir/f/005d8f8fc19a44f4927b/] --- ## Submission ⌛ From 486027c9a7cfffa1fc5957a1fbd667ca26ab19c8 Mon Sep 17 00:00:00 2001 From: MehrdadShirvani Date: Fri, 24 Apr 2026 12:56:05 +0000 Subject: [PATCH 24/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aeadf9c..4a47337 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ GUI version using JavaFX --- ## References 📚 -API : +API (Replace placeholders with numbers): - genres: https://api.meshcomp.ir/api/v1/genres - movies: https://api.meshcomp.ir/api/v1/movies - movies (specifying the page): https://api.meshcomp.ir/api/v1/movies?page={pageId} From 3f603210912848e11d7c2141c3ec5bc9335dbf40 Mon Sep 17 00:00:00 2001 From: MehrdadShirvani Date: Fri, 24 Apr 2026 12:57:08 +0000 Subject: [PATCH 25/31] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4a47337..037b0df 100644 --- a/README.md +++ b/README.md @@ -148,14 +148,14 @@ API (Replace placeholders with numbers): - details of a specific movie: https://api.meshcomp.ir/api/v1/movies/{movieId} Video Tutorials (watch before starting the assignment): - (link)[https://drive.meshcomp.ir/d/a29a5f6ea6484834bcf0/] + [link](https://drive.meshcomp.ir/d/a29a5f6ea6484834bcf0/) Gson Tutorial: -(`Gson` Reading and Parsing Data from a JSONObject)[https://drive.meshcomp.ir/f/e8dea01f31b24cbca152/] +[`Gson` Reading and Parsing Data from a JSONObject](https://drive.meshcomp.ir/f/e8dea01f31b24cbca152/) Jackson Tutorial: -(`Jackson` Parsing Json in Java Tutorial - Part 1 Jackson and Simple Objects)[https://drive.meshcomp.ir/f/005d8f8fc19a44f4927b/] +[`Jackson` Parsing Json in Java Tutorial - Part 1 Jackson and Simple Objects](https://drive.meshcomp.ir/f/005d8f8fc19a44f4927b/) --- ## Submission ⌛ From c011ac665ddca340cdc8122c2db0953c0776a593 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Fri, 24 Apr 2026 17:31:09 +0330 Subject: [PATCH 26/31] Edit Bouns --- src/main/java/movie/apis/Main.java | 8 +- src/main/java/movie/apis/MovieService.java | 128 +++++++++------------ 2 files changed, 58 insertions(+), 78 deletions(-) diff --git a/src/main/java/movie/apis/Main.java b/src/main/java/movie/apis/Main.java index babf179..f0e713d 100644 --- a/src/main/java/movie/apis/Main.java +++ b/src/main/java/movie/apis/Main.java @@ -25,11 +25,8 @@ public class Main { break; - case 3: - // TODO: Get page number from user, then call movieService.displayAllMovies() - break; - case 4: + case 3: // TODO (BONUS): Get movie ID from user, then call movieService.displayMovieDetails() @@ -61,8 +58,7 @@ public class Main { 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("3. Get movie details by ID"); System.out.println("0. Exit"); System.out.println("================================"); } diff --git a/src/main/java/movie/apis/MovieService.java b/src/main/java/movie/apis/MovieService.java index 7ceef15..cbbe70b 100644 --- a/src/main/java/movie/apis/MovieService.java +++ b/src/main/java/movie/apis/MovieService.java @@ -11,19 +11,13 @@ 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://api.meshcomp.ir/api/v1/genres"; + private final static String MOVIE_BY_ID_URL = "https://api.meshcomp.ir/api/v1/movies/"; private final static HttpClient client = HttpClient.newHttpClient(); - 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() @@ -67,6 +61,7 @@ public class MovieService { } + public void displayGenres() { String jsonResponse = getGenresList(); @@ -92,7 +87,6 @@ public class MovieService { } } - /** * TODO 1: Display movies for a specific genre and page * @@ -120,85 +114,75 @@ public class MovieService { /** - * 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 + * BONUS: Fetch movie details from API using movie ID + * URL format: https://api.meshcomp.ir/api/v1/movies/{movieId} */ - private void loadAllMovies() { - // TODO: Write your code here - // All parsing code must be inside try-catch + private String getMovieById(Long movieId) { try { - // Your code here + // TODO: Complete this method + // String url = MOVIE_BY_ID_URL + movieId; + // HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build(); + // HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + // if (response.statusCode() == 200) return response.body(); + return null; } catch (Exception e) { - System.err.println("ERROR loading movies: " + e.getMessage()); + System.out.println("!!Exception : " + e.getMessage()); } + return null; } - - + /** - * TODO 3: Display all movies with pagination + * BONUS TODO: Display complete movie details for a given movie ID * - * 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})" + * 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" + * } * - * 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 + * 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 * - * 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 + * PUT ALL PARSING CODE INSIDE THE EXISTING try-catch * - * loadAllMovies() already has try-catch inside + * @param movieId The ID of the movie to display */ public void displayMovieDetails(Long movieId) { - // TODO: Write your code here (BONUS) - // loadAllMovies() already has try-catch - // Your display logic here - } + // Step 1: Get JSON response from API + String jsonResponse = getMovieById(movieId); - private String getGenresString(List genres) { - if (genres == null || genres.isEmpty()) { - return "No genres"; + // Step 2: Check if we got valid data + if (jsonResponse == null) { + System.out.println("Failed to get movie details for ID: " + movieId); + return; } - 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; + // Step 3-6: Parse JSON and display details (PUT YOUR CODE INSIDE try-catch) + try { + // TODO: Parse jsonResponse to JsonObject + // TODO: Extract id, title, year, genres array, poster, country, imdb_rating + // TODO: Convert genres array to a readable string + // TODO: Print all movie details + // HINT: Use JsonParser.parseString(jsonResponse).getAsJsonObject() + // HINT: Use getAsJsonArray("genres") to get genres + // HINT: For each genre, use getAsString() + + // Your code here: + + + } catch (Exception e) { + System.err.println("ERROR parsing movie details: " + e.getMessage()); + } } } \ No newline at end of file From 28212a75980cd41cac7973c8fb3e39b7e5834ea1 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Fri, 24 Apr 2026 14:09:32 +0000 Subject: [PATCH 27/31] Update README.md --- README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 037b0df..2febd66 100644 --- a/README.md +++ b/README.md @@ -125,8 +125,55 @@ Understanding: You must be able to explain your implementation --- ## Bonus Tasks ✒️ -Parse the JSON returned by `getMovieInfo` into a `MovieInfo` entity and display structured movie details based on user-provided movie ID. +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. + +Movie Class Fields (already defined): + +- id (Long) - Movie identifier + +- title (String) - Movie title + +- year (String) - Release year + +- genres (List) - List of genres + +- images (String) - Poster image URL + +- country (String) - Production country + +- imdbRating (String) - IMDB rating + +Implementation Steps: + +1. 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 + +2. Handle Response (getMovieById method): + +If status code is 200, return JSON body + +Otherwise, print error and return null + +3. 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 + +4. Display Results (displayMovieDetails method): + +Print all movie details in a clean format Advanced search (title, genre, year, rating, etc.) Sorting options for movies From a4717ae4dc1b4a5e7725c93c42709261320732e3 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Fri, 24 Apr 2026 14:11:41 +0000 Subject: [PATCH 28/31] Update README.md --- README.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 2febd66..baa7e93 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ Understanding: You must be able to explain your implementation --- ## Bonus Tasks ✒️ -Fetch and display movie information using movie ID +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. @@ -149,40 +149,41 @@ Implementation Steps: 1. Build and Send Request (getMovieById method): -Create HTTP request to: https://api.meshcomp.ir/api/v1/movies/{movieId} + Create HTTP request to: https://api.meshcomp.ir/api/v1/movies/{movieId} -Replace {movieId} with the ID from user + Replace {movieId} with the ID from user -Send request and get response + Send request and get response 2. Handle Response (getMovieById method): -If status code is 200, return JSON body + If status code is 200, return JSON body -Otherwise, print error and return null + Otherwise, print error and return null 3. Parse JSON and Create Movie Object (displayMovieDetails method): -Parse JSON response to JsonObject + Parse JSON response to JsonObject -Extract all fields: id, title, year, poster, country, imdb_rating + Extract all fields: id, title, year, poster, country, imdb_rating -Parse "genres" array and convert each to Genre object + Parse "genres" array and convert each to Genre object -Create a Movie object with all extracted data + Create a Movie object with all extracted data 4. Display Results (displayMovieDetails method): -Print all movie details in a clean format -Advanced search (title, genre, year, rating, etc.) + Print all movie details in a clean format -Sorting options for movies +2. Advanced search (title, genre, year, rating, etc.) -Save/load favorite movies to/from a file +3. Sorting options for movies -Improved console menu design +4. Save/load favorite movies to/from a file -GUI version using JavaFX +5. Improved console menu design + +6. GUI version using JavaFX --- ## References 📚 From fc9df9873816fd900f428efa3f09fa5521315e28 Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Fri, 24 Apr 2026 14:13:04 +0000 Subject: [PATCH 29/31] Update README.md --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index baa7e93..a942a0b 100644 --- a/README.md +++ b/README.md @@ -149,31 +149,31 @@ Implementation Steps: 1. Build and Send Request (getMovieById method): - Create HTTP request to: https://api.meshcomp.ir/api/v1/movies/{movieId} + - Create HTTP request to: https://api.meshcomp.ir/api/v1/movies/{movieId} - Replace {movieId} with the ID from user + - Replace {movieId} with the ID from user - Send request and get response + - Send request and get response 2. Handle Response (getMovieById method): - If status code is 200, return JSON body + - If status code is 200, return JSON body - Otherwise, print error and return null + - Otherwise, print error and return null 3. Parse JSON and Create Movie Object (displayMovieDetails method): - Parse JSON response to JsonObject + - Parse JSON response to JsonObject - Extract all fields: id, title, year, poster, country, imdb_rating + - Extract all fields: id, title, year, poster, country, imdb_rating - Parse "genres" array and convert each to Genre object + - Parse "genres" array and convert each to Genre object - Create a Movie object with all extracted data + - Create a Movie object with all extracted data 4. Display Results (displayMovieDetails method): - Print all movie details in a clean format + - Print all movie details in a clean format 2. Advanced search (title, genre, year, rating, etc.) From 3631ba8545af16872dba5a135c3e021b60dec87f Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Fri, 24 Apr 2026 14:14:19 +0000 Subject: [PATCH 30/31] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a942a0b..a27eee7 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ Movie Class Fields (already defined): Implementation Steps: -1. Build and Send Request (getMovieById method): +- Build and Send Request (getMovieById method): - Create HTTP request to: https://api.meshcomp.ir/api/v1/movies/{movieId} @@ -155,13 +155,13 @@ Implementation Steps: - Send request and get response -2. Handle Response (getMovieById method): +- Handle Response (getMovieById method): - If status code is 200, return JSON body - Otherwise, print error and return null -3. Parse JSON and Create Movie Object (displayMovieDetails method): +- Parse JSON and Create Movie Object (displayMovieDetails method): - Parse JSON response to JsonObject @@ -171,7 +171,7 @@ Implementation Steps: - Create a Movie object with all extracted data -4. Display Results (displayMovieDetails method): +- Display Results (displayMovieDetails method): - Print all movie details in a clean format From 63eed8c84a71efa127e5c6a5d28b316bdd49e21c Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Fri, 24 Apr 2026 14:41:38 +0000 Subject: [PATCH 31/31] Update README.md --- README.md | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a27eee7..b2b0ac9 100644 --- a/README.md +++ b/README.md @@ -52,19 +52,13 @@ Only complete the TODO methods. ### Your Tasks -1. Complete the `Genre` class (fields, constructor, getters, and setters). +1. Complete the `Movie` class (fields, constructor, getters, and setters). -2. Complete the `Movie` class (fields, constructor, getters, and setters). +2. Write a method that receives the JSON string returned by `getMoviesByGenreList()` and converts it into a `List`. -3. Write a method that receives the JSON string returned by `getGenresList()` and converts it into a `List`. +3. Write another method that displays the list of movies (for the selected genre) in a clean and readable format. -4. Write another method that prints the list of genres in a clean and readable format for the user. - -5. Write a method that receives the JSON string returned by `getMoviesByGenreList()` and converts it into a `List`. - -6. Write another method that displays the list of movies in a clean and readable format. - -7. Implement a console menu in `Main` that allows the user to: +4. Implement a console menu in `Main` that allows the user to: - View the list of genres - Select a genre - View movies for the selected genre (with pagination)