UNPKG

@grnsft/if

Version:

Impact Framework

146 lines 20.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Interpolation = void 0; const typescript_cubic_spline_1 = __importDefault(require("typescript-cubic-spline")); const zod_1 = require("zod"); const types_1 = require("@grnsft/if-core/types"); const interfaces_1 = require("@grnsft/if-core/interfaces"); const utils_1 = require("@grnsft/if-core/utils"); const validations_1 = require("../../../common/util/validations"); const config_1 = require("../../config"); const { X_Y_EQUAL, ARRAY_LENGTH_NON_EMPTY, WITHIN_THE_RANGE, MISSING_CONFIG } = config_1.STRINGS; const { ConfigError } = utils_1.ERRORS; exports.Interpolation = (0, interfaces_1.PluginFactory)({ configValidation: (config) => { if (!config || !Object.keys(config)?.length) { throw new ConfigError(MISSING_CONFIG); } const schema = zod_1.z .object({ method: zod_1.z.nativeEnum(types_1.Method), x: zod_1.z.array(zod_1.z.number()), y: zod_1.z.array(zod_1.z.number()), 'input-parameter': zod_1.z.string(), 'output-parameter': zod_1.z.string(), }) .refine(data => data.x && data.y && data.x.length === data.y.length, { message: X_Y_EQUAL, }) .refine(data => data.x.length > 1 && data.y.length > 1, { message: ARRAY_LENGTH_NON_EMPTY, }); const defaultMethod = config.method ?? types_1.Method.LINEAR; const updatedConfig = Object.assign({}, { method: defaultMethod }, config, { x: sortPoints(config.x), y: sortPoints(config.y), }); return (0, validations_1.validate)(schema, updatedConfig); }, inputValidation: (input, config, index) => { const inputParameter = config['input-parameter']; const schema = zod_1.z .object({ timestamp: zod_1.z.string().or(zod_1.z.date()), duration: zod_1.z.number(), [inputParameter]: zod_1.z.number().gte(0).or(zod_1.z.literal('off')), }) .refine(data => (data[inputParameter] >= config.x[0] && data[inputParameter] <= config.x[config.x.length - 1]) || data[inputParameter] === 'off', { message: WITHIN_THE_RANGE, }); return (0, validations_1.validate)(schema, input, index); }, implementation: async (inputs, config) => { const { 'input-parameter': inputParameter, 'output-parameter': outputParameter, } = config; return inputs.map(input => { if (input[inputParameter] === 'off') { return { ...input, [inputParameter]: 0, [outputParameter]: 0, }; } return { ...input, [outputParameter]: calculateResult(config, input), }; }); }, allowArithmeticExpressions: ['input-parameter'], }); /** * Calculates the appropriate interpolation value based on the specified method type in the config and input parameters. */ const calculateResult = (config, input) => { const methodType = { linear: getLinearInterpolation(config, input), spline: getSplineInterpolation(config, input), polynomial: getPolynomialInterpolation(config, input), }; return methodType[config.method]; }; /** * Calculates the interpolation when the method is linear. */ const getLinearInterpolation = (config, input) => { const parameter = typeof config['input-parameter'] === 'number' ? config['input-parameter'] : input[config['input-parameter']]; const xPoints = config.x; const yPoints = config.y; const result = xPoints.reduce((acc, xPoint, i) => { if (parameter === xPoint) { acc.baseCpu = xPoint; acc.baseRate = yPoints[i]; } else if (parameter > xPoint && parameter < xPoints[i + 1]) { acc.baseCpu = xPoint; acc.baseRate = yPoints[i]; acc.ratio = (yPoints[i + 1] - yPoints[i]) / (xPoints[i + 1] - xPoint); } return acc; }, { baseRate: 0, baseCpu: 0, ratio: 0 }); return result.baseRate + (parameter - result.baseCpu) * result.ratio; }; /** * Calculates the interpolation when the method is spline. */ const getSplineInterpolation = (config, input) => { const parameter = typeof config['input-parameter'] === 'number' ? config['input-parameter'] : input[config['input-parameter']]; const xPoints = config.x; const yPoints = config.y; const spline = new typescript_cubic_spline_1.default(xPoints, yPoints); return spline.at(parameter); }; /** * Calculates the interpolation when the method is polynomial. */ const getPolynomialInterpolation = (config, input) => { const parameter = typeof config['input-parameter'] === 'number' ? config['input-parameter'] : input[config['input-parameter']]; const xPoints = config.x; const yPoints = config.y; const result = xPoints.reduce((acc, x, i) => { const term = yPoints[i] * xPoints.reduce((prod, xPoint, j) => { if (j !== i) { return (prod * (parameter - xPoint)) / (x - xPoint); } return prod; }, 1); return acc + term; }, 0); return result; }; /** * Sorts given point items in ascending order. */ const sortPoints = (items) => items.sort((a, b) => a - b); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaWYtcnVuL2J1aWx0aW5zL2ludGVycG9sYXRpb24vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsc0ZBQTZDO0FBQzdDLDZCQUFzQjtBQUV0QixpREFBeUU7QUFDekUsMkRBQXlEO0FBQ3pELGlEQUE2QztBQUU3QyxrRUFBMEQ7QUFFMUQseUNBQXFDO0FBRXJDLE1BQU0sRUFBQyxTQUFTLEVBQUUsc0JBQXNCLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFDLEdBQ3pFLGdCQUFPLENBQUM7QUFFVixNQUFNLEVBQUMsV0FBVyxFQUFDLEdBQUcsY0FBTSxDQUFDO0FBRWhCLFFBQUEsYUFBYSxHQUFHLElBQUEsMEJBQWEsRUFBQztJQUN6QyxnQkFBZ0IsRUFBRSxDQUFDLE1BQW9CLEVBQUUsRUFBRTtRQUN6QyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLEVBQUU7WUFDM0MsTUFBTSxJQUFJLFdBQVcsQ0FBQyxjQUFjLENBQUMsQ0FBQztTQUN2QztRQUVELE1BQU0sTUFBTSxHQUFHLE9BQUM7YUFDYixNQUFNLENBQUM7WUFDTixNQUFNLEVBQUUsT0FBQyxDQUFDLFVBQVUsQ0FBQyxjQUFNLENBQUM7WUFDNUIsQ0FBQyxFQUFFLE9BQUMsQ0FBQyxLQUFLLENBQUMsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3RCLENBQUMsRUFBRSxPQUFDLENBQUMsS0FBSyxDQUFDLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN0QixpQkFBaUIsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFO1lBQzdCLGtCQUFrQixFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUU7U0FDL0IsQ0FBQzthQUNELE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUks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InNvdXJjZXNDb250ZW50IjpbImltcG9ydCBTcGxpbmUgZnJvbSAndHlwZXNjcmlwdC1jdWJpYy1zcGxpbmUnO1xuaW1wb3J0IHt6fSBmcm9tICd6b2QnO1xuXG5pbXBvcnQge1BsdWdpblBhcmFtcywgQ29uZmlnUGFyYW1zLCBNZXRob2R9IGZyb20gJ0Bncm5zZnQvaWYtY29yZS90eXBlcyc7XG5pbXBvcnQge1BsdWdpbkZhY3Rvcnl9IGZyb20gJ0Bncm5zZnQvaWYtY29yZS9pbnRlcmZhY2VzJztcbmltcG9ydCB7RVJST1JTfSBmcm9tICdAZ3Juc2Z0L2lmLWNvcmUvdXRpbHMnO1xuXG5pbXBvcnQge3ZhbGlkYXRlfSBmcm9tICcuLi8uLi8uLi9jb21tb24vdXRpbC92YWxpZGF0aW9ucyc7XG5cbmltcG9ydCB7U1RSSU5HU30gZnJvbSAnLi4vLi4vY29uZmlnJztcblxuY29uc3Qge1hfWV9FUVVBTCwgQVJSQVlfTEVOR1RIX05PTl9FTVBUWSwgV0lUSElOX1RIRV9SQU5HRSwgTUlTU0lOR19DT05GSUd9ID1cbiAgU1RSSU5HUztcblxuY29uc3Qge0NvbmZpZ0Vycm9yfSA9IEVSUk9SUztcblxuZXhwb3J0IGNvbnN0IEludGVycG9sYXRpb24gPSBQbHVnaW5GYWN0b3J5KHtcbiAgY29uZmlnVmFsaWRhdGlvbjogKGNvbmZpZzogQ29uZmlnUGFyYW1zKSA9PiB7XG4gICAgaWYgKCFjb25maWcgfHwgIU9iamVjdC5rZXlzKGNvbmZpZyk/Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IENvbmZpZ0Vycm9yKE1JU1NJTkdfQ09ORklHKTtcbiAgICB9XG5cbiAgICBjb25zdCBzY2hlbWEgPSB6XG4gICAgICAub2JqZWN0KHtcbiAgICAgICAgbWV0aG9kOiB6Lm5hdGl2ZUVudW0oTWV0aG9kKSxcbiAgICAgICAgeDogei5hcnJheSh6Lm51bWJlcigpKSxcbiAgICAgICAgeTogei5hcnJheSh6Lm51bWJlcigpKSxcbiAgICAgICAgJ2lucHV0LXBhcmFtZXRlcic6IHouc3RyaW5nKCksXG4gICAgICAgICdvdXRwdXQtcGFyYW1ldGVyJzogei5zdHJpbmcoKSxcbiAgICAgIH0pXG4gICAgICAucmVmaW5lKGRhdGEgPT4gZGF0YS54ICYmIGRhdGEueSAmJiBkYXRhLngubGVuZ3RoID09PSBkYXRhLnkubGVuZ3RoLCB7XG4gICAgICAgIG1lc3NhZ2U6IFhfWV9FUVVBTCxcbiAgICAgIH0pXG4gICAgICAucmVmaW5lKGRhdGEgPT4gZGF0YS54Lmxlbmd0aCA+IDEgJiYgZGF0YS55Lmxlbmd0aCA+IDEsIHtcbiAgICAgICAgbWVzc2FnZTogQVJSQVlfTEVOR1RIX05PTl9FTVBUWSxcbiAgICAgIH0pO1xuXG4gICAgY29uc3QgZGVmYXVsdE1ldGhvZCA9IGNvbmZpZy5tZXRob2QgPz8gTWV0aG9kLkxJTkVBUjtcbiAgICBjb25zdCB1cGRhdGVkQ29uZmlnID0gT2JqZWN0LmFzc2lnbih7fSwge21ldGhvZDogZGVmYXVsdE1ldGhvZH0sIGNvbmZpZywge1xuICAgICAgeDogc29ydFBvaW50cyhjb25maWcueCksXG4gICAgICB5OiBzb3J0UG9pbnRzKGNvbmZpZy55KSxcbiAgICB9KTtcblxuICAgIHJldHVybiB2YWxpZGF0ZTx6LmluZmVyPHR5cGVvZiBzY2hlbWE+PihzY2hlbWEsIHVwZGF0ZWRDb25maWcpO1xuICB9LFxuICBpbnB1dFZhbGlkYXRpb246IChcbiAgICBpbnB1dDogUGx1Z2luUGFyYW1zLFxuICAgIGNvbmZpZzogQ29uZmlnUGFyYW1zLFxuICAgIGluZGV4OiBudW1iZXIgfCB1bmRlZmluZWRcbiAgKSA9PiB7XG4gICAgY29uc3QgaW5wdXRQYXJhbWV0ZXIgPSBjb25maWdbJ2lucHV0LXBhcmFtZXRlciddO1xuXG4gICAgY29uc3Qgc2NoZW1hID0gelxuICAgICAgLm9iamVjdCh7XG4gICAgICAgIHRpbWVzdGFtcDogei5zdHJpbmcoKS5vcih6LmRhdGUoKSksXG4gICAgICAgIGR1cmF0aW9uOiB6Lm51bWJlcigpLFxuICAgICAgICBbaW5wdXRQYXJhbWV0ZXJdOiB6Lm51bWJlcigpLmd0ZSgwKS5vcih6LmxpdGVyYWwoJ29mZicpKSxcbiAgICAgIH0pXG4gICAgICAucmVmaW5lKFxuICAgICAgICBkYXRhID0+XG4gICAgICAgICAgKGRhdGFbaW5wdXRQYXJhbWV0ZXJdID49IGNvbmZpZy54WzBdICYmXG4gICAgICAgICAgICBkYXRhW2lucHV0UGFyYW1ldGVyXSA8PSBjb25maWcueFtjb25maWcueC5sZW5ndGggLSAxXSkgfHxcbiAgICAgICAgICBkYXRhW2lucHV0UGFyYW1ldGVyXSA9PT0gJ29mZicsXG4gICAgICAgIHtcbiAgICAgICAgICBtZXNzYWdlOiBXSVRISU5fVEhFX1JBTkdFLFxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgcmV0dXJuIHZhbGlkYXRlPHouaW5mZXI8dHlwZW9mIHNjaGVtYT4+KHNjaGVtYSwgaW5wdXQsIGluZGV4KTtcbiAgfSxcbiAgaW1wbGVtZW50YXRpb246IGFzeW5jIChpbnB1dHM6IFBsdWdpblBhcmFtc1tdLCBjb25maWc6IENvbmZpZ1BhcmFtcykgPT4ge1xuICAgIGNvbnN0IHtcbiAgICAgICdpbnB1dC1wYXJhbWV0ZXInOiBpbnB1dFBhcmFtZXRlcixcbiAgICAgICdvdXRwdXQtcGFyYW1ldGVyJzogb3V0cHV0UGFyYW1ldGVyLFxuICAgIH0gPSBjb25maWc7XG5cbiAgICByZXR1cm4gaW5wdXRzLm1hcChpbnB1dCA9PiB7XG4gICAgICBpZiAoaW5wdXRbaW5wdXRQYXJhbWV0ZXJdID09PSAnb2ZmJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLmlucHV0LFxuICAgICAgICAgIFtpbnB1dFBhcmFtZXRlcl06IDAsXG4gICAgICAgICAgW291dHB1dFBhcmFtZXRlcl06IDAsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLmlucHV0LFxuICAgICAgICBbb3V0cHV0UGFyYW1ldGVyXTogY2FsY3VsYXRlUmVzdWx0KGNvbmZpZywgaW5wdXQpLFxuICAgICAgfTtcbiAgICB9KTtcbiAgfSxcbiAgYWxsb3dBcml0aG1ldGljRXhwcmVzc2lvbnM6IFsnaW5wdXQtcGFyYW1ldGVyJ10sXG59KTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBhcHByb3ByaWF0ZSBpbnRlcnBvbGF0aW9uIHZhbHVlIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQgbWV0aG9kIHR5cGUgaW4gdGhlIGNvbmZpZyBhbmQgaW5wdXQgcGFyYW1ldGVycy5cbiAqL1xuY29uc3QgY2FsY3VsYXRlUmVzdWx0ID0gKGNvbmZpZzogQ29uZmlnUGFyYW1zLCBpbnB1dDogUGx1Z2luUGFyYW1zKSA9PiB7XG4gIGNvbnN0IG1ldGhvZFR5cGU6IHtba2V5OiBzdHJpbmddOiBudW1iZXJ9ID0ge1xuICAgIGxpbmVhcjogZ2V0TGluZWFySW50ZXJwb2xhdGlvbihjb25maWcsIGlucHV0KSxcbiAgICBzcGxpbmU6IGdldFNwbGluZUludGVycG9sYXRpb24oY29uZmlnLCBpbnB1dCksXG4gICAgcG9seW5vbWlhbDogZ2V0UG9seW5vbWlhbEludGVycG9sYXRpb24oY29uZmlnLCBpbnB1dCksXG4gIH07XG5cbiAgcmV0dXJuIG1ldGhvZFR5cGVbY29uZmlnLm1ldGhvZF07XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGludGVycG9sYXRpb24gd2hlbiB0aGUgbWV0aG9kIGlzIGxpbmVhci5cbiAqL1xuY29uc3QgZ2V0TGluZWFySW50ZXJwb2xhdGlvbiA9IChjb25maWc6IENvbmZpZ1BhcmFtcywgaW5wdXQ6IFBsdWdpblBhcmFtcykgPT4ge1xuICBjb25zdCBwYXJhbWV0ZXIgPVxuICAgIHR5cGVvZiBjb25maWdbJ2lucHV0LXBhcmFtZXRlciddID09PSAnbnVtYmVyJ1xuICAgICAgPyBjb25maWdbJ2lucHV0LXBhcmFtZXRlciddXG4gICAgICA6IGlucHV0W2NvbmZpZ1snaW5wdXQtcGFyYW1ldGVyJ11dO1xuICBjb25zdCB4UG9pbnRzOiBudW1iZXJbXSA9IGNvbmZpZy54O1xuICBjb25zdCB5UG9pbnRzOiBudW1iZXJbXSA9IGNvbmZpZy55O1xuXG4gIGNvbnN0IHJlc3VsdCA9IHhQb2ludHMucmVkdWNlKFxuICAgIChhY2MsIHhQb2ludCwgaSkgPT4ge1xuICAgICAgaWYgKHBhcmFtZXRlciA9PT0geFBvaW50KSB7XG4gICAgICAgIGFjYy5iYXNlQ3B1ID0geFBvaW50O1xuICAgICAgICBhY2MuYmFzZVJhdGUgPSB5UG9pbnRzW2ldO1xuICAgICAgfSBlbHNlIGlmIChwYXJhbWV0ZXIgPiB4UG9pbnQgJiYgcGFyYW1ldGVyIDwgeFBvaW50c1tpICsgMV0pIHtcbiAgICAgICAgYWNjLmJhc2VDcHUgPSB4UG9pbnQ7XG4gICAgICAgIGFjYy5iYXNlUmF0ZSA9IHlQb2ludHNbaV07XG4gICAgICAgIGFjYy5yYXRpbyA9ICh5UG9pbnRzW2kgKyAxXSAtIHlQb2ludHNbaV0pIC8gKHhQb2ludHNbaSArIDFdIC0geFBvaW50KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LFxuICAgIHtiYXNlUmF0ZTogMCwgYmFzZUNwdTogMCwgcmF0aW86IDB9XG4gICk7XG5cbiAgcmV0dXJuIHJlc3VsdC5iYXNlUmF0ZSArIChwYXJhbWV0ZXIgLSByZXN1bHQuYmFzZUNwdSkgKiByZXN1bHQucmF0aW87XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGludGVycG9sYXRpb24gd2hlbiB0aGUgbWV0aG9kIGlzIHNwbGluZS5cbiAqL1xuY29uc3QgZ2V0U3BsaW5lSW50ZXJwb2xhdGlvbiA9IChjb25maWc6IENvbmZpZ1BhcmFtcywgaW5wdXQ6IFBsdWdpblBhcmFtcykgPT4ge1xuICBjb25zdCBwYXJhbWV0ZXIgPVxuICAgIHR5cGVvZiBjb25maWdbJ2lucHV0LXBhcmFtZXRlciddID09PSAnbnVtYmVyJ1xuICAgICAgPyBjb25maWdbJ2lucHV0LXBhcmFtZXRlciddXG4gICAgICA6IGlucHV0W2NvbmZpZ1snaW5wdXQtcGFyYW1ldGVyJ11dO1xuICBjb25zdCB4UG9pbnRzOiBudW1iZXJbXSA9IGNvbmZpZy54O1xuICBjb25zdCB5UG9pbnRzOiBudW1iZXJbXSA9IGNvbmZpZy55O1xuICBjb25zdCBzcGxpbmU6IGFueSA9IG5ldyBTcGxpbmUoeFBvaW50cywgeVBvaW50cyk7XG5cbiAgcmV0dXJuIHNwbGluZS5hdChwYXJhbWV0ZXIpO1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBpbnRlcnBvbGF0aW9uIHdoZW4gdGhlIG1ldGhvZCBpcyBwb2x5bm9taWFsLlxuICovXG5jb25zdCBnZXRQb2x5bm9taWFsSW50ZXJwb2xhdGlvbiA9IChcbiAgY29uZmlnOiBDb25maWdQYXJhbXMsXG4gIGlucHV0OiBQbHVnaW5QYXJhbXNcbikgPT4ge1xuICBjb25zdCBwYXJhbWV0ZXIgPVxuICAgIHR5cGVvZiBjb25maWdbJ2lucHV0LXBhcmFtZXRlciddID09PSAnbnVtYmVyJ1xuICAgICAgPyBjb25maWdbJ2lucHV0LXBhcmFtZXRlciddXG4gICAgICA6IGlucHV0W2NvbmZpZ1snaW5wdXQtcGFyYW1ldGVyJ11dO1xuICBjb25zdCB4UG9pbnRzOiBudW1iZXJbXSA9IGNvbmZpZy54O1xuICBjb25zdCB5UG9pbnRzOiBudW1iZXJbXSA9IGNvbmZpZy55O1xuXG4gIGNvbnN0IHJlc3VsdCA9IHhQb2ludHMucmVkdWNlKChhY2MsIHgsIGkpID0+IHtcbiAgICBjb25zdCB0ZXJtID1cbiAgICAgIHlQb2ludHNbaV0gKlxuICAgICAgeFBvaW50cy5yZWR1Y2UoKHByb2QsIHhQb2ludCwgaikgPT4ge1xuICAgICAgICBpZiAoaiAhPT0gaSkge1xuICAgICAgICAgIHJldHVybiAocHJvZCAqIChwYXJhbWV0ZXIgLSB4UG9pbnQpKSAvICh4IC0geFBvaW50KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJvZDtcbiAgICAgIH0sIDEpO1xuICAgIHJldHVybiBhY2MgKyB0ZXJtO1xuICB9LCAwKTtcblxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuLyoqXG4gKiBTb3J0cyBnaXZlbiBwb2ludCBpdGVtcyBpbiBhc2NlbmRpbmcgb3JkZXIuXG4gKi9cbmNvbnN0IHNvcnRQb2ludHMgPSAoaXRlbXM6IG51bWJlcltdKSA9PlxuICBpdGVtcy5zb3J0KChhOiBudW1iZXIsIGI6IG51bWJlcikgPT4gYSAtIGIpO1xuIl19