import { numberInterpolator, piecewiseInterpolator, hslInterpolator } from 'muze-utils';
import { CONTINOUS, DISCRETE } from '../enums/constants';
import { LINEAR, SEQUENTIAL, ORDINAL, QUANTILE } from '../enums/scale-type';
import { getHslString } from './props';
const getStops = (domain, stops) => {
let newStops = [];
if (stops instanceof Array) {
newStops = stops.slice().sort();
newStops = [...new Set([domain[0], ...stops, domain[1]])].sort();
} else {
const interpolator = numberInterpolator()(...domain);
for (let i = 0; i <= stops; i++) {
newStops[i] = interpolator(i / stops);
}
}
if (newStops[0] < domain[0]) {
newStops.shift();
}
return { domain, newStops };
};
const rangeStops = (newStopsLength, range) => {
let newRange = [];
const maxRangeLength = Math.min(range.length, 18);
if (newStopsLength > maxRangeLength) {
const interpolator = piecewiseInterpolator()(hslInterpolator(), range.map(e => getHslString(e)));
for (let i = 0; i < newStopsLength; i++) {
newRange[i] = interpolator(i / (newStopsLength - 1));
}
} else {
newRange = range.slice(0, newStopsLength);
}
return { newRange };
};
/**
*
*
* @param {*} domain
*
*/
const indexedDomain = (domain) => {
const uniqueVals = domain;
const retDomain = domain.map((d, i) => (i) / (domain.length - 1));
return { domain: retDomain, uniqueVals, scaleDomain: [0, 1] };
};
/**
*
*
* @param {*} domain
*
*/
const indexedDomainMeasure = (domain, stops, range) => {
const uniqueVals = domain;
return { domain, uniqueVals, scaleDomain: [0, 1], range };
};
/**
*
*
* @param {*} domain
*
*/
const normalDomain = (domain, stops, range) => {
const uniqueVals = domain;
return { uniqueVals, domain, nice: true, range };
};
/**
*
*
* @param {*} domain
* @param {*} stops
*
*/
const steppedDomain = (domain, stops, range) => {
const { domain: uniqueVals, newStops } = getStops(domain, stops);
const { newRange } = rangeStops(newStops.length - 1, range);
return { uniqueVals, domain: newStops, nice: true, range: newRange };
};
const continousSteppedDomain = (domain, stops, range) => {
const { domain: uniqueVals, newStops } = getStops(domain, range.length - 1);
const hslRange = range.map(e => getHslString(e));
return { uniqueVals, domain: newStops, nice: true, range: hslRange };
};
/**
*
*
* @param {*} domainValue
* @param {*} scale
* @param {*} domain
* @param {*} uniqueVals
*
*/
const uniqueRange = (domainValue, scale, domain, uniqueVals) => {
const index = uniqueVals.indexOf(domainValue);
const numVal = domain[index];
return scale(numVal);
};
/**
*
*
* @param {*} domainValue
* @param {*} scale
* @param {*} domain
*
*/
const indexedRange = (domainValue, scale, domain) => {
const numVal = (domainValue - domain[0]) / (domain[domain.length - 1] - domain[0]);
return scale(numVal);
};
/**
*
*
* @param {*} domainValue
* @param {*} scale
*/
const normalRange = (domainValue, scale) => scale(domainValue);
/**
*
*
* @param {*} stops
*/
const strategies = () => ({
[`${CONTINOUS}-${CONTINOUS}-${SEQUENTIAL}`]: {
scale: SEQUENTIAL,
domainRange: () => indexedDomainMeasure,
value: () => indexedRange
},
[`${CONTINOUS}-${DISCRETE}-${SEQUENTIAL}`]: {
scale: SEQUENTIAL,
domainRange: () => indexedDomainMeasure,
value: () => indexedRange
},
[`${DISCRETE}-${DISCRETE}-${SEQUENTIAL}`]: {
scale: SEQUENTIAL,
domainRange: () => indexedDomain,
value: () => uniqueRange
},
[`${DISCRETE}-${DISCRETE}-${ORDINAL}`]: {
scale: ORDINAL,
domainRange: () => normalDomain,
value: () => normalRange
},
[`${CONTINOUS}-${CONTINOUS}-${ORDINAL}`]: {
scale: LINEAR,
domainRange: () => continousSteppedDomain,
value: () => normalRange
},
[`${CONTINOUS}-${DISCRETE}-${ORDINAL}`]: {
scale: QUANTILE,
domainRange: () => steppedDomain,
value: () => normalRange
}
});
/**
*
*
* @param {*} domainType
* @param {*} rangeType
* @param {*} schemeType
* @param {*} stops
*/
export const strategyGetter = (domainType, rangeType, schemeType, stops) =>
strategies(stops)[`${domainType}-${rangeType}-${schemeType || ''}`];