Commit a4f1160e authored by Hallvard Trætteberg's avatar Hallvard Trætteberg
Browse files

Removed lf

parent c49cf453
......@@ -51,7 +51,6 @@
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<excludePackageNames>ord2019.lf.*</excludePackageNames>
</configuration>
</plugin>
</plugins>
......
package ord2019.lf.part1;
/**
* A doctor has the capacity to treat one patient at a time.
*/
public class Doctor {
private Patient patient;
/**
* @return the patient this doctor is treating, or null if s/he isn't currently treating any patient.
*/
public Patient getPatient() {
return patient;
}
/**
* @return true if this doctor is currently treating a patient, otherwise false.
*/
public boolean isAvailable() {
return getPatient() == null;
}
/**
* Sets the patient that this doctor is treating, use null to indicate s/he isn't currently treating any patient.
* @param patient
*/
public void setPatient(final Patient patient) {
this.patient = patient;
}
}
package ord2019.lf.part1;
public class Patient {
}
package ord2019.lf.part1;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Predicate;
/**
* A class for managing a set of doctors and the patients they're treating.
* When doctors or patients arrive, it is made sure that patients are treated as soon as possible.
*/
public class TreatmentUnit {
private final Collection<Doctor> doctors = new ArrayList<>();
private final Collection<Patient> patients = new ArrayList<>();
/**
* Adds a doctor and makes sure s/he starts treating a patient, if one is waiting.
* @param doctor
*/
public void addDoctor(final Doctor doctor) {
doctors.add(doctor);
startTreatment(doctor);
}
/**
* @return the currently available doctors
*/
public Collection<Doctor> getAvailableDoctors() {
final Collection<Doctor> result = new ArrayList<>();
for (final Doctor doctor : doctors) {
if (doctor.isAvailable()) {
result.add(doctor);
}
}
return result;
// return doctors.stream().filter(Doctor::isAvailable).collect(Collectors.toList());
}
/**
* Adds a patient to this treatment unit, and makes sure treatment starts if any doctor is available.
* Otherwise the patient is queued for treatment when a doctor becomes available.
* @param patient
*/
public void addPatient(final Patient patient) {
patients.add(patient);
startTreatment(patient);
}
/**
* @param pred the predicate that the doctor must satisfy
* @return some doctor satisfying the predicate
*/
public Doctor getDoctor(final Predicate<Doctor> pred) {
for (final Doctor doctor : doctors) {
if (pred.test(doctor)) {
return doctor;
}
}
return null;
}
/**
* Find the doctor, if any, that treats the provided patient.
* @param patient
* @return the doctor treating the provided patient, or null, of the patient isn't currently being treated
*/
public Doctor getDoctor(final Patient patient) {
return getDoctor(doctor -> doctor.getPatient() == patient);
}
/**
* Find all patients that are not currently being treated
* @return the patients not currently being treated
*/
public Collection<Patient> getWaitingPatients() {
final Collection<Patient> result = new ArrayList<>();
for (final Patient patient : patients) {
if (getDoctor(patient) == null) {
result.add(patient);
}
}
return result;
}
/**
* Finds a waiting patient and sets him/her as the provided doctor's patient
* @param doctor the doctor for which a patient to treat should be found
* @return true if a patient for the provided doctor was found, false otherwise
*/
private boolean startTreatment(final Doctor doctor) {
final Collection<Patient> waitingPatients = getWaitingPatients();
if (waitingPatients.isEmpty()) {
return false;
}
doctor.setPatient(waitingPatients.iterator().next());
return true;
}
/**
* Finds an available doctor for the provided patient, and sets that doctor to treat the patient
* @param patient the patient for which a treating doctor should be found
* @return true if a doctor for the provided patient was found, false otherwise
*/
private boolean startTreatment(final Patient patient) {
final Collection<Doctor> availableDoctors = getAvailableDoctors();
if (availableDoctors.isEmpty()) {
return false;
}
final Doctor doctor = availableDoctors.iterator().next();
doctor.setPatient(patient);
return true;
}
/**
* Removes the link between doctor and patient, after treatment is finished.
* Since the patient is fully treated, s/he is removed from this treatment unit.
* Also ensure the doctor starts treating another patient.
* @param doctor the doctor that has finished treating his/her patient
*/
public void treatmentFinished(final Doctor doctor) {
if (doctor.getPatient() == null) {
throw new IllegalStateException(doctor + " has no patient!");
}
final Patient patient = doctor.getPatient();
doctor.setPatient(null);
patients.remove(patient);
startTreatment(doctor);
}
}
package ord2019.lf.part2;
import java.util.Arrays;
import java.util.Collection;
/**
* A doctor has the capacity to treat one patient at a time.
* The doctor as a list of competencies (of type String) that
* indicates what conditions s/he can treat.
*/
public class Doctor {
private final Collection<String> competencies;
/**
* Initialise this doctor with a set of competencies
* @param competencies
*/
public Doctor(final String... competencies) {
this.competencies = Arrays.asList(competencies);
}
private Patient patient;
/**
* @return the patient this doctor is treating, or null if s/he isn't currently treating any patient.
*/
public Patient getPatient() {
return patient;
}
/**
* @return true if this doctor is currently treating a patient, otherwise false.
*/
public boolean isAvailable() {
return getPatient() == null;
}
/**
* Sets the patient that this doctor is treating, use null to indicate s/he isn't currently treating any patient.
* @param patient
*/
public void setPatient(final Patient patient) {
this.patient = patient;
}
/**
* Indicates to what extent this doctor can treat the provided patient.
* The value is the number of the patient's conditions this doctor can treat
* divided by the number of conditions the patient has
* Conditions and competencies are matches using simple String comparison
* @param patient
* @return the ratio of the patient's conditions that this doctor can treat
*/
public double canTreat(final Patient patient) {
int count = 0, total = 0;
for (final String item : patient) {
total++;
if (competencies.contains(item)) {
count++;
}
}
return ((double) count) / total;
}
/**
* "Treats" the patient by removing all the patient's conditions that this doctor can treat.
*/
public void treat() {
patient.removeConditions(competencies);
}
}
package ord2019.lf.part2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
/**
* A patient has a set of conditions (of type String) that needs to be treated.
* Implements Iterable to support iterating over all conditions.
*/
public class Patient implements Iterable<String> {
private final Collection<String> conditions = new ArrayList<>();
/**
* Add conditions to this patient, to indicate what s/he should be treated for.
* @param conditions
*/
public void addConditions(final String... conditions) {
this.conditions.addAll(Arrays.asList(conditions));
}
/**
* Indicates if this patient has conditions that needs to be treated.
* @return true if this patient has conditions that needs to be treated, false otherwise.
*/
public boolean requiresTreatment( ) {
return ! conditions.isEmpty();
}
/**
* Removes conditions from this patient, to indicate that these have been treated.
* @param conditions
*/
public void removeConditions(final Collection<String> conditions) {
this.conditions.removeAll(conditions);
}
@Override
public Iterator<String> iterator() {
return conditions.iterator();
}
}
package ord2019.lf.part2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Predicate;
/**
* A class for managing a set of doctors and the patients they're treating.
* When doctors or patients arrive, it is made sure that patients are treated as soon as possible.
*/
public class TreatmentUnit {
private final Collection<Doctor> doctors = new ArrayList<>();
private final Collection<Patient> patients = new ArrayList<>();
/**
* Adds a doctor and makes sure s/he starts treating a patient, if one is waiting.
* @param doctor
*/
public void addDoctor(final Doctor doctor) {
doctors.add(doctor);
startTreatment(doctor);
}
/**
* @return the currently available doctors
*/
public Collection<Doctor> getAvailableDoctors() {
final Collection<Doctor> result = new ArrayList<>();
for (final Doctor doctor : doctors) {
if (doctor.isAvailable()) {
result.add(doctor);
}
}
return result;
// return doctors.stream().filter(Doctor::isAvailable).collect(Collectors.toList());
}
/**
* Adds a patient to this treatment unit, and makes sure treatment starts if any doctor is available.
* Otherwise the patient is queued for treatment when a doctor becomes available.
* @param patient
*/
public void addPatient(final Patient patient) {
patients.add(patient);
startTreatment(patient);
}
/**
* @param pred the predicate that the doctor must satisfy
* @return some doctor satisfying the predicate
*/
public Doctor getDoctor(final Predicate<Doctor> pred) {
for (final Doctor doctor : doctors) {
if (pred.test(doctor)) {
return doctor;
}
}
return null;
}
/**
* Find the doctor, if any, that treats the provided patient.
* @param patient
* @return the doctor treating the provided patient, or null, of the patient isn't currently being treated
*/
public Doctor getDoctor(final Patient patient) {
return getDoctor(doctor -> doctor.getPatient() == patient);
}
/**
* Find all patients that are not currently being treated
* @return the patients not currently being treated
*/
public Collection<Patient> getWaitingPatients() {
final Collection<Patient> result = new ArrayList<>();
for (final Patient patient : patients) {
if (getDoctor(patient) == null) {
result.add(patient);
}
}
return result;
}
/**
* Finds a waiting patient and sets him/her as the provided doctor's patient.
* Will only accept a patient that has some condition that the doctor actually can treat.
* @param doctor the doctor for which a patient to treat should be found
* @return true if a patient for the provided doctor was found, false otherwise
*/
private boolean startTreatment(final Doctor doctor) {
for (final Patient patient : getWaitingPatients()) {
if (doctor.canTreat(patient) > 0.0) {
doctor.setPatient(patient);
return true;
}
}
return false;
}
/**
* Finds an available doctor for the provided patient, and sets that doctor to treat the patient.
* Will only accept a doctor that actually can treat some condition for the provided patient.
* @param patient the patient for which a treating doctor should be found
* @return true if a doctor for the provided patient was found, false otherwise
*/
private boolean startTreatment(final Patient patient) {
for (final Doctor doctor : getAvailableDoctors()) {
if (doctor.canTreat(patient) > 0.0) {
doctor.setPatient(patient);
return true;
}
}
return false;
}
/**
* Removes the link between doctor and patient, after treatment is finished.
* If the patient is fully treated, s/he is removed from this treatment unit,
* othewise another round of treatment is initiated.
* Also ensure the doctor starts treating another patient.
* @param doctor the doctor that has finished treating his/her patient
*/
public void treatmentFinished(final Doctor doctor) {
if (doctor.getPatient() == null) {
throw new IllegalStateException(doctor + " has no patient!");
}
final Patient patient = doctor.getPatient();
doctor.setPatient(null);
if (patient.requiresTreatment()) {
startTreatment(patient);
} else {
patients.remove(patient);
}
startTreatment(doctor);
}
}
package ord2019.lf.part2;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
public class TreatmentUnitTest {
private TreatmentUnit treatmentUnit;
@Before
public void setUp() {
treatmentUnit = new TreatmentUnit();
}
@Test
public void testAddDoctorPatient() {
final Doctor doctor = new Doctor("flu", "noseblead");
treatmentUnit.addDoctor(doctor);
assertTrue(doctor.isAvailable());
assertNull(doctor.getPatient());
final Patient patient = new Patient();
patient.addConditions("flu");
treatmentUnit.addPatient(patient);
assertTrue(! doctor.isAvailable());
assertSame(patient, doctor.getPatient());
doctor.treat();
treatmentUnit.treatmentFinished(doctor);
assertTrue(doctor.isAvailable());
assertNull(doctor.getPatient());
}
@Test
public void testAddPatientDoctor() {
final Patient patient = new Patient();
patient.addConditions("flu");
treatmentUnit.addPatient(patient);
final Doctor doctor = new Doctor("flu", "noseblead");
treatmentUnit.addDoctor(doctor);
assertTrue(! doctor.isAvailable());
assertSame(patient, doctor.getPatient());
doctor.treat();
treatmentUnit.treatmentFinished(doctor);
assertTrue(doctor.isAvailable());
assertNull(doctor.getPatient());
}
/**
* @startuml
* "tut : TreatmentUnitTest" as tut -> "tu : TreatmentUnit" as tu: addPatient(patient)
* tu -> tu: startTreatment(patient)
* tu -> "doctor1 : Doctor" as doc1: canTreat(patient)
* doc1 -> "patient : Patient" as patient: iterator()
* doc1 --> tu: 0.5
* tu -> doc1: setPatient(patient)
* tu --> tu: true
* tut -> tu: getDoctor(patient)
* tu --> tut: doctor1
* tut -> doc1: treat()
* doc1 -> patient: removeConditions("flu")
* tut -> tu: treatmentFinished(doc1)
* tu -> doc1: setPatient(null)
* tu -> patient: requiresTreatment()
* patient --> tu: true
* tu -> tu: startTreatment(patient)
* tu -> "doctor2 : Doctor" as doc2: canTreat(patient)
* doc2 -> patient: iterator()
* doc2 --> tu: 1.0
* tu -> doc2: setPatient(patient)
* tu --> tu: true
* tu -> tu: startTreatment(doc1)
* tu --> tu: false
* @enduml
*/
@Test
public void testAddDoctorsPatient() {
final Doctor doctor1 = new Doctor("flu");
final Doctor doctor2 = new Doctor("noseblead");
treatmentUnit.addDoctor(doctor1);
treatmentUnit.addDoctor(doctor2);
assertTrue(doctor1.isAvailable() && doctor2.isAvailable());
final Patient patient = new Patient();
patient.addConditions("flu", "noseblead");
// start sequence diagram
treatmentUnit.addPatient(patient);
assertTrue(! (doctor1.isAvailable() && doctor2.isAvailable()));
Doctor patientDoctor = treatmentUnit.getDoctor(patient);
patientDoctor.treat();
treatmentUnit.treatmentFinished(patientDoctor);
// end sequence diagram
assertTrue(patientDoctor.isAvailable());
assertNotSame(patientDoctor, treatmentUnit.getDoctor(patient));
patientDoctor = treatmentUnit.getDoctor(patient);
patientDoctor.treat();
treatmentUnit.treatmentFinished(patientDoctor);
assertTrue(doctor1.isAvailable() && doctor2.isAvailable());
}
}
package ord2019.lf.part3;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Predicate;
public abstract class AbstractTreatmentUnit {
private final Collection<Doctor> doctors = new ArrayList<>();
private final Collection<Patient> patients = new ArrayList<>();
public void addDoctor(final Doctor doctor) {
doctors.add(doctor);
startTreatment(doctor);
}
public Collection<Doctor> getAllDoctors() {
return new ArrayList<>(doctors);
}
public Collection<Doctor> getAvailableDoctors() {
final Collection<Doctor> result = new ArrayList<>();
for (final Doctor doctor : doctors) {
if (doctor.isAvailable()) {
result.add(doctor);
}
}
return result;
// return doctors.stream().filter(Doctor::isAvailable).collect(Collectors.toList());
}
public void addPatient(final Patient patient) {
patients.add(patient);
startTreatment(patient);
}
public Doctor getDoctor(final Predicate<Doctor> pred) {
for (final Doctor doctor : doctors) {
if (pred.test(doctor)) {
return doctor;
}
}
return null;
}
public Doctor getDoctor(final Patient patient) {
return getDoctor(doctor -> doctor.getPatient() == patient);
}
public Collection<Patient> getAllPatients() {
return new ArrayList<>(patients);
}
public Collection<Patient> getWaitingPatients() {
final Collection<Patient> result = new ArrayList<>();
for (final Patient patient : patients) {
if (getDoctor(patient) == null) {
result.add(patient);
}
}
return result;
}