import { LocalDate } from 'js-joda' import { scaleObservable, unitObservable } from '../../local-storage' import { getCycleDay } from '../../db' import config from '../../config' export function normalizeToScale(temp, columnHeight) { const scale = scaleObservable.value const valueRelativeToScale = (scale.max - temp) / (scale.max - scale.min) return getAbsoluteValue(valueRelativeToScale, columnHeight) } function getAbsoluteValue(relative, columnHeight) { // we add some height to have some breathing room const verticalPadding = columnHeight * config.temperatureScale.verticalPadding const scaleHeight = columnHeight - 2 * verticalPadding return scaleHeight * relative + verticalPadding } export function getTickPositions(columnHeight) { const units = unitObservable.value const scaleMin = scaleObservable.value.min const scaleMax = scaleObservable.value.max const numberOfTicks = (scaleMax - scaleMin) * (1 / units) + 1 const tickDistance = 1 / (numberOfTicks - 1) const tickPositions = [] for (let i = 0; i < numberOfTicks; i++) { const position = getAbsoluteValue(tickDistance * i, columnHeight) tickPositions.push(position) } return tickPositions } export function getTickList(columnHeight) { const units = unitObservable.value const scaleMax = scaleObservable.value.max return getTickPositions(columnHeight).map((tickPosition, i) => { const tick = scaleMax - i * units let isBold, label, shouldShowLabel if (Number.isInteger(tick)) { isBold = true label = tick.toString() + '.0' } else { isBold = false label = tick.toString() } // when temp range <= 3, units === 0.1 we show temp values with step 0.2 // when temp range > 3, units === 0.5 we show temp values with step 0.5 if (units === 0.1) { // show label with step 0.2 shouldShowLabel = !(tick * 10 % 2) } else { // show label with step 0.5 shouldShowLabel = !(tick * 10 % 5) } return { position: tickPosition, label, isBold, shouldShowLabel, } }) } export function isSymptomDataComplete(symptom, dateString) { const cycleDayData = getCycleDay(dateString) const symptomData = cycleDayData[symptom] const dataCompletenessCheck = { 'cervix': () => { const { opening, firmness } = symptomData return (opening !== null) && (firmness !== null) }, 'mucus': () => { const { feeling, texture } = symptomData return (feeling !== null) && (texture !== null) }, 'default': () => { return true } } return (dataCompletenessCheck[symptom] || dataCompletenessCheck['default'])() } function getInfoForNeighborColumns(dateString, columnHeight) { const ret = { rightY: null, rightTemperatureExclude: null, leftY: null, leftTemperatureExclude: null } const target = LocalDate.parse(dateString) const dayBefore = target.minusDays(1).toString() const dayAfter = target.plusDays(1).toString() const cycleDayBefore = getCycleDay(dayBefore) const cycleDayAfter = getCycleDay(dayAfter) if (cycleDayAfter && cycleDayAfter.temperature) { ret.rightY = normalizeToScale(cycleDayAfter.temperature.value, columnHeight) ret.rightTemperatureExclude = cycleDayAfter.temperature.exclude } if (cycleDayBefore && cycleDayBefore.temperature) { ret.leftY = normalizeToScale(cycleDayBefore.temperature.value, columnHeight) ret.leftTemperatureExclude = cycleDayBefore.temperature.exclude } return ret } export function getTemperatureProps(symptomData, columnHeight, dateString) { const extractedData = {} const { value, exclude } = symptomData const neighborTemperatureGraphPoints = getInfoForNeighborColumns(dateString, columnHeight) for (const key in neighborTemperatureGraphPoints) { extractedData[key] = neighborTemperatureGraphPoints[key] } return Object.assign({ value, y: normalizeToScale(value, columnHeight), temperatureExclude: exclude, }, extractedData) } export const symptomColorMethods = { 'mucus': (symptomData) => { const { feeling, texture } = symptomData const colorIndex = feeling + texture return colorIndex }, 'cervix': (symptomData) => { const { opening, firmness } = symptomData const isDataComplete = opening !== null && firmness !== null const isClosedAndHard = isDataComplete && (opening === 0 && firmness === 0) const colorIndex = isClosedAndHard ? 0 : 2 return colorIndex }, 'sex': (symptomData) => { const { solo, partner } = symptomData const colorIndex = (solo !== null && partner !== null) ? (solo + 2 * partner - 1) : 0 return colorIndex }, 'bleeding': (symptomData) => { const { value } = symptomData const colorIndex = value return colorIndex }, 'default': () => { // desire, pain, mood, note const colorIndex = 0 return colorIndex } }