C, PHP, VB, .NET

Дневникът на Филип Петров


* Упражнение 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();
  }
}

 



Добави коментар

Адресът на електронната поща няма да се публикува


*