<commit_before>var Flatpickr = require('flatpickr');
require('flatpickr/dist/l10n');

var L = require('leaflet');
require('leaflet-contextmenu');
require('leaflet-loading');
require('leaflet.heightgraph');
var moment = require('moment');
require('./lib/leaflet_numbered_markers.js');

global.jQuery = require('jquery');
global.$ = global.jQuery;
require('./lib/jquery-ui-custom-1.12.0.min.js');
require('./lib/jquery.history.js');
require('./lib/jquery.autocomplete.js');

var ghenv = require("./config/options.js").options;
console.log(ghenv.environment);

var GHInput = require('./graphhopper/GHInput.js');
var GHRequest = require('./graphhopper/GHRequest.js');
var host = ghenv.routing.host;
if (!host) {
    if (location.port === '') {
        host = location.protocol + '//' + location.hostname;
    } else {
        host = location.protocol + '//' + location.hostname + ":" + location.port;
    }
}

var AutoComplete = require('./autocomplete.js');
if (ghenv.environment === 'development') {
    var autocomplete = AutoComplete.prototype.createStub();
} else {
    var autocomplete = new AutoComplete(ghenv.geocoding.host, ghenv.geocoding.api_key);
}

var mapLayer = require('./map.js');
var nominatim = require('./nominatim.js');
var routeManipulation = require('./routeManipulation.js');
var gpxExport = require('./gpxexport.js');
var messages = require('./messages.js');
var translate = require('./translate.js');
var customModelEditor = require('custom-model-editor/dist/index.js');

var format = require('./tools/format.js');
var urlTools = require('./tools/url.js');
var tileLayers = require('./config/tileLayers.js');
if(ghenv.with_tiles)
   tileLayers.enableVectorTiles();

var debug = false;
var ghRequest = new GHRequest(host, ghenv.routing.api_key);
var bounds = {};
var metaVersionInfo;

// usage: log('inside coolFunc',this,arguments);
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
if (global.window) {
    window.log = function () {
        log.history = log.history || [];   // store logs to an array for reference
        log.history.push(arguments);
        if (this.console && debug) {
            console.log(Array.prototype.slice.call(arguments));
        }
    };
}

$(document).ready(function (e) {
    // fixing cross domain support e.g in Opera
    jQuery.support.cors = true;

    gpxExport.addGpxExport(ghRequest);
    // we start without encoded values, they will be loaded later
    var cmEditor = customModelEditor.create({}, function (element) {
        $("#custom-model-editor").append(element);
    });

    cmEditor.validListener = function(valid) {
        $("#custom-model-search-button").prop('disabled', !valid);
    };
    ghRequest.cmEditor = cmEditor;
    ghRequest.cmEditorActive = false;
    var toggleCustomModelBox = function(sendRoute) {
        $("#custom-model-box").toggle();
        ghRequest.cmEditorActive = !ghRequest.cmEditorActive;
        // avoid default action, so use a different search button
        $("#searchButton").toggle();
        mapLayer.adjustMapSize();
        cmEditor.cm.refresh();
        cmEditor.cm.focus();
        cmEditor.cm.setCursor(cmEditor.cm.lineCount());
        if (sendRoute)
            sendCustomData();
    };
    $("#custom-model-button").click(function() {
        toggleCustomModelBox(true);
    });
    function showCustomModelExample() {
        cmEditor.value =
            "{"
            + "\n \"speed\": ["
            + "\n  {"
            + "\n   \"if\": \"road_class == MOTORWAY\","
            + "\n   \"multiply_by\": 0.8"
            + "\n  }"
            + "\n ],"
            + "\n \"priority\": ["
            + "\n  {"
            + "\n   \"if\": \"road_environment == TUNNEL\","
            + "\n   \"multiply_by\": 0.0"
            + "\n  },"
            + "\n  {"
            + "\n   \"if\": \"max_weight < 3\","
            + "\n   \"multiply_by\": 0.0"
            + "\n  }"
            + "\n ]"
            + "\n}";
        cmEditor.cm.focus();
        cmEditor.cm.setCursor(0);
        cmEditor.cm.execCommand('selectAll');
        cmEditor.cm.refresh();
    }
    $("#custom-model-example").click(function () {
        showCustomModelExample();
        return false;
    });

    $("#export-link").click(function (e) {
        try {
          e.preventDefault();
          var url = location.href;
          if(url.indexOf("?") > 0)
            url = url.substring(0, url.indexOf("?")) + ghRequest.createHistoryURL() + "&layer=" + encodeURIComponent(tileLayers.activeLayerName);
          if(ghRequest.cmEditorActive) {
            var text = cmEditor.value.replaceAll("&","%26");
            url += "&custom_model=" + new URLSearchParams(JSON.stringify(JSON.parse(text))).toString();
          }
          navigator.clipboard.writeText(url).then(() => { alert('Link copied to clipboard'); });
        } catch(e) { console.warn(e); }
    });

    var sendCustomData = function () {
        ghRequest.ignoreCustomErrors = false;
        mySubmit();
    };

    var sendCustomDataIgnoreErrors = function () {
        ghRequest.ignoreCustomErrors = true;
        mySubmit();
    }

    cmEditor.setExtraKey('Ctrl-Enter', sendCustomDataIgnoreErrors);
    $("#custom-model-search-button").click(sendCustomData);

    if (isProduction())
        $('#hosting').show();

    var History = window.History;
    if (History.enabled) {
        History.Adapter.bind(window, 'statechange', function () {
            // No need for workaround?
            // Chrome and Safari always emit a popstate event on page load, but Firefox doesn’t
            // https://github.com/defunkt/jquery-pjax/issues/143#issuecomment-6194330

            var state = History.getState();
            initFromParams(state.data, true);
        });
    }

    $('#locationform').submit(function (e) {
        // no page reload
        e.preventDefault();
        mySubmit();
    });

    var urlParams = urlTools.parseUrlWithHisto();

    var customModelJSON = urlParams.custom_model;
    if(customModelJSON) {
        toggleCustomModelBox(false);
        cmEditor.value = customModelJSON; // if json parsing fails we still have the partial custom model in the box
        try {
            var tmpObj = JSON.parse(customModelJSON);
            cmEditor.value = JSON.stringify(tmpObj, null, 2);
        } catch(e) {
            console.warn('cannot pretty print custom model: ' + e);
        }

    } else {
        // todo: the idea was to highlight everything so if we start typing the example is overwritten. But unfortunately
        // this does not work. And not even sure this is so useful?
        showCustomModelExample();
    }

    $.when(ghRequest.fetchTranslationMap(urlParams.locale), ghRequest.getInfo())
            .then(function (arg1, arg2) {
                // init translation retrieved from first call (fetchTranslationMap)
                var translations = arg1[0];
                autocomplete.setLocale(translations.locale);
                ghRequest.setLocale(translations.locale);
                translate.init(translations);

                // init bounding box from getInfo result
                var json = arg2[0];
                var tmp = json.bbox;
                bounds.initialized = true;
                bounds.minLon = tmp[0];
                bounds.minLat = tmp[1];
                bounds.maxLon = tmp[2];
                bounds.maxLat = tmp[3];
                nominatim.setBounds(bounds);
                var profilesDiv = $("#profiles");

                function createButton(profile, hide) {
                    var vehicle = profile.vehicle;
                    var profileName = profile.name;
                    var button = $("<button class='vehicle-btn' title='" + profileDisplayName(profileName) + "'/>");
                    if (hide)
                        button.hide();

                    button.attr('id', profileName);
                    button.html("<img src='img/" + vehicle.toLowerCase() + ".png' alt='" + profileDisplayName(profileName) + "'></img>");
                    button.click(function () {
                        ghRequest.setProfile(profileName);
                        ghRequest.removeLegacyParameters();
                        resolveAll();
                        if (ghRequest.route.isResolved())
                          routeLatLng(ghRequest);
                    });
                    return button;
                }

                if (json.profiles) {
                    var profiles = json.profiles;
                    // first sort alphabetically to maintain a consistent order, then move certain elements to front/back
                    profiles.sort(function (a, b) {
                         return a.vehicle < b.vehicle ? -1 : a.vehicle > b.vehicle ? 1 : 0;
                    });
                    // the desired order is car,foot,bike,<others>,motorcycle
                    var firstVehicles = ["car", "foot", "bike"];
                    for (var i=firstVehicles.length-1; i>=0; --i) {
                        profiles = moveToFront(profiles, function(p) { return p.vehicle === firstVehicles[i]; });
                    }
                    var lastVehicles = ["mtb", "motorcycle"];
                    for (var i=0; i<lastVehicles.length; ++i) {
                        profiles = moveToFront(profiles, function(p) { return p.vehicle !== lastVehicles[i]; });
                    }
                    ghRequest.profiles = profiles;
                    ghRequest.setElevation(json.elevation);

                    // only show all profiles if the url already specifies an existing profile that is not amongst the 'firstVehicles'
                    var urlProfile = profiles.find(function (profile) { return urlParams.profile && profile.name === urlParams.profile; });
                    var showAllProfiles = urlProfile && firstVehicles.indexOf(urlProfile.vehicle) >= 0;
                    if (profiles.length > 0)
                        ghRequest.setProfile(profiles[0].name);

                    var numVehiclesWhenCollapsed = 3;
                    var hiddenVehicles = [];
                    for (var i = 0; i < profiles.length; ++i) {
                        var btn = createButton(profiles[i], !showAllProfiles && i >= numVehiclesWhenCollapsed);
                        profilesDiv.append(btn);
                        if (i >= numVehiclesWhenCollapsed)
                            hiddenVehicles.push(btn);
                    }

                    if (!showAllProfiles && profiles.length > numVehiclesWhenCollapsed) {
                        var moreBtn = $("<a id='more-vehicle-btn'> ...</a>").click(function () {
                            moreBtn.hide();
                            for (var i in hiddenVehicles) {
                                hiddenVehicles[i].show();
                            }
                        });
                        profilesDiv.append($("<a class='vehicle-info-link' href='https://docs.graphhopper.com/#section/Map-Data-and-Routing-Profiles/OpenStreetMap'>?</a>"));
                        profilesDiv.append(moreBtn);
                    }
                }
                $("button#" + profiles[0].name).addClass("selectprofile");

                metaVersionInfo = messages.extractMetaVersionInfo(json);
                // a very simplistic helper system that shows the possible entries and encoded values
                if(json.encoded_values) {
                    const categories = {};
                    Object.keys(json.encoded_values).forEach((k) => {
                        const v = json.encoded_values[k];
                        if (v.length == 2 && v[0] === 'true' && v[1] === 'false') {
                            categories[k] = {type: 'boolean'};
                        } else if (v.length === 2 && v[0] === '>number' && v[1] === '<number') {
                            categories[k] = {type: 'numeric'};
                        } else {
                            categories[k] = {type: 'enum', values: v.sort()};
                        }
                    });
                    cmEditor.categories = categories;
                }

                mapLayer.initMap(bounds, setStartCoord, setIntermediateCoord, setEndCoord, urlParams.layer, urlParams.use_miles);

                // execute query
                initFromParams(urlParams, true);

                checkInput();
            }, function (err) {
                console.log(err);
                $('#error').html('GraphHopper API offline? <a href="http://graphhopper.com/maps/">Refresh</a>' + '<br/>Status: ' + err.statusText + '<br/>' + host);

                bounds = {
                    "minLon": -180,
                    "minLat": -90,
                    "maxLon": 180,
                    "maxLat": 90
                };
                nominatim.setBounds(bounds);
                mapLayer.initMap(bounds, setStartCoord, setIntermediateCoord, setEndCoord, urlParams.layer, urlParams.use_miles);
            });

    var language_code = urlParams.locale && urlParams.locale.split('-', 1)[0];
    if (language_code != 'en') {
        // A few language codes are different in GraphHopper and Flatpickr.
        var flatpickr_locale;
        switch (language_code) {
            case 'ca':  // Catalan
                flatpickr_locale = 'cat';
                break;
            case 'el':  // Greek
                flatpickr_locale = 'gr';
                break;
            default:
                flatpickr_locale = language_code;
        }
        if (Flatpickr.l10ns.hasOwnProperty(flatpickr_locale)) {<commit_msg>Minor improvement to avoid changing the url (#2428)<commit_after>var Flatpickr = require('flatpickr');
require('flatpickr/dist/l10n');

var L = require('leaflet');
require('leaflet-contextmenu');
require('leaflet-loading');
require('leaflet.heightgraph');
var moment = require('moment');
require('./lib/leaflet_numbered_markers.js');

global.jQuery = require('jquery');
global.$ = global.jQuery;
require('./lib/jquery-ui-custom-1.12.0.min.js');
require('./lib/jquery.history.js');
require('./lib/jquery.autocomplete.js');

var ghenv = require("./config/options.js").options;
console.log(ghenv.environment);

var GHInput = require('./graphhopper/GHInput.js');
var GHRequest = require('./graphhopper/GHRequest.js');
var host = ghenv.routing.host;
if (!host) {
    if (location.port === '') {
        host = location.protocol + '//' + location.hostname;
    } else {
        host = location.protocol + '//' + location.hostname + ":" + location.port;
    }
}

var AutoComplete = require('./autocomplete.js');
if (ghenv.environment === 'development') {
    var autocomplete = AutoComplete.prototype.createStub();
} else {
    var autocomplete = new AutoComplete(ghenv.geocoding.host, ghenv.geocoding.api_key);
}

var mapLayer = require('./map.js');
var nominatim = require('./nominatim.js');
var routeManipulation = require('./routeManipulation.js');
var gpxExport = require('./gpxexport.js');
var messages = require('./messages.js');
var translate = require('./translate.js');
var customModelEditor = require('custom-model-editor/dist/index.js');

var format = require('./tools/format.js');
var urlTools = require('./tools/url.js');
var tileLayers = require('./config/tileLayers.js');
if(ghenv.with_tiles)
   tileLayers.enableVectorTiles();

var debug = false;
var ghRequest = new GHRequest(host, ghenv.routing.api_key);
var bounds = {};
var metaVersionInfo;

// usage: log('inside coolFunc',this,arguments);
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
if (global.window) {
    window.log = function () {
        log.history = log.history || [];   // store logs to an array for reference
        log.history.push(arguments);
        if (this.console && debug) {
            console.log(Array.prototype.slice.call(arguments));
        }
    };
}

$(document).ready(function (e) {
    // fixing cross domain support e.g in Opera
    jQuery.support.cors = true;

    gpxExport.addGpxExport(ghRequest);
    // we start without encoded values, they will be loaded later
    var cmEditor = customModelEditor.create({}, function (element) {
        $("#custom-model-editor").append(element);
    });

    cmEditor.validListener = function(valid) {
        $("#custom-model-search-button").prop('disabled', !valid);
    };
    ghRequest.cmEditor = cmEditor;
    ghRequest.cmEditorActive = false;
    var toggleCustomModelBox = function(sendRoute) {
        $("#custom-model-box").toggle();
        ghRequest.cmEditorActive = !ghRequest.cmEditorActive;
        // avoid default action, so use a different search button
        $("#searchButton").toggle();
        mapLayer.adjustMapSize();
        cmEditor.cm.refresh();
        cmEditor.cm.focus();
        cmEditor.cm.setCursor(cmEditor.cm.lineCount());
        if (sendRoute)
            sendCustomData();
    };
    $("#custom-model-button").click(function() {
        toggleCustomModelBox(true);
    });
    function showCustomModelExample() {
        cmEditor.value =
            "{"
            + "\n \"speed\": ["
            + "\n  {"
            + "\n   \"if\": \"road_class == MOTORWAY\","
            + "\n   \"multiply_by\": 0.8"
            + "\n  }"
            + "\n ],"
            + "\n \"priority\": ["
            + "\n  {"
            + "\n   \"if\": \"road_environment == TUNNEL\","
            + "\n   \"multiply_by\": 0.0"
            + "\n  },"
            + "\n  {"
            + "\n   \"if\": \"max_weight < 3\","
            + "\n   \"multiply_by\": 0.0"
            + "\n  }"
            + "\n ]"
            + "\n}";
        cmEditor.cm.focus();
        cmEditor.cm.setCursor(0);
        cmEditor.cm.execCommand('selectAll');
        cmEditor.cm.refresh();
    }
    $("#custom-model-example").click(function () {
        showCustomModelExample();
        return false;
    });

    $("#export-link").click(function (e) {
        try {
          e.preventDefault();
          var url = location.href;
          if(url.indexOf("?") > 0)
            url = url.substring(0, url.indexOf("?")) + ghRequest.createHistoryURL() + "&layer=" + encodeURIComponent(tileLayers.activeLayerName);
          if(ghRequest.cmEditorActive) {
            var text = cmEditor.value.replaceAll("&","%26");
            url += "&custom_model=" + new URLSearchParams(JSON.stringify(JSON.parse(text))).toString();
          }
          navigator.clipboard.writeText(url).then(() => { alert('Link copied to clipboard'); });
        } catch(e) { console.warn(e); }
    });

    var sendCustomData = function () {
        ghRequest.ignoreCustomErrors = false;
        mySubmit();
    };

    var sendCustomDataIgnoreErrors = function () {
        ghRequest.ignoreCustomErrors = true;
        mySubmit();
    }

    cmEditor.setExtraKey('Ctrl-Enter', sendCustomDataIgnoreErrors);
    $("#custom-model-search-button").click(sendCustomData);

    if (isProduction())
        $('#hosting').show();

    var History = window.History;
    if (History.enabled) {
        History.Adapter.bind(window, 'statechange', function () {
            // No need for workaround?
            // Chrome and Safari always emit a popstate event on page load, but Firefox doesn’t
            // https://github.com/defunkt/jquery-pjax/issues/143#issuecomment-6194330

            var state = History.getState();
            initFromParams(state.data, true);
        });
    }

    $('#locationform').submit(function (e) {
        // no page reload
        e.preventDefault();
        mySubmit();
    });

    var urlParams = urlTools.parseUrlWithHisto();

    var customModelJSON = urlParams.custom_model;
    if(customModelJSON) {
        toggleCustomModelBox(false);
        cmEditor.value = customModelJSON; // if json parsing fails we still have the partial custom model in the box
        try {
            var tmpObj = JSON.parse(customModelJSON);
            cmEditor.value = JSON.stringify(tmpObj, null, 2);
        } catch(e) {
            console.warn('cannot pretty print custom model: ' + e);
        }

    } else {
        // todo: the idea was to highlight everything so if we start typing the example is overwritten. But unfortunately
        // this does not work. And not even sure this is so useful?
        showCustomModelExample();
    }

    $.when(ghRequest.fetchTranslationMap(urlParams.locale), ghRequest.getInfo())
            .then(function (arg1, arg2) {
                // init translation retrieved from first call (fetchTranslationMap)
                var translations = arg1[0];
                autocomplete.setLocale(translations.locale);
                ghRequest.setLocale(translations.locale);
                translate.init(translations);

                // init bounding box from getInfo result
                var json = arg2[0];
                var tmp = json.bbox;
                bounds.initialized = true;
                bounds.minLon = tmp[0];
                bounds.minLat = tmp[1];
                bounds.maxLon = tmp[2];
                bounds.maxLat = tmp[3];
                nominatim.setBounds(bounds);
                var profilesDiv = $("#profiles");

                function createButton(profile, hide) {
                    var vehicle = profile.vehicle;
                    var profileName = profile.name;
                    var button = $("<button class='vehicle-btn' title='" + profileDisplayName(profileName) + "'/>");
                    if (hide)
                        button.hide();

                    button.attr('id', profileName);
                    button.html("<img src='img/" + vehicle.toLowerCase() + ".png' alt='" + profileDisplayName(profileName) + "'></img>");
                    button.click(function () {
                        ghRequest.setProfile(profileName);
                        ghRequest.removeLegacyParameters();
                        resolveAll();
                        if (ghRequest.route.isResolved())
                          routeLatLng(ghRequest);
                    });
                    return button;
                }

                if (json.profiles) {
                    var profiles = json.profiles;
                    // first sort alphabetically to maintain a consistent order, then move certain elements to front/back
                    profiles.sort(function (a, b) {
                         return a.vehicle < b.vehicle ? -1 : a.vehicle > b.vehicle ? 1 : 0;
                    });
                    // the desired order is car,foot,bike,<others>,motorcycle
                    var firstVehicles = ["car", "foot", "bike"];
                    for (var i=firstVehicles.length-1; i>=0; --i) {
                        profiles = moveToFront(profiles, function(p) { return p.vehicle === firstVehicles[i]; });
                    }
                    var lastVehicles = ["mtb", "motorcycle"];
                    for (var i=0; i<lastVehicles.length; ++i) {
                        profiles = moveToFront(profiles, function(p) { return p.vehicle !== lastVehicles[i]; });
                    }
                    ghRequest.profiles = profiles;
                    ghRequest.setElevation(json.elevation);

                    // only show all profiles if the url already specifies an existing profile that is not amongst the 'firstVehicles'
                    var urlProfile = profiles.find(function (profile) { return urlParams.profile && profile.name === urlParams.profile; });
                    var showAllProfiles = urlProfile && firstVehicles.indexOf(urlProfile.vehicle) >= 0;
                    if (profiles.length > 0)
                        ghRequest.setProfile(profiles[0].name);

                    var numVehiclesWhenCollapsed = 3;
                    var hiddenVehicles = [];
                    for (var i = 0; i < profiles.length; ++i) {
                        var btn = createButton(profiles[i], !showAllProfiles && i >= numVehiclesWhenCollapsed);
                        profilesDiv.append(btn);
                        if (i >= numVehiclesWhenCollapsed)
                            hiddenVehicles.push(btn);
                    }

                    if (!showAllProfiles && profiles.length > numVehiclesWhenCollapsed) {
                        var moreBtn = $("<a id='more-vehicle-btn'> ...</a>").click(function () {
                            moreBtn.hide();
                            for (var i in hiddenVehicles) {
                                hiddenVehicles[i].show();
                            }
                        });
                        profilesDiv.append($("<a class='vehicle-info-link' href='https://docs.graphhopper.com/#section/Map-Data-and-Routing-Profiles/OpenStreetMap'>?</a>"));
                        profilesDiv.append(moreBtn);
                    }
                }
                $("button#" + profiles[0].name).addClass("selectprofile");

                metaVersionInfo = messages.extractMetaVersionInfo(json);
                // a very simplistic helper system that shows the possible entries and encoded values
                if(json.encoded_values) {
                    const categories = {};
                    Object.keys(json.encoded_values).forEach((k) => {
                        const v = json.encoded_values[k];
                        if (v.length == 2 && v[0] === 'true' && v[1] === 'false') {
                            categories[k] = {type: 'boolean'};
                        } else if (v.length === 2 && v[0] === '>number' && v[1] === '<number') {
                            categories[k] = {type: 'numeric'};
                        } else {
                            categories[k] = {type: 'enum', values: v.sort()};
                        }
                    });
                    cmEditor.categories = categories;
                }

                mapLayer.initMap(bounds, setStartCoord, setIntermediateCoord, setEndCoord, urlParams.layer, urlParams.use_miles);

                // execute query
                initFromParams(urlParams, true);

                checkInput();
            }, function (err) {
                console.log(err);
                $('#error').html('GraphHopper API offline? <a href="#" onclick="location.reload();event.preventDefault();">Refresh</a>' + '<br/>Status: ' + err.statusText + '<br/>' + host);

                bounds = {
                    "minLon": -180,
                    "minLat": -90,
                    "maxLon": 180,
                    "maxLat": 90
                };
                nominatim.setBounds(bounds);
                mapLayer.initMap(bounds, setStartCoord, setIntermediateCoord, setEndCoord, urlParams.layer, urlParams.use_miles);
            });

    var language_code = urlParams.locale && urlParams.locale.split('-', 1)[0];
    if (language_code != 'en') {
        // A few language codes are different in GraphHopper and Flatpickr.
        var flatpickr_locale;
        switch (language_code) {
            case 'ca':  // Catalan
                flatpickr_locale = 'cat';
                break;
            case 'el':  // Greek
                flatpickr_locale = 'gr';
                break;
            default:
                flatpickr_locale = language_code;
        }
        if (Flatpickr.l10ns.hasOwnProperty(flatpickr_locale)) {
{'fraction_non_alphanumeric': 0.13798540574236368, 'fraction_numerical': 0.005647024311539731, 'mean_word_length': 1.8063387528298003, 'pattern_counts': {'":': 26, '<': 37, '<?xml version=': 0, '>': 49, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3141699', 'n_tokens_mistral': 7630, 'n_tokens_neox': 7231, 'n_words': 1506}