2017-05-23 23:06:07 +01:00
package Pear::LocalLoop::Schema::Result::Leaderboard ;
use strict ;
use warnings ;
use base 'DBIx::Class::Core' ;
use DateTime ;
__PACKAGE__ - > table ( "leaderboards" ) ;
__PACKAGE__ - > add_columns (
"id" = > {
data_type = > "integer" ,
is_auto_increment = > 1 ,
is_nullable = > 0 ,
} ,
"name" = > {
data_type = > "varchar" ,
size = > 255 ,
is_nullable = > 0 ,
} ,
"type" = > {
data_type = > "varchar" ,
size = > 255 ,
is_nullable = > 0 ,
} ,
) ;
__PACKAGE__ - > set_primary_key ( "id" ) ;
__PACKAGE__ - > add_unique_constraint ( [ "type" ] ) ;
__PACKAGE__ - > has_many (
"sets" ,
"Pear::LocalLoop::Schema::Result::LeaderboardSet" ,
{ "foreign.leaderboard_id" = > "self.id" } ,
{ cascade_copy = > 0 , cascade_delete = > 0 } ,
) ;
sub create_new {
my $ self = shift ;
my $ start = shift ;
my $ type = $ self - > type ;
if ( $ type eq 'daily_total' ) {
return $ self - > _create_total_set ( $ start , $ start - > clone - > add ( days = > 1 ) ) ;
} elsif ( $ type eq 'weekly_total' ) {
return $ self - > _create_total_set ( $ start , $ start - > clone - > add ( days = > 7 ) ) ;
} elsif ( $ type eq 'monthly_total' ) {
return $ self - > _create_total_set ( $ start , $ start - > clone - > add ( months = > 1 ) ) ;
} elsif ( $ type eq 'all_time_total' ) {
2017-06-05 22:59:31 +01:00
return $ self - > _create_total_all_time ( $ start ) ;
2017-05-23 23:06:07 +01:00
} elsif ( $ type eq 'daily_count' ) {
return $ self - > _create_count_set ( $ start , $ start - > clone - > add ( days = > 1 ) ) ;
} elsif ( $ type eq 'weekly_count' ) {
return $ self - > _create_count_set ( $ start , $ start - > clone - > add ( days = > 7 ) ) ;
} elsif ( $ type eq 'monthly_count' ) {
return $ self - > _create_count_set ( $ start , $ start - > clone - > add ( months = > 1 ) ) ;
} elsif ( $ type eq 'all_time_count' ) {
2017-06-05 22:59:31 +01:00
return $ self - > _create_count_all_time ( $ start ) ;
2017-05-23 23:06:07 +01:00
}
warn "Unrecognised type" ;
return $ self ;
}
2017-06-05 22:59:31 +01:00
sub _get_customer_rs {
my $ self = shift ;
2017-08-31 18:25:27 +01:00
return $ self - > result_source - > schema - > resultset ( 'Entity' ) - > search ( {
type = > 'customer' ,
2017-06-05 22:59:31 +01:00
} ) ;
}
2017-06-13 23:15:10 +01:00
sub _set_position_and_trend {
my ( $ self , @ leaderboard ) = @ _ ;
2017-05-23 23:06:07 +01:00
2017-06-13 23:15:10 +01:00
# Sort numerically descending
@ leaderboard = sort { $ b - > { value } <=> $ a - > { value } } @ leaderboard ;
2017-05-23 23:06:07 +01:00
2017-06-13 23:15:10 +01:00
my $ position = 0 ;
2017-05-23 23:06:07 +01:00
2017-06-06 22:30:02 +01:00
my $ previous_board = $ self - > get_latest ;
if ( defined $ previous_board ) {
$ previous_board = $ previous_board - > values ;
}
2017-05-23 23:06:07 +01:00
2017-06-13 23:15:10 +01:00
for my $ lb_val ( @ leaderboard ) {
$ position + + ;
$ lb_val - > { position } = $ position ;
2017-05-23 23:06:07 +01:00
2017-06-06 22:30:02 +01:00
my $ previous_value ;
if ( defined $ previous_board ) {
2017-08-31 18:25:27 +01:00
$ previous_value = $ previous_board - > find ( { entity_id = > $ lb_val - > { entity_id } } ) ;
2017-06-06 22:30:02 +01:00
}
my $ trend ;
if ( ! defined $ previous_value ) {
$ trend = 0 ;
2017-06-13 23:15:10 +01:00
} elsif ( $ previous_value - > position > $ position ) {
2017-06-06 22:30:02 +01:00
$ trend = - 1 ;
2017-06-13 23:15:10 +01:00
} elsif ( $ previous_value - > position < $ position ) {
2017-06-06 22:30:02 +01:00
$ trend = 1 ;
} else {
$ trend = 0 ;
}
2017-06-13 23:15:10 +01:00
$ lb_val - > { trend } = $ trend ;
}
return @ leaderboard ;
}
sub _create_total_set {
my ( $ self , $ start , $ end ) = @ _ ;
my $ user_rs = $ self - > _get_customer_rs ;
my @ leaderboard ;
while ( my $ user_result = $ user_rs - > next ) {
2017-08-31 18:25:27 +01:00
my $ transaction_rs = $ user_result - > purchases - > search_between ( $ start , $ end ) ;
2017-06-13 23:15:10 +01:00
my $ transaction_sum = $ transaction_rs - > get_column ( 'value' ) - > sum ;
2017-05-23 23:06:07 +01:00
push @ leaderboard , {
2017-08-31 18:25:27 +01:00
entity_id = > $ user_result - > id ,
2017-05-23 23:06:07 +01:00
value = > $ transaction_sum || 0 ,
} ;
}
2017-06-13 23:15:10 +01:00
@ leaderboard = $ self - > _set_position_and_trend ( @ leaderboard ) ;
2017-05-23 23:06:07 +01:00
$ self - > create_related (
'sets' ,
{
date = > $ start ,
values = > \ @ leaderboard ,
} ,
) ;
return $ self ;
}
sub _create_count_set {
my ( $ self , $ start , $ end ) = @ _ ;
2017-06-05 22:59:31 +01:00
my $ user_rs = $ self - > _get_customer_rs ;
2017-05-23 23:06:07 +01:00
my @ leaderboard ;
while ( my $ user_result = $ user_rs - > next ) {
2017-08-31 18:25:27 +01:00
my $ transaction_rs = $ user_result - > purchases - > search_between ( $ start , $ end ) ;
2017-05-23 23:06:07 +01:00
my $ transaction_count = $ transaction_rs - > count ;
push @ leaderboard , {
2017-08-31 18:25:27 +01:00
entity_id = > $ user_result - > id ,
2017-05-23 23:06:07 +01:00
value = > $ transaction_count || 0 ,
} ;
}
2017-06-13 23:15:10 +01:00
@ leaderboard = $ self - > _set_position_and_trend ( @ leaderboard ) ;
2017-05-23 23:06:07 +01:00
$ self - > create_related (
'sets' ,
{
date = > $ start ,
values = > \ @ leaderboard ,
} ,
) ;
return $ self ;
}
sub _create_total_all_time {
2017-06-05 22:59:31 +01:00
my ( $ self , $ end ) = @ _ ;
2017-05-23 23:06:07 +01:00
2017-06-05 22:59:31 +01:00
my $ user_rs = $ self - > _get_customer_rs ;
2017-05-23 23:06:07 +01:00
my @ leaderboard ;
while ( my $ user_result = $ user_rs - > next ) {
2017-08-31 18:25:27 +01:00
my $ transaction_rs = $ user_result - > purchases - > search_before ( $ end ) ;
2017-05-23 23:06:07 +01:00
my $ transaction_sum = $ transaction_rs - > get_column ( 'value' ) - > sum ;
push @ leaderboard , {
2017-08-31 18:25:27 +01:00
entity_id = > $ user_result - > id ,
2017-05-23 23:06:07 +01:00
value = > $ transaction_sum || 0 ,
} ;
}
2017-06-13 23:15:10 +01:00
@ leaderboard = $ self - > _set_position_and_trend ( @ leaderboard ) ;
2017-05-23 23:06:07 +01:00
$ self - > create_related (
'sets' ,
{
date = > $ end ,
values = > \ @ leaderboard ,
} ,
) ;
return $ self ;
}
sub _create_count_all_time {
2017-06-05 22:59:31 +01:00
my ( $ self , $ end ) = @ _ ;
2017-05-23 23:06:07 +01:00
2017-06-05 22:59:31 +01:00
my $ user_rs = $ self - > _get_customer_rs ;
2017-05-23 23:06:07 +01:00
my @ leaderboard ;
while ( my $ user_result = $ user_rs - > next ) {
2017-08-31 18:25:27 +01:00
my $ transaction_rs = $ user_result - > purchases - > search_before ( $ end ) ;
2017-05-23 23:06:07 +01:00
my $ transaction_count = $ transaction_rs - > count ;
push @ leaderboard , {
2017-08-31 18:25:27 +01:00
entity_id = > $ user_result - > id ,
2017-05-23 23:06:07 +01:00
value = > $ transaction_count || 0 ,
} ;
}
2017-06-13 23:15:10 +01:00
@ leaderboard = $ self - > _set_position_and_trend ( @ leaderboard ) ;
2017-05-23 23:06:07 +01:00
$ self - > create_related (
'sets' ,
{
date = > $ end ,
values = > \ @ leaderboard ,
} ,
) ;
return $ self ;
}
sub get_latest {
my $ self = shift ;
2017-06-05 22:15:27 +01:00
my $ latest = $ self - > search_related ( 'sets' , { } , {
order_by = > { - desc = > 'date' } ,
} ) - > first ;
return $ latest ;
2017-05-23 23:06:07 +01:00
}
1 ;