<commit_before>class Flag {
    constructor(
        public aliases: string[],
        public value: any,
        public required = false
    ) {}
}

/**
 * Configuration object used to parse and assign command line arguments
 */
export class Configuration {
    flags: any = {
        noWatch: new Flag(['--no-watch'], false),
        noServe: new Flag(['--no-serve'], false),
        checkErrors: new Flag(['--check-errors'], false),
        randomScenario: new Flag(['--random-scenario'], false),
        sourceRoot: new Flag(['--src', '-S'], './src', true),
        config: new Flag(['--config', '-C'], 'angular-playground.json'),
        timeout: new Flag(['--timeout'], 90),
        angularCli: {
            appName: new Flag(['--ng-cli-app'], 'playground'),
            environment: new Flag(['--ng-cli-env'], null),
            port: new Flag(['--ng-cli-port'], 4201),
            cmdPath: new Flag(['--ng-cli-cmd'], 'node_modules/@angular/cli/bin/ng')
        }
    };

    // Used to tailor the version of headless chromium ran by puppeteer
    chromeArguments = [ '--disable-gpu', '--no-sandbox' ];

    constructor(rawArgv: string[]) {
        // Apply command line arguments
        rawArgv.forEach((argv, i) => {
            const matchingFlag = this.findFlag(argv, this.flags);
            if (!matchingFlag) return;

            if (typeof matchingFlag.value === 'boolean') {
                matchingFlag.value = true;
            } else {
                matchingFlag.value = rawArgv[i + 1];
            }
        });
    }

    /**
     * Override flags and switches with angular playground configuration JSON file
     * @param playgroundConfig
     */
    applyConfigurationFile(playgroundConfig: any) {
        Object.keys(playgroundConfig).forEach(key => {
            if (this.instanceOfFlagGroup(this.flags[key])) {
                Object.keys(playgroundConfig[key]).forEach(nestedKey => {
                    if (this.flags[key].hasOwnProperty(nestedKey)) {
                        this.flags[key][nestedKey].value = playgroundConfig[key][nestedKey];
                    }
                });
            } else {
                if (this.flags.hasOwnProperty(key)) {
                    this.flags[key].value = playgroundConfig[key];
                }
            }
        });
    }<commit_msg>refactor applyConfig to use recursion<commit_after>class Flag {
    constructor(
        public aliases: string[],
        public value: any,
        public required = false
    ) {}
}

/**
 * Configuration object used to parse and assign command line arguments
 */
export class Configuration {
    flags: any = {
        noWatch: new Flag(['--no-watch'], false),
        noServe: new Flag(['--no-serve'], false),
        checkErrors: new Flag(['--check-errors'], false),
        randomScenario: new Flag(['--random-scenario'], false),
        sourceRoot: new Flag(['--src', '-S'], './src', true),
        config: new Flag(['--config', '-C'], 'angular-playground.json'),
        timeout: new Flag(['--timeout'], 90),
        angularCli: {
            appName: new Flag(['--ng-cli-app'], 'playground'),
            environment: new Flag(['--ng-cli-env'], null),
            port: new Flag(['--ng-cli-port'], 4201),
            cmdPath: new Flag(['--ng-cli-cmd'], 'node_modules/@angular/cli/bin/ng')
        }
    };

    // Used to tailor the version of headless chromium ran by puppeteer
    chromeArguments = [ '--disable-gpu', '--no-sandbox' ];

    constructor(rawArgv: string[]) {
        // Apply command line arguments
        rawArgv.forEach((argv, i) => {
            const matchingFlag = this.findFlag(argv, this.flags);
            if (!matchingFlag) return;

            if (typeof matchingFlag.value === 'boolean') {
                matchingFlag.value = true;
            } else {
                matchingFlag.value = rawArgv[i + 1];
            }
        });
    }

    /**
     * Override flags and switches with angular playground configuration JSON file
     * @param playgroundConfig
     */
    applyConfigurationFile(playgroundConfig: any) {
        const applyToFlags = (config: any, flagGroup: any) => {
            Object.keys(config).forEach(key => {
                if (!flagGroup.hasOwnProperty(key)) return;
                const flag = flagGroup[key];

                if (this.instanceOfFlagGroup(flag)) {
                    applyToFlags(config[key], flag);
                }

                flag.value = config[key];
            });
        };

        applyToFlags(playgroundConfig, this.flags);
    }
{'fraction_non_alphanumeric': 0.14753018660812295, 'fraction_numerical': 0.0030735455543358945, 'mean_word_length': 1.9412524209167206, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '5978876', 'n_tokens_mistral': 1260, 'n_tokens_neox': 1199, 'n_words': 294}