3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-10-04 10:28:45 +02:00

Spinach: Rename Stats.pm and Statskeeper.pm

This commit is contained in:
Pragmatic Software 2019-04-24 23:04:09 -07:00
parent 1c5ed2fb0e
commit 59b5f61de3
4 changed files with 351 additions and 350 deletions

View File

@ -30,8 +30,8 @@ $Data::Dumper::Useqq = 1;
use PBot::HashObject;
use PBot::Plugins::Spinach::Statskeeper;
use PBot::Plugins::Spinach::Stats;
use PBot::Plugins::Spinach::Rank;
sub new {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref $_[1] eq 'HASH';
@ -63,8 +63,8 @@ sub initialize {
$self->{metadata} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Spinach Metadata', filename => $self->{metadata_filename});
$self->load_metadata;
$self->{stats} = PBot::Plugins::Spinach::Statskeeper->new(filename => $self->{stats_filename});
$self->{statscmd} = PBot::Plugins::Spinach::Stats->new(pbot => $self->{pbot}, channel => $self->{channel}, filename => $self->{stats_filename});
$self->{stats} = PBot::Plugins::Spinach::Stats->new(filename => $self->{stats_filename});
$self->{rankcmd} = PBot::Plugins::Spinach::Rank->new(pbot => $self->{pbot}, channel => $self->{channel}, filename => $self->{stats_filename});
$self->create_states;
$self->load_questions;
@ -854,7 +854,7 @@ sub spinach_cmd {
}
when ('rank') {
return $self->{statscmd}->rank($arguments);
return $self->{rankcmd}->rank($arguments);
}
default {
@ -2044,6 +2044,7 @@ sub showfinalscore {
if ($i == 4) {
$mentions = "Honorable mentions: $mentions";
}
$self->{stats}->update_player_data($player_id, $player_data);
$i--;
next;
} elsif ($i == 3) {

View File

@ -0,0 +1,215 @@
#!/usr/bin/env perl
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
package PBot::Plugins::Spinach::Rank;
use warnings;
use strict;
use FindBin;
use lib "$FindBin::RealBin/../../..";
use PBot::Plugins::Spinach::Stats;
sub new {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref $_[1] eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
}
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{channel} = $conf{channel} // Carp::croak("Missing channel reference to " . __FILE__);
$self->{filename} = $conf{filename} // 'stats.sqlite';
$self->{stats} = PBot::Plugins::Spinach::Stats->new(filename => $self->{filename});
}
sub sort_generic {
my ($self, $key) = @_;
if ($self->{rank_direction} eq '+') {
return $b->{$key} <=> $a->{$key};
} else {
return $a->{$key} <=> $b->{$key};
}
}
sub print_generic {
my ($self, $key, $player) = @_;
return undef if $player->{games_played} == 0;
return "$player->{nick}: $player->{$key}";
}
sub sort_bad_lies {
my ($self) = @_;
if ($self->{rank_direction} eq '+') {
return $b->{questions_played} - $b->{good_lies} <=> $a->{questions_played} - $a->{good_lies};
} else {
return $a->{questions_played} - $a->{good_lies} <=> $b->{questions_played} - $b->{good_lies};
}
}
sub print_bad_lies {
my ($self, $player) = @_;
return undef if $player->{games_played} == 0;
my $result = $player->{questions_played} - $player->{good_lies};
return "$player->{nick}: $result";
}
sub sort_mentions {
my ($self) = @_;
if ($self->{rank_direction} eq '+') {
return $b->{games_played} - $b->{times_first} - $b->{times_second} - $b->{times_third} <=>
$a->{games_played} - $a->{times_first} - $a->{times_second} - $a->{times_third};
} else {
return $a->{games_played} - $a->{times_first} - $a->{times_second} - $a->{times_third} <=>
$b->{games_played} - $b->{times_first} - $b->{times_second} - $b->{times_third};
}
}
sub print_mentions {
my ($self, $player) = @_;
return undef if $player->{games_played} == 0;
my $result = $player->{games_played} - $player->{times_first} - $player->{times_second} - $player->{times_third};
return "$player->{nick}: $result";
}
sub rank {
my ($self, $arguments) = @_;
my %ranks = (
highscore => { sort => sub { $self->sort_generic('high_score', @_) }, print => sub { $self->print_generic('high_score', @_) }, title => 'high score' },
lowscore => { sort => sub { $self->sort_generic('low_score', @_) }, print => sub { $self->print_generic('low_score', @_) }, title => 'low score' },
avgscore => { sort => sub { $self->sort_generic('avg_score', @_) }, print => sub { $self->print_generic('avg_score', @_) }, title => 'average score' },
goodlies => { sort => sub { $self->sort_generic('good_lies', @_) }, print => sub { $self->print_generic('good_lies', @_) }, title => 'good lies' },
badlies => { sort => sub { $self->sort_bad_lies(@_) }, print => sub { $self->print_bad_lies(@_) }, title => 'bad lies' },
first => { sort => sub { $self->sort_generic('times_first', @_) }, print => sub { $self->print_generic('times_first', @_) }, title => 'first place' },
second => { sort => sub { $self->sort_generic('times_second', @_) }, print => sub { $self->print_generic('times_second', @_) }, title => 'second place' },
third => { sort => sub { $self->sort_generic('times_third', @_) }, print => sub { $self->print_generic('times_third', @_) }, title => 'third place' },
mentions => { sort => sub { $self->sort_mentions(@_) }, print => sub { $self->print_mentions(@_) }, title => 'mentions' },
games => { sort => sub { $self->sort_generic('games_played', @_) }, print => sub { $self->print_generic('games_played', @_) }, title => 'games played' },
questions => { sort => sub { $self->sort_generic('questions_played', @_) }, print => sub { $self->print_generic('questions_played', @_) }, title => 'questions played' },
goodguesses => { sort => sub { $self->sort_generic('good_guesses', @_) }, print => sub { $self->print_generic('good_guesses', @_) }, title => 'good guesses' },
badguesses => { sort => sub { $self->sort_generic('bad_guesses', @_) }, print => sub { $self->print_generic('bad_guesses', @_) }, title => 'bad guesses' },
deceptions => { sort => sub { $self->sort_generic('players_deceived', @_) }, print => sub { $self->print_generic('players_deceived', @_) }, title => 'players deceived' },
);
my @order = qw/highscore lowscore avgscore first second third mentions games questions goodlies badlies deceptions goodguesses badguesses/;
if (not $arguments) {
my $result = "Usage: rank [-]<keyword> [offset] or rank [-]<nick>; available keywords: ";
$result .= join ', ', @order;
$result .= ".\n";
$result .= "Prefix with a dash to invert sort.\n";
return $result;
}
$arguments = lc $arguments;
if ($arguments =~ s/^([+-])//) {
$self->{rank_direction} = $1;
} else {
$self->{rank_direction} = '+';
}
my $offset = 1;
if ($arguments =~ s/\s+(\d+)$//) {
$offset = $1;
}
if (not exists $ranks{$arguments}) {
$self->{stats}->begin;
my $player_id = $self->{stats}->get_player_id($arguments, $self->{channel}, 1);
my $player_data = $self->{stats}->get_player_data($player_id);
if (not defined $player_id) {
$self->{stats}->end;
return "I don't know anybody named $arguments.";
}
my $players = $self->{stats}->get_all_players($self->{channel});
my @rankings;
foreach my $key (@order) {
my $sort_method = $ranks{$key}->{sort};
@$players = sort $sort_method @$players;
my $rank = 0;
my $stats;
my $last_value = -1;
foreach my $player (@$players) {
$stats = $ranks{$key}->{print}->($player);
if (defined $stats) {
my ($value) = $stats =~ /[^:]+:\s+(.*)/;
$rank++ if $value ne $last_value;
$last_value = $value;
} else {
$rank++ if lc $player->{nick} eq $arguments;
}
last if lc $player->{nick} eq $arguments;
}
if (not $rank) {
push @rankings, "$ranks{key}->{title}: N/A";
} else {
if (not $stats) {
push @rankings, "$ranks{$key}->{title}: N/A";
} else {
$stats =~ s/[^:]+:\s+//;
push @rankings, "$ranks{$key}->{title}: #$rank ($stats)";
}
}
}
my $result = "$player_data->{nick}'s rankings: ";
$result .= join ', ', @rankings;
$self->{stats}->end;
return $result;
}
$self->{stats}->begin;
my $players = $self->{stats}->get_all_players($self->{channel});
my $sort_method = $ranks{$arguments}->{sort};
@$players = sort $sort_method @$players;
my @ranking;
my $rank = 0;
my $last_value = -1;
foreach my $player (@$players) {
my $entry = $ranks{$arguments}->{print}->($player);
if (defined $entry) {
my ($value) = $entry =~ /[^:]+:\s+(.*)/;
$rank++ if $value ne $last_value;
$last_value = $value;
next if $rank < $offset;
push @ranking, "#$rank $entry" if defined $entry;
last if scalar @ranking >= 15;
}
}
my $result;
if (not scalar @ranking) {
if ($offset > 1) {
$result = "No rankings available for $self->{channel} at offset #$offset.\n";
} else {
$result = "No rankings available for $self->{channel} yet.\n";
}
} else {
$result = "Rankings for $ranks{$arguments}->{title}: ";
$result .= join ', ', @ranking;
}
$self->{stats}->end;
return $result;
}
1;

View File

@ -9,13 +9,12 @@ package PBot::Plugins::Spinach::Stats;
use warnings;
use strict;
use FindBin;
use lib "$FindBin::RealBin/../../..";
use DBI;
use Carp qw(shortmess);
use PBot::Plugins::Spinach::Statskeeper;
my $debug = 0;
sub new {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref $_[1] eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
@ -24,192 +23,149 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{channel} = $conf{channel} // Carp::croak("Missing channel reference to " . __FILE__);
$self->{filename} = $conf{filename} // 'stats.sqlite';
$self->{stats} = PBot::Plugins::Spinach::Statskeeper->new(filename => $self->{filename});
}
sub sort_generic {
my ($self, $key) = @_;
if ($self->{rank_direction} eq '+') {
return $b->{$key} <=> $a->{$key};
} else {
return $a->{$key} <=> $b->{$key};
sub begin {
my $self = shift;
print STDERR "Opening stats SQLite database: $self->{filename}\n" if $debug;
$self->{dbh} = DBI->connect("dbi:SQLite:dbname=$self->{filename}", "", "", { RaiseError => 1, PrintError => 0 }) or die $DBI::errstr;
eval {
$self->{dbh}->do(<< 'SQL');
CREATE TABLE IF NOT EXISTS Stats (
id INTEGER PRIMARY KEY,
nick TEXT NOT NULL COLLATE NOCASE,
channel TEXT NOT NULL COLLATE NOCASE,
high_score INTEGER DEFAULT 0,
low_score INTEGER DEFAULT 0,
avg_score INTEGER DEFAULT 0,
times_first INTEGER DEFAULT 0,
times_second INTEGER DEFAULT 0,
times_third INTEGER DEFAULT 0,
good_lies INTEGER DEFAULT 0,
players_deceived INTEGER DEFAULT 0,
questions_played INTEGER DEFAULT 0,
games_played INTEGER DEFAULT 0,
good_guesses INTEGER DEFAULT 0,
bad_guesses INTEGER DEFAULT 0
)
SQL
};
print STDERR $@ if $@;
}
sub end {
my $self = shift;
print STDERR "Closing stats SQLite database\n" if $debug;
if(exists $self->{dbh} and defined $self->{dbh}) {
$self->{dbh}->disconnect();
delete $self->{dbh};
}
}
sub print_generic {
my ($self, $key, $player) = @_;
return undef if $player->{games_played} == 0;
return "$player->{nick}: $player->{$key}";
sub add_player {
my ($self, $nick, $channel) = @_;
my $id = eval {
my $sth = $self->{dbh}->prepare('INSERT INTO Stats (nick, channel) VALUES (?, ?)');
$sth->bind_param(1, $nick) ;
$sth->bind_param(2, $channel) ;
$sth->execute();
return $self->{dbh}->sqlite_last_insert_rowid();
};
print STDERR $@ if $@;
return $id;
}
sub sort_bad_lies {
my ($self) = @_;
if ($self->{rank_direction} eq '+') {
return $b->{questions_played} - $b->{good_lies} <=> $a->{questions_played} - $a->{good_lies};
} else {
return $a->{questions_played} - $a->{good_lies} <=> $b->{questions_played} - $b->{good_lies};
}
sub get_player_id {
my ($self, $nick, $channel, $dont_create_new) = @_;
my $id = eval {
my $sth = $self->{dbh}->prepare('SELECT id FROM Stats WHERE nick = ? AND channel = ?');
$sth->bind_param(1, $nick);
$sth->bind_param(2, $channel);
$sth->execute();
my $row = $sth->fetchrow_hashref();
return $row->{id};
};
print STDERR $@ if $@;
$id = $self->add_player($nick, $channel) if not defined $id and not $dont_create_new;
return $id;
}
sub print_bad_lies {
my ($self, $player) = @_;
return undef if $player->{games_played} == 0;
my $result = $player->{questions_played} - $player->{good_lies};
return "$player->{nick}: $result";
}
sub get_player_data {
my ($self, $id, @columns) = @_;
sub sort_mentions {
my ($self) = @_;
if ($self->{rank_direction} eq '+') {
return $b->{games_played} - $b->{times_first} - $b->{times_second} - $b->{times_third} <=>
$a->{games_played} - $a->{times_first} - $a->{times_second} - $a->{times_third};
} else {
return $a->{games_played} - $a->{times_first} - $a->{times_second} - $a->{times_third} <=>
$b->{games_played} - $b->{times_first} - $b->{times_second} - $b->{times_third};
}
}
my $player_data = eval {
my $sql = 'SELECT ';
sub print_mentions {
my ($self, $player) = @_;
return undef if $player->{games_played} == 0;
my $result = $player->{games_played} - $player->{times_first} - $player->{times_second} - $player->{times_third};
return "$player->{nick}: $result";
}
sub rank {
my ($self, $arguments) = @_;
my %ranks = (
highscores => { sort => sub { $self->sort_generic('high_score', @_) }, print => sub { $self->print_generic('high_score', @_) }, title => 'high scores' },
lowscores => { sort => sub { $self->sort_generic('low_score', @_) }, print => sub { $self->print_generic('low_score', @_) }, title => 'low scores' },
avgscores => { sort => sub { $self->sort_generic('avg_score', @_) }, print => sub { $self->print_generic('avg_score', @_) }, title => 'average scores' },
goodlies => { sort => sub { $self->sort_generic('good_lies', @_) }, print => sub { $self->print_generic('good_lies', @_) }, title => 'good lies' },
badlies => { sort => sub { $self->sort_bad_lies(@_) }, print => sub { $self->print_bad_lies(@_) }, title => 'bad lies' },
first => { sort => sub { $self->sort_generic('times_first', @_) }, print => sub { $self->print_generic('times_first', @_) }, title => 'first place' },
second => { sort => sub { $self->sort_generic('times_second', @_) }, print => sub { $self->print_generic('times_second', @_) }, title => 'second place' },
third => { sort => sub { $self->sort_generic('times_third', @_) }, print => sub { $self->print_generic('times_third', @_) }, title => 'third place' },
mentions => { sort => sub { $self->sort_mentions(@_) }, print => sub { $self->print_mentions(@_) }, title => 'mentions' },
games => { sort => sub { $self->sort_generic('games_played', @_) }, print => sub { $self->print_generic('games_played', @_) }, title => 'games played' },
questions => { sort => sub { $self->sort_generic('questions_played', @_) }, print => sub { $self->print_generic('questions_played', @_) }, title => 'questions played' },
goodguesses => { sort => sub { $self->sort_generic('good_guesses', @_) }, print => sub { $self->print_generic('good_guesses', @_) }, title => 'good guesses' },
badguesses => { sort => sub { $self->sort_generic('bad_guesses', @_) }, print => sub { $self->print_generic('bad_guesses', @_) }, title => 'bad guesses' },
deceptions => { sort => sub { $self->sort_generic('players_deceived', @_) }, print => sub { $self->print_generic('players_deceived', @_) }, title => 'players deceived' },
);
my @order = qw/highscores lowscores avgscores first second third mentions games questions goodlies badlies deceptions goodguesses badguesses/;
if (not $arguments) {
my $result = "Usage: rank [-]<keyword> [offset] or rank [-]<nick>; available keywords: ";
$result .= join ', ', @order;
$result .= ".\n";
$result .= "Prefix with a dash to invert sort.\n";
return $result;
}
$arguments = lc $arguments;
if ($arguments =~ s/^([+-])//) {
$self->{rank_direction} = $1;
} else {
$self->{rank_direction} = '+';
}
my $offset = 1;
if ($arguments =~ s/\s+(\d+)$//) {
$offset = $1;
}
if (not exists $ranks{$arguments}) {
$self->{stats}->begin;
my $player_id = $self->{stats}->get_player_id($arguments, $self->{channel}, 1);
my $player_data = $self->{stats}->get_player_data($player_id);
if (not defined $player_id) {
$self->{stats}->end;
return "I don't know anybody named $arguments.";
}
my $players = $self->{stats}->get_all_players($self->{channel});
my @rankings;
foreach my $key (@order) {
my $sort_method = $ranks{$key}->{sort};
@$players = sort $sort_method @$players;
my $rank = 0;
my $stats;
my $last_value = -1;
foreach my $player (@$players) {
$stats = $ranks{$key}->{print}->($player);
if (defined $stats) {
my ($value) = $stats =~ /[^:]+:\s+(.*)/;
$rank++ if $value ne $last_value;
$last_value = $value;
} else {
$rank++ if lc $player->{nick} eq $arguments;
}
last if lc $player->{nick} eq $arguments;
}
if (not $rank) {
push @rankings, "$ranks{key}->{title}: N/A";
} else {
if (not $stats) {
push @rankings, "$ranks{$key}->{title}: N/A";
} else {
$stats =~ s/[^:]+:\s+//;
push @rankings, "$ranks{$key}->{title}: #$rank ($stats)";
}
}
}
my $result = "$player_data->{nick}'s rankings: ";
$result .= join ', ', @rankings;
$self->{stats}->end;
return $result;
}
$self->{stats}->begin;
my $players = $self->{stats}->get_all_players($self->{channel});
my $sort_method = $ranks{$arguments}->{sort};
@$players = sort $sort_method @$players;
my @ranking;
my $rank = 0;
my $last_value = -1;
foreach my $player (@$players) {
my $entry = $ranks{$arguments}->{print}->($player);
if (defined $entry) {
my ($value) = $entry =~ /[^:]+:\s+(.*)/;
$rank++ if $value ne $last_value;
$last_value = $value;
next if $rank < $offset;
push @ranking, "#$rank $entry" if defined $entry;
last if scalar @ranking >= 15;
}
}
my $result;
if (not scalar @ranking) {
if ($offset > 1) {
$result = "No rankings available for $self->{channel} at offset #$offset.\n";
if(not @columns) {
$sql .= '*';
} else {
$result = "No rankings available for $self->{channel} yet.\n";
my $comma = '';
foreach my $column (@columns) {
$sql .= "$comma$column";
$comma = ', ';
}
}
} else {
$result = "Rankings for $ranks{$arguments}->{title}: ";
$result .= join ', ', @ranking;
}
$self->{stats}->end;
return $result;
$sql .= ' FROM Stats WHERE id = ?';
my $sth = $self->{dbh}->prepare($sql);
$sth->bind_param(1, $id);
$sth->execute();
return $sth->fetchrow_hashref();
};
print STDERR $@ if $@;
return $player_data;
}
sub update_player_data {
my ($self, $id, $data) = @_;
eval {
my $sql = 'UPDATE Stats SET ';
my $comma = '';
foreach my $key (keys %$data) {
$sql .= "$comma$key = ?";
$comma = ', ';
}
$sql .= ' WHERE id = ?';
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
foreach my $key (keys %$data) {
$sth->bind_param($param++, $data->{$key});
}
$sth->bind_param($param, $id);
$sth->execute();
};
print STDERR $@ if $@;
}
sub get_all_players {
my ($self, $channel) = @_;
my $players = eval {
my $sth = $self->{dbh}->prepare('SELECT * FROM Stats WHERE channel = ?');
$sth->bind_param(1, $channel);
$sth->execute();
return $sth->fetchall_arrayref({});
};
print STDERR $@ if $@;
return $players;
}
1;

View File

@ -1,171 +0,0 @@
#!/usr/bin/env perl
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
package PBot::Plugins::Spinach::Statskeeper;
use warnings;
use strict;
use DBI;
use Carp qw(shortmess);
my $debug = 0;
sub new {
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
}
sub initialize {
my ($self, %conf) = @_;
$self->{filename} = $conf{filename} // 'stats.sqlite';
}
sub begin {
my $self = shift;
print STDERR "Opening stats SQLite database: $self->{filename}\n" if $debug;
$self->{dbh} = DBI->connect("dbi:SQLite:dbname=$self->{filename}", "", "", { RaiseError => 1, PrintError => 0 }) or die $DBI::errstr;
eval {
$self->{dbh}->do(<< 'SQL');
CREATE TABLE IF NOT EXISTS Stats (
id INTEGER PRIMARY KEY,
nick TEXT NOT NULL COLLATE NOCASE,
channel TEXT NOT NULL COLLATE NOCASE,
high_score INTEGER DEFAULT 0,
low_score INTEGER DEFAULT 0,
avg_score INTEGER DEFAULT 0,
times_first INTEGER DEFAULT 0,
times_second INTEGER DEFAULT 0,
times_third INTEGER DEFAULT 0,
good_lies INTEGER DEFAULT 0,
players_deceived INTEGER DEFAULT 0,
questions_played INTEGER DEFAULT 0,
games_played INTEGER DEFAULT 0,
good_guesses INTEGER DEFAULT 0,
bad_guesses INTEGER DEFAULT 0
)
SQL
};
print STDERR $@ if $@;
}
sub end {
my $self = shift;
print STDERR "Closing stats SQLite database\n" if $debug;
if(exists $self->{dbh} and defined $self->{dbh}) {
$self->{dbh}->disconnect();
delete $self->{dbh};
}
}
sub add_player {
my ($self, $nick, $channel) = @_;
my $id = eval {
my $sth = $self->{dbh}->prepare('INSERT INTO Stats (nick, channel) VALUES (?, ?)');
$sth->bind_param(1, $nick) ;
$sth->bind_param(2, $channel) ;
$sth->execute();
return $self->{dbh}->sqlite_last_insert_rowid();
};
print STDERR $@ if $@;
return $id;
}
sub get_player_id {
my ($self, $nick, $channel, $dont_create_new) = @_;
my $id = eval {
my $sth = $self->{dbh}->prepare('SELECT id FROM Stats WHERE nick = ? AND channel = ?');
$sth->bind_param(1, $nick);
$sth->bind_param(2, $channel);
$sth->execute();
my $row = $sth->fetchrow_hashref();
return $row->{id};
};
print STDERR $@ if $@;
$id = $self->add_player($nick, $channel) if not defined $id and not $dont_create_new;
return $id;
}
sub get_player_data {
my ($self, $id, @columns) = @_;
my $player_data = eval {
my $sql = 'SELECT ';
if(not @columns) {
$sql .= '*';
} else {
my $comma = '';
foreach my $column (@columns) {
$sql .= "$comma$column";
$comma = ', ';
}
}
$sql .= ' FROM Stats WHERE id = ?';
my $sth = $self->{dbh}->prepare($sql);
$sth->bind_param(1, $id);
$sth->execute();
return $sth->fetchrow_hashref();
};
print STDERR $@ if $@;
return $player_data;
}
sub update_player_data {
my ($self, $id, $data) = @_;
eval {
my $sql = 'UPDATE Stats SET ';
my $comma = '';
foreach my $key (keys %$data) {
$sql .= "$comma$key = ?";
$comma = ', ';
}
$sql .= ' WHERE id = ?';
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
foreach my $key (keys %$data) {
$sth->bind_param($param++, $data->{$key});
}
$sth->bind_param($param, $id);
$sth->execute();
};
print STDERR $@ if $@;
}
sub get_all_players {
my ($self, $channel) = @_;
my $players = eval {
my $sth = $self->{dbh}->prepare('SELECT * FROM Stats WHERE channel = ?');
$sth->bind_param(1, $channel);
$sth->execute();
return $sth->fetchall_arrayref({});
};
print STDERR $@ if $@;
return $players;
}
1;