diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.gitattributes b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.gitattributes new file mode 100644 index 00000000..00a51aff --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.github/workflows/gradle.yml b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.github/workflows/gradle.yml new file mode 100644 index 00000000..94e9b475 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.github/workflows/gradle.yml @@ -0,0 +1,34 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the main branch + push: + branches: [ main ] + pull_request: + branches: [ main ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + - name: Set up JDK 16 + uses: actions/setup-java@v2 + with: + java-version: '16' + distribution: 'adopt' + + - name: Build with Gradle + run: ./gradlew build diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.gitignore b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.gitignore new file mode 100644 index 00000000..652102b6 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/.gitignore @@ -0,0 +1,32 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +# Ignore IntelliJ IDEA project files +.idea diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/README.md b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/README.md new file mode 100644 index 00000000..ca0f7ebb --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/README.md @@ -0,0 +1,18 @@ +# Hausaufgabe 1 + +Deadline für Abgabe per Pull Request: 24.10.2021 23:59 Uhr bzw. 27.10.2021 23:59 Uhr je nach dem in welcher Übungsgruppe Sie eingeschrieben sind. + +## Aufgabenstellung + +- Forken Sie dieses Repository (github.com/prog2-ws21/ha1) in Ihren eigenen GitHub Account. +- Analysieren Sie das Verhalten der Klasse `Calculator` und finden Sie ein paar Abweichungen im Vergleich zu `www.online-calculator.com` und/oder zu dem im JavaDoc beschriebenen Verhalten. +- Teilaufgabe 1: Schreiben Sie einen neuen zusätzlichen Test, der eine bisher nicht getestete Funktionalität abdeckt, die bereits funktioniert und der daher direkt grün wird. +- Teilaufgabe 2: Schreiben Sie zwei weitere zusätzliche Tests, die zwei unterschiedliche Fehlerkategorien aufdecken (d.h. deren Fehlerursachen in unterschiedlichen Methoden liegen) und somit fehlschlagen. +- Teilaufgabe 3: Schreiben Sie zwei Bugfixes (also Änderungen der Implementierungsklasse `Calculator`), so dass die zwei zuvor hinzugefügten Tests erfolgreich durchlaufen. Falls Sie dabei das Verhalten so erweitern, dass es über das im JavaDoc spezifizierte hinausgeht (aber zum Verhalten des Online Calculator passt), dann erweitern Sie bitte auch das JavaDoc entsprechend. +- Pushen Sie Ihre Tests & Änderungen auf Ihr eigenes, geforktes Repository, und zwar strukturiert in mindestens drei Commits: z.B. 1. Commit für neuer grüner Test, 2. Commit für neuer roter Test, 3. Commit für den Fix zu diesem Test, 4. Commit für weiteren neuen roter Test, 5. Commit für Fix zu diesem Test. +- Stellen Sie zum Abschluss einen Pull Request auf das obere Repository, und zwar vor der oben genannten Deadline. + +## Hinweise + +Sie dürfen mit Ihren Bugfixes die bestehende Implementierung deutlich verändern (z.B. die Verwendung der privaten Variablen), solange Sie dabei nicht die Signaturen (Name, Typ, Parameter) der öffentlichen Methoden ändern. +Sie dürfen auch gerne Hilfsmethoden hinzufügen, die intern von den öffentlichen Methoden aufgerufen werden, und diese internen Hilfsmethoden zum Zwecke der besseren Testbarkeit auch öffentlich (public) machen, um entsprechende Unit-Tests für diese Hilfsmethoden hinzufügen zu können. diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/build.gradle b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/build.gradle new file mode 100644 index 00000000..6a953c2b --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/build.gradle @@ -0,0 +1,68 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.logging.TestLogEvent + +plugins { + // Apply the application plugin to add support for building a CLI application in Java. + id 'application' +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2' + + // This dependency is used by the application. + implementation 'com.google.guava:guava:30.1.1-jre' +} + +application { + // Define the main class for the application. + mainClass = 'htw.berlin.prog2.ha1.App' +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} + +// https://stackoverflow.com/questions/3963708/gradle-how-to-display-test-results-in-the-console-in-real-time#answer-36130467 +tasks.withType(Test) { + testLogging { + // set options for log level LIFECYCLE + events TestLogEvent.FAILED, + TestLogEvent.PASSED, + TestLogEvent.SKIPPED, + TestLogEvent.STANDARD_OUT + exceptionFormat TestExceptionFormat.FULL + showExceptions true + showCauses true + showStackTraces true + + // set options for log level DEBUG and INFO + debug { + events TestLogEvent.STARTED, + TestLogEvent.FAILED, + TestLogEvent.PASSED, + TestLogEvent.SKIPPED, + TestLogEvent.STANDARD_ERROR, + TestLogEvent.STANDARD_OUT + exceptionFormat TestExceptionFormat.FULL + } + info.events = debug.events + info.exceptionFormat = debug.exceptionFormat + + afterSuite { desc, result -> + if (!desc.parent) { // will match the outermost suite + def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)" + def startItem = '| ', endItem = ' |' + def repeatLength = startItem.length() + output.length() + endItem.length() + println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength)) + } + } + } +} + diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/src/main/java/htw/berlin/prog2/ha1/Calculator.java b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/src/main/java/htw/berlin/prog2/ha1/Calculator.java new file mode 100644 index 00000000..939d7fb8 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/src/main/java/htw/berlin/prog2/ha1/Calculator.java @@ -0,0 +1,135 @@ +package htw.berlin.prog2.ha1; + +/** + * Eine Klasse, die das Verhalten des Online Taschenrechners imitiert, welcher auf + * https://www.online-calculator.com/ aufgerufen werden kann (ohne die Memory-Funktionen) + * und dessen Bildschirm bis zu zehn Ziffern plus einem Dezimaltrennzeichen darstellen kann. + * Enthält mit Absicht noch diverse Bugs oder unvollständige Funktionen. + */ +public class Calculator { + + private String screen = "0"; + + private double latestValue; + + private String latestOperation = ""; + + /** + * @return den aktuellen Bildschirminhalt als String + */ + public String readScreen() { + return screen; + } + + /** + * Empfängt den Wert einer gedrückten Zifferntaste. Da man nur eine Taste auf einmal + * drücken kann muss der Wert positiv und einstellig sein und zwischen 0 und 9 liegen. + * Führt in jedem Fall dazu, dass die gerade gedrückte Ziffer auf dem Bildschirm angezeigt + * oder rechts an die zuvor gedrückte Ziffer angehängt angezeigt wird. + * @param digit Die Ziffer, deren Taste gedrückt wurde + */ + public void pressDigitKey(int digit) { + if(digit > 9 || digit < 0) throw new IllegalArgumentException(); + + if(screen.equals("0") || latestValue == Double.parseDouble(screen)) screen = ""; + + screen = screen + digit; + } + + /** + * Empfängt den Befehl der C- bzw. CE-Taste (Clear bzw. Clear Entry). + * Einmaliges Drücken der Taste löscht die zuvor eingegebenen Ziffern auf dem Bildschirm + * so dass "0" angezeigt wird, jedoch ohne zuvor zwischengespeicherte Werte zu löschen. + * Wird daraufhin noch einmal die Taste gedrückt, dann werden auch zwischengespeicherte + * Werte sowie der aktuelle Operationsmodus zurückgesetzt, so dass der Rechner wieder + * im Ursprungszustand ist. + */ + public void pressClearKey() { + screen = "0"; + latestOperation = ""; + latestValue = 0.0; + } + + /** + * Empfängt den Wert einer gedrückten binären Operationstaste, also eine der vier Operationen + * Addition, Substraktion, Division, oder Multiplikation, welche zwei Operanden benötigen. + * Beim ersten Drücken der Taste wird der Bildschirminhalt nicht verändert, sondern nur der + * Rechner in den passenden Operationsmodus versetzt. + * Beim zweiten Drücken nach Eingabe einer weiteren Zahl wird direkt des aktuelle Zwischenergebnis + * auf dem Bildschirm angezeigt. Falls hierbei eine Division durch Null auftritt, wird "Error" angezeigt. + * @param operation "+" für Addition, "-" für Substraktion, "x" für Multiplikation, "/" für Division + */ + public void pressBinaryOperationKey(String operation) { + latestValue = Double.parseDouble(screen); + latestOperation = operation; + } + + /** + * Empfängt den Wert einer gedrückten unären Operationstaste, also eine der drei Operationen + * Quadratwurzel, Prozent, Inversion, welche nur einen Operanden benötigen. + * Beim Drücken der Taste wird direkt die Operation auf den aktuellen Zahlenwert angewendet und + * der Bildschirminhalt mit dem Ergebnis aktualisiert. + * @param operation "√" für Quadratwurzel, "%" für Prozent, "1/x" für Inversion + */ + public void pressUnaryOperationKey(String operation) { + latestValue = Double.parseDouble(screen); + latestOperation = operation; + var result = switch(operation) { + case "√" -> Math.sqrt(Double.parseDouble(screen)); + case "%" -> Double.parseDouble(screen) / 100; + case "1/x" -> 1 / Double.parseDouble(screen); + default -> throw new IllegalArgumentException(); + }; + screen = Double.toString(result); + if(screen.contains(".") && screen.length() > 11) screen = screen.substring(0, 10); + + } + + /** + * Empfängt den Befehl der gedrückten Dezimaltrennzeichentaste, im Englischen üblicherweise "." + * Fügt beim ersten Mal Drücken dem aktuellen Bildschirminhalt das Trennzeichen auf der rechten + * Seite hinzu und aktualisiert den Bildschirm. Daraufhin eingegebene Zahlen werden rechts vom + * Trennzeichen angegeben und daher als Dezimalziffern interpretiert. + * Beim zweimaligem Drücken, oder wenn bereits ein Trennzeichen angezeigt wird, passiert nichts. + */ + public void pressDotKey() { + if(!screen.endsWith(".")) screen = screen + "."; + } + + /** + * Empfängt den Befehl der gedrückten Vorzeichenumkehrstaste ("+/-"). + * Zeigt der Bildschirm einen positiven Wert an, so wird ein "-" links angehängt, der Bildschirm + * aktualisiert und die Inhalt fortan als negativ interpretiert. + * Zeigt der Bildschirm bereits einen negativen Wert mit führendem Minus an, dann wird dieses + * entfernt und der Inhalt fortan als positiv interpretiert. + */ + public void pressNegativeKey() { + screen = screen.startsWith("-") ? screen.substring(1) : "-" + screen; + } + + /** + * Empfängt den Befehl der gedrückten "="-Taste. + * Wurde zuvor keine Operationstaste gedrückt, passiert nichts. + * Wurde zuvor eine binäre Operationstaste gedrückt und zwei Operanden eingegeben, wird das + * Ergebnis der Operation angezeigt. Falls hierbei eine Division durch Null auftritt, wird "Error" angezeigt. + * Wird die Taste weitere Male gedrückt (ohne andere Tasten dazwischen), so wird die letzte + * Operation (ggf. inklusive letztem Operand) erneut auf den aktuellen Bildschirminhalt angewandt + * und das Ergebnis direkt angezeigt. + */ + public void pressEqualsKey() { + if ((latestOperation.equals("/")) && screen.equals("0")) screen = "Error"; + else if (latestOperation.equals("*") && (screen.equals("0") || screen.equals("-0"))) screen = "0"; + else { + var result = switch (latestOperation) { + case "+" -> latestValue + Double.parseDouble(screen); + case "-" -> latestValue - Double.parseDouble(screen); + case "x" -> latestValue * Double.parseDouble(screen); + case "/" -> latestValue / Double.parseDouble(screen); + default -> throw new IllegalArgumentException(); + }; + screen = Double.toString(result); + if (screen.endsWith(".0")) screen = screen.substring(0, screen.length() - 2); + if (screen.contains(".") && screen.length() > 11) screen = screen.substring(0, 10); + } + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java new file mode 100644 index 00000000..efc7561e --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/app/src/test/java/htw/berlin/prog2/ha1/CalculatorTest.java @@ -0,0 +1,96 @@ +package htw.berlin.prog2.ha1; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@DisplayName("Retro calculator") +class CalculatorTest { + + @Test + @DisplayName("should display result after adding two positive multi-digit numbers") + void testPositiveAddition() { + Calculator calc = new Calculator(); + + calc.pressDigitKey(2); + calc.pressDigitKey(0); + calc.pressBinaryOperationKey("+"); + calc.pressDigitKey(2); + calc.pressDigitKey(0); + calc.pressEqualsKey(); + + String expected = "40"; + String actual = calc.readScreen(); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("should display result after getting the square root of two") + void testSquareRoot() { + Calculator calc = new Calculator(); + + calc.pressDigitKey(2); + calc.pressUnaryOperationKey("√"); + + String expected = "1.41421356"; + String actual = calc.readScreen(); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("should display result after subtraction two negative multi-digit numbers") + void testNegativeNumbersSubtraction() { + Calculator calc = new Calculator(); + + calc.pressDigitKey(5); + calc.pressNegativeKey(); + calc.pressBinaryOperationKey("-"); + calc.pressDigitKey(3); + calc.pressNegativeKey(); + calc.pressEqualsKey(); + + String expected = "-2"; + String actual = calc.readScreen(); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("should display 'Error' when a multi-digit number is divided by 0") + void testDivideByZero() { + Calculator calc = new Calculator(); + + calc.pressDigitKey(3); + calc.pressBinaryOperationKey("/"); + calc.pressDigitKey(0); + calc.pressEqualsKey(); + + String expected = "Error"; + String actual = calc.readScreen(); + + assertEquals(expected, actual); + } + + @Test + @DisplayName("should display 0 when a multi-digit number is multiplied by 0 or -0") + void testMultipleByZero() { + Calculator calc = new Calculator(); + + calc.pressDigitKey(5); + calc.pressBinaryOperationKey("*"); + calc.pressDigitKey(0); + calc.pressNegativeKey(); + calc.pressEqualsKey(); + + String expected = "0"; + String actual = calc.readScreen(); + + assertEquals(expected, actual); + } + + +} + diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradle/wrapper/gradle-wrapper.properties b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..ffed3a25 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradlew b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradlew new file mode 100755 index 00000000..1b6c7873 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradlew.bat b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/ha1 b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/ha1 new file mode 160000 index 00000000..4f93ded6 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/ha1 @@ -0,0 +1 @@ +Subproject commit 4f93ded6327aa84c12696a61681b791620756313 diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/settings.gradle b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/settings.gradle new file mode 100644 index 00000000..d5f1def5 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha1-main/settings.gradle @@ -0,0 +1,11 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/7.2/userguide/multi_project_builds.html + */ + +rootProject.name = 'ha1' +include('app') diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.gitattributes b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.gitattributes new file mode 100644 index 00000000..00a51aff --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.github/.keep b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.github/.keep new file mode 100644 index 00000000..e69de29b diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.github/classroom/autograding.json b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.github/classroom/autograding.json new file mode 100644 index 00000000..afbdc8e0 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.github/classroom/autograding.json @@ -0,0 +1,14 @@ +{ + "tests": [ + { + "name": "Run all tests", + "setup": "", + "run": "gradle test", + "input": "", + "output": "", + "comparison": "included", + "timeout": 10, + "points": null + } + ] +} \ No newline at end of file diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.github/workflows/classroom.yml b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.github/workflows/classroom.yml new file mode 100644 index 00000000..9e190afc --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.github/workflows/classroom.yml @@ -0,0 +1,14 @@ + name: GitHub Classroom Workflow + + on: [push] + + jobs: + build: + name: Autograding + runs-on: ubuntu-latest + steps: + - uses: actions/setup-java@v1 + with: + java-version: '16' + - uses: actions/checkout@v2 + - uses: education/autograding@v1 diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.gitignore b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.gitignore new file mode 100644 index 00000000..56cd3272 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/.gitignore @@ -0,0 +1,32 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +# IntelliJ +.idea diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/README.md b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/README.md new file mode 100644 index 00000000..01aba256 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/README.md @@ -0,0 +1,28 @@ +# Hausaufgabe Nr. 2 + +## Abgabe + +Nehmen Sie das Assignment auf Github Classroom an und wählen Sie Ihren Namen aus der Liste aus. +Dadurch wird ein (dieses) Repository für Sie erstellt. +Klonen Sie das Repo und pushen Sie Ihre Lösungen in mehreren sinnvoll zusammengefassten Commits (z.B. einer pro Teilaufgabe, es können aber auch gerne mehr sein). +Die Erstellung eines Pull Requests ist bei diesem Setup nicht notwendig. +Sie müssen Ihre Lösung bis zum 7. bzw. 11. November um 23:59 Uhr gepusht haben, alle Tests müssen grün sein, und Sie müssen spätestens in der darauf folgenden von Ihnen belegten Übungsgruppe Ihre Lösung kurz demonstrieren. + +## Aufgabenstellung + +1. Betrachten Sie die Klasse `BowlBuilder` im Paket `service`, das Interface `Bowl` und die Klasse `DummyBowlImpl` im Unterpaket `domain`, sowie den dazugehörigen Test `BowlBuilderTest`, der das Soll-Verhalten dieser Klassen in Kombination spezifiziert. + Betrachten Sie außerdem die Klasse `Ingredient`, sowie die statische Klasse `Menu` im Paket `data`, die bereits eine Reihe von Zutaten definiert. +2. Erstellen Sie zwei Klassen `PrecomputedBowl` und `DynamicallyComputedBowl`, die jeweils das Interface `Bowl` implementieren. + Beide Klassen sollen sich nach außen gleich verhalten. + Ein `PrecomputedBowl`-Objekt soll jedoch schon bei seiner Erstellung den fertig berechneten Gesamtpreis, die Gesamtkalorienzahl, sowie die Namen der Zutaten übergeben bekommen, während ein `DynamicallyComputedBowl`-Objekt bei seiner Erstellung nur eine Liste von `Ingredient`-Objekten übergeben bekommt und die jeweiligen Preis-, Kalorien- und Zutatenangaben erst zu dem Zeitpunkt berechnet, wenn die entsprechende Methode aufgerufen wird. + Erstellen Sie, wenn es Ihnen hilft, einfache neue Unit-Tests, die testen, ob Ihre Bowl-Implementierungen so funktionieren, wie sie sollen. +3. Implementieren Sie nun in der `BowlBuilder`-Klasse die drei Methoden `add`, `buildPrecomputed` und `buildDynamically` so, dass sie die jeweilige Bowl-Implementierung nutzen (statt der `DummyBowlImpl`), um die Testfälle im `BowlBuilderTest` grün zu machen (ohne die Tests zu verändern!). +4. Erstellen Sie mindesten einen neuen Testfall, der beschreibt, dass ein Bowl nur mit mindestens zwei Zutaten gebaut werden kann und ansonsten (also bei weniger als zwei Zutaten) eine `IllegalBowlException` beim Aufruf der jeweiligen build-Methode geworfen wird. +5. Betrachten Sie die Klasse `SimpleInputParser` und extrahieren Sie daraus ein neues Interface namens `InputParser` und lassen dieses vom `SimpleInputParser` implementieren. Ändern Sie dann überall im Code, wo bisher der Typ `SimpleInputParser` in Variablendeklarationen verwendet wurde, die Deklaration so, dass stattdessen der Interface-Typ `InputParser` verwendet wird. + +## Hinweise + +- Allgemein: Sie können die Anwendung über die Klasse `BowlBotApp` starten, um das aktuelle Verhalten des Gesamtprogramms auszuprobieren. +- Zu Teilaufgabe 2: Beachten Sie bei beiden Bowl-Implementierungen die Grundsätze der Datenkapselung. +- Zu Teilaufgabe 3: Bedenken Sie, dass es einen Unterschied macht, ob Sie eine Referenz einer Liste übergeben oder eine Kopie einer Liste erstellen und diese übergeben. +- Zu Teilaufgabe 4: Die JUnit-Methode zum Prüfen, ob eine erwartete Exception geworfen wird, heißt `assertThrows` und wird mit der erwarteten Exception-Klasse (`ErwarteterTyp.class`) sowie einer Lambda-Funktion nach dem Schema `() -> AufrufInDemDieExceptionFliegenSoll` parametrisiert. diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/build.gradle b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/build.gradle new file mode 100644 index 00000000..b18ebc88 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/build.gradle @@ -0,0 +1,77 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.logging.TestLogEvent + +plugins { + // Apply the application plugin to add support for building a CLI application in Java. + id 'application' +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + // Use JUnit Jupiter API for testing. + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.1' + + // Mockito for mocking dependencies + testImplementation 'org.mockito:mockito-core:3.9.0' + + // Use JUnit Jupiter Engine for testing. + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' + + // This dependency is used by the application. + implementation 'com.google.guava:guava:30.0-jre' +} + +application { + // Define the main class for the application. + mainClass = 'htw.berlin.wi.prog2.BowlBotApp' +} + +tasks.named('test') { + // Use junit platform for unit tests. + useJUnitPlatform() +} + +apply plugin: 'java' +compileJava {options.encoding = "UTF-8"} +compileTestJava {options.encoding = "UTF-8"} + +// https://stackoverflow.com/questions/3963708/gradle-how-to-display-test-results-in-the-console-in-real-time#answer-36130467 +tasks.withType(Test) { + testLogging { + // set options for log level LIFECYCLE + events TestLogEvent.FAILED, + TestLogEvent.PASSED, + TestLogEvent.SKIPPED, + TestLogEvent.STANDARD_OUT + exceptionFormat TestExceptionFormat.FULL + showExceptions true + showCauses true + showStackTraces true + + // set options for log level DEBUG and INFO + debug { + events TestLogEvent.STARTED, + TestLogEvent.FAILED, + TestLogEvent.PASSED, + TestLogEvent.SKIPPED, + TestLogEvent.STANDARD_ERROR, + TestLogEvent.STANDARD_OUT + exceptionFormat TestExceptionFormat.FULL + } + info.events = debug.events + info.exceptionFormat = debug.exceptionFormat + + afterSuite { desc, result -> + if (!desc.parent) { // will match the outermost suite + def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} passed, ${result.failedTestCount} failed, ${result.skippedTestCount} skipped)" + def startItem = '| ', endItem = ' |' + def repeatLength = startItem.length() + output.length() + endItem.length() + println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength)) + } + } + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/BowlBotApp.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/BowlBotApp.java new file mode 100644 index 00000000..0a7c2ca6 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/BowlBotApp.java @@ -0,0 +1,18 @@ +/* + * This Java source file was generated by the Gradle 'init' task. + */ +package htw.berlin.wi.prog2; + +import htw.berlin.wi.prog2.service.SimpleInputParser; +import htw.berlin.wi.prog2.service.BowlBuilder; +import htw.berlin.wi.prog2.ui.CommandLineUI; +import htw.berlin.wi.prog2.ui.UserInputWrapper; + +public class BowlBotApp { + public static void main(String[] args) { + SimpleInputParser parser = new SimpleInputParser(); + BowlBuilder builder = new BowlBuilder(); + CommandLineUI clui = new CommandLineUI(new UserInputWrapper(System.in, System.out), builder, parser); + clui.launch(); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/data/Menu.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/data/Menu.java new file mode 100644 index 00000000..fd70d9f9 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/data/Menu.java @@ -0,0 +1,41 @@ +package htw.berlin.wi.prog2.data; + +import htw.berlin.wi.prog2.domain.Ingredient; + +import java.util.*; + +// Eine statische Datenbank-Klasse +public class Menu { + private Menu() {} + + public static Map base = Map.of( + 1, new Ingredient("Reis", 0.6, 120), + 2, new Ingredient("Quinoa", 0.7, 100)); + public static Map protein = Map.of( + 3, new Ingredient("Lachs", 0.9, 90), + 4, new Ingredient("Tofu", 0.9, 80)); + public static Map topping = Map.of( + 5, new Ingredient("Tomate", 0.4, 20), + 6, new Ingredient("Edamame", 0.6, 30), + 7, new Ingredient("Avocado", 0.6, 40), + 8, new Ingredient("Zwiebeln", 0.3, 20)); + public static Map sauces = Map.of( + 9, new Ingredient("Mayo", 0.3, 40), + 10, new Ingredient("Sesam", 0.3, 40)); + + public static Map getAllArticles() { + Map articles = new HashMap<>(); + articles.putAll(base); + articles.putAll(protein); + articles.putAll(topping); + articles.putAll(sauces); + return articles; + } + + public static List getAllArticleNames() { + Collection articles = getAllArticles().values(); + List names = new ArrayList<>(); + for (Ingredient art : articles) names.add(art.getName()); + return names; + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/Bowl.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/Bowl.java new file mode 100644 index 00000000..44b950b3 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/Bowl.java @@ -0,0 +1,9 @@ +package htw.berlin.wi.prog2.domain; + +import java.util.List; + +public interface Bowl { + double calculatePrice(); + int calculateCalories(); + List getIngredientNames(); +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/DummyBowlImpl.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/DummyBowlImpl.java new file mode 100644 index 00000000..f5ef9f72 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/DummyBowlImpl.java @@ -0,0 +1,21 @@ +package htw.berlin.wi.prog2.domain; + +import java.util.List; + +public class DummyBowlImpl implements Bowl { + + @Override + public double calculatePrice() { + return 0.01; + } + + @Override + public int calculateCalories() { + return 10000; + } + + @Override + public List getIngredientNames() { + return List.of("Käse", "Käse", "Käse"); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/DynamicallyComputedBowl.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/DynamicallyComputedBowl.java new file mode 100644 index 00000000..57eff68a --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/DynamicallyComputedBowl.java @@ -0,0 +1,13 @@ +package htw.berlin.wi.prog2.domain; + +import java.util.Collections; +import java.util.List; + +public class DynamicallyComputedBowl { + private final List ingredients; + + public DynamicallyComputedBowl(List ingredients){ + //this.ingredients = Collections.unmodifiableList(ingredients); + } + +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/Ingredient.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/Ingredient.java new file mode 100644 index 00000000..cd8b826a --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/Ingredient.java @@ -0,0 +1,25 @@ +package htw.berlin.wi.prog2.domain; + +public class Ingredient { + private final String name; + private final double price; + private final int calories; + + public Ingredient(String name, double price, int calories) { + this.name = name; + this.price = price; + this.calories = calories; + } + + public String getName() { + return name; + } + + public double getPrice() { + return price; + } + + public int getCalories() { + return calories; + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/PrecomputedBowl.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/PrecomputedBowl.java new file mode 100644 index 00000000..a94fa827 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/domain/PrecomputedBowl.java @@ -0,0 +1,16 @@ +package htw.berlin.wi.prog2.domain; + +import java.util.List; + +public class PrecomputedBowl { + private final double totalPrice; + private final int totalCalories; + private final List ingredientNames; + + public PrecomputedBowl(double totalPrice, int totalCalories, List ingredientName){ + this.totalPrice = totalPrice; + this.totalCalories = totalCalories; + this.ingredientNames = ingredientName; + } + +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/BowlBuilder.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/BowlBuilder.java new file mode 100644 index 00000000..382a91fc --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/BowlBuilder.java @@ -0,0 +1,23 @@ +package htw.berlin.wi.prog2.service; + +import htw.berlin.wi.prog2.domain.Ingredient; +import htw.berlin.wi.prog2.domain.DummyBowlImpl; +import htw.berlin.wi.prog2.domain.Bowl; + +public class BowlBuilder { + + public BowlBuilder add(Ingredient ingredient) { + // TODO hier die Annahme von Zutaten implementieren + return this; // die Rückgabe von this sollte beibehalten bleiben (siehe Benutzung im BowlBuilderTest) + } + + public Bowl buildPrecomputed() { + // TODO hier stattdessen die neue Klasse PrecomputedBowl verwenden + return new DummyBowlImpl(); + } + + public Bowl buildDynamicallyComputed() { + // TODO hier stattdessen die neue Klasse DynamicallyComputedBowl verwenden + return new DummyBowlImpl(); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/IllegalBowlException.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/IllegalBowlException.java new file mode 100644 index 00000000..025642fa --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/IllegalBowlException.java @@ -0,0 +1,7 @@ +package htw.berlin.wi.prog2.service; + +public class IllegalBowlException extends RuntimeException { + public IllegalBowlException(String message) { + super(message); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/SimpleInputParser.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/SimpleInputParser.java new file mode 100644 index 00000000..4eb12cc4 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/service/SimpleInputParser.java @@ -0,0 +1,19 @@ +package htw.berlin.wi.prog2.service; + +import htw.berlin.wi.prog2.data.Menu; +import htw.berlin.wi.prog2.domain.Ingredient; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class SimpleInputParser { + public List ingredientsFromInput(String inputLine) { + List result = new ArrayList<>(); + for (Ingredient ing : Menu.getAllArticles().values()) { + if(inputLine.contains(ing.getName())) result.add(ing); + } + return result; + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/ui/CommandLineUI.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/ui/CommandLineUI.java new file mode 100644 index 00000000..cd7658c1 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/ui/CommandLineUI.java @@ -0,0 +1,38 @@ +package htw.berlin.wi.prog2.ui; + +import htw.berlin.wi.prog2.data.Menu; +import htw.berlin.wi.prog2.domain.Ingredient; +import htw.berlin.wi.prog2.domain.Bowl; +import htw.berlin.wi.prog2.service.SimpleInputParser; +import htw.berlin.wi.prog2.service.BowlBuilder; + +import java.util.*; + +public class CommandLineUI { + private final UserInputWrapper input; + private final BowlBuilder builder; + private final SimpleInputParser parser; + + public CommandLineUI(UserInputWrapper uiw, BowlBuilder sb, SimpleInputParser ip) { + input = uiw; + builder = sb; + parser = ip; + } + + public String launch() { + String inputLine = input.ask("Willkommen beim Bowl-Bot! Was möchtest du gerne bestellen?"); + while (!(inputLine.equals("Bestellung abschliessen") || inputLine.equals("Auf Wiedersehen"))) { + List ingredients = parser.ingredientsFromInput(inputLine); + if(ingredients.isEmpty()) { + inputLine = input.ask("Entschuldigung, ich habe dich nicht verstanden. Wähle aus folgenden Zutaten: " + + Menu.getAllArticleNames()); + } else { + for (Ingredient ing : ingredients) builder.add(ing); + Bowl bowl = builder.buildPrecomputed(); + inputLine = input.ask("In Ordnung. Deine Bowl mit " + bowl.getIngredientNames() + + " kostet " + bowl.calculatePrice() + " Euro. Willst du die Bestellung abschliessen?"); + } + } + return inputLine; + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/ui/UserInputWrapper.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/ui/UserInputWrapper.java new file mode 100644 index 00000000..96c22522 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/main/java/htw/berlin/wi/prog2/ui/UserInputWrapper.java @@ -0,0 +1,20 @@ +package htw.berlin.wi.prog2.ui; + +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Scanner; + +public class UserInputWrapper { + private final Scanner scanner; + private final PrintStream out; + + public UserInputWrapper(InputStream in, PrintStream out) { + scanner = new Scanner(in); + this.out = out; + } + + public String ask(String message) { + out.println(message); + return scanner.nextLine(); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/service/BowlBuilderTest.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/service/BowlBuilderTest.java new file mode 100644 index 00000000..101b7ff9 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/service/BowlBuilderTest.java @@ -0,0 +1,87 @@ +package htw.berlin.wi.prog2.service; + +import htw.berlin.wi.prog2.domain.Ingredient; +import htw.berlin.wi.prog2.domain.Bowl; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; + +class BowlBuilderTest { + + private final BowlBuilder builder = new BowlBuilder(); + + private final Ingredient lachs = new Ingredient("Lachs", 0.01, 2000); + private final Ingredient reis = new Ingredient("Reis", 0.02, 1000); + + @Test + @DisplayName("can build a precomputed bowl with two ingredients") + void buildABowl() { + Bowl bowl = builder.add(reis).add(lachs).buildPrecomputed(); + + assertEquals(List.of("Reis", "Lachs"), bowl.getIngredientNames()); + assertEquals(0.03, bowl.calculatePrice()); + assertEquals(3000, bowl.calculateCalories()); + } + + @Test + @DisplayName("can build two precomputed bowls after another without mixing things up") + void buildTwoBowls() { + Bowl bowl1 = builder.add(reis).add(lachs).buildPrecomputed(); + Bowl bowl2 = builder.add(reis).add(reis).buildPrecomputed(); + + assertEquals(List.of("Reis", "Lachs"), bowl1.getIngredientNames()); + assertEquals(List.of("Reis", "Reis"), bowl2.getIngredientNames()); + } + + @Test + @DisplayName("can build a dynamically computed bowl with two ingredients") + void buildABowlDynamically() { + Bowl bowl = builder.add(reis).add(lachs).buildDynamicallyComputed(); + + assertEquals(List.of("Reis", "Lachs"), bowl.getIngredientNames()); + assertEquals(0.03, bowl.calculatePrice()); + assertEquals(3000, bowl.calculateCalories()); + } + + @Test + @DisplayName("can build two dynamically computed bowles after another without mixing things up") + void buildTwoBowlesDynamically() { + Bowl bowl1 = builder.add(reis).add(lachs).buildDynamicallyComputed(); + Bowl bowl2 = builder.add(reis).add(reis).buildDynamicallyComputed(); + + assertEquals(List.of("Reis", "Lachs"), bowl1.getIngredientNames()); + assertEquals(List.of("Reis", "Reis"), bowl2.getIngredientNames()); + } + + // Diese folgenden Tests sind keine typischen Tests, da sie testen, wie Sie etwas im Detail implementiert haben + @Test + @DisplayName("a dynamically computed bowl should have only one field, which is the list of ingredients") + void buildDynamicallyComputed() { + Bowl bowl = builder.add(reis).add(lachs).buildDynamicallyComputed(); + + var clazz = bowl.getClass(); + var fields = clazz.getDeclaredFields(); + assertEquals(1, fields.length); + assertEquals("java.util.List", fields[0].getGenericType().getTypeName()); + } + + @Test + @DisplayName("a precomputed bowl should have three field for the precomputed values") + void buildPrecomputed() { + Bowl bowl = builder.add(reis).add(lachs).buildPrecomputed(); + + var clazz = bowl.getClass(); + var fields = clazz.getDeclaredFields(); + assertEquals(3, fields.length); + assertTrue(Arrays.stream(fields).map(Field::getType).collect(Collectors.toList()).contains(int.class)); + assertTrue(Arrays.stream(fields).map(Field::getType).collect(Collectors.toList()).contains(double.class)); + } + + // TODO hier mind. einen Test hinzufügen, der das korrekte Werfen der IllegalBowlException testet (assertThrows) +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/service/SimpleInputParserTest.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/service/SimpleInputParserTest.java new file mode 100644 index 00000000..436249b4 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/service/SimpleInputParserTest.java @@ -0,0 +1,32 @@ +package htw.berlin.wi.prog2.service; + +import htw.berlin.wi.prog2.data.Menu; +import htw.berlin.wi.prog2.domain.Ingredient; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class SimpleInputParserTest { + + @Test + @DisplayName("can detect ingredients in text input") + void ingredientsFromInput() { + // System under test (SUT) + SimpleInputParser parser = new SimpleInputParser(); + + // Test-Daten + String input = "Ich hätte gerne eine Bowl mit Quinoa, Lachs, Tomate und Mayo."; + Ingredient quinoa = Menu.base.get(2); + Ingredient lachs = Menu.protein.get(3); + Ingredient tomate = Menu.topping.get(5); + Ingredient mayo = Menu.sauces.get(9); + + List expected = List.of(quinoa, lachs, tomate, mayo); + List actual = parser.ingredientsFromInput(input); + + assertEquals(expected, actual); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/ui/CommandLineUITest.java b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/ui/CommandLineUITest.java new file mode 100644 index 00000000..71f8097b --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/app/src/test/java/htw/berlin/wi/prog2/ui/CommandLineUITest.java @@ -0,0 +1,65 @@ +package htw.berlin.wi.prog2.ui; + +import htw.berlin.wi.prog2.domain.DummyBowlImpl; +import htw.berlin.wi.prog2.domain.Ingredient; +import htw.berlin.wi.prog2.service.SimpleInputParser; +import htw.berlin.wi.prog2.service.BowlBuilder; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.AdditionalMatchers.not; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +// testing approach inspired from https://stackoverflow.com/questions/6415728/junit-testing-with-simulated-user-input#answer-6416591 +public class CommandLineUITest { + + @Test + @DisplayName("text input loop should get a first input line") + void canGetInput() { + String initialQuestion = "Was möchtest du gerne bestellen?"; + UserInputWrapper input = mock(UserInputWrapper.class); + when(input.ask(contains(initialQuestion))).thenReturn("Ich bin mir nicht sicher"); + when(input.ask(not(contains(initialQuestion)))).thenReturn("Auf Wiedersehen"); + + BowlBuilder builder = mock(BowlBuilder.class); + when(builder.add(any())).thenReturn(builder); + when(builder.buildPrecomputed()).thenReturn(new DummyBowlImpl()); + + SimpleInputParser parser = mock(SimpleInputParser.class); + when(parser.ingredientsFromInput(anyString())).thenReturn(List.of( + new Ingredient("Käse", 0.01, 2000) + )); + + CommandLineUI ui = new CommandLineUI(input, builder, parser); + + assertEquals("Auf Wiedersehen", ui.launch()); + } + + @Test + @DisplayName("calls the parser with correct input line") + void canCallParser() { + String initialQuestion = "Was möchtest du gerne bestellen?"; + String inputLine = "Ich hätte gerne eine Qunioa-Bowl mit Lachs"; + UserInputWrapper input = mock(UserInputWrapper.class); + when(input.ask(contains(initialQuestion))).thenReturn(inputLine); + when(input.ask(not(contains(initialQuestion)))).thenReturn("Auf Wiedersehen"); + + BowlBuilder builder = mock(BowlBuilder.class); + when(builder.add(any())).thenReturn(builder); + when(builder.buildPrecomputed()).thenReturn(new DummyBowlImpl()); + + SimpleInputParser parser = mock(SimpleInputParser.class); + when(parser.ingredientsFromInput(anyString())).thenReturn(List.of( + new Ingredient("Käse", 0.01, 2000) + )); + + CommandLineUI ui = new CommandLineUI(input, builder, parser); + + assertEquals("Auf Wiedersehen", ui.launch()); + verify(parser).ingredientsFromInput(inputLine); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradle/wrapper/gradle-wrapper.properties b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..ffed3a25 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradlew b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradlew new file mode 100644 index 00000000..4f906e0c --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradlew.bat b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/ha2-CaoNgocYen b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/ha2-CaoNgocYen new file mode 160000 index 00000000..22d59ff0 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/ha2-CaoNgocYen @@ -0,0 +1 @@ +Subproject commit 22d59ff0c5329ca3138cda8a77e17cde92aac8b7 diff --git a/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/settings.gradle b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/settings.gradle new file mode 100644 index 00000000..c8605a39 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/ha2-CaoNgocYen-main/settings.gradle @@ -0,0 +1,11 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/7.0/userguide/multi_project_builds.html + */ + +rootProject.name = 'bowl-bot' +include('app') diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.gitattributes b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.gitattributes new file mode 100644 index 00000000..00a51aff --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.github/.keep b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.github/.keep new file mode 100644 index 00000000..e69de29b diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.github/classroom/autograding.json b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.github/classroom/autograding.json new file mode 100644 index 00000000..afbdc8e0 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.github/classroom/autograding.json @@ -0,0 +1,14 @@ +{ + "tests": [ + { + "name": "Run all tests", + "setup": "", + "run": "gradle test", + "input": "", + "output": "", + "comparison": "included", + "timeout": 10, + "points": null + } + ] +} \ No newline at end of file diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.github/workflows/classroom.yml b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.github/workflows/classroom.yml new file mode 100644 index 00000000..16807db9 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.github/workflows/classroom.yml @@ -0,0 +1,14 @@ + name: GitHub Classroom Workflow + + on: [push] + + jobs: + build: + name: Autograding + runs-on: ubuntu-latest + steps: + - uses: actions/setup-java@v1 + with: + java-version: '14' + - uses: actions/checkout@v2 + - uses: education/autograding@v1 diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.gitignore b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.gitignore new file mode 100644 index 00000000..b7f8b3de --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/.gitignore @@ -0,0 +1,32 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +# IntelliJ +.idea \ No newline at end of file diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/QUESTIONS.md b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/QUESTIONS.md new file mode 100644 index 00000000..1a365bfa --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/QUESTIONS.md @@ -0,0 +1,17 @@ +# Klausurfragen + +### Name und Matrikelnummer +^-- Bitte eintragen und 1. Commit pushen, 2. Commit spätestens nach 30 Minuten pushen sonst 5.0 + +## Fragen zum Code (je 6 Punkte) + +### Nennen Sie zwei Klassen, deren Objekte einen Zustand haben und zwei Klassen, deren Objekte keinen Zustand haben. + +### ... + + +## Theoretische Fragen (je 3 Punkte) + +### Was sind die Hauptunterschiede zwischen Java-Interface und abstrakter Klasse? + +### ... diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/README.md b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/README.md new file mode 100644 index 00000000..244b5d71 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/README.md @@ -0,0 +1,24 @@ +# Klausur Angewandte Programmierung WS20/21 + +Die Klausur besteht aus zwei Teilen: einem praktischen und einem theoretischen Teil. +Sie haben insgesamt 90 Minuten Zeit für die Bearbeitung, massgeblich ist der Zeitstempel des entsprechenden Commits. +Sie müssen Ihre Abgabe auf mindestens vier Commits aufteilen (z.B. 1x für Antworten zum Code, 1x für Test-Code, 1x für allgemeine Antworten, 1x für Implementierungs-Code), ansonsten gibt es Punktabzug von bis zu 20 Punkten. +Es handelt sich um eine Open-Book-Klausur, Sie müssen jedoch nicht offensichtliche Quellen ausreichend kennzeichnen und dürfen keine fremde Leistung als Ihre eigene darstellen. + +## Theoretischer Teil (60 Punkte) + +Beantworten Sie die Fragen, die Sie in der Datei QUESTIONS.md finden. +Die Fragen beziehen sich teilweise auf den Code in diesem Repository. +Schreiben Sie Ihre Antworten direkt in diese Datei unter die jeweilige Frage. +Wenn sinnvoll, schreiben Sie Freitext, jedoch höchstens drei Sätze pro Frage (in der Regel weniger). +Bei manchen Fragen ist eine Beantwortung als Auflistung sinnvoller, aber achten Sie hier darauf, dass es unmissverständlich ist, was Sie auflisten. +Reichen Sie das Ergebnis per Git Commit & Push ein. +Sie können die Beantwortung über mehrere Commits verteilen und Ihre Antworten bis zum Ende der Bearbeitungszeit korrigieren. + + +## Praktischer Teil (60 Punkte) + +Betrachten Sie die Klasse `Accounting` im Package `/service/accounting`, sowie das Interface `ReadOnlyInvoice`. +Implementieren Sie die zwei Methoden `createInvoice` und `calculateRevenue` so wie durch das entsprechende JavaDoc spezifiziert und erstellen Sie dafür eine Klasse `Invoice`, welche `ReadOnlyInvoice` implementiert (30 Punkte). +Erstellen Sie ausserdem für beide Methoden jeweils mindestens zwei automatische Testfälle, welche unterschiedliches Verhalten testen, also insgesamt mindestens vier (30 Punkte). +Es kann sinnvoll sein die Tests teilweise vor der Implementierung der zu testenden Methode zu erstellen (test-driven development), dies ist jedoch keine Muss. \ No newline at end of file diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/build.gradle.kts b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/build.gradle.kts new file mode 100644 index 00000000..366503ab --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/build.gradle.kts @@ -0,0 +1,62 @@ +/* + * This file was originally generated by the Gradle 'init' task. + * + * This generated file contains a sample Java project to get you started. + * For more details take a look at the Java Quickstart chapter in the Gradle + * User Manual available at https://docs.gradle.org/6.6.1/userguide/tutorial_java_projects.html + */ + +import org.gradle.api.tasks.testing.logging.TestLogEvent + +tasks { + test { + testLogging { + events.addAll(setOf( + TestLogEvent.PASSED, + TestLogEvent.SKIPPED, + TestLogEvent.FAILED, + TestLogEvent.STANDARD_OUT, + TestLogEvent.STANDARD_ERROR + )) + setExceptionFormat("full") + } + } +} + +plugins { + // Apply the java plugin to add support for Java + java + + // Apply the application plugin to add support for building a CLI application. + application +} + +repositories { + // Use jcenter for resolving dependencies. + // You can declare any Maven/Ivy/file repository here. + jcenter() +} + +dependencies { + // This dependency is used by the application. + implementation("com.google.guava:guava:29.0-jre") + + // Use JUnit Jupiter API for testing. + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") + + // Use JUnit Jupiter Engine for testing. + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0") + + // Use Mockito for mocking implementations in tests + testImplementation("org.mockito:mockito-core:3.6.0") +} + +application { + // Define the main class for the application. + mainClassName = "htw.berlin.BurgerApplication" +} + +val test by tasks.getting(Test::class) { + // Use junit platform for unit tests + useJUnitPlatform() +} \ No newline at end of file diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradle/wrapper/gradle-wrapper.properties b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..f371643e --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradlew b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradlew new file mode 100644 index 00000000..4f906e0c --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradlew.bat b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/settings.gradle.kts b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/settings.gradle.kts new file mode 100644 index 00000000..9c20cf6f --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/settings.gradle.kts @@ -0,0 +1,10 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/6.6.1/userguide/multi_project_builds.html + */ + +rootProject.name = "Burger Bot" diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/BurgerApplication.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/BurgerApplication.java new file mode 100644 index 00000000..e335ae02 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/BurgerApplication.java @@ -0,0 +1,22 @@ +package htw.berlin; + +import htw.berlin.service.accounting.Accounting; +import htw.berlin.service.BurgerBuilderImpl; +import htw.berlin.service.kitchen.Kitchen; +import htw.berlin.ui.ChatbotUI; +import htw.berlin.ui.CommaAndWhitespaceSplittingInputParser; +import htw.berlin.ui.UserInputWrapper; + +public class BurgerApplication { + + public static void main(String[] args) { + var parser = new CommaAndWhitespaceSplittingInputParser(); + var builder = new BurgerBuilderImpl(); + var input = new UserInputWrapper(System.in, System.out); + var ui = new ChatbotUI(input, builder, parser); + var kitchen = new Kitchen(ui); + var accounting = new Accounting(ui, input); + ui.launch(); + } +} + diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/Burger.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/Burger.java new file mode 100644 index 00000000..ccd43cdf --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/Burger.java @@ -0,0 +1,9 @@ +package htw.berlin.domain; + +import java.math.BigDecimal; +import java.util.List; + +public interface Burger { + BigDecimal calculatePrice(); + List getIngredients(); +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/BurgerImpl.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/BurgerImpl.java new file mode 100644 index 00000000..f6317dce --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/BurgerImpl.java @@ -0,0 +1,32 @@ +package htw.berlin.domain; + +import java.math.BigDecimal; +import java.util.List; + +public class BurgerImpl implements Burger { + + private final List ingredients; + + public BurgerImpl(List ingredients) { + this.ingredients = ingredients; + } + + @Override + public BigDecimal calculatePrice() { + var result = new BigDecimal("0.00"); + for (Ingredient ingredient : ingredients) { + result = result.add(ingredient.getPrice()); + } + return result; + } + + @Override + public List getIngredients() { + return ingredients; + } + + @Override + public String toString() { + return ingredients.toString(); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/Ingredient.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/Ingredient.java new file mode 100644 index 00000000..78913fb9 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/Ingredient.java @@ -0,0 +1,9 @@ +package htw.berlin.domain; + +import java.math.BigDecimal; + +public interface Ingredient { + String getName(); + BigDecimal getPrice(); + double getCalories(); +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/IngredientImpl.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/IngredientImpl.java new file mode 100644 index 00000000..a7e19c31 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/domain/IngredientImpl.java @@ -0,0 +1,36 @@ +package htw.berlin.domain; + +import java.math.BigDecimal; + +public class IngredientImpl implements Ingredient { + + private String name; + private BigDecimal price; + private double calories; + + public IngredientImpl(String name, BigDecimal price, double calories) { + this.name = name; + this.price = price; + this.calories = calories; + } + + @Override + public String getName() { + return name; + } + + @Override + public BigDecimal getPrice() { + return price; + } + + @Override + public double getCalories() { + return calories; + } + + @Override + public String toString() { + return name; + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/ArticleInfos.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/ArticleInfos.java new file mode 100644 index 00000000..d2e52f8e --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/ArticleInfos.java @@ -0,0 +1,46 @@ +package htw.berlin.service; + +import htw.berlin.domain.Ingredient; +import htw.berlin.domain.IngredientImpl; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +public class ArticleInfos { + + private ArticleInfos() {} + + private static ArticleInfos theInstance = null; + + public static ArticleInfos getInstance() { + if(theInstance == null) theInstance = new ArticleInfos(); + return theInstance; + } + + public Map buns = Map.of( + 100, new IngredientImpl("Burgerbrot", new BigDecimal("1.50"), 300), + 200, new IngredientImpl("Ciabatta", new BigDecimal("1.90"), 250)); + public Map patties = Map.of( + 300, new IngredientImpl("Rindfleisch", new BigDecimal("4.50"), 200), + 400, new IngredientImpl("Falafel", new BigDecimal("3.50"), 150)); + public Map salads = Map.of( + 500, new IngredientImpl("Eisbergsalat", new BigDecimal("0.40"), 20), + 600, new IngredientImpl("Rucolasalat", new BigDecimal("0.60"), 25)); + public Map veggies = Map.of( + 700, new IngredientImpl("Tomate", new BigDecimal("0.70"), 15), + 800, new IngredientImpl("Gurke", new BigDecimal("0.65"), 12)); + public Map sauces = Map.of( + 900, new IngredientImpl("Ketchup", new BigDecimal("0.25"), 30), + 1000, new IngredientImpl("Mayo", new BigDecimal("0.30"), 40)); + + public Map getAllArticles() { + Map articles = new HashMap<>(); + articles.putAll(buns); + articles.putAll(patties); + articles.putAll(salads); + articles.putAll(veggies); + articles.putAll(sauces); + return articles; + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/ArticleInfosToMenuAdapter.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/ArticleInfosToMenuAdapter.java new file mode 100644 index 00000000..cf8db57f --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/ArticleInfosToMenuAdapter.java @@ -0,0 +1,26 @@ +package htw.berlin.service; + +import java.util.Map; +import java.util.stream.Collectors; + + public class ArticleInfosToMenuAdapter implements IMenu { + + private ArticleInfos infos; + + public ArticleInfosToMenuAdapter(ArticleInfos infos) { + this.infos = infos; + } + + @Override + public Map getAllArticles() { + return infos.getAllArticles().entrySet().stream().collect(Collectors.toMap( + e -> e.getValue().getName(), + e -> e.getKey())); + } + + @Override + public String printAllArticles() { + return getAllArticles().keySet().toString(); + } + } + diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/BurgerBuilder.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/BurgerBuilder.java new file mode 100644 index 00000000..e31c18f0 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/BurgerBuilder.java @@ -0,0 +1,10 @@ +package htw.berlin.service; + +import htw.berlin.domain.Burger; + +import java.util.List; + +public interface BurgerBuilder { + boolean addIngredientsById(List ids); + Burger build(); +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/BurgerBuilderImpl.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/BurgerBuilderImpl.java new file mode 100644 index 00000000..7ce67f1a --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/BurgerBuilderImpl.java @@ -0,0 +1,32 @@ +package htw.berlin.service; + +import htw.berlin.domain.Burger; +import htw.berlin.domain.BurgerImpl; +import htw.berlin.domain.Ingredient; +import htw.berlin.domain.IngredientImpl; + +import java.util.ArrayList; +import java.util.List; + +public class BurgerBuilderImpl implements BurgerBuilder { + + private final List ingredients; + + public BurgerBuilderImpl() { + this.ingredients = new ArrayList<>(); + } + + @Override + public boolean addIngredientsById(List ids) { + for (Integer id : ids) { + var info = ArticleInfos.getInstance().getAllArticles().get(id); + ingredients.add(new IngredientImpl(info.getName(), info.getPrice(), info.getCalories())); + } + return true; + } + + @Override + public Burger build() { + return new BurgerImpl(ingredients); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/IMenu.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/IMenu.java new file mode 100644 index 00000000..a1bb3516 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/IMenu.java @@ -0,0 +1,9 @@ +package htw.berlin.service; + +import java.util.Map; + +public interface IMenu { + Map getAllArticles(); + + String printAllArticles(); +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/Observer.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/Observer.java new file mode 100644 index 00000000..13758acd --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/Observer.java @@ -0,0 +1,5 @@ +package htw.berlin.service; + +public interface Observer { + void update(); +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/accounting/Accounting.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/accounting/Accounting.java new file mode 100644 index 00000000..4a445365 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/accounting/Accounting.java @@ -0,0 +1,64 @@ +package htw.berlin.service.accounting; + +import htw.berlin.domain.Burger; +import htw.berlin.service.Observer; +import htw.berlin.ui.ChatbotUI; +import htw.berlin.ui.UserInputWrapper; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDate; +import java.util.*; + +public class Accounting implements Observer { + private ChatbotUI ui; + private UserInputWrapper uiw; + + private Map> invoicesByYear = new HashMap<>(); + + public Accounting(ChatbotUI ui, UserInputWrapper uiw) { + this.ui = ui; + this.uiw = uiw; + ui.addObserver(this); + } + + /** nur da, um die Methoden createInvoice und calculateRevenue testen zu können, ohne ChatbotUI mocken zu müssen */ + public Accounting() { } + + @Override + public void update() { + Burger order = ui.getLatestOrder(); + LocalDate today = LocalDate.from(LocalDate.now()); + ReadOnlyInvoice invoice = createInvoice(order, today); + if(invoice != null) { + int year = invoice.getDate().getYear(); + if (!invoicesByYear.containsKey(year)) invoicesByYear.put(year, new HashSet<>()); + invoicesByYear.get(year).add(invoice); + } + uiw.state("Nettoumsatz in " + today.getYear() + " soweit: " + calculateRevenue(invoicesByYear, today.getYear())); + } + + /** + * Erzeugt eine Rechnung für die Bestellung eines Burgers. + * Liegt das Datum der Bestellung zwischen dem 1. Juni 2020 und dem 31. Dezember 2020 + * werden 5% Mehrwertsteuer (engl. VAT) berechnet, ansonsten 7%. + * @param burger Der Burger, der bestellt wurde und für den eine Rechnung erstellt werden soll + * @param date Datum der Rechnungsstellung, ohne Uhrzeit. + * @return Die Rechnung für den übergebenen Burger + */ + public ReadOnlyInvoice createInvoice(Burger burger, LocalDate date) { + return null; + } + + /** + * Berechnet den Nettoumsatz eines Jahres aus einer gegebenen Menge von Rechnungen. + * D.h. die Summe aller Rechnungen des spezifizierten Jahres ohne Mehrwertsteuer (engl. VAT). + * @param allYears Alle Rechnungen, die berücksichtigt werden sollen, aufgelistet nach Jahren + * @param year Das Jahr für welches der Nettoumsatz berechnet werden soll + * @return Der aufaddierte Nettoumsatz des spezifizierten Jahres + */ + public BigDecimal calculateRevenue(Map> allYears, Integer year) { + return new BigDecimal(BigInteger.ZERO); + } + +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/accounting/ReadOnlyInvoice.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/accounting/ReadOnlyInvoice.java new file mode 100644 index 00000000..71f5b70b --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/accounting/ReadOnlyInvoice.java @@ -0,0 +1,23 @@ +package htw.berlin.service.accounting; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Date; + +public interface ReadOnlyInvoice { + + /** + * @return das Datum der Rechnungsstellung, ohne Uhrzeit + */ + LocalDate getDate(); + + /** + * @return Gesamtbetrag der Rechnung inkl. angefallener Mehrwertsteuer. + */ + BigDecimal getTotalAmount(); + + /** + * @return Nur der Mehrwertsteuer-Anteil des Gesamtbetrags. + */ + BigDecimal getVatIncluded(); +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/kitchen/Kitchen.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/kitchen/Kitchen.java new file mode 100644 index 00000000..73ae7e3d --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/service/kitchen/Kitchen.java @@ -0,0 +1,25 @@ +package htw.berlin.service.kitchen; + +import htw.berlin.domain.Burger; +import htw.berlin.service.Observer; +import htw.berlin.ui.ChatbotUI; + +public class Kitchen implements Observer { + + private ChatbotUI ui; + + public Kitchen(ChatbotUI ui) { + this.ui = ui; + ui.addObserver(this); + } + + @Override + public void update() { + Burger order = ui.getLatestOrder(); + System.out.println("Preparing order ... " + order); + } + + public void prepare(Burger order) { + System.out.println("Preparing order ... " + order); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/ChatbotUI.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/ChatbotUI.java new file mode 100644 index 00000000..b9133b4f --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/ChatbotUI.java @@ -0,0 +1,87 @@ +package htw.berlin.ui; + +import htw.berlin.domain.Burger; +import htw.berlin.service.*; +import htw.berlin.service.Observer; + +import java.util.*; + +public class ChatbotUI implements Observable { + private final UserInputWrapper input; + private final BurgerBuilder builder; + private final InputParser parser; + + public ChatbotUI(UserInputWrapper uiw, BurgerBuilder bb, InputParser ip) { + input = uiw; + builder = bb; + parser = ip; + } + + private final List orders = new ArrayList<>(); + + public Burger getLatestOrder() { + return orders.get(orders.size()-1); + } + + private final Set observers = new HashSet<>(); + + @Override + public void addObserver(Observer ob) { + observers.add(ob); + } + + @Override + public void removeObserver(Observer ob) { + observers.remove(ob); + } + + @Override + public void notifyObservers() { + observers.forEach(Observer::update); + } + + public String launch() { + String inputLine = input.ask("Willkommen beim Burgerbot! Was moechtest du gerne bestellen?"); + while (!(inputLine.contains("Bestellung abschliessen") || inputLine.contains("Auf Wiedersehen"))) { + List articles = articleIdsFromOrder(inputLine); + if(articles.isEmpty()) { + inputLine = input.ask("Entschuldigung, ich habe dich nicht verstanden. Waehle aus folgenden Zutaten: " + + (new ArticleInfosToMenuAdapter(ArticleInfos.getInstance())).printAllArticles()); + } else { + builder.addIngredientsById(articles); + Burger burger = builder.build(); + inputLine = input.ask("In Ordnung. Dein Burger mit " + burger.getIngredients() + + " kostet " + burger.calculatePrice() + " Euro. Willst du die Bestellung abschliessen?"); + + if(inputLine.contains("Ja")) { + orders.add(burger); + this.notifyObservers(); + break; + } + } + } + return inputLine; + } + + // nur public zum einfacheren Testen + public List articleIdsFromOrder(String inputLine) { + IMenu menu = new ArticleInfosToMenuAdapter(ArticleInfos.getInstance()); + Set articles = menu.getAllArticles().keySet(); + Map articleCount = parser.countKeywords(inputLine, articles); + Map articleMap = menu.getAllArticles(); + List ids = new ArrayList<>(); + + for (Map.Entry entry : articleCount.entrySet()) { + String articleName = entry.getKey(); + int articleId = articleMap.get(articleName); + int count = entry.getValue(); + + for (int frequency = 0; frequency < count; frequency++) { + ids.add(articleId); + } + } + + Collections.sort(ids); + return ids; + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/CommaAndWhitespaceSplittingInputParser.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/CommaAndWhitespaceSplittingInputParser.java new file mode 100644 index 00000000..392cc0dd --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/CommaAndWhitespaceSplittingInputParser.java @@ -0,0 +1,18 @@ +package htw.berlin.ui; + +import java.util.*; + +public class CommaAndWhitespaceSplittingInputParser implements InputParser { + + @Override + public Map countKeywords(String line, Set keywords) { + Map keywordCount = new HashMap<>(); + List splitInput = line != null ? Arrays.asList(line.split("[\\s,]+")) : Collections.emptyList(); + + for (String keyword : keywords) { + keywordCount.put(keyword, Collections.frequency(splitInput, keyword)); + } + + return keywordCount; + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/InputParser.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/InputParser.java new file mode 100644 index 00000000..7a44c09a --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/InputParser.java @@ -0,0 +1,8 @@ +package htw.berlin.ui; + +import java.util.Map; +import java.util.Set; + +public interface InputParser { + Map countKeywords(String line, Set keywords); +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/Observable.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/Observable.java new file mode 100644 index 00000000..71dd0b67 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/Observable.java @@ -0,0 +1,9 @@ +package htw.berlin.ui; + +import htw.berlin.service.Observer; + +public interface Observable { + void addObserver(Observer obs); + void removeObserver(Observer obs); + void notifyObservers(); +} \ No newline at end of file diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/UserInputWrapper.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/UserInputWrapper.java new file mode 100644 index 00000000..f5670e32 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/main/java/htw/berlin/ui/UserInputWrapper.java @@ -0,0 +1,24 @@ +package htw.berlin.ui; + +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Scanner; + +public class UserInputWrapper { + private final Scanner scanner; + private final PrintStream out; + + public UserInputWrapper(InputStream in, PrintStream out) { + scanner = new Scanner(in); + this.out = out; + } + + public String ask(String message) { + out.println(message); + return scanner.nextLine(); + } + + public void state(String message) { + out.println(message); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotAccountingIntegrationTest.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotAccountingIntegrationTest.java new file mode 100644 index 00000000..c201f022 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotAccountingIntegrationTest.java @@ -0,0 +1,35 @@ +package htw.berlin; + +import htw.berlin.service.BurgerBuilderImpl; +import htw.berlin.service.accounting.Accounting; +import htw.berlin.ui.ChatbotUI; +import htw.berlin.ui.CommaAndWhitespaceSplittingInputParser; +import htw.berlin.ui.UserInputWrapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.contains; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +public class ChatbotAccountingIntegrationTest { + @Test + @DisplayName("should notify accounting and state the current revenue") + void integrationTestRevenue() { + String orderQuestion = "Willkommen beim Burgerbot! Was moechtest du gerne bestellen?"; + String simpleOrder = "Ich haette gerne einen Burger mit Burgerbrot, Rindfleisch, Eisbergsalat, Tomate und Ketchup"; + String confirmationQuestion = "Willst du die Bestellung abschliessen?"; + UserInputWrapper input = mock(UserInputWrapper.class); + when(input.ask(eq(orderQuestion))).thenReturn(simpleOrder); + when(input.ask(contains(confirmationQuestion))).thenReturn("Ja"); + + ChatbotUI ui = new ChatbotUI(input, new BurgerBuilderImpl(), new CommaAndWhitespaceSplittingInputParser()); + Accounting acc = new Accounting(ui, input); + + String expectedMessage = "Nettoumsatz in 2021 soweit: 7.35"; + + assertEquals("Ja", ui.launch()); + verify(input).state(expectedMessage); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotIngredientIntegrationTest.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotIngredientIntegrationTest.java new file mode 100644 index 00000000..4bacccce --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotIngredientIntegrationTest.java @@ -0,0 +1,63 @@ +package htw.berlin; + +import htw.berlin.domain.BurgerImpl; +import htw.berlin.service.BurgerBuilder; +import htw.berlin.service.BurgerBuilderImpl; +import htw.berlin.ui.ChatbotUI; +import htw.berlin.ui.CommaAndWhitespaceSplittingInputParser; +import htw.berlin.ui.UserInputWrapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +public class ChatbotIngredientIntegrationTest { + @Test + @DisplayName("should understand a simple order and list the burger's individual ingredients and it's price") + void integrationTestSimpleOrder() { + String orderQuestion = "Willkommen beim Burgerbot! Was moechtest du gerne bestellen?"; + String simpleOrder = "Ich haette gerne einen Burger mit Burgerbrot, Rindfleisch, Eisbergsalat, Tomate und Ketchup"; + String confirmationQuestion = "Willst du die Bestellung abschliessen?"; + String orderConfirmation = "Bestellung abschliessen"; + UserInputWrapper input = mock(UserInputWrapper.class); + when(input.ask(eq(orderQuestion))).thenReturn(simpleOrder); + when(input.ask(contains(confirmationQuestion))).thenReturn(orderConfirmation); + + ChatbotUI ui = new ChatbotUI(input, new BurgerBuilderImpl(), new CommaAndWhitespaceSplittingInputParser()); + + String expectedMessage = "In Ordnung. Dein Burger mit " + + "[Burgerbrot, Rindfleisch, Eisbergsalat, Tomate, Ketchup] " + + "kostet 7.35 Euro. " + + "Willst du die Bestellung abschliessen?"; + + assertEquals("Bestellung abschliessen", ui.launch()); + verify(input).ask(expectedMessage); + } + + @Test + @DisplayName("should understand a special order and list the burger's individual ingredients and it's price") + void integrationTestSpecialOrder() { + String orderQuestion = "Willkommen beim Burgerbot! Was moechtest du gerne bestellen?"; + String simpleOrder = "Ich haette gerne ein Ciabatta mit Falafel, Rucolasalat, Tomate, Gurke und Mayo"; + String confirmationQuestion = "Willst du die Bestellung abschliessen?"; + String orderConfirmation = "Bestellung abschliessen"; + UserInputWrapper input = mock(UserInputWrapper.class); + when(input.ask(eq(orderQuestion))).thenReturn(simpleOrder); + when(input.ask(contains(confirmationQuestion))).thenReturn(orderConfirmation); + + ChatbotUI ui = new ChatbotUI(input, new BurgerBuilderImpl(), new CommaAndWhitespaceSplittingInputParser()); + + String expectedMessage = "In Ordnung. Dein Burger mit " + + "[Ciabatta, Falafel, Rucolasalat, Tomate, Gurke, Mayo] " + + "kostet 7.65 Euro. " + + "Willst du die Bestellung abschliessen?"; + + assertEquals("Bestellung abschliessen", ui.launch()); + verify(input).ask(expectedMessage); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotParserIntegrationTest.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotParserIntegrationTest.java new file mode 100644 index 00000000..421b5532 --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ChatbotParserIntegrationTest.java @@ -0,0 +1,39 @@ +package htw.berlin; + +import htw.berlin.domain.BurgerImpl; +import htw.berlin.service.BurgerBuilder; +import htw.berlin.ui.ChatbotUI; +import htw.berlin.ui.CommaAndWhitespaceSplittingInputParser; +import htw.berlin.ui.UserInputWrapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +public class ChatbotParserIntegrationTest { + @Test + @DisplayName("should understand an order and trigger a burger build with the right article ids") + void integrationTestSimpleOrderWithInputParser() { + String orderQuestion = "Willkommen beim Burgerbot! Was moechtest du gerne bestellen?"; + String simpleOrder = "Ich haette gerne einen Burger mit Burgerbrot, Rindfleisch, Eisbergsalat, Tomate und Ketchup"; + String confirmationQuestion = "Willst du die Bestellung abschliessen?"; + String orderConfirmation = "Bestellung abschliessen"; + UserInputWrapper input = mock(UserInputWrapper.class); + when(input.ask(eq(orderQuestion))).thenReturn(simpleOrder); + when(input.ask(contains(confirmationQuestion))).thenReturn(orderConfirmation); + + BurgerBuilder builder = mock(BurgerBuilder.class); + when(builder.addIngredientsById(anyList())).thenReturn(true); + when(builder.build()).thenReturn(new BurgerImpl(Collections.emptyList())); + + ChatbotUI ui = new ChatbotUI(input, builder, new CommaAndWhitespaceSplittingInputParser()); + + assertEquals("Bestellung abschliessen", ui.launch()); + verify(builder).addIngredientsById(Arrays.asList(100, 300, 500, 700, 900)); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/domain/BurgerImplTest.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/domain/BurgerImplTest.java new file mode 100644 index 00000000..e4283eee --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/domain/BurgerImplTest.java @@ -0,0 +1,32 @@ +package htw.berlin.domain; + +import htw.berlin.service.ArticleInfos; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class BurgerImplTest { + + private final ArticleInfos infos = ArticleInfos.getInstance(); + + private final Burger sut = new BurgerImpl(List.of( + infos.buns.get(100), + infos.patties.get(300), + infos.salads.get(500), + infos.veggies.get(700), + infos.sauces.get(900) + )); + + @Test + @DisplayName("should calculate the price of a burger based on its ingredients") + void canCalculatePrice() { + BigDecimal expected = new BigDecimal("7.35"); + BigDecimal actual = sut.calculatePrice(); + assertEquals(expected, actual); + } + +} \ No newline at end of file diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/service/BurgerBuilderImplTest.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/service/BurgerBuilderImplTest.java new file mode 100644 index 00000000..6e9ccc7f --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/service/BurgerBuilderImplTest.java @@ -0,0 +1,23 @@ +package htw.berlin.service; + +import htw.berlin.domain.Burger; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class BurgerBuilderImplTest { + + @Test + @DisplayName("should build a burger from article ids") + void testBuildBurger() { + BurgerBuilder burgerBuilder = new BurgerBuilderImpl(); + List ids = List.of(100, 300, 900); + burgerBuilder.addIngredientsById(ids); + Burger burger = burgerBuilder.build(); + + assertEquals(3, burger.getIngredients().size()); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ui/ChatbotUITest.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ui/ChatbotUITest.java new file mode 100644 index 00000000..b526a06b --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ui/ChatbotUITest.java @@ -0,0 +1,91 @@ +package htw.berlin.ui; + +import htw.berlin.service.BurgerBuilderImpl; +import htw.berlin.ui.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import static org.mockito.AdditionalMatchers.*; +import static org.mockito.ArgumentMatchers.*; + +import java.util.Arrays; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +// testing approach inspired from https://stackoverflow.com/questions/6415728/junit-testing-with-simulated-user-input#answer-6416591 +public class ChatbotUITest { + + @Test + @DisplayName("text input loop should get a first input line") + void canGetInput() { + String initialQuestion = "Was moechtest du gerne bestellen?"; + UserInputWrapper input = mock(UserInputWrapper.class); + when(input.ask(contains(initialQuestion))).thenReturn("Ich bin mir nicht sicher"); + when(input.ask(not(contains(initialQuestion)))).thenReturn("Auf Wiedersehen"); + + InputParser parser = mock(InputParser.class); + when(parser.countKeywords(anyString(), anySet())).thenReturn(Map.of( + "Burgerbrot", 0, + "Ciabatta", 0, + "Rindfleisch", 0, + "Falafel", 0, + "Eisbergsalat", 0, + "Rucolasalat", 0, + "Tomate", 0, + "Gurke", 0, + "Ketchup", 0, + "Mayo", 0 + )); + + ChatbotUI ui = new ChatbotUI(input, new BurgerBuilderImpl(), parser); + + assertEquals("Auf Wiedersehen", ui.launch()); + } + + @Test + @DisplayName("helper method articleIdsFromOrder can get the correct article ids") + void canGetArticleIds() { + InputParser parser = mock(InputParser.class); + when(parser.countKeywords(anyString(), anySet())).thenReturn(Map.of( + "Burgerbrot", 1, + "Ciabatta", 0, + "Rindfleisch", 0, + "Falafel", 0, + "Eisbergsalat", 0, + "Rucolasalat", 0, + "Tomate", 1, + "Gurke", 0, + "Ketchup", 0, + "Mayo", 0 + )); + ChatbotUI ui = new ChatbotUI(null, null, parser); + + var expected = Arrays.asList(100, 700); + var actual = ui.articleIdsFromOrder("Ich haette gerne einen Burger mit Burgerbrot und Tomate"); + assertEquals(expected, actual); + } + + @Test + @DisplayName("helper method articleIdsFromOrder can get article ids multiple times if they ordered multiple times") + void canGetArticleIdsMultipleTimes() { + InputParser parser = mock(InputParser.class); + when(parser.countKeywords(anyString(), anySet())).thenReturn(Map.of( + "Burgerbrot", 1, + "Ciabatta", 0, + "Rindfleisch", 3, + "Falafel", 0, + "Eisbergsalat", 0, + "Rucolasalat", 0, + "Tomate", 1, + "Gurke", 0, + "Ketchup", 0, + "Mayo", 0 + )); + ChatbotUI ui = new ChatbotUI(null, null, parser); + + var expected = Arrays.asList(100, 300, 300, 300, 700); + var actual = ui.articleIdsFromOrder("Ich haette gerne einen Burger mit Burgerbrot, Rindfleisch, Rindfleisch, Rindfleisch und Tomate"); + assertEquals(expected, actual); + } +} diff --git a/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ui/InputParserTest.java b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ui/InputParserTest.java new file mode 100644 index 00000000..8aa7bfae --- /dev/null +++ b/Downloads/HTW Berlin/Sem3/Prog2/klausurvorbereitung-CaoNgocYen-main/src/test/java/htw/berlin/ui/InputParserTest.java @@ -0,0 +1,63 @@ +package htw.berlin.ui; + +import htw.berlin.ui.InputParser; +import htw.berlin.ui.CommaAndWhitespaceSplittingInputParser; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +public class InputParserTest { + + @Test + @DisplayName("should count how often specified keywords occur") + void canCountKeywords() { + InputParser classUnderTest = new CommaAndWhitespaceSplittingInputParser(); + Set keywords = new HashSet<>(Arrays.asList("Burgerbrot", "Rindfleisch", "Eisbergsalat", "Tomate", "Ketchup", "Mayo", "Avocado")); + String inputLine = "Ich haette gerne einen Burger mit Burgerbrot, Rindfleisch, Eisbergsalat, Tomate, und Ketchup"; + var expected = Map.of( + "Burgerbrot", 1, + "Rindfleisch", 1, + "Eisbergsalat", 1, + "Tomate", 1, + "Ketchup", 1, + "Mayo", 0, + "Avocado", 0); + assertEquals(expected, classUnderTest.countKeywords(inputLine, keywords)); + } + + @Test + @DisplayName("should be able to count multiple occurrences of a keyword") + void canCountMultipleKeywordOccurrences() { + InputParser classUnderTest = new CommaAndWhitespaceSplittingInputParser(); + Set keywords = new HashSet<>(Arrays.asList("Burgerbrot", "Rindfleisch", "Eisbergsalat", "Tomate", "Ketchup", "Mayo", "Avocado")); + String inputLine = "Ich haette gerne einen Burger mit Burgerbrot, Rindfleisch, Rindfleisch, Rindfleisch und Tomate"; + var expected = Map.of( + "Burgerbrot", 1, + "Rindfleisch", 3, + "Eisbergsalat", 0, + "Tomate", 1, + "Ketchup", 0, + "Mayo", 0, + "Avocado", 0); + assertEquals(expected, classUnderTest.countKeywords(inputLine, keywords)); + } + + @Test + @DisplayName("should be able to handle null input") + void canHandleNullInput() { + InputParser classUnderTest = new CommaAndWhitespaceSplittingInputParser(); + Set keywords = new HashSet<>(Arrays.asList("Rindfleisch", "Eisbergsalat", "Tomate", "Ketchup", "Mayo", "Avocado")); + String inputLine = null; + var expected = Map.of( + "Rindfleisch", 0, + "Eisbergsalat", 0, + "Tomate", 0, + "Ketchup", 0, + "Mayo", 0, + "Avocado", 0); + assertEquals(expected, classUnderTest.countKeywords(inputLine, keywords)); + } +}