University Introduction to Programming Project

Short Overview of the project

The thought process for this project was to build a simple points calculator for the tabletop game Warhammer 40k. This concept was taken and compared to the guidelines provided by my university, to see if the potential features I could add would fulfill the brief. Fortunately they did so I got to planning. I produced this flow chart so I could map out my ideas and the program structure.

Once the planning was complete I started to code my project. This was broken up into 4 main sprints;

  • reading data from the predefined csv file.
  • user selection of units and input storage.
  • report generation for the users reference at a later date.
  • testing of all main data processing methods.

Sprint 1 (CSV Reading)

The first sprint consisted of creating a csv with all the data of each unit in the ork army (id, unit name, unit points, amount of models in unit). 

				
					id,unitName,unitPoints,modelsInUnit
1,battlewagon,185,1
2,beastsnaggaboyz,105,10
3,beastboss,80,1
4,beastbossonsquigosaur,165,1
5,bigmekinmegaarmour,100,1
6,bigmekwithshokkattackgun,75,1
7,bigmekwithkustomforcefield,65,1
8,bigedbossbunka,135,1
9,blitza-bommer,115,1
10,boomdakkasnazzwagon,90,1
				
			

Once all the testing data was compiled, I created a method that would locate the chosen army file and read each line as a string and store the data as a variable. I decided during the project to separate all of my main program requirements into separate methods. This decision was made for two reasons: the first was to make the code more readable and easier to debug, the second was for re-usability, as I will need to use these methods several times throughout the project.

				
					package lib;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class csvRead {
    /**
 * @param searchColumnIndex
 * @param searchString
 * @return
 * @throws IOException 
 * 
 */

 // will search csv file
    public static String searchCsvLine(int searchColumnIndex, String searchString, String pathSelection) throws IOException {
        BufferedReader csvReader = new BufferedReader(new FileReader("src\\main\\java\\data\\"+pathSelection+"ArmyPoints.csv"));
        String resultRow = "";
        String line;
        while ( (line = csvReader.readLine()) != null ) {
            String[] values = line.split(",");
            if(values[searchColumnIndex].equals(searchString)) {
                resultRow = line;
                break;
            }
        }
        csvReader.close();
        return resultRow;
    }
}

				
			

Sprint 2 (Unit Selection & Selection Storage)

During the second sprint, I added two main features; the functionality to select a unit in the army from the csv and the ability for that data to be stored.

First, was functionality that allows the user to select a unit they would like to be added to their army. I did this by collecting a user input then searching the csv file for the rest of the row and saving that row as a string variable.

The second feature I added was the storage of the user selection. I did this by merging the amount of units selected and the unit data into an array list as it allowed me to store the data in the same format that I was already using, without having to do some of the complex data handling that would be needed with a 3d array.

				
					package lib;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class armyUnitSelectionSave {
    public static ArrayList<String> armyUnitSelectionSave(Scanner mainInput, int pointsTarget, String armyPath) throws Exception{
        int amountOfUnits;
        int usedTotal = 0;

        // creates main output array for the result of the user selection
        ArrayList<String> fullStringLog = new ArrayList<String>();
        while (usedTotal<=pointsTarget) { 
            System.out.println("Please enter the unit you wish to add:");
            String UnitFinder = mainInput.nextLine().toLowerCase();
            String result = csvRead.searchCsvLine(1, UnitFinder, armyPath);
            String[] resultArray = csvResponceAray.responceArray(result);
            System.out.println("Please enter the amount of this unit you would like in your army");
            amountOfUnits = mainInput.nextInt();
            mainInput.nextLine();
            int pointTotalForSelectedUnit = amountOfUnits * Integer.parseInt(resultArray[2]);
            System.out.println("you have selected "+amountOfUnits +" x "+ resultArray[1]+ " which is worth " + pointTotalForSelectedUnit +" points");
            String output = result + "," + String.valueOf(amountOfUnits);
            fullStringLog.add(output);
            usedTotal = usedTotal + pointTotalForSelectedUnit;
            System.out.println("you have used "+usedTotal+" points ");

            // error handling for if the user puts the wrong input when deciding when to continue
            if (usedTotal<=pointsTarget){
                System.out.println("would you like to continue your selection? [y/n]");
                String endConformation = mainInput.nextLine();
                while(!endConformation.equals("y") && !endConformation.equals("n")){
                    System.out.println("You must enter 'y' or 'n'");
                    endConformation = mainInput.nextLine();
                }
                if (endConformation.equals("n")){
                    break;
                }
            }
        }
                return (fullStringLog);
                
    }
}

				
			

Sprint 3 (Report Generation)

During my third sprint I added the ability for the user to create a report with a full breakdown of what units they selected, how many units there are and total points. To add this feature I used the FileWriter module to create a text file and write a dynamic report that allows the user to keep a record and full breakdown of their army for later use.

To create this feature I used W3 Schools to see the basic processes to create and write to a file, then I used the knowledge I already had to fully flush out the feature.

				
					package lib;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


public class dataOutputToFiles {
    //output to file in /data/outputFiles
    public static void dataOutputToFiles (ArrayList<String> fullStringLog, Scanner mainInput ){

        int usedTotal = 0;

        //gets user input and creates file object
        System.out.println("please enter the name you wih your file to be.");
        String fileName = mainInput.nextLine();
        File userFilePath = new File ("src\\main\\java\\data\\userFiles\\"+fileName+".txt");

        try {
            FileWriter myWriter = new FileWriter(userFilePath);
            myWriter.write(fileName);
            myWriter.write("\n");
            myWriter.write("id | squad name | points per squad | amount of units per squad | amount of total squads | total amount of points for squad");
            myWriter.write("\n");
            for (int i = 0; i<fullStringLog.size(); i++) {
                System.out.println(fullStringLog.get(i));
                String[] resultArray = csvResponceAray.responceArray(fullStringLog.get(i)); 
                int totalPointsForSquad =  (Integer.parseInt(resultArray[4])*Integer.parseInt(resultArray[2]));
                usedTotal = totalPointsForSquad + usedTotal;
                myWriter.write("--------------------------------------------------------");
                myWriter.write("\n");
                myWriter.write(resultArray[0]+" | "+resultArray[1]+" | "+ resultArray[2]+" | "+resultArray[3]+" | "+resultArray[4]+" | "+ (Integer.parseInt(resultArray[4])*Integer.parseInt(resultArray[2])));
                myWriter.write("\n");
            }
            myWriter.write("--------------------------------------------------------");
            myWriter.write("\n");
            myWriter.write("This army is "+usedTotal+" points.");

            myWriter.close();
            System.out.println("Successfully wrote to the file.");;
        } 
        catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }

    }

}
				
			
				
					Test
id | squad name | points per squad | amount of units per squad | amount of total squads | total amount of points for squad
--------------------------------------------------------
51 | warboss | 70 | 1 | 1 | 70
--------------------------------------------------------
47 | stormboyz | 65 | 5 | 4 | 260
--------------------------------------------------------
54 | weirdboy | 55 | 1 | 5 | 275
--------------------------------------------------------
This army is 605 points.
				
			

Sprint 4 (Testing)

During my fourth sprint I used the testing framework JUnit to write several unit tests that test the data output of all the major data processing methods that I have written. This includes the reading of the csv, the splitting of each row into a array, and the selection of the path for each army.

To add this to my project I had to learn two main packages that can be added to java; JUnit itself, and Maven.

				
					package com.digitalartifact;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import org.junit.jupiter.api.Test;

import lib.csvResponceAray;
 
/**
 *
 * @author Stefan
 */
public class CSVResponceArrayTest {
    @Test
    public void CSVResponceArrayTest() {
        String result[] = csvResponceAray.responceArray("8,bigedbossbunka,135,1");
        String expected[] = {"8","bigedbossbunka","135","1"};
        assertArrayEquals(expected, result);
    }
}
				
			

Main Features of Java I Used

There were three main features of Java that i used during my project:

  • Method – During my project I used methods to create repeatable processes that are used multiple times in my program, like the use of a Split method to create an array out of the csv string that is used throughout my program for data storage.
				
					package lib;

public class csvResponceAray{

    public static String[] responceArray(String result){

        //spliting the csv into an array
        String[] fields = result.split(",");
        return fields;
    }

}
				
			
  • Array – Arrays make up the majority of the data handling in my project as they provide a good way to cycle through many data points. An example of where I used an array was when I needed to separate my unit data into a string so I can display it when the user selects what units are in the army.
				
					String[] resultArray = csvResponceAray.responceArray(result);
				
			
  • Testing – Testing is used in my program to make sure that all the code in my artefact works as expected. For the testing I used JUnit, a  java package that specialized in testing, and integrates with VSCode to provide a GUI for monitoring unit testing results. I chose JUnit as it is an industry standard and widely used framework for testing, which allowed me to find loads of helpful resources for learning the syntax and structure of a JUnit test. The main function of JUnit I used was the assert equals function that checks if two inputs are equal, then passes the test if they are.
				
					
package com.digitalartifact;

import java.io.IOException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

import lib.csvRead;
 
/**
 *
 * @author Stefan
 */
public class CSVReadTest {
    @Test
    public void  CSVReadTest() throws IOException {
        String result = csvRead.searchCsvLine(1,"bigedbossbunka", "ork");
        assertEquals("8,bigedbossbunka,135,1", result);
    }

}
				
			

Issues encountered

During this project I encounters 3 main issues :

The first and biggest issue was creating an array to store the amount of units selected and all the unit data. Originally I was going to use a 3d array that would store the data in two with the amount of units in one array and unit data in another ({{amount of units},{Unit Data}}) but after realizing that the data handling of two different data types in the array would be difficult,I re-evaluated how I could create a reliable data structure. Instead I created a large string array that has the amount of units selected added to the end.

The one downside to creating the array like this is that I need to use the parseInt() method to do any calculations, as all numbers stored in the array had to be a string as I was storing the unit names along side them.

				
					Integer.parseInt(resultArray[2])
				
			

The Second issue I encountered was the addition of JUnit after I had started the project, as I didn’t include maven on the original project setup. This meant I had to create a new maven based project and transfer all my written code to the new project in the correct format. This meant I had to learn, in depth, how maven structures its files and how to properly organize the project. On top of this I had to learn how to write a pom file in the correct way for maven to build the project effectively with all the packages I needed. This added a significant amount of time to the project, as I needed to learn the fundamentals of JUnit and Maven.

The final issue I encountered was adding an object with inheritance to my project, as not only is it a feature that I don’t have much experience working with, it was also tough to identify a proper use for one in my project that meets the brief requirements.  That is why I added a prompt for the user to enter their name and email. For this object I also had to include inheritance, so I implemented a “userData” object that retains the users first and second names then I extended the “userData” object into a “fullUserData” object which also includes the users email.

				
					package com.digitalartifact.lib;

public class userData{

    private String firstName;
    private String secondName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String newFirstName) {
        this.firstName = newFirstName;
    }

    public String getSecondName() {
        return secondName;
    }

    public void setSecondName(String newSecondName) {
        this.secondName = newSecondName;
    }

}


				
			
				
					package com.digitalartifact.lib;

public class fullUserData extends userData {
    private String Email;

    public String getEmail(){
        return Email;
    }

    public void setUserEmail(String Email) {
        this.Email = Email;
    }

}

				
			

Potential Features

During the time I spent coding this project I would of liked to add; better error handling on user inputs when selecting what unit they would like to add to their army and additional armies (e.g. Adeptus Castodies, Tau). If I were to add additional armies all I would need to do is to create a new csv file with all the data for that army.

Another additional feature I would of liked to add is the ability for the report file to be emailed to the user. To do this I would of added the Jakarta Mail dependency which would allow me to use a mail api to send emails programmatically.

Conclusions

Overall I think the project met all the criteria for a proof of concept and provided several great learning opportunities;  including learning java in much more depth than previously, learning about unit testing and how to write one, and learning how to use maven and its core concepts.

Bibliography:

Bechtold, S., Brannen, S., Link, J., Merdes, M., Philipp, M., de Rancourt, J. and Stein, C. (n.d.). JUnit 5 User Guide. [online] junit.org. Available at: https://junit.org/junit5/docs/current/user-guide/.

code.visualstudio.com. (n.d.). Java Unit Tests in Visual Studio Code. [online] Available at: https://code.visualstudio.com/docs/java/java-testing.

maven.apache.org. (n.d.). Maven – Welcome to Apache Maven. [online] Available at: https://maven.apache.org/.

W3Schools (2019). Java ArrayList. [online] W3schools.com. Available at: https://www.w3schools.com/java/java_arraylist.asp.

W3Schools (2020). Java Create and Write To Files. [online] W3schools.com. Available at: https://www.w3schools.com/java/java_files_create.asp.

www.w3schools.com. (n.d.). Java Files. [online] Available at: https://www.w3schools.com/java/java_files.asp.

sp.