<commit_before>'use strict';

var _ = require('lodash');
var async = require('async');
var mongoose = require('mongoose');
var Person = mongoose.model('Person');
var GraphNode = mongoose.model('GraphNode');
var ActivityLink = mongoose.model('ActivityLink');

var getNode = function(person, graphnode) {
    var result = {
        id:       person.id,
        fullName: person.fullName,
        team:     person.team,
        type:     person.getType()
    };

    if (typeof graphnode !== 'undefined') {
        if (typeof graphnode.coordX !== 'undefined') {
            result.coordX = graphnode.coordX;
        }
        if (typeof graphnode.coordY !== 'undefined') {
            result.coordY = graphnode.coordY;
        }
    }

    return result;
};

// TODO: this needs unit testing
// TODO: this function is ridiculously long
var getGraph = function(person, cb) {
    GraphNode
        .find({owner: person.id})
        .populate('target', 'fullName password team')
        .exec(function (err, nodes) {
            if (err) {
                cb(err);
                return;
            }

            var persons = _.pluck(nodes, 'target');
            var friendIds = _.pluck(persons, 'id');

            // transform this into a map for easier random access
            persons = _.indexBy(persons, 'id');
            nodes   = _.indexBy(nodes, function(n) { return n.target.id; });

            // Count the activities between the people in the social graph
            // Get all the activities of the user and the friends
            // (including activities to friends of friends)
            ActivityLink
                .find()
                .or([
                    {source: { $in: friendIds } },
                    {target: { $in: friendIds } }
                ])
                .populate('source')
                .populate('target')
                .exec(function(err, links) {
                    // We need to map these activity links, and transform them into a 2d
                    // structure that maps source/target pairs to counts.
                    var counts = {};
                    _.each(links, function(l) {
                        counts[l.source.id] = counts[l.source.id] || {};
                        if (typeof counts[l.source.id][l.target.id] === 'undefined') {
                            counts[l.source.id][l.target.id] = {
                                open: 0,
                                completed: 0
                            };
                        }
                        counts[l.source.id][l.target.id][l.success ? 'completed' : 'open'] += 1;
                        _.each([l.source, l.target], function(p) {
                            if (typeof persons[p.id] === 'undefined') {
                                persons[p.id] = p;
                            }
                        });
                    });

                    // Convert to the format needed by the frontend
                    var graphLinks = _.map(counts, function(cc, s) {
                        return _.map(cc, function(c, t) {
                            var link = {
                                source: s,
                                target: t
                            };

                            // Add the number of activities if the given person is part of the link
                            if (s === person.id || t === person.id) {
                                link.openActivities = c.open;
                                link.completedActivities = c.completed;
                            }
                            return link;
                        });
                    });
                    graphLinks = _.flatten(graphLinks);

                    async.each(
                        _.toArray(persons),
                        function(p, cb) {
                            p.populateActivityLinks(cb);
                        },
                        function (err) {
                            if (err) {
                                cb(err);
                            } else {
                                var friendIndex = _.indexBy(friendIds, 'id');
                                var resultnodes = _.map(persons, function (n) {
                                    var result = getNode(n, nodes[n.id]);
                                    if (result.id === person.id) {
                                        result.relation = 'me';
                                        result.coordX = 0.5;
                                        result.coordY = 0.5;
                                    } else if (friendIndex[result.id]) {
                                        result.relation = 'friend';
                                    } else {
                                        result.relation = 'friendOfFriend';
                                        result.fullName = undefined;
                                    }
                                    return result;
                                });
                                cb(null, {
                                    nodes: resultnodes,
                                    links: graphLinks
                                });
                            }
                        }
                    );
                })
            ;
        })
    ;
};

exports.view = function(req, res, next) {
    // Get the entire social graph for me
    getGraph(req.user, function(err, graph) {
        if (err) {
            return next(err);
        }
        res.send(graph);<commit_msg>Graph nodes should be indexed by id.<commit_after>'use strict';

var _ = require('lodash');
var async = require('async');
var mongoose = require('mongoose');
var Person = mongoose.model('Person');
var GraphNode = mongoose.model('GraphNode');
var ActivityLink = mongoose.model('ActivityLink');

var getNode = function(person, graphnode) {
    var result = {
        id:       person.id,
        fullName: person.fullName,
        team:     person.team,
        type:     person.getType()
    };

    if (typeof graphnode !== 'undefined') {
        if (typeof graphnode.coordX !== 'undefined') {
            result.coordX = graphnode.coordX;
        }
        if (typeof graphnode.coordY !== 'undefined') {
            result.coordY = graphnode.coordY;
        }
    }

    return result;
};

// TODO: this needs unit testing
// TODO: this function is ridiculously long
var getGraph = function(person, cb) {
    GraphNode
        .find({owner: person.id})
        .populate('target', 'fullName password team')
        .exec(function (err, nodes) {
            if (err) {
                cb(err);
                return;
            }

            var persons = _.pluck(nodes, 'target');
            var friendIds = _.pluck(persons, 'id');

            // transform this into a map for easier random access
            persons = _.indexBy(persons, 'id');
            nodes   = _.indexBy(nodes, function(n) { return n.target.id; });

            // Count the activities between the people in the social graph
            // Get all the activities of the user and the friends
            // (including activities to friends of friends)
            ActivityLink
                .find()
                .or([
                    {source: { $in: friendIds } },
                    {target: { $in: friendIds } }
                ])
                .populate('source')
                .populate('target')
                .exec(function(err, links) {
                    // We need to map these activity links, and transform them into a 2d
                    // structure that maps source/target pairs to counts.
                    var counts = {};
                    _.each(links, function(l) {
                        counts[l.source.id] = counts[l.source.id] || {};
                        if (typeof counts[l.source.id][l.target.id] === 'undefined') {
                            counts[l.source.id][l.target.id] = {
                                open: 0,
                                completed: 0
                            };
                        }
                        counts[l.source.id][l.target.id][l.success ? 'completed' : 'open'] += 1;
                        _.each([l.source, l.target], function(p) {
                            if (typeof persons[p.id] === 'undefined') {
                                persons[p.id] = p;
                            }
                        });
                    });

                    // Convert to the format needed by the frontend
                    var graphLinks = _.map(counts, function(cc, s) {
                        return _.map(cc, function(c, t) {
                            var link = {
                                source: s,
                                target: t
                            };

                            // Add the number of activities if the given person is part of the link
                            if (s === person.id || t === person.id) {
                                link.openActivities = c.open;
                                link.completedActivities = c.completed;
                            }
                            return link;
                        });
                    });
                    graphLinks = _.flatten(graphLinks);

                    async.each(
                        _.toArray(persons),
                        function(p, cb) {
                            p.populateActivityLinks(cb);
                        },
                        function (err) {
                            if (err) {
                                cb(err);
                            } else {
                                var friendIndex = _.indexBy(friendIds, 'id');
                                var resultnodes = _.map(persons, function (n) {
                                    var result = getNode(n, nodes[n.id]);
                                    if (result.id === person.id) {
                                        result.relation = 'me';
                                        result.coordX = 0.5;
                                        result.coordY = 0.5;
                                    } else if (friendIndex[result.id]) {
                                        result.relation = 'friend';
                                    } else {
                                        result.relation = 'friendOfFriend';
                                        result.fullName = undefined;
                                    }
                                    return result;
                                });
                                cb(null, {
                                    nodes: _.indexBy(resultnodes, 'id'),
                                    links: graphLinks
                                });
                            }
                        }
                    );
                })
            ;
        })
    ;
};

exports.view = function(req, res, next) {
    // Get the entire social graph for me
    getGraph(req.user, function(err, graph) {
        if (err) {
            return next(err);
        }
        res.send(graph);
{'fraction_non_alphanumeric': 0.1, 'fraction_numerical': 0.0014298480786416443, 'mean_word_length': 0.8865475387727579, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2452540', 'n_tokens_mistral': 2599, 'n_tokens_neox': 2473, 'n_words': 628}