123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- /**
- * @author tlwr [toby@toby.codes]
- * @author Matt C [me@mitt.dev]
- * @copyright Crown Copyright 2019
- * @license Apache-2.0
- */
- import OperationError from "../errors/OperationError.mjs";
- /**
- * @constant
- * @default
- */
- export const RECORD_DELIMITER_OPTIONS = ["Line feed", "CRLF"];
- /**
- * @constant
- * @default
- */
- export const FIELD_DELIMITER_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Tab"];
- /**
- * Default from colour
- *
- * @constant
- * @default
- */
- export const COLOURS = {
- min: "white",
- max: "black"
- };
- /**
- * Gets values from input for a plot.
- *
- * @param {string} input
- * @param {string} recordDelimiter
- * @param {string} fieldDelimiter
- * @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
- * @param {number} length
- * @returns {Object[]}
- */
- export function getValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded, length) {
- let headings;
- const values = [];
- input
- .split(recordDelimiter)
- .forEach((row, rowIndex) => {
- const split = row.split(fieldDelimiter);
- if (split.length !== length) throw new OperationError(`Each row must have length ${length}.`);
- if (columnHeadingsAreIncluded && rowIndex === 0) {
- headings = split;
- } else {
- values.push(split);
- }
- });
- return { headings, values };
- }
- /**
- * Gets values from input for a scatter plot.
- *
- * @param {string} input
- * @param {string} recordDelimiter
- * @param {string} fieldDelimiter
- * @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
- * @returns {Object[]}
- */
- export function getScatterValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
- let { headings, values } = getValues(
- input,
- recordDelimiter,
- fieldDelimiter,
- columnHeadingsAreIncluded,
- 2
- );
- if (headings) {
- headings = {x: headings[0], y: headings[1]};
- }
- values = values.map(row => {
- const x = parseFloat(row[0], 10),
- y = parseFloat(row[1], 10);
- if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
- if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");
- return [x, y];
- });
- return { headings, values };
- }
- /**
- * Gets values from input for a scatter plot with colour from the third column.
- *
- * @param {string} input
- * @param {string} recordDelimiter
- * @param {string} fieldDelimiter
- * @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
- * @returns {Object[]}
- */
- export function getScatterValuesWithColour(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
- let { headings, values } = getValues(
- input,
- recordDelimiter, fieldDelimiter,
- columnHeadingsAreIncluded,
- 3
- );
- if (headings) {
- headings = {x: headings[0], y: headings[1]};
- }
- values = values.map(row => {
- const x = parseFloat(row[0], 10),
- y = parseFloat(row[1], 10),
- colour = row[2];
- if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
- if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");
- return [x, y, colour];
- });
- return { headings, values };
- }
- /**
- * Gets values from input for a time series plot.
- *
- * @param {string} input
- * @param {string} recordDelimiter
- * @param {string} fieldDelimiter
- * @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
- * @returns {Object[]}
- */
- export function getSeriesValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
- const { values } = getValues(
- input,
- recordDelimiter, fieldDelimiter,
- false,
- 3
- );
- let xValues = new Set();
- const series = {};
- values.forEach(row => {
- const serie = row[0],
- xVal = row[1],
- val = parseFloat(row[2], 10);
- if (Number.isNaN(val)) throw new OperationError("Values must be numbers in base 10.");
- xValues.add(xVal);
- if (typeof series[serie] === "undefined") series[serie] = {};
- series[serie][xVal] = val;
- });
- xValues = new Array(...xValues);
- const seriesList = [];
- for (const seriesName in series) {
- const serie = series[seriesName];
- seriesList.push({name: seriesName, data: serie});
- }
- return { xValues, series: seriesList };
- }
|