]> ruin.nu Git - NDIRC.git/blobdiff - Commands/PA.pm
T2 is 70% and T3 is 50% now
[NDIRC.git] / Commands / PA.pm
index a71e897b3d6eb81239aaf4e861fa0d27c1d6ae80..8b64205c7af45f90b7ace83ba4730f7d491c28d2 100644 (file)
 #   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 #**************************************************************************/
 
-package NDIRC::Commands::PA;
-
 use strict;
 use warnings;
 use feature ':5.10';
 
-use Moose;
-use MooseX::MethodAttributes;
+use MooseX::Declare;
+use NDIRC::Dispatcher;
 
-use NDIRC::Misc;
-use ND::Include;
+command bcalc => {
+       help => q(Lists bcalc and stats info),
+}, class extends NDIRC::Command {
+       method execute($c,$msg) {
+               $c->reply("http://game.planetarion.com/bcalc.pl http://game.planetarion.com/manual.php?page=stats");
+       }
+};
 
-sub p
-       : Help(usage: .p X:Y:Z | or .p nick with high enough access)
-{
-       my ($self, $c, $msg) = @_;
+command p => {
+       help => q(usage: .p X:Y:Z | or .p nick with high enough access),
+       type => 'member',
+}, class extends NDIRC::Command {
+       method execute($c,$msg) {
 
-       my ($x,$y,$z,$nick);
-       if ($msg =~ /(\d+)\D+(\d+)\D+(\d+)/){
-               $x = $1;
-               $y = $2;
-               $z = $3;
-       }elsif ($msg && $c->check_user_roles(qw/irc_p_nick/)){
-               $nick = $msg;
-       }else{
-               die "ARGS";
-       }
-
-       my $f = $c->model->prepare(q{
-SELECT coords(x,y,z),ruler,planet,race,score,size,value,scorerank,sizerank,
-       valuerank, xp, xprank, alliance, relationship, nick, planet_status, hit_us, channel
-FROM current_planet_stats WHERE (x = $1 AND y = $2 and z = $3) OR nick ILIKE $4 LIMIT 1
-       });
-       $f->execute($x,$y,$z,$nick);
-       if (my $planet = $f->fetchrow_hashref()){
-               for (keys %{$planet}){
-                       $planet->{$_} = valuecolor(1,$planet->{$_});
+               my ($x,$y,$z,$nick);
+               if ($msg =~ /(\d+)\D+(\d+)\D+(\d+)/){
+                       $x = $1;
+                       $y = $2;
+                       $z = $3;
+               }elsif ($msg && $c->check_user_roles(qw/irc_p_nick/)){
+                       $nick = $msg;
+               }else{
+                       die "ARGS";
                }
-               my $ally = "";
-               if ($c->check_user_roles(qw/irc_p_intel/)){
-                       $ally = "Alliance=$planet->{alliance} ($planet->{relationship}), Nick=$planet->{nick} ($planet->{planet_status}), Channel: $planet->{channel}, Hostile Count: $planet->{hit_us},";
+
+               my $f = $c->model->prepare(q{
+WITH p AS (SELECT pid,coords(x,y,z),ruler,planet,race,score,size,value,scorerank,sizerank,
+               valuerank, xp, xprank, alliance, relationship, nick, planet_status, hit_us, channel
+       FROM current_planet_stats
+       WHERE (x = $1 AND y = $2 and z = $3) OR nick ILIKE $4 LIMIT 1
+), t AS (SELECT tag,bool_or(uid = $5) AS own,max(time) AS time
+       FROM planet_tags
+       WHERE pid = (SELECT pid FROM p)
+               AND ($6 OR uid = $5)
+       GROUP BY tag
+       ORDER BY time DESC
+), tags AS (SELECT array_to_string(array_agg(tag || CASE WHEN own THEN '*' ELSE '' END),' ') AS tags
+       FROM t
+)
+SELECT * FROM p, tags;
+                       });
+               $f->execute($x,$y,$z,$nick,$c->uid,$c->check_user_roles(qw/irc_p_intel/) // 0);
+               if (my $planet = $f->fetchrow_hashref()){
+                       for (keys %{$planet}){
+                               $planet->{$_} = $c->valuecolor(1,$planet->{$_});
+                       }
+                       my $ally = "";
+                       if ($c->check_user_roles(qw/irc_p_intel/)){
+                               $ally = "Alliance=$planet->{alliance} ($planet->{relationship}), Nick=$planet->{nick} ($planet->{planet_status}), Channel: $planet->{channel}, Hostile Count: $planet->{hit_us},";
+                       }
+                       $c->reply("$planet->{coords} $planet->{ruler} OF $planet->{planet},$ally Race=$planet->{race}, Score=$planet->{score} ($planet->{scorerank}), Size=$planet->{size} ($planet->{sizerank}), Value=$planet->{value} ($planet->{valuerank}), XP=$planet->{xp} ($planet->{xprank}) TAGS: $planet->{tags}");
+               }else{
+                       $c->reply("Couldn't find planet: $msg");
                }
-               $c->reply("$planet->{coords} $planet->{ruler} OF $planet->{planet},$ally Race=$planet->{race}, Score=$planet->{score} ($planet->{scorerank}), Size=$planet->{size} ($planet->{sizerank}), Value=$planet->{value} ($planet->{valuerank}), XP=$planet->{xp} ($planet->{xprank})");
-       }else{
-               $c->reply("Couldn't find planet: $msg");
        }
-}
+};
 
-sub g
-       : Help(usage: .g X:Y)
-{
-       my ($self, $c, $msg) = @_;
+command g => {
+       help => q(usage: .g X:Y),
+}, class extends NDIRC::Command {
+       method execute($c,$msg) {
 
-       my ($x,$y) = ($msg =~ /(\d+)\D+(\d+)/) or die 'ARGS';
+               my ($x,$y) = ($msg =~ /(\d+)\D+(\d+)/) or die 'ARGS';
+               my $dbh = $c->model;
 
-       my $f = $c->model->prepare(q{
-SELECT score,scorerank,size,sizerank,value,valuerank,planets
-FROM galaxies WHERE x = ? AND y = ? AND tick = (SELECT max(tick) from galaxies)
-       });
-       $f->execute($x,$y);
-       while (my @row = $f->fetchrow()){
-               @row = map (valuecolor(1),@row);
-               $c->reply("$x:$y  Score=$row[0] ($row[1]), Size=$row[2] ($row[3]), Value=$row[4] ($row[5]), Planets=$row[6]");
+               my $f = $dbh->prepare(q{
+                       SELECT score,scorerank,size,sizerank,value,valuerank,planets
+                       FROM galaxies WHERE x = ? AND y = ? AND tick = (SELECT max(tick) from galaxies)
+                       });
+               $f->execute($x,$y);
+               my @row = $f->fetchrow;
+               unless (@row){
+                       $c->reply("No galaxy at $x:$y");
+                       return;
+               }
+               my @planets;
+               if ($c->check_user_roles(qw/irc_g_intel/)) {
+                       my $query = $dbh->prepare(q{
+SELECT z,COALESCE(nick,'?') AS nick,COALESCE(alliance,'?') AS alliance
+FROM current_planet_stats
+WHERE x = $1 AND y = $2 ORDER BY z
+                               });
+                       $query->execute($x,$y);
+                       while(my $p = $query->fetchrow_hashref){
+                               push @planets, "$p->{z} [$p->{nick}/$p->{alliance}]";
+                       }
+               }
+               @row = map ($c->valuecolor(1),@row);
+               $c->reply("$x:$y  Score=$row[0] ($row[1]), Size=$row[2] ($row[3]), Value=$row[4] ($row[5]), Planets=$row[6] - "
+                       . join " ", @planets);
        }
-}
+};
 
-sub time
-       : Help(syntax: .time [tick] [timezone] | Gives the time at the specied tick. Assumes GMT if no timezone is given and current tick if no tick is given.)
-{
-       my ($self, $c, $msg) = @_;
+command time => {
+       help => q(syntax: .time [tick] [timezone] | Gives the time at the specied tick. Assumes GMT if no timezone is given and current tick if no tick is given.),
+}, class extends NDIRC::Command {
+       method execute($c,$msg) {
        my ($tick,$timezone) = $msg =~ /^(\d+)?\s*(\S+)?$/ or die 'ARGS';
 
        eval {
@@ -105,29 +139,32 @@ SELECT date_trunc('seconds',now() + (($1 - tick()) || ' hr')::interval) AT TIME
                }
                die $@ if $@;
        }
-}
+       }
+};
 
-sub xp
-       : Help(syntax: .xp X:Y:Z [roids] [cap] | if roids < 10 then it's taken as the wave, cap is a floating point number, defaults to 0.25)
-{
-       my ($self, $c, $msg) = @_;
+command xp => {
+       help => q(syntax: .xp X:Y:Z [roids] [cap] | if roids < 10 then it's taken as the wave, cap is a floating point number, defaults to cap according to your value),
+}, class extends NDIRC::Command {
+       use POSIX qw/pow/;
+       use ND::Include;
+       method execute($c,$msg) {
 
        my ($x,$y,$z,$roids,$cap) = $msg =~ /^(\d+)\D+(\d+)\D+(\d+)(?:[^\.\d]+(\d+))?(?:[^\.\d]+(\d*\.\d+))?$/
                or die 'ARGS';
 
        my ($avalue,$ascore) = $c->model->selectrow_array(q{
 SELECT value,score FROM current_planet_stats
-WHERE id = (SELECT planet FROM users WHERE hostmask ILIKE ?)
-               }, undef, $c->host);
+WHERE pid = (SELECT pid FROM users WHERE uid = ?)
+               }, undef, $c->uid);
        my ($tvalue,$tscore,$tsize) = $c->model->selectrow_array(q{
 SELECT value,score,size FROM current_planet_stats
 WHERE x = ? AND y = ? and z = ?
                }, undef, $x,$y,$z);
-       $cap //= 0.25;
+       $cap //= min(0.25,0.25 * pow($tvalue/$avalue , 0.5));
        unless($roids){
                $roids = int($tsize*$cap);
        }elsif ($roids < 10){
-               $tsize = ceil($tsize*.75**($roids-1));
+               $tsize = int($tsize*.75**($roids-1));
                $roids = int($cap*$tsize);
        }
        $tsize -= $roids;
@@ -143,7 +180,188 @@ WHERE x = ? AND y = ? and z = ?
        my $score = 60 * $xp;
        my $value = $roids*200;
        my $totscore = prettyValue($score + $value);
-       $c->reply("You will gain <b>$xp</b> XP, <b>$score</b> score, if you steal $roids roids (<b>$value</b> value), from <b>$x:$y:$z</b>, who will have <b>$tsize</b> roids left, total score gain will be: <b>$totscore</b> in total,");
-}
+       $cap = sprintf "%.1f", $cap*100;
+       $c->reply("You will gain <b>$xp</b> XP, <b>$score</b> score, if you steal <b>$roids</b> roids (<b>$value</b> value, <b>$cap%</b> cap), from <b>$x:$y:$z</b>, who will have <b>$tsize</b> roids left, total score gain will be: <b>$totscore</b> in total,");
+       }
+};
+
+command fco => {
+       help => q(syntax: .fco agents stolen [tick] | tick can be omitted if you're doing this the same tick you got cov opped, if you have different amount of your resources stolen, specify the highest amount. Only works if less than 10% of your resources and < 10,000*agents were stolen),
+}, class extends NDIRC::Command {
+       method execute($c,$msg) {
 
+       my ($agents,$stolen,$tick) = $msg =~ /^(\d+)\s+(\d+)\s*(\d+)?$/ or die 'ARGS';
+
+       $tick //= $c->model->selectrow_array(q{SELECT tick()});
+
+       my ($value,$score) = $c->model->selectrow_array(q{
+SELECT value,score FROM planet_stats WHERE tick = $2 AND
+       pid = (SELECT pid FROM users WHERE uid = $1)
+               }, undef, $c->uid,$tick);
+       unless ($value){
+               $c->reply("You don't have a planet registered.");
+               return;
+       }
+       my $attackers = $c->model->prepare(q{
+SELECT coords(p.x,p.y,p.z), ruler, planet FROM current_planet_stats p
+       JOIN planet_stats ps using (pid)
+WHERE ps.tick = $1 AND trunc(2000.0*$2*$3/ps.value)::int = $4
+               });
+       $attackers->execute($tick,$agents,$value,$stolen);
+       if ($attackers->rows == 0){
+               $c->reply("No cov opper found, did you specify the right tick, and was the stolen amount not capped?");
+       }else{
+               my $coords = '';
+               while (my $attacker = $attackers->fetchrow_hashref){
+                       $coords .= " ($attacker->{coords} : $attacker->{ruler} OF $attacker->{planet})";
+               }
+               $c->reply("The planet that cov opped you is one of: $coords");
+       }
+       }
+};
+
+my $eff = class extends NDIRC::Command {
+       use ND::Include;
+       method execute($c,$msg) {
+               my ($amount,$ship,$target) = $msg =~ /^(-?\d+(?:\.\d+)?[hkMG]?) ([\w\%]+)(?: (\w+))?/
+                       or die 'ARGS';
+
+               $ship = "$ship\%";
+               $target //= '%';
+               my $value;
+               if ($self->name =~ /^v.+$/){
+                       $value = parseValue($amount);
+                       $value *= -1.5 if $value < 0;
+               }else{
+                       $amount = parseValue($amount);
+               }
+
+               my $feud = '';
+
+               my $s= $c->model->selectrow_hashref(q{
+SELECT ship,t1,t2,t3,"type",damage
+       ,metal+crystal+eonium AS cost
+       ,init,"class",guns,race,eres,armor
+FROM ship_stats WHERE ship ILIKE ?
+                       }, undef, $ship);
+
+               return unless $s;
+
+               if (defined $value){
+                       $amount = int(($value*100/$s->{cost}));
+                       $feud = '(Dem/Tot: '.prettyValue(int($amount/0.92)).') ';
+               }
+               $value = prettyValue(($amount*$s->{cost}/100));
+               my $name = shipColor($s->{ship},$s->{type});
+               my $text = prettyValue($amount)." $feud $name ($s->{init}:$value) :";
+               for my $tn ('t1','t2','t3'){
+                       next unless defined ($self->target($s,$tn));
+                       $text .= " <b><c03>" . $self->target($s,$tn) . "</c></b>: ";
+                       my $st = $self->query(q{
+SELECT ship,"class","type",armor
+       ,metal+crystal+eonium AS cost
+       ,init,t1,t2,t3,eres,race
+       ,damage,guns
+FROM ship_stats
+                               },$c,$s,$tn,$target);
+                       while (my $t = $st->fetchrow_hashref()){
+                               my $number = $self->calcEff($s,$t,$tn,$amount);
+                               $value = prettyValue($number*$t->{cost}/100);
+                               my $name = shipColor($t->{ship},$t->{type});
+                               $text .= " <b>$number</b> $name ($t->{init}:$value),";
+                       }
+                       chop $text;
+               }
+               $c->reply($text);
+       }
+
+       method calcEff ($s,$t,$tn,$amount) {
+               my $number = int($self->amount($s,$t,$tn,$amount));
+
+               for my $tn ('t1','t2','t3'){
+                       my ($s1,$t1) = $self->shipOrder($s,$t);
+                       next unless (defined $t1->{$tn});
+                       next unless ($t1->{$tn} eq $s1->{class});
+
+                       if($t1->{init} <= $s1->{init}){
+                               $t->{init} = "<c04>$t->{init}</c>";
+                       }else{
+                               $t->{init} = "<c12>$t->{init}</c>";
+                       }
+               }
+               return $number;
+       }
+
+       sub shipColor {
+               my ($string,$type) = @_;
+               my $c = 04;
+               $c = 12 if $type eq 'EMP';
+               $c = 13 if $type eq 'Steal';
+               return "<c$c>$string</c>";
+       }
+
+       method amount ($s,$t,$tn,$amount) {
+               my $number = $s->{type} eq 'EMP' ?
+                       ($amount*$s->{guns}*(100-$t->{eres})/100)
+                       : ($amount*$s->{damage}/$t->{armor});
+               $number *= 0.70 if $tn eq 't2';
+               $number *= 0.50 if $tn eq 't3';
+               return $number;
+       }
+
+       method target ($s,$tn) {
+               return $s->{$tn};
+       }
+
+       method query ($st,$c,$s,$tn,$target) {
+               $st = $c->model->prepare($st . q{
+                       WHERE "class" = $1
+                       AND ("class" ILIKE $2 OR race ILIKE $2)
+                       });
+               $st->execute($s->{$tn},$target);
+               return $st;
+       }
+
+       method shipOrder ($s,$t) {
+               return ($s,$t);
+       }
+};
+
+command eff => {
+       alias => q/veff/,
+       help => q( syntax: .[v]eff amount ship [race|class] | Amount can use SI prefixes like k and M. Race or class is an optional argument, using the short form (i.e. Ter or Fi) | veff uses value instead of amount),
+}, $eff;
+
+command stop => {
+       alias => q/vstop/,
+       help => q( syntax: .[v]stop amount ship [race|class] | Amount can use SI prefixes like k and M. Race or class is an optional argument, using the short form (i.e. Ter or Fi) | vstop uses value instead of amount),
+}, class {
+       extends $eff->name;
+
+       method target ($s,$tn){
+               return $tn;
+       }
+
+       method query ($st,$c,$s,$tn,$target) {
+               $st = $c->model->prepare($st . qq{
+                       WHERE $tn = \$1
+                       AND ("class" ILIKE \$2 OR race ILIKE \$2)
+                       });
+               $st->execute($s->{class},$target);
+               return $st;
+       }
+
+       method amount ($s,$t,$tn,$amount) {
+               my $number = $t->{type} eq 'EMP' ?
+                       ($amount*100/(100 - $s->{eres})/$t->{guns})
+                       : ($amount*$s->{armor}/$t->{damage});
+               $number /= 0.60 if $tn eq 't2';
+               $number /= 0.30 if $tn eq 't3';
+               return $number;
+       }
+
+       method shipOrder ($s,$t) {
+               return ($t,$s);
+       }
+};
 1;