From 19e880183e6c39a301a03d6c324d0bc3783746b4 Mon Sep 17 00:00:00 2001 From: Julia Friesel <julia.friesel@gmail.com> Date: Wed, 11 Jul 2018 14:14:42 +0200 Subject: [PATCH] Accept previousCycles as array --- lib/sympto/index.js | 17 +++++++++----- lib/sympto/pre-ovulatory.js | 23 ++++++++++++------ test/sympto/index.spec.js | 47 ++++++++++++++++++++++--------------- 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/lib/sympto/index.js b/lib/sympto/index.js index 6a9f66a3..36f8e5e6 100644 --- a/lib/sympto/index.js +++ b/lib/sympto/index.js @@ -4,18 +4,20 @@ import getPreOvulatoryPhase from './pre-ovulatory' import { LocalDate } from 'js-joda' import assert from 'assert' -export default function ({ cycle, previousCycle }) { - throwIfArgsAreNotInRequiredFormat(cycle, previousCycle) +export default function ({ cycle, previousCycles = [] }) { + throwIfArgsAreNotInRequiredFormat(cycle, previousCycles) const status = { assumeFertility: true, phases: {} } + // TODO handle no previous cycles // if there was no first higher measurement in the previous cycle, // no infertile pre-ovulatory phase may be assumed - if (getTemperatureShift(previousCycle).detected && !cycle[0].mucus) { - status.phases.preOvulatory = getPreOvulatoryPhase(cycle) + const lastCycle = previousCycles[previousCycles.length - 1] + if (getTemperatureShift(lastCycle).detected && !cycle[0].mucus) { + status.phases.preOvulatory = getPreOvulatoryPhase(cycle, previousCycles) if (status.phases.preOvulatory.cycleDays.length === cycle.length) { status.assumeFertility = false return status @@ -70,9 +72,10 @@ export default function ({ cycle, previousCycle }) { return status } -function throwIfArgsAreNotInRequiredFormat(cycle, previousCycle) { - [cycle, previousCycle].forEach(cycle => { +function throwIfArgsAreNotInRequiredFormat(cycle, previousCycles) { + [cycle, ...previousCycles].forEach(cycle => { assert.ok(Array.isArray(cycle)) + // TODO handle case of no previous cycles assert.ok(cycle.length > 0) assert.equal(typeof cycle[0].bleeding, 'object') assert.equal(typeof cycle[0].bleeding.value, 'number') @@ -81,6 +84,8 @@ function throwIfArgsAreNotInRequiredFormat(cycle, previousCycle) { assert.doesNotThrow(() => LocalDate.parse(day.date)) if (day.temperature) assert.equal(typeof day.temperature.value, 'number') if (day.mucus) assert.equal(typeof day.mucus.value, 'number') + if (day.mucus) assert.ok(day.mucus.value >= 0) + if (day.mucus) assert.ok(day.mucus.value < 5) }) }) } \ No newline at end of file diff --git a/lib/sympto/pre-ovulatory.js b/lib/sympto/pre-ovulatory.js index 8cc86b9d..5749e1a2 100644 --- a/lib/sympto/pre-ovulatory.js +++ b/lib/sympto/pre-ovulatory.js @@ -1,13 +1,20 @@ import { LocalDate } from "js-joda" -export default function(cycle) { +export default function(cycle, previousCycles) { + // TODO handle no previous cycles + let preOvuPhaseLength = 5 + + //TODO make sure it handles weird cases like fhm < 9 + const minus8DayRuleResult = apply8DayRule(previousCycles) + if (minus8DayRuleResult) preOvuPhaseLength = minus8DayRuleResult + const startDate = LocalDate.parse(cycle[0].date) - const fiveDayEndDate = startDate.plusDays(4).toString() - const fiveDayRuleDays = cycle.slice(0, 5).filter(d => d.date <= fiveDayEndDate) - const preOvulatoryDays = getDaysUntilFertileMucus(fiveDayRuleDays) + const preOvuPhaseEndDate = startDate.plusDays(preOvuPhaseLength - 1).toString() + const maybePreOvuDays = cycle.slice(0, 5).filter(d => d.date <= preOvuPhaseEndDate) + const preOvulatoryDays = getDaysUntilFertileMucus(maybePreOvuDays) let endDate - if (preOvulatoryDays.length === fiveDayRuleDays.length) { - endDate = fiveDayEndDate + if (preOvulatoryDays.length === maybePreOvuDays.length) { + endDate = preOvuPhaseEndDate } else { endDate = preOvulatoryDays[preOvulatoryDays.length - 1].date } @@ -29,4 +36,6 @@ function getDaysUntilFertileMucus(days) { return days.slice(0, firstFertileMucusDayIndex) } return days -} \ No newline at end of file +} + +function apply8DayRule() {} \ No newline at end of file diff --git a/test/sympto/index.spec.js b/test/sympto/index.spec.js index ebc0106f..eaf1e5c6 100644 --- a/test/sympto/index.spec.js +++ b/test/sympto/index.spec.js @@ -23,7 +23,7 @@ describe('sympto', () => { it('with no shifts detects only peri-ovulatory', function () { const status = getSensiplanStatus({ cycle: cycleWithoutAnyShifts, - previousCycle: cycleWithoutTempShift + previousCycles: [cycleWithoutTempShift] }) expect(status).to.eql({ @@ -40,7 +40,7 @@ describe('sympto', () => { it('with shifts detects only peri-ovulatory and post-ovulatory', function () { const status = getSensiplanStatus({ cycle: cycleWithTempAndMucusShift, - previousCycle: cycleWithoutTempShift + previousCycles: [cycleWithoutTempShift] }) expect(status.temperatureShift).to.be.an('object') @@ -66,7 +66,7 @@ describe('sympto', () => { it('according to 5-day-rule', function () { const status = getSensiplanStatus({ cycle: fiveDayCycle, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(Object.keys(status.phases).length).to.eql(1) @@ -83,7 +83,7 @@ describe('sympto', () => { it('according to 5-day-rule', function () { const status = getSensiplanStatus({ cycle: cycleWithTempAndNoMucusShift, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(Object.keys(status.phases).length).to.eql(2) @@ -101,7 +101,7 @@ describe('sympto', () => { it('according to 5-day-rule with shortened pre-phase', function () { const status = getSensiplanStatus({ cycle: cycleWithEarlyMucus, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(Object.keys(status.phases).length).to.eql(2) @@ -121,7 +121,7 @@ describe('sympto', () => { it('according to 5-day-rule', function () { const status = getSensiplanStatus({ cycle: cycleWithTempAndMucusShift, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(Object.keys(status.phases).length).to.eql(3) @@ -149,7 +149,7 @@ describe('sympto', () => { it('with fhM + mucus peak on same day finds correct start of post-ovu phase', () => { const status = getSensiplanStatus({ cycle: mucusPeakAndFhmOnSameDay, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(status.temperatureShift).to.be.an('object') @@ -180,7 +180,7 @@ describe('sympto', () => { it('with fhM 2 days before mucus peak waits for end of mucus eval', () => { const status = getSensiplanStatus({ cycle: fhmTwoDaysBeforeMucusPeak, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(status.temperatureShift).to.be.an('object') @@ -211,7 +211,7 @@ describe('sympto', () => { it('with another mucus peak 5 days after fHM ignores it', () => { const status = getSensiplanStatus({ cycle: mucusPeak5DaysAfterFhm, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(status.temperatureShift).to.be.an('object') @@ -242,7 +242,7 @@ describe('sympto', () => { it('with mucus peak 2 days before fhM waits for end of temp eval', () => { const status = getSensiplanStatus({ cycle: mucusPeakTwoDaysBeforeFhm, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(status.temperatureShift).to.be.an('object') @@ -273,7 +273,7 @@ describe('sympto', () => { it('with mucus peak 5 days before fhM waits for end of temp eval', () => { const status = getSensiplanStatus({ cycle: fhm5DaysAfterMucusPeak, - previousCycle: cycleWithTempShift + previousCycles: [cycleWithTempShift] }) expect(status.temperatureShift).to.be.an('object') @@ -302,6 +302,15 @@ describe('sympto', () => { }) }) + describe('applying the minus-8 rule', () => { + it('shortens the pre-ovu phase if there is a previous <13 fhm') + it('shortens the pre-ovu phase if there is a previous <13 fhm with less than 12 cycles') + it('shortens the pre-ovu phase if mucus occurs') + it('lengthens the pre-ovu phase if >= 12 cycles') + it('does not lengthen the pre-ovu phase if < 12 cycles') + it('does not lengthen the pre-ovu phase if < 12 cycles') + }) + describe('when args are wrong', () => { it('throws when arg object is not in right format', () => { const wrongObject = { hello: 'world' } @@ -316,10 +325,10 @@ describe('sympto', () => { hello: 'world', bleeding: { value: 0 } }], - previousCycle: [{ + previousCycles: [[{ date: '1992-09-09', bleeding: { value: 0 } - }] + }]] })).to.throw(AssertionError) expect(() => getSensiplanStatus({ cycle: [{ @@ -327,20 +336,20 @@ describe('sympto', () => { temperature: {value: '35'}, bleeding: { value: 0 } }], - previousCycle: [{ + previousCycles: [[{ date: '1992-09-09', bleeding: { value: 0 } - }] + }]] })).to.throw(AssertionError) expect(() => getSensiplanStatus({ cycle: [{ date: '09-14-2017', bleeding: { value: 0 } }], - previousCycle: [{ + previousCycles: [[{ date: '1992-09-09', bleeding: { value: 0 } - }] + }]] })).to.throw(AssertionError) }) it('throws if first cycle day does not have bleeding value', () => { @@ -351,11 +360,11 @@ describe('sympto', () => { value: 'medium' } }], - previousCycle: [ + previousCycles: [[ { date: '2017-09-23', } - ] + ]] })).to.throw(AssertionError) }) }) -- GitLab