* Упражнение 10, 2015 – добавка
Публикувано на 01 декември 2015 в раздел ПИК3 Java.
Тук представям разширен вариант на задачата от упражнение 10. На практика са решени всички поставени допълнителни задачи. Кода на много места може да се изчисти и да стане по-лесно четим, но се надявам и така да е достатъчно разбираем. Вмъкнати са следните допълнителни функционалности, които подобряват предишната задача:
- GPOffice вече е самостоятелен клас;
- Създаден е клас Report. При всяко посещение в стая с лекар за пациента се изготвя доклад за извършената дейност. После обратно в GPOffice докладите се сливат в един общ (метод mergeWith). За целта е променена логиката на метод nextPatient() - вече връща доклад за следващия пациент;
- Няма хвърляне на изключения и не се утежняваме с try-catch блокове;
- MedicalRoom и HospitalRoom вече са наследници на клас Room, с което структурата им става по-ясна;
- Вече можете да вкарвате всякакви диагнози на пациенти, а не само предварително дефинираните. В MedicalRoom и HospitalRoom ще бъдат лекувани само тези болести, които са възможни (possibleCures), а непознатите няма да бъдат разглеждани;
- Две болести (Diagnosis) приемаме за еднакви, ако имената им съвпадат - не обръщаме внимание на цените. Тоест ако даден пациент е болен от болест A и си мисли, че тя струва X лева, това не значи, че в болницата ще му струва толкова - може да е по-евтино или по-скъпо. Реализирано е по този начин, защото се стремих да намаля количеството код. Реално в масива с болести на пациента (sicknesses) не е нужно да се пази цената, а само името на болестта, но в случая преизползвах вече готовия клас (което следва и по наследство от решението на оригиналната задача);
- Двама пациента приемаме за еднакви, ако са с едно и също име и ЕГН. Заболяванията им и болестите им не се взимат под внимание при сравнение на обекти;
- GPOffice няма опашка с пациенти - такива има само при MedicalRoom и HospitalRoom. За опашката пред GPOffice се грижи main метода;
- Пазим дълга (debt) на пациентите на две места - веднъж в репорта му в GPOffice и веднъж в статичния ArrayList debtors. За конкретната програма не е необходимо това дублиране на информация, но го запазих заради продължението от предишната задача.
Решение:
Debtor.java:
package upr11;
public class Debtor{ Patient patient; Double debt; Debtor(Patient patient, Double debt){ this.patient = patient; this.debt = debt; } }
Diagnosis.java:
package upr11; public class Diagnosis{ double cost; String name; public Diagnosis(double cost, String name){ this.cost = cost; this.name = name; } public int hashCode(){ int result = 17; result = result*37 + this.name==null?0:this.name.hashCode(); return result; } public boolean equals(Object o){ if(!(o instanceof Diagnosis)) return false; String name = ((Diagnosis)o).name; if(this.name.equals(name)) return true; else return false; } }
GPOffice.java:
package upr11; import java.util.HashMap; import java.util.Map; public class GPOffice{ MedicalRoom mr; HospitalRoom hr; HashMap<Patient, Report> reports; public GPOffice(MedicalRoom mr, HospitalRoom hr){ this.mr = mr; this.hr = hr; this.reports = new HashMap<>(); } // Queues patient to a Room if we can cure him boolean nextPatient(Patient p){ // First the serious sicknesses for HospitalRoom for(Diagnosis ps: p.sicknesses){ if(hr.cures(ps)){ hr.queuePatient(p); return true; } } // If not, check for MedicalRoom sicknesses for(Diagnosis ps: p.sicknesses){ if(mr.cures(ps)){ mr.queuePatient(p); return true; } } // If not, we cannot queue him anywhere return false; } void logReport(Patient p, Report r){ Report old = this.reports.get(p); if(old!=null){ old.mergeWith(r); this.reports.put(p, old); } else this.reports.put(p, r); } void printReports(){ for(Map.Entry<Patient, Report> es : this.reports.entrySet()){ es.getValue().print(); } } }
Patient.java:
package upr11; import java.util.Set; import java.util.HashSet; import java.util.HashMap; import java.util.List; import java.util.Iterator; public class Patient{ final String name; final String egn; double paycheck; HashSet<Diagnosis> sicknesses; Patient(String name, String egn, double paycheck, Set<Diagnosis> sicknesses){ this.name = name; this.egn = egn; this.paycheck = paycheck; this.sicknesses = new HashSet<>(sicknesses); } Patient(String name, String egn, double paycheck, List<Diagnosis> sicknesses){ this.name = name; this.egn = egn; this.paycheck = paycheck; this.sicknesses = new HashSet<>(sicknesses); } double payBill(double amount){ this.paycheck -= amount; if(this.paycheck >= 0) return 0; else{ double debt = -this.paycheck; this.paycheck = 0; return debt; } } boolean isSick(){ return !this.sicknesses.isEmpty(); } boolean isSickFrom(Diagnosis sickness){ return this.sicknesses.contains(sickness); } public int hashCode(){ int result = 17; result = result*37 + this.name==null?0:this.name.hashCode(); result = result*37 + this.egn==null?0:this.egn.hashCode(); return result; } public boolean equals(Object o){ if(!(o instanceof Patient)) return false; Patient p = (Patient)o; if(this.name == p.name && this.egn == p.egn ) return true; else return false; } }
Report.java:
package upr11; public final class Report{ final Patient patient; String message; double debt; Report(Patient p){ this.patient = p; this.message = ""; this.debt = 0.0; } public Report(Patient patient, String message, double debt){ this.patient = patient; this.message = message; this.debt = debt; } // Merges reports. True on success. boolean mergeWith(Report r){ if(!this.patient.equals(r.patient)) return false; this.debt += r.debt; if(this.message.equals("")) this.message += r.message; else this.message += "\n> "+r.message; return true; } void print(){ System.out.println("Report for: "+this.patient.name); if(!this.message.equals("")) System.out.println("> "+this.message); else System.out.println("> No messages from doctors"); System.out.print("> List of current sicknesses: "); if(this.patient.isSick()){ for(Diagnosis s: this.patient.sicknesses) System.out.print(s.name+"; "); } else{ System.out.print("COMPLETELY CURED. HOORAY!"); } System.out.println("\n> Report debt: "+this.debt); System.out.println("End report for:"+this.patient.name); } }
Room.java:
package upr11; import java.util.LinkedList; import java.util.HashMap; public abstract class Room{ int number; String doctor; LinkedList<Patient> queue; Diagnosis[] possibleCures; protected Room(int number, String doctor, Diagnosis[] possibleCures) { this.number = number; this.doctor = doctor; this.queue = new LinkedList<>(); this.possibleCures = possibleCures; } // Shows if room cures certain sickness boolean cures(Diagnosis sickness){ for(Diagnosis pc: this.possibleCures){ if(pc.equals(sickness)) return true; } return false; } // Cures patient from the sickness. // True on success and False if patient is not sick from sickness private boolean curePatient(Patient patient, Diagnosis sickness) throws RuntimeException{ if(patient == null || sickness == null){ throw new RuntimeException("Invalid call to curePatient"); } return patient.sicknesses.remove(sickness); } // Cures next patient from the queue // Writes report and returns it // or returns null if the queue was empty Report nextPatient(){ Patient p = null; // Cleans the queue from possible null elements // Assigns valid Patient or returns null on empty queue do{ if(this.queue.isEmpty()) return null; p = this.queue.getFirst(); this.queue.removeFirst(); } while(p == null); Report r = new Report(p); // Examines the patient for all known Diagnosis for(Diagnosis sickness: possibleCures){ StringBuilder reportMessage = new StringBuilder(); double debt = 0.0; // If patient is not sick from the current sickness, check next one if(!p.sicknesses.contains(sickness)) continue; // If Patient has no more money, we stop any cures if(p.paycheck<=0){ reportMessage.append("Room "+this.number+", doctor "+this.doctor+": "); reportMessage.append("Patient is out of money. Can't cure "+sickness.name); break; } else{ // Patient pays debt += p.payBill(sickness.cost); // We cure him boolean cureResult = this.curePatient(p, sickness); reportMessage.append("Room "+this.number+", doctor "+this.doctor+": "); if(cureResult == true) reportMessage.append("Cured from "+sickness.name); else reportMessage.append("Not cured from "+sickness.name+". Bug?"); } r.mergeWith(new Report(p, reportMessage.toString(), debt)); } return r; } void queuePatient(Patient p){ this.queue.addLast(p); } boolean hasMorePatients(){ return !this.queue.isEmpty(); } } class MedicalRoom extends Room{ MedicalRoom(int number, String doctor){ super(number, doctor, new Diagnosis[2]); super.possibleCures[0] = new Diagnosis(50.0, "Not sick"); super.possibleCures[1] = new Diagnosis(100.0, "Little sick"); } } class HospitalRoom extends Room{ HospitalRoom(int number, String doctor){ super(number, doctor, new Diagnosis[2]); super.possibleCures[0] = new Diagnosis(150.0, "Sick"); super.possibleCures[1] = new Diagnosis(200.0, "Very sick"); } }
Upr11.java:
package upr11; import java.util.ArrayList; import java.util.HashSet; public class Upr11{ private static ArrayList<Debtor> debtors = new ArrayList<Debtor>(); static void addDebtor(Debtor d){ debtors.add(d); } static void printDebtors(){ for(Debtor d: debtors){ System.out.println(d.patient.name + " owes " + d.debt); } } public static void main(String[] args) { MedicalRoom mr = new MedicalRoom(1, "Ivan Ivanov"); HospitalRoom hr = new HospitalRoom(2, "Petar Petrov"); GPOffice gp = new GPOffice(mr, hr); ArrayList<Diagnosis> combination1 = new ArrayList<>(); combination1.add(mr.possibleCures[0]); combination1.add(hr.possibleCures[1]); Patient p1 = new Patient("Ivan", "1234", 50.0, combination1); ArrayList<Diagnosis> combination2 = new ArrayList<>(); combination2.add(mr.possibleCures[1]); combination2.add(hr.possibleCures[0]); combination2.add(hr.possibleCures[1]); Patient p2 = new Patient("Petar", "5678", 1000.0, combination2); ArrayList<Diagnosis> combination3 = new ArrayList<>(); combination3.add(mr.possibleCures[0]); Patient p3 = new Patient("Maria", "9012", 100.0, combination3); ArrayList<Diagnosis> combination4 = new ArrayList<>(); combination4.add(mr.possibleCures[0]); combination4.add(new Diagnosis(500.0, "Unknown condition")); Patient p4 = new Patient("Todor", "9012", 100.0, combination4); gp.nextPatient(p1); gp.nextPatient(p2); gp.nextPatient(p3); gp.nextPatient(p4); // First pass HospitalRoom while(hr.hasMorePatients()){ Report r = hr.nextPatient(); if(r.debt>0) addDebtor(new Debtor(r.patient, r.debt)); gp.logReport(r.patient, r); if(r.patient.isSick() && r.patient.paycheck>0) mr.queuePatient(r.patient); } // First pass MedicalRoom while(mr.hasMorePatients()){ Report r = mr.nextPatient(); if(r.debt>0) addDebtor(new Debtor(r.patient, r.debt)); gp.logReport(r.patient, r); } gp.printReports(); System.out.println("-------------------"); printDebtors(); } }
Добави коментар