Skip to content
Snippets Groups Projects
chart.js 4.82 KiB
Newer Older
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
  }
}