Initial commit
This commit is contained in:
@@ -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 :-)
|
||||
...
|
||||
*/
|
||||
}
|
||||
+19
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user