es.usc.citius.servando.calendula.util.PickupUtils.java Source code

Java tutorial

Introduction

Here is the source code for es.usc.citius.servando.calendula.util.PickupUtils.java

Source

/*
 *    Calendula - An assistant for personal medication management.
 *    Copyright (C) 2016 CITIUS - USC
 *
 *    Calendula is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this software.  If not, see <http://www.gnu.org/licenses/>.
 */

package es.usc.citius.servando.calendula.util;

import android.support.v4.util.Pair;
import android.util.Log;

import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.joda.time.Interval;
import org.joda.time.LocalDate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import es.usc.citius.servando.calendula.database.DB;
import es.usc.citius.servando.calendula.persistence.Medicine;
import es.usc.citius.servando.calendula.persistence.Patient;
import es.usc.citius.servando.calendula.persistence.PickupInfo;

/**
 * Created by joseangel.pineiro on 4/07/16.
 */
public class PickupUtils {

    private final int MAX_DAYS = 10;

    List<PickupInfo> pickups;
    List<PickupInfo> urgentMeds;
    Map<LocalDate, List<PickupInfo>> pickupsMap = new HashMap<>();
    Pair<LocalDate, List<PickupInfo>> bestDay;

    public PickupUtils(List<PickupInfo> pickups) {
        this.pickups = pickups;
        this.bestDay = null;
        Collections.sort(this.pickups, PickupInfo.PickupComparator.instance);
        pickupsMap.clear();
        for (PickupInfo pk : pickups) {
            if (!pickupsMap.containsKey(pk.from())) {
                pickupsMap.put(pk.from(), new ArrayList<PickupInfo>());
            }
            pickupsMap.get(pk.from()).add(pk);
        }
    }

    /**
     * Get urgent meds, that are meds we can take within a margin of one or two days
     * before the next intake is delayed
     * @return
     */
    public List<PickupInfo> urgentMeds() {
        if (urgentMeds == null) {
            urgentMeds = new ArrayList<>();
            LocalDate now = LocalDate.now();
            for (PickupInfo p : pickups) {
                if (!p.taken() && p.to().isAfter(now) && p.from().plusDays(MAX_DAYS - 3).isBefore(now)) {
                    urgentMeds.add(p);
                }
            }
        }
        return urgentMeds;
    }

    public Pair<LocalDate, List<PickupInfo>> getBestDay() {

        if (this.bestDay != null) {
            return this.bestDay;
        }

        HashMap<LocalDate, List<PickupInfo>> bestDays = new HashMap<>();
        if (pickups.size() > 0) {
            LocalDate today = LocalDate.now();
            LocalDate first = LocalDate.now();
            LocalDate now = LocalDate.now().minusDays(MAX_DAYS);

            if (now.getDayOfWeek() == DateTimeConstants.SUNDAY) {
                now = now.plusDays(1);
            }

            // get the date of the first med we can take from 10 days ago
            for (PickupInfo p : pickups) {
                if (p.from().isAfter(now) && !p.taken()) {
                    first = p.from();
                    break;
                }
            }

            for (int i = 0; i < 10; i++) {
                LocalDate d = first.plusDays(i);
                if (!d.isAfter(today) && d.getDayOfWeek() != DateTimeConstants.SUNDAY) {
                    // only take care of days after today that are not sundays
                    continue;
                }

                // compute the number of meds we cant take for each day
                for (PickupInfo p : pickups) {
                    // get the pickup take secure interval
                    DateTime iStart = p.from().toDateTimeAtStartOfDay();
                    DateTime iEnd = p.from().plusDays(MAX_DAYS - 1).toDateTimeAtStartOfDay();
                    Interval interval = new Interval(iStart, iEnd);
                    // add the pickup to the daily list if we can take it
                    if (!p.taken() && interval.contains(d.toDateTimeAtStartOfDay())) {
                        if (!bestDays.containsKey(d)) {
                            bestDays.put(d, new ArrayList<PickupInfo>());
                        }
                        bestDays.get(d).add(p);
                    }
                }
            }

            // select the day with the highest number of meds
            int bestDayCount = 0;
            LocalDate bestOption = null;
            Set<LocalDate> localDates = bestDays.keySet();
            ArrayList<LocalDate> sorted = new ArrayList<>(localDates);
            Collections.sort(sorted);
            for (LocalDate day : sorted) {
                List<PickupInfo> pks = bestDays.get(day);
                Log.d("PickupUtils", day.toString("dd/MM/YYYY") + ": " + pks.size());
                if (pks.size() >= bestDayCount) {
                    bestDayCount = pks.size();
                    bestOption = day;
                    if (bestOption.getDayOfWeek() == DateTimeConstants.SUNDAY) {
                        bestOption = bestOption.minusDays(1);
                    }
                }
            }
            if (bestOption != null) {
                this.bestDay = new Pair<>(bestOption, bestDays.get(bestOption));
                return this.bestDay;
            }
        }

        return null;
    }

    HashMap<Long, Patient> colorCache = new HashMap<>();

    public Patient getPatient(PickupInfo p) {
        Long id = p.medicine().getId();
        if (!colorCache.containsKey(id)) {
            Medicine m = DB.medicines().findById(p.medicine().getId());
            Patient patient = DB.patients().findById(m.patient().id());
            colorCache.put(id, patient);
        }
        return colorCache.get(id);
    }

    //    private List<PickupInfo> canTakeAt(LocalDate d) {
    //        List<PickupInfo> all = pickups;
    //        List<PickupInfo> canTake = new ArrayList<>();
    //        List<Long> medIds = new ArrayList<>();
    //        for (PickupInfo p : all) {
    //            DateTime iStart = p.from().toDateTimeAtStartOfDay();
    //            DateTime iEnd = p.from().plusDays(MAX_DAYS-1).toDateTimeAtStartOfDay();
    //            Interval interval = new Interval(iStart, iEnd);
    //            if (!p.taken() && interval.contains(d.toDateTimeAtStartOfDay())) {
    //                if (!medIds.contains(p.medicine().getId())) {
    //                    canTake.add(p);
    //                    medIds.add(p.medicine().getId());
    //                }
    //            }
    //        }
    //        return canTake;
    //    }

    public List<PickupInfo> pickups() {
        return pickups;
    }

    public Map<LocalDate, List<PickupInfo>> pickupsMap() {
        return pickupsMap;
    }
}