package entity.values; import entity.building.Station; import entity.building.StationTools; import entity.info.Resident; import entity.info.ResidentTools; import gui.GUITools; import op.OPDE; import op.tools.Pair; import op.tools.SYSCalendar; import op.tools.SYSConst; import op.tools.SYSTools; import org.apache.commons.collections.Closure; import org.joda.time.DateMidnight; import org.joda.time.DateTime; import org.joda.time.LocalDate; import javax.persistence.EntityManager; import javax.persistence.Query; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.Format; import java.text.SimpleDateFormat; import java.util.*; /** * Created by IntelliJ IDEA. * User: tloehr * Date: 28.10.11 * Time: 16:41 * To change this template use File | Settings | File Templates. */ public class ResValueTools { // weight adjustment percentages for amputation public static final BigDecimal FOOT = new BigDecimal(1.8); public static final BigDecimal BELOW_KNEE = new BigDecimal(6); public static final BigDecimal ABOVE_KNEE = new BigDecimal(15); public static final BigDecimal ENTIRE_LOWER_EXTREMITY = new BigDecimal(18.5); public static final BigDecimal HAND = new BigDecimal(1); public static final BigDecimal BELOW_ELLBOW = new BigDecimal(3); public static final BigDecimal ABOVE_ELLBOW = new BigDecimal(5); public static final BigDecimal ENTIRE_UPPER_EXTREMITY = new BigDecimal(6.5); // public static final String[] VALUES = new String[]{"DBVERSION_UNKNOWN", "RR", "PULSE", "TEMP", "GLUCOSE", "WEIGHT", "HEIGHT", "BREATHING", "QUICK", "STOOL", "VOMIT", "LIQUIDBALANCE"}; // public static final String[] UNITS = new String[]{"", "mmHg", "s/m", "°C", "mg/dl", "kg", "m", "A/m", "%", "", "", "ml"}; public static final String RRSYS = "systolisch"; public static final String RRDIA = "diatolisch"; /** * Rendert eine HTML Darstellung des Datums und des Benutzers eines bestimmten Bewohner Wertes * * @param bwert * @param showids * @param colorize * @return */ public static String getPITasHTML(ResValue bwert, boolean showids, boolean colorize) { SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd.MM.yyyy HH:mm"); String color = ""; if (colorize) { if (bwert.isReplaced() || bwert.isDeleted()) { color = SYSConst.html_lightslategrey; } else { color = GUITools.getHTMLColor(SYSCalendar.getFGItem(SYSCalendar.whatShiftIs(bwert.getPit()))); } } String result = sdf.format(bwert.getPit()) + "; " + bwert.getUser().getFullname(); if (showids) { result += "<br/><i>[" + bwert.getID() + "]</i>"; } return (colorize ? "<font " + color + " " + SYSConst.html_arial14 + ">" + result + "</font>" : result); } public static ArrayList<Integer> getYearsWithValues(Resident resident, ResValueTypes type) { EntityManager em = OPDE.createEM(); Query query = em.createNativeQuery("SELECT DISTINCT(YEAR(PIT)) j FROM resvalue WHERE BWKennung = ? AND TYPE = ? ORDER BY j DESC"); query.setParameter(1, resident.getRID()); query.setParameter(2, type.getValType()); ArrayList<Integer> result = new ArrayList<Integer>(query.getResultList()); em.close(); return result; } // public static ArrayList<Date> getDaysWithValues(Resident resident, ResValueTypes type, int year) { // DateTime from = new LocalDate(year, 1, 1).dayOfYear().withMinimumValue().toDateTimeAtStartOfDay(); // DateTime to = new LocalDate(year, 1, 1).dayOfYear().withMaximumValue().toDateTimeAtStartOfDay().secondOfDay().withMaximumValue(); // // EntityManager em = OPDE.createEM(); // Query query = em.createNativeQuery(" " + // " SELECT DISTINCT DATE(r.pit) d" + // " FROM resvalue r " + // " INNER JOIN resvaluetypes t ON r.type = t.id " + // " WHERE DATE(r.pit) >= ? AND DATE(r.pit) <= ? AND r.bwkennung = ? AND t.valtype = ? " + // " GROUP BY DATE(r.pit)" + // " ORDER BY d DESC"); // // query.setParameter(1, from.toDate()); // query.setParameter(2, to.toDate()); // query.setParameter(3, resident.getRID()); // query.setParameter(4, type.getValType()); // ArrayList<Date> result = new ArrayList<Date>(query.getResultList()); // em.close(); // return result; // } /** * Ermittelt den ersten bisher eingetragenen Wert für einen Bewohner. * * @param bewohner * @return */ public static ResValue getFirst(Resident bewohner) { EntityManager em = OPDE.createEM(); Query query = em.createQuery("SELECT b FROM ResValue b WHERE b.resident = :bewohner ORDER BY b.pit "); query.setParameter("bewohner", bewohner); query.setMaxResults(1); ResValue p = (ResValue) query.getSingleResult(); em.close(); return p; } /** * Ermittelt den jeweils zuletzt eingetragenen Wert. * * @param resident um den es geht * @param type des gesuchten Wertes * @return der Wert. <code>null</code>, wenn es keinen gibt. */ public static ResValue getLast(Resident resident, short type) { ResValue result; EntityManager em = OPDE.createEM(); Query query = em.createQuery(" " + " SELECT b FROM ResValue b WHERE b.resident = :bewohner AND b.replacedBy IS NULL AND b.vtype.valType = :type " + " ORDER BY b.pit DESC "); query.setMaxResults(1); query.setParameter("bewohner", resident); query.setParameter("type", type); try { result = (ResValue) query.getSingleResult(); } catch (Exception e) { result = null; } finally { em.close(); } return result; } public static String getInfoAsHTML(ResValue resValue) { String result = "<div id=\"fonttext\">"; DateFormat df = DateFormat.getDateTimeInstance(); if (resValue.isDeleted()) { result += SYSTools.xx("misc.msg.thisentryhasbeendeleted") + " <br/>" + SYSTools.xx("misc.msg.atchrono") + " " + df.format(resValue.getEditDate()) + " <br/>" + SYSTools.xx("misc.msg.Bywhom") + " " + resValue.getEditedBy().getFullname() + "<br/>"; } if (resValue.isReplacement() && !resValue.isReplaced()) { result += SYSTools.xx("misc.msg.thisEntryIsAReplacement") + " <br/>" + SYSTools.xx("misc.msg.atchrono") + " " + df.format(resValue.getCreateDate()) + "<br/>" + SYSTools.xx("misc.msg.originalentry") + ": " + resValue.getReplacementFor().getID() + "<br/>"; } if (resValue.isReplaced()) { result += SYSTools.xx("misc.msg.thisentryhasbeenedited") + " <br/>" + SYSTools.xx("misc.msg.atchrono") + " " + df.format(resValue.getCreateDate()) + "<br/>" + SYSTools.xx("misc.msg.Bywhom") + " " + resValue.getEditedBy().getFullname(); result += "<br/>" + SYSTools.xx("misc.msg.replaceentry") + ": " + resValue.getReplacedBy().getID() + "</i><br/>"; } if (!resValue.getText().trim().isEmpty()) { result += "<br/>" + SYSConst.html_bold("misc.msg.comment") + ":"; result += SYSConst.html_paragraph(resValue.getText().trim()); } return result + "</div>"; } // // // public static String getTitle(ResValue param) { // String result = ""; // if (param.getType() == RR) { // result += "<b>" + param.getValue1() + "/" + param.getValue2() + " " + UNITS[RR] + " " + VALUES[PULSE] + ": " + param.getValue3() + " " + UNITS[PULSE] + "</b>"; // } else if (param.getType() == STOOL || param.getType() == VOMIT) { // result += "<i>" + SYSTools.xx("misc.msg.novalue") + "</i>"; // } else { // result += "<b>" + param.getValue1() + " " + UNITS[param.getType()] + "</b>"; // } // return result; // } public static String getTextAsHTML(ResValue wert, boolean colorize) { String result = ""; if (!SYSTools.catchNull(wert.getText()).isEmpty()) { String color = ""; if (colorize) { if (wert.isReplaced() || wert.isDeleted()) { color = SYSConst.html_lightslategrey; } else { color = GUITools.getHTMLColor(SYSCalendar.getFGItem(SYSCalendar.whatShiftIs(wert.getPit()))); } } result = "<font " + color + " " + SYSConst.html_arial14 + ">" + "<b>" + SYSTools.xx("misc.msg.comment") + ":</b> " + wert.getText() + "</font>"; } return result; } public static String getAsHTML(List<ResValue> resValues) { if (resValues.isEmpty()) { return SYSConst.html_italic("misc.msg.noentryyet"); } String html = ""; html += SYSConst.html_h1(resValues.get(0).getType().getText()); html += SYSConst.html_h2(ResidentTools.getLabelText(resValues.get(0).getResident())); html += "<table id=\"fonttext\" border=\"1\" cellspacing=\"0\"><tr>" + "<th style=\"width:20%\">" + SYSTools.xx("nursingrecords.vitalparameters.tabheader1") + "</th><th style=\"width:40%\">" + SYSTools.xx("nursingrecords.vitalparameters.tabheader2") + "</th>" + "</th><th style=\"width:40%\">" + SYSTools.xx("nursingrecords.vitalparameters.tabheader3") + "</th></tr>\n"; for (ResValue resValue : resValues) { html += "<tr>"; html += "<td>"; html += resValue.isReplaced() ? SYSConst.html_22x22_Eraser + " " : ""; html += resValue.isReplacement() ? SYSConst.html_22x22_Edited + " " : ""; html += getPITasHTML(resValue, true, false); html += "</td>"; html += "<td>" + getAsHTML(resValue) + "</td>"; html += "<td>" + getTextAsHTML(resValue, false) + "</td>"; html += "</tr>\n"; } html += "</table>\n"; return html; } public static String getAsHTML(ResValue rv) { String result = ""; result += getInfoAsHTML(rv); result += getValueAsHTML(rv); // result += " (" + VALUES[rv.getType()] + ")"; return "<div = \"fonttext\">" + result + "</div>"; } public static boolean hatEinfuhren(Resident bewohner) { boolean result = false; EntityManager em = OPDE.createEM(); Query query = em.createQuery("SELECT SUM(b.val1) FROM ResValue b WHERE b.val1 > 0 AND b.replacedBy IS NULL AND b.resident = :bewohner AND b.vtype.valType = :type AND b.pit >= :pit "); query.setParameter("bewohner", bewohner); query.setParameter("type", ResValueTypesTools.LIQUIDBALANCE); query.setParameter("pit", new DateTime().minusWeeks(1).toDateMidnight().toDate()); BigDecimal sumwert = (BigDecimal) query.getSingleResult(); result = sumwert != null && sumwert.abs().compareTo(BigDecimal.ZERO) > 0; return result; } public static boolean hatAusfuhren(Resident bewohner) { boolean result = false; EntityManager em = OPDE.createEM(); Query query = em.createQuery("SELECT SUM(b.val1) FROM ResValue b WHERE b.val1 < 0 AND b.replacedBy IS NULL AND b.resident = :bewohner AND b.vtype.valType = :type AND b.pit >= :pit "); query.setParameter("bewohner", bewohner); query.setParameter("type", ResValueTypesTools.LIQUIDBALANCE); query.setParameter("pit", new DateTime().minusWeeks(1).toDateMidnight().toDate()); BigDecimal sumwert = (BigDecimal) query.getSingleResult(); result = sumwert != null && sumwert.abs().compareTo(BigDecimal.ZERO) > 0; return result; } // /** // * retrieves the PITs of the first and the last entry in the ResValue table. // * // * @param resident // * @return // */ // public static Pair<DateTime, DateTime> getMinMax(Resident resident, ResValueTypes vtype) { // Pair<DateTime, DateTime> result = null; // // EntityManager em = OPDE.createEM(); // Query queryMin = em.createQuery("SELECT rv FROM ResValue rv WHERE rv.resident = :resident AND rv.vtype = :vtype ORDER BY rv.pit ASC "); // queryMin.setParameter("resident", resident); // queryMin.setParameter("vtype", vtype); // queryMin.setMaxResults(1); // // Query queryMax = em.createQuery("SELECT rv FROM ResValue rv WHERE rv.resident = :resident AND rv.vtype = :vtype ORDER BY rv.pit DESC "); // queryMax.setParameter("resident", resident); // queryMax.setParameter("vtype", vtype); // queryMax.setMaxResults(1); // // try { // ArrayList<ResValue> min = new ArrayList<ResValue>(queryMin.getResultList()); // ArrayList<ResValue> max = new ArrayList<ResValue>(queryMax.getResultList()); // if (min.isEmpty()) { // result = null; // } else { // result = new Pair<DateTime, DateTime>(new DateTime(min.get(0).getPit()), new DateTime(max.get(0).getPit())); // } // // } catch (Exception e) { // OPDE.fatal(e); // } // return result; // } // // public static ArrayList<ResValue> getResValues(Resident resident, ResValueTypes vtype) { // EntityManager em = OPDE.createEM(); // Query query = em.createQuery("" + // " SELECT rv FROM ResValue rv " + // " WHERE rv.resident = :resident " + // " AND rv.vtype = :vtype" + // " ORDER BY rv.pit DESC "); // query.setParameter("resident", resident); // query.setParameter("vtype", vtype); // ArrayList<ResValue> list = new ArrayList<ResValue>(query.getResultList()); // em.close(); // // return list; // } public static ArrayList<ResValue> getResValues(Resident resident, short type, LocalDate f, LocalDate t) { // DateTime theYear = new DateTime(year, 1, 1, 0, 0, 0); DateTime from = f.toDateTimeAtStartOfDay(); DateTime to = SYSCalendar.eod(t); EntityManager em = OPDE.createEM(); Query query = em.createQuery("" + " SELECT rv FROM ResValue rv " + " WHERE rv.resident = :resident " + " AND rv.pit >= :from" + " AND rv.pit <= :to" + " AND rv.vtype.valType = :type" + " ORDER BY rv.pit DESC "); query.setParameter("resident", resident); query.setParameter("type", type); query.setParameter("from", from.toDate()); query.setParameter("to", to.toDate()); ArrayList<ResValue> list = new ArrayList<ResValue>(query.getResultList()); em.close(); return list; } public static ArrayList<ResValue> getPainvalues(LocalDate f, LocalDate t) { // DateTime theYear = new DateTime(year, 1, 1, 0, 0, 0); DateTime from = f.toDateTimeAtStartOfDay(); DateTime to = SYSCalendar.eod(t); EntityManager em = OPDE.createEM(); Query query = em.createQuery("" + " SELECT rv FROM ResValue rv " + " WHERE rv.pit >= :from" + " AND rv.pit <= :to" + " AND rv.vtype.valType = :type" + " AND rv.editedBy IS NULL " + " ORDER BY rv.pit DESC "); query.setParameter("type", ResValueTypesTools.PAIN); query.setParameter("from", from.toDate()); query.setParameter("to", to.toDate()); ArrayList<ResValue> list = new ArrayList<ResValue>(query.getResultList()); em.close(); return list; } public static ArrayList<ResValue> getResValuesNoEdits(Resident resident, short type, LocalDate f, LocalDate t) { // DateTime theYear = new DateTime(year, 1, 1, 0, 0, 0); DateTime from = f.toDateTimeAtStartOfDay(); DateTime to = SYSCalendar.eod(t); EntityManager em = OPDE.createEM(); Query query = em.createQuery("" + " SELECT rv FROM ResValue rv " + " WHERE rv.resident = :resident " + " AND rv.pit >= :from" + " AND rv.pit <= :to" + " AND rv.vtype.valType = :type " + " AND rv.editedBy IS NULL " + " ORDER BY rv.pit DESC "); query.setParameter("resident", resident); query.setParameter("type", type); query.setParameter("from", from.toDate()); query.setParameter("to", to.toDate()); ArrayList<ResValue> list = new ArrayList<ResValue>(query.getResultList()); em.close(); return list; } public static ArrayList<ResValue> getResValues(Resident resident, ResValueTypes vtype, LocalDate day) { // // DateTime theYear = new DateTime(year, 1, 1, 0, 0, 0); // DateTime from = day.toDateTime().secondOfDay().withMinimumValue(); // DateTime to = day.toDateTime().secondOfDay().withMaximumValue(); EntityManager em = OPDE.createEM(); Query query = em.createQuery("" + " SELECT rv FROM ResValue rv " + " WHERE rv.resident = :resident " + " AND rv.vtype = :vtype" + " AND rv.pit >= :from" + " AND rv.pit <= :to" + " ORDER BY rv.pit DESC "); query.setParameter("resident", resident); query.setParameter("vtype", vtype); query.setParameter("from", day.toDateTimeAtStartOfDay().toDate()); query.setParameter("to", SYSCalendar.eod(day).toDate()); ArrayList<ResValue> list = new ArrayList<ResValue>(query.getResultList()); em.close(); return list; } public static ArrayList<ResValue> getResValues(Resident resident, ResValueTypes vtype, int year) { // DateTime theYear = new DateTime(year, 1, 1, 0, 0, 0); DateTime from = SYSCalendar.boy(year); DateTime to = SYSCalendar.eoy(year); EntityManager em = OPDE.createEM(); Query query = em.createQuery("" + " SELECT rv FROM ResValue rv " + " WHERE rv.resident = :resident " + " AND rv.vtype = :vtype" + " AND rv.pit >= :from" + " AND rv.pit <= :to" + " ORDER BY rv.pit DESC "); query.setParameter("resident", resident); query.setParameter("vtype", vtype); query.setParameter("from", from.toDate()); query.setParameter("to", to.toDate()); ArrayList<ResValue> list = new ArrayList<ResValue>(query.getResultList()); em.close(); return list; } public static String getValueAsHTML(ResValue rv) { String result = (rv.isDeleted() || rv.isReplaced() ? "<s>" : ""); // NumberFormat dcf = DecimalFormat.getNumberInstance(); if (rv.getType().getValType() == ResValueTypesTools.RR) { DecimalFormat dcf1 = new DecimalFormat(rv.getType().getFormat1()); DecimalFormat dcf2 = new DecimalFormat(rv.getType().getFormat2()); DecimalFormat dcf3 = new DecimalFormat(rv.getType().getFormat3()); result += "<b>" + dcf1.format(rv.getVal1()) + "/" + dcf2.format(rv.getVal2()) + " " + rv.getType().getUnit1() + " " + rv.getType().getLabel3() + ": " + dcf3.format(rv.getVal3()) + " " + rv.getType().getUnit3() + "</b>"; } else if (rv.getType().getValType() == ResValueTypesTools.STOOL || rv.getType().getValType() == ResValueTypesTools.VOMIT || rv.getType().getValType() == ResValueTypesTools.ASPIRATION) { result += "<i>" + SYSTools.catchNull(rv.getText(), "--") + "</i>"; } else { DecimalFormat dcf = new DecimalFormat(rv.getType().getFormat1()); result += "<b>" + dcf.format(rv.getVal1()) + " " + SYSTools.catchNull(rv.getType().getUnit1()) + "</b>"; } result += (rv.isDeleted() || rv.isReplaced() ? "</s>" : ""); return result; } public static String getLiquidBalance(LocalDate month, Closure progress) { ArrayList<Resident> listResidents = ResidentTools.getAllActive(month); Format monthFormmatter = new SimpleDateFormat("MMMM yyyy"); DateTime from = SYSCalendar.bom(month).toDateTimeAtStartOfDay(); DateTime to = SYSCalendar.eod(SYSCalendar.eom(month)); int p = -1; progress.execute(new Pair<Integer, Integer>(p, listResidents.size())); StringBuilder html = new StringBuilder(1000); html.append(SYSConst.html_h1(SYSTools.xx("opde.controlling.nutrition.liquidbalance"))); html.append(SYSConst.html_h2(monthFormmatter.format(month.toDate()))); p = 0; for (Resident resident : listResidents) { p++; progress.execute(new Pair<Integer, Integer>(p, listResidents.size())); Properties controlling = resident.getControlling(); if (controlling.containsKey(ResidentTools.KEY_BALANCE) && controlling.getProperty(ResidentTools.KEY_BALANCE).equals("on")) { BigDecimal targetIn = SYSTools.parseDecimal(controlling.getProperty(ResidentTools.KEY_TARGETIN)); html.append(SYSConst.html_h3(ResidentTools.getTextCompact(resident))); html.append(SYSConst.html_div(SYSConst.html_bold(SYSTools.xx("misc.msg.targetDrink")) + ": " + SYSTools.formatBigDecimal(targetIn.setScale(2, RoundingMode.HALF_UP)) + " ml")); HashMap<LocalDate, Pair<BigDecimal, BigDecimal>> balanceMap = getLiquidBalancePerDay(resident, from.toLocalDate(), to.toLocalDate()); ArrayList<LocalDate> listDays = new ArrayList<>(balanceMap.keySet()); Collections.sort(listDays); StringBuilder table = new StringBuilder(1000); table.append(SYSConst.html_table_tr( SYSConst.html_table_th(SYSTools.xx("misc.msg.Date")) + SYSConst.html_table_th(SYSTools.xx("misc.msg.ingestion")) + SYSConst.html_table_th(SYSTools.xx("misc.msg.egestion")) + SYSConst.html_table_th(SYSTools.xx("misc.msg.balance")) )); for (LocalDate day : listDays) { BigDecimal linesum = balanceMap.get(day).getFirst().add(balanceMap.get(day).getSecond()); table.append(SYSConst.html_table_tr( SYSConst.html_table_td(DateFormat.getDateInstance().format(day.toDate()), null) + SYSConst.html_table_td(SYSTools.formatBigDecimal(balanceMap.get(day).getFirst().setScale(2, RoundingMode.HALF_UP)), "right") + SYSConst.html_table_td(SYSTools.formatBigDecimal(balanceMap.get(day).getSecond().setScale(2, RoundingMode.HALF_UP)), "right") + SYSConst.html_table_td(SYSTools.formatBigDecimal(linesum.setScale(2, RoundingMode.HALF_UP)), "right") )); } html.append(SYSConst.html_table(table.toString(), "1")); } } return html.toString(); } /** * creates a combined weight and bmi statistics for the given period in html. bmi is only calculated if there is a height available for the particular resident. * * @param monthsback number of months from now on. starts always at the beginning of that month. * @param progress * @return */ public static String getWeightStats(int monthsback, Closure progress) { StringBuffer html = new StringBuffer(1000); int p = -1; progress.execute(new Pair<Integer, Integer>(p, 100)); DateMidnight from = new DateMidnight().minusMonths(monthsback).dayOfMonth().withMinimumValue(); EntityManager em = OPDE.createEM(); DateFormat df = DateFormat.getDateInstance(); String jpql = " " + " SELECT rv " + " FROM ResValue rv " + " WHERE rv.vtype.valType = :valType " + " AND rv.resident.adminonly <> 2 " + " AND rv.pit >= :from " + " ORDER BY rv.resident.name, rv.resident.firstname, rv.pit "; Query query = em.createQuery(jpql); query.setParameter("valType", ResValueTypesTools.WEIGHT); query.setParameter("from", from.toDate()); ArrayList<ResValue> listVal = new ArrayList<ResValue>(query.getResultList()); em.close(); HashMap<Resident, ArrayList<ResValue>> listData = new HashMap<Resident, ArrayList<ResValue>>(); for (ResValue val : listVal) { if (!listData.containsKey(val.getResident())) { listData.put(val.getResident(), new ArrayList<ResValue>()); } listData.get(val.getResident()).add(val); } ArrayList<Resident> listResidents = new ArrayList<Resident>(listData.keySet()); Collections.sort(listResidents); html.append(SYSConst.html_h1(SYSTools.xx("opde.controlling.nutrition.weightstats"))); html.append(SYSConst.html_h2(SYSTools.xx("misc.msg.analysis") + ": " + df.format(from.toDate()) + " »» " + df.format(new Date()))); ResValueTypes heightType = ResValueTypesTools.getType(ResValueTypesTools.HEIGHT); ResValueTypes weightType = ResValueTypesTools.getType(ResValueTypesTools.WEIGHT); p = 0; for (Resident resident : listResidents) { progress.execute(new Pair<Integer, Integer>(p, listResidents.size())); p++; html.append(SYSConst.html_h3(ResidentTools.getTextCompact(resident))); ResValue height = getLast(resident, ResValueTypesTools.HEIGHT); html.append( SYSConst.html_div( heightType.getText() + ": " + (height == null ? SYSTools.xx("misc.msg.noentryyet") : SYSTools.formatBigDecimal(height.getVal1().setScale(2, RoundingMode.HALF_UP)) + " " + heightType.getUnit1()) ) ); BigDecimal prevWeight = null; BigDecimal prevBMI = null; StringBuffer table = new StringBuffer(1000); table.append(SYSConst.html_table_tr( SYSConst.html_table_th("misc.msg.Date") + SYSConst.html_table_th(weightType.getText()) + SYSConst.html_table_th("misc.msg.comment") + SYSConst.html_table_th("+-") + SYSConst.html_table_th("BMI") + SYSConst.html_table_th("+-") )); for (ResValue weight : listData.get(resident)) { BigDecimal bmi = height == null ? null : weight.getVal1().divide(height.getVal1().pow(2), 2, RoundingMode.HALF_UP); BigDecimal divWeight = prevWeight == null ? null : weight.getVal1().subtract(prevWeight); BigDecimal divBMI = prevBMI == null ? null : bmi.subtract(prevBMI); table.append(SYSConst.html_table_tr( SYSConst.html_table_td(df.format(weight.getPit())) + SYSConst.html_table_td(SYSTools.formatBigDecimal(weight.getVal1().setScale(2, RoundingMode.HALF_UP)), "right") + SYSConst.html_table_td(SYSTools.catchNull(weight.getText(), "--"), weight.getText() == null ? "center" : "left") + SYSConst.html_table_td(SYSTools.catchNull(SYSTools.formatBigDecimal(divWeight), "--"), divWeight == null ? "center" : "right") + SYSConst.html_table_td(SYSTools.catchNull(SYSTools.formatBigDecimal(bmi), "--"), bmi == null ? "center" : "right") + SYSConst.html_table_td(SYSTools.catchNull(SYSTools.formatBigDecimal(divBMI), "--"), divBMI == null ? "center" : "right") )); prevBMI = bmi; prevWeight = weight.getVal1(); } // Stats over the whole analysis period ResValue firstValue = listData.get(resident).get(0); BigDecimal firstBMI = height == null ? null : firstValue.getVal1().divide(height.getVal1().pow(2), 2, RoundingMode.HALF_UP); BigDecimal divWeight = prevWeight.subtract(firstValue.getVal1()); BigDecimal divBMI = firstBMI == null || prevBMI == null ? null : prevBMI.subtract(firstBMI); table.append(SYSConst.html_table_tr( SYSConst.html_table_th("misc.msg.completePeriod") + SYSConst.html_table_th("--", "center") + SYSConst.html_table_th("--", "center") + SYSConst.html_table_th(SYSTools.catchNull(divWeight, "--"), divWeight == null ? "center" : "right") + SYSConst.html_table_th("--", "center") + SYSConst.html_table_th(SYSTools.catchNull(divBMI, "--"), divBMI == null ? "center" : "right") )); html.append(SYSConst.html_table(table.toString(), "1")); } return html.toString(); } public static HashMap<LocalDate, Pair<BigDecimal, BigDecimal>> getLiquidBalancePerDay(Resident resident, LocalDate from, LocalDate to) { // First BD is for the influx, second for the outflow EntityManager em = OPDE.createEM(); Query query = em.createQuery("" + " SELECT rv FROM ResValue rv " + " WHERE rv.resident = :resident " + " AND rv.replacedBy IS NULL " + " AND rv.editedBy IS NULL " + " AND rv.vtype.valType = :valType" + " AND rv.pit >= :from" + " AND rv.pit <= :to" + " ORDER BY rv.pit DESC "); query.setParameter("resident", resident); query.setParameter("valType", ResValueTypesTools.LIQUIDBALANCE); query.setParameter("from", from.toDateTimeAtStartOfDay().toDate()); query.setParameter("to", SYSCalendar.eod(to).toDate()); ArrayList<ResValue> list = null; list = new ArrayList<ResValue>(query.getResultList()); em.close(); // init with dates. so that there are now "empty" days HashMap<LocalDate, Pair<BigDecimal, BigDecimal>> hm = new HashMap<>(); for (LocalDate day = from; day.compareTo(to) <= 0; day = day.plusDays(1)) { hm.put(day, new Pair<>(BigDecimal.ZERO, BigDecimal.ZERO)); } for (ResValue val : list) { Pair<BigDecimal, BigDecimal> pair = hm.get(new LocalDate(val.getPit())); BigDecimal ingestion = pair.getFirst(); BigDecimal egestion = pair.getSecond(); if (val.getVal1().compareTo(BigDecimal.ZERO) < 0) { egestion = egestion.add(val.getVal1().abs()); } else { ingestion = ingestion.add(val.getVal1()); } hm.put(new LocalDate(val.getPit()), new Pair<>(ingestion, egestion)); } return hm; } // public static BigDecimal getIngestion(Resident resident, LocalDate day) { // // First BD is for the influx, second for the outflow // EntityManager em = OPDE.createEM(); // Query query = em.createQuery("" + // " SELECT SUM(rv.val1) FROM ResValue rv " + // " WHERE rv.resident = :resident " + // " AND rv.replacedBy IS NULL " + // " AND rv.editedBy IS NULL " + // " AND rv.val1 > 0 " + // " AND rv.vtype.valType = :valType " + // " AND rv.pit >= :from " + // " AND rv.pit <= :to "); // // query.setParameter("resident", resident); // query.setParameter("valType", ResValueTypesTools.LIQUIDBALANCE); // query.setParameter("from", day.toDateTimeAtStartOfDay().toDate()); // query.setParameter("to", SYSCalendar.eod(day).toDate()); // BigDecimal sum = (BigDecimal) query.getSingleResult(); // em.close(); // // return sum == null ? BigDecimal.ZERO : sum; // } // // public static BigDecimal getEgestion(Resident resident, LocalDate day) { // // First BD is for the influx, second for the outflow // EntityManager em = OPDE.createEM(); // Query query = em.createQuery("" + // " SELECT SUM(rv.val1) FROM ResValue rv " + // " WHERE rv.resident = :resident " + // " AND rv.replacedBy IS NULL " + // " AND rv.editedBy IS NULL " + // " AND rv.val1 < 0 " + // " AND rv.vtype.valType = :valType " + // " AND rv.pit >= :from " + // " AND rv.pit <= :to "); // // query.setParameter("resident", resident); // query.setParameter("valType", ResValueTypesTools.LIQUIDBALANCE); // query.setParameter("from", day.toDateTimeAtStartOfDay().toDate()); // query.setParameter("to", SYSCalendar.eod(day).toDate()); // BigDecimal sum = (BigDecimal) query.getSingleResult(); // em.close(); // // return sum == null ? BigDecimal.ZERO : sum; // } // public static BigDecimal getAvgIn(Resident resident, DateMidnight month) { // DateTime from = month.dayOfMonth().withMinimumValue().toDateTime(); // DateTime to = month.dayOfMonth().withMaximumValue().plusDays(1).toDateTime().minusSeconds(1); // // // First BD is for the influx, second for the outflow // EntityManager em = OPDE.createEM(); // Query query = em.createQuery("" + // " SELECT AVG(rv.val1) FROM ResValue rv " + // " WHERE rv.resident = :resident " + // " AND rv.replacedBy IS NULL " + // " AND rv.vtype.valType = :valType" + // " AND rv.val1 >= 0 " + // " AND rv.pit >= :from" + // " AND rv.pit <= :to" + // " ORDER BY rv.pit DESC "); // query.setParameter("resident", resident); // query.setParameter("valType", ResValueTypesTools.LIQUIDBALANCE); // query.setParameter("from", from.toDate()); // query.setParameter("from", to.plusDays(1).toDateTime().minusSeconds(1).toDate()); // BigDecimal avg = (BigDecimal) query.getSingleResult(); // em.close(); // // return avg == null ? BigDecimal.ZERO : avg; // } public static HashMap<LocalDate, BigDecimal> getLiquidIn(Resident resident, LocalDate from) { EntityManager em = OPDE.createEM(); Query query = em.createQuery("" + " SELECT rv FROM ResValue rv " + " WHERE rv.resident = :resident " + " AND rv.replacedBy IS NULL " + " AND rv.vtype.valType = :valType " + " AND rv.val1 > 0 " + " AND rv.pit >= :from" + " ORDER BY rv.pit DESC "); query.setParameter("resident", resident); query.setParameter("valType", ResValueTypesTools.LIQUIDBALANCE); query.setParameter("from", from.toDate()); ArrayList<ResValue> list = new ArrayList<ResValue>(query.getResultList()); em.close(); HashMap<LocalDate, BigDecimal> hm = new HashMap<LocalDate, BigDecimal>(); for (LocalDate day = from; day.compareTo(new LocalDate()) <= 0; day = day.plusDays(1)) { hm.put(day, BigDecimal.ZERO); } for (ResValue val : list) { BigDecimal bd = hm.get(new LocalDate(val.getPit())); hm.put(new LocalDate(val.getPit()), bd.add(val.getVal1())); } return hm; } // public static HashMap<DateMidnight, BigDecimal> getLiquidOut(Resident resident, DateMidnight from) { // EntityManager em = OPDE.createEM(); // Query query = em.createQuery("" + // " SELECT rv FROM ResValue rv " + // " WHERE rv.resident = :resident " + // " AND rv.replacedBy IS NULL " + // " AND rv.vtype.valType = :valType " + // " AND rv.val1 < 0 " + // " AND rv.pit >= :from" + // " ORDER BY rv.pit DESC "); // query.setParameter("resident", resident); // query.setParameter("valType", ResValueTypesTools.LIQUIDBALANCE); // query.setParameter("from", from.toDate()); // ArrayList<ResValue> list = new ArrayList<ResValue>(query.getResultList()); // em.close(); // // HashMap<DateMidnight, BigDecimal> hm = new HashMap<DateMidnight, BigDecimal>(); // for (DateMidnight day = from; day.compareTo(new DateMidnight()) <= 0; day = day.plusDays(1)) { // hm.put(day, BigDecimal.ZERO); // } // // for (ResValue val : list) { // BigDecimal bd = hm.get(new DateMidnight(val.getPit())); // hm.put(new DateMidnight(val.getPit()), bd.add(val.getVal1())); // } // // return hm; // } /** * returns a list of triples of {Resident, ResValue, int} for residents which havent had a stool in the last int days. * The ResValue denotes the last stool, if there was any. NULL otherwise. * * @return */ public static ArrayList<Object[]> getNoStool() { ArrayList<Object[]> result = new ArrayList<Object[]>(); Station currentStation = StationTools.getStationForThisHost(); ArrayList<Resident> listResident = ResidentTools.getAllActive(currentStation.getHome()); // DateTime now = new DateTime(); LocalDate now = new LocalDate(); for (Resident resident : listResident) { Properties controlling = resident.getControlling(); // if the controlling was just set its not necessary to look too far into the past // #24 String sDate = controlling.getProperty(ResidentTools.KEY_DATE1); LocalDate startingOn = null; if (sDate != null) { startingOn = new LocalDate(sDate); } if (controlling.containsKey(ResidentTools.KEY_STOOLDAYS) && !controlling.getProperty(ResidentTools.KEY_STOOLDAYS).equals("off")) { int days = Integer.parseInt(controlling.getProperty(ResidentTools.KEY_STOOLDAYS)); if (startingOn == null || now.minusDays(days).compareTo(startingOn) >= 0) { startingOn = now.minusDays(days); } ResValue lastStool = getLast(resident, ResValueTypesTools.STOOL); if (lastStool == null || new DateTime(lastStool.getPit()).toLocalDate().isBefore(startingOn)) { result.add(new Object[]{resident, lastStool, days}); } } } listResident.clear(); return result; } public static ArrayList<Object[]> getHighLowIn() { ArrayList<Object[]> result = new ArrayList(); Station currentStation = StationTools.getStationForThisHost(); ArrayList<Resident> listResident = ResidentTools.getAllActive(currentStation.getHome()); LocalDate now = new LocalDate(); try { for (Resident resident : listResident) { ArrayList<Pair<LocalDate, BigDecimal>> violatingValues = new ArrayList<Pair<LocalDate, BigDecimal>>(); Properties controlling = resident.getControlling(); if (controlling.containsKey(ResidentTools.KEY_LOWIN) && !controlling.getProperty(ResidentTools.KEY_LOWIN).equals("off")) { // if the controlling was just set its not necessary to look too far into the past // #24 String sDate = controlling.getProperty(ResidentTools.KEY_DATE2); LocalDate startingOn = null; if (sDate != null) { startingOn = new LocalDate(sDate); } int days = Integer.parseInt(controlling.getProperty(ResidentTools.KEY_DAYSDRINK)); if (startingOn == null || now.minusDays(days).compareTo(startingOn) >= 0) { startingOn = now.minusDays(days); } HashMap<LocalDate, BigDecimal> in = getLiquidIn(resident, startingOn); if (!in.isEmpty()) { for (LocalDate day = startingOn; day.compareTo(new LocalDate()) <= 0; day = day.plusDays(1)) { if (in.get(day).compareTo(new BigDecimal(controlling.getProperty(ResidentTools.KEY_LOWIN))) < 0) { violatingValues.add(new Pair<LocalDate, BigDecimal>(day, in.get(day))); } } } } if (controlling.containsKey(ResidentTools.KEY_HIGHIN) && !controlling.getProperty(ResidentTools.KEY_HIGHIN).equals("off")) { // if the controlling was just set its not necessary to look too far into the past // #24 String sDate = controlling.getProperty(ResidentTools.KEY_DATE3); LocalDate startingOn = null; if (sDate != null) { startingOn = new LocalDate(sDate); } int days = Integer.parseInt(controlling.getProperty(ResidentTools.KEY_DAYSDRINK)); if (startingOn == null || now.minusDays(days).compareTo(startingOn) >= 0) { startingOn = now.minusDays(days); } HashMap<LocalDate, BigDecimal> in = getLiquidIn(resident, startingOn); if (!in.isEmpty()) { for (LocalDate day = startingOn; day.compareTo(new LocalDate()) <= 0; day = day.plusDays(1)) { if (in.get(day).compareTo(new BigDecimal(controlling.getProperty(ResidentTools.KEY_HIGHIN))) > 0) { violatingValues.add(new Pair<LocalDate, BigDecimal>(day, in.get(day))); } } } } if (!violatingValues.isEmpty()) { result.add(new Object[]{resident, violatingValues}); } } } catch (Exception e) { OPDE.fatal(e); } listResident.clear(); return result; } /** * @param weight in kg * @return Required liquid in ml */ public static BigDecimal getRequiredLiquid(BigDecimal weight) { if (weight == null) { return null; } BigDecimal rl = new BigDecimal(1500); // for the first 20 kg of weight return rl.add(new BigDecimal(15).multiply(weight.subtract(new BigDecimal(20)))); } /** * Harris-Benedict-Formula * * @param weight in kg * @param height in m * @param age in years * @return Basal Metabolic Rate in kcal / 24h */ public static BigDecimal getBasalMetabolicRate(BigDecimal weight, BigDecimal height, int age, int gender) { if (weight == null || height == null) { return null; } height = height.multiply(new BigDecimal(100)); BigDecimal bmr; if (gender == ResidentTools.MALE) { bmr = new BigDecimal(66.5).add(new BigDecimal(13.7).multiply(weight)).add(new BigDecimal(5).multiply(height)).subtract(new BigDecimal(6.8).multiply(new BigDecimal(age))); } else { bmr = new BigDecimal(655).add(new BigDecimal(9.6).multiply(weight)).add(new BigDecimal(1.8).multiply(height)).subtract(new BigDecimal(4.7).multiply(new BigDecimal(age))); } return bmr; } /** * Ideal Body Weight (Hamwi Method) * * @param height in m * @param gender * @return */ public static BigDecimal getIBW(BigDecimal height, int gender) { if (height == null) { return null; } height = height.multiply(new BigDecimal(100)); BigDecimal HEIGHT_BARRIER = new BigDecimal(152.4); BigDecimal WEIGHT_PER_CM = gender == ResidentTools.MALE ? new BigDecimal(1.1) : new BigDecimal(0.9); BigDecimal BASE_WEIGHT = gender == ResidentTools.MALE ? new BigDecimal(48) : new BigDecimal(45); BigDecimal heightAboveBarrier = height.subtract(HEIGHT_BARRIER); if (heightAboveBarrier.compareTo(BigDecimal.ZERO) < 0) { heightAboveBarrier = BigDecimal.ZERO; } return BASE_WEIGHT.add(heightAboveBarrier.multiply(WEIGHT_PER_CM)); } /** * Body Mass Index * * @param weight in kg * @param height in meter * @return */ public static BigDecimal getBMI(BigDecimal weight, BigDecimal height) { BigDecimal bmi = null; if (weight != null && height != null) { bmi = weight.divide(height.pow(2), 2, BigDecimal.ROUND_HALF_UP); } return bmi; } public static ArrayList<Object[]> getLiquidBalances(Resident resident, LocalDate start, int entriesBack) { // DateTime to = new LocalDate(year, 1, 1).dayOfYear().withMaximumValue().toDateTimeAtStartOfDay().secondOfDay().withMaximumValue(); EntityManager em = OPDE.createEM(); // Query query = em.createNativeQuery(" " + // " SELECT DATE(pit), SUM(Wert) FROM resvalue " + // " WHERE TYPE = ? AND BWKennung = ? AND DATE(pit) <= ? AND EditBy IS NULL" + // " GROUP BY DATE(Pit) " + // " ORDER BY PIT DESC " + // " LIMIT 0,? "); Query query = em.createNativeQuery(" " + " SELECT d1, IFNULL(i, 0), IFNULL(o,0), IFNULL(s,0) FROM (" + " SELECT DATE(pit) d1, SUM(Wert) i FROM resvalue" + " WHERE TYPE = ? AND BWKennung = ? AND DATE(pit) <= ? AND EditBy IS NULL AND Wert > 0" + " GROUP BY DATE(Pit)" + " ORDER BY PIT DESC" + " LIMIT 0,? " + " ) a LEFT OUTER JOIN (" + " SELECT DATE(pit) d2, SUM(Wert) o FROM resvalue" + " WHERE TYPE = ? AND BWKennung = ? AND DATE(pit) <= ? AND EditBy IS NULL AND Wert < 0" + " GROUP BY DATE(Pit)" + " ORDER BY PIT DESC" + " LIMIT 0,? " + ") b ON d1 = d2 LEFT OUTER JOIN (" + " SELECT DATE(pit) d3, SUM(Wert) s FROM resvalue" + " WHERE TYPE = ? AND BWKennung = ? AND DATE(pit) <= ? AND EditBy IS NULL" + " GROUP BY DATE(Pit)" + " ORDER BY PIT DESC" + " LIMIT 0,?" + ") c ON d1 = d3 "); query.setParameter(1, ResValueTypesTools.LIQUIDBALANCE); query.setParameter(2, resident.getRID()); query.setParameter(3, start.toDateTimeAtStartOfDay().toDate()); query.setParameter(4, entriesBack); query.setParameter(5, ResValueTypesTools.LIQUIDBALANCE); query.setParameter(6, resident.getRID()); query.setParameter(7, start.toDateTimeAtStartOfDay().toDate()); query.setParameter(8, entriesBack); query.setParameter(9, ResValueTypesTools.LIQUIDBALANCE); query.setParameter(10, resident.getRID()); query.setParameter(11, start.toDateTimeAtStartOfDay().toDate()); query.setParameter(12, entriesBack); ArrayList<Object[]> result = new ArrayList(query.getResultList()); em.close(); return result; } }