Improving cervix:
* adding tempEvalEnd value to cervix tests * more comments in code for cervix sympto * better description in cervix temp tests * take out cervix.value
This commit is contained in:
+18
-7
@@ -1,15 +1,26 @@
|
||||
export default function (cycleDays, tempEvalEndIndex) {
|
||||
const cervixDays = cycleDays.filter(day => day.cervix && !day.cervix.exclude)
|
||||
const notDetected = { detected: false }
|
||||
const cervixDays = cycleDays
|
||||
.filter(day => day.cervix && !day.cervix.exclude)
|
||||
.filter(day => typeof day.cervix.opening === 'number' && typeof day.cervix.firmness === 'number')
|
||||
|
||||
// we search for the day of cervix peak, which must:
|
||||
// * have fertile cervix values
|
||||
// * be followed by at least 3 days
|
||||
// these 3 following days must all show infertile cervix values
|
||||
// if everything applies we must check the days until the end of temperature evaluation
|
||||
// during these relevantDays no fertile cervix must occur
|
||||
|
||||
for (let i = 0; i < cervixDays.length; i++) {
|
||||
const day = cervixDays[i]
|
||||
if (isClosedAndHard(day.cervix)) continue
|
||||
// the three following days must be with closed and hard cervix
|
||||
// AND no other cervix value may occur until temperature evaluation has
|
||||
// been completed
|
||||
|
||||
// the three following days must be with closed and hard cervix (indicating an infertile cervix)
|
||||
const threeFollowingDays = cervixDays.slice(i + 1, i + 4)
|
||||
if (threeFollowingDays.length < 3) continue
|
||||
|
||||
// no other fertile cervix value may occur until temperature evaluation has
|
||||
// been completed
|
||||
const fertileCervixOccursIn3FollowingDays = threeFollowingDays.some(day => {
|
||||
return !isClosedAndHard(day.cervix)
|
||||
})
|
||||
@@ -33,9 +44,9 @@ export default function (cycleDays, tempEvalEndIndex) {
|
||||
}
|
||||
}
|
||||
|
||||
return { detected: false }
|
||||
return notDetected
|
||||
}
|
||||
|
||||
function isClosedAndHard (cervix) {
|
||||
return cervix.value.opening === 0 && cervix.value.firmness === 0
|
||||
function isClosedAndHard (cervixDay) {
|
||||
return cervixDay.opening === 0 && cervixDay.firmness === 0
|
||||
}
|
||||
|
||||
+4
-4
@@ -115,10 +115,10 @@ function throwIfArgsAreNotInRequiredFormat(cycles) {
|
||||
if (day.mucus) assert.equal(typeof day.mucus.value, 'number', "Mucus value must be a number.")
|
||||
if (day.mucus) assert.ok(day.mucus.value >= 0, "Mucus value must greater or equal to 0.")
|
||||
if (day.mucus) assert.ok(day.mucus.value <= 4, "Mucus value must be below 5.")
|
||||
if (day.cervix) assert.ok(day.cervix.value.opening >= 0, "Cervix opening value must be 0 or bigger")
|
||||
if (day.cervix) assert.ok(day.cervix.value.opening <= 2, "Cervix opening value must be 2 or smaller")
|
||||
if (day.cervix) assert.ok(day.cervix.value.firmness >= 0, "Cervix firmness value must be 0 or bigger")
|
||||
if (day.cervix) assert.ok(day.cervix.value.firmness <= 1, "Cervix firmness value must be 1 or smaller")
|
||||
if (day.cervix) assert.ok(day.cervix.opening >= 0, "Cervix opening value must be 0 or bigger")
|
||||
if (day.cervix) assert.ok(day.cervix.opening <= 2, "Cervix opening value must be 2 or smaller")
|
||||
if (day.cervix) assert.ok(day.cervix.firmness >= 0, "Cervix firmness value must be 0 or bigger")
|
||||
if (day.cervix) assert.ok(day.cervix.firmness <= 1, "Cervix firmness value must be 1 or smaller")
|
||||
assert.equal(typeof cycle[0].bleeding.value, 'number', "Bleeding value must be a number")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -4,8 +4,10 @@ function convertToSymptoFormat(val) {
|
||||
value: val.temperature,
|
||||
exclude: false
|
||||
}
|
||||
if (val.cervix) sympto.cervix = {
|
||||
value: val.cervix,
|
||||
|
||||
if (val.cervix && typeof val.cervix.opening === 'number' && typeof val.cervix.firmness === 'number') sympto.cervix = {
|
||||
opening: val.cervix.opening,
|
||||
firmness: val.cervix.firmness,
|
||||
exclude: false
|
||||
}
|
||||
if (val.bleeding) sympto.bleeding = {
|
||||
@@ -130,7 +132,7 @@ export const tempShift3DaysAfterCervixShift = [
|
||||
{ date: '2018-05-20', temperature: 36.7, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-05-21', temperature: 36.6, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-05-22', temperature: 36.85, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-05-23', temperature: 36.8, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-05-23', temperature: 36.8, cervix: { opening: 1, firmness: 0 } },
|
||||
{ date: '2018-05-24', temperature: 36.85, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-05-25', temperature: 36.95, cervix: { opening: 0, firmness: 0 } },
|
||||
{ date: '2018-05-26', temperature: 36.85, cervix: { opening: 0, firmness: 1 } },
|
||||
|
||||
@@ -48,10 +48,9 @@ describe('sympto', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
it('with temp and cervix shifts detects only peri- and post-ovulatory phases', () => {
|
||||
it('with temp and cervix shifts at the same day an no previous cycle detects only peri- and post-ovulatory phases', () => {
|
||||
const status = getSensiplanStatus({
|
||||
cycle: cervixShiftAndFhmOnSameDay,
|
||||
previousCycle: cycleWithoutFhm,
|
||||
secondarySymptom: 'cervix'
|
||||
})
|
||||
expect(Object.keys(status.phases).length).to.eql(2)
|
||||
@@ -72,7 +71,7 @@ describe('sympto', () => {
|
||||
})
|
||||
})
|
||||
describe('with previous higher temp measurement', () => {
|
||||
it('with no shifts detects only peri-ovulatory in 5-day long cycle according to 5-day rule', () => {
|
||||
it('with no shifts in 5-day long cycle detects only peri-ovulatory according to 5-day rule', () => {
|
||||
const status = getSensiplanStatus({
|
||||
cycle: fiveDayCycle,
|
||||
previousCycle: cervixShiftAndFhmOnSameDay,
|
||||
@@ -85,7 +84,7 @@ describe('sympto', () => {
|
||||
end: { date: '2018-08-05' }
|
||||
})
|
||||
})
|
||||
it('with no shifts detects pre- and peri-ovulatory phase according to 5-day-rule', () => {
|
||||
it('with no shifts in long cycle detects pre- and peri-ovulatory phase according to 5-day-rule', () => {
|
||||
const status = getSensiplanStatus({
|
||||
cycle: longCycleWithoutAnyShifts,
|
||||
previousCycle: cervixShiftAndFhmOnSameDay,
|
||||
@@ -105,7 +104,7 @@ describe('sympto', () => {
|
||||
start: { date: '2018-07-06' }
|
||||
})
|
||||
})
|
||||
it('with evaluation of temperature and cervix end on same day', () => {
|
||||
it('with temperature and cervix evaluation end on same day detects all 3 phases', () => {
|
||||
const status = getSensiplanStatus({
|
||||
cycle: cervixShiftAndFhmOnSameDay,
|
||||
previousCycle: cervixShiftAndFhmOnSameDay,
|
||||
@@ -135,7 +134,7 @@ describe('sympto', () => {
|
||||
.filter(({date}) => date >= '2018-08-15')
|
||||
})
|
||||
})
|
||||
it('when temperature shift happens 3 days after cervix shift', () => {
|
||||
it('with temperature shift 3 days after cervix shift detects all 3 phases', () => {
|
||||
const status = getSensiplanStatus({
|
||||
cycle: tempShift3DaysAfterCervixShift,
|
||||
previousCycle: cervixShiftAndFhmOnSameDay,
|
||||
@@ -167,7 +166,7 @@ describe('sympto', () => {
|
||||
.filter(({date}) => date >= '2018-05-21')
|
||||
})
|
||||
})
|
||||
it('when cervix shift happens 2 days after temperature shift', () => {
|
||||
it('with cervix shift 2 days after temperature shift detects all 3 phases', () => {
|
||||
const status = getSensiplanStatus({
|
||||
cycle: cervixShift2DaysAfterTempShift,
|
||||
previousCycle: cervixShiftAndFhmOnSameDay,
|
||||
@@ -198,7 +197,7 @@ describe('sympto', () => {
|
||||
start: { date: '2018-04-19', time: '18:00' }
|
||||
})
|
||||
})
|
||||
it('when no infertile phase can be detected', () => {
|
||||
it('with no shifts no ovulation is found detects only pre and peri-ovulatory phase', () => {
|
||||
const status = getSensiplanStatus({
|
||||
cycle: noOvulationDetected,
|
||||
previousCycle: cervixShiftAndFhmOnSameDay,
|
||||
|
||||
+107
-34
@@ -5,87 +5,160 @@ const expect = chai.expect
|
||||
|
||||
function turnIntoCycleDayObject(value, fakeDate) {
|
||||
const hardAndClosed = {
|
||||
value: { opening: 0, firmness: 0 }
|
||||
opening: 0,
|
||||
firmness: 0
|
||||
}
|
||||
const hardAndOpen = {
|
||||
value: { opening: 1, firmness: 0 }
|
||||
opening: 1,
|
||||
firmness: 0
|
||||
}
|
||||
const softAndClosed = {
|
||||
value: { opening: 0, firmness: 1 }
|
||||
opening: 0,
|
||||
firmness: 1
|
||||
}
|
||||
const softAndOpen = {
|
||||
value: { opening: 1, firmness: 1 }
|
||||
opening: 1,
|
||||
firmness: 1
|
||||
}
|
||||
const cervixStates = [hardAndClosed, hardAndOpen, softAndClosed, softAndOpen]
|
||||
return {
|
||||
date: fakeDate,
|
||||
cervix: cervixStates[value],
|
||||
exclude: false
|
||||
cervix: {
|
||||
opening: cervixStates[value].opening,
|
||||
firmness: cervixStates[value].firmness,
|
||||
exclude: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('sympto', () => {
|
||||
describe('detects cervix shift', () => {
|
||||
it('when shift happens at day 15 with consistent following days', function () {
|
||||
const values = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 1, 3, 1, 0, 0, 0, 0]
|
||||
it('when shift happens at day 13 with consistent following days of infertile cervix until tempEvalEnd', () => {
|
||||
const values = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0]
|
||||
.map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values)
|
||||
const status = getCervixStatus(values, 16)
|
||||
expect(status).to.eql({
|
||||
detected: true,
|
||||
cervixPeakBeforeShift: {
|
||||
date: 13,
|
||||
cervix: {value: { opening: 1, firmness: 0 }},
|
||||
exclude: false
|
||||
date: 10,
|
||||
cervix: {
|
||||
opening: 1,
|
||||
firmness: 1,
|
||||
exclude: false
|
||||
}
|
||||
},
|
||||
evaluationCompleteDay: {
|
||||
date: 16,
|
||||
cervix: { value: { opening: 0, firmness: 0 }},
|
||||
exclude: false
|
||||
date: 13,
|
||||
cervix: {
|
||||
opening: 0,
|
||||
firmness: 0,
|
||||
exclude: false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
it('at the very first day of cycle days even if later shift happens again', function () {
|
||||
it('right at the start of cycle days even if later shift happens again because tempEvalEnd happened before second potential shift', () => {
|
||||
const values = [2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
.map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values)
|
||||
const status = getCervixStatus(values, 5)
|
||||
expect(status).to.eql({
|
||||
detected: true,
|
||||
cervixPeakBeforeShift: {
|
||||
date: 0,
|
||||
cervix: { value: { opening: 0, firmness: 1 } },
|
||||
exclude: false
|
||||
cervix: {
|
||||
opening: 0,
|
||||
firmness: 1,
|
||||
exclude: false
|
||||
},
|
||||
},
|
||||
evaluationCompleteDay: {
|
||||
date: 3,
|
||||
cervix: { value: { opening: 0, firmness: 0 } },
|
||||
exclude: false
|
||||
cervix: {
|
||||
opening: 0,
|
||||
firmness: 0,
|
||||
exclude: false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
it('at day 6 although right at the start of cycle days a potential shift happened but because tempEvalEnd happens after second shift', () => {
|
||||
const values = [2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
.map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values, 10)
|
||||
expect(status).to.eql({
|
||||
detected: true,
|
||||
cervixPeakBeforeShift: {
|
||||
date: 6,
|
||||
cervix: {
|
||||
opening: 1,
|
||||
firmness: 0,
|
||||
exclude: false
|
||||
},
|
||||
},
|
||||
evaluationCompleteDay: {
|
||||
date: 9,
|
||||
cervix: {
|
||||
opening: 0,
|
||||
firmness: 0,
|
||||
exclude: false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
it('when the cervix shift is happening after tempEvalEnd', () => {
|
||||
const values = [1,1,1,1,1,2,3,3,3,3,1,1,1,1,0,0,0,0,0,0,0]
|
||||
.map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values, 10)
|
||||
expect(status).to.eql({
|
||||
detected: true,
|
||||
cervixPeakBeforeShift: {
|
||||
date: 13,
|
||||
cervix: {
|
||||
opening: 1,
|
||||
firmness: 0,
|
||||
exclude: false
|
||||
}
|
||||
},
|
||||
evaluationCompleteDay: {
|
||||
date: 16,
|
||||
cervix: {
|
||||
opening: 0,
|
||||
firmness: 0,
|
||||
exclude: false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('detects no cervix shift', () => {
|
||||
it('if there are less than 3 days closed and hard cervix', function () {
|
||||
const values = [0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 1, 1, 1, 0, 0, 2, 0]
|
||||
it('if there are less than 3 days closed and hard cervix', () => {
|
||||
const values = [0, 0, 0, 1, 1, 1, 2, 0, 3, 3, 3, 1, 1, 1, 0, 0, 2, 0]
|
||||
.map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values)
|
||||
const status = getCervixStatus(values, 15)
|
||||
expect(status).to.eql({ detected: false })
|
||||
})
|
||||
it('if there are no cervix values', function () {
|
||||
const values = [].map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values)
|
||||
expect(status).to.eql({ detected: false })
|
||||
})
|
||||
it('when the cervix values are all the same', function () {
|
||||
const values = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
it('if cycleDays have not enough cervix values to detect valid cervix shift', () => {
|
||||
const values = [2,0,0]
|
||||
.map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values)
|
||||
const status = getCervixStatus(values, 17)
|
||||
expect(status).to.eql({ detected: false })
|
||||
})
|
||||
it('if no days of hard and closed cervix are tracked', function () {
|
||||
it('if no days indicate fertile cervix which could be cervix peak', () => {
|
||||
const values = [1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1]
|
||||
.map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values)
|
||||
const status = getCervixStatus(values, 12)
|
||||
expect(status).to.eql({ detected: false })
|
||||
})
|
||||
it('if all days indicate infertile cervix values', () => {
|
||||
const values = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
.map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values, 9)
|
||||
expect(status).to.eql({ detected: false })
|
||||
})
|
||||
it('if there are no cervix values', () => {
|
||||
const values = [].map(turnIntoCycleDayObject)
|
||||
const status = getCervixStatus(values, 15)
|
||||
expect(status).to.eql({ detected: false })
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user