2023-12-12 15:00:07 +01:00
|
|
|
package de.hs_mannheim.informatik.spreadsheet;
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
import java.io.File;
|
2023-12-14 08:31:20 +01:00
|
|
|
import java.io.FileNotFoundException;
|
2023-12-27 03:54:24 +01:00
|
|
|
import java.util.ArrayList;
|
2023-12-18 00:53:59 +01:00
|
|
|
import java.util.Scanner;
|
2023-12-27 03:54:24 +01:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
2023-12-12 15:00:07 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Part of a simplified spreadsheet system for the PR1 programming lab at Hochschule Mannheim.
|
|
|
|
*
|
2023-12-18 00:53:59 +01:00
|
|
|
* @author Oliver Hummel & Victor Waitz
|
2023-12-12 15:00:07 +01:00
|
|
|
*/
|
|
|
|
public class Axel {
|
2023-12-18 00:53:59 +01:00
|
|
|
static Scanner keyboard = new Scanner(System.in);
|
2023-12-30 01:27:14 +01:00
|
|
|
static Spreadsheet spr = new Spreadsheet(11, 11);
|
|
|
|
static String saveFilePath = "Axel\\resources\\zahlen.csv";
|
2023-12-12 15:00:07 +01:00
|
|
|
|
2023-12-14 08:31:20 +01:00
|
|
|
public static void main(String[] args) throws FileNotFoundException {
|
2023-12-29 20:28:36 +01:00
|
|
|
System.out.println("Welcome to Axel (Totally not Excel)");
|
|
|
|
System.out.println();
|
2023-12-30 01:27:14 +01:00
|
|
|
|
|
|
|
spr.loadSpecialTable();
|
2023-12-12 15:00:07 +01:00
|
|
|
System.out.println(spr);
|
2023-12-29 20:28:36 +01:00
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
// spr.saveCsv("/tmp/test.csv");
|
2023-12-18 00:53:59 +01:00
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
while (true) {
|
2023-12-18 00:53:59 +01:00
|
|
|
String userCommandPositionInput = userCommandPositionInput();
|
2023-12-30 01:27:14 +01:00
|
|
|
if (userCommandPositionInput.charAt(0) == '*') {
|
2023-12-18 00:53:59 +01:00
|
|
|
executeCommand(userCommandPositionInput);
|
2023-12-27 03:54:24 +01:00
|
|
|
System.out.println(spr);
|
2023-12-18 00:53:59 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
String userPositionInput = userCommandPositionInput;
|
|
|
|
|
2023-12-29 20:28:36 +01:00
|
|
|
String userValueFormulaInput = userValueFormulaInput(userPositionInput);
|
2023-12-18 00:53:59 +01:00
|
|
|
|
|
|
|
spr.put(userPositionInput, userValueFormulaInput);
|
|
|
|
|
|
|
|
System.out.println(spr);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//? User input for a program command or a position
|
2023-12-30 01:27:14 +01:00
|
|
|
public static String userCommandPositionInput() {
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.println();
|
|
|
|
System.out.println("Input a command for the program or a position");
|
2023-12-30 01:27:14 +01:00
|
|
|
System.out.printf("List of program commands: *clear, *load, *save, *exit or *help %nFormat for position: A1 or B14%n");
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.print("Input: ");
|
|
|
|
String userCommandPositionInput = keyboard.nextLine();
|
|
|
|
|
|
|
|
return userCommandPositionComputation(userCommandPositionInput);
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static String userCommandPositionComputation(String userCommandPositionInput) {
|
2023-12-18 00:53:59 +01:00
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
if (userCommandPositionInput.isEmpty()) {
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.println("Input is empty!");
|
|
|
|
return userCommandPositionInput();
|
|
|
|
}
|
|
|
|
|
|
|
|
//? Program command
|
2023-12-30 01:27:14 +01:00
|
|
|
if (userCommandPositionInput.charAt(0) == '*') {
|
2023-12-18 00:53:59 +01:00
|
|
|
if (!(userCommandErrorCheck(userCommandPositionInput))) {
|
|
|
|
System.out.println("Invalid command!");
|
|
|
|
return userCommandPositionInput();
|
|
|
|
}
|
|
|
|
return userCommandPositionInput;
|
|
|
|
}
|
|
|
|
|
|
|
|
//? Position
|
2023-12-30 01:27:14 +01:00
|
|
|
if (!(userPositionErrorCheck(userCommandPositionInput, spr))) {
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.println("Invalid position!");
|
|
|
|
return userCommandPositionInput();
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
if (!(userPositionBoundsErrorCheck(userCommandPositionInput, spr))) {
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.println("Position out of bounds!");
|
|
|
|
return userCommandPositionInput();
|
|
|
|
}
|
|
|
|
|
|
|
|
return userCommandPositionInput;
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static boolean userCommandErrorCheck(String CommandToCheck) {
|
2023-12-18 00:53:59 +01:00
|
|
|
//? true if valid
|
2023-12-30 01:27:14 +01:00
|
|
|
//? valid inputs are: *clear, *exit, *save, *load, *help (and all upper case variants)
|
2023-12-18 00:53:59 +01:00
|
|
|
|
|
|
|
CommandToCheck = CommandToCheck.toLowerCase();
|
2023-12-30 01:27:14 +01:00
|
|
|
if (CommandToCheck.equals("*clear") || CommandToCheck.equals("*exit") || CommandToCheck.equals("*save") || CommandToCheck.equals("*load") || CommandToCheck.equals("*help")) {
|
2023-12-18 00:53:59 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static boolean userPositionErrorCheck(String positionToCheck, Spreadsheet spr) {
|
2023-12-18 00:53:59 +01:00
|
|
|
//? 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
|
2023-12-30 01:27:14 +01:00
|
|
|
if (positionToCheck.length() < 2 || positionToCheck.length() > 3) {
|
2023-12-18 00:53:59 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//? Check if input is in the right format
|
2023-12-30 01:27:14 +01:00
|
|
|
if (!(Character.isLetter(positionToCheck.charAt(0)) && Character.isDigit(positionToCheck.charAt(1)))) {
|
2023-12-18 00:53:59 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
if (positionToCheck.length() == 3) {
|
|
|
|
if (!(Character.isDigit(positionToCheck.charAt(2)))) {
|
2023-12-18 00:53:59 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static boolean userPositionBoundsErrorCheck(String positionToCheck, Spreadsheet spr) {
|
2023-12-18 00:53:59 +01:00
|
|
|
//? true if valid
|
|
|
|
|
|
|
|
positionToCheck = positionToCheck.toUpperCase();
|
|
|
|
|
|
|
|
if ((spr.getRow(positionToCheck) >= spr.getRowsLCount()) || (spr.getCol(positionToCheck) >= spr.getColsCount())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2023-12-12 15:00:07 +01:00
|
|
|
}
|
|
|
|
|
2023-12-27 03:54:24 +01:00
|
|
|
|
2023-12-18 00:53:59 +01:00
|
|
|
//? User input for a value or a formula
|
2023-12-30 01:27:14 +01:00
|
|
|
public static String userValueFormulaInput(String currentPos) {
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.println();
|
2023-12-29 20:28:36 +01:00
|
|
|
System.out.printf("Input a value of a formula for the selected position: %s.%n", currentPos);
|
2023-12-27 03:54:24 +01:00
|
|
|
System.out.printf("Format for a value: 7 or 1337 %nFormat for a formula: =7*6 or =SUMME(A1:A3)%n");
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.print("Input: ");
|
|
|
|
String userCommandInput = keyboard.nextLine();
|
|
|
|
|
2023-12-29 20:28:36 +01:00
|
|
|
return userValueFormulaComputation(userCommandInput, currentPos);
|
2023-12-18 00:53:59 +01:00
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static String userValueFormulaComputation(String userValueFormulaInput, String currentPos) {
|
|
|
|
if (userValueFormulaInput.isEmpty()) {
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.println("Input is empty!");
|
2023-12-29 20:28:36 +01:00
|
|
|
return userValueFormulaInput(currentPos);
|
2023-12-18 00:53:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//? Formula
|
2023-12-30 01:27:14 +01:00
|
|
|
if (userValueFormulaInput.charAt(0) == '=') {
|
2023-12-18 00:53:59 +01:00
|
|
|
if (!(userFormulaErrorCheck(userValueFormulaInput))) {
|
|
|
|
System.out.println("Invalid formula!");
|
2023-12-29 20:28:36 +01:00
|
|
|
return userValueFormulaInput(currentPos);
|
2023-12-18 00:53:59 +01:00
|
|
|
}
|
|
|
|
return userValueFormulaInput;
|
|
|
|
}
|
|
|
|
|
|
|
|
//? Value
|
2023-12-30 01:27:14 +01:00
|
|
|
if (!(userValueErrorCheck(userValueFormulaInput))) {
|
2023-12-18 00:53:59 +01:00
|
|
|
System.out.println("Invalid value!");
|
2023-12-29 20:28:36 +01:00
|
|
|
return userValueFormulaInput(currentPos);
|
2023-12-18 00:53:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return userValueFormulaInput;
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static boolean userFormulaErrorCheck(String formulaToCheck) {
|
2023-12-18 00:53:59 +01:00
|
|
|
//? true if valid
|
|
|
|
//? valid inputs are: =7*6, =SUM(A1:A3), =A1, =A1+A2, =A1-A2, ... (and all lower case variants)
|
|
|
|
|
|
|
|
//? remove '=' at the beginning and make everything upper case
|
|
|
|
formulaToCheck = formulaToCheck.toUpperCase().substring(1);
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
if (formulaToCheck.startsWith("SUMME(") || formulaToCheck.startsWith("PRODUKT(") || formulaToCheck.startsWith("MITTELWERT(") || formulaToCheck.startsWith("STABW(") || formulaToCheck.startsWith("MIN(") || formulaToCheck.startsWith("MAX(")) {
|
2023-12-27 03:54:24 +01:00
|
|
|
return userFormulaFunctionErrorCheck(formulaToCheck);
|
|
|
|
}
|
|
|
|
|
|
|
|
return userFormulaExpressionErrorCheck(formulaToCheck);
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static boolean userFormulaFunctionErrorCheck(String functionToCheck) {
|
2023-12-27 03:54:24 +01:00
|
|
|
String[] functionCorners = spr.isolateFunctionCorners(functionToCheck);
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
if (functionCorners.length != 2) {
|
2023-12-27 03:54:24 +01:00
|
|
|
return false;
|
2023-12-18 00:53:59 +01:00
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
for (String functionCorner : functionCorners) {
|
|
|
|
if (!(spr.isValueCellName(functionCorner).equals("cellName"))) {
|
2023-12-27 03:54:24 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
if (!userPositionBoundsErrorCheck(functionCorner, spr)) {
|
2023-12-29 20:28:36 +01:00
|
|
|
System.out.print("Out of bounds - ");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (functionToCheck.startsWith("MITTELWERT(") || functionToCheck.startsWith("STABW(")) {
|
2023-12-30 01:27:14 +01:00
|
|
|
String[] functionBlock = spr.wholeFunctionBlock(functionToCheck);
|
2023-12-29 20:28:36 +01:00
|
|
|
boolean allEmpty = true;
|
|
|
|
|
|
|
|
for (String cell : functionBlock) {
|
2023-12-30 01:27:14 +01:00
|
|
|
if (!cell.isEmpty()) {
|
2023-12-29 20:28:36 +01:00
|
|
|
allEmpty = false;
|
|
|
|
}
|
|
|
|
}
|
2023-12-30 01:27:14 +01:00
|
|
|
if (allEmpty) {
|
2023-12-29 20:28:36 +01:00
|
|
|
System.out.print("Division by zero - ");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (functionToCheck.startsWith("STABW(")) {
|
2023-12-30 01:27:14 +01:00
|
|
|
String[] functionBlock = spr.wholeFunctionBlock(functionToCheck);
|
2023-12-29 20:28:36 +01:00
|
|
|
String[] notEmptyValues = spr.extractNotEmptyCells(functionBlock);
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
if (notEmptyValues.length < 2) {
|
2023-12-29 20:28:36 +01:00
|
|
|
System.out.print("Division by zero - ");
|
2023-12-27 03:54:24 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static boolean userFormulaExpressionErrorCheck(String expressionToCheck) {
|
|
|
|
//TODO ME: Maybe not worth the time
|
2023-12-18 00:53:59 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static boolean userValueErrorCheck(String valueToCheck) {
|
2023-12-18 00:53:59 +01:00
|
|
|
//? true if valid
|
2023-12-27 03:54:24 +01:00
|
|
|
//? valid inputs are: 7, 1337, 0, , -213,...
|
2023-12-18 00:53:59 +01:00
|
|
|
|
2023-12-27 03:54:24 +01:00
|
|
|
//? For floating point numbers
|
|
|
|
// String digitCheckRegex = "-?\\d+(\\.\\d+)?";
|
|
|
|
//? For integers
|
|
|
|
String digitCheckRegex = "-?\\d+";
|
2023-12-30 01:27:14 +01:00
|
|
|
if (!(valueToCheck.matches(digitCheckRegex))) {
|
2023-12-18 00:53:59 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
public static void executeCommand(String command) throws FileNotFoundException {
|
|
|
|
switch (command) {
|
|
|
|
case "*clear":
|
|
|
|
progClear();
|
|
|
|
break;
|
|
|
|
|
2023-12-27 03:54:24 +01:00
|
|
|
case "*load":
|
|
|
|
progLoad();
|
|
|
|
break;
|
2023-12-30 01:27:14 +01:00
|
|
|
|
|
|
|
case "*save":
|
|
|
|
progSave();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case "*exit":
|
|
|
|
progExit();
|
|
|
|
break;
|
2023-12-27 03:54:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
private static void progClear(){
|
|
|
|
System.out.println("Are you sure you want to clear the table? (yes/no)");
|
|
|
|
System.out.print("Input: ");
|
|
|
|
String userClearInput = keyboard.nextLine().toLowerCase();
|
2023-12-27 03:54:24 +01:00
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
if (userClearInput.equals("yes") || userClearInput.equals("y")){
|
|
|
|
spr.clearTable();
|
|
|
|
System.out.println("Table cleared!");
|
2023-12-27 03:54:24 +01:00
|
|
|
}
|
2023-12-30 01:27:14 +01:00
|
|
|
}
|
2023-12-27 03:54:24 +01:00
|
|
|
|
2023-12-30 01:27:14 +01:00
|
|
|
private static void progLoad() throws FileNotFoundException {
|
|
|
|
spr.readCsv(saveFilePath, ",", "Amogus");
|
|
|
|
System.out.println("File loaded!");
|
2023-12-18 00:53:59 +01:00
|
|
|
}
|
2023-12-30 01:27:14 +01:00
|
|
|
|
|
|
|
private static void progSave() throws FileNotFoundException {
|
|
|
|
String savePath = saveFilePath;
|
|
|
|
spr.saveCsv(savePath);
|
|
|
|
System.out.println("File saved");
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void progExit() throws FileNotFoundException {
|
|
|
|
System.out.println("Do you want to save befor you exit? (yes/no)");
|
|
|
|
System.out.print("Input: ");
|
|
|
|
String userExitInput = keyboard.nextLine().toLowerCase();
|
|
|
|
|
|
|
|
if (userExitInput.equals("yes") || userExitInput.equals("y")) {
|
|
|
|
progSave();
|
|
|
|
}
|
|
|
|
System.out.println("Goodbye!");
|
|
|
|
}
|
|
|
|
|
2023-12-12 15:00:07 +01:00
|
|
|
}
|