<commit_before>'use strict';

const chemistEquations = require('../data/data.json');
var equations = processChemist(chemistEquations);
const allComponents = getComponentList(equations);
const Equilibrium = require('./Equilibrium');
const defaultOptions = {
    solvent: 'H2O'
};

class Factory {
    constructor(options) {
        options = Object.assign({}, defaultOptions, options);
        this.components = [];
        this.options = {};
        this._hasChanged = true;
        this._setSolvent(options.solvent);
    }

    static getSpecieLabels(type) {
        var labels = new Set();
        var keys = Object.keys(equations);
        for(var i=0; i<keys.length; i++) {
            var eq = equations[keys[i]];
            if(!type || eq.type === type) {
                labels.add(keys[i]);
                for(let key in eq.components) {
                    labels.add(key);
                }
            }
        }
        return Array.from(labels);
    }


    _setSolvent(solvent) {
        this.solvent = solvent;
        this._solventEquations();
        // de facto add components linked to solvent
        this.addSpecie(this.solvent);
    }

    addSpecie(label, total) {
        if(label === this.solvent) {
            total = 0;
        }
        var eq = this.solventEquations[label] || equations[label];
        if (eq) {
            for (var key in eq.components) {
                this._addComponent(key, total * eq.components[key]);
            }
        } else if (allComponents.indexOf(label) >= 0) {
            this._addComponent(label, total);
        } else if(label !== this.solvent){
            throw new Error('Specie not found');
        }
    }

    _addComponent(label, total) {
        if (!total) total = 0;
        var comp = this.components.find(c => c.label === label);
        if (comp) comp.total += total;
        else {
            this._hasChanged = true;
            this.components.push({
                label, total
            });
        }
    }

    _solventEquations() {
        var solvent = {};
        var keys = Object.keys(equations);
        for(var i=0; i<keys.length; i++) {
            var key = keys[i];

            var comp = equations[key].components;
            var compKeys = Object.keys(comp);
            if(key === this.solvent) {
                solvent[key] = {
                    formed: compKeys[compKeys.length-1],
                    components: {},
                    pK: -equations[key].pK
                };
                for(let j=0; j<compKeys.length-1; j++) {
                    let compKey = compKeys[j];
                    solvent[key].components[compKey] = -equations[key].components[compKey];
                }
                // check for repercussions on other equations
                replaceComponent(key, solvent);
                // alias
                solvent[solvent[key].formed] = solvent[key];

            } else {
                for(let j=0; j<compKeys.length; j++) {
                    let compKey = compKeys[i];
                    if(equations[key].components[compKey] === this.solvent) {
                        solvent[key] = {
                            components: Object.assign(equations[key].components),
                            pK: equations[key].pK
                        };
                        // Remove solvent from equation
                        delete solvent[key].components[compKey];
                    }
                }
            }

        }
        this.solventEquations = solvent;
        return solvent;
    }

    setTotal(componentLabel, total) {
        var c = this.components.find(c => c.label === componentLabel);
        c.total = total;
        c.atEquilibrium = undefined;
    }

    setAtEquilibrium(componentLabel, atEquilibrium) {
        var c = this.components.find(c => c.label === componentLabel);
        c.atEquilibrium = atEquilibrium;
        c.total = undefined;
    }

    setOptions(options) {
        this.options = options;
    }

    getEquilibrium() {
        return new Equilibrium(this.getModel(), this.options);
    }

    getComponents() {
        return this.components;
    }

    getEquations(type) {
        var that = this;
        type = type || 'chemist';
        this._getEquations();
        var result = [];
        function addEquations(eq, solid) {
            var keys = Object.keys(eq);
            for(var i=0; i<keys.length; i++) {
                var key = keys[i];
                var label, currentEq;
                if(type === 'decomposed') {
                    label = key;
                    currentEq = equations[key];
                } else if(type === 'decomposed-solvent') {
                    label = that.solventEquations[key] && that.solventEquations[key].formed || key;
                    currentEq = that.solventEquations[key] || eq[key];
                } else if(type === 'chemist') {
                    label = key;
                    currentEq = chemistEquations[key];
                }
                result.push({
                    label: label,
                    components: []
                });
                var idx = result.length - 1;
                if(solid) result[idx].solid = true;

                var ks = Object.keys(currentEq.components);
                for(var j=0; j<ks.length; j++) {
                    var k = ks[j];
                    result[idx].components.push({
                        label: ks[j],
                        n: currentEq.components[k]
                    });
                }
            }
        }
        addEquations(this._equations);
        addEquations(this._solidEquations, true);
        return result;
    }

    getModel() {
        var that = this;
        var nbComponents = this.components.length;
        var model = {};

        this._getEquations();
        var equations = this._equations;
        var solidEquations = this._solidEquations;

        function addEquations(equations, modelEq, solid) {
            var keys = Object.keys(equations);
            for (var i = 0; i < keys.length; i++) {
                var key = keys[i];
                var equation = equations[key];
                var eq = {
                    label: that.solventEquations[key] && that.solventEquations[key].formed || key,
                    beta: Math.pow(10, equation.pK),
                    components: new Array(that.components.length).fill(0)
                };
                if (solid) eq.solid = true;
                modelEq.push(eq);
                var comp = equation.components;
                var compKeys = Object.keys(comp);
                for (var j = 0; j < compKeys.length; j++) {
                    var idx = that.components.findIndex(c => c.label === compKeys[j]);
                    eq.components[idx] += comp[compKeys[j]];
                }
            }
        }


        model.formedSpecies = [];
        addEquations(equations, model.formedSpecies);
        addEquations(solidEquations, model.formedSpecies, true);



        // Model components
        model.components = new Array(nbComponents);
        for (var i = 0; i < this.components.length; i++) {
            model.components[i] = Object.assign({}, this.components[i]);
        }

        return model;
    }<commit_msg>fix beta calculation for precipitation equations<commit_after>'use strict';

const chemistEquations = require('../data/data.json');
var equations = processChemist(chemistEquations);
const allComponents = getComponentList(equations);
const Equilibrium = require('./Equilibrium');
const defaultOptions = {
    solvent: 'H2O'
};

class Factory {
    constructor(options) {
        options = Object.assign({}, defaultOptions, options);
        this.components = [];
        this.options = {};
        this._hasChanged = true;
        this._setSolvent(options.solvent);
    }

    static getSpecieLabels(type) {
        var labels = new Set();
        var keys = Object.keys(equations);
        for(var i=0; i<keys.length; i++) {
            var eq = equations[keys[i]];
            if(!type || eq.type === type) {
                labels.add(keys[i]);
                for(let key in eq.components) {
                    labels.add(key);
                }
            }
        }
        return Array.from(labels);
    }


    _setSolvent(solvent) {
        this.solvent = solvent;
        this._solventEquations();
        // de facto add components linked to solvent
        this.addSpecie(this.solvent);
    }

    addSpecie(label, total) {
        if(label === this.solvent) {
            total = 0;
        }
        var eq = this.solventEquations[label] || equations[label];
        if (eq) {
            for (var key in eq.components) {
                this._addComponent(key, total * eq.components[key]);
            }
        } else if (allComponents.indexOf(label) >= 0) {
            this._addComponent(label, total);
        } else if(label !== this.solvent){
            throw new Error('Specie not found');
        }
    }

    _addComponent(label, total) {
        if (!total) total = 0;
        var comp = this.components.find(c => c.label === label);
        if (comp) comp.total += total;
        else {
            this._hasChanged = true;
            this.components.push({
                label, total
            });
        }
    }

    _solventEquations() {
        var solvent = {};
        var keys = Object.keys(equations);
        for(var i=0; i<keys.length; i++) {
            var key = keys[i];

            var comp = equations[key].components;
            var compKeys = Object.keys(comp);
            if(key === this.solvent) {
                solvent[key] = {
                    formed: compKeys[compKeys.length-1],
                    components: {},
                    pK: -equations[key].pK
                };
                for(let j=0; j<compKeys.length-1; j++) {
                    let compKey = compKeys[j];
                    solvent[key].components[compKey] = -equations[key].components[compKey];
                }
                // check for repercussions on other equations
                replaceComponent(key, solvent);
                // alias
                solvent[solvent[key].formed] = solvent[key];

            } else {
                for(let j=0; j<compKeys.length; j++) {
                    let compKey = compKeys[i];
                    if(equations[key].components[compKey] === this.solvent) {
                        solvent[key] = {
                            components: Object.assign(equations[key].components),
                            pK: equations[key].pK
                        };
                        // Remove solvent from equation
                        delete solvent[key].components[compKey];
                    }
                }
            }

        }
        this.solventEquations = solvent;
        return solvent;
    }

    setTotal(componentLabel, total) {
        var c = this.components.find(c => c.label === componentLabel);
        c.total = total;
        c.atEquilibrium = undefined;
    }

    setAtEquilibrium(componentLabel, atEquilibrium) {
        var c = this.components.find(c => c.label === componentLabel);
        c.atEquilibrium = atEquilibrium;
        c.total = undefined;
    }

    setOptions(options) {
        this.options = options;
    }

    getEquilibrium() {
        return new Equilibrium(this.getModel(), this.options);
    }

    getComponents() {
        return this.components;
    }

    getEquations(type) {
        var that = this;
        type = type || 'chemist';
        this._getEquations();
        var result = [];
        function addEquations(eq, solid) {
            var keys = Object.keys(eq);
            for(var i=0; i<keys.length; i++) {
                var key = keys[i];
                var label, currentEq;
                if(type === 'decomposed') {
                    label = key;
                    currentEq = equations[key];
                } else if(type === 'decomposed-solvent') {
                    label = that.solventEquations[key] && that.solventEquations[key].formed || key;
                    currentEq = that.solventEquations[key] || eq[key];
                } else if(type === 'chemist') {
                    label = key;
                    currentEq = chemistEquations[key];
                }
                result.push({
                    label: label,
                    components: []
                });
                var idx = result.length - 1;
                if(solid) result[idx].solid = true;

                var ks = Object.keys(currentEq.components);
                for(var j=0; j<ks.length; j++) {
                    var k = ks[j];
                    result[idx].components.push({
                        label: ks[j],
                        n: currentEq.components[k]
                    });
                }
            }
        }
        addEquations(this._equations);
        addEquations(this._solidEquations, true);
        return result;
    }

    getModel() {
        var that = this;
        var nbComponents = this.components.length;
        var model = {};

        this._getEquations();
        var equations = this._equations;
        var solidEquations = this._solidEquations;

        function addEquations(equations, modelEq, solid) {
            var keys = Object.keys(equations);
            for (var i = 0; i < keys.length; i++) {
                var key = keys[i];
                var equation = equations[key];
                var eq = {
                    label: that.solventEquations[key] && that.solventEquations[key].formed || key,
                    beta: equations[key].type === 'precipitation' ? Math.pow(10, -equation.pK) : Math.pow(10, equation.pK),
                    components: new Array(that.components.length).fill(0)
                };
                if (solid) eq.solid = true;
                modelEq.push(eq);
                var comp = equation.components;
                var compKeys = Object.keys(comp);
                for (var j = 0; j < compKeys.length; j++) {
                    var idx = that.components.findIndex(c => c.label === compKeys[j]);
                    eq.components[idx] += comp[compKeys[j]];
                }
            }
        }


        model.formedSpecies = [];
        addEquations(equations, model.formedSpecies);
        addEquations(solidEquations, model.formedSpecies, true);



        // Model components
        model.components = new Array(nbComponents);
        for (var i = 0; i < this.components.length; i++) {
            model.components[i] = Object.assign({}, this.components[i]);
        }

        return model;
    }
{'fraction_non_alphanumeric': 0.11954304365565076, 'fraction_numerical': 0.0027199782401740786, 'mean_word_length': 1.4401858304297328, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 13, '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': '2918378', 'n_tokens_mistral': 4087, 'n_tokens_neox': 3847, 'n_words': 819}