<commit_before>/*jslint node: true */
"use strict";

var _ = require('underscore');
var Promise = require('bluebird');

var eventTree = function () {
    return {
        hash: {}
        , funcs: []
        , promises: []
    };
};

var addCallback = function (route, tree, cb) {
    var head = _.head(route);
    if (!tree.hash.hasOwnProperty(head)) {
        tree.hash[head] = eventTree();
    }

    if (route.length > 1) {
        return addCallback(_.rest(route), tree.hash[head], cb);
    }
    else if (route.length === 1) {
        tree.hash[head].funcs.push(cb);
    }
};

var execTree = function (tree, msg) {
    if (!tree || tree.funcs.length === 0) {
        return Promise.resolve(false);
    }
    return new Promise(function (resolve) {
        _.each(tree.funcs, function (cb) {
            cb(msg);
        });
        resolve(true);
    });
};

var applySubTrees = function (tree, method) {
    return Promise.map(_.pairs(tree.hash)
                       , function (kv) {
                           if (kv[0] === '**') {
                               return false;
                           }
                           else {
                               return method(kv[1]);
                           }
                       }, {concurrency: 1});
};

var joinTwoExecutions = function (left, right) {
    return Promise.join(left, right, function (l, r) {
        return l || r;
    });
};

var joinThreeExecutions = function (left, mid, right) {
    return Promise.join(left, mid, right, function (l, m, r) {
        return l || m || r;
    });
};


var execAll = function (tree, msg) {
    var subTreeExecution = applySubTrees(tree, function (subtree) {
        return execAll(subtree, msg);
    });
    return joinTwoExecutions(execTree(tree, msg)
                            , subTreeExecution);
};

var execMatch = function (target, tree, msg) {
    if (!tree) {
        return Promise.resolve(false);
    }
    var targetTree = tree.hash.hasOwnProperty(target) && tree.hash[target];
    if (!targetTree) {
        return Promise.resolve(false);
    }
    var doubleStarTree = targetTree.hash['**'];
    return joinTwoExecutions(execTree(targetTree, msg)
                            , execTree(doubleStarTree, msg));
};

var anyExecutions = function (executions) {
    return _.any(executions);
};

var noExecution = function () {
    return Promise.resolve(false);
};

var execCallbacks = function (route, tree, msg) {
    if (!tree) {
        return noExecution();
    }
    var head = _.head(route);
    if (head === '**') {
        return execAll(tree, msg);
    }
    else if (route.length > 1) {
        var rest = _.rest(route);
        if (head === '*') {
            return applySubTrees(tree, function (subtree) {
                return execCallbacks(rest, subtree, msg);
            })
                .then(anyExecutions);    
        }
        else {
            var matchTree = tree.hash.hasOwnProperty(head) && tree.hash[head];
            return Promise.join(execTree(tree.hash['*'] && tree.hash['*'].hash['**'], msg)
                               , execTree(matchTree && matchTree.hash['**'], msg)
                               , execCallbacks(rest, tree.hash['*'], msg)
                               , execCallbacks(rest, matchTree, msg), function () {
                                   return _.any(arguments);
                               });
        }
    }
    else if (route.length === 1) {
        if (head === '*') {
            return applySubTrees(tree, function (subtree) {
                return execMatch(rest, subtree[1], msg);
            })
                .then(anyExecutions);    
        }
        else {
            return joinTwoExecutions(execMatch('*', tree, msg)
                                     , execMatch(head, tree, msg));
        }
    }
    else {
        return noExecution();
    }
};

var removeCallback = function (route, tree, f) {
    var head = _.head(route);
    if (tree.hash.hasOwnProperty(head)) {
        if (route.length > 1) {
            return removeCallback(_.rest(route), tree.hash[head], f);
        }
        else if (route.length === 1) {
            tree.hash[head].funcs = _.without(tree.hash[head].funcs, f);
        }
    }
};

var EventEmitter = function () {
    this._eventTree = eventTree();
};

_.extend(EventEmitter.prototype, {
    on: function (route, cb) {
        return addCallback(route, this._eventTree, cb);
    }
    , emit: function (route, msg) {
        // return execCallbacks(route, this._eventTree, msg);
        return joinTwoExecutions(execTree(this._eventTree.hash['**'], msg)
                                 , execCallbacks(route, this._eventTree, msg));
    } 
    , removeListener: function (route, f) {
        return removeCallback(route, this._eventTree, f);
    }
});

module.exports = {
    EventEmitter: EventEmitter
};<commit_msg>Satisfy once tests.<commit_after>/*jslint node: true */
"use strict";

var _ = require('underscore');
var Promise = require('bluebird');

var eventTree = function () {
    return {
        hash: {}
        , funcs: []
        , promises: []
    };
};

var addCallback = function (route, tree, cb) {
    var head = _.head(route);
    if (!tree.hash.hasOwnProperty(head)) {
        tree.hash[head] = eventTree();
    }

    if (route.length > 1) {
        return addCallback(_.rest(route), tree.hash[head], cb);
    }
    else if (route.length === 1) {
        tree.hash[head].funcs.push(cb);
    }
};

var execTree = function (tree, msg) {
    if (!tree || tree.funcs.length === 0) {
        return Promise.resolve(false);
    }
    return new Promise(function (resolve) {
        _.each(tree.funcs, function (cb) {
            cb(msg);
        });
        resolve(true);
    });
};

var applySubTrees = function (tree, method) {
    return Promise.map(_.pairs(tree.hash)
                       , function (kv) {
                           if (kv[0] === '**') {
                               return false;
                           }
                           else {
                               return method(kv[1]);
                           }
                       }, {concurrency: 1});
};

var joinTwoExecutions = function (left, right) {
    return Promise.join(left, right, function (l, r) {
        return l || r;
    });
};

var joinThreeExecutions = function (left, mid, right) {
    return Promise.join(left, mid, right, function (l, m, r) {
        return l || m || r;
    });
};


var execAll = function (tree, msg) {
    var subTreeExecution = applySubTrees(tree, function (subtree) {
        return execAll(subtree, msg);
    });
    return joinTwoExecutions(execTree(tree, msg)
                            , subTreeExecution);
};

var execMatch = function (target, tree, msg) {
    if (!tree) {
        return Promise.resolve(false);
    }
    var targetTree = tree.hash.hasOwnProperty(target) && tree.hash[target];
    if (!targetTree) {
        return Promise.resolve(false);
    }
    var doubleStarTree = targetTree.hash['**'];
    return joinTwoExecutions(execTree(targetTree, msg)
                            , execTree(doubleStarTree, msg));
};

var anyExecutions = function (executions) {
    return _.any(executions);
};

var noExecution = function () {
    return Promise.resolve(false);
};

var execCallbacks = function (route, tree, msg) {
    if (!tree) {
        return noExecution();
    }
    var head = _.head(route);
    if (head === '**') {
        return execAll(tree, msg);
    }
    else if (route.length > 1) {
        var rest = _.rest(route);
        if (head === '*') {
            return applySubTrees(tree, function (subtree) {
                return execCallbacks(rest, subtree, msg);
            })
                .then(anyExecutions);    
        }
        else {
            var matchTree = tree.hash.hasOwnProperty(head) && tree.hash[head];
            return Promise.join(execTree(tree.hash['*'] && tree.hash['*'].hash['**'], msg)
                               , execTree(matchTree && matchTree.hash['**'], msg)
                               , execCallbacks(rest, tree.hash['*'], msg)
                               , execCallbacks(rest, matchTree, msg), function () {
                                   return _.any(arguments);
                               });
        }
    }
    else if (route.length === 1) {
        if (head === '*') {
            return applySubTrees(tree, function (subtree) {
                return execMatch(rest, subtree[1], msg);
            })
                .then(anyExecutions);    
        }
        else {
            return joinTwoExecutions(execMatch('*', tree, msg)
                                     , execMatch(head, tree, msg));
        }
    }
    else {
        return noExecution();
    }
};

var removeCallback = function (route, tree, f) {
    var head = _.head(route);
    if (tree.hash.hasOwnProperty(head)) {
        if (route.length > 1) {
            return removeCallback(_.rest(route), tree.hash[head], f);
        }
        else if (route.length === 1) {
            tree.hash[head].funcs = _.without(tree.hash[head].funcs, f);
        }
    }
};

var EventEmitter = function () {
    this._eventTree = eventTree();
};

_.extend(EventEmitter.prototype, {
    on: function (route, cb) {
        return addCallback(route, this._eventTree, cb);
    }
    , emit: function (route, msg) {
        // return execCallbacks(route, this._eventTree, msg);
        return joinTwoExecutions(execTree(this._eventTree.hash['**'], msg)
                                 , execCallbacks(route, this._eventTree, msg));
    } 
    , removeListener: function (route, f) {
        return removeCallback(route, this._eventTree, f);
    }
    , once: function (route, cb) {
        var _this = this;
        _this.on(route, cb);
        _this.on(route, function () {
            _this.removeListener(route, cb);
        });
    }
});

module.exports = {
    EventEmitter: EventEmitter
};
{'fraction_non_alphanumeric': 0.14366027507278387, 'fraction_numerical': 0.00220861359301275, 'mean_word_length': 1.7819044959508517, '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': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1473536', 'n_tokens_mistral': 2912, 'n_tokens_neox': 2883, 'n_words': 641}