<commit_before>import { Class, getInstanceClass, permutateEntries } from "../../utils";

import { OrCombinedValueCriteria } from "./or-combined-value-criteria";
import { ValueCriteria } from "./value-criteria";
import { ValueCriterion } from "./value-criterion";

type RemapTemplate<T> = {
    [K in keyof T]?: Exclude<T[K], undefined> extends boolean | number | string | null ? Class<ValueCriterion<T[K]>> | Class<ValueCriterion<T[K]>>[] : never;
};

type InstantiatedTemplate<T> = {
    [K in keyof T]?: T[K] extends Class<ValueCriterion>[] ? InstanceType<T[K][number]>[] : T[K] extends Class<ValueCriterion> ? InstanceType<T[K]> : never;
};

export class EntityCriterion<T = unknown> extends ValueCriterion<T> {
    constructor(items: Partial<Record<keyof T, ValueCriterion>>) {
        super();
        this.bag = items;
    }

    readonly bag: Partial<Record<keyof T, ValueCriterion>>;

    getBag(): Partial<Record<keyof T, ValueCriterion>> {
        return this.bag;
    }

    // [todo] need to recursively get entries from nested ObjectCriterions
    getEntries(): [string, ValueCriterion[]][] {
        const entries: [string, ValueCriterion[]][] = [];
        const bag = this.getBag();

        for (const key in bag) {
            const valueCriteria = bag[key];
            if (valueCriteria === void 0 || !(valueCriteria instanceof ValueCriteria)) {
                continue;
            }

            entries.push([key, valueCriteria.getItems()]);
        }

        return entries;
    }

    remap<U extends RemapTemplate<T>>(handler: () => U): InstantiatedTemplate<U>[] {
        const entries = this.getEntries();
        const permutationEntries: [string, any[]][] = [];
        const template = handler();

        for (const key in template) {
            const entry = entries.find(([entryKey]) => entryKey === key);
            if (!entry) continue;

            const stuffInTemplate = template[key];
            const allowedTypes = Array.isArray(stuffInTemplate) ? stuffInTemplate : ([stuffInTemplate] as any[]);
            const filteredByType = entry[1].filter(item => allowedTypes.includes(getInstanceClass(item)));

            if (Array.isArray(stuffInTemplate)) {
                permutationEntries.push([key, [filteredByType]]);
            } else {<commit_msg>fix(criteria): #75 entity-criterion remap() works again (kinda)<commit_after>import { Class, getInstanceClass, permutateEntries } from "../../utils";

import { OrCombinedValueCriteria } from "./or-combined-value-criteria";
import { ValueCriteria } from "./value-criteria";
import { ValueCriterion } from "./value-criterion";

type RemapTemplate<T> = {
    [K in keyof T]?: Exclude<T[K], undefined> extends boolean | number | string | null ? Class<ValueCriterion<T[K]>> | Class<ValueCriterion<T[K]>>[] : never;
};

type InstantiatedTemplate<T> = {
    [K in keyof T]?: T[K] extends Class<ValueCriterion>[] ? InstanceType<T[K][number]>[] : T[K] extends Class<ValueCriterion> ? InstanceType<T[K]> : never;
};

export class EntityCriterion<T = unknown> extends ValueCriterion<T> {
    constructor(items: Partial<Record<keyof T, ValueCriterion>>) {
        super();
        this.bag = items;
    }

    readonly bag: Partial<Record<keyof T, ValueCriterion>>;

    getBag(): Partial<Record<keyof T, ValueCriterion>> {
        return this.bag;
    }

    // [todo] need to recursively get entries from nested ObjectCriterions
    getEntries(): [string, ValueCriterion[]][] {
        const entries: [string, ValueCriterion[]][] = [];
        const bag = this.getBag();

        for (const key in bag) {
            const valueCriteria = bag[key];
            if (valueCriteria === void 0) {
                continue;
            } else if (valueCriteria instanceof OrCombinedValueCriteria) {
                entries.push([key, valueCriteria.getItems()]);
            } else {
                entries.push([key, [valueCriteria]]);
            }
        }

        return entries;
    }

    remap<U extends RemapTemplate<T>>(handler: () => U): InstantiatedTemplate<U>[] {
        const entries = this.getEntries();
        const permutationEntries: [string, any[]][] = [];
        const template = handler();

        for (const key in template) {
            const entry = entries.find(([entryKey]) => entryKey === key);
            if (!entry) continue;

            const stuffInTemplate = template[key];
            const allowedTypes = Array.isArray(stuffInTemplate) ? stuffInTemplate : ([stuffInTemplate] as any[]);
            const filteredByType = entry[1].filter(item => allowedTypes.includes(getInstanceClass(item)));

            if (Array.isArray(stuffInTemplate)) {
                permutationEntries.push([key, [filteredByType]]);
            } else {
{'fraction_non_alphanumeric': 0.1419259882253995, 'fraction_numerical': 0.001261564339781329, 'mean_word_length': 2.9575707154742097, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7052217', 'n_tokens_mistral': 1351, 'n_tokens_neox': 1334, 'n_words': 329}