squiggle/packages/squiggle-lang/src/rescript/utility/Sparklines.res

52 lines
1.5 KiB
Plaintext
Raw Normal View History

// Port of Sindre Sorhus' Sparkly to Rescript
// reference implementation: https://github.com/sindresorhus/sparkly
// Omitting rgb "fire" style, so no `chalk` dependency
type sparklyConfig = {
minimum: option<float>,
maximum: option<float>
}
let sparkly = (
2022-03-29 14:04:08 +00:00
numbers: array<float>,
~options = {minimum: None, maximum: None}
) => {
// if not numbers is not an array, throw typeerror "Expected an array"
// Unlike reference impl, we assume that all numbers are finite, i.e. no NaN.
2022-03-29 14:40:38 +00:00
let ticks = [`▁`, `▂`, `▃`, `▄`, `▅`, `▆`, `▇`, `█`]
let minimum = switch options.minimum {
2022-03-29 14:04:08 +00:00
| None => Js.Math.minMany_float(numbers)
| Some(x) => x
}
2022-03-29 14:40:38 +00:00
// let minimum = E.O.default(Js.Math.minMany_float(numbers))
let maximum = switch options.maximum {
2022-03-29 14:04:08 +00:00
| None => Js.Math.maxMany_float(numbers)
| Some(x) => x
}
2022-03-29 14:40:38 +00:00
// let maximum = E.O.default(Js.Math.maxMany_float(numbers))
// Use a high tick if data is constant and max is not equal
let ticks = if minimum == maximum && maximum != 0.0 {
[ticks[4]]
} else {
ticks
}
2022-03-29 14:04:08 +00:00
let toMapWith = (number: float) => {
let ret = {
let tickIndex = Js.Math.ceil_int((number /. maximum) *. Belt.Int.toFloat(Belt.Array.length(ticks))) - 1
let tickIndex = if maximum == 0.0 || tickIndex < 0 {
0
} else {
tickIndex
}
ticks[tickIndex]
}
ret
}
2022-03-29 14:04:08 +00:00
let ret = Belt.Array.map(numbers, toMapWith)
// Belt.Array.reduce(ret, "", (x, y) => x ++ y)
Js.Array.joinWith("", ret)
}