All files / data_handler filter_check.ts

59.32% Statements 35/59
51.42% Branches 18/35
100% Functions 4/4
64% Lines 32/50

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98      8x                                                           8x       4x           8x 8x 8x 8x 8x 8x   8x     8x 8x 8x   8x 8x 8x     4x   4x     4x 4x 4x 4x 4x 4x 4x 8x 7x 7x             2x     4x 4x 4x                  
import {Filter, VariableFilter, Variables, VectorSummary, Entity} from '../types'
 
function vector_summary(vec: number | number[], range: number[]): VectorSummary {
  Iif (Array.isArray(vec)) {
    const n = Math.min(range[1] + 1, vec.length),
      r: VectorSummary = {
        missing: 0,
        first: vec[0],
        min: Infinity,
        mean: 0,
        sum: 0,
        max: -Infinity,
        last: vec[n - 1],
      }
    let on = 0
    for (let i = Math.max(range[0], 0); i < n; i++) {
      const v = vec[i]
      if ('number' === typeof v) {
        if (isNaN(v)) {
          r.missing++
        } else {
          on++
          Iif (r.min > v) r.min = v
          Iif (r.max < v) r.max = v
          r.sum += v
        }
      } else {
        Iif ('NA' !== v) on++
      }
    }
    r.mean = on ? r.sum / on : 0
    return r
  } else {
    return {missing: Number(isNaN(vec)) + 0, first: vec, min: vec, mean: vec, sum: vec, max: vec, last: vec}
  }
}
 
export function passes_filter(
  entity: Entity,
  time_range: number[],
  filter: VariableFilter,
  variables: Variables
): boolean {
  const s: {[index: string]: VectorSummary} = {},
    adjs: {[index: string]: number} = {}
  for (let i = filter.filter_by.length; i--; ) {
    const f = filter.filter_by[i]
    const c = variables[f].code
    Iif (!(c in entity.data)) return false
    const r =
      entity.group in variables[f].info
        ? variables[f].info[entity.group].time_range
        : variables[f].time_range[entity.group]
    Iif (!r) return false
    adjs[f] = r[0]
    s[f] = vector_summary(entity.data[c], [time_range[0] - r[0], Math.max(time_range[1] - r[0], time_range[1] - r[1])])
  }
  for (let i = filter.conditions.length; i--; ) {
    const co = filter.conditions[i]
    if (
      !(co.time_component ? co.check(entity.data[variables[co.name].code], adjs[co.name] || 0) : co.check(s[co.name]))
    )
      return false
  }
  return true
}
 
export function passes_feature_filter(entities: {[index: string]: Entity}, id: string, filter: Filter[]): boolean {
  const entity = entities[id]
  for (let i = filter.length; i--; ) {
    const value = filter[i].value
    if (value !== '-1') {
      let pass = false
      const ck = (id: string) => {
        if (!pass) {
          const group = id in entities && entities[id].group
          if (
            group && group in entity.features
              ? id === entity.features[group]
              : id.length < entity.features.id.length
              ? id === entity.features.id.substring(0, id.length)
              : id === entity.features.id
          )
            pass = true
        }
      }
      if ('id' === filter[i].name && Array.isArray(value)) {
        value.forEach(ck)
        return pass
      } else E{
        ck(value + '')
        return pass
      }
    }
  }
  return true
}