package waelti.statistics.queries;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import waelti.statistics.queries.annotations.GetProperty;
import waelti.statistics.queries.annotations.SetProperty;
import ch.elexis.Hub;
import ch.elexis.actions.AbstractDataLoaderJob;
import ch.elexis.data.Fall;
import ch.elexis.data.Konsultation;
import ch.elexis.data.Patient;
/**
* 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 AbstractQuery {
/** Loader which loads all patients from the database */
private AbstractDataLoaderJob loader = (AbstractDataLoaderJob) Hub.jobPool
.getJob("PatientenListe");
/**
* 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 first date of the calculation period. Default value is the 1.1. of
* the actual year.
*/
private Calendar startDate = null;
/**
* The last date of the calculation period. Default value is the 31.12. of
* the actual year.
*/
private Calendar endDate = null;
/**
* The internal result list of this object. This list has to be converted
* before being used in any table.
*/
private List<Object[]> list;
/** The list containing all header strings for each column. */
private List<String> header;
/** empty constructor */
public Consultations() {
super("consultation stats");
initData();
initHeader();
}
/** Initializes the standard data for this query. */
private void initData() {
this.startDate = Calendar.getInstance();
this.startDate.set(startDate.get(Calendar.YEAR), Calendar.JANUARY, 1);
this.endDate = Calendar.getInstance();
this.endDate
.set(this.endDate.get(Calendar.YEAR), Calendar.DECEMBER, 31);
this.cohortSize = 1;
}
private void initHeader() {
header = new ArrayList<String>(4);
header.add("year of birth");
header.add("total costs");
header.add("No of consultations");
header.add("average");
}
@Override
public List<String> getTableHeadings() {
return this.header;
}
/**
* This method queries the database and returns the results in an ArrayList
* with each entry in the list representing a cohort.
*/
public List<String[]> createContent() {
Object[] patients = (Object[]) loader.getData();
this.initList(patients);
for (int i = 0; i < patients.length; i++) {
Patient patient = (Patient) patients[i];
int year = QueryUtil.extractYear(patient.getGeburtsdatum());
if (year != 0) {
this.handleCases(patient, year);
}
}
// TODO: createCohort changes all to Double. This is necessary for
// a faultles run of the query. Integrate to this query.
this.list = QueryUtil.createCohorts(this.list, this.cohortSize);
this.list = QueryUtil.addAverage(list, 1, 2, 3);
QueryUtil.convertDoubleToInteger(this.list, 2); // consultation count.
QueryUtil.convertToCurrency(list, 1);
QueryUtil.convertToCurrency(list, 3);
return QueryUtil.convertToString(list);
}
/**
* 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
list = QueryUtil.initiateYears(firstCohort, 4);
}
/**
* 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 void handleCases(Patient patient, int birthYear) {
Fall[] faelle = patient.getFaelle();
for (int i = 0; i < faelle.length; i++) {
if (this.inPeriod(faelle[i].getBeginnDatum())) {
this.handleConsultaion(faelle[i], patient, birthYear);
}
}
}
/**
* returns true if the given Fall 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.startDate) >= 0 && fallDate
.compareTo(this.endDate) <= 0);
}
private void handleConsultaion(Fall fall, Patient patient, int birthYear) {
Konsultation[] consultations = fall.getBehandlungen(false);
for (int i = 0; i < consultations.length; i++) {
Konsultation cons = consultations[i];
if (this.inPeriod(cons.getDatum())) {
list.get(birthYear - firstCohort)[1] = (Integer) list
.get(birthYear - firstCohort)[1]
+ ((Double) cons.getUmsatz()).intValue();
list.get(birthYear - firstCohort)[2] = (Integer) list
.get(birthYear - firstCohort)[2] + 1;
}
}
}
@Override
public int getSize() {
// TODO determine size
return 0;
}
/** {@inheritDoc} */
public String getDescription() {
return ("Number of consultations, total costs and average costs over the"
+ "defined period");
}
/** {@inheritDoc} */
public String getTitle() {
return "Consultations";
}
/** {@inheritDoc} */
@Override
public List<String[]> getContent() {
if (this.list != null) {
return QueryUtil.convertToString(this.list);
} else {
return null;
}
}
@Override
public String getHeader() {
String str = super.getHeader();
str += "\nKohortengrösse: " + this.cohortSize;
str += "\nAuswertungszeitraum: "
+ QueryUtil.convertFromCalendar(this.startDate);
str += " - " + QueryUtil.convertFromCalendar(this.endDate);
return str;
}
/*-------------------------- metadata ---------------------------------*/
/*
* 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.
*/
/** Get the start date of this query. Inclusive. */
@GetProperty("Anfangsdatum")
public String getStartDate() {
return QueryUtil.convertFromCalendar(this.startDate);
}
/**
* Set the start date of this query. Inclusive the given date. Format of the
* string has to be d[d].m[m].yyyy
*
* @throws SetDataException
*/
@SetProperty("Anfangsdatum")
public void setStartDate(String startDate) throws SetDataException {
try {
this.startDate = QueryUtil.convertToCalendar(startDate);
} catch (Exception e) {
System.out.println("Anfangsdatum failed"); // TODO debug
throw new SetDataException(
"Anfangsdatum nicht im richtigen Format: dd.mm.yyy");
}
}
/** Get the end date of this query. Inclusive. */
@GetProperty("Enddatum")
public String getEndDate() {
return QueryUtil.convertFromCalendar(this.endDate);
}
/**
* Set the end date of this query. Inclusive the given date. The string has
* to be in this format: d[d].m[m].yyyy
*
* @throws SetDataException
*/
@SetProperty("Enddatum")
public void setEndDate(String endDate) throws SetDataException {
try {
this.endDate = QueryUtil.convertToCalendar(endDate);
} catch (Exception e) {
System.out.println("Enddatum failed"); // TODO debug
throw new SetDataException(
"Enddatum nicht im richtigen Format: dd.mm.yyy");
}
}
@GetProperty("Kohortengrösse")
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);
this.cohortSize = size;
} catch (Exception e) {
throw new SetDataException(
"Kohortengrösse muss eine Ganzzahl sein.");
}
}
}