116 lines
3.0 KiB
JavaScript
116 lines
3.0 KiB
JavaScript
/**
|
|
* Formats a number string with common prefixes like K, M, B, T.
|
|
* For negative numbers, it returns "Negative".
|
|
* For numbers between 0 and 1, it rounds up to two decimal places.
|
|
*
|
|
* @param {string} input - The input string containing numerals.
|
|
* @returns {string} The formatted string.
|
|
*/
|
|
exports.formatPriceString = function(input) {
|
|
// Ensure input is a number
|
|
let number = typeof input === 'string' ? parseFloat(input) : input;
|
|
|
|
// Check if input is not a number
|
|
if (isNaN(number)) {
|
|
return 'Invalid input';
|
|
}
|
|
|
|
// Handle negative numbers
|
|
if (number < 0) {
|
|
return 'Negative';
|
|
}
|
|
|
|
// Handle zero
|
|
if (number === 0) {
|
|
return 'Zero';
|
|
}
|
|
|
|
// Handle numbers between 0 and 1
|
|
if (number < 1) {
|
|
return Math.ceil(number * 100) / 100;
|
|
}
|
|
|
|
// Define suffixes
|
|
const suffixes = ['', 'K', 'M', 'B', 'T'];
|
|
|
|
// Determine the suffix index
|
|
let suffixIndex = 0;
|
|
while (number >= 1000 && suffixIndex < suffixes.length - 1) {
|
|
number /= 1000;
|
|
suffixIndex++;
|
|
}
|
|
|
|
// Format the number with three decimal places after the comma
|
|
const formattedNumber = number.toFixed(3) + suffixes[suffixIndex];
|
|
|
|
return formattedNumber;
|
|
}
|
|
|
|
exports.findMinMax = function(values) {
|
|
var min = values[0];
|
|
var max = values[0];
|
|
|
|
for (var i = 1; i < values.length; i++) {
|
|
if (values[i] < min) min = values[i];
|
|
if (values[i] > max) max = values[i];
|
|
}
|
|
|
|
return { min: min, max: max };
|
|
}
|
|
|
|
exports.myLog10 = function(value) {
|
|
return Math.log(value) / Math.LN10;
|
|
}
|
|
|
|
exports.calculateOptimalYAxisSpacing = function(data) {
|
|
// Check if data is empty
|
|
if (data.length === 0) {
|
|
return { min: 0, max: 1, interval: 1 };
|
|
}
|
|
|
|
// Find the minimum and maximum values in the data
|
|
const bounds = exports.findMinMax(data);
|
|
let minY = bounds.min;
|
|
let maxY = bounds.max;
|
|
|
|
// Calculate the range of the data
|
|
let range = maxY - minY;
|
|
|
|
// If all values are the same, set a small range to avoid division by zero
|
|
if (range === 0) {
|
|
range = 1;
|
|
}
|
|
|
|
// Determine the number of ticks (e.g., 5 to 10 ticks)
|
|
let numTicks = 7; // You can adjust this value based on your preference
|
|
|
|
// Calculate the interval
|
|
let interval = range / (numTicks - 1);
|
|
|
|
// Round the interval to a nice number (e.g., 1, 2, 5, 10)
|
|
let roundedInterval = Math.pow(10, Math.floor(exports.myLog10(interval)));
|
|
if (interval / roundedInterval > 5) {
|
|
roundedInterval *= 5;
|
|
} else if (interval / roundedInterval > 2) {
|
|
roundedInterval *= 2;
|
|
}
|
|
|
|
// Adjust min and max to ensure they are on the rounded interval
|
|
let adjustedMin = Math.floor(minY / roundedInterval) * roundedInterval;
|
|
let adjustedMax = Math.ceil(maxY / roundedInterval) * roundedInterval;
|
|
|
|
let first = data[0];
|
|
let last = data[data.length - 1];
|
|
return {
|
|
min: adjustedMin,
|
|
max: adjustedMax,
|
|
interval: roundedInterval,
|
|
first: first,
|
|
last: last,
|
|
rawMin: minY,
|
|
rawMax: maxY
|
|
};
|
|
}
|
|
|
|
|