diff --git a/README.md b/README.md
index 5e1d8b77c..d73ae192c 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,108 @@
-# Note Application
+# Chess Puzzles
-This is a minimal example demonstrating usage of the
-password-protected user part of the API used in lab 5.
+## Team Members
-You can find more information about the API endpoints in
-[the documentation](https://www.postman.com/cloudy-astronaut-813156/csc207-grade-apis-demo/documentation/fg3zkjm/5-password-protected-user).
+Chihana Kashiwabara - unomaru
-If your team is considering an application for which it would be convenient to
-store data in something like a database, you may find that the API calls demonstrated
-here will be useful in your project, as this will allow you to store
-an arbitrary JSON object associated with a username and password.
+Jiaqi Ma - DDMMMAA
-In this application, a single note has a name (the "username" in terms of the API) and the note
-can be read by anyone who knows the name — but only edited by someone who
-knows the password for it.
+Michelle Bakman - 207moment
-You can see the documentation in the various files for more information.
+John Ding - J0hnDing
-## Testing
+Yann Chi - YannChi22
-The repo also includes an example of a use case interactor test, as well as
-an example of an end-to-end test which automates button clicks and inspects
-the contents of the actual views. This is something we discussed in the lectures
-about testing in CA but had not provided a code example of before. Note, one
-could also inspect the contents of the ViewModel objects instead when testing
-CA to make a similar test which would be less dependent on the details of the
-specific UI implementation.
+## Table of content
-## Project Starter Code
++ [About This Project](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#about-this-project)
++ [Installation](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#installation)
++ [Use Case (Feature)](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#use-cases-features)
+ + [Signup & Login](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#signup--login)
+ + [Show Profile](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#show-profile)
+ + [Generate Daily Puzzle](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#generate-daily-puzzle)
+ + [Step by Step Move](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#generate-daily-puzzle)
++ [Usage Guide](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#usage-guide)
++ [Feedback](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#feedback)
++ [Contribute to this project](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#this-project-is-close-for-contributions)
++ [User Stories](https://github.com/DDMMMAA/CSC207-Team179?tab=readme-ov-file#user-stories)
-Your team may choose to use this repo as starter code for your project. You could
-also use the lab 5 code — or start from an empty repo if your team prefers.
-If you choose to use one of the repositories we have provided, you can either make
-a fork of it or copy the subset of code you want into a completely new repository.
+## About this project
+
+This app/project is able to generate random chess puzzles with options for daily, random puzzles, or specifically themed puzzles.
+A user will be able to view their puzzle statistics or review past puzzles within the current session of the program.
+Users should have the option to log in or create an account [built into the lichess api].
+If a user is logged in, they should be able to access any past puzzle scores or game histories they’ve played on that account.
+
+## Installation
+
+To Start: Clone ```main``` branch into your favorite JAVA IDE, then run ```MainChessAPP.java``` in ```src/main/java/app```
+```
+git clone https://github.com/DDMMMAA/CSC207-Team179.git
+```
+
+To close: Left click ```X``` icon at top right.
+
+Note: No additional package needed
+
+## Use Cases (Features)
+
+
+
+
+### Signup & Login
+
+This feature allows users to signup by creating username and password and login to the account created.
+
+To Signup: Enter username and password(two times) to be used for an account, and click ```Signup``` to confirm signup.
+
+To Login: Click ```Login``` to navigate to a login page, enter username and password for the account, and click ```Login``` to confirm login.
+
+
+### Show Profile
+
+User can view their profile (Contain User name and rank point currently) after login by click ```Show Profile``` after login.
+
+Note: New user's rank point is set to ```0```
+
+
+
+
+### Generate daily puzzle
+
+This requests the algebraic chess notation for the current daily puzzle in the Lichess API
+and stores the set of solutions and the series of moves to create the puzzle board.
+
+### Step by step move
+
+This feature enables users to move a chess piece to a valid position during their turn.
+Since moving a piece involves two steps, select and move, this usecase have two functionality.
+
+To Select: User clicks on the square containing the chess piece they want to select. The program then highlights all valid moves in yellow.
+
+To Move: If one piece is selected and the user clicks on one of the highlighted squares, the chess piece is moved to the target position.
+
+Note: Clicking an invalid move after select deselects the piece.
+
+## Usage Guide
+
+This meant to me used in order of ```Signup & Login``` → ```Generate daily puzzle``` → ```Step by step move```
+(Please refer to above ```use cases (Features)``` for detail of each use case)
+
+## Feedback
+
+Plead use github [Discussion board](https://github.com/DDMMMAA/CSC207-Team179/discussions) to submit your feedback.
+
+Simply start a new discussion with appropriate title (eg., associated use case).
+
+## This project is close for contributions
+
+## User Stories
+
+Group User Story. Tom generate a chess puzzle, solve it step by step, and eventually win.
+
+1. John wants to play a chess puzzle. He opens the chess puzzle player and clicks generate puzzle of the day. The chess puzzle of the day loads on screen. [Michelle’s Story]
+2. Tom and Tim argued about who is a better chess player, so they decided to compare their Rank point of Ranking system. [Jiaqi Ma’s Story]
+3. As Mary hears about this chess puzzle, she wants to create an account and log in to start a puzzle. [Chihana’s Story]
+4. Andy is learning chess, and he can use this program to check his learning progress, by looking at past statistics of chess puzzles. He can search up his user account using the username. [Yann Chi's Story]
+5. Felix wants to see the possible moves he can make with one piece, so he click on that piece and the possible cells will be indicated. [John’s Story]
diff --git a/Show Profilegif.gif b/Show Profilegif.gif
new file mode 100644
index 000000000..1484376dd
Binary files /dev/null and b/Show Profilegif.gif differ
diff --git a/accessibility-report.md b/accessibility-report.md
new file mode 100644
index 000000000..70a3e6883
--- /dev/null
+++ b/accessibility-report.md
@@ -0,0 +1,22 @@
+## Principle of Universal desgin
+
++ Equitable Use
+ + Users are allowed to input any String as their username, not restricted to english. User with none english name can benefit from this.
++ Flexibility in Use
+ + Features could add: Allowed user to pick board theme (ie., Black/white, light theme, dark theme).
++ Simple and Intuitive Use
+ + Move use are match with intuition. Click a piece to select, slick a grid to move
++ Perceptible Information
+ + This program can't accommodate user with visual disability currently. A potential feature might add to accommodate visual disability is allowed user to select other output device (ie., touch board)
++ Tolerance of Error
+ + Tolerating wrong click on grid that doesn't contain piece. Error message like "Can't select empty grid" doesn't sent, because click on empty grid is common that sent error message everytime wrong click happened will be annoyed.
++ Low Physical Effort
+ + The only interaction use need while play the chess game is clicking mose.
++ Size and Space for Approach and Use
+ + Size of the window (chess board) is adjustable.
+
+## Program Market
++ If I were to market my chess puzzle program, I would target chess enthusiasts and learners of all ages, particularly those seeking to improve their strategic thinking and problem-solving skills. The program would appeal to students and educators looking for engaging tools to teach or practice chess fundamentals, as well as casual players who enjoy the intellectual challenge of solving puzzles in their leisure time. Additionally, the program could attract competitive chess players aiming to refine their tactics through a curated collection of puzzles ranging from beginner to advanced levels.
+
+## People who can't take advantage of this App
++ People with dysgnosia is less likely to take advantage of this App, simply because this App is meant to be intellectually challenging. However, puzzle difficulty classification feature can be added and might accommodate people with dysgnosia.
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 527f61e36..8f715e7bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,6 +27,16 @@
4.13.1
test
+
+ io.github.tors42
+ chariot
+ 0.1.10
+
+
+ com.alibaba
+ fastjson
+ 1.2.79
+
diff --git a/src/main/java/app/ChessAppBuilder.java b/src/main/java/app/ChessAppBuilder.java
new file mode 100644
index 000000000..5bc5118c2
--- /dev/null
+++ b/src/main/java/app/ChessAppBuilder.java
@@ -0,0 +1,67 @@
+package app;
+
+import data_access.ChessDataAccessObject;
+import entity.Board;
+import entity.Game;
+import interface_adapter.ViewManagerModel;
+import interface_adapter.move.MoveController;
+import interface_adapter.move.MovePresenter;
+import interface_adapter.move.MoveViewModel;
+import use_case.move.MoveInteractor;
+import use_case.move.MoveOutputBoundary;
+import view.ChessBoardView;
+
+/**
+ * Builder for the Chess Application.
+ */
+public class ChessAppBuilder {
+ public static final int HEIGHT = 800;
+ public static final int WIDTH = 800;
+ // TODO change to ChessDataAccessInterface once implemented
+ private ChessDataAccessObject chessDataAccessObject;
+ private MoveViewModel moveViewModel = new MoveViewModel();
+ private final ViewManagerModel viewManagerModel = new ViewManagerModel();
+ private ChessBoardView chessBoardView;
+ private MoveInteractor moveInteractor;
+
+ /**
+ * Set the ChessDAO to be used in this application.
+ * @param chessDataAccess the DAO to use
+ * @return this builder
+ */
+ public ChessAppBuilder addChessDAO(ChessDataAccessObject chessDataAccess) {
+ chessDataAccessObject = chessDataAccess;
+ return this;
+ }
+
+ /**
+ * Creates the objects for the Move Use Case and connects the ChessBoardView to Move controller.
+ * @return this builder
+ */
+ public ChessAppBuilder addMoveUseCase() {
+ final MoveOutputBoundary moveOutPutBoundary = new MovePresenter(moveViewModel, viewManagerModel);
+ Board board = new Board();
+ Game game = new Game(board, true);
+ moveInteractor = new MoveInteractor(
+ chessDataAccessObject, moveOutPutBoundary, game);
+
+ final MoveController moveController = new MoveController(moveInteractor);
+ chessBoardView.setMoveController(moveController);
+ return this;
+ }
+
+ /**
+ * Creates the ChessBoardView and underlying MoveViewModel.
+ * @return this builder
+ */
+ public ChessAppBuilder addMoveView() {
+ moveViewModel = new MoveViewModel();
+ final MoveController moveController = new MoveController(moveInteractor);
+ chessBoardView = new ChessBoardView(moveViewModel, moveController);
+ return this;
+ }
+
+ public ChessBoardView buildChessBoardView() {
+ return chessBoardView;
+ }
+}
diff --git a/src/main/java/app/LoginUseCaseFactory.java b/src/main/java/app/LoginUseCaseFactory.java
new file mode 100644
index 000000000..d0d6fef26
--- /dev/null
+++ b/src/main/java/app/LoginUseCaseFactory.java
@@ -0,0 +1,61 @@
+package app;
+
+import interface_adapter.ViewManagerModel;
+import interface_adapter.logged_in.LoggedInViewModel;
+import interface_adapter.login.LoginController;
+import interface_adapter.login.LoginPresenter;
+import interface_adapter.login.LoginViewModel;
+import interface_adapter.signup.SignupViewModel;
+import use_case.login.LoginInputBoundary;
+import use_case.login.LoginInteractor;
+import use_case.login.LoginOutputBoundary;
+import use_case.login.LoginUserDataAccessInterface;
+import view.LoginView;
+
+/**
+ * This class contains the static factory function for creating the LoginView.
+ */
+public final class LoginUseCaseFactory {
+
+ /** Prevent instantiation. */
+ private LoginUseCaseFactory() {
+
+ }
+
+ /**
+ * Factory function for creating the LoginView.
+ * @param viewManagerModel the ViewManagerModel to inject into the LoginView
+ * @param loginViewModel the LoginViewModel to inject into the LoginView
+ * @param loggedInViewModel the LoggedInViewModel to inject into the LoginView
+ * @param userDataAccessObject the LoginUserDataAccessInterface to inject into the LoginView
+ * @param signupViewModel the SignupViewModel to inject into the LoginView
+ * @return the LoginView created for the provided input classes
+ */
+ public static LoginView create(
+ ViewManagerModel viewManagerModel,
+ LoginViewModel loginViewModel,
+ LoggedInViewModel loggedInViewModel,
+ LoginUserDataAccessInterface userDataAccessObject,
+ SignupViewModel signupViewModel) {
+
+ final LoginController loginController = createLoginUseCase(viewManagerModel, loginViewModel,
+ loggedInViewModel, userDataAccessObject, signupViewModel);
+ return new LoginView(loginViewModel, loginController);
+
+ }
+
+ private static LoginController createLoginUseCase(
+ ViewManagerModel viewManagerModel,
+ LoginViewModel loginViewModel,
+ LoggedInViewModel loggedInViewModel,
+ LoginUserDataAccessInterface userDataAccessObject,
+ SignupViewModel signupViewModel) {
+
+ final LoginOutputBoundary loginOutputBoundary = new LoginPresenter(viewManagerModel,
+ loggedInViewModel, loginViewModel, signupViewModel);
+ final LoginInputBoundary loginInteractor = new LoginInteractor(
+ userDataAccessObject, loginOutputBoundary);
+
+ return new LoginController(loginInteractor);
+ }
+}
diff --git a/src/main/java/app/MainChessApp.java b/src/main/java/app/MainChessApp.java
new file mode 100644
index 000000000..12e1010be
--- /dev/null
+++ b/src/main/java/app/MainChessApp.java
@@ -0,0 +1,21 @@
+package app;
+
+/**
+ * Main that activates login page.
+ */
+public class MainChessApp {
+
+ /**
+ * The main method for starting the program with an external database used to persist user data.
+ * @param args input to main
+ */
+ public static void main(String[] args) {
+
+ final UserAppBuilder userAppBuilder = new UserAppBuilder();
+ userAppBuilder.addViewModels()
+ .addViews()
+ .initializeState()
+ .addChessGame()
+ .build();
+ }
+}
diff --git a/src/main/java/app/MainNoteApplication.java b/src/main/java/app/MainNoteApplication.java
deleted file mode 100644
index c37860156..000000000
--- a/src/main/java/app/MainNoteApplication.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package app;
-
-import data_access.DBNoteDataAccessObject;
-import use_case.note.NoteDataAccessInterface;
-
-/**
- * An application where we can view and add to a note stored by a user.
- *
- * This is a minimal example of using the password-protected user API from lab 5,
- * but demonstrating the endpoint allowing you to store an arbitrary JSON object.
- * This functionality could be used in any project where your team wants to persist
- * data which is then accessible across devices.
- * The code is intentionally somewhat incomplete to leave work to be done if your
- * team were to choose to work on a project which would require similar functionality.
- * For example, we have intentionally not created a full "Note" entity here, but
- * rather just represented a note as a string.
- *
- * The ViewManager code has also been removed, since this minimal program only requires a single
- * view. Your team may wish to bring back the ViewManager or make your own implementation of supporting
- * switching between views depending on your project.
- */
-public class MainNoteApplication {
-
- /**
- * The main entry point of the application.
- *
- * The program will show you the note currently saved in the system.
- * You are able to edit it and then save it to the system. You can refresh
- * to update the note to reflect what was saved most recently. This
- * uses the API from lab, so there is one database storing the note,
- * which means that if anyone updates the note, that is what you will
- * see when you refresh.
- *
- * You can generalize the code to allow you to
- * specify which "user" to save the note for, which will allow your team
- * to store information specific to your team which is password-protected.
- * The username and password used in this application are currently for
- * user jonathan_calver2, but you can change that. As you did in lab 3,
- * you will likely want to store password information locally rather than
- * in your repo. Or you can require the user to enter their credentials
- * in your application; it just depends on what your program's main
- * functionality.
- *
- * @param args commandline arguments are ignored
- */
- public static void main(String[] args) {
-
- // create the data access and inject it into our builder!
- final NoteDataAccessInterface noteDataAccess = new DBNoteDataAccessObject();
-
- final NoteAppBuilder builder = new NoteAppBuilder();
- builder.addNoteDAO(noteDataAccess)
- .addNoteView()
- .addNoteUseCase().build().setVisible(true);
- }
-}
diff --git a/src/main/java/app/NoteAppBuilder.java b/src/main/java/app/NoteAppBuilder.java
deleted file mode 100644
index a68cb9ad6..000000000
--- a/src/main/java/app/NoteAppBuilder.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package app;
-
-import javax.swing.JFrame;
-import javax.swing.WindowConstants;
-
-import interface_adapter.note.NoteController;
-import interface_adapter.note.NotePresenter;
-import interface_adapter.note.NoteViewModel;
-import use_case.note.NoteDataAccessInterface;
-import use_case.note.NoteInteractor;
-import use_case.note.NoteOutputBoundary;
-import view.NoteView;
-
-/**
- * Builder for the Note Application.
- */
-public class NoteAppBuilder {
- public static final int HEIGHT = 300;
- public static final int WIDTH = 400;
- private NoteDataAccessInterface noteDAO;
- private NoteViewModel noteViewModel = new NoteViewModel();
- private NoteView noteView;
- private NoteInteractor noteInteractor;
-
- /**
- * Sets the NoteDAO to be used in this application.
- * @param noteDataAccess the DAO to use
- * @return this builder
- */
- public NoteAppBuilder addNoteDAO(NoteDataAccessInterface noteDataAccess) {
- noteDAO = noteDataAccess;
- return this;
- }
-
- /**
- * Creates the objects for the Note Use Case and connects the NoteView to its
- * controller.
- * This method must be called after addNoteView!
- * @return this builder
- * @throws RuntimeException if this method is called before addNoteView
- */
- public NoteAppBuilder addNoteUseCase() {
- final NoteOutputBoundary noteOutputBoundary = new NotePresenter(noteViewModel);
- noteInteractor = new NoteInteractor(
- noteDAO, noteOutputBoundary);
-
- final NoteController controller = new NoteController(noteInteractor);
- if (noteView == null) {
- throw new RuntimeException("addNoteView must be called before addNoteUseCase");
- }
- noteView.setNoteController(controller);
- return this;
- }
-
- /**
- * Creates the NoteView and underlying NoteViewModel.
- * @return this builder
- */
- public NoteAppBuilder addNoteView() {
- noteViewModel = new NoteViewModel();
- noteView = new NoteView(noteViewModel);
- return this;
- }
-
- /**
- * Builds the application.
- * @return the JFrame for the application
- */
- public JFrame build() {
- final JFrame frame = new JFrame();
- frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
- frame.setTitle("Note Application");
- frame.setSize(WIDTH, HEIGHT);
-
- frame.add(noteView);
-
- // refresh so that the note will be visible when we start the program
- noteInteractor.executeRefresh();
-
- return frame;
-
- }
-}
diff --git a/src/main/java/app/ShowProfileUseCaseFactory.java b/src/main/java/app/ShowProfileUseCaseFactory.java
new file mode 100644
index 000000000..6ef95e9aa
--- /dev/null
+++ b/src/main/java/app/ShowProfileUseCaseFactory.java
@@ -0,0 +1,99 @@
+package app;
+
+import interface_adapter.ViewManagerModel;
+import interface_adapter.logged_in.LoggedInController;
+import interface_adapter.logged_in.LoggedInPresenter;
+import interface_adapter.logged_in.LoggedInViewModel;
+import interface_adapter.query.QueryController;
+import interface_adapter.query.QueryPresenter;
+import interface_adapter.query.QueryViewModel;
+import interface_adapter.showProfile.ShowProfileController;
+import interface_adapter.showProfile.ShowProfilePresenter;
+import interface_adapter.showProfile.ShowProfileViewModel;
+import interface_adapter.signup.SignupViewModel;
+import use_case.logged_in.LoggedInInputBoundary;
+import use_case.logged_in.LoggedInInteractor;
+import use_case.logged_in.LoggedInOutputBoundary;
+import use_case.query.QueryDataAccessInterface;
+import use_case.query.QueryInputBoundary;
+import use_case.query.QueryInteractor;
+import use_case.query.QueryOutputBoundary;
+import use_case.showProfile.ShowProfileInputBoundary;
+import use_case.showProfile.ShowProfileInteractor;
+import use_case.showProfile.ShowProfileOutputBoundary;
+import use_case.showProfile.ShowProfileUserDataAccessInterface;
+import view.LoggedInView;
+
+/**
+ * This class contains the static factory function for creating the LoggedInView.
+ */
+public final class ShowProfileUseCaseFactory {
+
+ /** Prevent instantiation. */
+ private ShowProfileUseCaseFactory() {
+
+ }
+
+ /**
+ * Factory function for creating the LoggedInView.
+ *
+ * @param viewManagerModel the ViewManagerModel to inject into the LoggedInView
+ * @param loggedInViewModel the loggedInViewModel to inject into the LoggedInView
+ * @param signupViewModel the signupViewModel
+ * @param showProfileViewModel the showProfileViewModel
+ * @param userDataAccessObject the ChangePasswordUserDataAccessInterface to inject into the LoggedInView
+ * @param queryViewModel the QueryViewModel to inject into the LoggedInView
+ * @param queryDataAccessObject the Query DataAccessObject
+ * @return the LoggedInView created for the provided input classes
+ */
+ public static LoggedInView create(
+ ViewManagerModel viewManagerModel,
+ LoggedInViewModel loggedInViewModel,
+ SignupViewModel signupViewModel,
+ ShowProfileViewModel showProfileViewModel,
+ QueryViewModel queryViewModel,
+ ShowProfileUserDataAccessInterface userDataAccessObject,
+ QueryDataAccessInterface queryDataAccessObject) {
+
+ final ShowProfileController showProfileController =
+ createShowProfileUseCase(viewManagerModel,
+ showProfileViewModel, userDataAccessObject);
+
+ final QueryOutputBoundary queryOutputBoundary = new QueryPresenter(queryViewModel, viewManagerModel);
+ final QueryInputBoundary queryInputInteractor = new QueryInteractor(queryDataAccessObject, queryOutputBoundary);
+ final QueryController queryController = new QueryController(queryInputInteractor);
+
+ final LoggedInController loggedInController = createLoggedInUseCase(viewManagerModel, loggedInViewModel,
+ signupViewModel);
+
+ return new LoggedInView(viewManagerModel, loggedInController, loggedInViewModel,
+ showProfileController, queryController);
+ }
+
+ private static ShowProfileController createShowProfileUseCase(
+ ViewManagerModel viewManagerModel,
+ ShowProfileViewModel showProfileViewModel,
+ ShowProfileUserDataAccessInterface userDataAccessObject) {
+
+ final ShowProfileOutputBoundary showProfileOutputBoundary = new ShowProfilePresenter(showProfileViewModel,
+ viewManagerModel);
+
+ final ShowProfileInputBoundary showProfileInputInteractor = new ShowProfileInteractor(userDataAccessObject,
+ showProfileOutputBoundary);
+
+ return new ShowProfileController(showProfileInputInteractor);
+ }
+
+ private static LoggedInController createLoggedInUseCase(
+ ViewManagerModel viewManagerModel,
+ LoggedInViewModel loggedInViewModel,
+ SignupViewModel signupViewModel) {
+
+ final LoggedInOutputBoundary loggedInOutputBoundary = new LoggedInPresenter(viewManagerModel, loggedInViewModel,
+ signupViewModel);
+
+ final LoggedInInputBoundary loggedInInputBoundary = new LoggedInInteractor(loggedInOutputBoundary);
+
+ return new LoggedInController(loggedInInputBoundary);
+ }
+}
diff --git a/src/main/java/app/SignupUseCaseFactory.java b/src/main/java/app/SignupUseCaseFactory.java
new file mode 100644
index 000000000..06dfe8f35
--- /dev/null
+++ b/src/main/java/app/SignupUseCaseFactory.java
@@ -0,0 +1,55 @@
+package app;
+
+import interface_adapter.ViewManagerModel;
+import interface_adapter.login.LoginViewModel;
+import interface_adapter.signup.SignupController;
+import interface_adapter.signup.SignupPresenter;
+import interface_adapter.signup.SignupViewModel;
+import use_case.signup.SignupInputBoundary;
+import use_case.signup.SignupInteractor;
+import use_case.signup.SignupOutputBoundary;
+import use_case.signup.SignupUserDataAccessInterface;
+import view.SignupView;
+
+/**
+ * This class contains the static factory function for creating the SignupView.
+ */
+public final class SignupUseCaseFactory {
+
+ /** Prevent instantiation. */
+ private SignupUseCaseFactory() {
+
+ }
+
+ /**
+ * Factory function for creating the SignupView.
+ * @param viewManagerModel the ViewManagerModel to inject into the SignupView
+ * @param loginViewModel the LoginViewModel to inject into the SignupView
+ * @param signupViewModel the SignupViewModel to inject into the SignupView
+ * @param userDataAccessObject the SignupUserDataAccessInterface to inject into the SignupView
+ * @return the LoginView created for the provided input classes
+ */
+ public static SignupView create(
+ ViewManagerModel viewManagerModel, LoginViewModel loginViewModel,
+ SignupViewModel signupViewModel, SignupUserDataAccessInterface userDataAccessObject) {
+
+ final SignupController signupController = createUserSignupUseCase(viewManagerModel, signupViewModel,
+ loginViewModel, userDataAccessObject);
+ return new SignupView(signupController, signupViewModel);
+
+ }
+
+ private static SignupController createUserSignupUseCase(ViewManagerModel viewManagerModel,
+ SignupViewModel signupViewModel,
+ LoginViewModel loginViewModel,
+ SignupUserDataAccessInterface userDataAccessObject) {
+
+ final SignupOutputBoundary signupOutputBoundary = new SignupPresenter(viewManagerModel,
+ signupViewModel, loginViewModel);
+
+ final SignupInputBoundary userSignupInteractor = new SignupInteractor(
+ userDataAccessObject, signupOutputBoundary);
+
+ return new SignupController(userSignupInteractor);
+ }
+}
diff --git a/src/main/java/app/UserAppBuilder.java b/src/main/java/app/UserAppBuilder.java
new file mode 100644
index 000000000..c38765f78
--- /dev/null
+++ b/src/main/java/app/UserAppBuilder.java
@@ -0,0 +1,124 @@
+package app;
+
+import java.awt.CardLayout;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.WindowConstants;
+
+import data_access.ChessDataAccessObject;
+import data_access.QueryDataAccessObject;
+import data_access.UserDataAccessObject;
+import interface_adapter.ViewManagerModel;
+import interface_adapter.logged_in.LoggedInViewModel;
+import interface_adapter.login.LoginViewModel;
+import interface_adapter.query.QueryViewModel;
+import interface_adapter.showProfile.ShowProfileViewModel;
+import interface_adapter.signup.SignupViewModel;
+import view.ChessBoardView;
+import view.LoggedInView;
+import view.LoginView;
+import view.ProfileView;
+import view.QueryView;
+import view.SignupView;
+import view.ViewManager;
+
+public class UserAppBuilder {
+ private CardLayout cardLayout;
+ private JPanel views;
+ private ViewManagerModel viewManagerModel;
+ private ChessBoardView chessBoardView;
+ private UserDataAccessObject userDataAccessObject;
+ private QueryDataAccessObject queryDataAccessObject;
+
+ private LoginViewModel loginViewModel;
+ private LoggedInViewModel loggedInViewModel;
+ private SignupViewModel signupViewModel;
+ private ShowProfileViewModel showProfileViewModel;
+ private QueryViewModel queryViewModel;
+
+ public UserAppBuilder() {
+ this.cardLayout = new CardLayout();
+ this.views = new JPanel(cardLayout);
+ this.viewManagerModel = new ViewManagerModel();
+ this.userDataAccessObject = new UserDataAccessObject();
+ this.queryDataAccessObject = new QueryDataAccessObject();
+
+ new ViewManager(views, cardLayout, viewManagerModel);
+ }
+
+ /**
+ * Set the addViewModels to be used in this application.
+ * @return this builder
+ */
+ public UserAppBuilder addViewModels() {
+ this.loginViewModel = new LoginViewModel();
+ this.loggedInViewModel = new LoggedInViewModel();
+ this.signupViewModel = new SignupViewModel();
+ this.showProfileViewModel = new ShowProfileViewModel();
+ this.queryViewModel = new QueryViewModel();
+
+ return this;
+ }
+
+ /**
+ * Set the addViews to be used in this application.
+ * @return this builder
+ */
+ public UserAppBuilder addViews() {
+ final SignupView signupView = SignupUseCaseFactory.create(viewManagerModel, loginViewModel, signupViewModel,
+ userDataAccessObject);
+ final LoginView loginView = LoginUseCaseFactory.create(viewManagerModel, loginViewModel, loggedInViewModel,
+ userDataAccessObject, signupViewModel);
+ final LoggedInView loggedInView = ShowProfileUseCaseFactory.create(viewManagerModel, loggedInViewModel,
+ signupViewModel, showProfileViewModel, queryViewModel, userDataAccessObject, queryDataAccessObject);
+ final ProfileView profileView = new ProfileView(viewManagerModel, showProfileViewModel);
+ final QueryView queryView = new QueryView(viewManagerModel, queryViewModel);
+
+ views.add(signupView, signupView.getViewName());
+ views.add(loginView, loginView.getViewName());
+ views.add(loggedInView, loggedInView.getViewName());
+ views.add(profileView, profileView.getViewName());
+ views.add(queryView, queryView.getViewName());
+
+ return this;
+ }
+
+ /**
+ * Set the addChessGame to be used in this application.
+ * @return this builder
+ */
+ public UserAppBuilder addChessGame() {
+ final ChessAppBuilder chessAppBuilder = new ChessAppBuilder();
+ chessAppBuilder.addChessDAO(new ChessDataAccessObject())
+ .addMoveView()
+ .addMoveUseCase();
+
+ this.chessBoardView = chessAppBuilder.buildChessBoardView();
+ this.views.add(chessBoardView, "chessBoardView");
+ return this;
+ }
+
+ /**
+ * Set the initializeState to be used in this application.
+ * @return this builder
+ */
+ public UserAppBuilder initializeState() {
+ this.viewManagerModel.setState("signUpView");
+ this.viewManagerModel.firePropertyChanged();
+ return this;
+ }
+
+ /**
+ * Set the build to be used in this application.
+ * @return this builder
+ */
+ public JFrame build() {
+ final JFrame frame = new JFrame("Chess Game Login");
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ frame.add(this.views);
+ frame.pack();
+ frame.setVisible(true);
+ return frame;
+ }
+}
diff --git a/src/main/java/data_access/ChessDataAccessObject.java b/src/main/java/data_access/ChessDataAccessObject.java
new file mode 100644
index 000000000..2035f74f4
--- /dev/null
+++ b/src/main/java/data_access/ChessDataAccessObject.java
@@ -0,0 +1,12 @@
+package data_access;
+
+import use_case.daily_puzzle.DailyPuzzleDataAccessInterface;
+import use_case.move.MoveDataAccessInterface;
+
+/**
+ * The DAO to access lichess API.
+ * related use case are 'daily Puzzle' & 'Move'
+ */
+public class ChessDataAccessObject implements MoveDataAccessInterface, DailyPuzzleDataAccessInterface {
+
+}
diff --git a/src/main/java/data_access/DBNoteDataAccessObject.java b/src/main/java/data_access/DBNoteDataAccessObject.java
deleted file mode 100644
index dadb0cab0..000000000
--- a/src/main/java/data_access/DBNoteDataAccessObject.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package data_access;
-
-import java.io.IOException;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import entity.User;
-import okhttp3.MediaType;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.RequestBody;
-import okhttp3.Response;
-import use_case.note.DataAccessException;
-import use_case.note.NoteDataAccessInterface;
-
-/**
- * The DAO for accessing notes stored in the database.
- * This class demonstrates how your group can use the password-protected user
- * endpoints of the API used in lab 5 to store persistent data in your program.
- *
- * You can also refer to the lab 5 code for signing up a new user and other use cases.
- *
- * See
- *
- * the documentation
- * of the API for more details.
- */
-public class DBNoteDataAccessObject implements NoteDataAccessInterface {
- private static final int SUCCESS_CODE = 200;
- private static final int CREDENTIAL_ERROR = 401;
- private static final String CONTENT_TYPE_LABEL = "Content-Type";
- private static final String CONTENT_TYPE_JSON = "application/json";
- private static final String STATUS_CODE_LABEL = "status_code";
- private static final String USERNAME = "username";
- private static final String PASSWORD = "password";
- private static final String MESSAGE = "message";
-
- @Override
- public String saveNote(User user, String note) throws DataAccessException {
- final OkHttpClient client = new OkHttpClient().newBuilder()
- .build();
-
- // POST METHOD
- final MediaType mediaType = MediaType.parse(CONTENT_TYPE_JSON);
- final JSONObject requestBody = new JSONObject();
- requestBody.put(USERNAME, user.getName());
- requestBody.put(PASSWORD, user.getPassword());
- final JSONObject extra = new JSONObject();
- extra.put("note", note);
- requestBody.put("info", extra);
- final RequestBody body = RequestBody.create(requestBody.toString(), mediaType);
- final Request request = new Request.Builder()
- .url("http://vm003.teach.cs.toronto.edu:20112/modifyUserInfo")
- .method("PUT", body)
- .addHeader(CONTENT_TYPE_LABEL, CONTENT_TYPE_JSON)
- .build();
- try {
- final Response response = client.newCall(request).execute();
-
- final JSONObject responseBody = new JSONObject(response.body().string());
-
- if (responseBody.getInt(STATUS_CODE_LABEL) == SUCCESS_CODE) {
- return loadNote(user);
- }
- else if (responseBody.getInt(STATUS_CODE_LABEL) == CREDENTIAL_ERROR) {
- throw new DataAccessException("message could not be found or password was incorrect");
- }
- else {
- throw new DataAccessException("database error: " + responseBody.getString(MESSAGE));
- }
- }
- catch (IOException | JSONException ex) {
- throw new DataAccessException(ex.getMessage());
- }
- }
-
- @Override
- public String loadNote(User user) throws DataAccessException {
- // Make an API call to get the user object.
- final String username = user.getName();
- final OkHttpClient client = new OkHttpClient().newBuilder().build();
- final Request request = new Request.Builder()
- .url(String.format("http://vm003.teach.cs.toronto.edu:20112/user?username=%s", username))
- .addHeader("Content-Type", CONTENT_TYPE_JSON)
- .build();
- try {
- final Response response = client.newCall(request).execute();
-
- final JSONObject responseBody = new JSONObject(response.body().string());
-
- if (responseBody.getInt(STATUS_CODE_LABEL) == SUCCESS_CODE) {
- final JSONObject userJSONObject = responseBody.getJSONObject("user");
- final JSONObject data = userJSONObject.getJSONObject("info");
- return data.getString("note");
- }
- else {
- throw new DataAccessException(responseBody.getString(MESSAGE));
- }
- }
- catch (IOException | JSONException ex) {
- throw new RuntimeException(ex);
- }
- }
-}
diff --git a/src/main/java/data_access/PuzzleDataAccessObject.java b/src/main/java/data_access/PuzzleDataAccessObject.java
new file mode 100644
index 000000000..0a2f1f6af
--- /dev/null
+++ b/src/main/java/data_access/PuzzleDataAccessObject.java
@@ -0,0 +1,67 @@
+package data_access;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import use_case.daily_puzzle.PuzzleAccessException;
+import use_case.daily_puzzle.PuzzleDataAccessInterface;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class PuzzleDataAccessObject implements PuzzleDataAccessInterface {
+ private static final int SUCCESS_CODE = 200;
+ private static final String LICHESS_PUZZLE_URL = "https://lichess.org/api/puzzle/";
+ private static final String DAILY_PUZZLE_URL = "daily";
+ private static String PUZZLE_FROM_ID_URL;
+
+ public ArrayList getDaily() throws PuzzleAccessException {
+ final OkHttpClient client = new OkHttpClient().newBuilder().build();
+ final Request request = new Request.Builder().url(LICHESS_PUZZLE_URL + DAILY_PUZZLE_URL).build();
+ ArrayList output = null;
+
+ try {
+ final Response response = client.newCall(request).execute();
+
+ final JSONObject responseBody = new JSONObject(response.body().string());
+
+ JSONObject puzzle = responseBody.getJSONObject("puzzle");
+ JSONArray solution = puzzle.getJSONArray("solution");
+ output.add(puzzle.getString("id"));
+ for (int i = 0; i < solution.length(); i++) {
+ output.add(solution.getString(i));
+ }
+ }
+ catch (final IOException | JSONException e) {
+ throw new PuzzleAccessException(e.getMessage());
+ }
+ return output;
+ }
+
+ @Override
+ public ArrayList fetchPuzzle(String id) throws PuzzleAccessException {
+ final OkHttpClient client = new OkHttpClient().newBuilder().build();
+ final Request request = new Request.Builder().url(LICHESS_PUZZLE_URL + PUZZLE_FROM_ID_URL).build();
+ ArrayList output = null;
+
+ try {
+ final Response response = client.newCall(request).execute();
+
+ final JSONObject responseBody = new JSONObject(response.body().string());
+
+ JSONArray solution = responseBody.getJSONArray("solution");
+ output.add(responseBody.getJSONObject("game").getString("pgn"));
+ for (int i = 0; i < solution.length(); i++) {
+ output.add(solution.getString(i));
+ }
+ }
+ catch (final IOException | JSONException e) {
+ throw new PuzzleAccessException(e.getMessage());
+ }
+ return output;
+ }
+}
diff --git a/src/main/java/data_access/QueryDataAccessObject.java b/src/main/java/data_access/QueryDataAccessObject.java
new file mode 100644
index 000000000..0680dfa34
--- /dev/null
+++ b/src/main/java/data_access/QueryDataAccessObject.java
@@ -0,0 +1,60 @@
+package data_access;
+
+import entity.RankHistory;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import use_case.query.QueryDataAccessInterface;
+
+import java.io.IOException;
+
+/**
+ * The DAO for accessing user rank history stored in the database.
+ */
+public class QueryDataAccessObject implements QueryDataAccessInterface {
+ @Override
+ public RankHistory showRankHistory(String username) {
+
+ final RankHistory rankHistory = new RankHistory();
+
+ final String url = String.format("https://lichess.org/api/user/%s/rating-history", username);
+ final OkHttpClient client = new OkHttpClient().newBuilder().build();
+ final Request request = new Request.Builder()
+ .url(url)
+ .build();
+
+ try (Response response = client.newCall(request).execute()) {
+
+ final String responseBody = response.body().string();
+ final com.alibaba.fastjson.JSONArray jsonArray = com.alibaba.fastjson.JSONArray.parseArray(responseBody);
+
+ jsonArray.stream().forEach(str -> {
+ final com.alibaba.fastjson.JSONObject jsonObject =
+ com.alibaba.fastjson.JSONObject.parseObject(str.toString());
+
+ final String name = (String) jsonObject.get("name");
+ if ("Puzzles".equals(name)) {
+ final Object points = jsonObject.get("points");
+ final com.alibaba.fastjson.JSONArray pointarr =
+ com.alibaba.fastjson.JSONArray.parseArray(points.toString());
+
+ final Object[] objects = pointarr.toArray();
+
+ for (Object object : objects) {
+ final com.alibaba.fastjson.JSONArray ranks =
+ com.alibaba.fastjson.JSONArray.parseArray(object.toString());
+ final int year = (Integer) ranks.get(0);
+ final int month = (Integer) ranks.get(1);
+ final int day = (Integer) ranks.get(2);
+ final int rank = (Integer) ranks.get(3);
+ rankHistory.addRankHistory(year, month, day, rank);
+ }
+ }
+ });
+ return rankHistory;
+ }
+ catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+}
diff --git a/src/main/java/data_access/UserDataAccessObject.java b/src/main/java/data_access/UserDataAccessObject.java
new file mode 100644
index 000000000..ab175b910
--- /dev/null
+++ b/src/main/java/data_access/UserDataAccessObject.java
@@ -0,0 +1,44 @@
+package data_access;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import entity.User;
+import use_case.login.LoginUserDataAccessInterface;
+import use_case.showProfile.ShowProfileUserDataAccessInterface;
+import use_case.signup.SignupUserDataAccessInterface;
+
+/**
+ * The DAO for user data.
+ */
+public class UserDataAccessObject implements LoginUserDataAccessInterface, SignupUserDataAccessInterface,
+ ShowProfileUserDataAccessInterface {
+
+ private final Map users = new HashMap<>();
+ private String currentUser;
+
+ @Override
+ public User get(String username) {
+ return users.get(username);
+ }
+
+ @Override
+ public void setCurrentUser(String name) {
+ this.currentUser = name;
+ }
+
+ @Override
+ public String getCurrentUser() {
+ return currentUser;
+ }
+
+ @Override
+ public boolean existsByName(String username) {
+ return users.containsKey(username);
+ }
+
+ @Override
+ public void save(User user) {
+ users.put(user.getName(), user);
+ }
+}
diff --git a/src/main/java/entity/Bishop.java b/src/main/java/entity/Bishop.java
new file mode 100644
index 000000000..ca54f1397
--- /dev/null
+++ b/src/main/java/entity/Bishop.java
@@ -0,0 +1,72 @@
+package entity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * The bishop class.
+ */
+public class Bishop extends ChessPiece {
+ public Bishop(String color, int xCoord, int yCoord) {
+ super(color, xCoord, yCoord);
+ }
+
+ /**
+ * Returns all possible moves for a bishop from the given position on an 8x8 chessboard.
+ *
+ * @return A list of int arrays, each representing a valid move [newX, newY].
+ */
+ @SuppressWarnings({"unchecked", "checkstyle:MagicNumber", "checkstyle:SuppressWarnings"})
+ @Override
+ public T getValidMoves() {
+ // Create an ArrayList to hold four ArrayLists (one for each direction)
+ final ArrayList> validMoves = new ArrayList<>();
+
+ // Initialize four ArrayLists for each diagonal direction
+ final ArrayList upLeft = new ArrayList<>();
+ final ArrayList upRight = new ArrayList<>();
+ final ArrayList downLeft = new ArrayList<>();
+ final ArrayList downRight = new ArrayList<>();
+
+ final int x = this.getPosition()[0];
+ final int y = this.getPosition()[1];
+
+ // Up-Left Diagonal
+ int i = 1;
+ while (x - i >= 0 && y - i >= 0) {
+ upLeft.add(0, new int[]{x - i, y - i});
+ i++;
+ }
+
+ // Up-Right Diagonal
+ i = 1;
+ while (x + i < 8 && y - i >= 0) {
+ upRight.add(0, new int[]{x + i, y - i});
+ i++;
+ }
+
+ // Down-Left Diagonal
+ i = 1;
+ while (x - i >= 0 && y + i < 8) {
+ downLeft.add(0, new int[]{x - i, y + i});
+ i++;
+ }
+
+ // Down-Right Diagonal
+ i = 1;
+ while (x + i < 8 && y + i < 8) {
+ downRight.add(0, new int[]{x + i, y + i});
+ i++;
+ }
+ Collections.reverse(upLeft);
+ Collections.reverse(upRight);
+ Collections.reverse(downLeft);
+ Collections.reverse(downRight);
+ validMoves.add(upLeft);
+ validMoves.add(upRight);
+ validMoves.add(downLeft);
+ validMoves.add(downRight);
+
+ return (T) validMoves;
+ }
+}
diff --git a/src/main/java/entity/Board.java b/src/main/java/entity/Board.java
new file mode 100644
index 000000000..ecea5d3dd
--- /dev/null
+++ b/src/main/java/entity/Board.java
@@ -0,0 +1,116 @@
+package entity;
+
+import org.json.JSONObject;
+
+/**
+ * The chess board entity.
+ */
+public class Board {
+ private ChessPiece[][] grid;
+
+ @SuppressWarnings("checkstyle:MagicNumber")
+ public Board() {
+ final ChessPiece[][] chessGrid = new ChessPiece[8][8];
+
+ final String white = "White";
+ chessGrid[0][0] = new Rook(white, 0, 0);
+ chessGrid[0][1] = new Knight(white, 0, 1);
+ chessGrid[0][2] = new Bishop(white, 0, 2);
+ chessGrid[0][3] = new Queen(white, 0, 3);
+ chessGrid[0][4] = new King(white, 0, 4);
+ chessGrid[0][5] = new Bishop(white, 0, 5);
+ chessGrid[0][6] = new Knight(white, 0, 6);
+ chessGrid[0][7] = new Rook(white, 0, 7);
+ for (int i = 0; i < 8; i++) {
+ chessGrid[1][i] = new Pawn(white, 1, i);
+ }
+
+ final String black = "Black";
+ chessGrid[7][0] = new Rook(black, 7, 0);
+ chessGrid[7][1] = new Knight(black, 7, 1);
+ chessGrid[7][2] = new Bishop(black, 7, 2);
+ chessGrid[7][3] = new Queen(black, 7, 3);
+ chessGrid[7][4] = new King(black, 7, 4);
+ chessGrid[7][5] = new Bishop(black, 7, 5);
+ chessGrid[7][6] = new Knight(black, 7, 6);
+ chessGrid[7][7] = new Rook(black, 7, 7);
+ for (int i = 0; i < 8; i++) {
+ chessGrid[6][i] = new Pawn(black, 6, i);
+ }
+
+ for (int row = 2; row < 6; row++) {
+ for (int col = 0; col < 8; col++) {
+ chessGrid[row][col] = null;
+ }
+ }
+ this.grid = chessGrid;
+ }
+
+ public Board(JSONObject boardFile) {
+ // will call some other method to read the file, placeholder for now.
+ }
+
+ /**
+ * Returns if a tile is empty.
+ *
+ * @param position position of piece
+ * @return bool
+ */
+ public boolean isEmpty(int[] position) {
+ return grid[position[0]][position[1]] == null;
+ }
+
+ /**
+ * Returns the chess piece at a given tile.
+ *
+ * @param position position of piece
+ * @return Chesspiece
+ */
+ public ChessPiece getPiece(int[] position) {
+ return grid[position[0]][position[1]];
+ }
+
+ /**
+ * Moves a piece to the specified position on the board.
+ *
+ * @param position The new position (x, y) for the piece.
+ * @param piece The piece to move.
+ */
+ public void moveToLocation(int[] position, ChessPiece piece) {
+ grid[piece.getPosition()[0]][piece.getPosition()[1]] = null;
+ piece.setPosition(position);
+ grid[position[0]][position[1]] = piece;
+ }
+
+ /**
+ * Checks if the game is over by determining if either king is missing.
+ *
+ * @return "None" if both kings are present, "Black" if the white king is missing,
+ * "White" if the black king is missing.
+ */
+ public String over() {
+ boolean whiteKingPresent = false;
+ boolean blackKingPresent = false;
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++) {
+ if (grid[i][j] instanceof King) {
+ if (grid[i][j].getColor().equals("White")) {
+ whiteKingPresent = true;
+ }
+ else {
+ blackKingPresent = true;
+ }
+ }
+ }
+ }
+ if (whiteKingPresent && blackKingPresent) {
+ return "None";
+ }
+ else if (whiteKingPresent) {
+ return "Black";
+ }
+ else {
+ return "White";
+ }
+ }
+}
diff --git a/src/main/java/entity/ChessPiece.java b/src/main/java/entity/ChessPiece.java
new file mode 100644
index 000000000..b37995972
--- /dev/null
+++ b/src/main/java/entity/ChessPiece.java
@@ -0,0 +1,36 @@
+package entity;
+
+/**
+ * The abstract class of all chess piece.
+ */
+@SuppressWarnings({"checkstyle:AbstractClassName", "checkstyle:SuppressWarnings"})
+public abstract class ChessPiece {
+ private final String color;
+ private int[] position;
+
+ protected ChessPiece(String color, int xCoordinate, int yCoordinate) {
+ this.color = color;
+ this.position = new int[2];
+ position[0] = xCoordinate;
+ position[1] = yCoordinate;
+ }
+
+ /**
+ * The abstract class for getting the valid moves of a piece.
+ * @param type of return value.
+ * @return return a list of valid moves.
+ */
+ public abstract T getValidMoves();
+
+ public String getColor() {
+ return color;
+ }
+
+ public int[] getPosition() {
+ return this.position;
+ }
+
+ public void setPosition(int[] position) {
+ this.position = position;
+ }
+}
diff --git a/src/main/java/entity/Game.java b/src/main/java/entity/Game.java
new file mode 100644
index 000000000..37b3b2058
--- /dev/null
+++ b/src/main/java/entity/Game.java
@@ -0,0 +1,57 @@
+package entity;
+
+public class Game {
+ private final Board board;
+ private boolean gameOver;
+ private boolean whiteTurn; //if whiteturn is false, then its blacks turn
+ private boolean selectMode; //if select mode is false, game is in movemode.
+ private ChessPiece chesspiece_to_move;
+
+ public Game(Board board, boolean whiteTurn) {
+ this.board = board;
+ this.gameOver = false;
+ this.whiteTurn = whiteTurn;
+ this.selectMode = true;
+ this.chesspiece_to_move = null;
+ }
+
+ public void switchTurn() {
+ if (whiteTurn) {
+ whiteTurn = false;
+ }
+ else {
+ whiteTurn = true;
+ }
+ }
+
+ public boolean getCurrentPlayer() {
+ return this.whiteTurn;
+ }
+
+ public ChessPiece getChesspiece_to_move() {
+ return chesspiece_to_move;
+ }
+
+ public void setChesspiece_to_move(ChessPiece chesspiece_to_move) {
+ this.chesspiece_to_move = chesspiece_to_move;
+ }
+
+ public void switchMode() {
+ if (selectMode) {
+ selectMode = false;
+ }
+ else {
+ selectMode = true;
+ }
+ }
+
+ public boolean getGameMode() {
+ return selectMode;
+ }
+
+ public Board getBoard() {
+ return board;
+ }
+
+
+}
diff --git a/src/main/java/entity/King.java b/src/main/java/entity/King.java
new file mode 100644
index 000000000..b31ad099b
--- /dev/null
+++ b/src/main/java/entity/King.java
@@ -0,0 +1,32 @@
+package entity;
+
+import java.util.ArrayList;
+
+
+/**
+ * King piece.
+ */
+public class King extends ChessPiece {
+ public King(String color, int x, int y) {
+ super(color, x, y);
+ }
+
+ /**
+ * Returns all possible moves for a king from the given position on an 8x8 chessboard.
+ *
+ * @return A list of int arrays, each representing a valid move [newX, newY].
+ */
+ @Override
+ public T getValidMoves() {
+ final ArrayList validMoves = new ArrayList<>();
+ final int x = this.getPosition()[0];
+ final int y = this.getPosition()[1];
+ validMoves.add(new int[]{x + 1, y});
+ validMoves.add(new int[]{x - 1, y});
+ validMoves.add(new int[]{x, y - 1});
+ validMoves.add(new int[]{x, y + 1});
+ validMoves.removeIf(move -> move[0] < 0 || move[0] >= 8 || move[1] < 0 || move[1] >= 8);
+ return (T) validMoves;
+
+ }
+}
diff --git a/src/main/java/entity/Knight.java b/src/main/java/entity/Knight.java
new file mode 100644
index 000000000..8194c44c4
--- /dev/null
+++ b/src/main/java/entity/Knight.java
@@ -0,0 +1,41 @@
+package entity;
+
+import java.util.ArrayList;
+
+
+/**
+ * Knight piece.
+ */
+public class Knight extends ChessPiece {
+ public Knight(String color, int x, int y) {
+ super(color, x, y);
+ }
+
+ /**
+ * Returns all possible moves for a knight from the given position on an 8x8 chessboard.
+ *
+ * @return A list of int arrays, each representing a valid move [newX, newY].
+ */
+ @Override
+ public T getValidMoves() {
+ final ArrayList validMoves = new ArrayList<>();
+ final int x = this.getPosition()[0];
+ final int y = this.getPosition()[1];
+
+ final int[][] potentialMoves = {
+ {x + 2, y + 1}, {x + 2, y - 1},
+ {x - 2, y + 1}, {x - 2, y - 1},
+ {x + 1, y + 2}, {x + 1, y - 2},
+ {x - 1, y + 2}, {x - 1, y - 2}
+ };
+
+ // Add valid moves within board boundaries (0 to 7)
+ for (int[] move : potentialMoves) {
+ if (move[0] >= 0 && move[0] < 8 && move[1] >= 0 && move[1] < 8) {
+ validMoves.add(move);
+ }
+ }
+
+ return (T) validMoves;
+ }
+}
diff --git a/src/main/java/entity/Pawn.java b/src/main/java/entity/Pawn.java
new file mode 100644
index 000000000..e0bdea624
--- /dev/null
+++ b/src/main/java/entity/Pawn.java
@@ -0,0 +1,38 @@
+package entity;
+
+import java.util.ArrayList;
+
+public class Pawn extends ChessPiece {
+ public Pawn(String color, int x, int y) {
+ super(color, x, y);
+ }
+
+ /**
+ * Returns all possible moves for a pawn from the given position on an 8x8 chessboard.
+ * @return A list of int arrays, each representing a valid move [newX, newY].
+ */
+ @Override
+ public T getValidMoves() {
+ final ArrayList validMoves = new ArrayList<>();
+ final int x = this.getPosition()[0];
+ final int y = this.getPosition()[1];
+
+ if (this.getColor().equals("White") && x != 7) {
+ validMoves.add(new int[]{x + 1, y - 1});
+ validMoves.add(new int[]{x + 1, y + 1});
+ validMoves.add(new int[]{x + 1, y});
+ if (x == 1) {
+ validMoves.add(new int[]{x + 2, y});
+ }
+ } else if (this.getColor().equals("Black") && x != 0) {
+ validMoves.add(new int[]{x - 1, y - 1});
+ validMoves.add(new int[]{x - 1, y + 1});
+ validMoves.add(new int[]{x - 1, y});
+ if (x == 6) {
+ validMoves.add(new int[]{x - 2, y});
+ }
+ }
+
+ return (T) validMoves;
+ }
+}
diff --git a/src/main/java/entity/Queen.java b/src/main/java/entity/Queen.java
new file mode 100644
index 000000000..90e0f8cfe
--- /dev/null
+++ b/src/main/java/entity/Queen.java
@@ -0,0 +1,94 @@
+package entity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * Queen Class.
+ */
+public class Queen extends ChessPiece {
+ public Queen(String color, int x, int y) {
+ super(color, x, y);
+ }
+
+ /**
+ * Returns all possible moves for a bishop from the given position on an 8x8 chessboard.
+ *
+ * @return A list of int arrays, each representing a valid move [newX, newY].
+ */
+ @SuppressWarnings({"checkstyle:CyclomaticComplexity", "checkstyle:MagicNumber", "checkstyle:SuppressWarnings"})
+ public T getValidMoves() {
+ final ArrayList> validMoves = new ArrayList<>();
+ // Initialize four ArrayLists for each diagonal direction
+ final ArrayList upLeft = new ArrayList<>();
+ final ArrayList upRight = new ArrayList<>();
+ final ArrayList downLeft = new ArrayList<>();
+ final ArrayList downRight = new ArrayList<>();
+
+ final int x = this.getPosition()[0];
+ final int y = this.getPosition()[1];
+
+ // Up-Left Diagonal
+ int i = 1;
+ while (x - i >= 0 && y - i >= 0) {
+ upLeft.add(0, new int[]{x - i, y - i});
+ i++;
+ }
+
+ // Up-Right Diagonal
+ i = 1;
+ while (x + i < 8 && y - i >= 0) {
+ upRight.add(0, new int[]{x + i, y - i});
+ i++;
+ }
+
+ // Down-Left Diagonal
+ i = 1;
+ while (x - i >= 0 && y + i < 8) {
+ downLeft.add(0, new int[]{x - i, y + i});
+ i++;
+ }
+
+ // Down-Right Diagonal
+ i = 1;
+ while (x + i < 8 && y + i < 8) {
+ downRight.add(0, new int[]{x + i, y + i});
+ i++;
+ }
+ Collections.reverse(upLeft);
+ Collections.reverse(upRight);
+ Collections.reverse(downLeft);
+ Collections.reverse(downRight);
+ validMoves.add(upLeft);
+ validMoves.add(upRight);
+ validMoves.add(downLeft);
+ validMoves.add(downRight);
+
+ final ArrayList upMoves = new ArrayList<>();
+ final ArrayList downMoves = new ArrayList<>();
+ final ArrayList leftMoves = new ArrayList<>();
+ final ArrayList rightMoves = new ArrayList<>();
+
+ for (int j = y - 1; j >= 0; j--) {
+ upMoves.add(new int[] {x, j});
+ }
+
+ for (int j = y + 1; j < 8; j++) {
+ downMoves.add(new int[] {x, j});
+ }
+
+ for (int j = x - 1; j >= 0; j--) {
+ leftMoves.add(new int[] {j, y});
+ }
+
+ for (int j = x + 1; j < 8; j++) {
+ rightMoves.add(new int[] {j, y});
+ }
+
+ validMoves.add(upMoves);
+ validMoves.add(downMoves);
+ validMoves.add(leftMoves);
+ validMoves.add(rightMoves);
+ return (T) validMoves;
+ }
+}
diff --git a/src/main/java/entity/RankHistory.java b/src/main/java/entity/RankHistory.java
new file mode 100644
index 000000000..e13cd9842
--- /dev/null
+++ b/src/main/java/entity/RankHistory.java
@@ -0,0 +1,64 @@
+package entity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The representation of user rank history for our program.
+ */
+
+public class RankHistory {
+ private final List rankHistoryList;
+
+ public RankHistory() {
+ this.rankHistoryList = new ArrayList<>();
+ }
+
+ public List getRanks() {
+ return rankHistoryList;
+ }
+
+ /**
+ * Print the RankHistory.
+ */
+ public void printRankHistory() {
+ for (Rank rank : rankHistoryList) {
+ System.out.println(rank);
+ }
+ }
+
+ /**
+ * Add user rank for our program.
+ * @param year the rank year.
+ * @param month the rank month.
+ * @param day the rank day.
+ * @param rank the rank .
+ */
+ public void addRankHistory(int year, int month, int day, int rank) {
+ final Rank rh = new Rank(year, month, day, rank);
+ this.rankHistoryList.add(rh);
+ }
+
+ /**
+ * The representation of user rank for our program.
+ */
+ public static class Rank {
+ private final int year;
+ private final int month;
+ private final int day;
+ private final int rank;
+
+ public Rank(int year, int month, int day, int rank) {
+ this.year = year;
+ this.month = month + 1;
+ this.day = day;
+ this.rank = rank;
+ }
+
+ @Override
+ public String toString() {
+ return "Year:" + year + " Month:" + month
+ + " Day:" + day + " Rank:" + rank;
+ }
+ }
+}
diff --git a/src/main/java/entity/Rook.java b/src/main/java/entity/Rook.java
new file mode 100644
index 000000000..4286543fc
--- /dev/null
+++ b/src/main/java/entity/Rook.java
@@ -0,0 +1,52 @@
+package entity;
+
+import java.util.ArrayList;
+
+/**
+ * The class that defines the rook piece.
+ */
+public class Rook extends ChessPiece {
+ public Rook(String color, int x, int y) {
+ super(color, x, y);
+ }
+ /**
+ * Return valid moves.
+ */
+
+ @Override
+ public T getValidMoves() {
+ final ArrayList> validMoves = new ArrayList<>();
+
+ ArrayList upMoves = new ArrayList<>();
+ ArrayList downMoves = new ArrayList<>();
+ ArrayList leftMoves = new ArrayList<>();
+ ArrayList rightMoves = new ArrayList<>();
+
+ final int x = this.getPosition()[0];
+ final int y = this.getPosition()[1];
+
+ for (int i = y - 1; i >= 0; i--) {
+ upMoves.add(new int[] {x, i});
+ }
+
+ for (int i = y + 1; i < 8; i++) {
+ downMoves.add(new int[] {x, i});
+ }
+
+ for (int i = x - 1; i >= 0; i--) {
+ leftMoves.add(new int[] {i, y});
+ }
+
+ for (int i = x + 1; i < 8; i++) {
+ rightMoves.add(new int[] {i, y});
+ }
+
+ validMoves.add(upMoves);
+ validMoves.add(downMoves);
+ validMoves.add(leftMoves);
+ validMoves.add(rightMoves);
+
+ return (T) validMoves;
+ }
+
+}
diff --git a/src/main/java/entity/User.java b/src/main/java/entity/User.java
index e0c57e9a6..398ccef03 100644
--- a/src/main/java/entity/User.java
+++ b/src/main/java/entity/User.java
@@ -1,5 +1,7 @@
package entity;
+import java.util.ArrayList;
+
/**
* The representation of a password-protected user for our program.
*/
@@ -7,10 +9,13 @@ public class User {
private final String name;
private final String password;
+ private ArrayList rankPointHistory;
public User(String name, String password) {
this.name = name;
this.password = password;
+ this.rankPointHistory = new ArrayList<>();
+ this.rankPointHistory.add(0);
}
public String getName() {
@@ -21,4 +26,24 @@ public String getPassword() {
return password;
}
+ public ArrayList getRankPointHistory() {
+ return rankPointHistory;
+ }
+
+ /**
+ * Return current rankPoint, last element of 'rankPointHistory'.
+ * @return current rankPoint, last element of 'rankPointHistory'
+ */
+ public int getCurrentRankPoint() {
+ return rankPointHistory.get(rankPointHistory.size() - 1);
+ }
+
+ /**
+ * This method add latest rankPoint to the end of rankPointHistory.
+ * @param rankPoint is the new rankPoint after one puzzle finished
+ */
+ public void addRankPointHistory(int rankPoint) {
+ this.rankPointHistory.add(rankPoint);
+ }
+
}
diff --git a/src/main/java/interface_adapter/ViewManagerModel.java b/src/main/java/interface_adapter/ViewManagerModel.java
new file mode 100644
index 000000000..99dc0ffe5
--- /dev/null
+++ b/src/main/java/interface_adapter/ViewManagerModel.java
@@ -0,0 +1,14 @@
+package interface_adapter;
+
+/**
+ * Model for the View Manager. Its state is the name of the View which
+ * is currently active. An initial state of "" is used.
+ */
+public class ViewManagerModel extends ViewModel {
+
+ public ViewManagerModel() {
+ super("view manager");
+ this.setState("");
+ }
+
+}
diff --git a/src/main/java/interface_adapter/ViewModel.java b/src/main/java/interface_adapter/ViewModel.java
index 130d797a1..4c06a9080 100644
--- a/src/main/java/interface_adapter/ViewModel.java
+++ b/src/main/java/interface_adapter/ViewModel.java
@@ -14,7 +14,7 @@ public class ViewModel {
private final String viewName;
- private final PropertyChangeSupport support = new PropertyChangeSupport(this);
+ protected final PropertyChangeSupport support = new PropertyChangeSupport(this);
private T state;
@@ -53,6 +53,10 @@ public void firePropertyChanged(String propertyName) {
this.support.firePropertyChange(propertyName, null, this.state);
}
+ public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
+ this.support.firePropertyChange(propertyName, oldValue, newValue);
+ }
+
/**
* Adds a PropertyChangeListener to this ViewModel.
* @param listener The PropertyChangeListener to be added
diff --git a/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleController.java b/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleController.java
new file mode 100644
index 000000000..4325bcf51
--- /dev/null
+++ b/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleController.java
@@ -0,0 +1,22 @@
+package interface_adapter.daily_puzzle;
+
+import use_case.daily_puzzle.DailyPuzzleInputboundary;
+
+/**
+ * Controller for the daily puzzle use case.
+ */
+public class DailyPuzzleController {
+
+ private DailyPuzzleInputboundary dailyPuzzleInteractor;
+
+ public DailyPuzzleController(DailyPuzzleInputboundary interactor) {
+ this.dailyPuzzleInteractor = interactor;
+ }
+
+ /**
+ * Executes the daily puzzle use case.
+ */
+ public void execute() {
+ dailyPuzzleInteractor.executeDailyPuzzle();
+ }
+}
diff --git a/src/main/java/interface_adapter/daily_puzzle/DailyPuzzlePresenter.java b/src/main/java/interface_adapter/daily_puzzle/DailyPuzzlePresenter.java
new file mode 100644
index 000000000..8bc1ac684
--- /dev/null
+++ b/src/main/java/interface_adapter/daily_puzzle/DailyPuzzlePresenter.java
@@ -0,0 +1,36 @@
+package interface_adapter.daily_puzzle;
+
+import java.util.ArrayList;
+
+import use_case.daily_puzzle.DailyPuzzleOutputBoundary;
+
+/**
+ * The presenter for daily puzzles.
+ */
+public class DailyPuzzlePresenter implements DailyPuzzleOutputBoundary {
+
+ private final DailyPuzzleViewModel dailyPuzzleViewModel;
+
+ public DailyPuzzlePresenter(DailyPuzzleViewModel dailyPuzzleViewModel) {
+ this.dailyPuzzleViewModel = dailyPuzzleViewModel;
+ }
+
+ /**
+ * Prepares the success view for the daily puzzle use case.
+ * @param puzzleData contains puzzle setup and solution.
+ */
+ @Override
+ public void prepareSuccessView(ArrayList puzzleData) {
+
+ }
+
+ /**
+ * Prepares failure view for daily puzzle.
+ * @param errorMessage Explanation of the failure
+ */
+ @Override
+ public void prepareFailView(String errorMessage) {
+ dailyPuzzleViewModel.getState().setError(errorMessage);
+ dailyPuzzleViewModel.firePropertyChanged();
+ }
+}
diff --git a/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleState.java b/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleState.java
new file mode 100644
index 000000000..85b8e9b39
--- /dev/null
+++ b/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleState.java
@@ -0,0 +1,34 @@
+package interface_adapter.daily_puzzle;
+
+import entity.Board;
+
+/**
+ * The state for a daily puzzle.
+ */
+public class DailyPuzzleState {
+ private static final String ROOK = "♖";
+ private static final String BISHOP = "♗";
+ private static final String QUEEN = "♕";
+ private static final String KING = "♔";
+ private static final String KNIGHT = "♘";
+ private static final String PAWN = "♙";
+ private Board board;
+ private String error;
+
+ public Board getBoard() {
+ return board;
+ }
+
+ public void setBoard(Board board) {
+ this.board = board;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+}
diff --git a/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleViewModel.java b/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleViewModel.java
new file mode 100644
index 000000000..ad42ee0fe
--- /dev/null
+++ b/src/main/java/interface_adapter/daily_puzzle/DailyPuzzleViewModel.java
@@ -0,0 +1,13 @@
+package interface_adapter.daily_puzzle;
+
+import interface_adapter.ViewModel;
+
+/**
+ * ViewModel for daily puzzle.
+ */
+public class DailyPuzzleViewModel extends ViewModel {
+ public DailyPuzzleViewModel() {
+ super("daily puzzle");
+ setState(new DailyPuzzleState());
+ }
+}
diff --git a/src/main/java/interface_adapter/logged_in/LoggedInController.java b/src/main/java/interface_adapter/logged_in/LoggedInController.java
new file mode 100644
index 000000000..6169be369
--- /dev/null
+++ b/src/main/java/interface_adapter/logged_in/LoggedInController.java
@@ -0,0 +1,22 @@
+package interface_adapter.logged_in;
+
+import use_case.logged_in.LoggedInInputBoundary;
+
+/**
+ * Controller for the Signup Use Case.
+ */
+public class LoggedInController {
+
+ private final LoggedInInputBoundary userLoggedInUseCaseInteractor;
+
+ public LoggedInController(LoggedInInputBoundary userLoggedInUseCaseInteractor) {
+ this.userLoggedInUseCaseInteractor = userLoggedInUseCaseInteractor;
+ }
+
+ /**
+ * Executes the "switch to SignUpView" Use Case.
+ */
+ public void switchToSignUpView() {
+ userLoggedInUseCaseInteractor.switchToSignUpView();
+ }
+}
diff --git a/src/main/java/interface_adapter/logged_in/LoggedInPresenter.java b/src/main/java/interface_adapter/logged_in/LoggedInPresenter.java
new file mode 100644
index 000000000..6d6128ac2
--- /dev/null
+++ b/src/main/java/interface_adapter/logged_in/LoggedInPresenter.java
@@ -0,0 +1,42 @@
+package interface_adapter.logged_in;
+
+import interface_adapter.ViewManagerModel;
+import interface_adapter.signup.SignupViewModel;
+import use_case.logged_in.LoggedInOutputBoundary;
+
+/**
+ * The Presenter for the Change Password Use Case.
+ */
+public class LoggedInPresenter implements LoggedInOutputBoundary {
+
+ private final LoggedInViewModel loggedInViewModel;
+ private final SignupViewModel signupViewModel;
+ private final ViewManagerModel viewManagerModel;
+
+ public LoggedInPresenter(ViewManagerModel viewManagerModel,
+ LoggedInViewModel loggedInViewModel,
+ SignupViewModel signupViewModel) {
+ this.viewManagerModel = viewManagerModel;
+ this.loggedInViewModel = loggedInViewModel;
+ this.signupViewModel = signupViewModel;
+ }
+
+ public void prepareSuccessView(String username) {
+ final LoggedInState state = loggedInViewModel.getState();
+ state.setUsername(username);
+ loggedInViewModel.setState(state);
+ loggedInViewModel.firePropertyChanged();
+
+ }
+
+ public void prepareFailView(String error) {
+ loggedInViewModel.setState(new LoggedInState());
+ loggedInViewModel.firePropertyChanged();
+ }
+
+ @Override
+ public void switchToSignUpView() {
+ viewManagerModel.setState(signupViewModel.getViewName());
+ viewManagerModel.firePropertyChanged();
+ }
+}
diff --git a/src/main/java/interface_adapter/logged_in/LoggedInState.java b/src/main/java/interface_adapter/logged_in/LoggedInState.java
new file mode 100644
index 000000000..4f7fca6ed
--- /dev/null
+++ b/src/main/java/interface_adapter/logged_in/LoggedInState.java
@@ -0,0 +1,36 @@
+package interface_adapter.logged_in;
+
+/**
+ * The State information representing the logged-in user.
+ */
+public class LoggedInState {
+ private String username = "";
+ private String password = "";
+
+ public LoggedInState(LoggedInState copy) {
+ username = copy.username;
+ password = copy.password;
+ }
+
+ // Because of the previous copy constructor, the default constructor must be explicit.
+ public LoggedInState() {
+
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+}
diff --git a/src/main/java/interface_adapter/logged_in/LoggedInViewModel.java b/src/main/java/interface_adapter/logged_in/LoggedInViewModel.java
new file mode 100644
index 000000000..6398183cc
--- /dev/null
+++ b/src/main/java/interface_adapter/logged_in/LoggedInViewModel.java
@@ -0,0 +1,19 @@
+package interface_adapter.logged_in;
+
+import interface_adapter.ViewModel;
+
+/**
+ * The View Model for the Logged In View.
+ */
+public class LoggedInViewModel extends ViewModel {
+
+ public LoggedInViewModel() {
+ super("logged in");
+ setState(new LoggedInState());
+ }
+
+ public String getUsername() {
+ return getState().getUsername();
+ }
+
+}
diff --git a/src/main/java/interface_adapter/login/LoginController.java b/src/main/java/interface_adapter/login/LoginController.java
new file mode 100644
index 000000000..5ec3363ee
--- /dev/null
+++ b/src/main/java/interface_adapter/login/LoginController.java
@@ -0,0 +1,35 @@
+package interface_adapter.login;
+
+import use_case.login.LoginInputBoundary;
+import use_case.login.LoginInputData;
+
+/**
+ * The controller for the Login Use Case.
+ */
+public class LoginController {
+
+ private final LoginInputBoundary loginUseCaseInteractor;
+
+ public LoginController(LoginInputBoundary loginUseCaseInteractor) {
+ this.loginUseCaseInteractor = loginUseCaseInteractor;
+ }
+
+ /**
+ * Executes the Login Use Case.
+ * @param username the username of the user logging in
+ * @param password the password of the user logging in
+ */
+ public void execute(String username, String password) {
+ final LoginInputData loginInputData = new LoginInputData(
+ username, password);
+
+ loginUseCaseInteractor.execute(loginInputData);
+ }
+
+ /**
+ * Executes the "switch to SignUpView" Use Case.
+ */
+ public void switchToSignUpView() {
+ loginUseCaseInteractor.switchToSignUpView();
+ }
+}
diff --git a/src/main/java/interface_adapter/login/LoginPresenter.java b/src/main/java/interface_adapter/login/LoginPresenter.java
new file mode 100644
index 000000000..3b0ff9e0e
--- /dev/null
+++ b/src/main/java/interface_adapter/login/LoginPresenter.java
@@ -0,0 +1,55 @@
+package interface_adapter.login;
+
+import interface_adapter.ViewManagerModel;
+import interface_adapter.logged_in.LoggedInState;
+import interface_adapter.logged_in.LoggedInViewModel;
+import interface_adapter.signup.SignupViewModel;
+import use_case.login.LoginOutputBoundary;
+import use_case.login.LoginOutputData;
+
+/**
+ * The Presenter for the Login Use Case.
+ */
+public class LoginPresenter implements LoginOutputBoundary {
+
+ private final LoginViewModel loginViewModel;
+ private final LoggedInViewModel loggedInViewModel;
+ private final ViewManagerModel viewManagerModel;
+ private final SignupViewModel signupViewModel;
+
+ public LoginPresenter(ViewManagerModel viewManagerModel,
+ LoggedInViewModel loggedInViewModel,
+ LoginViewModel loginViewModel,
+ SignupViewModel signupViewModel) {
+ this.viewManagerModel = viewManagerModel;
+ this.loggedInViewModel = loggedInViewModel;
+ this.loginViewModel = loginViewModel;
+ this.signupViewModel = signupViewModel;
+ }
+
+ @Override
+ public void prepareSuccessView(LoginOutputData response) {
+ // On success, switch to the logged in view.
+
+ final LoggedInState loggedInState = loggedInViewModel.getState();
+ loggedInState.setUsername(response.getUsername());
+ this.loggedInViewModel.setState(loggedInState);
+ this.loggedInViewModel.firePropertyChanged();
+
+ this.viewManagerModel.setState(loggedInViewModel.getViewName());
+ this.viewManagerModel.firePropertyChanged();
+ }
+
+ @Override
+ public void prepareFailView(String error) {
+ final LoginState loginState = loginViewModel.getState();
+ loginState.setLoginError(error);
+ loginViewModel.firePropertyChanged();
+ }
+
+ @Override
+ public void switchToSignUpView() {
+ viewManagerModel.setState(signupViewModel.getViewName());
+ viewManagerModel.firePropertyChanged();
+ }
+}
diff --git a/src/main/java/interface_adapter/login/LoginState.java b/src/main/java/interface_adapter/login/LoginState.java
new file mode 100644
index 000000000..11117fe42
--- /dev/null
+++ b/src/main/java/interface_adapter/login/LoginState.java
@@ -0,0 +1,36 @@
+package interface_adapter.login;
+
+/**
+ * The state for the Login View Model.
+ */
+public class LoginState {
+ private String username = "";
+ private String loginError;
+ private String password = "";
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getLoginError() {
+ return loginError;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setLoginError(String usernameError) {
+ this.loginError = usernameError;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+}
+
diff --git a/src/main/java/interface_adapter/login/LoginViewModel.java b/src/main/java/interface_adapter/login/LoginViewModel.java
new file mode 100644
index 000000000..b24171c03
--- /dev/null
+++ b/src/main/java/interface_adapter/login/LoginViewModel.java
@@ -0,0 +1,16 @@
+package interface_adapter.login;
+
+import interface_adapter.ViewModel;
+
+/**
+ * The View Model for the Login View.
+ */
+public class LoginViewModel extends ViewModel {
+
+ public LoginViewModel() {
+ super("log in");
+ setState(new LoginState());
+ }
+
+}
+
diff --git a/src/main/java/interface_adapter/move/MoveController.java b/src/main/java/interface_adapter/move/MoveController.java
new file mode 100644
index 000000000..d89e1fc9c
--- /dev/null
+++ b/src/main/java/interface_adapter/move/MoveController.java
@@ -0,0 +1,28 @@
+package interface_adapter.move;
+
+import use_case.move.MoveInputBoundary;
+import use_case.move.MoveInputdata;
+/**
+ * The controller for the Move Use Case.
+ */
+
+public class MoveController {
+ private final MoveInputBoundary moveInteractor;
+
+ public MoveController(MoveInputBoundary moveInteractor) {
+ this.moveInteractor = moveInteractor;
+ }
+
+ /**
+ * Convert the data into ArrayList and delegate the execution to move interactor.
+ * @param xcord the horizontal coordinate form 0 to 7
+ * @param ycord the horizontal coordinate form 0 to 7
+ */
+ public void onClick(Integer xcord, Integer ycord) {
+ final int[] position = new int[2];
+ position[0] = xcord;
+ position[1] = ycord;
+ final MoveInputdata moveInputdata = new MoveInputdata(position);
+ moveInteractor.execute(moveInputdata);
+ }
+}
diff --git a/src/main/java/interface_adapter/move/MovePresenter.java b/src/main/java/interface_adapter/move/MovePresenter.java
new file mode 100644
index 000000000..f163ef262
--- /dev/null
+++ b/src/main/java/interface_adapter/move/MovePresenter.java
@@ -0,0 +1,82 @@
+package interface_adapter.move;
+
+import interface_adapter.ViewManagerModel;
+import java.util.ArrayList;
+import use_case.move.MoveOutputBoundary;
+import use_case.move.MoveOutputdata;
+
+/**
+ * The presenter for Move use case.
+ */
+public class MovePresenter implements MoveOutputBoundary {
+ private final MoveViewModel moveViewModel;
+ private final ViewManagerModel viewManagerModel;
+
+ public MovePresenter(MoveViewModel moveViewModel, ViewManagerModel viewManagerModel) {
+ this.moveViewModel = moveViewModel;
+ this.viewManagerModel = viewManagerModel;
+ }
+
+ public void prepareMove(MoveOutputdata input) {
+ String[][] pieces = new String[8][8];
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++) {
+ if (input.getBoard().isEmpty(new int[] {i, j})) {
+ pieces[7 - i][j] = null;
+ } else {
+ if (input.getBoard().getPiece(new int[] {i, j}) instanceof entity.Bishop) {
+ if (input.getBoard().getPiece(new int[] {i, j}).getColor().equals("White")) {
+ pieces[7 - i][j] = "♗";
+ } else {
+ pieces[7 - i][j] = "♝";
+ }
+ }
+ else if (input.getBoard().getPiece(new int[] {i, j}) instanceof entity.Rook) {
+ if (input.getBoard().getPiece(new int[] {i, j}).getColor().equals("White")) {
+ pieces[7 - i][j] = "♖";
+ } else {
+ pieces[7 - i][j] = "♜";
+ }
+ }
+ else if (input.getBoard().getPiece(new int[] {i, j}) instanceof entity.Knight) {
+ if (input.getBoard().getPiece(new int[] {i, j}).getColor().equals("White")) {
+ pieces[7 - i][j] = "♘";
+ } else {
+ pieces[7 - i][j] = "♞";
+ }
+ }
+ else if (input.getBoard().getPiece(new int[] {i, j}) instanceof entity.Pawn) {
+ if (input.getBoard().getPiece(new int[] {i, j}).getColor().equals("White")) {
+ pieces[7 - i][j] = "♙";
+ } else {
+ pieces[7 - i][j] = "♟";
+ }
+ }
+ else if (input.getBoard().getPiece(new int[] {i, j}) instanceof entity.Queen) {
+ if (input.getBoard().getPiece(new int[] {i, j}).getColor().equals("White")) {
+ pieces[7 - i][j] = "♕";
+ } else {
+ pieces[7-i][j]= "♛";
+ }
+ }
+ else if (input.getBoard().getPiece(new int[] {i, j}) instanceof entity.King) {
+ if (input.getBoard().getPiece(new int[] {i, j}).getColor().equals("White")) {
+ pieces[7 - i][j] = "♔";
+ } else {
+ pieces[7 - i][j] = "♚";
+ }
+ }
+ }
+
+ }
+ }
+ ArrayList validMoves = input.getValidMoves();
+ for (int[] move : validMoves) {
+ pieces[7-move[0]][move[1]] = "Valid";
+ }
+
+ moveViewModel.setPieces(pieces);
+ // present the select chess board
+ }
+
+}
diff --git a/src/main/java/interface_adapter/move/MoveState.java b/src/main/java/interface_adapter/move/MoveState.java
new file mode 100644
index 000000000..9abd2f4c7
--- /dev/null
+++ b/src/main/java/interface_adapter/move/MoveState.java
@@ -0,0 +1,4 @@
+package interface_adapter.move;
+
+public class MoveState {
+}
diff --git a/src/main/java/interface_adapter/move/MoveViewModel.java b/src/main/java/interface_adapter/move/MoveViewModel.java
new file mode 100644
index 000000000..04f3664a0
--- /dev/null
+++ b/src/main/java/interface_adapter/move/MoveViewModel.java
@@ -0,0 +1,41 @@
+package interface_adapter.move;
+
+import interface_adapter.ViewModel;
+import view.ChessBoardView;
+
+/**
+ * The ViewModel for the MoveView.
+ */
+public class MoveViewModel extends ViewModel {
+
+ public static final String TITLE_LABEL = "Move View";
+ private String[][] piece;
+ private final String[][] pieces = {
+ {"♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜"}, // Black major pieces
+ {"♟", "♟", "♟", "♟", "♟", "♟", "♟", "♟"}, // Black pawns
+ {null, null, null, null, null, null, null, null}, // Empty row with one Valid move
+ {null, null, null, null, null, null, null, null}, // Empty row
+ {null, null, null, null, null, null, null, null}, // Empty row
+ {null, null, null, null, null, null, null, null}, // Empty row
+ {"♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙"}, // White pawns
+ {"♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"} // White major pieces
+ };
+
+ public MoveViewModel() {
+ super("move");
+ this.piece = pieces;
+ setState(new MoveState());
+ }
+
+ public String[][] getPieces() {
+ return piece;
+ }
+
+ public void setPieces(String[][] input) {
+ String[][] oldPieces = this.piece; // Save the current state
+ this.piece = input; // Update with new state
+ support.firePropertyChange("pieces", oldPieces, input);
+
+ }
+
+}
diff --git a/src/main/java/interface_adapter/note/NoteController.java b/src/main/java/interface_adapter/note/NoteController.java
deleted file mode 100644
index e3e5dfb32..000000000
--- a/src/main/java/interface_adapter/note/NoteController.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package interface_adapter.note;
-
-import use_case.note.NoteInputBoundary;
-
-/**
- * Controller for our Note related Use Cases.
- */
-public class NoteController {
-
- private final NoteInputBoundary noteInteractor;
-
- public NoteController(NoteInputBoundary noteInteractor) {
- this.noteInteractor = noteInteractor;
- }
-
- /**
- * Executes the Note related Use Cases.
- * @param note the note to be recorded
- */
- public void execute(String note) {
- if (note != null) {
- noteInteractor.executeSave(note);
- }
- else {
- noteInteractor.executeRefresh();
- }
- }
-}
diff --git a/src/main/java/interface_adapter/note/NotePresenter.java b/src/main/java/interface_adapter/note/NotePresenter.java
deleted file mode 100644
index d4e416165..000000000
--- a/src/main/java/interface_adapter/note/NotePresenter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package interface_adapter.note;
-
-import use_case.note.NoteOutputBoundary;
-
-/**
- * The presenter for our Note viewing and editing program.
- */
-public class NotePresenter implements NoteOutputBoundary {
-
- private final NoteViewModel noteViewModel;
-
- public NotePresenter(NoteViewModel noteViewModel) {
- this.noteViewModel = noteViewModel;
- }
-
- /**
- * Prepares the success view for the Note related Use Cases.
- *
- * @param note the output data
- */
- @Override
- public void prepareSuccessView(String note) {
- noteViewModel.getState().setNote(note);
- noteViewModel.getState().setError(null);
- noteViewModel.firePropertyChanged();
- }
-
- /**
- * Prepares the failure view for the Note related Use Cases.
- *
- * @param errorMessage the explanation of the failure
- */
- @Override
- public void prepareFailView(String errorMessage) {
- noteViewModel.getState().setError(errorMessage);
- noteViewModel.firePropertyChanged();
- }
-}
diff --git a/src/main/java/interface_adapter/note/NoteState.java b/src/main/java/interface_adapter/note/NoteState.java
deleted file mode 100644
index c5b2234d6..000000000
--- a/src/main/java/interface_adapter/note/NoteState.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package interface_adapter.note;
-
-/**
- * The State for a note.
- * For this example, a note is simplay a string.
- */
-public class NoteState {
- private String note = "";
- private String error;
-
- public String getNote() {
- return note;
- }
-
- public void setNote(String note) {
- this.note = note;
- }
-
- public void setError(String errorMessage) {
- this.error = errorMessage;
- }
-
- public String getError() {
- return error;
- }
-}
diff --git a/src/main/java/interface_adapter/note/NoteViewModel.java b/src/main/java/interface_adapter/note/NoteViewModel.java
deleted file mode 100644
index 6e185d0fa..000000000
--- a/src/main/java/interface_adapter/note/NoteViewModel.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package interface_adapter.note;
-
-import interface_adapter.ViewModel;
-
-/**
- * The ViewModel for the NoteView.
- */
-public class NoteViewModel extends ViewModel {
- public NoteViewModel() {
- super("note");
- setState(new NoteState());
- }
-}
diff --git a/src/main/java/interface_adapter/query/QueryController.java b/src/main/java/interface_adapter/query/QueryController.java
new file mode 100644
index 000000000..8bb2cadd6
--- /dev/null
+++ b/src/main/java/interface_adapter/query/QueryController.java
@@ -0,0 +1,23 @@
+package interface_adapter.query;
+
+import use_case.query.QueryInputBoundary;
+
+/**
+ * The controller for the query use case.
+ */
+public class QueryController {
+
+ private final QueryInputBoundary queryInteractor;
+
+ public QueryController(QueryInputBoundary queryInteractor) {
+ this.queryInteractor = queryInteractor;
+ }
+
+ /**
+ * Execute the query use case.
+ * @param username the username of the user logging in
+ */
+ public void execute(String username) {
+ queryInteractor.execute(username);
+ }
+}
diff --git a/src/main/java/interface_adapter/query/QueryPresenter.java b/src/main/java/interface_adapter/query/QueryPresenter.java
new file mode 100644
index 000000000..aa5b152a4
--- /dev/null
+++ b/src/main/java/interface_adapter/query/QueryPresenter.java
@@ -0,0 +1,46 @@
+package interface_adapter.query;
+
+import entity.RankHistory;
+import interface_adapter.ViewManagerModel;
+import use_case.query.QueryOutputBoundary;
+
+/**
+ * The presenter for query viewing.
+ */
+public class QueryPresenter implements QueryOutputBoundary {
+
+ private final QueryViewModel queryViewModel;
+ private final ViewManagerModel viewManagerModel;
+
+ public QueryPresenter(QueryViewModel queryViewModel, ViewManagerModel viewManagerModel) {
+ this.queryViewModel = queryViewModel;
+ this.viewManagerModel = viewManagerModel;
+ }
+
+ /**
+ * Prepares the success view for the query related Use Cases.
+ *
+ * @param rankHistoryList the user rank history data.
+ */
+ @Override
+ public void prepareSuccessView(RankHistory rankHistoryList) {
+ // On success, switch to the Query view.
+ final QueryState queryState = queryViewModel.getState();
+ queryState.setRankHistoryList(rankHistoryList);
+ this.queryViewModel.setState(queryState);
+ this.queryViewModel.firePropertyChanged();
+
+ this.viewManagerModel.setState(queryViewModel.getViewName());
+ this.viewManagerModel.firePropertyChanged();
+ }
+
+ /**
+ * Prepares the failure view for the query related Use Cases.
+ *
+ * @param errorMessage the explanation of the failure
+ */
+ @Override
+ public void prepareFailView(String errorMessage) {
+
+ }
+}
diff --git a/src/main/java/interface_adapter/query/QueryState.java b/src/main/java/interface_adapter/query/QueryState.java
new file mode 100644
index 000000000..66ce0bef6
--- /dev/null
+++ b/src/main/java/interface_adapter/query/QueryState.java
@@ -0,0 +1,22 @@
+package interface_adapter.query;
+
+import entity.RankHistory;
+
+/**
+ * The State information representing the query user.
+ */
+public class QueryState {
+ private RankHistory rankHistoryList;
+
+ public QueryState() {
+
+ }
+
+ public void setRankHistoryList(RankHistory rankHistoryList) {
+ this.rankHistoryList = rankHistoryList;
+ }
+
+ public RankHistory getRankHistoryList() {
+ return rankHistoryList;
+ }
+}
diff --git a/src/main/java/interface_adapter/query/QueryViewModel.java b/src/main/java/interface_adapter/query/QueryViewModel.java
new file mode 100644
index 000000000..54c56cff8
--- /dev/null
+++ b/src/main/java/interface_adapter/query/QueryViewModel.java
@@ -0,0 +1,20 @@
+package interface_adapter.query;
+
+import entity.RankHistory;
+import interface_adapter.ViewModel;
+
+/**
+ * The View Model for the query view.
+ */
+public class QueryViewModel extends ViewModel {
+
+ public QueryViewModel() {
+ super("query");
+ setState(new QueryState());
+ }
+
+ public RankHistory getRankHistoryList() {
+ return getState().getRankHistoryList();
+ }
+
+}
diff --git a/src/main/java/interface_adapter/showProfile/ShowProfileController.java b/src/main/java/interface_adapter/showProfile/ShowProfileController.java
new file mode 100644
index 000000000..6222b8f7a
--- /dev/null
+++ b/src/main/java/interface_adapter/showProfile/ShowProfileController.java
@@ -0,0 +1,26 @@
+package interface_adapter.showProfile;
+
+import use_case.showProfile.ShowProfileInputBoundary;
+import use_case.showProfile.ShowProfileInputData;
+
+/**
+ * The controller for the ShowProfile use case.
+ */
+public class ShowProfileController {
+
+ private final ShowProfileInputBoundary showProfileInputInteractor;
+
+ public ShowProfileController(ShowProfileInputBoundary showProfileInteractor) {
+ this.showProfileInputInteractor = showProfileInteractor;
+ }
+
+ /**
+ * Execute the showProfile use case.
+ * @param username the username of the user logging in
+ */
+ public void execute(String username) {
+ final ShowProfileInputData showProfileInputData = new ShowProfileInputData(username);
+
+ showProfileInputInteractor.execute(showProfileInputData);
+ }
+}
diff --git a/src/main/java/interface_adapter/showProfile/ShowProfilePresenter.java b/src/main/java/interface_adapter/showProfile/ShowProfilePresenter.java
new file mode 100644
index 000000000..4ae8a8fbf
--- /dev/null
+++ b/src/main/java/interface_adapter/showProfile/ShowProfilePresenter.java
@@ -0,0 +1,36 @@
+package interface_adapter.showProfile;
+
+import interface_adapter.ViewManagerModel;
+import use_case.showProfile.ShowProfileOutputBoundary;
+import use_case.showProfile.ShowProfileOutputData;
+import view.ViewManager;
+
+public class ShowProfilePresenter implements ShowProfileOutputBoundary {
+
+ private final ShowProfileViewModel showProfileViewModel;
+ private final ViewManagerModel viewManagerModel;
+
+ public ShowProfilePresenter(ShowProfileViewModel showProfileViewModel, ViewManagerModel viewManagerModel) {
+ this.showProfileViewModel = showProfileViewModel;
+ this.viewManagerModel = viewManagerModel;
+ }
+
+ @Override
+ public void prepareSuccessView(ShowProfileOutputData outputData) {
+ // On success, switch to the Profile view.
+
+ final ShowProfileState showProfileState = showProfileViewModel.getState();
+ showProfileState.setUsername(outputData.getUsername());
+ showProfileState.setRankPoint(outputData.getRankPoint());
+ this.showProfileViewModel.setState(showProfileState);
+ this.showProfileViewModel.firePropertyChanged();
+
+ this.viewManagerModel.setState(showProfileViewModel.getViewName());
+ this.viewManagerModel.firePropertyChanged();
+ }
+
+ @Override
+ public void prepareFailView(String errorMessage) {
+
+ }
+}
diff --git a/src/main/java/interface_adapter/showProfile/ShowProfileState.java b/src/main/java/interface_adapter/showProfile/ShowProfileState.java
new file mode 100644
index 000000000..3b523b0ed
--- /dev/null
+++ b/src/main/java/interface_adapter/showProfile/ShowProfileState.java
@@ -0,0 +1,30 @@
+package interface_adapter.showProfile;
+
+/**
+ * The State information representing the logged-in user.
+ */
+public class ShowProfileState {
+ private String username = "";
+ private int rankPoint;
+
+ public ShowProfileState() {
+
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setRankPoint(int rankPoint) {
+ this.rankPoint = rankPoint;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public int getRankPoint() {
+ return rankPoint;
+ }
+
+}
diff --git a/src/main/java/interface_adapter/showProfile/ShowProfileViewModel.java b/src/main/java/interface_adapter/showProfile/ShowProfileViewModel.java
new file mode 100644
index 000000000..d32b490ff
--- /dev/null
+++ b/src/main/java/interface_adapter/showProfile/ShowProfileViewModel.java
@@ -0,0 +1,22 @@
+package interface_adapter.showProfile;
+
+import interface_adapter.ViewModel;
+
+/**
+ * The View Model for the profile view.
+ */
+public class ShowProfileViewModel extends ViewModel {
+
+ public ShowProfileViewModel() {
+ super("showProfile");
+ setState(new ShowProfileState());
+ }
+
+ public String getUsername() {
+ return getState().getUsername();
+ }
+
+ public int getRankPoint() {
+ return getState().getRankPoint();
+ }
+}
diff --git a/src/main/java/interface_adapter/signup/SignupController.java b/src/main/java/interface_adapter/signup/SignupController.java
new file mode 100644
index 000000000..c01d25aa5
--- /dev/null
+++ b/src/main/java/interface_adapter/signup/SignupController.java
@@ -0,0 +1,36 @@
+package interface_adapter.signup;
+
+import use_case.signup.SignupInputBoundary;
+import use_case.signup.SignupInputData;
+
+/**
+ * Controller for the Signup Use Case.
+ */
+public class SignupController {
+
+ private final SignupInputBoundary userSignupUseCaseInteractor;
+
+ public SignupController(SignupInputBoundary userSignupUseCaseInteractor) {
+ this.userSignupUseCaseInteractor = userSignupUseCaseInteractor;
+ }
+
+ /**
+ * Executes the Signup Use Case.
+ * @param username the username to sign up
+ * @param password1 the password
+ * @param password2 the password repeated
+ */
+ public void execute(String username, String password1, String password2) {
+ final SignupInputData signupInputData = new SignupInputData(
+ username, password1, password2);
+
+ userSignupUseCaseInteractor.execute(signupInputData);
+ }
+
+ /**
+ * Executes the "switch to LoginView" Use Case.
+ */
+ public void switchToLoginView() {
+ userSignupUseCaseInteractor.switchToLoginView();
+ }
+}
diff --git a/src/main/java/interface_adapter/signup/SignupPresenter.java b/src/main/java/interface_adapter/signup/SignupPresenter.java
new file mode 100644
index 000000000..9b654077e
--- /dev/null
+++ b/src/main/java/interface_adapter/signup/SignupPresenter.java
@@ -0,0 +1,50 @@
+package interface_adapter.signup;
+
+import interface_adapter.ViewManagerModel;
+import interface_adapter.login.LoginState;
+import interface_adapter.login.LoginViewModel;
+import use_case.signup.SignupOutputBoundary;
+import use_case.signup.SignupOutputData;
+
+/**
+ * The Presenter for the Signup Use Case.
+ */
+public class SignupPresenter implements SignupOutputBoundary {
+
+ private final SignupViewModel signupViewModel;
+ private final LoginViewModel loginViewModel;
+ private final ViewManagerModel viewManagerModel;
+
+ public SignupPresenter(ViewManagerModel viewManagerModel,
+ SignupViewModel signupViewModel,
+ LoginViewModel loginViewModel) {
+ this.viewManagerModel = viewManagerModel;
+ this.signupViewModel = signupViewModel;
+ this.loginViewModel = loginViewModel;
+ }
+
+ @Override
+ public void prepareSuccessView(SignupOutputData response) {
+ // On success, switch to the login view.
+ final LoginState loginState = loginViewModel.getState();
+ loginState.setUsername(response.getUsername());
+ this.loginViewModel.setState(loginState);
+ loginViewModel.firePropertyChanged();
+
+ viewManagerModel.setState(loginViewModel.getViewName());
+ viewManagerModel.firePropertyChanged();
+ }
+
+ @Override
+ public void prepareFailView(String error) {
+ final SignupState signupState = signupViewModel.getState();
+ signupState.setUsernameError(error);
+ signupViewModel.firePropertyChanged();
+ }
+
+ @Override
+ public void switchToLoginView() {
+ viewManagerModel.setState(loginViewModel.getViewName());
+ viewManagerModel.firePropertyChanged();
+ }
+}
diff --git a/src/main/java/interface_adapter/signup/SignupState.java b/src/main/java/interface_adapter/signup/SignupState.java
new file mode 100644
index 000000000..82337802a
--- /dev/null
+++ b/src/main/java/interface_adapter/signup/SignupState.java
@@ -0,0 +1,71 @@
+package interface_adapter.signup;
+
+/**
+ * The state for the Signup View Model.
+ */
+public class SignupState {
+ private String username = "";
+ private String usernameError;
+ private String password = "";
+ private String passwordError;
+ private String repeatPassword = "";
+ private String repeatPasswordError;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getUsernameError() {
+ return usernameError;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public String getPasswordError() {
+ return passwordError;
+ }
+
+ public String getRepeatPassword() {
+ return repeatPassword;
+ }
+
+ public String getRepeatPasswordError() {
+ return repeatPasswordError;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setUsernameError(String usernameError) {
+ this.usernameError = usernameError;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public void setPasswordError(String passwordError) {
+ this.passwordError = passwordError;
+ }
+
+ public void setRepeatPassword(String repeatPassword) {
+ this.repeatPassword = repeatPassword;
+ }
+
+ public void setRepeatPasswordError(String repeatPasswordError) {
+ this.repeatPasswordError = repeatPasswordError;
+ }
+
+ @Override
+ public String toString() {
+ return "SignupState{"
+ + "username='" + username + '\''
+ + ", password='" + password + '\''
+ + ", repeatPassword='" + repeatPassword + '\''
+ + '}';
+ }
+}
+
diff --git a/src/main/java/interface_adapter/signup/SignupViewModel.java b/src/main/java/interface_adapter/signup/SignupViewModel.java
new file mode 100644
index 000000000..29fe7b57c
--- /dev/null
+++ b/src/main/java/interface_adapter/signup/SignupViewModel.java
@@ -0,0 +1,26 @@
+package interface_adapter.signup;
+
+import interface_adapter.ViewModel;
+
+/**
+ * The ViewModel for the Signup View.
+ */
+public class SignupViewModel extends ViewModel {
+
+ public static final String TITLE_LABEL = "Sign Up View";
+ public static final String USERNAME_LABEL = "Choose username";
+ public static final String PASSWORD_LABEL = "Choose password";
+ public static final String REPEAT_PASSWORD_LABEL = "Enter password again";
+
+ public static final String SIGNUP_BUTTON_LABEL = "Sign up";
+ public static final String CANCEL_BUTTON_LABEL = "Cancel";
+
+ public static final String TO_LOGIN_BUTTON_LABEL = "Go to Login";
+
+ public SignupViewModel() {
+ super("sign up");
+ setState(new SignupState());
+ }
+
+}
+
diff --git a/src/main/java/use_case/daily_puzzle/DailyPuzzleDataAccessInterface.java b/src/main/java/use_case/daily_puzzle/DailyPuzzleDataAccessInterface.java
new file mode 100644
index 000000000..d905ee1a8
--- /dev/null
+++ b/src/main/java/use_case/daily_puzzle/DailyPuzzleDataAccessInterface.java
@@ -0,0 +1,7 @@
+package use_case.daily_puzzle;
+
+/**
+ * DAO for Daily Puzzle use case.
+ */
+public interface DailyPuzzleDataAccessInterface {
+}
diff --git a/src/main/java/use_case/daily_puzzle/DailyPuzzleInputboundary.java b/src/main/java/use_case/daily_puzzle/DailyPuzzleInputboundary.java
new file mode 100644
index 000000000..9b44e9a0a
--- /dev/null
+++ b/src/main/java/use_case/daily_puzzle/DailyPuzzleInputboundary.java
@@ -0,0 +1,12 @@
+package use_case.daily_puzzle;
+
+/**
+ * Input boundary for the daily puzzle use case.
+ */
+public interface DailyPuzzleInputboundary {
+
+ /**
+ * Executes daily puzzle use case.
+ */
+ void executeDailyPuzzle();
+}
diff --git a/src/main/java/use_case/daily_puzzle/DailyPuzzleInteractor.java b/src/main/java/use_case/daily_puzzle/DailyPuzzleInteractor.java
new file mode 100644
index 000000000..0ec891688
--- /dev/null
+++ b/src/main/java/use_case/daily_puzzle/DailyPuzzleInteractor.java
@@ -0,0 +1,32 @@
+package use_case.daily_puzzle;
+
+import java.util.ArrayList;
+
+/**
+ * The daily puzzle interactor.
+ */
+public class DailyPuzzleInteractor {
+ private final PuzzleDataAccessInterface dailyPuzzleDataAccessInterface;
+ private final DailyPuzzleOutputBoundary dailyPuzzleOutputBoundary;
+
+ public DailyPuzzleInteractor(PuzzleDataAccessInterface dailyPuzzleDataAccessInterface, DailyPuzzleOutputBoundary dailyPuzzleOutputBoundary) {
+ this.dailyPuzzleDataAccessInterface = dailyPuzzleDataAccessInterface;
+ this.dailyPuzzleOutputBoundary = dailyPuzzleOutputBoundary;
+ }
+
+ /**
+ * Executes the use case.
+ * @throws RuntimeException if API request fails.
+ */
+ public void execute() {
+
+ try {
+
+ final ArrayList puzzle = dailyPuzzleDataAccessInterface.getDaily();
+ dailyPuzzleOutputBoundary.prepareSuccessView(puzzle);
+ }
+ catch (Exception e) {
+ System.out.println("Error: " + e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/use_case/daily_puzzle/DailyPuzzleOutputBoundary.java b/src/main/java/use_case/daily_puzzle/DailyPuzzleOutputBoundary.java
new file mode 100644
index 000000000..eda4276dd
--- /dev/null
+++ b/src/main/java/use_case/daily_puzzle/DailyPuzzleOutputBoundary.java
@@ -0,0 +1,21 @@
+package use_case.daily_puzzle;
+
+import java.util.ArrayList;
+
+/**
+ * The output boundary for the Daily Puzzle Use case.
+ */
+public interface DailyPuzzleOutputBoundary {
+
+ /**
+ * Prepares the success view for the daily puzzle use case.
+ * @param outputData The puzzle's JSON file
+ */
+ void prepareSuccessView(ArrayList outputData);
+
+ /**
+ * Prepares the fail view for the daily puzzle use case.
+ * @param errorMessage Explanation of the failure
+ */
+ void prepareFailView(String errorMessage);
+}
diff --git a/src/main/java/use_case/daily_puzzle/DailyPuzzleOutputData.java b/src/main/java/use_case/daily_puzzle/DailyPuzzleOutputData.java
new file mode 100644
index 000000000..47c45919c
--- /dev/null
+++ b/src/main/java/use_case/daily_puzzle/DailyPuzzleOutputData.java
@@ -0,0 +1,23 @@
+package use_case.daily_puzzle;
+
+import java.util.ArrayList;
+
+/**
+ * Output data for the daily puzzle use case.
+ */
+public class DailyPuzzleOutputData {
+
+ private final ArrayList puzzle;
+
+ private final boolean useCaseFailed;
+
+ public DailyPuzzleOutputData(ArrayList puzzle, boolean useCaseFailed) {
+ this.puzzle = puzzle;
+ this.useCaseFailed = useCaseFailed;
+ }
+
+ public ArrayList getPuzzle() {
+ return puzzle;
+ }
+ // could change later to be board and this or the interactor will call for board generation.
+}
diff --git a/src/main/java/use_case/daily_puzzle/PuzzleAccessException.java b/src/main/java/use_case/daily_puzzle/PuzzleAccessException.java
new file mode 100644
index 000000000..360a1371f
--- /dev/null
+++ b/src/main/java/use_case/daily_puzzle/PuzzleAccessException.java
@@ -0,0 +1,8 @@
+package use_case.daily_puzzle;
+
+/**
+ * Exception thrown when a puzzle can't be returned.
+ */
+public class PuzzleAccessException extends Exception {
+ public PuzzleAccessException(String string) { super(string); }
+}
\ No newline at end of file
diff --git a/src/main/java/use_case/daily_puzzle/PuzzleDataAccessInterface.java b/src/main/java/use_case/daily_puzzle/PuzzleDataAccessInterface.java
new file mode 100644
index 000000000..12741b172
--- /dev/null
+++ b/src/main/java/use_case/daily_puzzle/PuzzleDataAccessInterface.java
@@ -0,0 +1,26 @@
+package use_case.daily_puzzle;
+
+import java.util.ArrayList;
+
+/**
+ * Interface for the Lichess api.
+ * It consists of methods for fetching a daily puzzle and a puzzle from id.
+ */
+public interface PuzzleDataAccessInterface {
+
+ /**
+ * Returns the daily puzzle's id and solutions
+ * @return The JSONObject corresponding to a puzzle
+ * @throws PuzzleAccessException if a puzzle cannot be fetched.
+ */
+ ArrayList getDaily() throws PuzzleAccessException;
+
+ /**
+ * Returns a puzzle's moves and solutions from puzzle id.
+ * @param id the id of the puzzle.
+ * @return strings of puzzle setup moves and puzzle solutions.
+ * @throws PuzzleAccessException If a puzzle cannot be fetched.
+ */
+ ArrayList fetchPuzzle(String id) throws PuzzleAccessException;
+
+}
diff --git a/src/main/java/use_case/logged_in/LoggedInInputBoundary.java b/src/main/java/use_case/logged_in/LoggedInInputBoundary.java
new file mode 100644
index 000000000..67659dd5e
--- /dev/null
+++ b/src/main/java/use_case/logged_in/LoggedInInputBoundary.java
@@ -0,0 +1,11 @@
+package use_case.logged_in;
+
+/**
+ * Input Boundary for actions which are related to signing up.
+ */
+public interface LoggedInInputBoundary {
+ /**
+ * Executes the switch to signup view use case.
+ */
+ void switchToSignUpView();
+}
diff --git a/src/main/java/use_case/logged_in/LoggedInInteractor.java b/src/main/java/use_case/logged_in/LoggedInInteractor.java
new file mode 100644
index 000000000..8962538b9
--- /dev/null
+++ b/src/main/java/use_case/logged_in/LoggedInInteractor.java
@@ -0,0 +1,17 @@
+package use_case.logged_in;
+
+/**
+ * The Signup Interactor.
+ */
+public class LoggedInInteractor implements LoggedInInputBoundary {
+ private final LoggedInOutputBoundary userPresenter;
+
+ public LoggedInInteractor(LoggedInOutputBoundary loggedInOutputBoundary) {
+ this.userPresenter = loggedInOutputBoundary;
+ }
+
+ @Override
+ public void switchToSignUpView() {
+ userPresenter.switchToSignUpView();
+ }
+}
diff --git a/src/main/java/use_case/logged_in/LoggedInOutputBoundary.java b/src/main/java/use_case/logged_in/LoggedInOutputBoundary.java
new file mode 100644
index 000000000..11a7710d6
--- /dev/null
+++ b/src/main/java/use_case/logged_in/LoggedInOutputBoundary.java
@@ -0,0 +1,8 @@
+package use_case.logged_in;
+
+public interface LoggedInOutputBoundary {
+ /**
+ * Switches to the Signup View.
+ */
+ void switchToSignUpView();
+}
diff --git a/src/main/java/use_case/login/LoginInputBoundary.java b/src/main/java/use_case/login/LoginInputBoundary.java
new file mode 100644
index 000000000..35d3bf853
--- /dev/null
+++ b/src/main/java/use_case/login/LoginInputBoundary.java
@@ -0,0 +1,17 @@
+package use_case.login;
+
+/**
+ * Input Boundary for actions which are related to logging in.
+ */
+public interface LoginInputBoundary {
+ /**
+ * Executes the login use case.
+ * @param loginInputData the input data
+ */
+ void execute(LoginInputData loginInputData);
+
+ /**
+ * Executes the switch to signup view use case.
+ */
+ void switchToSignUpView();
+}
diff --git a/src/main/java/use_case/login/LoginInputData.java b/src/main/java/use_case/login/LoginInputData.java
new file mode 100644
index 000000000..fceeb3c40
--- /dev/null
+++ b/src/main/java/use_case/login/LoginInputData.java
@@ -0,0 +1,23 @@
+package use_case.login;
+
+/**
+ * The Input Data for the Login Use Case.
+ */
+public class LoginInputData {
+
+ private final String username;
+ private final String password;
+
+ public LoginInputData(String username, String password) {
+ this.username = username;
+ this.password = password;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+}
diff --git a/src/main/java/use_case/login/LoginInteractor.java b/src/main/java/use_case/login/LoginInteractor.java
new file mode 100644
index 000000000..9d04c3692
--- /dev/null
+++ b/src/main/java/use_case/login/LoginInteractor.java
@@ -0,0 +1,44 @@
+package use_case.login;
+
+import entity.User;
+
+/**
+ * The Login Interactor.
+ */
+public class LoginInteractor implements LoginInputBoundary {
+ private final LoginUserDataAccessInterface userDataAccessObject;
+ private final LoginOutputBoundary loginPresenter;
+
+ public LoginInteractor(LoginUserDataAccessInterface userDataAccessInterface,
+ LoginOutputBoundary loginOutputBoundary) {
+ this.userDataAccessObject = userDataAccessInterface;
+ this.loginPresenter = loginOutputBoundary;
+ }
+
+ @Override
+ public void execute(LoginInputData loginInputData) {
+ final String username = loginInputData.getUsername();
+ final String password = loginInputData.getPassword();
+ if (!userDataAccessObject.existsByName(username)) {
+ loginPresenter.prepareFailView(username + ": Account does not exist.");
+ }
+ else {
+ final String pwd = userDataAccessObject.get(username).getPassword();
+ if (!password.equals(pwd)) {
+ loginPresenter.prepareFailView("Incorrect password for \"" + username + "\".");
+ }
+ else {
+
+ final User user = userDataAccessObject.get(loginInputData.getUsername());
+ userDataAccessObject.setCurrentUser(user.getName());
+ final LoginOutputData loginOutputData = new LoginOutputData(user.getName(), false);
+ loginPresenter.prepareSuccessView(loginOutputData);
+ }
+ }
+ }
+
+ @Override
+ public void switchToSignUpView() {
+ loginPresenter.switchToSignUpView();
+ }
+}
diff --git a/src/main/java/use_case/login/LoginOutputBoundary.java b/src/main/java/use_case/login/LoginOutputBoundary.java
new file mode 100644
index 000000000..f926e7785
--- /dev/null
+++ b/src/main/java/use_case/login/LoginOutputBoundary.java
@@ -0,0 +1,23 @@
+package use_case.login;
+
+/**
+ * The output boundary for the Login Use Case.
+ */
+public interface LoginOutputBoundary {
+ /**
+ * Prepares the success view for the Login Use Case.
+ * @param outputData the output data
+ */
+ void prepareSuccessView(LoginOutputData outputData);
+
+ /**
+ * Prepares the failure view for the Login Use Case.
+ * @param errorMessage the explanation of the failure
+ */
+ void prepareFailView(String errorMessage);
+
+ /**
+ * Switches to the Signup View.
+ */
+ void switchToSignUpView();
+}
diff --git a/src/main/java/use_case/login/LoginOutputData.java b/src/main/java/use_case/login/LoginOutputData.java
new file mode 100644
index 000000000..1ef2fbef5
--- /dev/null
+++ b/src/main/java/use_case/login/LoginOutputData.java
@@ -0,0 +1,22 @@
+package use_case.login;
+
+/**
+ * Output Data for the Login Use Case.
+ */
+public class LoginOutputData {
+ private final String username;
+ private final boolean useCaseFailed;
+
+ public LoginOutputData(String username, boolean useCaseFailed) {
+ this.username = username;
+ this.useCaseFailed = useCaseFailed;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public boolean isUseCaseFailed() {
+ return useCaseFailed;
+ }
+}
diff --git a/src/main/java/use_case/login/LoginUserDataAccessInterface.java b/src/main/java/use_case/login/LoginUserDataAccessInterface.java
new file mode 100644
index 000000000..4d4e631d2
--- /dev/null
+++ b/src/main/java/use_case/login/LoginUserDataAccessInterface.java
@@ -0,0 +1,33 @@
+package use_case.login;
+
+import entity.User;
+
+/**
+ * DAO for the Login Use Case.
+ */
+public interface LoginUserDataAccessInterface {
+
+ /**
+ * Checks if the given username exists.
+ * @param username the username to look for
+ * @return true if a user with the given username exists; false otherwise
+ */
+ boolean existsByName(String username);
+
+ /**
+ * Saves the user.
+ * @param user the user to save
+ */
+ void save(User user);
+
+ /**
+ * Returns the user with the given username.
+ * @param username the username to look up
+ * @return the user with the given username
+ */
+ User get(String username);
+
+ void setCurrentUser(String name);
+
+ String getCurrentUser();
+}
diff --git a/src/main/java/use_case/move/MoveDataAccessInterface.java b/src/main/java/use_case/move/MoveDataAccessInterface.java
new file mode 100644
index 000000000..b1b613e21
--- /dev/null
+++ b/src/main/java/use_case/move/MoveDataAccessInterface.java
@@ -0,0 +1,4 @@
+package use_case.move;
+
+public interface MoveDataAccessInterface {
+}
diff --git a/src/main/java/use_case/move/MoveInputBoundary.java b/src/main/java/use_case/move/MoveInputBoundary.java
new file mode 100644
index 000000000..5f3cd8617
--- /dev/null
+++ b/src/main/java/use_case/move/MoveInputBoundary.java
@@ -0,0 +1,12 @@
+package use_case.move;
+
+/**
+ * Input Boundary for actions which are related to moving.
+ */
+public interface MoveInputBoundary {
+ /**
+ * Executes the move use case.
+ * @param moveInputData the input data
+ */
+ void execute(MoveInputdata moveInputData);
+}
diff --git a/src/main/java/use_case/move/MoveInputdata.java b/src/main/java/use_case/move/MoveInputdata.java
new file mode 100644
index 000000000..26401730f
--- /dev/null
+++ b/src/main/java/use_case/move/MoveInputdata.java
@@ -0,0 +1,18 @@
+package use_case.move;
+import entity.Game;
+
+/**
+ * Input data for move use case.
+ */
+public class MoveInputdata {
+ private final int[] position;
+
+ public MoveInputdata(int[] input) {
+ this.position = new int[]{input[1], input[0]};
+ }
+
+ public int[] getPosition() {
+ return position;
+ }
+}
+
diff --git a/src/main/java/use_case/move/MoveInteractor.java b/src/main/java/use_case/move/MoveInteractor.java
new file mode 100644
index 000000000..76c8b2ca2
--- /dev/null
+++ b/src/main/java/use_case/move/MoveInteractor.java
@@ -0,0 +1,221 @@
+package use_case.move;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import entity.Bishop;
+import entity.ChessPiece;
+import entity.Game;
+import entity.King;
+import entity.Knight;
+import entity.Queen;
+import entity.Rook;
+
+/**
+ * Move interactor who handles the business logic of move.
+ */
+public class MoveInteractor implements MoveInputBoundary {
+ private final MoveDataAccessInterface moveDataAccessObject;
+ private final MoveOutputBoundary moveOutPutBoundary;
+ private final Game game;
+
+ public MoveInteractor(MoveDataAccessInterface moveDataAccessObject,
+ MoveOutputBoundary moveOutPutBoundary,
+ Game game) {
+ this.moveDataAccessObject = moveDataAccessObject;
+ this.moveOutPutBoundary = moveOutPutBoundary;
+ this.game = game;
+ }
+
+ /**
+ * Return a list of valid moves based on the chess game.
+ *
+ * @param chessPiece the piece
+ * @return return valid moves
+ */
+ @SuppressWarnings({"checkstyle:MagicNumber", "checkstyle:SuppressWarnings"})
+ private ArrayList validmoves(ChessPiece chessPiece) {
+ final ArrayList validList;
+ final ArrayList> listed;
+ if (chessPiece instanceof Knight || chessPiece instanceof King) {
+ validList = chessPiece.getValidMoves();
+ final Iterator iterator = validList.iterator();
+
+ while (iterator.hasNext()) {
+ final int[] pos = iterator.next();
+ if (game.getBoard().getPiece(pos) != null) {
+ if (game.getBoard().getPiece(pos).getColor().equals(chessPiece.getColor())) {
+ iterator.remove();
+ }
+ }
+ }
+ }
+ else if (chessPiece instanceof Bishop || chessPiece instanceof Rook) {
+ validList = new ArrayList<>();
+ listed = chessPiece.getValidMoves();
+
+ for (int i = 0; i <= 3; i++) {
+ for (int[] pos:listed.get(i)) {
+ if (game.getBoard().getPiece(pos) != null) {
+ if (game.getBoard().getPiece(pos).getColor().equals(chessPiece.getColor())) {
+ break;
+ }
+ else {
+ validList.add(pos);
+ break;
+ }
+ }
+ else {
+ validList.add(pos);
+ }
+ }
+ }
+
+ }
+ else if (chessPiece instanceof Queen) {
+ validList = new ArrayList<>();
+ listed = chessPiece.getValidMoves();
+ for (int i = 0; i <= 7; i++) {
+ for (int[] pos:listed.get(i)) {
+ if (game.getBoard().getPiece(pos) != null) {
+ if (game.getBoard().getPiece(pos).getColor().equals(chessPiece.getColor())) {
+ break;
+ }
+ else {
+ validList.add(pos);
+ break;
+ }
+ }
+ else {
+ validList.add(pos);
+ }
+ }
+ }
+
+ }
+ else {
+ validList = chessPiece.getValidMoves();
+
+ if (game.getBoard().getPiece(validList.get(2)) != null) {
+ validList.remove(2);
+ if (validList.size() == 3) {
+ validList.remove(2);
+ }
+ }
+ if (validList.get(1)[1] > 7 || validList.get(1)[1] < 0) {
+ validList.remove(1);
+ }
+ else if (game.getBoard().getPiece(validList.get(1)) != null) {
+ if (game.getBoard().getPiece(validList.get(1)).getColor().equals(chessPiece.getColor())) {
+ validList.remove(1);
+ }
+ }
+ else {
+ validList.remove(1);
+ }
+ if (validList.get(0)[1] > 7 || validList.get(0)[1] < 0) {
+ validList.remove(0);
+ }
+ else if (game.getBoard().getPiece(validList.get(0)) != null) {
+ if (game.getBoard().getPiece(validList.get(0)).getColor().equals(chessPiece.getColor())) {
+ validList.remove(0);
+ }
+ }
+ else {
+ validList.remove(0);
+ }
+ }
+ return validList;
+ }
+
+ @Override
+ public void execute(MoveInputdata position) {
+ final int[] pos = position.getPosition();
+ if (game.getGameMode()) {
+ select(pos);
+ }
+ else {
+ move(pos);
+ }
+ if (game.getBoard().over().equals("White")) {
+ // display white lost
+ }
+ else if (game.getBoard().over().equals("Black")) {
+ // display black lost
+ }
+
+ }
+
+ /**
+ * Executes the usecase when a piece is selected.
+ * @param position the position of the selected piece.
+ */
+ private void select(int[] position) {
+ final ChessPiece piece = game.getBoard().getPiece(position);
+ if (piece == null || game.getCurrentPlayer() && game.getBoard().getPiece(position).getColor().equals("Black")
+ || !game.getCurrentPlayer() && game.getBoard().getPiece(position).getColor().equals("White")) {
+ // Nothing happens since no piece selected
+ final MoveOutputdata nulldata = new MoveOutputdata(new ArrayList<>(), game.getBoard());
+ moveOutPutBoundary.prepareMove(nulldata);
+ }
+ else {
+ game.setChesspiece_to_move(piece);
+ game.switchMode();
+ final MoveOutputdata selectdata = new MoveOutputdata(validmoves(piece), game.getBoard());
+ moveOutPutBoundary.prepareMove(selectdata);
+ }
+ }
+
+ @SuppressWarnings({"checkstyle:MagicNumber", "checkstyle:SuppressWarnings"})
+ private void move(int[] pos) {
+ final ArrayList validmoves = validmoves(game.getChesspiece_to_move());
+
+ if (containsArray(validmoves, pos)) {
+ // Move the chess piece to location
+ game.getBoard().moveToLocation(pos, game.getChesspiece_to_move());
+ final MoveOutputdata movedata = new MoveOutputdata(new ArrayList<>(), game.getBoard());
+ moveOutPutBoundary.prepareMove(movedata);
+ game.switchMode();
+ game.switchTurn();
+ }
+ else if (game.getBoard().getPiece(pos) instanceof Rook
+ && game.getBoard().getPiece(new int[] {pos[0], pos[1] - 1}) == null
+ && game.getBoard().getPiece(new int[] {pos[0], pos[1] - 2}) == null
+ && game.getBoard().getPiece(new int[] {pos[0], pos[1] - 3}) instanceof King) {
+ final ChessPiece temp = game.getBoard().getPiece(pos);
+ game.getBoard().moveToLocation(new int[] {pos[0], pos[1] - 1}, game.getChesspiece_to_move());
+ game.getBoard().moveToLocation(new int[] {pos[0], pos[1] - 2}, temp);
+ final MoveOutputdata movedata = new MoveOutputdata(new ArrayList<>(), game.getBoard());
+ moveOutPutBoundary.prepareMove(movedata);
+ game.switchMode();
+ game.switchTurn();
+ }
+ else {
+ // Attempt to move to a invalid square
+ final MoveOutputdata nulldata = new MoveOutputdata(new ArrayList<>(), game.getBoard());
+ moveOutPutBoundary.prepareMove(nulldata);
+ game.switchMode();
+
+ }
+ }
+
+ /**
+ * Executes the usecase when a piece is selected.
+ * @param list The list of integer arrays to search through.
+ * @param target The target array to search for in the list.
+ * @return {@code true} if the target array is found in the list, {@code false} otherwise.
+ */
+ public static boolean containsArray(ArrayList list, int[] target) {
+ if (list == null || target == null) {
+ return false;
+ }
+ for (int[] array : list) {
+ if (Arrays.equals(array, target)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
diff --git a/src/main/java/use_case/move/MoveOutputBoundary.java b/src/main/java/use_case/move/MoveOutputBoundary.java
new file mode 100644
index 000000000..42a04de64
--- /dev/null
+++ b/src/main/java/use_case/move/MoveOutputBoundary.java
@@ -0,0 +1,5 @@
+package use_case.move;
+
+public interface MoveOutputBoundary {
+ void prepareMove(MoveOutputdata outputdata);
+}
diff --git a/src/main/java/use_case/move/MoveOutputdata.java b/src/main/java/use_case/move/MoveOutputdata.java
new file mode 100644
index 000000000..c0bd00423
--- /dev/null
+++ b/src/main/java/use_case/move/MoveOutputdata.java
@@ -0,0 +1,23 @@
+package use_case.move;
+
+import entity.Board;
+
+import java.util.ArrayList;
+
+public class MoveOutputdata {
+ private final ArrayList validMoves;
+ private final Board board; //This is yet to be changed.
+
+ public MoveOutputdata(ArrayList validMoves, Board board) {
+ this.validMoves = validMoves;
+ this.board = board;
+ }
+
+ public ArrayList getValidMoves() {
+ return validMoves;
+ }
+
+ public Board getBoard() {
+ return board;
+ }
+}
diff --git a/src/main/java/use_case/note/NoteDataAccessInterface.java b/src/main/java/use_case/note/NoteDataAccessInterface.java
deleted file mode 100644
index b71597828..000000000
--- a/src/main/java/use_case/note/NoteDataAccessInterface.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package use_case.note;
-
-import entity.User;
-
-/**
- * Interface for the NoteDAO. It consists of methods for
- * both loading and saving a note.
- */
-public interface NoteDataAccessInterface {
-
- /**
- * Saves a note for a given user. This will replace any existing note.
- * The password of the user must match that of the user saved in the system.
- * @param user the user information associated with the note
- * @param note the note to be saved
- * @return the contents of the note
- * @throws DataAccessException if the user's note can not be saved for any reason
- */
- String saveNote(User user, String note) throws DataAccessException;
-
- /**
- * Returns the note associated with the user. The password
- * is not checked, so anyone can read the information.
- * @param user the user information associated with the note
- * @return the contents of the note
- * @throws DataAccessException if the user's note can not be loaded for any reason
- */
- String loadNote(User user) throws DataAccessException;
-
-}
diff --git a/src/main/java/use_case/note/NoteInputBoundary.java b/src/main/java/use_case/note/NoteInputBoundary.java
deleted file mode 100644
index b41da9bf5..000000000
--- a/src/main/java/use_case/note/NoteInputBoundary.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package use_case.note;
-
-/**
- * The Input Boundary for our note-related use cases. Since they are closely related,
- * we have included them both in the same interface for simplicity.
- */
-public interface NoteInputBoundary {
-
- /**
- * Executes the refresh note use case.
- */
- void executeRefresh();
-
- /**
- * Executes the save note use case.
- * @param message the input data
- */
- void executeSave(String message);
-}
diff --git a/src/main/java/use_case/note/NoteInteractor.java b/src/main/java/use_case/note/NoteInteractor.java
deleted file mode 100644
index 369e9309a..000000000
--- a/src/main/java/use_case/note/NoteInteractor.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package use_case.note;
-
-import entity.User;
-
-/**
- * The "Use Case Interactor" for our two note-related use cases of refreshing
- * the contents of the note and saving the contents of the note. Since they
- * are closely related, we have combined them here for simplicity.
- */
-public class NoteInteractor implements NoteInputBoundary {
-
- private final NoteDataAccessInterface noteDataAccessInterface;
- private final NoteOutputBoundary noteOutputBoundary;
- // Note: this program has it hardcoded which user object it is getting data for;
- // you could change this if you wanted to generalize the code. For example,
- // you might allow a user of the program to create a new note, which you
- // could store as a "user" through the API OR you might maintain all notes
- // in a JSON object stored in one common "user" stored through the API.
- private final User user = new User("jonathan_calver2", "abc123");
-
- public NoteInteractor(NoteDataAccessInterface noteDataAccessInterface,
- NoteOutputBoundary noteOutputBoundary) {
- this.noteDataAccessInterface = noteDataAccessInterface;
- this.noteOutputBoundary = noteOutputBoundary;
- }
-
- /**
- * Executes the refresh note use case.
- *
- */
- @Override
- public void executeRefresh() {
- try {
-
- final String note = noteDataAccessInterface.loadNote(user);
- noteOutputBoundary.prepareSuccessView(note);
- }
- catch (DataAccessException ex) {
- noteOutputBoundary.prepareFailView(ex.getMessage());
- }
- }
-
- /**
- * Executes the save note use case.
- *
- * @param note the input data
- */
- @Override
- public void executeSave(String note) {
- try {
-
- final String updatedNote = noteDataAccessInterface.saveNote(user, note);
- noteOutputBoundary.prepareSuccessView(updatedNote);
- }
- catch (DataAccessException ex) {
- noteOutputBoundary.prepareFailView(ex.getMessage());
- }
- }
-}
diff --git a/src/main/java/use_case/note/NoteOutputBoundary.java b/src/main/java/use_case/note/NoteOutputBoundary.java
deleted file mode 100644
index c0c2bb1d0..000000000
--- a/src/main/java/use_case/note/NoteOutputBoundary.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package use_case.note;
-
-/**
- * The output boundary for the Login Use Case.
- */
-public interface NoteOutputBoundary {
- /**
- * Prepares the success view for the Note related Use Cases.
- * @param message the output data
- */
- void prepareSuccessView(String message);
-
- /**
- * Prepares the failure view for the Note related Use Cases.
- * @param errorMessage the explanation of the failure
- */
- void prepareFailView(String errorMessage);
-}
diff --git a/src/main/java/use_case/note/DataAccessException.java b/src/main/java/use_case/query/DataAccessException.java
similarity index 89%
rename from src/main/java/use_case/note/DataAccessException.java
rename to src/main/java/use_case/query/DataAccessException.java
index b8c17920d..a70b2edfb 100644
--- a/src/main/java/use_case/note/DataAccessException.java
+++ b/src/main/java/use_case/query/DataAccessException.java
@@ -1,4 +1,4 @@
-package use_case.note;
+package use_case.query;
/**
* Exception thrown when there is an error with accessing data.
diff --git a/src/main/java/use_case/query/QueryDataAccessInterface.java b/src/main/java/use_case/query/QueryDataAccessInterface.java
new file mode 100644
index 000000000..cee7dad35
--- /dev/null
+++ b/src/main/java/use_case/query/QueryDataAccessInterface.java
@@ -0,0 +1,16 @@
+package use_case.query;
+
+import entity.RankHistory;
+
+/**
+ * Interface for the QueryDAO.
+ */
+public interface QueryDataAccessInterface {
+
+ /**
+ * Saves a rank history for a given user.
+ * @param username the query user's name.
+ * @return the rank history of the user.
+ */
+ RankHistory showRankHistory(String username);
+}
diff --git a/src/main/java/use_case/query/QueryInputBoundary.java b/src/main/java/use_case/query/QueryInputBoundary.java
new file mode 100644
index 000000000..2a75ad8dd
--- /dev/null
+++ b/src/main/java/use_case/query/QueryInputBoundary.java
@@ -0,0 +1,13 @@
+package use_case.query;
+
+/**
+ * The Input Boundary for query use cases.
+ */
+public interface QueryInputBoundary {
+
+ /**
+ * Executes the query use case.
+ * @param username the user .
+ */
+ void execute(String username);
+}
diff --git a/src/main/java/use_case/query/QueryInteractor.java b/src/main/java/use_case/query/QueryInteractor.java
new file mode 100644
index 000000000..da198fed1
--- /dev/null
+++ b/src/main/java/use_case/query/QueryInteractor.java
@@ -0,0 +1,28 @@
+package use_case.query;
+
+import entity.RankHistory;
+
+/**
+ * The Query Interactor.
+ */
+public class QueryInteractor implements QueryInputBoundary {
+ private final QueryDataAccessInterface queryDataAccessInterface;
+ private final QueryOutputBoundary queryOutputBoundary;
+
+ public QueryInteractor(QueryDataAccessInterface queryDataAccessInterface,
+ QueryOutputBoundary queryOutputBoundary) {
+ this.queryDataAccessInterface = queryDataAccessInterface;
+ this.queryOutputBoundary = queryOutputBoundary;
+ }
+
+ /**
+ * Executes the query use case.
+ *
+ * @param username the user.
+ */
+ @Override
+ public void execute(String username) {
+ final RankHistory rankHistoryList = queryDataAccessInterface.showRankHistory(username);
+ queryOutputBoundary.prepareSuccessView(rankHistoryList);
+ }
+}
diff --git a/src/main/java/use_case/query/QueryOutputBoundary.java b/src/main/java/use_case/query/QueryOutputBoundary.java
new file mode 100644
index 000000000..3de9ac93a
--- /dev/null
+++ b/src/main/java/use_case/query/QueryOutputBoundary.java
@@ -0,0 +1,20 @@
+package use_case.query;
+
+import entity.RankHistory;
+
+/**
+ * The output boundary for the query Use Case.
+ */
+public interface QueryOutputBoundary {
+ /**
+ * Prepares the success view for the query related Use Cases.
+ * @param rankHistoryList the rank history data.
+ */
+ void prepareSuccessView(RankHistory rankHistoryList);
+
+ /**
+ * Prepares the failure view for the query related Use Cases.
+ * @param errorMessage the explanation of the failure
+ */
+ void prepareFailView(String errorMessage);
+}
diff --git a/src/main/java/use_case/showProfile/ShowProfileInputBoundary.java b/src/main/java/use_case/showProfile/ShowProfileInputBoundary.java
new file mode 100644
index 000000000..7ef135254
--- /dev/null
+++ b/src/main/java/use_case/showProfile/ShowProfileInputBoundary.java
@@ -0,0 +1,13 @@
+package use_case.showProfile;
+
+/**
+ * Input Boundary for actions related to logging in.
+ */
+public interface ShowProfileInputBoundary {
+
+ /**
+ * Executes the login use case.
+ * @param showProfileInputData the input data
+ */
+ void execute(ShowProfileInputData showProfileInputData);
+}
diff --git a/src/main/java/use_case/showProfile/ShowProfileInputData.java b/src/main/java/use_case/showProfile/ShowProfileInputData.java
new file mode 100644
index 000000000..83daf5d42
--- /dev/null
+++ b/src/main/java/use_case/showProfile/ShowProfileInputData.java
@@ -0,0 +1,16 @@
+package use_case.showProfile;
+
+/**
+ * The Input Data for the ShowProfile use case.
+ */
+public class ShowProfileInputData {
+ private final String username;
+
+ public ShowProfileInputData(String username) {
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+}
diff --git a/src/main/java/use_case/showProfile/ShowProfileInteractor.java b/src/main/java/use_case/showProfile/ShowProfileInteractor.java
new file mode 100644
index 000000000..5acfc27e1
--- /dev/null
+++ b/src/main/java/use_case/showProfile/ShowProfileInteractor.java
@@ -0,0 +1,27 @@
+package use_case.showProfile;
+
+import entity.User;
+
+/**
+ * The ShowProfile Interactor.
+ */
+public class ShowProfileInteractor implements ShowProfileInputBoundary {
+ private final ShowProfileUserDataAccessInterface userDataAccessObject;
+ private final ShowProfileOutputBoundary showProfilePresenter;
+
+ public ShowProfileInteractor(ShowProfileUserDataAccessInterface userDataAccessObject,
+ ShowProfileOutputBoundary showProfilePresenter) {
+ this.userDataAccessObject = userDataAccessObject;
+ this.showProfilePresenter = showProfilePresenter;
+ }
+
+ @Override
+ public void execute(ShowProfileInputData showProfileInputData) {
+ // The following code only handle success use case call
+ // Because I currently don't know what can cause this use case to fail
+ final User user = userDataAccessObject.get(showProfileInputData.getUsername());
+ final ShowProfileOutputData showProfileOutputData =
+ new ShowProfileOutputData(showProfileInputData.getUsername(), user.getCurrentRankPoint(), true);
+ showProfilePresenter.prepareSuccessView(showProfileOutputData);
+ }
+}
diff --git a/src/main/java/use_case/showProfile/ShowProfileOutputBoundary.java b/src/main/java/use_case/showProfile/ShowProfileOutputBoundary.java
new file mode 100644
index 000000000..2164cb5ad
--- /dev/null
+++ b/src/main/java/use_case/showProfile/ShowProfileOutputBoundary.java
@@ -0,0 +1,19 @@
+package use_case.showProfile;
+
+/**
+ * The output boundary for the ShowProfile Use Case.
+ */
+public interface ShowProfileOutputBoundary {
+
+ /**
+ * Prepares the success view for the ShowProfile Use Case.
+ * @param outputData the output data
+ */
+ void prepareSuccessView(ShowProfileOutputData outputData);
+
+ /**
+ * Prepares the failure view for the ShowProfile Use Case.
+ * @param errorMessage the explanation of the failure
+ */
+ void prepareFailView(String errorMessage);
+}
diff --git a/src/main/java/use_case/showProfile/ShowProfileOutputData.java b/src/main/java/use_case/showProfile/ShowProfileOutputData.java
new file mode 100644
index 000000000..3198e2fae
--- /dev/null
+++ b/src/main/java/use_case/showProfile/ShowProfileOutputData.java
@@ -0,0 +1,26 @@
+package use_case.showProfile;
+
+/**
+ * Output Data for the ShowProfile Use case.
+ */
+public class ShowProfileOutputData {
+
+ private final String username;
+ private final int rankPoint;
+ private final boolean useCaseSucceeded;
+
+ public ShowProfileOutputData(String username, int rankPoint, boolean useCaseSucceeded) {
+ this.username = username;
+ this.rankPoint = rankPoint;
+ this.useCaseSucceeded = useCaseSucceeded;
+ }
+
+ public int getRankPoint() {
+ return rankPoint;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+}
diff --git a/src/main/java/use_case/showProfile/ShowProfileUserDataAccessInterface.java b/src/main/java/use_case/showProfile/ShowProfileUserDataAccessInterface.java
new file mode 100644
index 000000000..7b3d80a27
--- /dev/null
+++ b/src/main/java/use_case/showProfile/ShowProfileUserDataAccessInterface.java
@@ -0,0 +1,23 @@
+package use_case.showProfile;
+
+import entity.User;
+
+/**
+ * DAO for the ShowProfile Use Case.
+ */
+public interface ShowProfileUserDataAccessInterface {
+
+ /**
+ * Saves the user.
+ * @param user the user to save
+ */
+ void save(User user);
+
+ /**
+ * Returns the user with the given username.
+ * @param username the username to look up
+ * @return the user with the given username
+ */
+ User get(String username);
+
+}
diff --git a/src/main/java/use_case/signup/SignupInputBoundary.java b/src/main/java/use_case/signup/SignupInputBoundary.java
new file mode 100644
index 000000000..1cb69e02e
--- /dev/null
+++ b/src/main/java/use_case/signup/SignupInputBoundary.java
@@ -0,0 +1,18 @@
+package use_case.signup;
+
+/**
+ * Input Boundary for actions which are related to signing up.
+ */
+public interface SignupInputBoundary {
+
+ /**
+ * Executes the signup use case.
+ * @param signupInputData the input data
+ */
+ void execute(SignupInputData signupInputData);
+
+ /**
+ * Executes the switch to login view use case.
+ */
+ void switchToLoginView();
+}
diff --git a/src/main/java/use_case/signup/SignupInputData.java b/src/main/java/use_case/signup/SignupInputData.java
new file mode 100644
index 000000000..86c5e8abc
--- /dev/null
+++ b/src/main/java/use_case/signup/SignupInputData.java
@@ -0,0 +1,29 @@
+package use_case.signup;
+
+/**
+ * The Input Data for the Signup Use Case.
+ */
+public class SignupInputData {
+
+ private final String username;
+ private final String password;
+ private final String repeatPassword;
+
+ public SignupInputData(String username, String password, String repeatPassword) {
+ this.username = username;
+ this.password = password;
+ this.repeatPassword = repeatPassword;
+ }
+
+ String getUsername() {
+ return username;
+ }
+
+ String getPassword() {
+ return password;
+ }
+
+ public String getRepeatPassword() {
+ return repeatPassword;
+ }
+}
diff --git a/src/main/java/use_case/signup/SignupInteractor.java b/src/main/java/use_case/signup/SignupInteractor.java
new file mode 100644
index 000000000..2cd2ed429
--- /dev/null
+++ b/src/main/java/use_case/signup/SignupInteractor.java
@@ -0,0 +1,39 @@
+package use_case.signup;
+
+import entity.User;
+
+/**
+ * The Signup Interactor.
+ */
+public class SignupInteractor implements SignupInputBoundary {
+ private final SignupUserDataAccessInterface userDataAccessObject;
+ private final SignupOutputBoundary userPresenter;
+
+ public SignupInteractor(SignupUserDataAccessInterface signupDataAccessInterface,
+ SignupOutputBoundary signupOutputBoundary) {
+ this.userDataAccessObject = signupDataAccessInterface;
+ this.userPresenter = signupOutputBoundary;
+ }
+
+ @Override
+ public void execute(SignupInputData signupInputData) {
+ if (userDataAccessObject.existsByName(signupInputData.getUsername())) {
+ userPresenter.prepareFailView("User already exists.");
+ }
+ else if (!signupInputData.getPassword().equals(signupInputData.getRepeatPassword())) {
+ userPresenter.prepareFailView("Passwords don't match.");
+ }
+ else {
+ final User user = new User(signupInputData.getUsername(), signupInputData.getPassword());
+ userDataAccessObject.save(user);
+
+ final SignupOutputData signupOutputData = new SignupOutputData(user.getName(), false);
+ userPresenter.prepareSuccessView(signupOutputData);
+ }
+ }
+
+ @Override
+ public void switchToLoginView() {
+ userPresenter.switchToLoginView();
+ }
+}
diff --git a/src/main/java/use_case/signup/SignupOutputBoundary.java b/src/main/java/use_case/signup/SignupOutputBoundary.java
new file mode 100644
index 000000000..314376b93
--- /dev/null
+++ b/src/main/java/use_case/signup/SignupOutputBoundary.java
@@ -0,0 +1,24 @@
+package use_case.signup;
+
+/**
+ * The output boundary for the Signup Use Case.
+ */
+public interface SignupOutputBoundary {
+
+ /**
+ * Prepares the success view for the Signup Use Case.
+ * @param outputData the output data
+ */
+ void prepareSuccessView(SignupOutputData outputData);
+
+ /**
+ * Prepares the failure view for the Signup Use Case.
+ * @param errorMessage the explanation of the failure
+ */
+ void prepareFailView(String errorMessage);
+
+ /**
+ * Switches to the Login View.
+ */
+ void switchToLoginView();
+}
diff --git a/src/main/java/use_case/signup/SignupOutputData.java b/src/main/java/use_case/signup/SignupOutputData.java
new file mode 100644
index 000000000..6dc74d2fb
--- /dev/null
+++ b/src/main/java/use_case/signup/SignupOutputData.java
@@ -0,0 +1,24 @@
+package use_case.signup;
+
+/**
+ * Output Data for the Signup Use Case.
+ */
+public class SignupOutputData {
+
+ private final String username;
+
+ private final boolean useCaseFailed;
+
+ public SignupOutputData(String username, boolean useCaseFailed) {
+ this.username = username;
+ this.useCaseFailed = useCaseFailed;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public boolean isUseCaseFailed() {
+ return useCaseFailed;
+ }
+}
diff --git a/src/main/java/use_case/signup/SignupUserDataAccessInterface.java b/src/main/java/use_case/signup/SignupUserDataAccessInterface.java
new file mode 100644
index 000000000..b9d60f585
--- /dev/null
+++ b/src/main/java/use_case/signup/SignupUserDataAccessInterface.java
@@ -0,0 +1,22 @@
+package use_case.signup;
+
+import entity.User;
+
+/**
+ * DAO for the Signup Use Case.
+ */
+public interface SignupUserDataAccessInterface {
+
+ /**
+ * Checks if the given username exists.
+ * @param username the username to look for
+ * @return true if a user with the given username exists; false otherwise
+ */
+ boolean existsByName(String username);
+
+ /**
+ * Saves the user.
+ * @param user the user to save
+ */
+ void save(User user);
+}
diff --git a/src/main/java/view/ChessBoardView.java b/src/main/java/view/ChessBoardView.java
new file mode 100644
index 000000000..cc550db08
--- /dev/null
+++ b/src/main/java/view/ChessBoardView.java
@@ -0,0 +1,131 @@
+package view;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import interface_adapter.move.MoveController;
+import interface_adapter.move.MoveViewModel;
+
+/**
+ * The view of actual chess game.
+ */
+public class ChessBoardView extends JPanel implements ActionListener, PropertyChangeListener {
+
+ private final int numRow = 8;
+ private final int numCol = 8;
+ private final int fontSize = 36;
+ private final String viewName = "Chess Board";
+ private final MoveViewModel moveViewModel;
+ private MoveController moveController;
+
+ public ChessBoardView(MoveViewModel moveViewModel, MoveController moveController) {
+ this.moveViewModel = moveViewModel;
+ this.moveController = moveController;
+ moveViewModel.addPropertyChangeListener(this);
+
+ final JLabel titleLabel = new JLabel(MoveViewModel.TITLE_LABEL);
+
+ this.setLayout(new GridLayout(numRow, numCol));
+
+ // Add buttons to the frame in a chessboard pattern
+ for (int row = 0; row < numRow; row++) {
+ for (int col = 0; col < numCol; col++) {
+ final JButton button = new JButton();
+ final String stringRow = String.valueOf(Math.abs(row - 7));
+ final String stringCol = String.valueOf(col);
+ button.setActionCommand(stringCol + "," + stringRow);
+
+ // Set background color to alternate between black and white
+ if ((row + col) % 2 == 0) {
+ button.setBackground(Color.GRAY);
+ } else {
+ button.setBackground(Color.orange);
+ }
+
+ // Add pieces to the board
+ final String[][] pieces = moveViewModel.getPieces();
+ if (pieces[row][col] != null) {
+ // Set highlighted background color associate with valid moves.
+ if (pieces[row][col].equals("Valid")) {
+ button.setBackground(Color.YELLOW);
+ } else {
+ button.setText(pieces[row][col]);
+ button.setFont(new Font("Serif", Font.BOLD, fontSize));
+ }
+ }
+
+ button.setFocusPainted(true);
+ button.addActionListener(this);
+ this.add(button);
+
+ }
+ }
+
+ }
+
+ public void setMoveController(MoveController moveController) {
+ this.moveController = moveController;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println(e.getActionCommand());
+ // Split the string at the comma
+ String[] parts = e.getActionCommand().split(",");
+ // Convert the parts to integers
+ int x = Integer.parseInt(parts[0]);
+ int y = Integer.parseInt(parts[1]);
+ moveController.onClick(x, y);
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if ("pieces".equals(evt.getPropertyName())) {
+ // Retrieve the updated pieces array
+ String[][] updatedPieces = (String[][]) evt.getNewValue();
+
+ // Update the board
+ for (int row = 0; row < numRow; row++) {
+ for (int col = 0; col < numCol; col++) {
+ // Find the button at this position
+ JButton button = (JButton) this.getComponent(row * numCol + col);
+
+ // Reset button background color
+ if ((row + col) % 2 == 0) {
+ button.setBackground(Color.GRAY);
+ } else {
+ button.setBackground(Color.orange);
+ }
+
+ // Update the button text and background based on the new pieces
+ if (updatedPieces[row][col] != null) {
+ if ("Valid".equals(updatedPieces[row][col])) {
+ button.setBackground(Color.YELLOW); // Highlight valid move
+ button.setText(""); // No text for "Valid" markers
+ } else {
+ button.setText(updatedPieces[row][col]); // Set piece text
+ button.setFont(new Font("Serif", Font.BOLD, fontSize));
+ }
+ } else {
+ button.setText(""); // Clear text if no piece
+ }
+ }
+ }
+
+ // Refresh the UI
+ this.revalidate();
+ this.repaint();
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/view/LabelTextPanel.java b/src/main/java/view/LabelTextPanel.java
new file mode 100644
index 000000000..e7138555f
--- /dev/null
+++ b/src/main/java/view/LabelTextPanel.java
@@ -0,0 +1,15 @@
+package view;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+/**
+ * A panel containing a label and a text field.
+ */
+class LabelTextPanel extends JPanel {
+ LabelTextPanel(JLabel label, JTextField textField) {
+ this.add(label);
+ this.add(textField);
+ }
+}
diff --git a/src/main/java/view/LoggedInView.java b/src/main/java/view/LoggedInView.java
new file mode 100644
index 000000000..6375250d1
--- /dev/null
+++ b/src/main/java/view/LoggedInView.java
@@ -0,0 +1,141 @@
+package view;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import interface_adapter.ViewManagerModel;
+import interface_adapter.logged_in.LoggedInController;
+import interface_adapter.logged_in.LoggedInState;
+import interface_adapter.logged_in.LoggedInViewModel;
+import interface_adapter.query.QueryController;
+import interface_adapter.showProfile.ShowProfileController;
+
+/**
+ * The View for when the user is logged into the program.
+ */
+public class LoggedInView extends JPanel implements ActionListener, PropertyChangeListener {
+
+ private final String viewName = "logged in";
+ private final LoggedInViewModel loggedInViewModel;
+ private final LoggedInController loggedInController;
+ private final JLabel passwordErrorField = new JLabel();
+
+ private final JLabel username;
+
+ private final JButton logOut;
+
+ private final JButton startChess;
+ private final JButton showProfile;
+ private final JButton showRankHistory;
+ private final ShowProfileController showProfileController;
+ private final QueryController queryController;
+
+ public LoggedInView(ViewManagerModel viewManagerModel, LoggedInController loggedInController,
+ LoggedInViewModel loggedInViewModel,
+ ShowProfileController showProfileController,
+ QueryController queryController) {
+ this.loggedInController = loggedInController;
+ this.loggedInViewModel = loggedInViewModel;
+ this.showProfileController = showProfileController;
+ this.queryController = queryController;
+ this.loggedInViewModel.addPropertyChangeListener(this);
+
+ final JLabel title = new JLabel("Logged In Screen");
+ title.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ final JLabel usernameInfo = new JLabel("Currently logged in: ");
+ username = new JLabel();
+
+ final JPanel buttons = new JPanel();
+ logOut = new JButton("Log Out");
+ buttons.add(logOut);
+
+ showProfile = new JButton("Show Profile");
+ buttons.add(showProfile);
+
+ showRankHistory = new JButton("Show Rank History");
+ buttons.add(showRankHistory);
+
+ startChess = new JButton("Start Chess Game");
+ buttons.add(startChess);
+
+ logOut.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource().equals(logOut)) {
+ loggedInController.switchToSignUpView();
+ }
+ }
+ }
+ );
+
+ startChess.addActionListener(
+ evt -> {
+ if (evt.getSource().equals(startChess)) {
+ viewManagerModel.setState("chessBoardView");
+ viewManagerModel.firePropertyChanged();
+ }
+ }
+ );
+
+ showProfile.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource().equals(showProfile)) {
+ final LoggedInState currentState = loggedInViewModel.getState();
+
+ showProfileController.execute(
+ currentState.getUsername()
+ );
+ }
+ }
+ }
+ );
+
+ showRankHistory.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource().equals(showRankHistory)) {
+ final LoggedInState currentState = loggedInViewModel.getState();
+
+ queryController.execute(
+ currentState.getUsername()
+ );
+ }
+ }
+ }
+ );
+
+ this.add(title);
+ this.add(usernameInfo);
+ this.add(username);
+
+ this.add(passwordErrorField);
+ this.add(buttons);
+ }
+
+ /**
+ * React to a button click that results in evt.
+ * @param evt the ActionEvent to react to
+ */
+ public void actionPerformed(ActionEvent evt) {
+ System.out.println("Click " + evt.getActionCommand());
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ final LoggedInState state = (LoggedInState) evt.getNewValue();
+ username.setText(state.getUsername());
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+}
diff --git a/src/main/java/view/LoginView.java b/src/main/java/view/LoginView.java
new file mode 100644
index 000000000..8b0f0bf6f
--- /dev/null
+++ b/src/main/java/view/LoginView.java
@@ -0,0 +1,164 @@
+package view;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import interface_adapter.login.LoginController;
+import interface_adapter.login.LoginState;
+import interface_adapter.login.LoginViewModel;
+
+/**
+ * The View for when the user is logging into the program.
+ */
+public class LoginView extends JPanel implements ActionListener, PropertyChangeListener {
+
+ private final String viewName = "log in";
+ private final LoginViewModel loginViewModel;
+
+ private final JTextField usernameInputField = new JTextField(15);
+ private final JLabel usernameErrorField = new JLabel();
+
+ private final JPasswordField passwordInputField = new JPasswordField(15);
+ private final JLabel passwordErrorField = new JLabel();
+
+ private final JButton logIn;
+ private final JButton cancel;
+ private final LoginController loginController;
+
+ public LoginView(LoginViewModel loginViewModel, LoginController controller) {
+
+ this.loginController = controller;
+ this.loginViewModel = loginViewModel;
+ this.loginViewModel.addPropertyChangeListener(this);
+
+ final JLabel title = new JLabel("Login Screen");
+ title.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ final LabelTextPanel usernameInfo = new LabelTextPanel(
+ new JLabel("Username"), usernameInputField);
+ final LabelTextPanel passwordInfo = new LabelTextPanel(
+ new JLabel("Password"), passwordInputField);
+
+ final JPanel buttons = new JPanel();
+ logIn = new JButton("log in");
+ buttons.add(logIn);
+ cancel = new JButton("cancel");
+ buttons.add(cancel);
+
+ logIn.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource().equals(logIn)) {
+ final LoginState currentState = loginViewModel.getState();
+
+ loginController.execute(
+ currentState.getUsername(),
+ currentState.getPassword()
+ );
+ }
+ }
+ }
+ );
+
+ cancel.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource().equals(cancel)) {
+ loginController.switchToSignUpView();
+ }
+ }
+ }
+ );
+
+ usernameInputField.getDocument().addDocumentListener(new DocumentListener() {
+
+ private void documentListenerHelper() {
+ final LoginState currentState = loginViewModel.getState();
+ currentState.setUsername(usernameInputField.getText());
+ loginViewModel.setState(currentState);
+ }
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+ });
+
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ passwordInputField.getDocument().addDocumentListener(new DocumentListener() {
+
+ private void documentListenerHelper() {
+ final LoginState currentState = loginViewModel.getState();
+ currentState.setPassword(new String(passwordInputField.getPassword()));
+ loginViewModel.setState(currentState);
+ }
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+ });
+
+ this.add(title);
+ this.add(usernameInfo);
+ this.add(usernameErrorField);
+ this.add(passwordInfo);
+ this.add(buttons);
+ }
+
+ /**
+ * React to a button click that results in evt.
+ * @param evt the ActionEvent to react to
+ */
+ public void actionPerformed(ActionEvent evt) {
+ System.out.println("Click " + evt.getActionCommand());
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ final LoginState state = (LoginState) evt.getNewValue();
+ setFields(state);
+ usernameErrorField.setText(state.getLoginError());
+ }
+
+ private void setFields(LoginState state) {
+ usernameInputField.setText(state.getUsername());
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+}
diff --git a/src/main/java/view/NoteView.java b/src/main/java/view/NoteView.java
deleted file mode 100644
index 331d76493..000000000
--- a/src/main/java/view/NoteView.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package view;
-
-import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JTextArea;
-
-import interface_adapter.note.NoteController;
-import interface_adapter.note.NoteState;
-import interface_adapter.note.NoteViewModel;
-
-/**
- * The View for when the user is viewing a note in the program.
- */
-public class NoteView extends JPanel implements ActionListener, PropertyChangeListener {
-
- private final NoteViewModel noteViewModel;
-
- private final JLabel noteName = new JLabel("note for jonathan_calver2");
- private final JTextArea noteInputField = new JTextArea();
-
- private final JButton saveButton = new JButton("Save");
- private final JButton refreshButton = new JButton("Refresh");
- private NoteController noteController;
-
- public NoteView(NoteViewModel noteViewModel) {
-
- noteName.setAlignmentX(Component.CENTER_ALIGNMENT);
- this.noteViewModel = noteViewModel;
- this.noteViewModel.addPropertyChangeListener(this);
-
- final JPanel buttons = new JPanel();
- buttons.add(saveButton);
- buttons.add(refreshButton);
-
- saveButton.addActionListener(
- evt -> {
- if (evt.getSource().equals(saveButton)) {
- noteController.execute(noteInputField.getText());
-
- }
- }
- );
-
- refreshButton.addActionListener(
- evt -> {
- if (evt.getSource().equals(refreshButton)) {
- noteController.execute(null);
-
- }
- }
- );
-
- this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
-
- this.add(noteName);
- this.add(noteInputField);
- this.add(buttons);
- }
-
- /**
- * React to a button click that results in evt.
- * @param evt the ActionEvent to react to
- */
- public void actionPerformed(ActionEvent evt) {
- System.out.println("Click " + evt.getActionCommand());
- }
-
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- final NoteState state = (NoteState) evt.getNewValue();
- setFields(state);
- if (state.getError() != null) {
- JOptionPane.showMessageDialog(this, state.getError(),
- "Error", JOptionPane.ERROR_MESSAGE);
- }
- }
-
- private void setFields(NoteState state) {
- noteInputField.setText(state.getNote());
- }
-
- public void setNoteController(NoteController controller) {
- this.noteController = controller;
- }
-}
-
diff --git a/src/main/java/view/ProfileView.java b/src/main/java/view/ProfileView.java
new file mode 100644
index 000000000..40b7916ff
--- /dev/null
+++ b/src/main/java/view/ProfileView.java
@@ -0,0 +1,84 @@
+package view;
+
+import interface_adapter.ViewManagerModel;
+import interface_adapter.logged_in.LoggedInViewModel;
+import interface_adapter.showProfile.ShowProfileState;
+import interface_adapter.showProfile.ShowProfileViewModel;
+
+
+
+import javax.swing.*;
+import javax.swing.text.View;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Observer;
+
+/**
+ * The view of user profile.
+ */
+public class ProfileView extends JPanel implements ActionListener, PropertyChangeListener {
+
+ private final String viewName = "showProfile";
+ private final ShowProfileViewModel showProfileViewModel;
+
+ private final JLabel username;
+ private final JLabel currentRankPoint;
+
+ private final JButton back;
+
+ public ProfileView(ViewManagerModel viewManagerModel, ShowProfileViewModel showProfileViewModel) {
+ this.showProfileViewModel = showProfileViewModel;
+ this.showProfileViewModel.addPropertyChangeListener(this);
+
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ final JLabel title = new JLabel("Profile");
+ title.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ final JLabel usernameInfo = new JLabel("Currently logged in: ");
+ username = new JLabel();
+
+ final JLabel rankPointInfo = new JLabel("Current rank point: ");
+ currentRankPoint = new JLabel();
+
+ back = new JButton("Back");
+
+ back.addActionListener(
+ evt -> {
+ if (evt.getSource().equals(back)) {
+ System.out.println("back button clicked");
+ }
+ }
+ );
+
+ this.add(title);
+ this.add(usernameInfo);
+ this.add(username);
+ this.add(rankPointInfo);
+ this.add(currentRankPoint);
+ this.add(back);
+ }
+
+ /**
+ * React to a button click that results in evt.
+ * @param evt the ActionEvent to react to
+ */
+ public void actionPerformed(ActionEvent evt) {
+ System.out.println("Click " + evt.getActionCommand());
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ final ShowProfileState showProfileState = (ShowProfileState) evt.getNewValue();
+ username.setText(showProfileState.getUsername());
+ currentRankPoint.setText(String.valueOf(showProfileState.getRankPoint()));
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+}
diff --git a/src/main/java/view/QueryView.java b/src/main/java/view/QueryView.java
new file mode 100644
index 000000000..0a9fb5b62
--- /dev/null
+++ b/src/main/java/view/QueryView.java
@@ -0,0 +1,64 @@
+package view;
+
+import entity.RankHistory;
+import interface_adapter.ViewManagerModel;
+import interface_adapter.query.QueryViewModel;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+/**
+ * The view of user profile.
+ */
+public class QueryView extends JPanel implements ActionListener, PropertyChangeListener {
+
+ private final String viewName = "query";
+ private final QueryViewModel queryViewModel;
+ private final JPanel contentPanel;
+
+ public QueryView(ViewManagerModel viewManagerModel, QueryViewModel queryViewModel) {
+ this.queryViewModel = queryViewModel;
+ this.queryViewModel.addPropertyChangeListener(this);
+
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ final JLabel title = new JLabel("Rank History");
+ title.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ final JScrollPane scrollPane = new JScrollPane();
+
+ contentPanel = new JPanel();
+ contentPanel.setLayout(new GridLayout(0, 1));
+
+ scrollPane.setViewportView(contentPanel);
+
+ this.add(title);
+ this.add(scrollPane);
+
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ final RankHistory rankHistory = queryViewModel.getRankHistoryList();
+ for (int i = 0; i < rankHistory.getRanks().size(); i++) {
+ contentPanel.add(new JLabel(rankHistory.getRanks().get(i).toString()));
+ }
+ }
+
+ /**
+ * React to a button click that results in evt.
+ * @param evt the ActionEvent to react to
+ */
+ public void actionPerformed(ActionEvent evt) {
+
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+}
diff --git a/src/main/java/view/SignupView.java b/src/main/java/view/SignupView.java
new file mode 100644
index 000000000..01b9f5fb3
--- /dev/null
+++ b/src/main/java/view/SignupView.java
@@ -0,0 +1,193 @@
+package view;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import interface_adapter.signup.SignupController;
+import interface_adapter.signup.SignupState;
+import interface_adapter.signup.SignupViewModel;
+
+/**
+ * The View for the Signup Use Case.
+ */
+public class SignupView extends JPanel implements ActionListener, PropertyChangeListener {
+ private final String viewName = "sign up";
+
+ private final SignupViewModel signupViewModel;
+ private final JTextField usernameInputField = new JTextField(15);
+ private final JPasswordField passwordInputField = new JPasswordField(15);
+ private final JPasswordField repeatPasswordInputField = new JPasswordField(15);
+ private final SignupController signupController;
+
+ private final JButton signUp;
+ private final JButton toLogin;
+
+ public SignupView(SignupController controller, SignupViewModel signupViewModel) {
+
+ this.signupController = controller;
+ this.signupViewModel = signupViewModel;
+ signupViewModel.addPropertyChangeListener(this);
+
+ final JLabel title = new JLabel(SignupViewModel.TITLE_LABEL);
+ title.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+ final LabelTextPanel usernameInfo = new LabelTextPanel(
+ new JLabel(SignupViewModel.USERNAME_LABEL), usernameInputField);
+ final LabelTextPanel passwordInfo = new LabelTextPanel(
+ new JLabel(SignupViewModel.PASSWORD_LABEL), passwordInputField);
+ final LabelTextPanel repeatPasswordInfo = new LabelTextPanel(
+ new JLabel(SignupViewModel.REPEAT_PASSWORD_LABEL), repeatPasswordInputField);
+
+ final JPanel buttons = new JPanel();
+ toLogin = new JButton(SignupViewModel.TO_LOGIN_BUTTON_LABEL);
+ buttons.add(toLogin);
+ signUp = new JButton(SignupViewModel.SIGNUP_BUTTON_LABEL);
+ buttons.add(signUp);
+
+ signUp.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource().equals(signUp)) {
+ final SignupState currentState = signupViewModel.getState();
+
+ signupController.execute(
+ currentState.getUsername(),
+ currentState.getPassword(),
+ currentState.getRepeatPassword()
+ );
+ }
+ }
+ }
+ );
+
+ toLogin.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ if (evt.getSource().equals(toLogin)) {
+ signupController.switchToLoginView();
+ }
+ }
+ }
+ );
+
+ addUsernameListener();
+ addPasswordListener();
+ addRepeatPasswordListener();
+
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ this.add(title);
+ this.add(usernameInfo);
+ this.add(passwordInfo);
+ this.add(repeatPasswordInfo);
+ this.add(buttons);
+ }
+
+ private void addUsernameListener() {
+ usernameInputField.getDocument().addDocumentListener(new DocumentListener() {
+
+ private void documentListenerHelper() {
+ final SignupState currentState = signupViewModel.getState();
+ currentState.setUsername(usernameInputField.getText());
+ signupViewModel.setState(currentState);
+ }
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+ });
+ }
+
+ private void addPasswordListener() {
+ passwordInputField.getDocument().addDocumentListener(new DocumentListener() {
+
+ private void documentListenerHelper() {
+ final SignupState currentState = signupViewModel.getState();
+ currentState.setPassword(new String(passwordInputField.getPassword()));
+ signupViewModel.setState(currentState);
+ }
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+ });
+ }
+
+ private void addRepeatPasswordListener() {
+ repeatPasswordInputField.getDocument().addDocumentListener(new DocumentListener() {
+
+ private void documentListenerHelper() {
+ final SignupState currentState = signupViewModel.getState();
+ currentState.setRepeatPassword(new String(repeatPasswordInputField.getPassword()));
+ signupViewModel.setState(currentState);
+ }
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ documentListenerHelper();
+ }
+ });
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent evt) {
+ JOptionPane.showMessageDialog(this, "Cancel not implemented yet.");
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ final SignupState state = (SignupState) evt.getNewValue();
+ if (state.getUsernameError() != null) {
+ JOptionPane.showMessageDialog(this, state.getUsernameError());
+ }
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+}
diff --git a/src/main/java/view/ViewManager.java b/src/main/java/view/ViewManager.java
new file mode 100644
index 000000000..7f9f07ec6
--- /dev/null
+++ b/src/main/java/view/ViewManager.java
@@ -0,0 +1,34 @@
+package view;
+
+import java.awt.CardLayout;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JPanel;
+
+import interface_adapter.ViewManagerModel;
+
+/**
+ * The View Manager for the program. It listens for property change events
+ * in the ViewManagerModel and updates which View should be visible.
+ */
+public class ViewManager implements PropertyChangeListener {
+ private final CardLayout cardLayout;
+ private final JPanel views;
+ private final ViewManagerModel viewManagerModel;
+
+ public ViewManager(JPanel views, CardLayout cardLayout, ViewManagerModel viewManagerModel) {
+ this.views = views;
+ this.cardLayout = cardLayout;
+ this.viewManagerModel = viewManagerModel;
+ this.viewManagerModel.addPropertyChangeListener(this);
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getPropertyName().equals("state")) {
+ final String viewModelName = (String) evt.getNewValue();
+ cardLayout.show(views, viewModelName);
+ }
+ }
+}
diff --git a/src/test/java/SignupANDLogin/LoginTest.java b/src/test/java/SignupANDLogin/LoginTest.java
new file mode 100644
index 000000000..55564831b
--- /dev/null
+++ b/src/test/java/SignupANDLogin/LoginTest.java
@@ -0,0 +1,38 @@
+package SignupANDLogin;
+
+import data_access.UserDataAccessObject;
+import entity.User;
+import org.junit.Test;
+import use_case.login.*;
+
+import static org.junit.Assert.*;
+
+public class LoginTest {
+
+ @Test
+ public void successTest() {
+ LoginInputData inputData = new LoginInputData("uno", "uno");
+ LoginUserDataAccessInterface userRepository = new UserDataAccessObject();
+
+ User user = new User("uno", "uno");
+ userRepository.save(user);
+
+ LoginOutputBoundary successPresenter = new LoginOutputBoundary() {
+ @Override
+ public void prepareSuccessView(LoginOutputData user) {
+ assertEquals("uno", user.getUsername());
+ }
+
+ @Override
+ public void prepareFailView(String error) {
+ fail("Use case failure is unexpected.");
+ }
+
+ @Override
+ public void switchToSignUpView(){}
+ };
+
+ LoginInputBoundary interactor = new LoginInteractor(userRepository, successPresenter);
+ interactor.execute(inputData);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/SignupANDLogin/SignupTest.java b/src/test/java/SignupANDLogin/SignupTest.java
new file mode 100644
index 000000000..04c776e53
--- /dev/null
+++ b/src/test/java/SignupANDLogin/SignupTest.java
@@ -0,0 +1,38 @@
+package SignupANDLogin;
+
+import org.junit.Test;
+import use_case.signup.*;
+import data_access.UserDataAccessObject;
+
+import static org.junit.Assert.*;
+
+public class SignupTest {
+
+ @Test
+ public void successTest() {
+ SignupInputData inputData = new SignupInputData("uno", "uno", "uno");
+ SignupUserDataAccessInterface userRepository = new UserDataAccessObject();
+
+ SignupOutputBoundary successPresenter = new SignupOutputBoundary() {
+ @Override
+ public void prepareSuccessView(SignupOutputData user) {
+ // 2 things to check: the output data is correct, and the user has been created in the DAO.
+ assertEquals("uno", user.getUsername());
+ assertTrue(userRepository.existsByName("uno"));
+ }
+
+ @Override
+ public void prepareFailView(String error) {
+ fail("Use case failure is unexpected.");
+ }
+
+ @Override
+ public void switchToLoginView() {
+ // This is expected
+ }
+ };
+
+ SignupInputBoundary interactor = new SignupInteractor(userRepository, successPresenter);
+ interactor.execute(inputData);
+ }
+}
diff --git a/src/test/java/app/MainNoteApplicationTest.java b/src/test/java/app/MainNoteApplicationTest.java
deleted file mode 100644
index 025d970e2..000000000
--- a/src/test/java/app/MainNoteApplicationTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package app;
-
-import entity.User;
-import org.junit.Before;
-import org.junit.Test;
-import use_case.note.NoteDataAccessInterface;
-
-import javax.swing.*;
-import java.awt.*;
-
-import static java.lang.Thread.sleep;
-import static org.junit.Assert.*;
-
-public class MainNoteApplicationTest {
-
- private JFrame app;
-
- @Before
- public void setUp() {
-
- // create the data access and inject it into our builder!
- final NoteDataAccessInterface noteDataAccess = new NoteDataAccessInterface() {
-
- private String note = "test";
-
- @Override
- public String saveNote(User user, String note) {
- this.note = note;
- return note;
- }
-
- @Override
- public String loadNote(User user) {
- return note;
- }
- };
-
- final NoteAppBuilder builder = new NoteAppBuilder();
- app = builder.addNoteDAO(noteDataAccess)
- .addNoteView()
- .addNoteUseCase().build();
-
- app.setVisible(true);
-
- }
-
- /**
- * This is an example of an end-to-end test with a mocked database.
- * The code creates the application and directly tests to see that the GUI
- * is updated as expected when the buttons and UI elements are interacted with.
- *
- * You can run the test to visually see what happens.
- */
- @Test
- public void testEndToEnd() {
-
- Component[] components = ((JPanel)app.getRootPane().getContentPane().getComponents()[0]).getComponents();
- JTextArea textArea = null;
- for (Component component : components) {
- if (component instanceof JTextArea) {
- textArea = (JTextArea) component;
- assertEquals("test", textArea.getText());
-
- }
- }
-
- textArea.setText("test test");
-
-
- JButton save = null;
- JButton load = null;
- for (Component component : components) {
- if (component instanceof JPanel) {
- for (Component c : ((JPanel) component).getComponents()) {
- if (c instanceof JButton) {
- if (save != null) {
- load = (JButton) c;
- }
- else {
- save = (JButton) c;
- }
- }
- }
- }
- }
-
- save.doClick();
- assertEquals("test test", textArea.getText());
- textArea.setText("");
-
- System.out.println("cleared text; about to refresh...");
- // pause execution for a bit so we can visually see the changes on the screen
- try {
- sleep(1500);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
-
- load.doClick();
- assertEquals("test test", textArea.getText());
-
- System.out.println("after refresh!");
-
- // pause execution for a bit so we can visually see the changes on the screen
- try {
- sleep(1500);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/test/java/use_case/note/NoteInteractorTest.java b/src/test/java/use_case/note/NoteInteractorTest.java
deleted file mode 100644
index a3ed466b6..000000000
--- a/src/test/java/use_case/note/NoteInteractorTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package use_case.note;
-
-import entity.User;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class NoteInteractorTest {
-
- @Test
- public void testExecuteRefreshSuccess() {
-
- NoteDataAccessInterface noteDAO = new NoteDataAccessInterface() {
-
-
- @Override
- public String saveNote(User user, String note) {
- return "";
- }
-
-
- @Override
- public String loadNote(User user) {
- return "test";
- }
- };
-
- NoteOutputBoundary noteOB = new NoteOutputBoundary() {
- @Override
- public void prepareSuccessView(String message) {
- assertEquals("test", message);
- }
-
- @Override
- public void prepareFailView(String errorMessage) {
- fail(errorMessage);
- }
- };
-
- NoteInteractor noteInteractor = new NoteInteractor(noteDAO, noteOB);
-
- noteInteractor.executeRefresh();
-
-
- }
-}
\ No newline at end of file
diff --git a/src/test/java/view/ChessBoardViewTest.java b/src/test/java/view/ChessBoardViewTest.java
new file mode 100644
index 000000000..5186f0bdf
--- /dev/null
+++ b/src/test/java/view/ChessBoardViewTest.java
@@ -0,0 +1,40 @@
+package view;
+
+import data_access.ChessDataAccessObject;
+import entity.Board;
+import entity.Game;
+import interface_adapter.ViewManagerModel;
+import interface_adapter.move.MoveController;
+import interface_adapter.move.MovePresenter;
+import interface_adapter.move.MoveViewModel;
+import use_case.move.MoveDataAccessInterface;
+import use_case.move.MoveInteractor;
+import use_case.move.MoveOutputBoundary;
+
+import javax.swing.*;
+
+
+public class ChessBoardViewTest {
+ public static void main(String[] args) {
+
+ JFrame frame = new JFrame("Test ChessBoardView");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setSize(800, 800);
+
+ MoveViewModel TestModel = new MoveViewModel();
+ MoveDataAccessInterface moveDataAccessObject = new ChessDataAccessObject();
+ MoveViewModel moveViewModel = new MoveViewModel();
+ ViewManagerModel viewManagerModel = new ViewManagerModel();
+ MoveOutputBoundary movePresenter = new MovePresenter(moveViewModel, viewManagerModel);
+ Board board = new Board();
+ Game game = new Game(board, true);
+ MoveInteractor TestInteractor = new MoveInteractor(moveDataAccessObject, movePresenter, game);
+ MoveController TestController = new MoveController(TestInteractor);
+
+ ChessBoardView TestView = new ChessBoardView(TestModel, TestController);
+
+ frame.add(TestView);
+ frame.setVisible(true);
+
+ }
+}