diff --git a/lib/Pear/LocalLoop/Command/recalc_leaderboards.pm b/lib/Pear/LocalLoop/Command/recalc_leaderboards.pm new file mode 100644 index 0000000..2573f67 --- /dev/null +++ b/lib/Pear/LocalLoop/Command/recalc_leaderboards.pm @@ -0,0 +1,26 @@ +package Pear::LocalLoop::Command::recalc_leaderboards; +use Mojo::Base 'Mojolicious::Command'; + +use Mojo::Util 'getopt'; + +has description => 'Build All leaderboards'; + +has usage => sub { shift->extract_usage }; + +sub run { + my ( $self, @args ) = @_; + + my $leaderboard_rs = $self->app->schema->resultset('Leaderboard'); + + $leaderboard_rs->recalculate_all; +} + +=head1 SYNOPSIS + + Usage: APPLICATION recalc_leaderboards + + Recalculates ALL leaderboards. + +=cut + +1; diff --git a/lib/Pear/LocalLoop/Schema/Result/Leaderboard.pm b/lib/Pear/LocalLoop/Schema/Result/Leaderboard.pm index e296d3f..480aaa4 100644 --- a/lib/Pear/LocalLoop/Schema/Result/Leaderboard.pm +++ b/lib/Pear/LocalLoop/Schema/Result/Leaderboard.pm @@ -184,7 +184,7 @@ sub _create_total_all_time { my @leaderboard; while ( my $user_result = $user_rs->next ) { - my $transaction_rs = $user_result->transactions; + my $transaction_rs = $user_result->transactions->search_before( $end ); my $transaction_sum = $transaction_rs->get_column('value')->sum; @@ -215,7 +215,7 @@ sub _create_count_all_time { my @leaderboard; while ( my $user_result = $user_rs->next ) { - my $transaction_rs = $user_result->transactions; + my $transaction_rs = $user_result->transactions->search_before( $end ); my $transaction_count = $transaction_rs->count; diff --git a/lib/Pear/LocalLoop/Schema/ResultSet/Leaderboard.pm b/lib/Pear/LocalLoop/Schema/ResultSet/Leaderboard.pm index d8fd9c6..a5ba33b 100644 --- a/lib/Pear/LocalLoop/Schema/ResultSet/Leaderboard.pm +++ b/lib/Pear/LocalLoop/Schema/ResultSet/Leaderboard.pm @@ -5,6 +5,8 @@ use warnings; use base 'DBIx::Class::ResultSet'; +use DateTime; + sub get_latest { my $self = shift; my $type = shift; @@ -39,4 +41,54 @@ sub find_by_type { return $self->find({ type => $type }); } +sub recalculate_all { + my $self = shift; + + for my $leaderboard_result ( $self->all ) { + my $lb_type = $leaderboard_result->type; + if ( $lb_type =~ /^daily/ ) { + + # Recalculating a daily set. This is calculated from the start of the + # day, so we need yesterdays date: + my $date = DateTime->today->subtract( days => 1 ); + $self->_recalculate_leaderboard( $leaderboard_result, $date, 'days' ); + + } elsif ( $lb_type =~ /^weekly/ ) { + + # Recalculating a weekly set. This is calculated from a Monday, of the + # week before. + my $date = DateTime->today->truncate( to => 'week' )->subtract( weeks => 1 ); + $self->_recalculate_leaderboard( $leaderboard_result, $date, 'weeks' ); + + } elsif ( $lb_type =~ /^monthly/ ) { + + # Recalculate a monthly set. This is calculated from the first of the + # month, for the month before. + my $date = DateTime->today->truncate( to => 'month' )->subtract( months => 1); + $self->_recalculate_leaderboard( $leaderboard_result, $date, 'months' ); + + } elsif ( $lb_type =~ /^all_time/ ) { + + # Recalculate for an all time set. This is calculated similarly to + # daily, but is calculated from an end time. + my $date = DateTime->today; + $self->_recalculate_leaderboard( $leaderboard_result, $date, 'days' ); + + } else { + warn "Unrecognised Set"; + } + } +} + +sub _recalculate_leaderboard { + my ( $self, $lb_result, $date, $diff ) = @_; + + $self->result_source->schema->txn_do( sub { + $lb_result->sets->related_resultset('values')->delete_all; + $lb_result->sets->delete_all; + $lb_result->create_new($date->clone->subtract( $diff => 1 )); + $lb_result->create_new($date); + }); +} + 1;