forked from hummel/PR1-Spreadsheet
Added Ui Loop, Error check for user input and test for the above
parent
505f428029
commit
6d8f8e7520
|
@ -1,29 +1,211 @@
|
||||||
package de.hs_mannheim.informatik.spreadsheet;
|
package de.hs_mannheim.informatik.spreadsheet;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Part of a simplified spreadsheet system for the PR1 programming lab at Hochschule Mannheim.
|
* Part of a simplified spreadsheet system for the PR1 programming lab at Hochschule Mannheim.
|
||||||
*
|
*
|
||||||
* @author Oliver Hummel
|
* @author Oliver Hummel & Victor Waitz
|
||||||
*/
|
*/
|
||||||
public class Axel {
|
public class Axel {
|
||||||
|
static Scanner keyboard = new Scanner(System.in);
|
||||||
|
static Spreadsheet spr = new Spreadsheet(6,8);
|
||||||
|
|
||||||
public static void main(String[] args) throws FileNotFoundException {
|
public static void main(String[] args) throws FileNotFoundException {
|
||||||
Spreadsheet spr = new Spreadsheet(10,10);
|
// Spreadsheet spr = new Spreadsheet(6,9);
|
||||||
|
|
||||||
|
|
||||||
spr.put("A3", "123");
|
spr.put("A3", "123");
|
||||||
spr.put("A2", "1");
|
spr.put("A2", "1");
|
||||||
|
|
||||||
spr.put("B9", "=41+A2");
|
spr.put("B4", "=41+A2");
|
||||||
spr.put("J5", "=7*6");
|
spr.put("C5", "=7*6");
|
||||||
spr.put("J6", "=3/2");
|
spr.put("D1", "=3/2");
|
||||||
|
|
||||||
System.out.println(spr);
|
System.out.println(spr);
|
||||||
|
|
||||||
spr.saveCsv("/tmp/test.csv");
|
// spr.saveCsv("/tmp/test.csv");
|
||||||
|
|
||||||
// TODO: You might want to put "UI loop" for entering value and formulas here resp. in some UI methods.
|
// DONE: You might want to put "UI loop" for entering value and formulas here resp. in some UI methods.
|
||||||
|
// TODO ME: Implement program commands
|
||||||
|
System.out.println("Welcome to Axel (Totally not Excel)");
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
String userCommandPositionInput = userCommandPositionInput();
|
||||||
|
if (userCommandPositionInput.charAt(0) == '*'){
|
||||||
|
executeCommand(userCommandPositionInput);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String userPositionInput = userCommandPositionInput;
|
||||||
|
|
||||||
|
String userValueFormulaInput = userValueFormulaInput();
|
||||||
|
|
||||||
|
spr.put(userPositionInput, userValueFormulaInput);
|
||||||
|
|
||||||
|
System.out.println(spr);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//? User input for a program command or a position
|
||||||
|
public static String userCommandPositionInput(){
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Input a command for the program or a position");
|
||||||
|
System.out.printf("List of program commands: *exit, *save, *load or *help %nFormat for position: A1 or B14%n");
|
||||||
|
System.out.print("Input: ");
|
||||||
|
String userCommandPositionInput = keyboard.nextLine();
|
||||||
|
|
||||||
|
return userCommandPositionComputation(userCommandPositionInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String userCommandPositionComputation(String userCommandPositionInput){
|
||||||
|
|
||||||
|
if (userCommandPositionInput.isEmpty()){
|
||||||
|
System.out.println("Input is empty!");
|
||||||
|
return userCommandPositionInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Program command
|
||||||
|
if (userCommandPositionInput.charAt(0) == '*'){
|
||||||
|
if (!(userCommandErrorCheck(userCommandPositionInput))) {
|
||||||
|
System.out.println("Invalid command!");
|
||||||
|
return userCommandPositionInput();
|
||||||
|
}
|
||||||
|
return userCommandPositionInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Position
|
||||||
|
if (!(userPositionErrorCheck(userCommandPositionInput))){
|
||||||
|
System.out.println("Invalid position!");
|
||||||
|
return userCommandPositionInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(userPositionBoundsErrorCheck(userCommandPositionInput, spr))){
|
||||||
|
System.out.println("Position out of bounds!");
|
||||||
|
return userCommandPositionInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
return userCommandPositionInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean userCommandErrorCheck(String CommandToCheck){
|
||||||
|
//? true if valid
|
||||||
|
//? valid inputs are: *exit, *save, *load, *help (and all upper case variants)
|
||||||
|
|
||||||
|
CommandToCheck = CommandToCheck.toLowerCase();
|
||||||
|
if (CommandToCheck.equals("*exit") || CommandToCheck.equals("*save") || CommandToCheck.equals("*load") || CommandToCheck.equals("*help")){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean userPositionErrorCheck(String positionToCheck){
|
||||||
|
//? true if valid
|
||||||
|
//? valid inputs are: A1, B14, C79, E99, F1, G99, J1, M98, ... (and all lower case variants)
|
||||||
|
|
||||||
|
positionToCheck = positionToCheck.toUpperCase();
|
||||||
|
|
||||||
|
//? Check if input is the right length
|
||||||
|
if (positionToCheck.length() < 2 || positionToCheck.length() > 3){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Check if input is in the right format
|
||||||
|
if (!(Character.isLetter(positionToCheck.charAt(0)) && Character.isDigit(positionToCheck.charAt(1)))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (positionToCheck.length() == 3){
|
||||||
|
if (!(Character.isDigit(positionToCheck.charAt(2)))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean userPositionBoundsErrorCheck(String positionToCheck, Spreadsheet spr){
|
||||||
|
//? true if valid
|
||||||
|
|
||||||
|
positionToCheck = positionToCheck.toUpperCase();
|
||||||
|
|
||||||
|
if ((spr.getRow(positionToCheck) >= spr.getRowsLCount()) || (spr.getCol(positionToCheck) >= spr.getColsCount())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//? User input for a value or a formula
|
||||||
|
public static String userValueFormulaInput(){
|
||||||
|
System.out.println();
|
||||||
|
System.out.printf("Input a value of a formula for the selected position.%n");
|
||||||
|
System.out.printf("Format for a value: 7 or 1337 %nFormat for a formula: =7*6 or =SUM(A1:A3)%n");
|
||||||
|
System.out.print("Input: ");
|
||||||
|
String userCommandInput = keyboard.nextLine();
|
||||||
|
|
||||||
|
return userValueFormulaComputation(userCommandInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String userValueFormulaComputation(String userValueFormulaInput){
|
||||||
|
if (userValueFormulaInput.isEmpty()){
|
||||||
|
System.out.println("Input is empty!");
|
||||||
|
return userValueFormulaInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Formula
|
||||||
|
if (userValueFormulaInput.charAt(0) == '='){
|
||||||
|
if (!(userFormulaErrorCheck(userValueFormulaInput))) {
|
||||||
|
System.out.println("Invalid formula!");
|
||||||
|
return userValueFormulaInput();
|
||||||
|
}
|
||||||
|
return userValueFormulaInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Value
|
||||||
|
if (!(userValueErrorCheck(userValueFormulaInput))){
|
||||||
|
System.out.println("Invalid value!");
|
||||||
|
return userValueFormulaInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
return userValueFormulaInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean userFormulaErrorCheck(String formulaToCheck){
|
||||||
|
//? true if valid
|
||||||
|
//? valid inputs are: =7*6, =SUM(A1:A3), =A1, =A1+A2, =A1-A2, ... (and all lower case variants)
|
||||||
|
|
||||||
|
//TODO ME: Formula format check, maybe too much work
|
||||||
|
//TODO ME: Check if formula vars are in bounds
|
||||||
|
|
||||||
|
//? remove '=' at the beginning and make everything upper case
|
||||||
|
formulaToCheck = formulaToCheck.toUpperCase().substring(1);
|
||||||
|
|
||||||
|
if (formulaToCheck.startsWith("SUMME(") || formulaToCheck.startsWith("PRODUKT(") || formulaToCheck.startsWith("MITTELWERT(") || formulaToCheck.startsWith("STABW(") || formulaToCheck.startsWith("MIN(") || formulaToCheck.startsWith("MAX(")){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean userValueErrorCheck(String valueToCheck){
|
||||||
|
//? true if valid
|
||||||
|
//? valid inputs are: 7, 1337, 0, ...
|
||||||
|
|
||||||
|
String digitCheckRegex = "-?\\d+(\\.\\d+)?";
|
||||||
|
if (!(valueToCheck.matches(digitCheckRegex))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void executeCommand(String command) {
|
||||||
|
System.out.printf("Executing command: %s%n", command);
|
||||||
|
//TODO ME:
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ package de.hs_mannheim.informatik.spreadsheet;
|
||||||
* Part of a simplified spreadsheet system for the PR1 programming lab at Hochschule Mannheim.
|
* Part of a simplified spreadsheet system for the PR1 programming lab at Hochschule Mannheim.
|
||||||
* A cell needs to be able to hold a formula and a value
|
* A cell needs to be able to hold a formula and a value
|
||||||
*
|
*
|
||||||
* @author Oliver Hummel
|
* @author Oliver Hummel & Victor Waitz
|
||||||
*/
|
*/
|
||||||
public class Cell {
|
public class Cell {
|
||||||
private String formula = "";
|
private String formula = "";
|
||||||
|
|
|
@ -10,7 +10,7 @@ import java.util.regex.Pattern;
|
||||||
* A simplified spreadsheet class for the PR1 programming lab at Hochschule Mannheim.
|
* A simplified spreadsheet class for the PR1 programming lab at Hochschule Mannheim.
|
||||||
* One aspect worth mentioning is that it only supports long numbers, not doubles.
|
* One aspect worth mentioning is that it only supports long numbers, not doubles.
|
||||||
*
|
*
|
||||||
* @author Oliver Hummel
|
* @author Oliver Hummel & Victor Waitz
|
||||||
*/
|
*/
|
||||||
public class Spreadsheet {
|
public class Spreadsheet {
|
||||||
Cell[][] cells;
|
Cell[][] cells;
|
||||||
|
@ -57,18 +57,19 @@ public class Spreadsheet {
|
||||||
put(getRow(cellName), getCol(cellName), value);
|
put(getRow(cellName), getCol(cellName), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCol(String cellName) {
|
public int getCol(String cellName) {
|
||||||
return cellName.charAt(0) - 'A';
|
return cellName.charAt(0) - 'A';
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getRow(String cellName) {
|
public int getRow(String cellName) {
|
||||||
|
//TODO ME: Implement row numbers with two digits
|
||||||
return cellName.charAt(1) - '1';
|
return cellName.charAt(1) - '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
// business logic
|
// business logic
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* A method for reading in data from a CSV file.
|
* A method for reading in data from a CSV file.
|
||||||
* @param path The file to read.
|
* @param path The file to read.
|
||||||
* @param separator The char used to split up the input, e.g. a comma or a semicolon.
|
* @param separator The char used to split up the input, e.g. a comma or a semicolon.
|
||||||
|
@ -80,7 +81,7 @@ public class Spreadsheet {
|
||||||
// TODO: implement this
|
// TODO: implement this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* A method for saving data to a CSV file.
|
* A method for saving data to a CSV file.
|
||||||
* @param path The file to write.
|
* @param path The file to write.
|
||||||
* @return Nothing.
|
* @return Nothing.
|
||||||
|
@ -105,27 +106,34 @@ public class Spreadsheet {
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This method does the actual evaluation/calcluation of a specific cell
|
* This method does the actual evaluation/calcluation of a specific cell
|
||||||
* @param cellName the name of the cell to be evaluated
|
* @param cellName the name of the cell to be evaluated
|
||||||
* @return Nothing.
|
* @return Nothing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private void evaluateCell(int row, int col) {
|
private void evaluateCell(int row, int col) {
|
||||||
String formula = cells[row][col].getFormula();
|
String formula = cells[row][col].getFormula();
|
||||||
String result = "";
|
String result = "";
|
||||||
|
|
||||||
if (formula.startsWith("SUMME(")) // e.g. SUMME(A3:A8)
|
if (formula.startsWith("SUMME(")) // e.g. SUMME(A3:A8)
|
||||||
result = "" + sum(formula.substring(6, 8), formula.substring(9, 11)); // TODO adapt to cells with two digits
|
result = "" + sum(formula.substring(6, 8), formula.substring(9, 11)); // TODO adapt to cells with two digits
|
||||||
|
|
||||||
else if (formula.startsWith("PRODUKT(")) // e.g. PRODUKT(A3:B9)
|
else if (formula.startsWith("PRODUKT(")) // e.g. PRODUKT(A3:B9)
|
||||||
result = "TODO"; // TODO
|
result = "TODO"; // TODO
|
||||||
|
|
||||||
else if (formula.startsWith("MITTELWERT(")) // e.g. MITTELWERT(A3:A5)
|
else if (formula.startsWith("MITTELWERT(")) // e.g. MITTELWERT(A3:A5)
|
||||||
result = "TODO"; // TODO
|
result = "TODO"; // TODO
|
||||||
|
|
||||||
else if (formula.startsWith("STABW(")) // e.g. STABW(C6:D8) -> Standardabweichung
|
else if (formula.startsWith("STABW(")) // e.g. STABW(C6:D8) -> Standardabweichung
|
||||||
result = "TODO"; // TODO
|
result = "TODO"; // TODO
|
||||||
|
|
||||||
else if (formula.startsWith("MIN(")) // e.g. MIN(C13:H13) -> größter Wert
|
else if (formula.startsWith("MIN(")) // e.g. MIN(C13:H13) -> größter Wert
|
||||||
result = "TODO"; // TODO
|
result = "TODO"; // TODO
|
||||||
|
|
||||||
else if (formula.startsWith("MAX(")) // e.g. MAX(A1:A10) -> Standardabweichung
|
else if (formula.startsWith("MAX(")) // e.g. MAX(A1:A10) -> Standardabweichung
|
||||||
result = "TODO"; // TODO
|
result = "TODO"; // TODO
|
||||||
|
|
||||||
else if (!formula.isEmpty()) {
|
else if (!formula.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
result = "" + calculate(formula);
|
result = "" + calculate(formula);
|
||||||
|
@ -137,7 +145,7 @@ public class Spreadsheet {
|
||||||
cells[row][col].setValue("" + result);
|
cells[row][col].setValue("" + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Method for calculating the sum of a rectangular block of cells, such as from A1 to B3.
|
* Method for calculating the sum of a rectangular block of cells, such as from A1 to B3.
|
||||||
* @param startCellName The name of the cell in the upper left corner of the rectangle.
|
* @param startCellName The name of the cell in the upper left corner of the rectangle.
|
||||||
* @param endCellName The name of the cell in the lower right corner of the rectangle.
|
* @param endCellName The name of the cell in the lower right corner of the rectangle.
|
||||||
|
@ -149,7 +157,7 @@ public class Spreadsheet {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* This method calculates the result of a "normal" algebraic expression. It only needs to support
|
* This method calculates the result of a "normal" algebraic expression. It only needs to support
|
||||||
* expressions like =B4 or =2+A3-B2, i.e. only with int numbers and other cells and with plus,
|
* expressions like =B4 or =2+A3-B2, i.e. only with int numbers and other cells and with plus,
|
||||||
* minus, times, split only. An expression always starts with either a number or a cell name. If it
|
* minus, times, split only. An expression always starts with either a number or a cell name. If it
|
||||||
|
@ -178,11 +186,20 @@ public class Spreadsheet {
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
|
public int getRowsLCount() {
|
||||||
|
return cells.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColsCount() {
|
||||||
|
return cells[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.append(" ");
|
sb.append(" ");
|
||||||
for (int i = 0; i < cells.length; i++) {
|
for (int i = 0; i < cells[0].length; i++) {
|
||||||
sb.append(" " + (char)('A'+ i) + " | ");
|
sb.append(" " + (char)('A'+ i) + " | ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,5 +215,4 @@ public class Spreadsheet {
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package de.hs_mannheim.informatik.spreadsheet;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class AxelTest {
|
||||||
|
|
||||||
|
@org.junit.jupiter.api.Test
|
||||||
|
@org.junit.jupiter.api.DisplayName("User command or position input")
|
||||||
|
void userCommandPositionComputation() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.jupiter.api.Test
|
||||||
|
@org.junit.jupiter.api.DisplayName("Command input error check")
|
||||||
|
void userCommandErrorCheck() {
|
||||||
|
String[] successTestList = {"*exit", "*save", "*load", "*help", "*eXiT", "*SAVE", "*LoAd", "*hElP"};
|
||||||
|
String[] failureTestList = {"exit", "save", "load", "help", "eXiT", "SAVE", "LoAd", "hElP", "*exit*", "*save*", "*load*", "*help*", "*eXiT*", "*SAVE*", "*LoAd*", "*hElP*", "*test", "*TEST", "*saev", "*xeit"};
|
||||||
|
|
||||||
|
for (String successTest : successTestList) {
|
||||||
|
assertTrue(Axel.userCommandErrorCheck(successTest));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String failureTest : failureTestList) {
|
||||||
|
assertFalse(Axel.userCommandErrorCheck(failureTest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@org.junit.jupiter.api.Test
|
||||||
|
@org.junit.jupiter.api.DisplayName("Position input error check")
|
||||||
|
void userPositionErrorCheck() {
|
||||||
|
//? Overall format test
|
||||||
|
String[] successTestList = {"A1", "B14", "C79", "E99", "F1", "G99", "J1", "M98", "N67", "o45", "p23", "q12", "r2"};
|
||||||
|
String[] failureTestList = {"A100", "Z101", "AA1", "AB2", "ZZ1", "A1A", "FHT", "AAA", "G3U", "ZZZ", "2A", "47H", "AAAA", "test", "TEST", "save", "*save", "*exit"};
|
||||||
|
|
||||||
|
for (String successTest : successTestList) {
|
||||||
|
assertTrue(Axel.userPositionErrorCheck(successTest));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String failureTest : failureTestList) {
|
||||||
|
assertFalse(Axel.userPositionErrorCheck(failureTest));
|
||||||
|
}
|
||||||
|
|
||||||
|
//? Out of bounds test
|
||||||
|
Spreadsheet testSpr = new Spreadsheet(6,8);
|
||||||
|
|
||||||
|
String[] successBoundsTest = {"A1", "a1", "b3", "c5", "A3", "H6", "h6"};
|
||||||
|
String[] failureBoundsTest = {"i2", "J6", "B7", "K9", "Z99"};
|
||||||
|
|
||||||
|
for (String successTest : successBoundsTest) {
|
||||||
|
assertTrue(Axel.userPositionBoundsErrorCheck(successTest, testSpr));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String failureTest : failureBoundsTest) {
|
||||||
|
assertFalse(Axel.userPositionBoundsErrorCheck(failureTest, testSpr));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.jupiter.api.Test
|
||||||
|
@org.junit.jupiter.api.DisplayName("User value or formula input")
|
||||||
|
void userValueFormulaComputation() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.jupiter.api.Test
|
||||||
|
@org.junit.jupiter.api.DisplayName("Value input error check")
|
||||||
|
void userValueErrorCheck() {
|
||||||
|
String[] successTestList = {"0", "1", "-1", "1234", "4324", "-465"};
|
||||||
|
String[] failureTestList = {"a", "aa", "A!", "A1", "wef", "-a", "a-","-1a"};
|
||||||
|
|
||||||
|
for (String successTest : successTestList) {
|
||||||
|
assertTrue(Axel.userValueErrorCheck(successTest));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String failureTest : failureTestList) {
|
||||||
|
assertFalse(Axel.userValueErrorCheck(failureTest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.jupiter.api.Test
|
||||||
|
@org.junit.jupiter.api.DisplayName("Formula input error check")
|
||||||
|
void userFormulaErrorCheck() {
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue