StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
6.9 KiB
248 lines
6.9 KiB
4 years ago
|
'use strict';
|
||
|
const semverutils = require('semver-utils');
|
||
|
const _ = require('lodash');
|
||
|
const chalk = require('chalk');
|
||
|
const util = require('util');
|
||
|
const semver = require('semver');
|
||
|
|
||
|
const VERSION_BASE_PARTS = ['major', 'minor', 'patch'];
|
||
|
const VERSION_ADDED_PARTS = ['release', 'build'];
|
||
|
const VERSION_PARTS = [].concat(VERSION_BASE_PARTS, VERSION_ADDED_PARTS);
|
||
|
const VERSION_PART_DELIM = {
|
||
|
major: '',
|
||
|
minor: '.',
|
||
|
patch: '.',
|
||
|
release: '-',
|
||
|
build: '+'
|
||
|
};
|
||
|
const WILDCARDS = ['^', '~', '.*', '.x'];
|
||
|
const WILDCARDS_PURE = ['^', '~', '^*', '*', 'x', 'x.x', 'x.x.x'];
|
||
|
const WILDCARD_PURE_REGEX = new RegExp(`^(${WILDCARDS_PURE.join('|')
|
||
|
.replace(/\^/g, '\\^')
|
||
|
.replace(/\*/g, '\\*')})$`);
|
||
|
const SEMANTIC_DIRECT = new RegExp('^\\d+\\.\\d+\\.\\d+([-|+].*)*$');
|
||
|
|
||
|
/**
|
||
|
* @param {string} version
|
||
|
* @returns {number} The number of parts in the version
|
||
|
*/
|
||
|
function numParts(version) {
|
||
|
|
||
|
const [semver] = semverutils.parseRange(version);
|
||
|
|
||
|
if (!semver) {
|
||
|
throw new Error(util.format('semverutils.parseRange returned null when trying to parse "%s". This is probably a problem with the "semver-utils" dependency. Please report an issue at https://github.com/tjunnone/npm-check-updates/issues.', version));
|
||
|
}
|
||
|
|
||
|
return _.intersection(VERSION_PARTS, Object.keys(semver)).length;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Increases or decreases the given precision by the given amount, e.g. major+1 -> minor
|
||
|
* @param {string} precision
|
||
|
* @param {number} n
|
||
|
* @returns {string}
|
||
|
*/
|
||
|
function precisionAdd(precision, n) {
|
||
|
|
||
|
if (n === 0) {
|
||
|
return precision;
|
||
|
}
|
||
|
|
||
|
const index = n === 0 ? precision :
|
||
|
VERSION_BASE_PARTS.includes(precision) ? VERSION_BASE_PARTS.indexOf(precision) + n :
|
||
|
VERSION_ADDED_PARTS.includes(precision) ? VERSION_BASE_PARTS.length + n :
|
||
|
null;
|
||
|
|
||
|
if (index === null) {
|
||
|
throw new Error(`Invalid precision: ${precision}`);
|
||
|
}
|
||
|
if (!VERSION_PARTS[index]) {
|
||
|
throw new Error(`Invalid precision math${arguments}`);
|
||
|
}
|
||
|
|
||
|
return VERSION_PARTS[index];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Joins the major, minor, patch, release, and build parts (controlled by an
|
||
|
* optional precision arg) of a semver object into a dot-delimited string.
|
||
|
* @param semver
|
||
|
* @param {string} [precision]
|
||
|
* @returns {string}
|
||
|
*/
|
||
|
function stringify(semver, precision) {
|
||
|
|
||
|
// get a list of the parts up until (and including) the given precision
|
||
|
// or all of them, if no precision is specified
|
||
|
const parts = precision ? VERSION_PARTS.slice(0, VERSION_PARTS.indexOf(precision)+1) : VERSION_PARTS;
|
||
|
|
||
|
// pair each part with its delimiter and join together
|
||
|
return parts
|
||
|
.filter(part => {
|
||
|
return VERSION_BASE_PARTS.includes(precision) || semver[part];
|
||
|
})
|
||
|
.map(part => {
|
||
|
return VERSION_PART_DELIM[part] + (semver[part] || '0');
|
||
|
})
|
||
|
.join('');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets how precise this version number is (major, minor, patch, release, or build)
|
||
|
* @param {string} version
|
||
|
* @returns {string}
|
||
|
*/
|
||
|
function getPrecision(version) {
|
||
|
const [semver] = semverutils.parseRange(version);
|
||
|
// expects VERSION_PARTS to be in correct order
|
||
|
return VERSION_PARTS.slice().reverse().find(_.propertyOf(semver));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the precision of a (loose) semver to the specified level: major, minor, etc.
|
||
|
* @param {string} version
|
||
|
* @param {string} [precision]
|
||
|
* @returns {string}
|
||
|
*/
|
||
|
function setPrecision(version, precision) {
|
||
|
const [semver] = semverutils.parseRange(version);
|
||
|
return stringify(semver, precision);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds a given wildcard (^,~,.*,.x) to a version number. Adds ^ and ~ to the
|
||
|
* beginning. Replaces everything after the major version number with .* or .x
|
||
|
* @param {string} version
|
||
|
* @param {string} wildcard
|
||
|
* @returns {string}
|
||
|
*/
|
||
|
function addWildCard(version, wildcard) {
|
||
|
return wildcard === '^' || wildcard === '~' ?
|
||
|
wildcard + version :
|
||
|
setPrecision(version, 'major') + wildcard;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if the given string is one of the wild cards.
|
||
|
* @param {string} version
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
function isWildCard(version) {
|
||
|
return WILDCARD_PURE_REGEX.test(version);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if the given digit is a wildcard for a part of a version.
|
||
|
* @param {"*"|"x"} versionPart
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
function isWildPart(versionPart) {
|
||
|
return versionPart === '*' || versionPart === 'x';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Colorize the parts of a version string (to) that are different than
|
||
|
* another (from). Assumes that the two verson strings are in the same format.
|
||
|
* @param from
|
||
|
* @param to
|
||
|
* @returns {string}
|
||
|
*/
|
||
|
function colorizeDiff(from, to) {
|
||
|
let leadingWildcard = '';
|
||
|
|
||
|
// separate out leading ^ or ~
|
||
|
if (/^[~^]/.test(to) && to[0] === from[0]) {
|
||
|
leadingWildcard = to[0];
|
||
|
to = to.slice(1);
|
||
|
from = from.slice(1);
|
||
|
}
|
||
|
|
||
|
// split into parts
|
||
|
const partsToColor = to.split('.');
|
||
|
const partsToCompare = from.split('.');
|
||
|
|
||
|
let i = partsToColor.findIndex((part, i) => part !== partsToCompare[i]);
|
||
|
i = i >= 0 ? i : partsToColor.length;
|
||
|
|
||
|
// major = red (or any change before 1.0.0)
|
||
|
// minor = cyan
|
||
|
// patch = green
|
||
|
const color = i === 0 || partsToColor[0] === '0' ? 'red' :
|
||
|
i === 1 ? 'cyan' :
|
||
|
'green';
|
||
|
|
||
|
// if we are colorizing only part of the word, add a dot in the middle
|
||
|
const middot = i > 0 && i < partsToColor.length ? '.' : '';
|
||
|
|
||
|
return leadingWildcard +
|
||
|
partsToColor.slice(0,i).join('.') +
|
||
|
middot +
|
||
|
chalk[color](partsToColor.slice(i).join('.'));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param versions Array of all available versions
|
||
|
* @param current Current version
|
||
|
* @param level major/minor
|
||
|
* @returns {string} String representation of the suggested version. If the current version
|
||
|
* is not direct then returns null
|
||
|
*/
|
||
|
function findGreatestByLevel(versions, current, level) {
|
||
|
if (!SEMANTIC_DIRECT.test(current)) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
const cur = semverutils.parse(current);
|
||
|
return _.chain(versions)
|
||
|
.map(v => {
|
||
|
return {
|
||
|
string: v,
|
||
|
parsed: semverutils.parse(v)
|
||
|
};
|
||
|
})
|
||
|
.filter(o => {
|
||
|
if (level === 'minor' && o.parsed.major !== cur.major) {
|
||
|
return false;
|
||
|
}
|
||
|
return o.parsed[level] === cur[level];
|
||
|
})
|
||
|
.map(o => {
|
||
|
return o.string;
|
||
|
})
|
||
|
.last()
|
||
|
.value();
|
||
|
}
|
||
|
|
||
|
/** Comparator used to sort semver versions */
|
||
|
function compareVersions(a, b) {
|
||
|
return semver.gt(a, b) ? 1 : a === b ? 0 : -1;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {String} version
|
||
|
* @returns {boolean} True if the version is any kind of prerelease: alpha, beta, rc, pre
|
||
|
*/
|
||
|
function isPre(version) {
|
||
|
return getPrecision(version) === 'release';
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
compareVersions,
|
||
|
numParts,
|
||
|
stringify,
|
||
|
precisionAdd,
|
||
|
getPrecision,
|
||
|
setPrecision,
|
||
|
addWildCard,
|
||
|
isPre,
|
||
|
isWildCard,
|
||
|
isWildPart,
|
||
|
colorizeDiff,
|
||
|
findGreatestByLevel,
|
||
|
VERSION_BASE_PARTS,
|
||
|
VERSION_ADDED_PARTS,
|
||
|
VERSION_PARTS,
|
||
|
WILDCARDS
|
||
|
};
|