summaryrefslogtreecommitdiff
path: root/lib/GitHub/Collector/Role/Graph
diff options
context:
space:
mode:
authorfranck cuny <franck@lumberjaph.net>2011-06-13 16:33:23 +0200
committerfranck cuny <franck@lumberjaph.net>2011-06-13 16:33:23 +0200
commit871336c030209b46ae6b124a702677363487f9a8 (patch)
tree86f234d42c68b26a7aeb9cc373667127ad661e19 /lib/GitHub/Collector/Role/Graph
parentuse template_toolkit and add infos about colors (diff)
downloadstargit-871336c030209b46ae6b124a702677363487f9a8.tar.gz
import github::collector
Signed-off-by: franck cuny <franck@lumberjaph.net>
Diffstat (limited to 'lib/GitHub/Collector/Role/Graph')
-rw-r--r--lib/GitHub/Collector/Role/Graph/Edges.pm13
-rw-r--r--lib/GitHub/Collector/Role/Graph/Gexf.pm47
-rw-r--r--lib/GitHub/Collector/Role/Graph/Neighbors.pm128
-rw-r--r--lib/GitHub/Collector/Role/Graph/Nodes.pm13
-rw-r--r--lib/GitHub/Collector/Role/Graph/Query.pm45
-rw-r--r--lib/GitHub/Collector/Role/Graph/Search.pm19
6 files changed, 265 insertions, 0 deletions
diff --git a/lib/GitHub/Collector/Role/Graph/Edges.pm b/lib/GitHub/Collector/Role/Graph/Edges.pm
new file mode 100644
index 0000000..bea5914
--- /dev/null
+++ b/lib/GitHub/Collector/Role/Graph/Edges.pm
@@ -0,0 +1,13 @@
+package GitHub::Collector::Role::Graph::Edges;
+
+use Moose::Role;
+
+has edges => (
+ is => 'rw',
+ isa => 'HashRef',
+ lazy => 1,
+ default => sub { {} },
+ auto_deref => 1,
+);
+
+1;
diff --git a/lib/GitHub/Collector/Role/Graph/Gexf.pm b/lib/GitHub/Collector/Role/Graph/Gexf.pm
new file mode 100644
index 0000000..ab83dd4
--- /dev/null
+++ b/lib/GitHub/Collector/Role/Graph/Gexf.pm
@@ -0,0 +1,47 @@
+package GitHub::Collector::Role::Graph::Gexf;
+
+use Moose::Role;
+use Graph::GEXF;
+
+has output => (
+ is => 'ro',
+ isa => 'Int',
+ predicate => 'should_export',
+);
+
+sub export {
+ my ($self, ) = @_;
+
+ my $gexf = Graph::GEXF->new();
+ $gexf->add_node_attribute( name => 'string' );
+ $gexf->add_node_attribute( lang => 'string' );
+ $gexf->add_node_attribute( size => 'int' );
+ $gexf->add_node_attribute( country => 'string' );
+ $gexf->add_node_attribute( indegree => 'int' );
+
+ my $nodes = {};
+ foreach my $node ( keys %{ $self->nodes } ) {
+ my $n = $gexf->add_node( $self->nodes->{$node}->{id} );
+ $n->label($node);
+ $n->attribute( name => $node );
+ $n->attribute( size => $self->nodes->{$node}->{size} );
+ $n->attribute( lang => $self->nodes->{$node}->{language} || '' );
+ $n->attribute( country => $self->nodes->{$node}->{country} || '' );
+ $n->attribute( indegree => $self->nodes->{$node}->{indegree} );
+ $nodes->{$node} = $n;
+ }
+
+ foreach my $edge (keys %{$self->edges}){
+ $nodes->{ $self->edges->{$edge}->{sourceId} }->link_to(
+ {
+ target => $self->edges->{$edge}->{targetId},
+ weight => $self->edges->{$edge}->{weight}
+ }
+ );
+ }
+
+ my $xml = $gexf->to_xml();
+ print $xml;
+}
+
+1;
diff --git a/lib/GitHub/Collector/Role/Graph/Neighbors.pm b/lib/GitHub/Collector/Role/Graph/Neighbors.pm
new file mode 100644
index 0000000..627de94
--- /dev/null
+++ b/lib/GitHub/Collector/Role/Graph/Neighbors.pm
@@ -0,0 +1,128 @@
+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},
+ };
+}
+
+1;
diff --git a/lib/GitHub/Collector/Role/Graph/Nodes.pm b/lib/GitHub/Collector/Role/Graph/Nodes.pm
new file mode 100644
index 0000000..5109e9a
--- /dev/null
+++ b/lib/GitHub/Collector/Role/Graph/Nodes.pm
@@ -0,0 +1,13 @@
+package GitHub::Collector::Role::Graph::Nodes;
+
+use Moose::Role;
+
+has nodes => (
+ is => 'rw',
+ isa => 'HashRef',
+ lazy => 1,
+ default => sub { {} },
+ auto_deref => 1,
+);
+
+1;
diff --git a/lib/GitHub/Collector/Role/Graph/Query.pm b/lib/GitHub/Collector/Role/Graph/Query.pm
new file mode 100644
index 0000000..d3ab7f0
--- /dev/null
+++ b/lib/GitHub/Collector/Role/Graph/Query.pm
@@ -0,0 +1,45 @@
+package GitHub::Collector::Role::Graph::Query;
+
+use Moose::Role;
+
+has language => (
+ is => 'rw',
+ isa => 'Str',
+ predicate => 'has_language',
+);
+
+has location => (
+ is => 'rw',
+ isa => 'Str',
+ predicate => 'has_location',
+);
+
+has company => (
+ is => 'ro',
+ isa => 'Str',
+ predicate => 'has_company',
+);
+
+has country => (
+ is => 'ro',
+ isa => 'Str',
+ predicate => 'has_country',
+);
+
+
+sub build_query {
+ my $self = shift;
+
+ my $search = {};
+
+ foreach my $attr (qw/language location company country/) {
+ my $predicate = "has_$attr";
+ if ( $self->$predicate ) {
+ $search->{$attr} = $self->$attr;
+ }
+ }
+
+ return $search;
+}
+
+1;
diff --git a/lib/GitHub/Collector/Role/Graph/Search.pm b/lib/GitHub/Collector/Role/Graph/Search.pm
new file mode 100644
index 0000000..fbd0d07
--- /dev/null
+++ b/lib/GitHub/Collector/Role/Graph/Search.pm
@@ -0,0 +1,19 @@
+package GitHub::Collector::Role::Graph::Search;
+
+use Moose::Role;
+
+sub build_from_query {
+ my ($self, $search) = @_;
+
+ $search ||= $self->build_query();
+
+ my $profiles = $self->db_profiles->find($search);
+
+ while ( my $profile = $profiles->next ) {
+ $self->neighbors( $profile->{login}, 0 );
+ }
+
+ $self->remove_leaves();
+}
+
+1;