Permalink
Browse files

Feed objects!

  • Loading branch information...
hakim
hakim committed Jul 16, 2010
1 parent fe0cf45 commit d91c07102e121d1f8fdf9f28d864501018330f42
@@ -1,5 +1,5 @@
package Event;
-use Moose;
+use KiokuDB::Class;
use MooseX::Types::DateTime;
has 'user' => (
@@ -0,0 +1,83 @@
+package Feed;
+use KiokuDB::Class;
+use MooseX::Types::DateTime;
+use Event;
+use List;
+use Scalar::Util 'refaddr';
+
+has 'store_as' => (
+ is => 'rw',
+ isa => 'Maybe[Str]',
+);
+
+has from_feed => (
+ is => 'ro',
+ isa => 'Maybe[Str]',
+);
+
+has list => (
+ is => 'rw',
+ isa => 'List',
+ default => sub { List->empty },
+);
+
+has make_list => (
+ is => 'rw',
+ isa => 'CodeRef',
+);
+
+has from_feed_up_to => (
+ is => 'rw',
+ isa => 'Maybe[Event]',
+);
+
+has from_root_up_to => (
+ is => 'rw',
+ isa => 'Maybe[Event]',
+);
+
+sub add_event {
+ my ($self, $event) = @_;
+ $self->list( $self->list->prepend($event) );
+}
+
+sub store {
+ my ($self, $kioku) = @_;
+
+ my $store_as = $self->store_as or return;
+ $kioku->store( $store_as, $self );
+}
+
+sub up_to_date {
+ my ($self, $kioku, $root) = @_;
+
+ return 1 unless $self->from_feed; # root list cannot be updated in this way
+ return unless $self->from_root_up_to; # if new, then must be updated!
+ # check if it's been updated
+ return 1 if refaddr $root->list->head == refaddr $self->from_root_up_to;
+}
+
+sub update {
+ my ($self, $kioku, $root) = @_;
+ $root ||= $kioku->lookup('root');
+
+ return if $self->up_to_date( $kioku, $root );
+
+ my $from = $kioku->lookup( $self->from_feed );
+ $from->update($kioku, $root);
+
+ my $from_feed_up_to = $self->from_feed_up_to;
+ my $new = $from_feed_up_to ?
+ $from->list->While( sub { refaddr $_[0] != refaddr $from_feed_up_to })
+ : $from->list;
+
+ my $new_list = $self->make_list->( $new );
+
+ my $whole_list = $new_list->concat($self->list);
+
+ $self->list($whole_list);
+ $self->from_feed_up_to( $from->list->head );
+ $self->from_root_up_to( $root->list->head );
+}
+
+1;
@@ -116,6 +116,11 @@ sub take {
return () unless $count;
return ($list->head, $list->tail->take($count-1));
}
+sub Take { # listy version
+ my ($list, $count) = @_;
+ return $list->empty unless $count;
+ return List->node($list->head, $list->tail->Take($count-1));
+}
sub While {
my ($list, $f) = @_;
@@ -137,9 +142,14 @@ sub isEmpty { 1 }
sub head { die "Empty lists have no head" }
sub tail { die "Empty lists have no tail" }
sub take { return () }
+sub Take { return shift }
sub Map { return shift }
sub Grep { return shift }
sub While { return __PACKAGE__->empty }
+sub concat {
+ my ($self, $list) = @_;
+ return $list;
+}
sub Foldl {
my ($self, $f, $init) = @_;
return $init;
@@ -42,7 +42,6 @@
}
}
-
{
my $kioku = KiokuDB->connect('hash');
my $scope = $kioku->new_scope;
@@ -53,6 +52,7 @@
$kioku->store(list => $list);
my $completions = $kioku->lookup('list')->Grep( sub { $_[0]->action eq 'completed' } );
+
my $high_score = $completions->Grep( sub { $_[0]->object >= 80 } );
$kioku->store(high_scores => $high_score);
@@ -0,0 +1,91 @@
+#!/usr/bin/perl
+
+use strict; use warnings;
+use List;
+use Data::Dumper;
+local $Data::Dumper::Indent = 1;
+local $Data::Dumper::Maxdepth = 2;
+
+# dummy modules for things we want to run feeds about
+use Feed;
+use Event;
+use User;
+use Module;
+use DateTime;
+
+use KiokuDB;
+
+{
+ my @modules = map { Module->new(id=>$_) } 1..10;
+ my @users = map { User ->new(id=>$_) } 1..10;
+
+ sub make_event {
+ my $date = shift || DateTime->now;
+ my $event = Event->new(
+ datestamp => $date,
+ user => $users[ int(rand(10)) ],
+ subject => $modules[ int(rand(10)) ],
+
+ ((rand > 0.5) ?
+ (
+ action => 'completed',
+ object => int(rand(100)),
+ )
+ :
+ (
+ action => 'started',
+ ))
+ );
+ }
+ sub make_event_list {
+ my $date = shift || DateTime->now;
+ return List->node(
+ make_event($date),
+ sub { make_event_list($date->clone->subtract( days => 1)) }
+ );
+ }
+}
+
+{
+ my $kioku = KiokuDB->connect('hash');
+ my $scope = $kioku->new_scope;
+
+ my $list = make_event_list()->Take(20);
+
+ my $root_list = Feed->new( list => $list, store_as => 'root' );
+ $root_list->store($kioku);
+
+ my $completions = Feed->new(
+ store_as => 'completions',
+ from_feed => 'root',
+ make_list => sub {
+ my $root = shift;
+ $root->Grep( sub { $_[0]->action eq 'completed' } );
+ },
+ );
+ $completions->update($kioku);
+ $completions->store($kioku);
+
+ my $high_score = Feed->new(
+ store_as => 'high_score',
+ from_feed => 'completions',
+ make_list => sub {
+ my $completions = shift;
+ $completions->Grep( sub { $_[0]->object >= 80 } );
+ }
+ );
+ $high_score->update($kioku);
+ $high_score->store($kioku);
+
+ my $h2 = $kioku->lookup( 'high_score' );
+ warn Dumper( [ $h2->list->take(2) ] );
+
+ # now, let's add some more events
+
+ for (1..10) {
+ $root_list->add_event( make_event() );
+ }
+
+ $high_score->update($kioku);
+ warn Dumper( [ $h2->list->take(5) ] ); # may be different from above
+}

0 comments on commit d91c071

Please sign in to comment.