From 0179c4588ed957c608cf9890ca7e8bb99638baf8 Mon Sep 17 00:00:00 2001 From: Julia Friesel <julia.friesel@gmail.com> Date: Tue, 10 Jul 2018 10:56:33 +0200 Subject: [PATCH] Detect pre- and postovulatory phase with no previous higher measurement --- lib/sympto/index.js | 73 +++++++++++++------- test/sympto/index.spec.js | 142 ++++++++++++++++++++++++++++---------- 2 files changed, 155 insertions(+), 60 deletions(-) diff --git a/lib/sympto/index.js b/lib/sympto/index.js index a4952bdf..8e448fe5 100644 --- a/lib/sympto/index.js +++ b/lib/sympto/index.js @@ -1,33 +1,58 @@ import getTemperatureShift from './temperature' import getMucusShift from './mucus' -export default function (cycleDays) { - const assumeFertileStatus = { assumeFertility: true } - // TODO second phase calculation - if (cycleDays.length) assumeFertileStatus.phases = [ - { - startDate: cycleDays[0].date, - startTime: '00:00' - }, - 'TODO' - ] - - const temperatureShift = getTemperatureShift(cycleDays) - if (!temperatureShift.detected) return assumeFertileStatus +export default function ({ cycle, previousCycle }) { + // TODO check for basic stuff, throw if nonexistent + const status = { + assumeFertility: true, + phases: { + periOvulatory: { + start: { + date: null, + time: '00:00' + }, + cycleDays: null + } + } + } - const tempEvalEndIndex = cycleDays.indexOf(temperatureShift.evaluationCompleteDay) - const mucusShift = getMucusShift(cycleDays, tempEvalEndIndex) - if (!mucusShift.detected) return assumeFertileStatus + // if there was no first higher measurement in the previous cycle, + // no infertile preovulatory phase may be assumed - const phase2 = { - startDate: temperatureShift.evaluationCompleteDay.date, - startTime: '18:00' + if (getTemperatureShift(previousCycle).detected) { + // add preOvulatory phase + } else { + const first = cycle[0] + status.phases.periOvulatory.start.date = first.date + status.phases.periOvulatory.cycleDays = [...cycle] } - return { - assumeFertility: false, - temperatureShift, - mucusShift, - phases: assumeFertileStatus.phases.concat(phase2) + const temperatureShift = getTemperatureShift(cycle) + if (!temperatureShift.detected) return status + + const tempEvalEndIndex = cycle.indexOf(temperatureShift.evaluationCompleteDay) + const mucusShift = getMucusShift(cycle, tempEvalEndIndex) + if (!mucusShift.detected) return status + + const periOvulatoryEnd = + temperatureShift.evaluationCompleteDay.date > mucusShift.evaluationCompleteDay.date ? + temperatureShift.evaluationCompleteDay : mucusShift.evaluationCompleteDay + + const prevPeriOvulatoryDays = status.phases.periOvulatory.cycleDays + const periOvulatoryEndIndex = prevPeriOvulatoryDays.indexOf(periOvulatoryEnd) + + status.phases.postOvulatory = { + start: { + date: periOvulatoryEnd.date, + time: '18:00' + }, + cycleDays: prevPeriOvulatoryDays.slice(periOvulatoryEndIndex) } + + status.phases.periOvulatory.cycleDays = prevPeriOvulatoryDays.slice(0, periOvulatoryEndIndex + 1) + + status.mucusShift = mucusShift + status.temperatureShift = temperatureShift + + return status } \ No newline at end of file diff --git a/test/sympto/index.spec.js b/test/sympto/index.spec.js index 65550a05..b27ca980 100644 --- a/test/sympto/index.spec.js +++ b/test/sympto/index.spec.js @@ -11,48 +11,117 @@ function convertToSymptoFormat(val, i) { return sympto } +const cycleWithTempShift = [36.6, 36.6, 36.6, 36.6, 36.6, 36.6, 36.8, 36.8, 36.8] + .map(num => ({ temperature: num })) + .map(convertToSymptoFormat) + +const cycleWithoutTempShift = [36.6, 36.6, 36.6, 36.6, 36.6, 36.6, 36.8, 36.8] + .map(num => ({ temperature: num })) + .map(convertToSymptoFormat) + +const cycleWithTempAndMucusShift = [ + { temperature: 36.6, bleeding: 2 }, + { temperature: 36.65 }, + { temperature: 36.5 }, + { temperature: 36.6 }, + { temperature: 36.55 }, + { temperature: 36.7, mucus: 0 }, + { temperature: 36.75, mucus: 0 }, + { temperature: 36.45, mucus: 1 }, + { temperature: 36.5, mucus: 4 }, + { temperature: 36.4, mucus: 2 }, + { temperature: 36.5, mucus: 3 }, + { temperature: 36.55, mucus: 3 }, + { temperature: 36.45, mucus: 3 }, + { temperature: 36.5, mucus: 4 }, + { temperature: 36.55, mucus: 4 }, + { temperature: 36.7, mucus: 3 }, + { temperature: 36.65, mucus: 3 }, + { temperature: 36.75, mucus: 4 }, + { temperature: 36.8, mucus: 1 }, + { temperature: 36.85, mucus: 2 }, + { temperature: 36.8, mucus: 2 }, + { temperature: 36.9, mucus: 2 }, + { temperature: 36.9, mucus: 1 }, + { temperature: 36.85, mucus: 1 }, + { temperature: 36.9, mucus: 1 }, + { temperature: 36.8, mucus: 1 }, + { temperature: 36.9, mucus: 1 } +].map(convertToSymptoFormat) + describe('sympto', () => { describe('evaluating mucus and temperature shift together', () => { - it('reports fertile when mucus reaches best quality again within temperature evaluation phase', function () { - const values = [ - { temperature: 36.6 , bleeding: 2 }, - { temperature: 36.65 }, - { temperature: 36.5 }, - { temperature: 36.6 }, - { temperature: 36.55 }, - { temperature: 36.7, mucus: 0 }, - { temperature: 36.75, mucus: 0 }, - { temperature: 36.45, mucus: 1 }, - { temperature: 36.5, mucus: 4 }, - { temperature: 36.4, mucus: 2 }, - { temperature: 36.5, mucus: 3 }, - { temperature: 36.55, mucus: 3 }, - { temperature: 36.45, mucus: 3 }, - { temperature: 36.5, mucus: 4 }, - { temperature: 36.55, mucus: 4 }, - { temperature: 36.7, mucus: 3 }, - { temperature: 36.65, mucus: 3 }, - { temperature: 36.75, mucus: 4 }, - { temperature: 36.8, mucus: 1 }, - { temperature: 36.85, mucus: 2 }, - { temperature: 36.8, mucus: 2 }, - { temperature: 36.9, mucus: 2 }, - { temperature: 36.9, mucus: 1 }, - { temperature: 36.85, mucus: 1 }, - { temperature: 36.9, mucus: 1 }, - { temperature: 36.8, mucus: 1 }, - { temperature: 36.9, mucus: 1 } - ] + describe('with no previous higher measurement', () => { + it('with no shifts detects only periovulatory', function () { + const values = [ + { temperature: 36.6, bleeding: 2 }, + { temperature: 36.65 }, + { temperature: 36.5 }, + { temperature: 36.6 }, + { temperature: 36.55 }, + { temperature: 36.7, mucus: 0 }, + { temperature: 36.75, mucus: 0 }, + { temperature: 36.45, mucus: 1 } + ] + + const cycle = values.map(convertToSymptoFormat) + const status = getSensiplanStatus({ + cycle, + previousCycle: cycleWithoutTempShift + }) + + expect(status).to.eql({ + assumeFertility: true, + phases: { + periOvulatory: { + start: { + date: 0, + time: '00:00' + }, + cycleDays: cycle + } + }, + }) + }) + + it('with shifts detects only periovulatory and postovulatory', function () { + const status = getSensiplanStatus({ + cycle: cycleWithTempAndMucusShift, + previousCycle: cycleWithoutTempShift + }) - const temperatures = values.map(convertToSymptoFormat) + expect(status.temperatureShift).to.be.an('object') + expect(status.mucusShift).to.be.an('object') + expect(status.assumeFertility).to.be.true() + expect(Object.keys(status.phases)).to.eql(['periOvulatory', 'postOvulatory']) + expect(status.phases.periOvulatory).to.eql({ + start: { + date: 0, + time: '00:00' + }, + cycleDays: cycleWithTempAndMucusShift.slice(0, 21) + }) + expect(status.phases.postOvulatory).to.eql({ + start: { + date: 20, + time: '18:00' + }, + cycleDays: cycleWithTempAndMucusShift.slice(20) + }) + }) + }) + }) + describe('with shifts', () => { + it.skip('reports fertile when mucus reaches best quality again within temperature evaluation phase', function () { const status = getSensiplanStatus(temperatures) expect(status).to.eql({ assumeFertility: false, - phases: [ - { startDate: 0, startTime: '00:00'}, - 'TODO', - { startDate: 17, startTime: '18:00'} - ], + phases: { + preOvulatory: + { startDate: 0, startTime: '00:00' }, + periOvulatory: 'TODO', + postOvulatory: { startDate: 17, startTime: '18:00' } + }, temperatureShift: { detected: true, ltl: 36.55, @@ -78,5 +147,6 @@ describe('sympto', () => { } }) }) + }) }) \ No newline at end of file -- GitLab