From c39538d459bd9fdc730dea74ccce8de48edf136f Mon Sep 17 00:00:00 2001
From: maheshreddym395 <39896413+maheshreddym395@users.noreply.github.com>
Date: Sat, 23 Nov 2024 12:45:18 +0530
Subject: [PATCH 1/3] Solved the Problem
---
SnakeAndLadder/pom.xml | 39 ++++++++
.../src/main/java/org/main/Dice.java | 30 ++++++
.../src/main/java/org/main/GameBoard.java | 5 +
.../java/org/main/GameFilePathManager.java | 40 ++++++++
.../src/main/java/org/main/GamePlay.java | 4 +
.../src/main/java/org/main/GamePlayers.java | 4 +
.../src/main/java/org/main/LoadGameBoard.java | 8 ++
.../src/main/java/org/main/Main.java | 29 ++++++
.../src/main/java/org/main/MovementCause.java | 16 ++++
.../src/main/java/org/main/Player.java | 45 +++++++++
.../src/main/java/org/main/PlayerStatus.java | 7 ++
.../org/main/SnakeAndLadderGameBoard.java | 33 +++++++
.../main/SnakeAndLadderGameBoardLoader.java | 91 +++++++++++++++++++
.../org/main/SnakeAndLadderGameBoardPlay.java | 74 +++++++++++++++
.../org/main/SnakeAndLadderGamePlayers.java | 22 +++++
.../resources/SankeAndLadderGameInput.txt | 22 +++++
.../src/test/java/org/main/DiceTest.java | 25 +++++
.../org/main/GameFilePathManagerTest.java | 39 ++++++++
.../SnakeAndLadderGameBoardLoaderTest.java | 19 ++++
.../classes/SankeAndLadderGameInput.txt | 22 +++++
20 files changed, 574 insertions(+)
create mode 100644 SnakeAndLadder/pom.xml
create mode 100644 SnakeAndLadder/src/main/java/org/main/Dice.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/GameBoard.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/GameFilePathManager.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/GamePlay.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/GamePlayers.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/LoadGameBoard.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/Main.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/MovementCause.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/Player.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/PlayerStatus.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoard.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardLoader.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardPlay.java
create mode 100644 SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGamePlayers.java
create mode 100644 SnakeAndLadder/src/main/resources/SankeAndLadderGameInput.txt
create mode 100644 SnakeAndLadder/src/test/java/org/main/DiceTest.java
create mode 100644 SnakeAndLadder/src/test/java/org/main/GameFilePathManagerTest.java
create mode 100644 SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardLoaderTest.java
create mode 100644 SnakeAndLadder/target/classes/SankeAndLadderGameInput.txt
diff --git a/SnakeAndLadder/pom.xml b/SnakeAndLadder/pom.xml
new file mode 100644
index 00000000..aac9edb1
--- /dev/null
+++ b/SnakeAndLadder/pom.xml
@@ -0,0 +1,39 @@
+
+
+ 4.0.0
+
+ org.main
+ SnakeAndLadder
+ 1.0-SNAPSHOT
+
+
+ 21
+ 21
+ UTF-8
+
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.32
+ provided
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.8.1
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.8.1
+ test
+
+
+
+
\ No newline at end of file
diff --git a/SnakeAndLadder/src/main/java/org/main/Dice.java b/SnakeAndLadder/src/main/java/org/main/Dice.java
new file mode 100644
index 00000000..b0f4f128
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/Dice.java
@@ -0,0 +1,30 @@
+package org.main;
+
+import java.util.Random;
+
+/**
+ *
+ */
+public class Dice {
+ private int maxDiceVal;
+
+ /**
+ *
+ * @param maxDiceVal Denotes the size of the Dice
+ */
+ public Dice(int maxDiceVal) {
+ this.maxDiceVal = maxDiceVal;
+ }
+
+ public int rollDice() {
+ return getRandomNumberBetween(1, maxDiceVal);
+ }
+
+ private int getRandomNumberBetween(int min, int max) throws IllegalArgumentException {
+ if (max < min) {
+ throw new IllegalArgumentException("Max value "+max+" should be less than min "+min);
+ }
+ Random r = new Random();
+ return r.nextInt((max-min)+1)+min;
+ }
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/GameBoard.java b/SnakeAndLadder/src/main/java/org/main/GameBoard.java
new file mode 100644
index 00000000..3ab50430
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/GameBoard.java
@@ -0,0 +1,5 @@
+package org.main;
+
+public interface GameBoard {
+
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/GameFilePathManager.java b/SnakeAndLadder/src/main/java/org/main/GameFilePathManager.java
new file mode 100644
index 00000000..6f1fcbc5
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/GameFilePathManager.java
@@ -0,0 +1,40 @@
+package org.main;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+@Getter
+@Setter(AccessLevel.PRIVATE)
+public class GameFilePathManager {
+ private Path filePath;
+
+ public GameFilePathManager() {
+ filePath = null;
+ }
+
+ public Boolean fileExists(Path path) {
+ if (Files.exists(path)) {
+ return true;
+ }
+ return false;
+ }
+
+ public Boolean validateAndSetFilePath(String path) {
+ if (path == null || path.isEmpty()) {
+ System.out.println("The File path provided for the game " +path+ " is not valid");
+ } else {
+ Path tempFilePath = Paths.get(path);
+ if (fileExists(tempFilePath)) {
+ filePath = tempFilePath;
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/GamePlay.java b/SnakeAndLadder/src/main/java/org/main/GamePlay.java
new file mode 100644
index 00000000..6713ebe5
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/GamePlay.java
@@ -0,0 +1,4 @@
+package org.main;
+
+public interface GamePlay {
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/GamePlayers.java b/SnakeAndLadder/src/main/java/org/main/GamePlayers.java
new file mode 100644
index 00000000..3e7e955f
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/GamePlayers.java
@@ -0,0 +1,4 @@
+package org.main;
+
+public interface GamePlayers {
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/LoadGameBoard.java b/SnakeAndLadder/src/main/java/org/main/LoadGameBoard.java
new file mode 100644
index 00000000..a6eb4b07
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/LoadGameBoard.java
@@ -0,0 +1,8 @@
+package org.main;
+
+import java.io.FileNotFoundException;
+
+public interface LoadGameBoard {
+ public void LoadGameboard() throws FileNotFoundException;
+}
+
diff --git a/SnakeAndLadder/src/main/java/org/main/Main.java b/SnakeAndLadder/src/main/java/org/main/Main.java
new file mode 100644
index 00000000..593e2f08
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/Main.java
@@ -0,0 +1,29 @@
+package org.main;
+
+import java.io.FileNotFoundException;
+import java.util.Scanner;
+
+public class Main {
+ public static void main(String[] args) throws FileNotFoundException {
+
+ System.out.println("Hello and welcome to the Snake and Ladder!");
+ Scanner scanner = new Scanner(System.in);
+ String filepath="";
+
+ GameFilePathManager gameFilePathManager = new GameFilePathManager();
+ while (!(gameFilePathManager.validateAndSetFilePath(filepath))) {
+ System.out.println("Please give the valid game Loader file path");
+ filepath = scanner.nextLine();
+ }
+ GameBoard gameBoard = new SnakeAndLadderGameBoard(gameFilePathManager, new Dice(6));
+ SnakeAndLadderGameBoardLoader snakeAndLadderGameBoardLoader = new SnakeAndLadderGameBoardLoader(gameBoard);
+ snakeAndLadderGameBoardLoader.LoadGameboard();
+
+ for(int i =0; i<1; i++) {
+ SnakeAndLadderGamePlayers snakeAndLadderGamePlayers = new SnakeAndLadderGamePlayers();
+ snakeAndLadderGamePlayers.LoadPlayers(snakeAndLadderGameBoardLoader.getSnakeAndLadderGamePlayers());
+ SnakeAndLadderGameBoardPlay snakeAndLadderGameBoardPlay = new SnakeAndLadderGameBoardPlay((SnakeAndLadderGameBoard)gameBoard, snakeAndLadderGamePlayers);
+ snakeAndLadderGameBoardPlay.StartGame();
+ }
+ }
+}
\ No newline at end of file
diff --git a/SnakeAndLadder/src/main/java/org/main/MovementCause.java b/SnakeAndLadder/src/main/java/org/main/MovementCause.java
new file mode 100644
index 00000000..0be1635a
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/MovementCause.java
@@ -0,0 +1,16 @@
+package org.main;
+
+import lombok.Getter;
+
+@Getter
+public enum MovementCause {
+ SNAKE_BITE("Snake bite"),
+ GOT_LADDER("Got Ladder"),
+ DICE("Dice");
+
+ MovementCause(String description) {
+ this.description = description;
+ }
+
+ private String description;
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/Player.java b/SnakeAndLadder/src/main/java/org/main/Player.java
new file mode 100644
index 00000000..e2abaf1d
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/Player.java
@@ -0,0 +1,45 @@
+package org.main;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.ArrayList;
+
+@Getter
+@Setter
+class PlayerMove {
+ private Integer initialPosition;
+ private Integer finalPosition;
+ private MovementCause cause;
+
+ public PlayerMove(Integer initialPosition, Integer finalPosition, MovementCause cause) {
+ this.initialPosition = initialPosition;
+ this.finalPosition = finalPosition;
+ this.cause = cause;
+ }
+}
+
+@Getter
+@Setter
+@ToString
+public class Player {
+ private String name;
+ private Integer curPosition;
+ private PlayerStatus playerStatus;
+ private ArrayList moves;
+
+ public Player(String name) {
+ this.name = name;
+ this.curPosition = 0;
+ this.playerStatus = PlayerStatus.IDLE;
+ this.moves = new ArrayList<>();
+ }
+
+ public boolean won() {
+ if (this.playerStatus == PlayerStatus.WON) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/PlayerStatus.java b/SnakeAndLadder/src/main/java/org/main/PlayerStatus.java
new file mode 100644
index 00000000..82b7d7d2
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/PlayerStatus.java
@@ -0,0 +1,7 @@
+package org.main;
+
+public enum PlayerStatus {
+ PLAYING,
+ WON,
+ IDLE;
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoard.java b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoard.java
new file mode 100644
index 00000000..4a8b12f4
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoard.java
@@ -0,0 +1,33 @@
+package org.main;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.HashMap;
+
+@Setter
+@Getter
+@ToString
+public class SnakeAndLadderGameBoard implements GameBoard {
+ private GameFilePathManager gameFilePathManager;
+ private HashMap SnakesMap;
+ private HashMap LadderMap;
+ private Dice dice;
+
+ public SnakeAndLadderGameBoard(GameFilePathManager gameFilePathManager, Dice dice) {
+ this.gameFilePathManager = gameFilePathManager;
+ SnakesMap = new HashMap<>();
+ LadderMap = new HashMap<>();
+ this.dice = dice;
+ }
+
+ public Integer caughtBySnake(Integer curPosition) {
+ return SnakesMap.getOrDefault(curPosition, -1);
+ }
+
+ public Integer gotLadder(Integer curPosition) {
+ return LadderMap.getOrDefault(curPosition, -1);
+ }
+
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardLoader.java b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardLoader.java
new file mode 100644
index 00000000..ca5317ee
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardLoader.java
@@ -0,0 +1,91 @@
+package org.main;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+@Getter
+@Setter
+public class SnakeAndLadderGameBoardLoader implements LoadGameBoard{
+ private GameBoard gameBoard;
+ private Scanner gameBoardFileScanner;
+ private ArrayList snakeAndLadderGamePlayers;
+ private SnakeAndLadderGameBoard snakeAndLadderGameBoard;
+
+ public SnakeAndLadderGameBoardLoader(GameBoard gameBoard) {
+ this.gameBoard = gameBoard;
+ this.snakeAndLadderGamePlayers = new ArrayList<>();
+ }
+
+ private void readGameBoardFile() throws FileNotFoundException {
+ snakeAndLadderGameBoard = (SnakeAndLadderGameBoard)(gameBoard);
+ Path path = snakeAndLadderGameBoard.getGameFilePathManager().getFilePath();
+ File file = new File(String.valueOf(path));
+ gameBoardFileScanner = new Scanner(file);
+ }
+
+ private boolean checkIfGameBoardIsOfSnakeAndLadder() {
+ return (gameBoard instanceof SnakeAndLadderGameBoard);
+ }
+
+ private void LoadSnakes(int numOfSnakes) {
+ while (numOfSnakes > 0) {
+ Integer snakeHead = gameBoardFileScanner.nextInt();
+ Integer snakeTail = gameBoardFileScanner.nextInt();
+ //System.out.println("Adding the snake with snakeHead "+snakeHead+" and snakeTail "+snakeTail);
+ snakeAndLadderGameBoard.getSnakesMap().put(snakeHead, snakeTail);
+ numOfSnakes--;
+ }
+ }
+
+ private void LoadLadders(int numOfLadders) {
+ while (numOfLadders > 0) {
+ Integer ladderHead = gameBoardFileScanner.nextInt();
+ Integer ladderTail = gameBoardFileScanner.nextInt();
+ //System.out.println("Adding the snake with ladderHead "+ladderHead+" and ladderTail "+ladderTail);
+ snakeAndLadderGameBoard.getLadderMap().put(ladderHead, ladderTail);
+ numOfLadders--;
+ }
+ }
+
+ private void LoadUsers(int numOfUsers) {
+ gameBoardFileScanner.nextLine();
+ while (numOfUsers > 0) {
+ String name = gameBoardFileScanner.nextLine();
+ //System.out.println("Adding a user with name "+name);
+ snakeAndLadderGamePlayers.add(name);
+ numOfUsers--;
+ }
+ }
+
+ @Override
+ public void LoadGameboard() throws FileNotFoundException {
+ if (checkIfGameBoardIsOfSnakeAndLadder()) {
+ readGameBoardFile();
+ //Load snakes
+ int numOfSnakes = gameBoardFileScanner.nextInt();
+ //System.out.println("Number of Snakes for the game is = "+ numOfSnakes);
+ LoadSnakes(numOfSnakes);
+
+ //Load Ladders
+ int numOfLadders = gameBoardFileScanner.nextInt();
+ //System.out.println("Number of Ladders for the game is = "+ numOfLadders);
+ LoadLadders(numOfLadders);
+
+ //Load Users
+ int numOfUsers = gameBoardFileScanner.nextInt();
+ //System.out.println("Number of Users for the game is = "+ numOfUsers);
+ LoadUsers(numOfUsers);
+
+ gameBoardFileScanner.close();
+ } else {
+ System.out.println("The Object Provided for the class"+ SnakeAndLadderGameBoardLoader.class +" is not of type "+ SnakeAndLadderGameBoard.class);
+ System.exit(0);
+ }
+ }
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardPlay.java b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardPlay.java
new file mode 100644
index 00000000..d675a68e
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardPlay.java
@@ -0,0 +1,74 @@
+package org.main;
+
+public class SnakeAndLadderGameBoardPlay implements GamePlay {
+ private SnakeAndLadderGameBoard snakeAndLadderGameBoard;
+ private SnakeAndLadderGamePlayers snakeAndLadderGamePlayers;
+ private boolean stopGame;
+
+ public SnakeAndLadderGameBoardPlay(SnakeAndLadderGameBoard snakeAndLadderGameBoard, SnakeAndLadderGamePlayers snakeAndLadderGamePlayers) {
+ this.snakeAndLadderGameBoard = snakeAndLadderGameBoard;
+ this.snakeAndLadderGamePlayers = snakeAndLadderGamePlayers;
+ }
+
+ public void updatePlayersGameStart() {
+ for (Player player : snakeAndLadderGamePlayers.getPlayers()) {
+ player.setPlayerStatus(PlayerStatus.PLAYING);
+ player.setPlayerStatus(PlayerStatus.PLAYING);
+ }
+ }
+
+ public void StartGame() {
+ stopGame = false;
+ Integer diceVal;
+ updatePlayersGameStart();
+
+ while (!(stopGame)) {
+ for (Player player : snakeAndLadderGamePlayers.getPlayers()) {
+ if (stopGame) {
+ break;
+ }
+ diceVal = snakeAndLadderGameBoard.getDice().rollDice();
+ movePlayerOnBoard(diceVal, player, MovementCause.DICE);
+ }
+ }
+ }
+
+ public void printMove(Integer newPos, Player player, MovementCause cause) {
+ if (cause == MovementCause.DICE) {
+ int diceVal = newPos - player.getCurPosition();
+ System.out.println(player.getName()+ " rolled a "+diceVal+" and Moved From "+player.getCurPosition()+ " to "+newPos);
+ } else {
+ System.out.println(player.getName()+" "+cause.getDescription()+" and Moved From "+player.getCurPosition()+ " to "+newPos);
+ }
+ }
+
+ public void updatePlayer(Integer newPos, Player player, MovementCause cause) {
+ if (newPos <= 100) {
+ printMove(newPos, player, cause);
+ player.getMoves().add(new PlayerMove(player.getCurPosition(), newPos, cause));
+ if (newPos == 100) {
+ stopGame = true;
+ player.setPlayerStatus(PlayerStatus.WON);
+ System.out.println(player.getName()+" won!! ");
+ }
+ player.setCurPosition(newPos);
+ }
+ }
+
+ public void movePlayerOnBoard(Integer diceVal, Player player, MovementCause cause) {
+ Integer newPos;
+ if (cause == MovementCause.DICE) {
+ newPos = player.getCurPosition() + diceVal;
+ } else {
+ newPos = diceVal;
+ }
+ updatePlayer(newPos, player, cause);
+ if (snakeAndLadderGameBoard.caughtBySnake(newPos)!=-1) {
+ newPos = snakeAndLadderGameBoard.caughtBySnake(newPos);
+ movePlayerOnBoard(newPos, player, MovementCause.SNAKE_BITE);
+ } else if (snakeAndLadderGameBoard.gotLadder(newPos)!=-1) {
+ newPos = snakeAndLadderGameBoard.gotLadder(newPos);
+ movePlayerOnBoard(newPos, player, MovementCause.GOT_LADDER);
+ }
+ }
+}
diff --git a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGamePlayers.java b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGamePlayers.java
new file mode 100644
index 00000000..57824078
--- /dev/null
+++ b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGamePlayers.java
@@ -0,0 +1,22 @@
+package org.main;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+
+@Getter
+@Setter
+public class SnakeAndLadderGamePlayers implements GamePlayers{
+ private ArrayList players;
+
+ public SnakeAndLadderGamePlayers() {
+ this.players = new ArrayList<>();
+ }
+
+ public void LoadPlayers (ArrayList players) {
+ for (String name : players) {
+ this.players.add(new Player(name));
+ }
+ }
+}
diff --git a/SnakeAndLadder/src/main/resources/SankeAndLadderGameInput.txt b/SnakeAndLadder/src/main/resources/SankeAndLadderGameInput.txt
new file mode 100644
index 00000000..5be01773
--- /dev/null
+++ b/SnakeAndLadder/src/main/resources/SankeAndLadderGameInput.txt
@@ -0,0 +1,22 @@
+9
+62 5
+33 6
+49 9
+88 16
+41 20
+56 53
+98 64
+93 73
+95 75
+8
+2 37
+27 46
+10 32
+51 68
+61 79
+65 84
+71 91
+81 100
+2
+Gaurav
+Sagar
\ No newline at end of file
diff --git a/SnakeAndLadder/src/test/java/org/main/DiceTest.java b/SnakeAndLadder/src/test/java/org/main/DiceTest.java
new file mode 100644
index 00000000..f9ea7201
--- /dev/null
+++ b/SnakeAndLadder/src/test/java/org/main/DiceTest.java
@@ -0,0 +1,25 @@
+package org.main;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class DiceTest {
+ public boolean isBetween(int min, int max, int val) {
+ return (val <= max && val >=min);
+ }
+
+ @Test
+ public void testRollDice() {
+ final int maxDiceVal = 4;
+ int diceVal;
+ Dice dice = new Dice(maxDiceVal);
+
+ //Test the Random generator used in Dice class
+ for (int i=0; i < 100; i++) {
+ diceVal = dice.rollDice();
+ System.out.println("Dice Val is "+diceVal);
+ assertTrue(isBetween(1, maxDiceVal, diceVal), "Val Produced "+ diceVal+" is in range 1 and "+maxDiceVal);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/SnakeAndLadder/src/test/java/org/main/GameFilePathManagerTest.java b/SnakeAndLadder/src/test/java/org/main/GameFilePathManagerTest.java
new file mode 100644
index 00000000..9b939507
--- /dev/null
+++ b/SnakeAndLadder/src/test/java/org/main/GameFilePathManagerTest.java
@@ -0,0 +1,39 @@
+package org.main;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class TestCase {
+ String path;
+ Boolean result;
+ String description;
+
+ public TestCase(String path, Boolean result, String description) {
+ this.path = path;
+ this.result = result;
+ this.description = description;
+ }
+}
+
+class GameFilePathManagerTest {
+ @Test
+ void validateAndSetFilePath() {
+ GameFilePathManager gameFilePathManager = new GameFilePathManager();
+
+ final TestCase[] testCases = new TestCase[] {
+ new TestCase("src/main/resources/SankeAndLadderGameInput.txt", true, "Correct path for Snake and Ladder Game"),
+ new TestCase("src/main/resources/SankeAndLadderGameInt.txt", false, "Correct path but wrong file name"),
+ new TestCase("resources/SankeAndLadderGameInput.txt", false, "Invalid path but correct File name")
+ };
+
+ for (TestCase test: testCases) {
+ try {
+ assertEquals(test.result, gameFilePathManager.validateAndSetFilePath(test.path));
+ System.out.println(test.description+" -- Passed");
+ } catch (AssertionError e) {
+ System.out.println(test.description+" -- Failed due to "+ e);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardLoaderTest.java b/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardLoaderTest.java
new file mode 100644
index 00000000..3b6421ea
--- /dev/null
+++ b/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardLoaderTest.java
@@ -0,0 +1,19 @@
+package org.main;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.FileNotFoundException;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class SnakeAndLadderGameBoardLoaderTest {
+
+ @Test
+ void loadGameboard() throws FileNotFoundException {
+ GameFilePathManager gameFilePathManager = new GameFilePathManager();
+ gameFilePathManager.validateAndSetFilePath("src/main/resources/SankeAndLadderGameInput.txt");
+ GameBoard gameBoard = new SnakeAndLadderGameBoard(gameFilePathManager, new Dice(4));
+ SnakeAndLadderGameBoardLoader snakeAndLadderGameBoardLoader = new SnakeAndLadderGameBoardLoader(gameBoard);
+ snakeAndLadderGameBoardLoader.LoadGameboard();
+ }
+}
\ No newline at end of file
diff --git a/SnakeAndLadder/target/classes/SankeAndLadderGameInput.txt b/SnakeAndLadder/target/classes/SankeAndLadderGameInput.txt
new file mode 100644
index 00000000..5be01773
--- /dev/null
+++ b/SnakeAndLadder/target/classes/SankeAndLadderGameInput.txt
@@ -0,0 +1,22 @@
+9
+62 5
+33 6
+49 9
+88 16
+41 20
+56 53
+98 64
+93 73
+95 75
+8
+2 37
+27 46
+10 32
+51 68
+61 79
+65 84
+71 91
+81 100
+2
+Gaurav
+Sagar
\ No newline at end of file
From 82f7aaf4ceb41d96268625410e036c99381119de Mon Sep 17 00:00:00 2001
From: maheshreddym395 <39896413+maheshreddym395@users.noreply.github.com>
Date: Sat, 23 Nov 2024 16:31:29 +0530
Subject: [PATCH 2/3] Added the extra checks into the code fort the other
requirements
---
SnakeAndLadder/pom.xml | 6 ++
.../src/main/java/org/main/Dice.java | 25 ++++---
.../src/main/java/org/main/Main.java | 7 +-
.../org/main/SnakeAndLadderGameBoard.java | 4 +-
.../main/SnakeAndLadderGameBoardLoader.java | 6 +-
.../org/main/SnakeAndLadderGameBoardPlay.java | 67 ++++++++++++++++---
.../org/main/SnakeAndLadderGamePlayers.java | 6 ++
.../resources/SankeAndLadderGameInput.txt | 6 +-
.../src/test/java/org/main/DiceTest.java | 6 +-
.../SnakeAndLadderGameBoardLoaderTest.java | 4 +-
.../main/SnakeAndLadderGameBoardPlayTest.java | 30 +++++++++
.../classes/SankeAndLadderGameInput.txt | 6 +-
12 files changed, 137 insertions(+), 36 deletions(-)
create mode 100644 SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardPlayTest.java
diff --git a/SnakeAndLadder/pom.xml b/SnakeAndLadder/pom.xml
index aac9edb1..68167b0c 100644
--- a/SnakeAndLadder/pom.xml
+++ b/SnakeAndLadder/pom.xml
@@ -15,6 +15,12 @@
+
+ org.mockito
+ mockito-core
+ 5.12.0
+ test
+
org.projectlombok
lombok
diff --git a/SnakeAndLadder/src/main/java/org/main/Dice.java b/SnakeAndLadder/src/main/java/org/main/Dice.java
index b0f4f128..1b404afd 100644
--- a/SnakeAndLadder/src/main/java/org/main/Dice.java
+++ b/SnakeAndLadder/src/main/java/org/main/Dice.java
@@ -1,23 +1,32 @@
package org.main;
+import lombok.Getter;
+import lombok.Setter;
+
import java.util.Random;
/**
*
*/
+@Getter
+@Setter
public class Dice {
- private int maxDiceVal;
+ private Integer numOfDices;
+ private Integer minDiceRollValue;
+ private Integer maxDiceRollValue;
+
+ public Dice(Integer numOfDices) {
+ this.numOfDices = numOfDices;
+ updateMinAndMaxDiceRollValues(numOfDices);
+ }
- /**
- *
- * @param maxDiceVal Denotes the size of the Dice
- */
- public Dice(int maxDiceVal) {
- this.maxDiceVal = maxDiceVal;
+ public void updateMinAndMaxDiceRollValues(Integer numOfDices) {
+ minDiceRollValue = numOfDices;
+ maxDiceRollValue = 6*numOfDices;
}
public int rollDice() {
- return getRandomNumberBetween(1, maxDiceVal);
+ return getRandomNumberBetween(minDiceRollValue, maxDiceRollValue);
}
private int getRandomNumberBetween(int min, int max) throws IllegalArgumentException {
diff --git a/SnakeAndLadder/src/main/java/org/main/Main.java b/SnakeAndLadder/src/main/java/org/main/Main.java
index 593e2f08..264b5756 100644
--- a/SnakeAndLadder/src/main/java/org/main/Main.java
+++ b/SnakeAndLadder/src/main/java/org/main/Main.java
@@ -4,7 +4,7 @@
import java.util.Scanner;
public class Main {
- public static void main(String[] args) throws FileNotFoundException {
+ public static void main(String[] args) throws FileNotFoundException, InterruptedException {
System.out.println("Hello and welcome to the Snake and Ladder!");
Scanner scanner = new Scanner(System.in);
@@ -15,15 +15,16 @@ public static void main(String[] args) throws FileNotFoundException {
System.out.println("Please give the valid game Loader file path");
filepath = scanner.nextLine();
}
- GameBoard gameBoard = new SnakeAndLadderGameBoard(gameFilePathManager, new Dice(6));
+ GameBoard gameBoard = new SnakeAndLadderGameBoard(gameFilePathManager, new Dice(2), 120);
SnakeAndLadderGameBoardLoader snakeAndLadderGameBoardLoader = new SnakeAndLadderGameBoardLoader(gameBoard);
snakeAndLadderGameBoardLoader.LoadGameboard();
for(int i =0; i<1; i++) {
SnakeAndLadderGamePlayers snakeAndLadderGamePlayers = new SnakeAndLadderGamePlayers();
- snakeAndLadderGamePlayers.LoadPlayers(snakeAndLadderGameBoardLoader.getSnakeAndLadderGamePlayers());
+ snakeAndLadderGamePlayers.LoadPlayers(snakeAndLadderGameBoardLoader.getSnakeAndLadderGamePlayersNames());
SnakeAndLadderGameBoardPlay snakeAndLadderGameBoardPlay = new SnakeAndLadderGameBoardPlay((SnakeAndLadderGameBoard)gameBoard, snakeAndLadderGamePlayers);
snakeAndLadderGameBoardPlay.StartGame();
+ System.out.println("Thanks for playing the snake and ladder Game!!!!");
}
}
}
\ No newline at end of file
diff --git a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoard.java b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoard.java
index 4a8b12f4..119b0d50 100644
--- a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoard.java
+++ b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoard.java
@@ -13,13 +13,15 @@ public class SnakeAndLadderGameBoard implements GameBoard {
private GameFilePathManager gameFilePathManager;
private HashMap SnakesMap;
private HashMap LadderMap;
+ private Integer boardSize;
private Dice dice;
- public SnakeAndLadderGameBoard(GameFilePathManager gameFilePathManager, Dice dice) {
+ public SnakeAndLadderGameBoard(GameFilePathManager gameFilePathManager, Dice dice, Integer size) {
this.gameFilePathManager = gameFilePathManager;
SnakesMap = new HashMap<>();
LadderMap = new HashMap<>();
this.dice = dice;
+ this.boardSize = size;
}
public Integer caughtBySnake(Integer curPosition) {
diff --git a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardLoader.java b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardLoader.java
index ca5317ee..8a08ab83 100644
--- a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardLoader.java
+++ b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardLoader.java
@@ -14,12 +14,12 @@
public class SnakeAndLadderGameBoardLoader implements LoadGameBoard{
private GameBoard gameBoard;
private Scanner gameBoardFileScanner;
- private ArrayList snakeAndLadderGamePlayers;
+ private ArrayList snakeAndLadderGamePlayersNames;
private SnakeAndLadderGameBoard snakeAndLadderGameBoard;
public SnakeAndLadderGameBoardLoader(GameBoard gameBoard) {
this.gameBoard = gameBoard;
- this.snakeAndLadderGamePlayers = new ArrayList<>();
+ this.snakeAndLadderGamePlayersNames = new ArrayList<>();
}
private void readGameBoardFile() throws FileNotFoundException {
@@ -58,7 +58,7 @@ private void LoadUsers(int numOfUsers) {
while (numOfUsers > 0) {
String name = gameBoardFileScanner.nextLine();
//System.out.println("Adding a user with name "+name);
- snakeAndLadderGamePlayers.add(name);
+ snakeAndLadderGamePlayersNames.add(name);
numOfUsers--;
}
}
diff --git a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardPlay.java b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardPlay.java
index d675a68e..90070617 100644
--- a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardPlay.java
+++ b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGameBoardPlay.java
@@ -3,7 +3,6 @@
public class SnakeAndLadderGameBoardPlay implements GamePlay {
private SnakeAndLadderGameBoard snakeAndLadderGameBoard;
private SnakeAndLadderGamePlayers snakeAndLadderGamePlayers;
- private boolean stopGame;
public SnakeAndLadderGameBoardPlay(SnakeAndLadderGameBoard snakeAndLadderGameBoard, SnakeAndLadderGamePlayers snakeAndLadderGamePlayers) {
this.snakeAndLadderGameBoard = snakeAndLadderGameBoard;
@@ -17,23 +16,69 @@ public void updatePlayersGameStart() {
}
}
- public void StartGame() {
- stopGame = false;
+ public boolean stopGame () {
+ if ((snakeAndLadderGamePlayers.getPlayers().size() - snakeAndLadderGamePlayers.getNumOfPlayersWon()) == 1) {
+ return true;
+ }
+ return false;
+ }
+
+ public void StartGame() throws InterruptedException {
Integer diceVal;
+ Integer consecutiveMaxDiceRollCount = 0;
updatePlayersGameStart();
- while (!(stopGame)) {
+ while (!(stopGame())) {
for (Player player : snakeAndLadderGamePlayers.getPlayers()) {
- if (stopGame) {
+ consecutiveMaxDiceRollCount = 0;
+ if (stopGame()) {
break;
}
+ if (player.getPlayerStatus() == PlayerStatus.WON) {
+ continue;
+ }
+
+ //First Roll
diceVal = snakeAndLadderGameBoard.getDice().rollDice();
- movePlayerOnBoard(diceVal, player, MovementCause.DICE);
+
+ //Consecutive Dice Rolls
+ if (diceVal == snakeAndLadderGameBoard.getDice().getMaxDiceRollValue()) {
+ do {
+ consecutiveMaxDiceRollCount++;
+ System.out.println(player.getName()+" Rolled a "+snakeAndLadderGameBoard.getDice().getMaxDiceRollValue()+" will get another chance ,Currently Chance num "+ consecutiveMaxDiceRollCount);
+ movePlayerOnBoard(diceVal, player, MovementCause.DICE);
+ diceVal = snakeAndLadderGameBoard.getDice().rollDice();
+ } while (diceVal == snakeAndLadderGameBoard.getDice().getMaxDiceRollValue() && consecutiveMaxDiceRollCount<3);
+ }
+
+ if (consecutiveMaxDiceRollCount == 3 && diceVal == snakeAndLadderGameBoard.getDice().getMaxDiceRollValue()) {
+ revertMovesOfPlayerOnBoard(player);
+ } else {
+ movePlayerOnBoard(diceVal, player, MovementCause.DICE);
+ }
}
}
}
+ public void revertMovesOfPlayerOnBoard(Player player) {
+ System.out.println(player.getName()+ " Rolled more than 4 times consecutively "+ snakeAndLadderGameBoard.getDice().getMaxDiceRollValue()+" So we are cancelling all his moves ");
+ PlayerMove lastMove;
+ int i = 3;
+
+ while (i>0) {
+ lastMove = player.getMoves().removeLast();
+ System.out.println(player.getName()+ " movement reverted from "+ lastMove.getFinalPosition() +" to "+lastMove.getInitialPosition());
+ player.setCurPosition(lastMove.getInitialPosition());
+ i--;
+ }
+
+ }
+
public void printMove(Integer newPos, Player player, MovementCause cause) {
+ if (newPos > snakeAndLadderGameBoard.getBoardSize()) {
+ System.out.println(player.getName()+" Is trying to move to "+ newPos +" which is out of boundary of the board of size "+ snakeAndLadderGameBoard.getBoardSize());
+ }
+
if (cause == MovementCause.DICE) {
int diceVal = newPos - player.getCurPosition();
System.out.println(player.getName()+ " rolled a "+diceVal+" and Moved From "+player.getCurPosition()+ " to "+newPos);
@@ -43,13 +88,13 @@ public void printMove(Integer newPos, Player player, MovementCause cause) {
}
public void updatePlayer(Integer newPos, Player player, MovementCause cause) {
- if (newPos <= 100) {
- printMove(newPos, player, cause);
+ printMove(newPos, player, cause);
+ if (newPos <= snakeAndLadderGameBoard.getBoardSize()) {
player.getMoves().add(new PlayerMove(player.getCurPosition(), newPos, cause));
- if (newPos == 100) {
- stopGame = true;
+ if (newPos == snakeAndLadderGameBoard.getBoardSize()) {
player.setPlayerStatus(PlayerStatus.WON);
- System.out.println(player.getName()+" won!! ");
+ System.out.println(player.getName()+" Reached "+snakeAndLadderGameBoard.getBoardSize()+" won!! ");
+ snakeAndLadderGamePlayers.getPlayersWon().add(player);
}
player.setCurPosition(newPos);
}
diff --git a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGamePlayers.java b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGamePlayers.java
index 57824078..026c49e6 100644
--- a/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGamePlayers.java
+++ b/SnakeAndLadder/src/main/java/org/main/SnakeAndLadderGamePlayers.java
@@ -9,9 +9,11 @@
@Setter
public class SnakeAndLadderGamePlayers implements GamePlayers{
private ArrayList players;
+ private ArrayList playersWon;
public SnakeAndLadderGamePlayers() {
this.players = new ArrayList<>();
+ this.playersWon = new ArrayList<>();
}
public void LoadPlayers (ArrayList players) {
@@ -19,4 +21,8 @@ public void LoadPlayers (ArrayList players) {
this.players.add(new Player(name));
}
}
+
+ public Integer getNumOfPlayersWon() {
+ return playersWon.size();
+ }
}
diff --git a/SnakeAndLadder/src/main/resources/SankeAndLadderGameInput.txt b/SnakeAndLadder/src/main/resources/SankeAndLadderGameInput.txt
index 5be01773..5ee5a87f 100644
--- a/SnakeAndLadder/src/main/resources/SankeAndLadderGameInput.txt
+++ b/SnakeAndLadder/src/main/resources/SankeAndLadderGameInput.txt
@@ -17,6 +17,8 @@
65 84
71 91
81 100
-2
+4
Gaurav
-Sagar
\ No newline at end of file
+Sagar
+Mahesh
+Anusha
\ No newline at end of file
diff --git a/SnakeAndLadder/src/test/java/org/main/DiceTest.java b/SnakeAndLadder/src/test/java/org/main/DiceTest.java
index f9ea7201..bfe10785 100644
--- a/SnakeAndLadder/src/test/java/org/main/DiceTest.java
+++ b/SnakeAndLadder/src/test/java/org/main/DiceTest.java
@@ -10,15 +10,15 @@ public boolean isBetween(int min, int max, int val) {
@Test
public void testRollDice() {
- final int maxDiceVal = 4;
+ final int numOfDices = 2;
int diceVal;
- Dice dice = new Dice(maxDiceVal);
+ Dice dice = new Dice(numOfDices);
//Test the Random generator used in Dice class
for (int i=0; i < 100; i++) {
diceVal = dice.rollDice();
System.out.println("Dice Val is "+diceVal);
- assertTrue(isBetween(1, maxDiceVal, diceVal), "Val Produced "+ diceVal+" is in range 1 and "+maxDiceVal);
+ assertTrue(isBetween(dice.getMinDiceRollValue(), dice.getMaxDiceRollValue(), diceVal), "Val Produced "+ dice.getMinDiceRollValue()+" is in range 1 and "+dice.getMaxDiceRollValue());
}
}
diff --git a/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardLoaderTest.java b/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardLoaderTest.java
index 3b6421ea..98580118 100644
--- a/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardLoaderTest.java
+++ b/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardLoaderTest.java
@@ -4,15 +4,13 @@
import java.io.FileNotFoundException;
-import static org.junit.jupiter.api.Assertions.*;
-
class SnakeAndLadderGameBoardLoaderTest {
@Test
void loadGameboard() throws FileNotFoundException {
GameFilePathManager gameFilePathManager = new GameFilePathManager();
gameFilePathManager.validateAndSetFilePath("src/main/resources/SankeAndLadderGameInput.txt");
- GameBoard gameBoard = new SnakeAndLadderGameBoard(gameFilePathManager, new Dice(4));
+ GameBoard gameBoard = new SnakeAndLadderGameBoard(gameFilePathManager, new Dice(2), 120);
SnakeAndLadderGameBoardLoader snakeAndLadderGameBoardLoader = new SnakeAndLadderGameBoardLoader(gameBoard);
snakeAndLadderGameBoardLoader.LoadGameboard();
}
diff --git a/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardPlayTest.java b/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardPlayTest.java
new file mode 100644
index 00000000..c5297377
--- /dev/null
+++ b/SnakeAndLadder/src/test/java/org/main/SnakeAndLadderGameBoardPlayTest.java
@@ -0,0 +1,30 @@
+package org.main;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.FileNotFoundException;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+class SnakeAndLadderGameBoardPlayTest {
+
+ @Test
+ void startGame() throws FileNotFoundException, InterruptedException {
+ String filepath = "C:\\Users\\mahes\\Exercism\\java\\SnakeAndLadder\\src\\main\\resources\\SankeAndLadderGameInput.txt";
+
+ GameFilePathManager gameFilePathManager = new GameFilePathManager();
+ gameFilePathManager.validateAndSetFilePath(filepath);
+ Dice spyDice = spy(new Dice(2));
+
+ GameBoard gameBoard = new SnakeAndLadderGameBoard(gameFilePathManager, spyDice, 120);
+ SnakeAndLadderGameBoardLoader snakeAndLadderGameBoardLoader = new SnakeAndLadderGameBoardLoader(gameBoard);
+ snakeAndLadderGameBoardLoader.LoadGameboard();
+ SnakeAndLadderGamePlayers snakeAndLadderGamePlayers = new SnakeAndLadderGamePlayers();
+ snakeAndLadderGamePlayers.LoadPlayers(snakeAndLadderGameBoardLoader.getSnakeAndLadderGamePlayersNames());
+ SnakeAndLadderGameBoardPlay snakeAndLadderGameBoardPlay = new SnakeAndLadderGameBoardPlay((SnakeAndLadderGameBoard) gameBoard, snakeAndLadderGamePlayers);
+
+ when(spyDice.rollDice()).thenReturn(12);
+ snakeAndLadderGameBoardPlay.StartGame();
+ }
+}
\ No newline at end of file
diff --git a/SnakeAndLadder/target/classes/SankeAndLadderGameInput.txt b/SnakeAndLadder/target/classes/SankeAndLadderGameInput.txt
index 5be01773..5ee5a87f 100644
--- a/SnakeAndLadder/target/classes/SankeAndLadderGameInput.txt
+++ b/SnakeAndLadder/target/classes/SankeAndLadderGameInput.txt
@@ -17,6 +17,8 @@
65 84
71 91
81 100
-2
+4
Gaurav
-Sagar
\ No newline at end of file
+Sagar
+Mahesh
+Anusha
\ No newline at end of file
From c04fd0acd67a075a1a4148f19e824a264a8eb65b Mon Sep 17 00:00:00 2001
From: maheshreddym395 <39896413+maheshreddym395@users.noreply.github.com>
Date: Sun, 24 Nov 2024 23:55:44 +0530
Subject: [PATCH 3/3] Solved the Problem of Splitwise
---
SplitWise/pom.xml | 56 ++++
.../src/main/java/org/main/Balances.java | 239 ++++++++++++++++++
.../src/main/java/org/main/Currencies.java | 19 ++
SplitWise/src/main/java/org/main/Group.java | 18 ++
.../src/main/java/org/main/GroupUsers.java | 35 +++
SplitWise/src/main/java/org/main/Main.java | 53 ++++
.../src/main/java/org/main/Transaction.java | 79 ++++++
.../java/org/main/TransactionSummary.java | 17 ++
.../main/java/org/main/TransactionType.java | 65 +++++
SplitWise/src/main/java/org/main/User.java | 42 +++
SplitWise/src/main/resources/transactions.txt | 10 +
.../src/test/java/org/main/BalancesTest.java | 35 +++
.../java/org/main/TransactionTypeTest.java | 41 +++
.../src/test/java/org/main/UserTest.java | 14 +
SplitWise/target/classes/transactions.txt | 10 +
15 files changed, 733 insertions(+)
create mode 100644 SplitWise/pom.xml
create mode 100644 SplitWise/src/main/java/org/main/Balances.java
create mode 100644 SplitWise/src/main/java/org/main/Currencies.java
create mode 100644 SplitWise/src/main/java/org/main/Group.java
create mode 100644 SplitWise/src/main/java/org/main/GroupUsers.java
create mode 100644 SplitWise/src/main/java/org/main/Main.java
create mode 100644 SplitWise/src/main/java/org/main/Transaction.java
create mode 100644 SplitWise/src/main/java/org/main/TransactionSummary.java
create mode 100644 SplitWise/src/main/java/org/main/TransactionType.java
create mode 100644 SplitWise/src/main/java/org/main/User.java
create mode 100644 SplitWise/src/main/resources/transactions.txt
create mode 100644 SplitWise/src/test/java/org/main/BalancesTest.java
create mode 100644 SplitWise/src/test/java/org/main/TransactionTypeTest.java
create mode 100644 SplitWise/src/test/java/org/main/UserTest.java
create mode 100644 SplitWise/target/classes/transactions.txt
diff --git a/SplitWise/pom.xml b/SplitWise/pom.xml
new file mode 100644
index 00000000..204be5a9
--- /dev/null
+++ b/SplitWise/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+ org.main
+ SplitWise
+ 1.0-SNAPSHOT
+
+
+ 21
+ 21
+ UTF-8
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.32
+ provided
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.8.1
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.8.1
+ test
+
+
+ org.mockito
+ mockito-core
+ 5.12.0
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 22
+ 22
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SplitWise/src/main/java/org/main/Balances.java b/SplitWise/src/main/java/org/main/Balances.java
new file mode 100644
index 00000000..81c09ba5
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/Balances.java
@@ -0,0 +1,239 @@
+package org.main;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.util.*;
+import java.text.DecimalFormat;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@Getter
+@Setter
+class StringFloat {
+ private String userId;
+ private Float amt;
+
+ public StringFloat(String userId, Float amt) {
+ this.userId = userId;
+ this.amt = amt;
+ }
+
+
+}
+
+class StringFloatMap extends HashMap {
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ this.forEach((key, value) -> sb.append(key).append("=").append(value).append(", "));
+ if (sb.length() > 1) sb.setLength(sb.length() - 2); // Remove trailing comma and space
+ sb.append("}");
+ return sb.toString();
+ }
+}
+
+@ToString
+public class Balances {
+ private Currencies currencies;
+ private Float totalGroupSpending;
+ private HashMap usersBalancesMap;
+ private HashMap userBalancesSimplifiedMap;
+ public static final DecimalFormat df = new DecimalFormat("#.00");
+
+ public Balances(Currencies currencies) {
+ this.currencies = currencies;
+ this.totalGroupSpending = 0f;
+ usersBalancesMap = new HashMap<>();
+ userBalancesSimplifiedMap = new HashMap<>();
+ }
+
+ //Function to debug print of Map
+ public void printBalancesMap() {
+ System.out.println("\n -- User balances map -- \n");
+ for (Map.Entry usersBalances : usersBalancesMap.entrySet()) {
+ System.out.println("{ "+ usersBalances.getKey()+" = { "+ usersBalances.getValue()+ " }" +" }");
+ }
+ }
+
+ public void initlizeUsersBalancesMap(GroupUsers users) {
+ initlizeUsersBalancesMap(users, this.usersBalancesMap);
+ }
+
+ public void initlizeUsersBalancesMap(GroupUsers users, HashMap usersBalancesMapInit) {
+ ArrayList userIds = new ArrayList<>();
+ StringFloatMap tempMap = new StringFloatMap();
+
+ //creating the Map for all Users present in the Group
+ for (Map.Entry user : users.getUsers().entrySet()) {
+ usersBalancesMapInit.put(user.getKey(), new StringFloatMap());
+ userIds.add(user.getKey());
+ }
+
+ //Updating every UserId with mappings of other user with default value as 0f
+ for (Map.Entry user : usersBalancesMapInit.entrySet()) {
+ for (String userId : userIds) {
+ //Avoiding BalanceMap of its own in the balances Map
+ if (user.getKey() != userId) {
+ user.getValue().put(userId, 0f);
+ }
+ }
+ }
+ }
+
+ public HashMap getBalanceForUser(String userId) {
+ return usersBalancesMap.get(userId);
+ }
+
+ public Float getBalanceForUser (String userId1, String userId2, HashMap usersBalancesMaping) {
+ StringFloatMap userBalances = usersBalancesMaping.get(userId1);
+ return userBalances.get(userId2);
+ }
+
+ //Set of print functions for Single user input
+ public void getBalanceForUserPrint(String userId1) {
+ getBalanceForUserPrint(userId1, true);
+ }
+
+ public void getBalanceForUserPrint(String userId1, Boolean showNoBalance) {
+ getBalanceForUserPrint(userId1, true, usersBalancesMap);
+ }
+
+ public int getBalanceForUserPrint(String userId1, Boolean showNoBalance, HashMap usersBalancesMaping)
+ {
+ AtomicInteger userWithBalanceSum = new AtomicInteger(0);
+
+ getBalanceForUser(userId1).forEach((userIdBal, balanceMap) -> {
+ userWithBalanceSum.addAndGet(getBalanceForUserPrint(userId1, userIdBal, false, usersBalancesMaping));
+ });
+
+ if (userWithBalanceSum.get() == 0 && showNoBalance) {
+ System.out.println("No Balance");
+ }
+
+ return userWithBalanceSum.get();
+ }
+
+ //Set of print functions for Dual user input
+ // By default, it shows the No Balance Msg
+ public void getBalanceForUserPrint(String userId1, String userId2) {
+ getBalanceForUserPrint(userId1, userId2, true);
+ }
+
+ public void getBalanceForUserPrint(String userId1, String userId2, Boolean showNoBalance) {
+ getBalanceForUserPrint(userId1, userId2, showNoBalance, usersBalancesMap);
+ }
+
+ public int getBalanceForUserPrint(String userId1, String userId2, Boolean showNoBalance, HashMap usersBalancesMaping) {
+ Float balance = getBalanceForUser(userId1, userId2, usersBalancesMaping);
+
+ if (balance > 0) {
+ System.out.println(userId2+ " Owes " + userId1 + " an amount of "+ currencies.getCurrencySymbol()+df.format(balance));
+ return 1;
+ } else if (showNoBalance) {
+ System.out.println("No Balance");
+ }
+ return 0;
+ }
+
+ public void printGroupBalances() {
+ System.out.println("\n -- Group balances Summary -- ");
+ AtomicInteger userWithBalanceSum = new AtomicInteger(0);
+
+ usersBalancesMap.forEach( (userId, userBalancesMap) -> {
+ userWithBalanceSum.addAndGet(getBalanceForUserPrint(userId, false, usersBalancesMap));
+ } );
+
+ if (userWithBalanceSum.get() == 0) {
+ System.out.println("No Balance");
+ }
+ }
+
+ public void printSimpliedBalances() {
+ System.out.println("\n -- Simplified balances Summary -- ");
+
+ AtomicInteger userWithBalanceSum = new AtomicInteger(0);
+
+ userBalancesSimplifiedMap.forEach( (userId, userBalancesMap) -> {
+ userWithBalanceSum.addAndGet(getBalanceForUserPrint(userId, false, userBalancesSimplifiedMap));
+ } );
+
+ if (userWithBalanceSum.get() == 0) {
+ System.out.println("No Balance");
+ }
+ }
+
+ public void processSimplifiedBalances(GroupUsers users) {
+ Comparator byBalance = (p1, p2) -> Float.compare(p2.getAmt(), p1.getAmt());
+ PriorityQueue owedSet = new PriorityQueue<>(byBalance);
+ PriorityQueue owesSet = new PriorityQueue<>(byBalance);
+ initlizeUsersBalancesMap(users, this.userBalancesSimplifiedMap);
+ updateOwesAndOwedSet(owedSet, owesSet);
+ calculateAndUpdateSimplifiedBalances(owedSet, owesSet);
+
+ }
+
+ private void calculateAndUpdateSimplifiedBalances(PriorityQueue owedSet, PriorityQueue owesSet)
+ {
+ while (!(owedSet.isEmpty() || owesSet.isEmpty())) {
+ StringFloat temp1 = owedSet.poll();
+ StringFloat temp2 = owesSet.poll();
+
+ /*Diff is negative which means that owedSet user will be cleared of balance and gets deleted and diff amt will be left in owes Set
+ Diff is Positive which means that owesSet user will be cleared of balance and gets deleted and diff amt will be left in owed set*/
+
+ Float balanceAmt = temp1.getAmt() - temp2.getAmt();
+ Float paymentAmt = balanceAmt<0? temp1.getAmt():temp2.getAmt();
+
+ if (balanceAmt < 0) {
+ owesSet.add(new StringFloat(temp2.getUserId(), Math.abs(balanceAmt)));
+ } else if (balanceAmt > 0) {
+ owedSet.add(new StringFloat(temp1.getUserId(), balanceAmt));
+ }
+ userBalancesSimplifiedMap.get(temp1.getUserId()).put(temp2.getUserId(), paymentAmt);
+ }
+ }
+
+ private void updateOwesAndOwedSet(PriorityQueue owedSet, PriorityQueue owesSet) {
+ usersBalancesMap.forEach( (userId, userBalances) -> {
+ float[] totalBalance = {0f};
+ userBalances.forEach( (_, balance) -> {
+ totalBalance[0] = totalBalance[0] + balance;
+ });
+ if (totalBalance[0] < 0f) {
+ owesSet.add(new StringFloat(userId, Math.abs(totalBalance[0])));
+ } else {
+ owedSet.add(new StringFloat(userId, totalBalance[0]));
+ }
+ });
+ }
+
+ public void updateBalances(String transactionUserId, StringFloatMap transactionDetails, Float totalTransactionVal, Group group)
+ {
+ totalGroupSpending = totalGroupSpending + totalTransactionVal;
+ updateTransactionUserBalances(transactionUserId, transactionDetails, totalTransactionVal, group);
+ }
+
+ public void updateTransactionUserBalances(String transactionUserId, StringFloatMap transactionDetails, Float totalTransactionVal, Group group) {
+ StringFloatMap transactionUserBalances = usersBalancesMap.get(transactionUserId);
+ for(Map.Entry transaction : transactionDetails.entrySet()) {
+ addTransactionSummaryToUser(transactionUserId, transaction.getKey(), transaction.getValue(), totalTransactionVal, group);
+ if ( !(transactionUserId.equals(transaction.getKey())) ) {
+ updateTransactionSplitUserBalances(transactionUserId, transaction.getKey(), transaction.getValue());
+ Float updatedBalance = transaction.getValue() + transactionUserBalances.get(transaction.getKey());
+ transactionUserBalances.put(transaction.getKey(), updatedBalance);
+ }
+ }
+ }
+
+ public void updateTransactionSplitUserBalances(String transactionUserId, String splitUser, Float transAmt) {
+ StringFloatMap splitUserBalances = usersBalancesMap.get(splitUser);
+ splitUserBalances.put(transactionUserId, splitUserBalances.get(transactionUserId) - transAmt);
+ }
+
+ public void addTransactionSummaryToUser(String transactorUser, String transactionUser, Float transactionUserShare, Float totalTransactionVal, Group group) {
+ TransactionSummary transactionSummary = new TransactionSummary(transactorUser, totalTransactionVal, transactionUserShare);
+ group.getGroupUsers().getUserByUserId(transactionUser).getTransactions().add(transactionSummary);
+ }
+}
diff --git a/SplitWise/src/main/java/org/main/Currencies.java b/SplitWise/src/main/java/org/main/Currencies.java
new file mode 100644
index 00000000..87ad2dd7
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/Currencies.java
@@ -0,0 +1,19 @@
+package org.main;
+
+import lombok.Getter;
+
+
+@Getter
+public enum Currencies {
+ RUPEE("Rupee", "₹"),
+
+ DOLLAR("Dollar", "$");
+
+ private String currencyName;
+ private String currencySymbol;
+
+ Currencies(String currencyName, String currencySymbol) {
+ this.currencyName = currencyName;
+ this.currencySymbol = currencySymbol;
+ }
+}
diff --git a/SplitWise/src/main/java/org/main/Group.java b/SplitWise/src/main/java/org/main/Group.java
new file mode 100644
index 00000000..b3219ef9
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/Group.java
@@ -0,0 +1,18 @@
+package org.main;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class Group {
+ private String groupName;
+ private GroupUsers groupUsers;
+ private Balances balances;
+
+ public Group(String groupName, GroupUsers groupUsers, Balances balances) {
+ this.groupName = groupName;
+ this.groupUsers = groupUsers;
+ this.balances = balances;
+ }
+}
diff --git a/SplitWise/src/main/java/org/main/GroupUsers.java b/SplitWise/src/main/java/org/main/GroupUsers.java
new file mode 100644
index 00000000..ade9feab
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/GroupUsers.java
@@ -0,0 +1,35 @@
+package org.main;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.*;
+
+@Getter
+@Setter
+public class GroupUsers {
+ private HashMap users;
+
+ public GroupUsers() {
+ this.users = new HashMap<>();
+ }
+
+ public User getUserByUserId(String userId) {
+ return users.getOrDefault(userId, null);
+ }
+
+ public void addUserToGroup(User user) {
+ users.put(user.getUserId(), user);
+ }
+
+ public void addUsersToGroup(ArrayList userList) {
+ for (User user : userList) {
+ users.put(user.generateUserID(), user);
+ }
+ }
+
+ public boolean checkIfUserIsPartOfGroup(String transUser) {
+ return (getUserByUserId(transUser) != null);
+ }
+}
diff --git a/SplitWise/src/main/java/org/main/Main.java b/SplitWise/src/main/java/org/main/Main.java
new file mode 100644
index 00000000..8391136b
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/Main.java
@@ -0,0 +1,53 @@
+package org.main;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+public class Main {
+ public static void main(String[] args) throws IOException {
+ String line;
+ String[] input;
+ String filePath = "C:\\Users\\mahes\\Exercism\\java\\SplitWise\\src\\main\\resources\\transactions.txt";
+ Scanner scanner = new Scanner(Path.of(filePath));
+
+ ArrayList users = new ArrayList<>();
+ users.add(new User("M", "1212", "1@"));
+ users.add(new User("A", "2212", "2@"));
+ users.add(new User("H", "1254", "3@"));
+ users.add(new User("E", "5415", "4@"));
+ GroupUsers groupUsers = new GroupUsers();
+ groupUsers.addUsersToGroup(users);
+ Balances balances = new Balances(Currencies.RUPEE);
+ balances.initlizeUsersBalancesMap(groupUsers);
+ Group group = new Group("Trip1", groupUsers, balances);
+
+ while (scanner.hasNextLine()) {
+ line = scanner.nextLine();
+ line = line.strip();
+ input = line.split(" ");
+ ArrayList processLine = new ArrayList<>(List.of(input));
+ Transaction transaction = new Transaction();
+
+ if (processLine.get(0).equals("SHOW")) {
+ if (input.length != 1) {
+ group.getBalances().getBalanceForUserPrint(processLine.get(1).strip());
+ System.out.println("--- = ---");
+ } else {
+ group.getBalances().printGroupBalances();
+ System.out.println("--- = ---");
+ }
+ } else if (processLine.get(0).equals("EXPENSE")) {
+ processLine.remove(0);
+ transaction.processTransaction(processLine, group);
+ group.getGroupUsers().getUserByUserId(processLine.get(0)).printTransactions();
+ System.out.println("--- = ---");
+ }
+ }
+ group.getBalances().printBalancesMap();
+ group.getBalances().processSimplifiedBalances(groupUsers);
+ group.getBalances().printSimpliedBalances();
+ }
+}
\ No newline at end of file
diff --git a/SplitWise/src/main/java/org/main/Transaction.java b/SplitWise/src/main/java/org/main/Transaction.java
new file mode 100644
index 00000000..106478d8
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/Transaction.java
@@ -0,0 +1,79 @@
+package org.main;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+
+@Getter
+@Setter
+public class Transaction {
+ private String transactionUser;
+ private Float totalTransactionValue;
+ private StringFloatMap transactionMap;
+ private TransactionType transactionType;
+ private static final float EPSILON = 0.000001f;
+
+ public boolean processTransaction(ArrayList transactionDetails, Group group) {
+ transactionType = getTransType(transactionDetails);
+
+ if (validateTransactionDetails(transactionDetails, group)) {
+ group.getBalances().updateBalances(transactionUser, transactionMap, totalTransactionValue, group);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean validateTransactionDetails(ArrayList transactionDetails, Group group) {
+ if (!basicChecksPassed(transactionDetails, group)) {
+ return false;
+ }
+ if (transactionType != null) {
+ return transactionType.validateTransactionDetails(transactionDetails, this);
+ }
+ return false;
+ }
+
+ private boolean basicChecksPassed(ArrayList transactionDetails, Group group) {
+ transactionMap = new StringFloatMap();
+ transactionUser = transactionDetails.get(0);
+ if (!group.getGroupUsers().checkIfUserIsPartOfGroup(transactionUser)) {
+ return false;
+ }
+ totalTransactionValue = Float.parseFloat(transactionDetails.get(1));
+ if (totalTransactionValue < EPSILON) {
+ return false;
+ }
+ int numOfUsers = Integer.parseInt(transactionDetails.get(2));
+ if (numOfUsers < 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean checkFloatsAreEqual(Float num1, Float num2) {
+ return Math.abs(num1 - num2) < EPSILON;
+ }
+
+ public TransactionType getTransType(ArrayList transactionDetails) {
+ TransactionType transactionType = null;
+ for (String input : transactionDetails) {
+ if (input.equals("EQUAL")) {
+ transactionDetails.remove("EQUAL");
+ transactionType = TransactionType.fromString("EQUAL");
+ break;
+ }
+ if (input.equals("EXACT")) {
+ transactionDetails.remove("EXACT");
+ transactionType = TransactionType.fromString("EXACT");
+ break;
+ }
+ if (input.equals("PERCENT")) {
+ transactionDetails.remove("PERCENT");
+ transactionType = TransactionType.fromString("PERCENT");
+ break;
+ }
+ }
+ return transactionType;
+ }
+}
diff --git a/SplitWise/src/main/java/org/main/TransactionSummary.java b/SplitWise/src/main/java/org/main/TransactionSummary.java
new file mode 100644
index 00000000..1c13bd45
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/TransactionSummary.java
@@ -0,0 +1,17 @@
+package org.main;
+
+public class TransactionSummary {
+ private String transactorName;
+ private Float transactionTotalVal;
+ private Float userShare;
+
+ public TransactionSummary(String transactorName, Float transactionTotalVal, Float userShare) {
+ this.transactorName = transactorName;
+ this.transactionTotalVal = transactionTotalVal;
+ this.userShare = userShare;
+ }
+
+ public void printTransactionSummary() {
+ System.out.println("User " + transactorName + " added Expense of total Val "+ transactionTotalVal+" your share is "+ userShare);
+ }
+}
diff --git a/SplitWise/src/main/java/org/main/TransactionType.java b/SplitWise/src/main/java/org/main/TransactionType.java
new file mode 100644
index 00000000..bfa7a3e8
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/TransactionType.java
@@ -0,0 +1,65 @@
+package org.main;
+
+import lombok.Getter;
+
+import java.util.ArrayList;
+
+@Getter
+public enum TransactionType {
+ EXACT("EXACT") {
+ @Override
+ public boolean validateTransactionDetails(ArrayList transDetails, Transaction transaction) {
+ int numOfUsers = Integer.parseInt(transDetails.get(2));
+ for (int i = 1; i <= numOfUsers; i++) {
+ Float transVal = Float.parseFloat(transDetails.get(2 + i + numOfUsers));
+ transaction.getTransactionMap().put(transDetails.get(2 + i), transVal);
+ }
+ return checkIfTransactionsMatchesTotal(transaction);
+ }
+ },
+ EQUAL("EQUAL") {
+ @Override
+ public boolean validateTransactionDetails(ArrayList transDetails, Transaction transaction) {
+ int numOfUsers = Integer.parseInt(transDetails.get(2));
+ for (int i = 1; i <= numOfUsers; i++) {
+ transaction.getTransactionMap().put(transDetails.get(2+i), transaction.getTotalTransactionValue() / numOfUsers);
+ }
+ return true;
+ }
+ },
+ PERCENT("PERCENT") {
+ @Override
+ public boolean validateTransactionDetails(ArrayList transDetails, Transaction transaction) {
+ float totalTransPerc = 0f;
+ int numOfUsers = Integer.parseInt(transDetails.get(2));
+ for (int i = 1; i <= numOfUsers; i++) {
+ Float transPer = Float.parseFloat(transDetails.get(2+i+numOfUsers));
+ totalTransPerc += transPer;
+ transaction.getTransactionMap().put(transDetails.get(2+i), transaction.getTotalTransactionValue() * (transPer / 100));
+ }
+ return transaction.checkFloatsAreEqual(totalTransPerc, 100f);
+ }
+ };
+
+ private final String transactionName;
+
+ TransactionType(String transactionName) {
+ this.transactionName = transactionName;
+ }
+
+ public abstract boolean validateTransactionDetails(ArrayList trans, Transaction transaction);
+
+ protected boolean checkIfTransactionsMatchesTotal(Transaction transaction) {
+ float sum = transaction.getTransactionMap().values().stream().reduce(0f, Float::sum);
+ return transaction.checkFloatsAreEqual(sum, transaction.getTotalTransactionValue());
+ }
+
+ public static TransactionType fromString(String name) {
+ for (TransactionType transactionType : TransactionType.values()) {
+ if (transactionType.transactionName.equalsIgnoreCase(name)) {
+ return transactionType;
+ }
+ }
+ throw new IllegalArgumentException("No constant named "+name);
+ }
+}
\ No newline at end of file
diff --git a/SplitWise/src/main/java/org/main/User.java b/SplitWise/src/main/java/org/main/User.java
new file mode 100644
index 00000000..d984901b
--- /dev/null
+++ b/SplitWise/src/main/java/org/main/User.java
@@ -0,0 +1,42 @@
+package org.main;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+@Getter
+@Setter
+public class User {
+ private String name;
+ @Setter(AccessLevel.NONE)
+ private String userId;
+ private String phoneNum;
+ private String emailId;
+ private ArrayList transactions;
+
+ public User(String name, String phoneNum, String emailId) {
+ this.name = name;
+ this.phoneNum = phoneNum;
+ this.emailId = emailId;
+ this.userId = generateUserID();
+ transactions = new ArrayList<>();
+ }
+
+ public String generateUserID() {
+ return name+Integer.valueOf(phoneNum.trim());
+ }
+
+ private long getRandom() {
+ Random r = new Random();
+ return r.nextLong(100-000-000-00) + Integer.valueOf(phoneNum.trim());
+ }
+
+ public void printTransactions() {
+ for (TransactionSummary transactionSummary : transactions) {
+ transactionSummary.printTransactionSummary();
+ }
+ }
+}
diff --git a/SplitWise/src/main/resources/transactions.txt b/SplitWise/src/main/resources/transactions.txt
new file mode 100644
index 00000000..e37bea65
--- /dev/null
+++ b/SplitWise/src/main/resources/transactions.txt
@@ -0,0 +1,10 @@
+SHOW
+SHOW M1212
+EXPENSE M1212 1000 4 M1212 A2212 H1254 E5415 EQUAL
+SHOW E5415
+SHOW M1212
+EXPENSE M1212 1250 3 A2212 H1254 E5415 EXACT 200 880 170
+SHOW
+EXPENSE E5415 1200 4 M1212 A2212 H1254 E5415 PERCENT 40 20 20 20
+SHOW M1212
+SHOW
\ No newline at end of file
diff --git a/SplitWise/src/test/java/org/main/BalancesTest.java b/SplitWise/src/test/java/org/main/BalancesTest.java
new file mode 100644
index 00000000..dee70128
--- /dev/null
+++ b/SplitWise/src/test/java/org/main/BalancesTest.java
@@ -0,0 +1,35 @@
+package org.main;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+
+class BalancesTest {
+
+ @Test
+ void initlizeUsersBalancesMap() {
+ ArrayList users = new ArrayList<>();
+ users.add(new User("M", "1212", "1@"));
+ users.add(new User("A", "2212", "2@"));
+ users.add(new User("H", "1254", "3@"));
+ users.add(new User("E", "5415", "4@"));
+ GroupUsers groupUsers = new GroupUsers();
+ groupUsers.addUsersToGroup(users);
+ Balances balances = new Balances(Currencies.RUPEE);
+ balances.initlizeUsersBalancesMap(groupUsers);
+ Group group = new Group("Test", groupUsers, balances);
+
+ StringFloatMap trans1 = new StringFloatMap();
+ trans1.put("A2212", 200f);
+ trans1.put("H1254", 200f);
+ trans1.put("E5415", 200f);
+ balances.printGroupBalances();
+// balances.updateBalances("M1212", trans1, 1000f);
+ balances.printBalancesMap();
+ System.out.println("A2212 and M1212");
+ balances.getBalanceForUserPrint("M1212", "A2212");
+ System.out.println("M1212");
+ balances.getBalanceForUserPrint("M1212");
+ balances.printGroupBalances();
+ }
+}
\ No newline at end of file
diff --git a/SplitWise/src/test/java/org/main/TransactionTypeTest.java b/SplitWise/src/test/java/org/main/TransactionTypeTest.java
new file mode 100644
index 00000000..1abee13b
--- /dev/null
+++ b/SplitWise/src/test/java/org/main/TransactionTypeTest.java
@@ -0,0 +1,41 @@
+package org.main;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+
+class TransactionTypeTest {
+
+ @Test
+ void processTransaction() {
+ ArrayList users = new ArrayList<>();
+ users.add(new User("M", "1212", "1@"));
+ users.add(new User("A", "2212", "2@"));
+ users.add(new User("H", "1254", "3@"));
+ users.add(new User("E", "5415", "4@"));
+ GroupUsers groupUsers = new GroupUsers();
+ groupUsers.addUsersToGroup(users);
+ Balances balances = new Balances(Currencies.RUPEE);
+ balances.initlizeUsersBalancesMap(groupUsers);
+ Group group = new Group("Test", groupUsers, balances);
+
+ StringFloatMap trans1 = new StringFloatMap();
+ trans1.put("M1212", 200f);
+ trans1.put("A2212", 20f);
+ trans1.put("H1254", 200f);
+ trans1.put("E5415", 200f);
+
+// System.out.println(TransactionType.EXACT.processTransaction("M1212 1000 4 M1212 A2212 H1254 E5415 250 350 250 150", group));
+// group.getBalances().printGroupBalances();
+// System.out.println(TransactionType.EQUAL.processTransaction("M1212 1000 3 M1212 A2212 H1254", group));
+// group.getBalances().printGroupBalances();
+// System.out.println(TransactionType.PERCENT.processTransaction("M1212 1000 3 M1212 A2212 H1254 40 20 40", group));
+// group.getBalances().printGroupBalances();
+ System.out.println("-- -- - -");
+ group.getBalances().getBalanceForUserPrint("M1212");
+ System.out.println("-- -- - -");
+ group.getBalances().getBalanceForUserPrint("A2212", "M1212");
+ System.out.println("-- -- - -");
+ group.getBalances().getBalanceForUserPrint("M1212", "A2212");
+ }
+}
\ No newline at end of file
diff --git a/SplitWise/src/test/java/org/main/UserTest.java b/SplitWise/src/test/java/org/main/UserTest.java
new file mode 100644
index 00000000..ec14a933
--- /dev/null
+++ b/SplitWise/src/test/java/org/main/UserTest.java
@@ -0,0 +1,14 @@
+package org.main;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class UserTest {
+
+ @Test
+ void generateUserID() {
+ User user = spy(new User("Mahesh", "334156413", "mahesh@bidgely.com"));
+ System.out.println(user.generateUserID());
+ }
+}
\ No newline at end of file
diff --git a/SplitWise/target/classes/transactions.txt b/SplitWise/target/classes/transactions.txt
new file mode 100644
index 00000000..e37bea65
--- /dev/null
+++ b/SplitWise/target/classes/transactions.txt
@@ -0,0 +1,10 @@
+SHOW
+SHOW M1212
+EXPENSE M1212 1000 4 M1212 A2212 H1254 E5415 EQUAL
+SHOW E5415
+SHOW M1212
+EXPENSE M1212 1250 3 A2212 H1254 E5415 EXACT 200 880 170
+SHOW
+EXPENSE E5415 1200 4 M1212 A2212 H1254 E5415 PERCENT 40 20 20 20
+SHOW M1212
+SHOW
\ No newline at end of file