Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 139 additions & 91 deletions lib/Bracket/Model/DBIC.pm
Original file line number Diff line number Diff line change
Expand Up @@ -155,34 +155,63 @@ sub _update_points_portable {

my @perfect_picks = $schema->resultset('Pick')->search(
{ player => 1 },
{ columns => [qw/game pick/] }
{
columns => [qw/game pick/],
result_class => 'DBIx::Class::ResultClass::HashRefInflator',
}
)->all;
my %perfect_winner_for_game = map {
$_->get_column('game') => $_->get_column('pick')
$_->{game} => $_->{pick}
} @perfect_picks;

my %games = map {
$_->get_column('id') => $_
} $schema->resultset('Game')->search({})->all;
my %teams = map {
$_->get_column('id') => $_
} $schema->resultset('Team')->search({})->all;
my %game_round_for = map {
$_->{id} => $_->{round}
} $schema->resultset('Game')->search(
{},
{
columns => [qw/id round/],
result_class => 'DBIx::Class::ResultClass::HashRefInflator',
}
)->all;

my %team_seed_for = map {
$_->{id} => $_->{seed}
} $schema->resultset('Team')->search(
{},
{
columns => [qw/id seed/],
result_class => 'DBIx::Class::ResultClass::HashRefInflator',
}
)->all;

my %parent_games;
foreach my $edge ($schema->resultset('GameGraph')->search({}, { order_by => [qw/game parent_game/] })->all) {
push @{$parent_games{ $edge->get_column('game') }}, $edge->get_column('parent_game');
foreach my $edge ($schema->resultset('GameGraph')->search(
{},
{
columns => [qw/game parent_game/],
order_by => [qw/game parent_game/],
result_class => 'DBIx::Class::ResultClass::HashRefInflator',
}
)->all) {
push @{$parent_games{ $edge->{game} }}, $edge->{parent_game};
}

my %seeded_teams;
foreach my $row ($schema->resultset('GameTeamGraph')->search({}, { order_by => [qw/game team/] })->all) {
push @{$seeded_teams{ $row->get_column('game') }}, $row->get_column('team');
foreach my $row ($schema->resultset('GameTeamGraph')->search(
{},
{
columns => [qw/game team/],
order_by => [qw/game team/],
result_class => 'DBIx::Class::ResultClass::HashRefInflator',
}
)->all) {
push @{$seeded_teams{ $row->{game} }}, $row->{team};
}

my $current_round = 0;
foreach my $game_id (keys %perfect_winner_for_game) {
my $game = $games{$game_id};
next if !$game;
my $round = $game->get_column('round');
my $round = $game_round_for{$game_id};
next if !defined $round;
$current_round = $round if $round > $current_round;
}

Expand All @@ -191,103 +220,122 @@ sub _update_points_portable {
}

$schema->txn_do(sub {
foreach my $game_id (sort { $a <=> $b } keys %games) {
my $game = $games{$game_id};
next if !$game || $game->get_column('round') != $current_round;
my $winner_team_id = $perfect_winner_for_game{$game_id};
next if !$winner_team_id;

my $winner_team = $teams{$winner_team_id};
next if !$winner_team;

my $lower_seed = 0;
if ($game->get_column('round') == 1) {
$lower_seed = $winner_team->get_column('seed') > 8 ? 1 : 0;
}
else {
my @parents = @{$parent_games{$game_id} || []};
my @parent_winners = map { $perfect_winner_for_game{$_} } grep { exists $perfect_winner_for_game{$_} } @parents;
my $loser_team_id = first { defined $_ && $_ != $winner_team_id } @parent_winners;
if (defined $loser_team_id && $teams{$loser_team_id}) {
$lower_seed = $winner_team->get_column('seed') > $teams{$loser_team_id}->get_column('seed') ? 1 : 0;
$schema->storage->dbh_do(sub {
my ($storage, $dbh) = @_;
my $update_game = $dbh->prepare('update game set winner = ?, lower_seed = ? where id = ?');

foreach my $game_id (sort { $a <=> $b } keys %game_round_for) {
next if $game_round_for{$game_id} != $current_round;
my $winner_team_id = $perfect_winner_for_game{$game_id};
next if !$winner_team_id;
my $winner_seed = $team_seed_for{$winner_team_id};
next if !defined $winner_seed;

my $lower_seed = 0;
if ($game_round_for{$game_id} == 1) {
$lower_seed = $winner_seed > 8 ? 1 : 0;
}
else {
my @parents = @{$parent_games{$game_id} || []};
my @parent_winners = map { $perfect_winner_for_game{$_} } grep { exists $perfect_winner_for_game{$_} } @parents;
my $loser_team_id = first { defined $_ && $_ != $winner_team_id } @parent_winners;
my $loser_seed = defined $loser_team_id ? $team_seed_for{$loser_team_id} : undef;
if (defined $loser_seed) {
$lower_seed = $winner_seed > $loser_seed ? 1 : 0;
}
}
}

$game->update({
winner => $winner_team_id,
lower_seed => $lower_seed,
});
}
$update_game->execute($winner_team_id, $lower_seed, $game_id);
}
});
});
$current_time = time();
$times{lower_seed} = $current_time - $previous_time;
$previous_time = $current_time;

$schema->txn_do(sub {
foreach my $game_id (sort { $a <=> $b } keys %games) {
my $game = $games{$game_id};
next if !$game || $game->get_column('round') != $current_round;
my $winner_team_id = $perfect_winner_for_game{$game_id};
next if !$winner_team_id;

my $loser_team_id;
if ($current_round == 1) {
my @team_ids = @{$seeded_teams{$game_id} || []};
$loser_team_id = first { $_ != $winner_team_id } @team_ids;
}
else {
my @parents = @{$parent_games{$game_id} || []};
my @parent_winners = map { $perfect_winner_for_game{$_} } grep { exists $perfect_winner_for_game{$_} } @parents;
$loser_team_id = first { defined $_ && $_ != $winner_team_id } @parent_winners;
}
$schema->storage->dbh_do(sub {
my ($storage, $dbh) = @_;
my $update_team_round_out = $dbh->prepare('update team set round_out = ? where id = ?');

foreach my $game_id (sort { $a <=> $b } keys %game_round_for) {
next if $game_round_for{$game_id} != $current_round;
my $winner_team_id = $perfect_winner_for_game{$game_id};
next if !$winner_team_id;

my $loser_team_id;
if ($current_round == 1) {
my @team_ids = @{$seeded_teams{$game_id} || []};
$loser_team_id = first { $_ != $winner_team_id } @team_ids;
}
else {
my @parents = @{$parent_games{$game_id} || []};
my @parent_winners = map { $perfect_winner_for_game{$_} } grep { exists $perfect_winner_for_game{$_} } @parents;
$loser_team_id = first { defined $_ && $_ != $winner_team_id } @parent_winners;
}

next if !defined $loser_team_id || !$teams{$loser_team_id};
$teams{$loser_team_id}->update({ round_out => $current_round });
}
next if !defined $loser_team_id || !exists $team_seed_for{$loser_team_id};
$update_team_round_out->execute($current_round, $loser_team_id);
}
});
});
$current_time = time();
$times{round_out} = $current_time - $previous_time;
$previous_time = $current_time;

my %points_for;
foreach my $pick ($schema->resultset('Pick')->search({}, { prefetch => [qw/game pick/] })->all) {
my $game_id = $pick->get_column('game');
my $winner_team_id = $perfect_winner_for_game{$game_id};
next if !defined $winner_team_id || $winner_team_id != $pick->get_column('pick');

my $game_row = $pick->game;
my $team_row = $pick->pick;
my $points_for_pick = $game_row->get_column('round') *
(5 + $game_row->get_column('lower_seed') * $team_row->get_column('seed'));
$points_for{$pick->get_column('player')}{ $team_row->get_column('region') } += $points_for_pick;
}

$schema->txn_do(sub {
foreach my $player ($schema->resultset('Player')->search({})->all) {
my $player_id = $player->get_column('id');
foreach my $region_id (1 .. 4) {
my $points = $points_for{$player_id}{$region_id} || 0;
$schema->resultset('RegionScore')->update_or_create({
player => $player_id,
region => $region_id,
points => $points,
});
}
}
$schema->storage->dbh_do(sub {
my ($storage, $dbh) = @_;

$dbh->do('delete from region_score');
$dbh->do(q{
insert into region_score (player, region, points)
select
player.id,
region.id,
coalesce(player_region_points.points, 0) as points
from player
cross join region
left join (
select
player_picks.player as player,
team.region as region,
sum(game.round * (5 + game.lower_seed * team.seed)) as points
from pick player_picks
join pick perfect_picks
on perfect_picks.game = player_picks.game
and perfect_picks.pick = player_picks.pick
join game
on game.id = player_picks.game
join team
on team.id = player_picks.pick
where perfect_picks.player = 1
group by player_picks.player, team.region
) as player_region_points
on player_region_points.player = player.id
and player_region_points.region = region.id
});
});
});
$current_time = time();
$times{update_region_score} = $current_time - $previous_time;
$previous_time = $current_time;

$schema->txn_do(sub {
foreach my $player ($schema->resultset('Player')->search({})->all) {
my $player_id = $player->get_column('id');
my $total_points = 0;
foreach my $region_id (1 .. 4) {
$total_points += $points_for{$player_id}{$region_id} || 0;
}
$player->update({ points => $total_points });
}
$schema->storage->dbh_do(sub {
my ($storage, $dbh) = @_;
$dbh->do(q{
update player
set points = coalesce(
(
select sum(region_score.points)
from region_score
where region_score.player = player.id
),
0
)
});
});
});
$current_time = time();
$times{update_player_points} = $current_time - $previous_time;
Expand Down
4 changes: 4 additions & 0 deletions t/model_update_points.t
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,8 @@ is($all_region_scores, 4, 'portable path maintains all region score rows per pla
my $player_row = $schema->resultset('Player')->find($player->id);
is($player_row->get_column('points'), 47, 'player total points updated from region scores');

my $admin_region_scores = $schema->resultset('RegionScore')->search({ player => 2 })->count;
is($admin_region_scores, 4, 'portable path also creates zeroed region rows for players with no winning picks');
is($schema->resultset('Player')->find(2)->get_column('points'), 0, 'players without winning picks keep zero total points');

done_testing();
Loading