Repository: neherlab/covid19_scenarios
File: src/algorithms/model.ts (TypeScript)

Code before:
        })
        ages.forEach((age, i) => {
          tp.current[k][age] = d.current.exposed[i].reduce((a, b) => a + b, 0)
        })
      } else {
        ages.forEach((age, i) => {
          tp.current[k][age] = d.current[k][i]
        })
        tp.current[k].total = d.current[k].reduce((a, b) => a + b)
      }
    })

    Object.keys(tp.cumulative).forEach((k) => {
      ages.forEach((age, i) => {
        tp.cumulative[k][age] = d.cumulative[k][i]
      })
      tp.cumulative[k].total = d.cumulative[k].reduce((a, b) => a + b, 0)
    })

    res.trajectory.push(tp)
  })

  return res
}

export function exportSimulation(result: UserResult, ...ageGroups: string[]) {
  // Store parameter values

  // Down sample trajectory to once a day.
  // TODO: Make the down sampling interval a parameter
  if (ageGroups.length == 0) {
    ageGroups = ['total']
  }

  const header = keys(result.trajectory[0].current)
  const tsvHeader: string[] = header.map((x) => (x === 'critical' ? 'ICU' : x))

  const headerCumulative = keys(result.trajectory[0].cumulative)
  const tsvHeaderCumulative = headerCumulative.map((x) => `cumulative_${x}`)

  let buf = 'time'
  tsvHeader.forEach((hdr) => {
    ageGroups.forEach((age) => {
      buf += `\t${hdr} (${age})`
    })
  })
  tsvHeaderCumulative.forEach((hdr) => {
    ageGroups.forEach((age) => {
      buf += `\t${hdr} (${age})`
    })
  })

Review comment (suggestion):
It seem that the variable arguments are not needed here, as you are destructuring the array on call site anyway.
To make it more robust and less surprising, could we just pass `ageGroups` as a simple array? Perhaps defaulting to an empty array, if needed.


Code after:
        })
        ages.forEach((age, i) => {
          tp.current[k][age] = d.current.exposed[i].reduce((a, b) => a + b, 0)
        })
      } else {
        ages.forEach((age, i) => {
          tp.current[k][age] = d.current[k][i]
        })
        tp.current[k].total = d.current[k].reduce((a, b) => a + b)
      }
    })

    Object.keys(tp.cumulative).forEach((k) => {
      ages.forEach((age, i) => {
        tp.cumulative[k][age] = d.cumulative[k][i]
      })
      tp.cumulative[k].total = d.cumulative[k].reduce((a, b) => a + b, 0)
    })

    res.trajectory.push(tp)
  })

  return res
}

export function exportSimulation(result: UserResult, ageGroups: string[] = ['total']) {
  // Store parameter values

  // Down sample trajectory to once a day.
  // TODO: Make the down sampling interval a parameter

  const header = keys(result.trajectory[0].current)
  const tsvHeader: string[] = header.map((x) => (x === 'critical' ? 'ICU' : x))

  const headerCumulative = keys(result.trajectory[0].cumulative)
  const tsvHeaderCumulative = headerCumulative.map((x) => `cumulative_${x}`)

  let buf = 'time'
  tsvHeader.concat(tsvHeaderCumulative).forEach((hdr) => {
    ageGroups.forEach((age) => {
      buf += `\t${hdr} (${age})`
    })
  })
  const tsv = [buf]

  const pop: Record<string, boolean> = {}
  result.trajectory.forEach((d) => {
    const t = new Date(d.time).toISOString().slice(0, 10)
    if (t in pop) {
      return
    } // skip if date is already in table