/**
   * @see
   *     PatientDataEvaluator#evaluate(org.openmrs.module.reporting.data.patient.definition.PatientDataDefinition,
   *     org.openmrs.module.reporting.evaluation.EvaluationContext)
   */
  public EvaluatedPatientData evaluate(PatientDataDefinition definition, EvaluationContext context)
      throws EvaluationException {

    CalculationDataDefinition def = (CalculationDataDefinition) definition;
    EvaluatedPatientData c = new EvaluatedPatientData(def, context);

    // return right away if there is nothing to evaluate
    if (context.getBaseCohort() != null && context.getBaseCohort().isEmpty()) {
      return c;
    }

    // evaluate the calculation
    PatientCalculationService service = Context.getService(PatientCalculationService.class);
    CalculationResultMap resultMap =
        service.evaluate(
            context.getBaseCohort().getMemberIds(),
            def.getCalculation(),
            def.getCalculationParameters(),
            context);

    // move data into return object
    for (Map.Entry<Integer, CalculationResult> entry : resultMap.entrySet()) {
      c.addData(entry.getKey(), entry.getValue());
    }

    return c;
  }
  @Override
  public CalculationResultMap evaluate(
      Collection<Integer> cohort, Map<String, Object> map, PatientCalculationContext context) {
    CalculationResultMap ret = new CalculationResultMap();
    PersonService personService = Context.getPersonService();
    PersonAttributeType personAttributeType =
        personService.getPersonAttributeTypeByUuid(
            CommonMetadata._PersonAttributeType.TELEPHONE_CONTACT);

    PersonAttributeCohortDefinition cd = new PersonAttributeCohortDefinition();
    cd.setAttributeType(personAttributeType);

    EvaluatedCohort peopleWithPhoneNumbersCohort =
        CalculationUtils.evaluateWithReporting(cd, cohort, null, context);

    PersonAttributeDataDefinition personAttributeDataDefinition =
        new PersonAttributeDataDefinition();
    personAttributeDataDefinition.setPersonAttributeType(personAttributeType);

    CalculationResultMap data =
        CalculationUtils.evaluateWithReporting(
            personAttributeDataDefinition, cohort, map, null, context);

    for (Integer ptId : cohort) {
      String phoneNumber = null;
      if (peopleWithPhoneNumbersCohort.contains(ptId)) {
        phoneNumber = data.get(ptId).toString();
      }
      ret.put(ptId, new SimpleResult(phoneNumber, this));
    }
    return ret;
  }
  @Test
  public void evaluate_shouldReturnHivPatientsNotScreenedForTb() throws Exception {

    // Get HIV Program and TB screening encounter type
    Program hivProgram = MetadataUtils.getProgram(Metadata.HIV_PROGRAM);
    EncounterType screeningEncType =
        MetadataUtils.getEncounterType(Metadata.TB_SCREENING_ENCOUNTER_TYPE);

    // Enroll patients #6 and #7
    PatientService ps = Context.getPatientService();
    TestUtils.enrollInProgram(ps.getPatient(6), hivProgram, TestUtils.date(2011, 1, 1));
    TestUtils.enrollInProgram(ps.getPatient(7), hivProgram, TestUtils.date(2011, 1, 1));

    // Screen patient #6 for TB a year later
    TestUtils.saveEncounter(ps.getPatient(6), screeningEncType, TestUtils.date(2012, 1, 1));

    Context.flushSession();

    List<Integer> cohort = Arrays.asList(6, 7, 8);
    CalculationResultMap resultMap =
        Context.getService(PatientCalculationService.class)
            .evaluate(cohort, new NeverScreenedForTbCalculation());
    Assert.assertFalse((Boolean) resultMap.get(6).getValue());
    Assert.assertTrue((Boolean) resultMap.get(7).getValue());
    Assert.assertNull(resultMap.get(8)); // not in HIV program
  }
  /**
   * @see org.openmrs.calculation.patient.PatientCalculation#evaluate(java.util.Collection,
   *     java.util.Map, org.openmrs.calculation.patient.PatientCalculationContext)
   */
  @Override
  public CalculationResultMap evaluate(
      Collection<Integer> cohort,
      Map<String, Object> parameterValues,
      PatientCalculationContext context) {

    Program mchcsProgram = MetadataUtils.getProgram(MchMetadata._Program.MCHCS);

    // Get all patients who are alive and in MCH-CS program
    Set<Integer> alive = Filters.alive(cohort, context);
    Set<Integer> inMchcsProgram = Filters.inProgram(mchcsProgram, alive, context);

    // get wheather the child is HIV Exposed
    CalculationResultMap lastChildHivStatus =
        Calculations.lastObs(
            Dictionary.getConcept(Dictionary.CHILDS_CURRENT_HIV_STATUS), inMchcsProgram, context);
    CalculationResultMap medOrdersObss =
        Calculations.allObs(Dictionary.getConcept(Dictionary.MEDICATION_ORDERS), cohort, context);

    // Get concepts for  medication prophylaxis
    Concept nvp = Dictionary.getConcept(Dictionary.NEVIRAPINE);
    Concept nvpazt3tc = Dictionary.getConcept(Dictionary.LAMIVUDINE_NEVIRAPINE_ZIDOVUDINE);
    Concept hivExposed = Dictionary.getConcept(Dictionary.EXPOSURE_TO_HIV);

    CalculationResultMap ret = new CalculationResultMap();

    for (Integer ptId : cohort) {
      boolean notOnPcp = false;

      // checking wheather the infant is in mchcs program, alive and HEI
      Obs hivStatusObs = EmrCalculationUtils.obsResultForPatient(lastChildHivStatus, ptId);
      if (inMchcsProgram.contains(ptId)
          && lastChildHivStatus != null
          && hivStatusObs != null
          && (hivStatusObs.getValueCoded().equals(hivExposed))) {
        notOnPcp = true;
        ListResult patientMedOrders = (ListResult) medOrdersObss.get(ptId);
        if (patientMedOrders != null) {
          // Look through list of medication order obs for any  CTX
          List<Obs> medOrderObsList = CalculationUtils.extractResultValues(patientMedOrders);
          for (Obs medOrderObs : medOrderObsList) {
            if (medOrderObs.getValueCoded().equals(nvp)
                || medOrderObs.getValueCoded().equals(nvpazt3tc)) {
              notOnPcp = false;
              break;
            }
          }
        }
      }
      ret.put(ptId, new BooleanResult(notOnPcp, this, context));
    }

    return ret;
  }
  /**
   * @see
   *     org.openmrs.module.kenyaemr.calculation.library.hiv.MissedAppointmentsOrDefaultedCalculation#evaluate(java.util.Collection,
   *     java.util.Map, org.openmrs.calculation.patient.PatientCalculationContext)
   * @verifies determine whether patients have a Missed appointments or defaulted
   */
  @Test
  public void evaluate_shouldDetermineWhetherPatientsWhoMissedAppointmentsOrDefaulted()
      throws Exception {

    // Get HIV Program
    Program hivProgram = MetadataUtils.getProgram(Metadata.HIV_PROGRAM);

    // Enroll patients #6, #7, #8 in the HIV Program
    PatientService ps = Context.getPatientService();
    for (int i = 6; i <= 8; ++i) {
      TestUtils.enrollInProgram(ps.getPatient(i), hivProgram, TestUtils.date(2011, 1, 1));
    }

    // Give patient #7 a return visit obs of 10 days ago
    Concept returnVisit = Context.getConceptService().getConcept(5096);
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DATE, -10);
    TestUtils.saveObs(
        Context.getPatientService().getPatient(7),
        returnVisit,
        calendar.getTime(),
        calendar.getTime());

    // Give patient #8 a return visit obs of 10 days in the future
    calendar = Calendar.getInstance();
    calendar.add(Calendar.DATE, 10);
    TestUtils.saveObs(
        Context.getPatientService().getPatient(8),
        returnVisit,
        calendar.getTime(),
        calendar.getTime());

    Context.flushSession();

    List<Integer> ptIds = Arrays.asList(6, 7, 8, 9);

    CalculationResultMap resultMap =
        new MissedAppointmentsOrDefaultedCalculation()
            .evaluate(
                ptIds,
                null,
                Context.getService(PatientCalculationService.class).createCalculationContext());
    Assert.assertFalse(
        (Boolean) resultMap.get(6).getValue()); // patient in HIV program but no return visit obs
    Assert.assertTrue((Boolean) resultMap.get(7).getValue()); // patient has missed visit
    Assert.assertFalse(
        (Boolean) resultMap.get(8).getValue()); // patient has future return visit date
    Assert.assertFalse((Boolean) resultMap.get(9).getValue()); // patient not in HIV Program
  }
  /**
   * @see VisitsOnDayCalculation#evaluate(java.util.Collection, java.util.Map,
   *     org.openmrs.calculation.patient.PatientCalculationContext)
   */
  @Test
  public void evaluate_shouldDefaultToToday() throws Exception {
    List<Integer> ptIds = Arrays.asList(7, 8);
    Map<String, Object> paramValues = new HashMap<String, Object>();

    CalculationResultMap resultMap =
        new VisitsOnDayCalculation()
            .evaluate(
                ptIds,
                paramValues,
                Context.getService(PatientCalculationService.class).createCalculationContext());

    Assert.assertThat(resultMap.get(7).isEmpty(), is(true)); // No visits on that day
    Assert.assertThat(resultMap.get(8).isEmpty(), is(true)); // No visits on that day
  }
  /**
   * Evaluates the calculation
   *
   * @should calculate false for deceased patients
   * @should calculate false for patients not in HIV program
   * @should calculate false for patients with an encounter in last LOST_TO_FOLLOW_UP_THRESHOLD_DAYS
   *     days days since appointment date
   * @should calculate true for patient with no encounter in last LOST_TO_FOLLOW_UP_THRESHOLD_DAYS
   *     days days since appointment date
   */
  @Override
  public CalculationResultMap evaluate(
      Collection<Integer> cohort, Map<String, Object> arg1, PatientCalculationContext context) {

    Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV);
    Concept reasonForDiscontinuation =
        Dictionary.getConcept(Dictionary.REASON_FOR_PROGRAM_DISCONTINUATION);
    Concept transferout = Dictionary.getConcept(Dictionary.TRANSFERRED_OUT);

    Set<Integer> alive = Filters.alive(cohort, context);
    Set<Integer> inHivProgram = Filters.inProgram(hivProgram, alive, context);

    // CalculationResultMap lastEncounters = Calculations.lastEncounter(null, inHivProgram,
    // context);
    CalculationResultMap lastReturnDateObss =
        Calculations.lastObs(
            Dictionary.getConcept(Dictionary.RETURN_VISIT_DATE), inHivProgram, context);
    CalculationResultMap lastProgramDiscontinuation =
        Calculations.lastObs(reasonForDiscontinuation, cohort, context);

    CalculationResultMap ret = new CalculationResultMap();
    for (Integer ptId : cohort) {
      boolean lost = false;

      // Is patient alive and in the HIV program
      if (alive.contains(ptId)) {

        // Patient is lost if no encounters in last X days
        // Encounter lastEncounter = EmrCalculationUtils.encounterResultForPatient(lastEncounters,
        // ptId);
        Date lastScheduledReturnDate =
            EmrCalculationUtils.datetimeObsResultForPatient(lastReturnDateObss, ptId);
        Obs discontuation =
            EmrCalculationUtils.obsResultForPatient(lastProgramDiscontinuation, ptId);
        if (lastScheduledReturnDate != null) {
          if (daysSince(lastScheduledReturnDate, context)
              > HivConstants.LOST_TO_FOLLOW_UP_THRESHOLD_DAYS) {
            lost = true;
          }
          if (discontuation != null && discontuation.getValueCoded().equals(transferout)) {
            lost = false;
          }
        }
      }
      ret.put(ptId, new SimpleResult(lost, this, context));
    }
    return ret;
  }
  @Test
  public void evaluate_shouldReturnTrueForAllAlivePatients() {

    // Mark patient #8 as deceased on 1st Jan 2012
    TestUtils.getPatient(8).setDead(true);
    TestUtils.getPatient(8).setDeathDate(TestUtils.date(2012, 1, 1));

    List<Integer> ptIds = Arrays.asList(2, 6, 7, 8);
    CalculationResultMap resultMap =
        Context.getService(PatientCalculationService.class)
            .evaluate(ptIds, new EligibleForTbProgramCalculation());
    Assert.assertTrue((Boolean) resultMap.get(2).getValue());
    Assert.assertTrue((Boolean) resultMap.get(6).getValue());
    Assert.assertTrue((Boolean) resultMap.get(7).getValue());
    Assert.assertFalse((Boolean) resultMap.get(8).getValue()); // Deceased
  }
  /**
   * @see VisitsOnDayCalculation#evaluate(java.util.Collection, java.util.Map,
   *     org.openmrs.calculation.patient.PatientCalculationContext)
   */
  @Test
  public void evaluate_shouldFetchAllPatientVisitsOnDate() throws Exception {
    List<Integer> ptIds = Arrays.asList(7, 8);
    Map<String, Object> paramValues = new HashMap<String, Object>();
    paramValues.put("date", TestUtils.date(2012, 1, 1));

    CalculationResultMap resultMap =
        new VisitsOnDayCalculation()
            .evaluate(
                ptIds,
                paramValues,
                Context.getService(PatientCalculationService.class).createCalculationContext());

    Assert.assertThat(((ListResult) resultMap.get(7)).getValues().size(), is(2)); // Has two visit
    Assert.assertThat(resultMap.get(8).isEmpty(), is(true)); // No visits on that day
  }
  @Override
  public CalculationResultMap evaluate(
      Collection<Integer> cohort,
      Map<String, Object> parameterValues,
      PatientCalculationContext context) {
    //		Date date = (Date) parameterValues.get("date");
    //		if (date == null) {
    //			date = new Date();
    //		}

    if (parameterValues != null) {
      logger.info("Parameter Values is NOT null");
      logger.info(parameterValues.toString());
    } else {

      logger.info("Parameter Values is null");
    }
    Date date = new Date();

    Date startOfDay = DateUtil.getStartOfDay(date);
    Date endOfDay = DateUtil.getEndOfDay(date);
    Concept returnVisitDate = Dictionary.getConcept(Dictionary.RETURN_VISIT_DATE);
    // EncounterType tbFollowup = MetadataUtils.existing(EncounterType.class,
    // TbMetadata._EncounterType.TB_CONSULTATION);

    DateObsCohortDefinition cd = new DateObsCohortDefinition();
    cd.setTimeModifier(TimeModifier.ANY);
    cd.setQuestion(returnVisitDate);
    cd.setOperator1(RangeComparator.GREATER_EQUAL);
    cd.setValue1(startOfDay);
    cd.setOperator2(RangeComparator.LESS_EQUAL);
    cd.setValue2(endOfDay);
    // cd.setEncounterTypeList(Collections.singletonList(tbFollowup));

    EvaluatedCohort withScheduledVisit =
        CalculationUtils.evaluateWithReporting(cd, cohort, null, context);

    CalculationResultMap ret = new CalculationResultMap();

    for (Integer ptId : cohort) {
      ret.put(ptId, new BooleanResult(withScheduledVisit.contains(ptId), this));
    }

    return ret;
  }
 /**
  * @see org.openmrs.calculation.patient.PatientCalculation#evaluate(java.util.Collection,
  *     java.util.Map, org.openmrs.calculation.patient.PatientCalculationContext)
  * @param cohort
  * @param parameterValues
  * @param context
  * @return true for deceased patients
  * @return False for non deceased patients
  */
 @Override
 public CalculationResultMap evaluate(
     Collection<Integer> cohort,
     Map<String, Object> parameterValues,
     PatientCalculationContext context) {
   Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV);
   Set<Integer> inHivProgram = Filters.inProgram(hivProgram, cohort, context);
   Set<Integer> alive = Filters.alive(cohort, context);
   CalculationResultMap ret = new CalculationResultMap();
   for (Integer ptId : cohort) {
     boolean dead = false;
     if (inHivProgram.contains(ptId) && !(alive.contains(ptId))) {
       dead = true;
     }
     ret.put(ptId, new SimpleResult(dead, this, context));
   }
   return ret;
 }
  /**
   * @see
   *     org.openmrs.module.kenyaemr.calculation.cd4.NeedsCD4Calculation#evaluate(java.util.Collection,
   *     java.util.Map, org.openmrs.calculation.patient.PatientCalculationContext)
   * @verifies calculate last CD4 percentage for all patients
   */
  @Test
  public void evaluate_shouldCalculateLastCD4() throws Exception {

    PatientService ps = Context.getPatientService();
    Concept cd4Percent =
        Context.getConceptService().getConceptByUuid(MetadataConstants.CD4_PERCENT_CONCEPT_UUID);

    // Give patient #6 some CD4 obs
    TestUtils.saveObs(ps.getPatient(6), cd4Percent, 20d, TestUtils.date(2012, 12, 1));
    TestUtils.saveObs(ps.getPatient(6), cd4Percent, 30d, TestUtils.date(2010, 11, 1));

    Context.flushSession();

    List<Integer> ptIds = Arrays.asList(6, 999);
    CalculationResultMap resultMap =
        Context.getService(PatientCalculationService.class)
            .evaluate(ptIds, new LastCD4PercentageCalculation());
    Assert.assertEquals(new Double(20d), ((Obs) resultMap.get(6).getValue()).getValueNumeric());
    Assert.assertNull(resultMap.get(999)); // has no recorded CD4 percent
  }
  /**
   * @see DecliningCd4Calculation#evaluate(java.util.Collection, java.util.Map,
   *     org.openmrs.calculation.patient.PatientCalculationContext)
   * @verifies determine whether patients have a decline in CD4
   */
  @Test
  public void evaluate_shouldDetermineWhetherPatientsHasDeclinedCD4() throws Exception {

    // Get HIV Program
    Program hivProgram = Metadata.getProgram(Metadata.HIV_PROGRAM);

    // Enroll patients #6, #7 and #8 in the HIV Program
    PatientService ps = Context.getPatientService();
    for (int i = 6; i <= 8; ++i) {
      TestUtils.enrollInProgram(ps.getPatient(i), hivProgram, new Date());
    }

    // Give patients #7 and #8 a CD4 count 180 days ago
    Concept cd4 = Dictionary.getConcept(Dictionary.CD4_COUNT);
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DATE, -180);
    TestUtils.saveObs(ps.getPatient(7), cd4, 123d, calendar.getTime());
    TestUtils.saveObs(ps.getPatient(8), cd4, 123d, calendar.getTime());

    // Give patient #7 a lower CD4 count today
    TestUtils.saveObs(ps.getPatient(7), cd4, 120d, new Date());

    // Give patient #8 a higher CD4 count today
    TestUtils.saveObs(ps.getPatient(8), cd4, 126d, new Date());

    Context.flushSession();

    List<Integer> ptIds = Arrays.asList(6, 7, 8, 999);

    CalculationResultMap resultMap =
        Context.getService(PatientCalculationService.class)
            .evaluate(ptIds, new DecliningCd4Calculation());
    Assert.assertFalse(
        (Boolean) resultMap.get(6).getValue()); // in Hiv program but without cd4 i.e needs cd4
    Assert.assertTrue((Boolean) resultMap.get(7).getValue()); // has decline in CD4
    Assert.assertFalse((Boolean) resultMap.get(8).getValue()); // has increase in CD4
    Assert.assertFalse((Boolean) resultMap.get(999).getValue()); // not in HIV Program
  }
 /**
  * Extracts patients from a calculation result map with date results in the given range
  *
  * @param results the calculation result map
  * @param minDateInclusive the minimum date (inclusive)
  * @param maxDateInclusive the maximum date (inclusive)
  * @return the extracted patient ids
  */
 protected static Set<Integer> datesWithinRange(
     CalculationResultMap results, Date minDateInclusive, Date maxDateInclusive) {
   Set<Integer> ret = new HashSet<Integer>();
   for (Map.Entry<Integer, CalculationResult> e : results.entrySet()) {
     Date result = null;
     try {
       result = e.getValue().asType(Date.class);
     } catch (Exception ex) {
       // pass
     }
     if (result != null) {
       if (OpenmrsUtil.compareWithNullAsEarliest(result, minDateInclusive) >= 0
           && OpenmrsUtil.compareWithNullAsLatest(result, maxDateInclusive) <= 0) {
         ret.add(e.getKey());
       }
     }
   }
   return ret;
 }
  /**
   * @see EligibleForArtTriggerCalculation#evaluate(java.util.Collection, java.util.Map,
   *     org.openmrs.calculation.patient.PatientCalculationContext)
   * @verifies calculate the obs which triggered a patient to become eligible for ART
   * @verifies return null for patients who have never been eligible for ART
   */
  @Test
  public void evaluate_shouldCalculateEligibilityTrigger() throws Exception {

    PatientService ps = Context.getPatientService();

    // Confirm patient #6 HIV+ when they're 1 year old and give them very low CD4 soon after
    TestUtils.saveObs(
        ps.getPatient(6),
        Dictionary.getConcept(Dictionary.DATE_OF_HIV_DIAGNOSIS),
        TestUtils.date(2008, 05, 27),
        TestUtils.date(2010, 1, 1));
    TestUtils.saveObs(
        ps.getPatient(6),
        Dictionary.getConcept(Dictionary.CD4_COUNT),
        300.0,
        TestUtils.date(2009, 1, 1));

    // Give patient #7 low CD4 when they're 3 years old and very low CD4 after
    TestUtils.saveObs(
        ps.getPatient(7),
        Dictionary.getConcept(Dictionary.CD4_COUNT),
        900.0,
        TestUtils.date(1979, 8, 25));
    TestUtils.saveObs(
        ps.getPatient(7),
        Dictionary.getConcept(Dictionary.CD4_COUNT),
        300.0,
        TestUtils.date(2009, 1, 1));

    // Give patient #8 WHO stage of 3
    TestUtils.saveObs(
        ps.getPatient(8),
        Dictionary.getConcept(Dictionary.CURRENT_WHO_STAGE),
        Dictionary.getConcept(Dictionary.WHO_STAGE_3_PEDS),
        TestUtils.date(2009, 1, 1));

    Context.flushSession();

    List<Integer> cohort = Arrays.asList(6, 7, 8, 999);

    CalculationResultMap resultMap =
        new EligibleForArtTriggerCalculation()
            .evaluate(
                cohort,
                null,
                Context.getService(PatientCalculationService.class).createCalculationContext());

    Obs patient6Trigger = (Obs) resultMap.get(6).getValue(); // Eligible through HIV confirmation
    Assert.assertEquals(Dictionary.DATE_OF_HIV_DIAGNOSIS, patient6Trigger.getConcept().getUuid());
    Assert.assertEquals(TestUtils.date(2008, 05, 27), patient6Trigger.getValueDate());

    Obs patient7Trigger = (Obs) resultMap.get(7).getValue(); // Eligible through CD4 count
    Assert.assertEquals(Dictionary.CD4_COUNT, patient7Trigger.getConcept().getUuid());
    Assert.assertEquals(TestUtils.date(1979, 8, 25), patient7Trigger.getObsDatetime());

    Obs patient8Trigger = (Obs) resultMap.get(8).getValue(); // Eligible through WHO stage
    Assert.assertEquals(Dictionary.CURRENT_WHO_STAGE, patient8Trigger.getConcept().getUuid());
    Assert.assertEquals(TestUtils.date(2009, 1, 1), patient8Trigger.getObsDatetime());

    Assert.assertNull(resultMap.get(999)); // Was never eligible for ART
  }
  @Override
  public CalculationResultMap evaluate(
      Collection<Integer> cohort,
      Map<String, Object> parameterValues,
      PatientCalculationContext context) {
    Program hivProgram = MetadataUtils.existing(Program.class, HivMetadata._Program.HIV);

    Set<Integer> alive = Filters.alive(cohort, context);
    Set<Integer> inHivProgram = Filters.inProgram(hivProgram, alive, context);

    Set<Integer> aliveAndFemale = Filters.female(Filters.alive(cohort, context), context);

    CalculationResultMap ret = new CalculationResultMap();

    // need to exclude those on ART already
    Set<Integer> onArt =
        CalculationUtils.patientsThatPass(calculate(new OnArtCalculation(), cohort, context));
    // find the observation for viral load recorded
    CalculationResultMap viralLoad =
        Calculations.lastObs(Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD), cohort, context);
    // get a list of all the viral load
    CalculationResultMap viralLoadList =
        Calculations.allObs(Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD), cohort, context);
    // check for non detectables
    CalculationResultMap ldlViralLoad =
        Calculations.allObs(
            Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD_QUALITATIVE), cohort, context);

    // check for test orders
    CalculationResultMap testOrders =
        Calculations.allObs(Dictionary.getConcept(Dictionary.TESTS_ORDERED), cohort, context);

    // check for last ldl
    CalculationResultMap ldlLast =
        Calculations.lastObs(
            Dictionary.getConcept(Dictionary.HIV_VIRAL_LOAD_QUALITATIVE), cohort, context);

    // find for prgnant females

    CalculationResultMap pregStatusObss =
        Calculations.lastObs(
            Dictionary.getConcept(Dictionary.PREGNANCY_STATUS), aliveAndFemale, context);

    // get the initial art start date
    CalculationResultMap artStartDate =
        calculate(new InitialArtStartDateCalculation(), cohort, context);

    for (Integer ptId : cohort) {
      boolean needsViralLoadTest = false;
      Obs viralLoadObs = EmrCalculationUtils.obsResultForPatient(viralLoad, ptId);
      Date dateInitiated = EmrCalculationUtils.datetimeResultForPatient(artStartDate, ptId);
      ListResult listResult = (ListResult) viralLoadList.get(ptId);
      ListResult testOrdersList = (ListResult) testOrders.get(ptId);
      List<Obs> testObsList = CalculationUtils.extractResultValues(testOrdersList);
      List<Obs> listObsViralLoads = CalculationUtils.extractResultValues(listResult);
      ListResult ldlList = (ListResult) ldlViralLoad.get(ptId);
      List<List> listLdl = CalculationUtils.extractResultValues(ldlList);
      Obs lastLdlObs = EmrCalculationUtils.obsResultForPatient(ldlLast, ptId);
      // find pregnancy obs
      Obs pregnantEdd = EmrCalculationUtils.obsResultForPatient(pregStatusObss, ptId);

      // Find latest viral load test order
      Obs lastVlTestOrder = getLatestVlOrder(testObsList);

      if (inHivProgram.contains(ptId) && onArt.contains(ptId)) {
        if (listObsViralLoads.size() == 0
            && listLdl.size() == 0
            && dateInitiated != null
            && (daysSince(dateInitiated, context) >= 180)) {
          needsViralLoadTest = true;
        }
        // need to check here if patient has had any viral load
        /*if(dateInitiated != null && (daysSince(dateInitiated, context) >= 360)) {
            needsViralLoadTest = true;
        }*/

        // those continuing should receive one VL every year
        // pick the date of the last viral load numeric values
        if (viralLoadObs != null && (daysSince(viralLoadObs.getObsDatetime(), context) >= 360)) {
          needsViralLoadTest = true;
        }
        // pick the date of the ldl
        if (lastLdlObs != null && (daysSince(lastLdlObs.getObsDatetime(), context) >= 360)) {
          needsViralLoadTest = true;
        }

        // if vl more than
        if (viralLoadObs != null
            && viralLoadObs.getValueNumeric() > 1000
            && (daysSince(viralLoadObs.getObsDatetime(), context) > 90)) {
          needsViralLoadTest = true;

          if (lastLdlObs != null && (daysSince(lastLdlObs.getObsDatetime(), context) < 360)) {
            needsViralLoadTest = false;
          }
        }

        // check for pregnancy
        if (pregnantEdd != null
            && pregnantEdd.getValueCoded().equals(Dictionary.getConcept(Dictionary.YES))
            && dateInitiated != null) {
          Date whenVLWillBeDue =
              DateUtil.adjustDate(
                  DateUtil.adjustDate(dateInitiated, 6, DurationUnit.MONTHS),
                  -1,
                  DurationUnit.DAYS);
          // if last vl is 6 months older then the patient is due for vl
          if (viralLoadObs == null && lastLdlObs == null) {
            needsViralLoadTest = true;
          }
          if (viralLoadObs == null
              && lastLdlObs == null
              && (context.getNow().after(whenVLWillBeDue))) {
            needsViralLoadTest = true;
          }
          if (viralLoadObs != null
              && viralLoadObs.getValueNumeric() > 1000
              && (monthsBetween(viralLoadObs.getObsDatetime(), context.getNow()) >= 3)) {
            needsViralLoadTest = true;
            if (lastLdlObs != null && (daysSince(lastLdlObs.getObsDatetime(), context) < 360)) {
              needsViralLoadTest = false;
            }
          }
          if (viralLoadObs != null && daysSince(viralLoadObs.getObsDatetime(), context) >= 180) {
            needsViralLoadTest = true;
          }
          if (lastLdlObs != null && daysSince(lastLdlObs.getObsDatetime(), context) >= 180) {
            needsViralLoadTest = true;
          }
        }

        // check if has vl test order within 6 months
        if (lastVlTestOrder != null
            && daysSince(lastVlTestOrder.getObsDatetime(), context) >= 180) {
          needsViralLoadTest = true;
        }

        if (lastVlTestOrder != null && daysSince(lastVlTestOrder.getObsDatetime(), context) < 180) {
          needsViralLoadTest = false;
        }
      }

      ret.put(ptId, new BooleanResult(needsViralLoadTest, this));
    }
    return ret;
  }