export class UtilityConsideration {
    name;
    curve;
    weight;
    threshold;
    slope;
    input;
    constructor(options) {
        this.name = options.name;
        this.input = options.input;
        this.curve = options.curve ?? "linear";
        this.weight = options.weight ?? 1;
        this.threshold = options.threshold ?? 0.5;
        this.slope = options.slope ?? 10;
    }
    evaluate(context) {
        const raw = this.input(context);
        const value = typeof raw === "boolean" ? (raw ? 1 : 0) : clamp01(raw);
        return round3(clamp01(applyCurve(value, this.curve, this.threshold, this.slope) * this.weight));
    }
}
export class UtilityAction {
    name;
    considerations;
    scoring;
    baseScore;
    enabled;
    constructor(options) {
        this.name = options.name;
        this.considerations = options.considerations;
        this.scoring = options.scoring ?? "multiply";
        this.baseScore = options.baseScore ?? 0;
        this.enabled = options.enabled ?? true;
    }
    score(context) {
        const considerationScores = Object.fromEntries(this.considerations.map((consideration) => [consideration.name, consideration.evaluate(context)]));
        const values = Object.values(considerationScores);
        const combined = values.length === 0 ? 0 : combineScores(values, this.scoring);
        return {
            action: this.name,
            score: round3(clamp01(combined + this.baseScore)),
            considerationScores
        };
    }
}
export class UtilityAI {
    actions = [];
    addAction(action) {
        if (this.actions.some((entry) => entry.name === action.name)) {
            throw new Error(`Utility action already registered: ${action.name}`);
        }
        this.actions.push(action);
    }
    removeAction(name) {
        const index = this.actions.findIndex((action) => action.name === name);
        if (index < 0)
            return false;
        this.actions.splice(index, 1);
        return true;
    }
    setActionEnabled(name, enabled) {
        const action = this.actions.find((entry) => entry.name === name);
        if (!action)
            throw new Error(`Utility action is not registered: ${name}`);
        action.enabled = enabled;
    }
    evaluate(context) {
        return this.actions
            .filter((action) => action.enabled)
            .map((action) => action.score(context))
            .sort((left, right) => right.score - left.score || left.action.localeCompare(right.action));
    }
    select(context) {
        return this.evaluate(context)[0];
    }
}
function combineScores(values, scoring) {
    switch (scoring) {
        case "average":
            return values.reduce((sum, value) => sum + value, 0) / values.length;
        case "min":
            return Math.min(...values);
        case "max":
            return Math.max(...values);
        case "sum":
            return Math.min(1, values.reduce((sum, value) => sum + value, 0));
        case "multiply":
            return values.reduce((product, value) => product * value, 1);
    }
}
function applyCurve(value, curve, threshold, slope) {
    switch (curve) {
        case "inverse":
            return 1 - value;
        case "quadratic":
            return value * value;
        case "cubic":
            return value * value * value;
        case "boolean":
            return value >= threshold ? 1 : 0;
        case "logistic":
            return 1 / (1 + Math.exp(-slope * (value - threshold)));
        case "linear":
            return value;
    }
}
function clamp01(value) {
    return Math.max(0, Math.min(1, Number.isFinite(value) ? value : 0));
}
function round3(value) {
    return Number(value.toFixed(3));
}
//# sourceMappingURL=UtilityAI.js.map