summaryrefslogtreecommitdiff
path: root/lib/GitHub/Collector/Role/Graph/Neighbors.pm
blob: 9f2ecdbcb5474d93d7e9271dda3c67b94f16f00f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package GitHub::Collector::Role::Graph::Neighbors;

use Moose::Role;
with qw(GitHub::Collector::Role::Languages);

sub neighbors {
    my ( $self, $name, $with_connections ) = @_;

    $self->_neighbors($name);

    if ($with_connections) {
        foreach my $id ( keys %{ $self->edges } ) {
            $self->_connections( $id, $name );
        }
    }
}

sub _neighbors {
    my ( $self, $name ) = @_;

    if ( !defined $self->nodes->{$name} ) {
        $self->_create_node($name);
    }

    $self->_fetch_edges_from($name);
    $self->_fetch_edges_to($name);
}

sub _connections {
    my ( $self, $id, $name ) = @_;

    if ( $self->edges->{$id}->{sourceId} eq $name ) {
        $self->_neighbors( $self->edges->{$id}->{targetId} );
    }
    else {
        $self->_neighbors( $self->edges->{$id}->{sourceId} );
    }
}

sub remove_leaves {
    my $self = shift;

    foreach my $id ( keys %{$self->nodes} ) {
        if ( $self->nodes->{$id}->{size} < 2 ) {
            delete $self->nodes->{$id};
        }
    }

    foreach my $id ( keys %{$self->edges} ) {
        unless ( $self->nodes->{ $self->edges->{$id}->{sourceId} }
            && $self->nodes->{ $self->edges->{$id}->{targetId} } )
        {
            delete $self->edges->{ $id };
        }
    }
}

sub _fetch_edges_from {
    my ( $self, $name ) = @_;

    my $connections = $self->db_edges->find( { source => $name } );

    while ( my $edge = $connections->next ) {
        my $edge_id = $edge->{source} . $edge->{target};

        if ( !defined $self->edges->{$edge_id} ) {
            $self->edges->{$edge_id} = {
                id       => $edge_id,
                targetId => $edge->{target},
                sourceId => $name,
                weight   => $edge->{weight},
            };

            $self->nodes->{$name}->{size}++;

            if ( defined $self->nodes->{ $edge->{target} } ) {
                $self->nodes->{ $edge->{target} }->{size}++;
            }
            else {
                $self->_create_node( $edge->{target}, 1 );
            }
        }
    }
}

sub _fetch_edges_to {
    my ($self, $name) = @_;
    my $connections = $self->db_edges->find( { target => $name } );
    while ( my $edge = $connections->next ) {
        my $edge_id = $edge->{source} . $edge->{target};

        if ( !defined $self->edges->{$edge_id} ) {
            $self->edges->{$edge_id} = {
                id       => $edge_id,
                targetId => $name,
                sourceId => $edge->{source},
                weight   => $edge->{weight},
            };

            $self->nodes->{$name}->{size}++;

            if ( defined $self->nodes->{ $edge->{source} } ) {
                $self->nodes->{ $edge->{source} }->{size}++;
            }
            else {
                $self->_create_node( $edge->{source}, 1 );
            }
        }
    }
}

sub _create_node {
    my ( $self, $login, $size ) = @_;

    $size ||= 0;

    my $info = $self->db_profiles->find_one( { login => $login } );
    $self->nodes->{$login} = {
        id       => $login,
        label    => $login,
        size     => $size,
        language => $self->map_languages($info->{language}),
        country  => $info->{country} || '',
        indegree => $info->{indegree},
        nbrepos  => $info->{public_repo_count},
        follower  => $info->{followers_count},        
    };
}

1;