<commit_before>const Core = require('./core');

const stringKeys = new Set([
    'website',
    'gametype',
    'gamemode',
    'player'
]);

function normalizeEntry([key,value]) {
    key = key.toLowerCase();
    const split = key.split('_');
    let keyType;
    if (split.length === 2 && !isNaN(parseInt(split[1]))) {
        keyType = split[0];
    } else {
        keyType = key;
    }
    if (!stringKeys.has(keyType) && !keyType.includes('name')) {
        if (value.toLowerCase() === 'true') {
            value = true;
        } else if (value.toLowerCase() === 'false') {
            value = false;
        } else if (!isNaN(parseInt(value))) {
            value = parseInt(value);
        }
    }
    return [key,value];
}

class Gamespy1 extends Core {
    constructor() {
        super();
        this.encoding = 'latin1';
        this.byteorder = 'be';
    }

    async run(state) {
        const raw = await this.sendPacket('\\status\\xserverquery');
        // Convert all keys to lowercase and normalize value types
        const data = Object.fromEntries(Object.entries(raw).map(entry => normalizeEntry(entry)));
        state.raw = data;
        if ('hostname' in data) state.name = data.hostname;
        if ('mapname' in data) state.map = data.mapname;
        if (this.trueTest(data.password)) state.password = <PASSWORD>;
        if ('maxplayers' in data) state.maxplayers = parseInt(data.maxplayers);
        if ('hostport' in data) state.gamePort = parseInt(data.hostport);

        const teamOffByOne = data.gameid === 'bf1942';
        const playersById = {};
        const teamNamesById = {};
        for (const ident of Object.keys(data)) {
            const split = ident.split('_');
            if (split.length !== 2) continue;
            let key = split[0].toLowerCase();
            const id = parseInt(split[1]);
            if (isNaN(id)) continue;
            let value = data[ident];

            delete data[ident];

            if (key !== 'team' && key.startsWith('team')) {
                // Info about a team
                if (key === 'teamname') {
                    teamNamesById[id] = value;
                } else {
                    // other team info which we don't track
                }
            } else {
                // Info about a player
                if (!(id in playersById)) playersById[id] = {};
                if (key === 'playername' || key === 'player') {<commit_msg>Fix teamOffByOne condition for Battlefield 1942<commit_after>const Core = require('./core');

const stringKeys = new Set([
    'website',
    'gametype',
    'gamemode',
    'player'
]);

function normalizeEntry([key,value]) {
    key = key.toLowerCase();
    const split = key.split('_');
    let keyType;
    if (split.length === 2 && !isNaN(parseInt(split[1]))) {
        keyType = split[0];
    } else {
        keyType = key;
    }
    if (!stringKeys.has(keyType) && !keyType.includes('name')) {
        if (value.toLowerCase() === 'true') {
            value = true;
        } else if (value.toLowerCase() === 'false') {
            value = false;
        } else if (!isNaN(parseInt(value))) {
            value = parseInt(value);
        }
    }
    return [key,value];
}

class Gamespy1 extends Core {
    constructor() {
        super();
        this.encoding = 'latin1';
        this.byteorder = 'be';
    }

    async run(state) {
        const raw = await this.sendPacket('\\status\\xserverquery');
        // Convert all keys to lowercase and normalize value types
        const data = Object.fromEntries(Object.entries(raw).map(entry => normalizeEntry(entry)));
        state.raw = data;
        if ('hostname' in data) state.name = data.hostname;
        if ('mapname' in data) state.map = data.mapname;
        if (this.trueTest(data.password)) state.password = true;
        if ('maxplayers' in data) state.maxplayers = parseInt(data.maxplayers);
        if ('hostport' in data) state.gamePort = parseInt(data.hostport);

        const teamOffByOne = data.gamename === 'bfield1942';
        const playersById = {};
        const teamNamesById = {};
        for (const ident of Object.keys(data)) {
            const split = ident.split('_');
            if (split.length !== 2) continue;
            let key = split[0].toLowerCase();
            const id = parseInt(split[1]);
            if (isNaN(id)) continue;
            let value = data[ident];

            delete data[ident];

            if (key !== 'team' && key.startsWith('team')) {
                // Info about a team
                if (key === 'teamname') {
                    teamNamesById[id] = value;
                } else {
                    // other team info which we don't track
                }
            } else {
                // Info about a player
                if (!(id in playersById)) playersById[id] = {};
                if (key === 'playername' || key === 'player') {
{'fraction_non_alphanumeric': 0.1454102355808286, 'fraction_numerical': 0.005686433793663688, 'mean_word_length': 1.910756501182033, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 6, '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': '3703640', 'n_tokens_mistral': 1422, 'n_tokens_neox': 1403, 'n_words': 363}