diff --git a/README.md b/README.md
index e6418ce..d3fdd3e 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
-### This repo contains my solutions to the end-of-chapter exercise’s from Y. Daniel Liang’s Intro to Java Programming (10th Edition)
+### This repo contains my solutions to the end-of-chapter exercise’s from Y. Daniel Liang’s Intro to Java Programming (10th Edition)
-### I've included links below to all the freely accessible compainion material and quick links to navigate through my solutions by chapter.
+### I've included links below to all the freely accessible companion material and quick links to navigate through my solutions by chapter.
### If you would like to contribute, please see: Ways to Contribute
@@ -63,7 +63,7 @@ ____
____
-
Exercise Solutions:
+Exercise Solutions:
Quick Links to navigate these solutions by chapter
diff --git a/ch_18/exercise18_31/Exercise18_31.class b/ch_18/exercise18_31/Exercise18_31.class
new file mode 100644
index 0000000..e04c1b2
Binary files /dev/null and b/ch_18/exercise18_31/Exercise18_31.class differ
diff --git a/ch_31/Exercise31_02.java b/ch_31/Exercise31_02.java
deleted file mode 100644
index cff8475..0000000
--- a/ch_31/Exercise31_02.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package ch_31;
-
-import javafx.application.Application;
-import javafx.geometry.Pos;
-import javafx.scene.Scene;
-import javafx.scene.layout.GridPane;
-import javafx.stage.Stage;
-import javafx.scene.image.ImageView;
-import javafx.scene.image.Image;
-
-import java.io.File;
-
-/**
- * *31.2 (BMI server) Write a server for a client. The client sends the weight and
- * height for a person to the server (see Figure 31.18a). The server computes
- * BMI (Body Mass Index) and sends back to the client a string that reports the
- * BMI (see Figure 31.18b). See Section 3.8 for computing BMI. Name the client
- * Exercise31_02Client and the server Exercise31_02Server.
- */
-public class Exercise31_02 extends Application {
- private final String SLASH = File.separator;
-
- @Override
- public void start(Stage primaryStage) {
- String imagePath1 = "resources" + SLASH + "image" + SLASH + "x.gif";
- String imagePath2 = "resources" + SLASH + "image" + SLASH + "o.gif";
- Image imageX = new Image(imagePath1);
- Image imageO = new Image(imagePath2);
-
- GridPane pane = new GridPane();
- pane.getStylesheets().add("mystyle.css");
- pane.getStyleClass().add("border");
-
- pane.setAlignment(Pos.CENTER);
- pane.setHgap(5);
- pane.setVgap(5);
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- if ((int) (Math.random() * 3) == 0) {
- ImageView imageView1 = new ImageView(imageX);
- imageView1.getStyleClass().add("border");
- pane.add(imageView1, j, i);
- } else if ((int) (Math.random() * 3) == 1) {
- ImageView imageView2 = new ImageView(imageO);
- imageView2.getStyleClass().add("border");
- pane.add(imageView2, j, i);
- }
- }
- }
-
- Scene scene = new Scene(pane);
- primaryStage.setTitle(getClass().getName());
- primaryStage.setScene(scene);
- primaryStage.show();
- }
-
-}
diff --git a/ch_31/exercise31_02/BmiDto.java b/ch_31/exercise31_02/BmiDto.java
new file mode 100644
index 0000000..3a799ed
--- /dev/null
+++ b/ch_31/exercise31_02/BmiDto.java
@@ -0,0 +1,28 @@
+package ch_31.exercise31_02;
+
+/**
+ * Data Transfer Object for BMI data
+ *
+ * This class is used to transfer data from the client to the server.
+ * For Exercise31_02, the client sends the weight and height for a person to the server.
+ */
+public class BmiDto {
+ private double weight;
+ private double height;
+
+ public BmiDto() {
+ }
+
+ public BmiDto(double weight, double height) {
+ this.weight = weight;
+ this.height = height;
+ }
+
+ public double getWeight() {
+ return weight;
+ }
+
+ public double getHeight() {
+ return height;
+ }
+}
diff --git a/ch_31/exercise31_02/Exercise31_02.java b/ch_31/exercise31_02/Exercise31_02.java
new file mode 100644
index 0000000..964cdf9
--- /dev/null
+++ b/ch_31/exercise31_02/Exercise31_02.java
@@ -0,0 +1,21 @@
+package ch_31.exercise31_02;
+
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.stage.Stage;
+
+/**
+ * *31.2 (BMI server) Write a server for a client. The client sends the weight and
+ * height for a person to the server (see Figure 31.18a). The server computes
+ * BMI (Body Mass Index) and sends back to the client a string that reports the
+ * BMI (see Figure 31.18b). See Section 3.8 for computing BMI. Name the client
+ * Exercise31_02Client and the server Exercise31_02Server.
+ */
+public class Exercise31_02 extends Application {
+ @Override
+ public void start(Stage primaryStage) throws Exception {
+ System.out.println("##-_-_--_--_--__-_-- Starting: Exercise31_02 --_-__--__--__--_--_--##");
+ Platform.runLater(() -> new Exercise31_02Server().start(new Stage()));
+ Platform.runLater(() -> new Exercise31_02Client().start(new Stage()));
+ }
+}
diff --git a/ch_31/exercise31_02/Exercise31_02Client.java b/ch_31/exercise31_02/Exercise31_02Client.java
new file mode 100644
index 0000000..a0b44a1
--- /dev/null
+++ b/ch_31/exercise31_02/Exercise31_02Client.java
@@ -0,0 +1,106 @@
+package ch_31.exercise31_02;
+
+import javafx.application.Application;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.geometry.HPos;
+import javafx.geometry.Pos;
+import javafx.geometry.VPos;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.GridPane;
+import javafx.stage.Stage;
+
+import java.io.*;
+import java.net.Socket;
+
+public class Exercise31_02Client extends Application {
+ private TextField weightTextInput = new TextField();
+ private TextField heightTextInput = new TextField();
+ private TextArea displayResultTextArea = new TextArea();
+
+ private Button submitButton = new Button("Submit");
+
+ // Host name or ip
+ String host = "localhost";
+
+ private ObjectOutputStream toServer;
+ private DataInputStream fromServer;
+
+ public Exercise31_02Client() {
+ System.out.println("##-_-_--_--_--__-_-- Starting: Exercise31_02Client --_-__--__--__--_--_--##");
+ }
+
+ @Override
+ public void start(Stage primaryStage) {
+ Stage stage = new Stage();
+ GridPane pane = new GridPane();
+ pane.add(new Label("Weight in pounds"), 0, 0);
+ pane.add(weightTextInput, 1, 0);
+ pane.add(new Label("Height in inches"), 0, 1);
+ pane.add(heightTextInput, 1, 1);
+ pane.add(submitButton, 1, 3);
+ pane.add(displayResultTextArea, 1, 4);
+ GridPane.setHalignment(submitButton, HPos.RIGHT);
+ GridPane.setValignment(displayResultTextArea, VPos.BOTTOM);
+ pane.setAlignment(Pos.CENTER);
+ weightTextInput.setPrefColumnCount(15);
+ heightTextInput.setPrefColumnCount(15);
+ submitButton.setOnAction(new ButtonListener());
+
+ Scene scene = new Scene(pane, 450, 200);
+ stage.setTitle("BMI Client");
+ stage.setScene(scene);
+ stage.show();
+
+ try (Socket socket = new Socket(host, 8000)) {
+ // Create an output stream to the server
+ toServer = new ObjectOutputStream(socket.getOutputStream());
+ // Create an input stream from the server
+ fromServer = new DataInputStream(socket.getInputStream());
+ } catch (IOException ex) {
+ System.out.println("##----------- Client Error: IOException: " + ex.getMessage() + " -----------##");
+ }
+ }
+
+ /**
+ * Custom event handler for the submit button
+ */
+ private class ButtonListener implements EventHandler {
+ @Override
+ public void handle(ActionEvent e) {
+ try {
+ // Get weight and height from the text fields
+ double weight = Double.parseDouble(weightTextInput.getText().trim());
+ double height = Double.parseDouble(heightTextInput.getText().trim());
+ // Create a BmiDto and send to the server
+ BmiDto s = new BmiDto(weight, height);
+ toServer.writeObject(s);
+ toServer.flush();
+ // Get resulting BMI from the server
+ double bmi = fromServer.readDouble();
+ // Display to the text area
+ displayResultTextArea.setText("Weight: " + weight + "\nHeight: " + height + "\nBMI is: " + bmi
+ + "\n" + getCategory(bmi));
+ } catch (IOException ex) {
+ System.out.println("##----------- Client Error: IOException: " + ex.getMessage() + " -----------##");
+ }
+ }
+ }
+
+ private String getCategory(double bmi) {
+ if (bmi < 18.5) {
+ return "Underweight";
+ } else if (bmi < 25) {
+ return "Normal";
+ } else if (bmi < 30) {
+ return "Overweight";
+ } else {
+ return "Obese";
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/ch_31/exercise31_02/Exercise31_02Server.java b/ch_31/exercise31_02/Exercise31_02Server.java
new file mode 100644
index 0000000..6cf501c
--- /dev/null
+++ b/ch_31/exercise31_02/Exercise31_02Server.java
@@ -0,0 +1,84 @@
+package ch_31.exercise31_02;
+
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.scene.Scene;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.TextArea;
+import javafx.stage.Stage;
+
+import java.io.*;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Date;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class Exercise31_02Server extends Application {
+ private static final double KILOGRAMS_PER_POUND = 0.45359237;
+ private static final double METERS_PER_INCH = 0.0254;
+
+ private AtomicBoolean isRunning = new AtomicBoolean(true);
+
+ public Exercise31_02Server() {
+ System.out.println("##-_-_--_--_--__-_-- Starting: Exercise31_02Server --_-__--__--__--_--_--##");
+ }
+
+
+ @Override
+ public void start(Stage primaryStage) {
+ TextArea displayLogTextArea = new TextArea();
+ Scene scene = new Scene(new ScrollPane(displayLogTextArea), 450, 200);
+ primaryStage.setTitle("TicTacToeServer");
+ primaryStage.setScene(scene);
+ primaryStage.show();
+ new Thread(() -> runServer(displayLogTextArea)).start();
+ }
+
+ private void runServer(TextArea displayLogTextArea) {
+ /* Create a server socket. Use try with resources to close the socket automatically */
+ try (ServerSocket serverSocket = new ServerSocket(8000)) {
+ // Listen for a connection request
+ Socket socket = socket = serverSocket.accept();
+ // Create data input and output streams
+ try (ObjectInputStream inputFromClient = new ObjectInputStream(
+ socket.getInputStream())) {
+ try (DataOutputStream outputToClient = new DataOutputStream(
+ socket.getOutputStream())) {
+
+ Platform.runLater(() -> displayLogTextArea.appendText(new Date() +
+ ": Server started at socket 8000\n"));
+ while (true) {
+ if (!isRunning.get()) {
+ break;
+ }
+ if (inputFromClient.available() > 0) {
+ // Receive Object from the client
+ Object object = inputFromClient.readObject();
+ if (Objects.nonNull(object) && object instanceof BmiDto) {
+ BmiDto bmiDto = (BmiDto) object;
+ double weight = bmiDto.getWeight();
+ double height = bmiDto.getHeight();
+ double bmi = calculateBmi(weight, height);
+ // Send area back to the client
+ outputToClient.writeDouble(bmi);
+ }
+ }
+
+ }
+ }
+ }
+
+ } catch (ClassNotFoundException | IOException ex) {
+ System.out.println("##----------- Server Error: Exception: " + ex.getMessage() + " -----------##");
+ }
+ }
+
+ private double calculateBmi(double weight, double height) {
+ double weightInKilograms = weight * KILOGRAMS_PER_POUND;
+ double heightInMeters = height * METERS_PER_INCH;
+ return weightInKilograms /
+ (heightInMeters * heightInMeters);
+ }
+
+}