gx
chenyc
2025-06-12 7b72ac13a83764a662159d4a49b7fffb90476ecb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/**
 * @license
 * Copyright 2018 Google LLC
 *
 * Use of this source code is governed by an MIT-style
 * license that can be found in the LICENSE file or at
 * https://opensource.org/licenses/MIT.
 * =============================================================================
 */
/**
 * Built-in metrics.
 */
import * as tfc from '@tensorflow/tfjs-core';
import { tidy } from '@tensorflow/tfjs-core';
import * as K from './backend/tfjs_backend';
import { NotImplementedError, ValueError } from './errors';
import { categoricalCrossentropy as categoricalCrossentropyLoss, cosineProximity, meanAbsoluteError, meanAbsolutePercentageError, meanSquaredError, sparseCategoricalCrossentropy as sparseCategoricalCrossentropyLoss } from './losses';
import { binaryCrossentropy as lossBinaryCrossentropy } from './losses';
import { lossesMap } from './losses';
import * as util from './utils/generic_utils';
export function binaryAccuracy(yTrue, yPred) {
    return tidy(() => {
        const threshold = tfc.mul(.5, tfc.onesLike(yPred));
        const yPredThresholded = K.cast(tfc.greater(yPred, threshold), yTrue.dtype);
        return tfc.mean(tfc.equal(yTrue, yPredThresholded), -1);
    });
}
export function categoricalAccuracy(yTrue, yPred) {
    return tidy(() => K.cast(tfc.equal(tfc.argMax(yTrue, -1), tfc.argMax(yPred, -1)), 'float32'));
}
function truePositives(yTrue, yPred) {
    return tidy(() => {
        return tfc.cast(tfc.sum(tfc.logicalAnd(tfc.equal(yTrue, 1), tfc.equal(yPred, 1))), 'float32');
    });
}
function falseNegatives(yTrue, yPred) {
    return tidy(() => {
        return tfc.cast(tfc.sum(tfc.logicalAnd(tfc.equal(yTrue, 1), tfc.equal(yPred, 0))), 'float32');
    });
}
function falsePositives(yTrue, yPred) {
    return tidy(() => {
        return tfc.cast(tfc.sum(tfc.logicalAnd(tfc.equal(yTrue, 0), tfc.equal(yPred, 1))), 'float32');
    });
}
export function precision(yTrue, yPred) {
    return tidy(() => {
        const tp = truePositives(yTrue, yPred);
        const fp = falsePositives(yTrue, yPred);
        const denominator = tfc.add(tp, fp);
        return tfc.cast(tfc.where(tfc.greater(denominator, 0), tfc.div(tp, denominator), 0), 'float32');
    });
}
export function recall(yTrue, yPred) {
    return tidy(() => {
        const tp = truePositives(yTrue, yPred);
        const fn = falseNegatives(yTrue, yPred);
        const denominator = tfc.add(tp, fn);
        return tfc.cast(tfc.where(tfc.greater(denominator, 0), tfc.div(tp, denominator), 0), 'float32');
    });
}
export function binaryCrossentropy(yTrue, yPred) {
    return lossBinaryCrossentropy(yTrue, yPred);
}
export function sparseCategoricalAccuracy(yTrue, yPred) {
    if (yTrue.rank === yPred.rank) {
        yTrue = tfc.squeeze(yTrue, [yTrue.rank - 1]);
    }
    yPred = tfc.argMax(yPred, -1);
    if (yPred.dtype !== yTrue.dtype) {
        yPred = tfc.cast(yPred, yTrue.dtype);
    }
    return tfc.cast(tfc.equal(yTrue, yPred), 'float32');
}
export function topKCategoricalAccuracy(yTrue, yPred) {
    throw new NotImplementedError();
}
export function sparseTopKCategoricalAccuracy(yTrue, yPred) {
    throw new NotImplementedError();
}
// Aliases.
export const mse = meanSquaredError;
export const MSE = meanSquaredError;
export const mae = meanAbsoluteError;
export const MAE = meanAbsoluteError;
export const mape = meanAbsolutePercentageError;
export const MAPE = meanAbsolutePercentageError;
export const categoricalCrossentropy = categoricalCrossentropyLoss;
export const cosine = cosineProximity;
export const sparseCategoricalCrossentropy = sparseCategoricalCrossentropyLoss;
// TODO(cais, nielsene): Add serialize().
export const metricsMap = {
    binaryAccuracy,
    categoricalAccuracy,
    precision,
    categoricalCrossentropy,
    sparseCategoricalCrossentropy,
    mse,
    MSE,
    mae,
    MAE,
    mape,
    MAPE,
    cosine
};
export function get(identifier) {
    if (typeof identifier === 'string' && identifier in metricsMap) {
        return metricsMap[identifier];
    }
    else if (typeof identifier !== 'string' && identifier != null) {
        return identifier;
    }
    else {
        throw new ValueError(`Unknown metric ${identifier}`);
    }
}
/**
 * Get the shortcut function name.
 *
 * If the fn name is a string,
 *   directly return the string name.
 * If the function is included in metricsMap or lossesMap,
 *   return key of the map.
 *   - If the function relative to multiple keys,
 *     return the first found key as the function name.
 *   - If the function exists in both lossesMap and metricsMap,
 *     search lossesMap first.
 * If the function is not included in metricsMap or lossesMap,
 *   return the function name.
 *
 * @param fn loss function, metric function, or short cut name.
 * @returns Loss or Metric name in string.
 */
export function getLossOrMetricName(fn) {
    util.assert(fn !== null, `Unknown LossOrMetricFn ${fn}`);
    if (typeof fn === 'string') {
        return fn;
    }
    else {
        let fnName;
        for (const key of Object.keys(lossesMap)) {
            if (lossesMap[key] === fn) {
                fnName = key;
                break;
            }
        }
        if (fnName !== undefined) {
            return fnName;
        }
        for (const key of Object.keys(metricsMap)) {
            if (metricsMap[key] === fn) {
                fnName = key;
                break;
            }
        }
        if (fnName !== undefined) {
            return fnName;
        }
        return fn.name;
    }
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3RmanMtbGF5ZXJzL3NyYy9tZXRyaWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBRUg7O0dBRUc7QUFFSCxPQUFPLEtBQUssR0FBRyxNQUFNLHVCQUF1QixDQUFDO0FBQzdDLE9BQU8sRUFBUyxJQUFJLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUVuRCxPQUFPLEtBQUssQ0FBQyxNQUFNLHdCQUF3QixDQUFDO0FBQzVDLE9BQU8sRUFBQyxtQkFBbUIsRUFBRSxVQUFVLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDekQsT0FBTyxFQUFDLHVCQUF1QixJQUFJLDJCQUEyQixFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSwyQkFBMkIsRUFBRSxnQkFBZ0IsRUFBRSw2QkFBNkIsSUFBSSxpQ0FBaUMsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUN2TyxPQUFPLEVBQUMsa0JBQWtCLElBQUksc0JBQXNCLEVBQUMsTUFBTSxVQUFVLENBQUM7QUFDdEUsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUVuQyxPQUFPLEtBQUssSUFBSSxNQUFNLHVCQUF1QixDQUFDO0FBRTlDLE1BQU0sVUFBVSxjQUFjLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDekQsT0FBTyxJQUFJLENBQUMsR0FBRyxFQUFFO1FBQ2YsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ25ELE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUUsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FB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LFVBQVUsSUFBSSxJQUFJLEVBQUU7UUFDL0QsT0FBTyxVQUFVLENBQUM7S0FDbkI7U0FBTTtRQUNMLE1BQU0sSUFBSSxVQUFVLENBQUMsa0JBQWtCLFVBQVUsRUFBRSxDQUFDLENBQUM7S0FDdEQ7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFNLFVBQVUsbUJBQW1CLENBQUMsRUFBeUI7SUFDM0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssSUFBSSxFQUFFLDBCQUEwQixFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELElBQUksT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFFO1FBQzFCLE9BQU8sRUFBRSxDQUFDO0tBQ1g7U0FBTTtRQUNMLElBQUksTUFBTSxDQUFDO1FBQ1gsS0FBSyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQ3hDLElBQUksU0FBUyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDekIsTUFBTSxHQUFHLEdBQUcsQ0FBQztnQkFDYixNQUFNO2FBQ1A7U0FDRjtRQUNELElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtZQUN4QixPQUFPLE1BQU0sQ0FBQztTQUNmO1FBQ0QsS0FBSyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQ3pDLElBQUksVUFBVSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDMUIsTUFBTSxHQUFHLEdBQUcsQ0FBQztnQkFDYixNQUFNO2FBQ1A7U0FDRjtRQUNELElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRTtZQUN4QixPQUFPLE1BQU0sQ0FBQztTQUNmO1FBQ0QsT0FBUSxFQUFlLENBQUMsSUFBSSxDQUFDO0tBQzlCO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE4IEdvb2dsZSBMTENcbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGVcbiAqIGxpY2Vuc2UgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBvciBhdFxuICogaHR0cHM6Ly9vcGVuc291cmNlLm9yZy9saWNlbnNlcy9NSVQuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8qKlxuICogQnVpbHQtaW4gbWV0cmljcy5cbiAqL1xuXG5pbXBvcnQgKiBhcyB0ZmMgZnJvbSAnQHRlbnNvcmZsb3cvdGZqcy1jb3JlJztcbmltcG9ydCB7VGVuc29yLCB0aWR5fSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuXG5pbXBvcnQgKiBhcyBLIGZyb20gJy4vYmFja2VuZC90ZmpzX2JhY2tlbmQnO1xuaW1wb3J0IHtOb3RJbXBsZW1lbnRlZEVycm9yLCBWYWx1ZUVycm9yfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQge2NhdGVnb3JpY2FsQ3Jvc3NlbnRyb3B5IGFzIGNhdGVnb3JpY2FsQ3Jvc3NlbnRyb3B5TG9zcywgY29zaW5lUHJveGltaXR5LCBtZWFuQWJzb2x1dGVFcnJvciwgbWVhbkFic29sdXRlUGVyY2VudGFnZUVycm9yLCBtZWFuU3F1YXJlZEVycm9yLCBzcGFyc2VDYXRlZ29yaWNhbENyb3NzZW50cm9weSBhcyBzcGFyc2VDYXRlZ29yaWNhbENyb3NzZW50cm9weUxvc3N9IGZyb20gJy4vbG9zc2VzJztcbmltcG9ydCB7YmluYXJ5Q3Jvc3NlbnRyb3B5IGFzIGxvc3NCaW5hcnlDcm9zc2VudHJvcHl9IGZyb20gJy4vbG9zc2VzJztcbmltcG9ydCB7bG9zc2VzTWFwfSBmcm9tICcuL2xvc3Nlcyc7XG5pbXBvcnQge0xvc3NPck1ldHJpY0ZufSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCAqIGFzIHV0aWwgZnJvbSAnLi91dGlscy9nZW5lcmljX3V0aWxzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGJpbmFyeUFjY3VyYWN5KHlUcnVlOiBUZW5zb3IsIHlQcmVkOiBUZW5zb3IpOiBUZW5zb3Ige1xuICByZXR1cm4gdGlkeSgoKSA9PiB7XG4gICAgY29uc3QgdGhyZXNob2xkID0gdGZjLm11bCguNSwgdGZjLm9uZXNMaWtlKHlQcmVkKSk7XG4gICAgY29uc3QgeVByZWRUaHJlc2hvbGRlZCA9IEsuY2FzdCh0ZmMuZ3JlYXRlcih5UHJlZCwgdGhyZXNob2xkKSwgeVRydWUuZHR5cGUpO1xuICAgIHJldHVybiB0ZmMubWVhbih0ZmMuZXF1YWwoeVRydWUsIHlQcmVkVGhyZXNob2xkZWQpLCAtMSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2F0ZWdvcmljYWxBY2N1cmFjeSh5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgcmV0dXJuIHRpZHkoXG4gICAgICAoKSA9PiBLLmNhc3QoXG4gICAgICAgICAgdGZjLmVxdWFsKHRmYy5hcmdNYXgoeVRydWUsIC0xKSwgdGZjLmFyZ01heCh5UHJlZCwgLTEpKSwgJ2Zsb2F0MzInKSk7XG59XG5cbmZ1bmN0aW9uIHRydWVQb3NpdGl2ZXMoeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiB0aWR5KCgpID0+IHtcbiAgICByZXR1cm4gdGZjLmNhc3QoXG4gICAgICAgIHRmYy5zdW0odGZjLmxvZ2ljYWxBbmQodGZjLmVxdWFsKHlUcnVlLCAxKSwgdGZjLmVxdWFsKHlQcmVkLCAxKSkpLFxuICAgICAgICAnZmxvYXQzMicpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZmFsc2VOZWdhdGl2ZXMoeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiB0aWR5KCgpID0+IHtcbiAgICByZXR1cm4gdGZjLmNhc3QoXG4gICAgICAgIHRmYy5zdW0odGZjLmxvZ2ljYWxBbmQodGZjLmVxdWFsKHlUcnVlLCAxKSwgdGZjLmVxdWFsKHlQcmVkLCAwKSkpLFxuICAgICAgICAnZmxvYXQzMicpO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZmFsc2VQb3NpdGl2ZXMoeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiB0aWR5KCgpID0+IHtcbiAgICByZXR1cm4gdGZjLmNhc3QoXG4gICAgICAgIHRmYy5zdW0odGZjLmxvZ2ljYWxBbmQodGZjLmVxdWFsKHlUcnVlLCAwKSwgdGZjLmVxdWFsKHlQcmVkLCAxKSkpLFxuICAgICAgICAnZmxvYXQzMicpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByZWNpc2lvbih5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgcmV0dXJuIHRpZHkoKCkgPT4ge1xuICAgIGNvbnN0IHRwID0gdHJ1ZVBvc2l0aXZlcyh5VHJ1ZSwgeVByZWQpO1xuICAgIGNvbnN0IGZwID0gZmFsc2VQb3NpdGl2ZXMoeVRydWUsIHlQcmVkKTtcblxuICAgIGNvbnN0IGRlbm9taW5hdG9yID0gdGZjLmFkZCh0cCwgZnApO1xuXG4gICAgcmV0dXJuIHRmYy5jYXN0KFxuICAgICAgICB0ZmMud2hlcmUodGZjLmdyZWF0ZXIoZGVub21pbmF0b3IsIDApLCB0ZmMuZGl2KHRwLCBkZW5vbWluYXRvciksIDApLFxuICAgICAgICAnZmxvYXQzMicpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlY2FsbCh5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgcmV0dXJuIHRpZHkoKCkgPT4ge1xuICAgIGNvbnN0IHRwID0gdHJ1ZVBvc2l0aXZlcyh5VHJ1ZSwgeVByZWQpO1xuICAgIGNvbnN0IGZuID0gZmFsc2VOZWdhdGl2ZXMoeVRydWUsIHlQcmVkKTtcblxuICAgIGNvbnN0IGRlbm9taW5hdG9yID0gdGZjLmFkZCh0cCwgZm4pO1xuXG4gICAgcmV0dXJuIHRmYy5jYXN0KFxuICAgICAgICB0ZmMud2hlcmUodGZjLmdyZWF0ZXIoZGVub21pbmF0b3IsIDApLCB0ZmMuZGl2KHRwLCBkZW5vbWluYXRvciksIDApLFxuICAgICAgICAnZmxvYXQzMicpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJpbmFyeUNyb3NzZW50cm9weSh5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgcmV0dXJuIGxvc3NCaW5hcnlDcm9zc2VudHJvcHkoeVRydWUsIHlQcmVkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNwYXJzZUNhdGVnb3JpY2FsQWNjdXJhY3koXG4gICAgeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIGlmICh5VHJ1ZS5yYW5rID09PSB5UHJlZC5yYW5rKSB7XG4gICAgeVRydWUgPSB0ZmMuc3F1ZWV6ZSh5VHJ1ZSwgW3lUcnVlLnJhbmsgLSAxXSk7XG4gIH1cbiAgeVByZWQgPSB0ZmMuYXJnTWF4KHlQcmVkLCAtMSk7XG4gIGlmICh5UHJlZC5kdHlwZSAhPT0geVRydWUuZHR5cGUpIHtcbiAgICB5UHJlZCA9IHRmYy5jYXN0KHlQcmVkLCB5VHJ1ZS5kdHlwZSk7XG4gIH1cbiAgcmV0dXJuIHRmYy5jYXN0KHRmYy5lcXVhbCh5VHJ1ZSwgeVByZWQpLCAnZmxvYXQzMicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9wS0NhdGVnb3JpY2FsQWNjdXJhY3koeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHRocm93IG5ldyBOb3RJbXBsZW1lbnRlZEVycm9yKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzcGFyc2VUb3BLQ2F0ZWdvcmljYWxBY2N1cmFjeShcbiAgICB5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgdGhyb3cgbmV3IE5vdEltcGxlbWVudGVkRXJyb3IoKTtcbn1cblxuLy8gQWxpYXNlcy5cbmV4cG9ydCBjb25zdCBtc2UgPSBtZWFuU3F1YXJlZEVycm9yO1xuZXhwb3J0IGNvbnN0IE1TRSA9IG1lYW5TcXVhcmVkRXJyb3I7XG5leHBvcnQgY29uc3QgbWFlID0gbWVhbkFic29sdXRlRXJyb3I7XG5leHBvcnQgY29uc3QgTUFFID0gbWVhbkFic29sdXRlRXJyb3I7XG5leHBvcnQgY29uc3QgbWFwZSA9IG1lYW5BYnNvbHV0ZVBlcmNlbnRhZ2VFcnJvcjtcbmV4cG9ydCBjb25zdCBNQVBFID0gbWVhbkFic29sdXRlUGVyY2VudGFnZUVycm9yO1xuZXhwb3J0IGNvbnN0IGNhdGVnb3JpY2FsQ3Jvc3NlbnRyb3B5ID0gY2F0ZWdvcmljYWxDcm9zc2VudHJvcHlMb3NzO1xuZXhwb3J0IGNvbnN0IGNvc2luZSA9IGNvc2luZVByb3hpbWl0eTtcbmV4cG9ydCBjb25zdCBzcGFyc2VDYXRlZ29yaWNhbENyb3NzZW50cm9weSA9IHNwYXJzZUNhdGVnb3JpY2FsQ3Jvc3NlbnRyb3B5TG9zcztcblxuLy8gVE9ETyhjYWlzLCBuaWVsc2VuZSk6IEFkZCBzZXJpYWxpemUoKS5cblxuZXhwb3J0IGNvbnN0IG1ldHJpY3NNYXA6IHtbZnVuY3Rpb25OYW1lOiBzdHJpbmddOiBMb3NzT3JNZXRyaWNGbn0gPSB7XG4gIGJpbmFyeUFjY3VyYWN5LFxuICBjYXRlZ29yaWNhbEFjY3VyYWN5LFxuICBwcmVjaXNpb24sXG4gIGNhdGVnb3JpY2FsQ3Jvc3NlbnRyb3B5LFxuICBzcGFyc2VDYXRlZ29yaWNhbENyb3NzZW50cm9weSxcbiAgbXNlLFxuICBNU0UsXG4gIG1hZSxcbiAgTUFFLFxuICBtYXBlLFxuICBNQVBFLFxuICBjb3NpbmVcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXQoaWRlbnRpZmllcjogc3RyaW5nfExvc3NPck1ldHJpY0ZuKTogTG9zc09yTWV0cmljRm4ge1xuICBpZiAodHlwZW9mIGlkZW50aWZpZXIgPT09ICdzdHJpbmcnICYmIGlkZW50aWZpZXIgaW4gbWV0cmljc01hcCkge1xuICAgIHJldHVybiBtZXRyaWNzTWFwW2lkZW50aWZpZXJdO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBpZGVudGlmaWVyICE9PSAnc3RyaW5nJyAmJiBpZGVudGlmaWVyICE9IG51bGwpIHtcbiAgICByZXR1cm4gaWRlbnRpZmllcjtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgVmFsdWVFcnJvcihgVW5rbm93biBtZXRyaWMgJHtpZGVudGlmaWVyfWApO1xuICB9XG59XG5cbi8qKlxuICogR2V0IHRoZSBzaG9ydGN1dCBmdW5jdGlvbiBuYW1lLlxuICpcbiAqIElmIHRoZSBmbiBuYW1lIGlzIGEgc3RyaW5nLFxuICogICBkaXJlY3RseSByZXR1cm4gdGhlIHN0cmluZyBuYW1lLlxuICogSWYgdGhlIGZ1bmN0aW9uIGlzIGluY2x1ZGVkIGluIG1ldHJpY3NNYXAgb3IgbG9zc2VzTWFwLFxuICogICByZXR1cm4ga2V5IG9mIHRoZSBtYXAuXG4gKiAgIC0gSWYgdGhlIGZ1bmN0aW9uIHJlbGF0aXZlIHRvIG11bHRpcGxlIGtleXMsXG4gKiAgICAgcmV0dXJuIHRoZSBmaXJzdCBmb3VuZCBrZXkgYXMgdGhlIGZ1bmN0aW9uIG5hbWUuXG4gKiAgIC0gSWYgdGhlIGZ1bmN0aW9uIGV4aXN0cyBpbiBib3RoIGxvc3Nlc01hcCBhbmQgbWV0cmljc01hcCxcbiAqICAgICBzZWFyY2ggbG9zc2VzTWFwIGZpcnN0LlxuICogSWYgdGhlIGZ1bmN0aW9uIGlzIG5vdCBpbmNsdWRlZCBpbiBtZXRyaWNzTWFwIG9yIGxvc3Nlc01hcCxcbiAqICAgcmV0dXJuIHRoZSBmdW5jdGlvbiBuYW1lLlxuICpcbiAqIEBwYXJhbSBmbiBsb3NzIGZ1bmN0aW9uLCBtZXRyaWMgZnVuY3Rpb24sIG9yIHNob3J0IGN1dCBuYW1lLlxuICogQHJldHVybnMgTG9zcyBvciBNZXRyaWMgbmFtZSBpbiBzdHJpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb3NzT3JNZXRyaWNOYW1lKGZuOiBzdHJpbmd8TG9zc09yTWV0cmljRm4pOiBzdHJpbmcge1xuICB1dGlsLmFzc2VydChmbiAhPT0gbnVsbCwgYFVua25vd24gTG9zc09yTWV0cmljRm4gJHtmbn1gKTtcbiAgaWYgKHR5cGVvZiBmbiA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZm47XG4gIH0gZWxzZSB7XG4gICAgbGV0IGZuTmFtZTtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhsb3NzZXNNYXApKSB7XG4gICAgICBpZiAobG9zc2VzTWFwW2tleV0gPT09IGZuKSB7XG4gICAgICAgIGZuTmFtZSA9IGtleTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChmbk5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGZuTmFtZTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMobWV0cmljc01hcCkpIHtcbiAgICAgIGlmIChtZXRyaWNzTWFwW2tleV0gPT09IGZuKSB7XG4gICAgICAgIGZuTmFtZSA9IGtleTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChmbk5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGZuTmFtZTtcbiAgICB9XG4gICAgcmV0dXJuIChmbiBhcyBGdW5jdGlvbikubmFtZTtcbiAgfVxufVxuIl19