Initial commit

This commit is contained in:
github-classroom[bot]
2022-04-27 10:00:50 +00:00
commit bd1d2e051c
40 changed files with 5271 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/7.2/userguide/building_java_projects.html
*/
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 {
// Junit 5 dependencies
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.+'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.+'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.+'
// Mockito dependencies
testImplementation 'org.mockito:mockito-core:4.3.+'
}
// Test task configuration
test {
// Use JUnit platform for unit tests
useJUnitPlatform()
// Output results of individual tests
testLogging {
events "PASSED", "SKIPPED", "FAILED"
}
}
application {
// Define the main class for the application.
mainClass = 'ch.zhaw.prog2.heartbeat.Heart'
}
// Java plugin configuration
java {
// By default the Java version of the gradle process is used as source/target version.
// This can be overridden, to ensure a specific version. Enable only if required.
// sourceCompatibility = JavaVersion.VERSION_17 // ensure Java source code compatibility
// targetCompatibility = JavaVersion.VERSION_17 // version of the created byte-code
// Java compiler specific options
compileJava {
// source files should be UTF-8 encoded
options.encoding = 'UTF-8'
// for more options see https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html
}
}
task autograding(type: Test) {
description = "Runs specific tests for autograding"
group = 'verification'
useJUnitPlatform()
testLogging {
events "PASSED", "SKIPPED", "FAILED"
}
filter {
failOnNoMatchingTests true
includeTestsMatching "PacemakerTest"
includeTestsMatching "HeartTest.testExecuteHartBeatErrorBehaviourWithStubbing"
includeTestsMatching "HeartTest.testValvesBehavior"
includeTestsMatching "HeartTest.testDiastoleException"
includeTestsMatching "HeartTest.testSystoleException"
}
}
@@ -0,0 +1,100 @@
package ch.zhaw.prog2.heartbeat;
import ch.zhaw.prog2.heartbeat.parts.*;
/**
* Represents one half of a heart.
*
* @author wahl, muon
*/
public class Half {
public enum Side {LEFT, RIGHT}
private Atrium atrium; // "Vorhof"
private Ventricle ventricle; // "Herzkammer"
private AtrioventricularValve atrioventricularValve; // "Segelklappe"
private SemilunarValve semilunarValve; // "Taschenklappe"
private final Side side;
public Half(Side side) {
this.side = side;
atrium = new Atrium(side);
ventricle = new Ventricle(side);
atrioventricularValve = new AtrioventricularValve(side);
semilunarValve = new SemilunarValve(side);
}
public void initializeState(Heart.State state) {
atrioventricularValve.initializeState(state);
semilunarValve.initializeState(state);
}
public AtrioventricularValve getAtrioventricularValve() {
return atrioventricularValve;
}
public SemilunarValve getSemilunarValve() {
return semilunarValve;
}
public boolean isAtrioventricularValveOpen() {
return atrioventricularValve.isOpen();
}
public boolean isSemilunarValveOpen() {
return semilunarValve.isOpen();
}
/**
* Closes the valve
*
* @throws IllegalStateException when valve is already closed
*/
public void closeSemilunarValve() throws Valve.IllegalValveStateException {
semilunarValve.close();
}
/**
* Opens the valve
*
* @throws Valve.IllegalValveStateException when the valve is already open
*/
public void openSemilunarValve() throws Valve.IllegalValveStateException {
semilunarValve.open();
}
/**
* Closes the valve
*
* @throws Valve.IllegalValveStateException when valve is already closed
*/
public void closeAtrioventricularValve() throws Valve.IllegalValveStateException {
atrioventricularValve.close();
}
/**
* Opens the valve
*
* @throws Valve.IllegalValveStateException when the valve is already open
*/
public void openAtrioventricularValve() throws Valve.IllegalValveStateException {
atrioventricularValve.open();
}
public void contractVentricle() {
ventricle.contract();
}
public void relaxVentricle() {
ventricle.relax();
}
public void contractAtrium() {
atrium.contract();
}
public void relaxAtrium() {
atrium.relax();
}
}
@@ -0,0 +1,145 @@
package ch.zhaw.prog2.heartbeat;
import ch.zhaw.prog2.heartbeat.parts.Valve;
import java.util.ArrayList;
import java.util.List;
/**
* This class represents a human heart (https://en.wikipedia.org/wiki/Heart).
* <p>
* <p>
* Example tests: before Chamber::contract() is called, the atrioventricular
* valves must be closed.
*
* @author wahl
*/
public class Heart {
private final static int AVERAGE_HEART_RATE = 60;
/**
* Encodes the states of the heart
*
* @author wahl
*/
public enum State {
SYSTOLE, DIASTOLE
}
private List<Half> halves;
private State state;
private int heartRate;
/**
* The default constructor calls the more specific constructor with a new left
* and right half.
*/
public Heart() {
this(new Half(Half.Side.LEFT), new Half(Half.Side.RIGHT));
}
/**
* The default constructor adds the left and the right half that are specified
* as parameters and sets the start state to diastole.
*/
public Heart(Half leftHalf, Half rightHalf) {
state = State.DIASTOLE;
heartRate = AVERAGE_HEART_RATE;
halves = new ArrayList<>();
halves.add(leftHalf);
halves.add(rightHalf);
initalizeState();
}
public void initalizeState(){
for(Half half : halves){
half.initializeState(state);
}
}
/**
* Executes a sequence of diastole and systole, beginning with the current
* state.
*
* @throws HeartBeatDysfunctionException when Valve.IllegalValveStateException or
* InvalidValvePositionException occurs during diastole or systole
* TODO Implement a pause mechanism based on the current heart rate
*/
public void executeHeartBeat() throws HeartBeatDysfunctionException{
//TODO implement
}
/**
* Executes the diastole phase of the heart.
*
* @throws Valve.IllegalValveStateException when one of the valves has an illegal State
*/
public void executeDiastole() {
//TODO implement
}
/**
* Executes the systole phase of the heart.
*
* @throws Valve.IllegalValveStateException when one of the valves has an illegal State
*/
public void executeSystole() {
//TODO implement
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
/**
* Sets the heart rate to the parameter value in Hz.
* Rate has to be inside range >30 && <220
* If rate is outside of range method rejects the change
* and returns false.
*
* @param frequencyInHz which should be applied to the heart
* @return true if the heart rate could be set, false otherwise
*/
public boolean setHeartRate(int frequencyInHz) {
if (frequencyInHz < 30 || frequencyInHz > 220) {
return false;
}
this.heartRate = frequencyInHz;
return true;
}
public int getHeartRate() {
return heartRate;
}
public List<Half> getHalves() {
return halves;
}
public static class HeartBeatDysfunctionException extends Exception {
public HeartBeatDysfunctionException() {
}
public HeartBeatDysfunctionException(String message) {
super(message);
}
public HeartBeatDysfunctionException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* The main method instantiates a heart object and executes a single heartbeat.
*
* @param args
*/
public static void main(String[] args) throws HeartBeatDysfunctionException {
Heart heart = new Heart();
heart.executeHeartBeat();
}
}
@@ -0,0 +1,44 @@
package ch.zhaw.prog2.heartbeat;
/**
* This class represents a pacemaker for a human hart.
*
* This is an incomplete implementation, reduced to the essentials for the content of the lab.
* There would be a lot more code needed to implement a pacemaker, but this is not part of this lab :-)
*
* @author muon
*
*/
public class Pacemaker {
Heart heart;
/**
* Constructor of Pacemaker
* @param heart
*/
public Pacemaker(Heart heart) {
this.heart = heart;
}
/**
* Sets the heart rate to the parameter value in Hz.
* Rate has to be inside range >30 && <220
* If frequency can be applied on heart, the current frequency will be returned.
* If heart does reject the change the method throws an exception.
*
* @param frequencyInHz needs to be applied on heart
* @return current frequency of the heart
* @throws IllegalArgumentException when heart does reject the change
*/
public int setHeartRate(int frequencyInHz) {
if(heart.setHeartRate(frequencyInHz) == false){
throw new IllegalArgumentException("Frequency could not be set.");
}
return heart.getHeartRate();
}
/*
...
There would be a lot more code needed to implement a pacemaker, but this is not part of this lab :-)
...
*/
}
@@ -0,0 +1,19 @@
package ch.zhaw.prog2.heartbeat.parts;
import ch.zhaw.prog2.heartbeat.Half.Side;
import ch.zhaw.prog2.heartbeat.Heart;
public class AtrioventricularValve extends Valve {
public AtrioventricularValve(Side side) {
super (side);
}
public void initializeState(Heart.State state) {
if(Heart.State.DIASTOLE.equals(state)){
setOpen(false);
}else{
setOpen(true);
}
}
}
@@ -0,0 +1,20 @@
package ch.zhaw.prog2.heartbeat.parts;
import ch.zhaw.prog2.heartbeat.Half.Side;
public class Atrium {
private Side side;
public Atrium (Side side) {
this.side = side;
}
public void contract() {
System.out.println("Atrium "+ side + " is contracting.");
}
public void relax() {
System.out.println("Atrium "+ side + " is relaxing.");
}
}
@@ -0,0 +1,20 @@
package ch.zhaw.prog2.heartbeat.parts;
import ch.zhaw.prog2.heartbeat.Half.Side;
import ch.zhaw.prog2.heartbeat.Heart;
public class SemilunarValve extends Valve {
public SemilunarValve(Side side) {
super (side);
}
public void initializeState(Heart.State state) {
if(Heart.State.DIASTOLE.equals(state)){
setOpen(true);
}else{
setOpen(false);
}
}
}
@@ -0,0 +1,61 @@
package ch.zhaw.prog2.heartbeat.parts;
import ch.zhaw.prog2.heartbeat.Half.Side;
public abstract class Valve {
private boolean open;
private Side side;
public Valve(Side side) {
this.side = side;
}
/**
* Opens the valve
*
* @throws IllegalValveStateException when the valve is already open
*/
public void open() throws IllegalValveStateException {
if (open) {
throw new IllegalValveStateException(this.getClass().getSimpleName() + " " + side + " valve is already open.");
}
System.out.println(this.getClass().getSimpleName() + " " + side + " is opening.");
open = true;
}
/**
* Closes the valve
*
* @throws IllegalValveStateException when valve is already closed
*/
public void close() throws IllegalValveStateException {
if (!open) {
throw new IllegalValveStateException(this.getClass().getSimpleName() + " " + side + " valve is already closed.");
}
System.out.println(this.getClass().getSimpleName() + " " + side + " is closing.");
open = false;
}
public boolean isOpen() {
return open;
}
protected void setOpen(Boolean open) {
this.open = open;
}
public static class IllegalValveStateException extends Exception {
public IllegalValveStateException() {
}
public IllegalValveStateException(String message) {
super(message);
}
public IllegalValveStateException(String message, Throwable cause) {
super(message, cause);
}
}
}
@@ -0,0 +1,20 @@
package ch.zhaw.prog2.heartbeat.parts;
import ch.zhaw.prog2.heartbeat.Half.Side;
public class Ventricle {
private Side side;
public Ventricle (Side side) {
this.side = side;
}
public void contract() {
System.out.println("Chamber "+ side + " is contracting.");
}
public void relax() {
System.out.println("Chamber "+ side + " is relaxing.");
}
}
@@ -0,0 +1,100 @@
/*
* Test Class for Heart
*/
package ch.zhaw.prog2.heartbeat;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import ch.zhaw.prog2.heartbeat.parts.Valve;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import ch.zhaw.prog2.heartbeat.Heart.State;
class HeartTest {
/**
* This is a very simple test to check if Junit and Mockito are properly set up.
*/
@Test
void testTheTest() {
Heart classUnderTest = new Heart();
assertNotNull(classUnderTest.getState(), "The heart must have a state.");
}
/**
* Tests a single heartbeat
*/
@Test
void testHeartBeat() throws Heart.HeartBeatDysfunctionException {
Heart heart = new Heart();
State startState = heart.getState();
heart.executeHeartBeat();
// after one heartbeat, the heart must be in the same state as before
assertEquals(startState, heart.getState());
}
/**
* Tests if the valves are open or closed depending on the status of the heart
*/
@Test
void testValveStatus() throws Heart.HeartBeatDysfunctionException {
Heart heart = new Heart();
heart.executeHeartBeat();
State state = heart.getState();
if (state.equals(Heart.State.DIASTOLE)) {
for (Half half : heart.getHalves()) {
assertFalse(half.isAtrioventricularValveOpen());
assertTrue(half.isSemilunarValveOpen());
}
} else if ((state.equals(Heart.State.SYSTOLE))) {
for (Half half : heart.getHalves()) {
assertTrue(half.isAtrioventricularValveOpen());
assertFalse(half.isSemilunarValveOpen());
}
}
}
/**
* Tests if the hart throws the appropriate Exception, when malfunction was detected during hartBeat
*/
@Test
void testExecuteHeartBeatErrorBehaviour() {
Heart heart = new Heart();
// prepare error situation due to wrong initialization
heart.setState(State.SYSTOLE);
assertThrows(Heart.HeartBeatDysfunctionException .class, // verification using lambda
() -> heart.executeHeartBeat());
}
/**
* Tests if the hart throws the appropriate Exception, when malfunction was detected during hartBeat
* with exception Stubbing
*/
@Test
void testExecuteHartBeatErrorBehaviourWithStubbing() throws Valve.IllegalValveStateException {
//TODO implement
fail();
}
/**
* We test if Heart::executeHeartbeat() sends the right signals to both of its
* halves.
*
* When Half::contractVentricle() is called, Half::closeAtrioventricularValve()
* and Half::openSemilunarValve() must have been called earlier.
*
*/
@Test
void testValvesBehavior() {
//TODO implement
fail();
}
}
@@ -0,0 +1,30 @@
package ch.zhaw.prog2.heartbeat;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/*
* Test Class for Pacemaker
*/
public class PacemakerTest {
/**
* Test if setHeartRate does throw correct exception when rate is rejected (because frequency is out of range)
*/
@Test
void testSetHeartRateRejectsFrequenciesOutOfRange() {
//TODO implement
fail();
}
/**
* Test if setHeartRate does correctly set the rate when frequency is inside range
*/
@Test
void testSetHeartRateAppliesFrequenciesInsideRange() {
//TODO implement
fail();
}
}