package waelti.statistics.queries; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import waelti.statistics.queries.annotations.GetProperty; import waelti.statistics.queries.annotations.SetProperty; import waelti.statistics.queries.providers.QueryContentProvider; import waelti.statistics.queries.providers.QueryLabelProvider; import ch.elexis.core.ui.util.SWTHelper; import ch.elexis.data.Fall; import ch.elexis.data.Konsultation; import ch.elexis.data.Patient; import ch.elexis.data.Query; /** * This class is responsible for retaining all information about costs per consultation in a given * time period and for specified cohorts. <br> * The resulting list contains following columns: * <ul> * <li>First year of birth of the cohort</li> * <li>Total costs of this cohort in the given time period</li> * <li>Number of consultations</li> * <li>Average costs</li> * </ul> * * @author michael waelti * @see AbstractQuery */ public class Consultations extends AbstractTimeSeries { /** Query which loads all patients from the database */ private Query patientQuery = new Query<Patient>(Patient.class); /** * This value is the first birth cohort. The value is determined when iterating through all * patients. The initial value is set to the actual year. */ private int firstCohort; /** The cohort's size. */ private int cohortSize; /** The list containing all header strings for each column. */ private List<String> header; private IProgressMonitor monitor; /** * The size of this computation. Counted as the numbers of patients to be searched for data. */ private int size = 0; /** empty constructor */ public Consultations(){ super("Konsultationsauswertung"); this.initHeader(); } @Override protected void initData(){ super.initData(); this.cohortSize = 1; } private void initHeader(){ this.header = new ArrayList<String>(7); this.header.add("Geburtsjahr"); this.header.add("Anzahl F"); this.header.add("Gesamtkosten F"); this.header.add("Konsultationen F"); this.header.add("Kosten/Konsultation F"); this.header.add("Kosten/Patient F"); this.header.add("Anzahl M"); this.header.add("Gesamtkosten M"); this.header.add("Konsultationen M"); this.header.add("Kosten/Konsultation M"); this.header.add("Kosten/Patient M"); } @Override public List<String> getTableHeadings(){ return this.header; } /** * This method executes the query and creates the content which is then accessible through * getContent. */ @Override public IStatus execute(IProgressMonitor monitor){ { this.monitor = monitor; this.createContent(); this.initProvider(); monitor.done(); return Status.OK_STATUS; } } /** * Initializes the label and content providers. Called after creating the content. */ private void initProvider(){ QueryContentProvider content = new QueryContentProvider(this.getList()); QueryLabelProvider label = new QueryLabelProvider(); this.setContentProvider(content); this.setLabelProvider(label); } /** * This method queries the database and returns the results in an ArrayList with each entry in * the list representing a cohort. */ private List<String[]> createContent(){ Object[] patients = this.patientQuery.execute().toArray(); this.size = patients.length; // required by BackgroundJob this.monitor.beginTask("querying database", this.size); // monitor this.initList(patients); this.calculateContent(patients); this.convertList(); return QueryUtil.convertToString(this.getList()); } private void convertList(){ // all values are converted to doubles this.setList(QueryUtil.createCohorts(this.getList(), this.cohortSize)); this.setList(QueryUtil.addAverage(this.getList(), 2, 3, 4)); this.setList(QueryUtil.addAverage(this.getList(), 7, 8, 9)); this.setList(QueryUtil.addAverage(this.getList(), 2, 1, 5)); this.setList(QueryUtil.addAverage(this.getList(), 7, 6, 10)); // consultation count: QueryUtil.convertDoubleToInteger(this.getList(), 3); QueryUtil.convertDoubleToInteger(this.getList(), 8); // patient count: QueryUtil.convertDoubleToInteger(this.getList(), 1); QueryUtil.convertDoubleToInteger(this.getList(), 6); QueryUtil.convertToCurrency(this.getList(), 2); QueryUtil.convertToCurrency(this.getList(), 4); QueryUtil.convertToCurrency(this.getList(), 5); QueryUtil.convertToCurrency(this.getList(), 7); QueryUtil.convertToCurrency(this.getList(), 9); QueryUtil.convertToCurrency(this.getList(), 10); } private void calculateContent(Object[] patients){ for (int i = 0; i < patients.length; i++) { Patient patient = (Patient) patients[i]; if (!this.validate_data(patient)) { continue; } int year = QueryUtil.extractYear(patient.getGeburtsdatum()); if (year != 0) { if (this.handleCases(patient, year)) { this.increment_patient_counter(patient, year); } } this.monitor.worked(1); // monitor } } /** * Determines the first birth year of all patients and initializes the list containing all * information. The first year in the resulting list is determined by the modulo 5 of the oldest * patients birth year. */ private void initList(Object[] patients){ this.firstCohort = Calendar.getInstance().get(Calendar.YEAR); for (int i = 0; i < patients.length; i++) { int birthYear = QueryUtil.extractYear(((Patient) patients[i]).getGeburtsdatum()); if (this.firstCohort > birthYear && birthYear > 0) { this.firstCohort = this.determineFirstYear(birthYear); } } // year, total costs (consultation), No of consultation, average costs this.setList(QueryUtil.initiateYears(this.firstCohort, 11)); } /** * Returns an integer with the property: integer % 5 == 0 && integer <= birthYear. */ private int determineFirstYear(int birthYear){ if (birthYear % 5 == 0) { return birthYear; } else { int diff = birthYear % 5; assert ((birthYear - diff) % 5 == 0); return (birthYear - diff); } } private boolean handleCases(Patient patient, int birthYear){ Fall[] faelle = patient.getFaelle(); boolean male = this.determineSex(patient); boolean result = false; for (int i = 0; i < faelle.length; i++) { if (this.handleConsultation(faelle[i], birthYear, male)) { result = true; } } return result; } private boolean determineSex(Patient patient){ return patient.getGeschlecht().equals("m"); } /** * returns true if the given date is in the period defined. Format: dd.mm.yyyy */ private boolean inPeriod(String date){ Calendar fallDate = Calendar.getInstance(); try { fallDate = QueryUtil.convertToCalendar(date); } catch (Exception e) { // TODO log e.printStackTrace(); } return (fallDate.compareTo(this.getStartDate()) >= 0 && fallDate.compareTo(this .getEndDate()) <= 0); } private boolean handleConsultation(Fall fall, int birthYear, boolean male){ Konsultation[] consultations = fall.getBehandlungen(false); boolean result = false; for (int i = 0; i < consultations.length; i++) { Konsultation cons = consultations[i]; if (this.inPeriod(cons.getDatum())) { result = true; if (male) { this.add_male(birthYear, cons); } else { this.add_female(birthYear, cons); } } } return result; } private void increment_patient_counter(Patient patient, int year){ int index = this.determineSex(patient) ? 6 : 1; this.getList().get(year - this.firstCohort)[index] = ((Integer) this.getList().get(year - this.firstCohort)[index]) + 1; } private void add_male(int birthYear, Konsultation cons){ this.getList().get(birthYear - this.firstCohort)[7] = (Integer) this.getList().get(birthYear - this.firstCohort)[7] + ((Double) cons.getUmsatz()).intValue(); this.getList().get(birthYear - this.firstCohort)[8] = (Integer) this.getList().get(birthYear - this.firstCohort)[8] + 1; } private void add_female(int birthYear, Konsultation cons){ this.getList().get(birthYear - this.firstCohort)[2] = (Integer) this.getList().get(birthYear - this.firstCohort)[2] + ((Double) cons.getUmsatz()).intValue(); this.getList().get(birthYear - this.firstCohort)[3] = (Integer) this.getList().get(birthYear - this.firstCohort)[3] + 1; } private boolean validate_data(Patient patient){ int birthYear = QueryUtil.extractYear(patient.getGeburtsdatum()); int actualYear = Calendar.getInstance().get(Calendar.YEAR); boolean birth = birthYear <= actualYear ? true : false; boolean gender = patient.getGeschlecht().equals("m") || patient.getGeschlecht().equals("w"); boolean result = birth && gender; if (!birth) { this.showValidationError(patient); } return result; } private void showValidationError(Patient patient){ String patientData = "Bei der Auswertung der Patientendaten ist ein " + "Fehler aufgetreten.\nDieser Patient wird in der Auswertung " + "nicht berücksichtigt.\n\nFolgender Patient hat ein " + "Geburtsdatum in der Zukunft:\n\n"; patientData += patient.getLabel(); SWTHelper.showError("Fehlerhafte Patientendaten", patientData); } @Override public int getSize(){ // TODO determine size return 0; } /** {@inheritDoc} */ @Override public String getDescription(){ return ("Erstellt eine Liste mit der Anzahl an Konsultationen, den totalen " + "sowie den durchschnittlichen Kosten pro Konsultation. Die " + "Kohortengrösse ist definiert als die Anzahl Jahrgänge, die in einer " + "Kohorte zusammengefasst werden sollen."); } /** {@inheritDoc} */ @Override public String getTitle(){ return "Konsultationsauswertung"; } /* -------------------------- meta data --------------------------------- */ /* * The following methods are getter and setter pairs which describe all fields which can be * changed by the user. Each pair is annotated since all information is gained by reflection * with the java reflection framework. */ @GetProperty(value = "Kohortengrösse", index = 2) public String getCohortSize(){ return "" + this.cohortSize; } @SetProperty("Kohortengrösse") public void setCohortSize(String cohortSize) throws SetDataException{ Integer size = new Integer(1); try { size = new Integer(cohortSize); if (size < 1) { throw new Exception(); // size must be greater or equal 1 } this.cohortSize = size; } catch (Exception e) { throw new SetDataException("Kohortengrösse muss eine positive Ganzzahl sein."); } } }