time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

index.js (13482B)


      1 import isInteger from "lodash/isInteger.js";
      2 import { REArrayIndexNotFound, REDictPropertyNotFound, REOther, } from "../errors/messages.js";
      3 import * as DateTime from "../utility/DateTime.js";
      4 import { ImmutableMap } from "../utility/immutableMap.js";
      5 import { shuffle } from "../utility/E_A.js";
      6 import lodashIsEqual from "lodash/isEqual.js";
      7 class BaseValue {
      8     clone() {
      9         return Object.assign(Object.create(Object.getPrototypeOf(this)), this);
     10     }
     11 }
     12 class VArray extends BaseValue {
     13     constructor(value) {
     14         super();
     15         this.value = value;
     16         this.type = "Array";
     17         this.publicName = "List";
     18     }
     19     toString() {
     20         return "[" + this.value.map((v) => v.toString()).join(",") + "]";
     21     }
     22     get(key) {
     23         if (key.type === "Number") {
     24             if (!isInteger(key.value)) {
     25                 throw new REArrayIndexNotFound("Array index must be an integer", key.value);
     26             }
     27             const index = key.value | 0;
     28             if (index >= 0 && index < this.value.length) {
     29                 return this.value[index];
     30             }
     31             else {
     32                 throw new REArrayIndexNotFound("Array index not found", index);
     33             }
     34         }
     35         throw new REOther("Can't access non-numerical key on an array");
     36     }
     37     flatten() {
     38         return new VArray(this.value.reduce((acc, v) => acc.concat(v.type === "Array" ? v.value : [v]), []));
     39     }
     40     shuffle() {
     41         return new VArray(shuffle(this.value));
     42     }
     43     isEqual(other) {
     44         if (this.value.length !== other.value.length) {
     45             return false;
     46         }
     47         for (let i = 0; i < this.value.length; i++) {
     48             isEqual(this.value[i], other.value[i]);
     49         }
     50         return true;
     51     }
     52 }
     53 export const vArray = (v) => new VArray(v);
     54 class VBool extends BaseValue {
     55     constructor(value) {
     56         super();
     57         this.value = value;
     58         this.type = "Bool";
     59         this.publicName = "Boolean";
     60     }
     61     toString() {
     62         return String(this.value);
     63     }
     64     isEqual(other) {
     65         return this.value === other.value;
     66     }
     67 }
     68 export const vBool = (v) => new VBool(v);
     69 class VDate extends BaseValue {
     70     constructor(value) {
     71         super();
     72         this.value = value;
     73         this.type = "Date";
     74         this.publicName = "Date";
     75     }
     76     toString() {
     77         return DateTime.Date.toString(this.value);
     78     }
     79     isEqual(other) {
     80         return this.value === other.value;
     81     }
     82 }
     83 export const vDate = (v) => new VDate(v);
     84 class VDist extends BaseValue {
     85     constructor(value) {
     86         super();
     87         this.value = value;
     88         this.type = "Dist";
     89         this.publicName = "Distribution";
     90     }
     91     toString() {
     92         return this.value.toString();
     93     }
     94     isEqual(other) {
     95         return this.value.isEqual(other.value);
     96     }
     97 }
     98 export const vDist = (v) => new VDist(v);
     99 class VLambda extends BaseValue {
    100     constructor(value) {
    101         super();
    102         this.value = value;
    103         this.type = "Lambda";
    104         this.publicName = "Function";
    105     }
    106     toString() {
    107         return this.value.toString();
    108     }
    109     get(key) {
    110         if (key.type === "String" && key.value === "parameters") {
    111             switch (this.value.type) {
    112                 case "UserDefinedLambda":
    113                     return vArray(this.value.parameters.map((parameter) => {
    114                         const fields = [
    115                             ["name", vString(parameter.name)],
    116                         ];
    117                         if (parameter.domain) {
    118                             fields.push(["domain", parameter.domain]);
    119                         }
    120                         return vDict(ImmutableMap(fields));
    121                     }));
    122                 case "BuiltinLambda":
    123                     throw new REOther("Can't access parameters on built in functions");
    124             }
    125         }
    126         throw new REOther("No such field");
    127     }
    128 }
    129 export const vLambda = (v) => new VLambda(v);
    130 class VNumber extends BaseValue {
    131     constructor(value) {
    132         super();
    133         this.value = value;
    134         this.type = "Number";
    135         this.publicName = "Number";
    136     }
    137     toString() {
    138         return String(this.value);
    139     }
    140     isEqual(other) {
    141         return this.value === other.value;
    142     }
    143 }
    144 export const vNumber = (v) => new VNumber(v);
    145 class VString extends BaseValue {
    146     constructor(value) {
    147         super();
    148         this.value = value;
    149         this.type = "String";
    150         this.publicName = "String";
    151     }
    152     toString() {
    153         return JSON.stringify(this.value);
    154     }
    155     isEqual(other) {
    156         return this.value === other.value;
    157     }
    158 }
    159 export const vString = (v) => new VString(v);
    160 class VDict extends BaseValue {
    161     constructor(value) {
    162         super();
    163         this.value = value;
    164         this.type = "Dict";
    165         this.publicName = "Dictionary";
    166     }
    167     toString() {
    168         return ("{" +
    169             [...this.value.entries()]
    170                 .map(([k, v]) => `${k}: ${v.toString()}`)
    171                 .join(",") +
    172             "}");
    173     }
    174     get(key) {
    175         if (key.type === "String") {
    176             const result = this.value.get(key.value);
    177             if (!result) {
    178                 throw new REDictPropertyNotFound("Dict property not found", key.value);
    179             }
    180             return result;
    181         }
    182         else {
    183             throw new REOther("Can't access non-string key on a dict");
    184         }
    185     }
    186     isEqual(other) {
    187         if (this.value.size !== other.value.size) {
    188             return false;
    189         }
    190         for (const [key, valueA] of this.value.entries()) {
    191             const valueB = other.value.get(key);
    192             if (!valueB) {
    193                 return false;
    194             }
    195             if (!isEqual(valueA, valueB)) {
    196                 return false;
    197             }
    198         }
    199         return true;
    200     }
    201 }
    202 export const vDict = (v) => new VDict(v);
    203 class VTimeDuration extends BaseValue {
    204     constructor(value) {
    205         super();
    206         this.value = value;
    207         this.type = "TimeDuration";
    208         this.publicName = "Time Duration";
    209     }
    210     toString() {
    211         return DateTime.Duration.toString(this.value);
    212     }
    213     isEqual(other) {
    214         return this.value === other.value;
    215     }
    216 }
    217 export const vTimeDuration = (v) => new VTimeDuration(v);
    218 function scaleIsEqual(valueA, valueB) {
    219     if (valueA.type !== valueB.type ||
    220         valueA.min !== valueB.min ||
    221         valueA.max !== valueB.max ||
    222         valueA.tickFormat !== valueB.tickFormat) {
    223         return false;
    224     }
    225     switch (valueA.type) {
    226         case "symlog":
    227             return (valueA.constant ===
    228                 valueB.constant);
    229         case "power":
    230             return (valueA.exponent ===
    231                 valueB.exponent);
    232         default:
    233             return true;
    234     }
    235 }
    236 export const SCALE_SYMLOG_DEFAULT_CONSTANT = 0.0001;
    237 export const SCALE_POWER_DEFAULT_CONSTANT = 0.1;
    238 class VScale extends BaseValue {
    239     constructor(value) {
    240         super();
    241         this.value = value;
    242         this.type = "Scale";
    243         this.publicName = "Scale";
    244     }
    245     toString() {
    246         switch (this.value.type) {
    247             case "linear":
    248                 return "Linear scale";
    249             case "log":
    250                 return "Logarithmic scale";
    251             case "symlog":
    252                 return `Symlog scale ({constant: ${this.value.constant || SCALE_SYMLOG_DEFAULT_CONSTANT}})`;
    253             case "power":
    254                 return `Power scale ({exponent: ${this.value.exponent || SCALE_POWER_DEFAULT_CONSTANT}})`;
    255         }
    256     }
    257     isEqual(other) {
    258         return scaleIsEqual(this.value, other.value);
    259     }
    260 }
    261 export const vScale = (scale) => new VScale(scale);
    262 class VInput extends BaseValue {
    263     constructor(value) {
    264         super();
    265         this.value = value;
    266         this.type = "Input";
    267         this.publicName = "Input";
    268     }
    269     toString() {
    270         switch (this.value.type) {
    271             case "text":
    272                 return "Text input";
    273             case "textArea":
    274                 return "Text area input";
    275             case "checkbox":
    276                 return "Check box input";
    277             case "select":
    278                 return `Select input (${this.value.options.join(", ")})`;
    279         }
    280     }
    281     isEqual(other) {
    282         return lodashIsEqual(this.value, other.value);
    283     }
    284 }
    285 export const vInput = (input) => new VInput(input);
    286 class VTableChart extends BaseValue {
    287     constructor(value) {
    288         super();
    289         this.value = value;
    290         this.type = "TableChart";
    291         this.publicName = "Table Chart";
    292     }
    293     toString() {
    294         return `Table with ${this.value.columns.length}x${this.value.data.length} elements`;
    295     }
    296 }
    297 export const vTableChart = (v) => new VTableChart(v);
    298 class VCalculator extends BaseValue {
    299     constructor(value) {
    300         super();
    301         this.value = value;
    302         this.type = "Calculator";
    303         this.publicName = "Calculator";
    304         this.error = null;
    305         if (!value.fn.parameterCounts().includes(value.inputs.length)) {
    306             this.setError(`Calculator function needs ${value.fn.parameterCountString()} parameters, but ${value.inputs.length} fields were provided.`);
    307         }
    308         if (value.inputs.some((x) => x.name === "")) {
    309             this.setError(`Calculator field names can't be empty.`);
    310         }
    311         const fieldNames = value.inputs.map((f) => f.name);
    312         const uniqueNames = new Set(fieldNames);
    313         if (fieldNames.length !== uniqueNames.size) {
    314             this.setError(`Duplicate calculator field names found.`);
    315         }
    316     }
    317     setError(message) {
    318         this.error = new REOther(message);
    319     }
    320     getError() {
    321         return this.error;
    322     }
    323     toString() {
    324         return `Calculator`;
    325     }
    326 }
    327 export const vCalculator = (v) => new VCalculator(v);
    328 class VPlot extends BaseValue {
    329     constructor(value) {
    330         super();
    331         this.value = value;
    332         this.type = "Plot";
    333         this.publicName = "Plot";
    334     }
    335     toString() {
    336         switch (this.value.type) {
    337             case "distributions":
    338                 return `Plot containing ${this.value.distributions
    339                     .map((x) => x.name)
    340                     .join(", ")}`;
    341             case "numericFn":
    342                 return `Plot for numeric function ${this.value.fn}`;
    343             case "distFn":
    344                 return `Plot for dist function ${this.value.fn}`;
    345             case "scatter":
    346                 return `Scatter plot for distributions ${this.value.xDist} and ${this.value.yDist}`;
    347             case "relativeValues":
    348                 return `Plot for relative values ${this.value.ids.join(", ")}`;
    349         }
    350     }
    351     get(key) {
    352         if (key.type === "String" &&
    353             key.value === "fn" &&
    354             (this.value.type === "numericFn" ||
    355                 this.value.type === "distFn" ||
    356                 this.value.type === "relativeValues")) {
    357             return vLambda(this.value.fn);
    358         }
    359         throw new REOther("Trying to access non-existent field");
    360     }
    361 }
    362 export const vPlot = (plot) => new VPlot(plot);
    363 export class VDomain extends BaseValue {
    364     constructor(value) {
    365         super();
    366         this.value = value;
    367         this.type = "Domain";
    368         this.publicName = "Domain";
    369     }
    370     toString() {
    371         return this.value.toString();
    372     }
    373     get(key) {
    374         if (key.type === "String" && this.value.type === "NumericRange") {
    375             if (key.value === "min") {
    376                 return vNumber(this.value.min);
    377             }
    378             if (key.value === "max") {
    379                 return vNumber(this.value.max);
    380             }
    381         }
    382         throw new REOther("Trying to access non-existent field");
    383     }
    384     isEqual(other) {
    385         return this.value.isEqual(other.value);
    386     }
    387 }
    388 export const vDomain = (domain) => new VDomain(domain);
    389 class VVoid extends BaseValue {
    390     constructor() {
    391         super();
    392         this.type = "Void";
    393         this.publicName = "Void";
    394     }
    395     toString() {
    396         return "()";
    397     }
    398 }
    399 export const vVoid = () => new VVoid();
    400 export function isEqual(a, b) {
    401     if (a.type !== b.type) {
    402         return false;
    403     }
    404     switch (a.type) {
    405         case "Bool":
    406         case "Number":
    407         case "String":
    408         case "Dist":
    409         case "Date":
    410         case "TimeDuration":
    411         case "Scale":
    412         case "Domain":
    413         case "Array":
    414         case "Dict":
    415             return a.isEqual(b);
    416         case "Void":
    417             return true;
    418     }
    419     if (a.toString() !== b.toString()) {
    420         return false;
    421     }
    422     throw new REOther("Equal not implemented for these inputs");
    423 }
    424 const _isUniqableType = (t) => "isEqual" in t;
    425 export function uniq(array) {
    426     const uniqueArray = [];
    427     for (const item of array) {
    428         if (!_isUniqableType(item)) {
    429             throw new REOther(`Can't apply uniq() to element with type ${item.type}`);
    430         }
    431         if (!uniqueArray.some((existingItem) => isEqual(existingItem, item))) {
    432             uniqueArray.push(item);
    433         }
    434     }
    435     return uniqueArray;
    436 }
    437 export function uniqBy(array, fn) {
    438     const seen = [];
    439     const uniqueArray = [];
    440     for (const item of array) {
    441         const computed = fn(item);
    442         if (!_isUniqableType(computed)) {
    443             throw new REOther(`Can't apply uniq() to element with type ${computed.type}`);
    444         }
    445         if (!seen.some((existingItem) => isEqual(existingItem, computed))) {
    446             seen.push(computed);
    447             uniqueArray.push(item);
    448         }
    449     }
    450     return uniqueArray;
    451 }
    452 //# sourceMappingURL=index.js.map