]> ruin.nu Git - ndwebbie.git/blob - lib/NDWeb/Controller/Stats.pm
Fix in case planets happens to be 0
[ndwebbie.git] / lib / NDWeb / Controller / Stats.pm
1 package NDWeb::Controller::Stats;
2
3 use strict;
4 use warnings;
5 use parent 'Catalyst::Controller';
6
7 use NDWeb::Include;
8 use HTML::TagCloud;
9
10 =head1 NAME
11
12 NDWeb::Controller::Stats - Catalyst Controller
13
14 =head1 DESCRIPTION
15
16 Catalyst Controller.
17
18 =head1 METHODS
19
20 =cut
21
22
23 =head2 index 
24
25 =cut
26
27 sub index :Path :Args(0) {
28     my ( $self, $c ) = @_;
29
30     $c->response->body('Matched NDWeb::Controller::Stats in Stats.');
31 }
32
33 sub galaxy : Local {
34         my ( $self, $c, $x, $y, $z ) = @_;
35         my $dbh = $c->model;
36
37         my $query = $dbh->prepare(q{
38 SELECT x,y
39         ,size, size_gain, size_gain_day
40         ,score,score_gain,score_gain_day
41         ,value,value_gain,value_gain_day
42         ,xp,xp_gain,xp_gain_day
43         ,sizerank,sizerank_gain,sizerank_gain_day
44         ,scorerank,scorerank_gain,scorerank_gain_day
45         ,valuerank,valuerank_gain,valuerank_gain_day
46         ,xprank,xprank_gain,xprank_gain_day
47         ,planets,planets_gain,planets_gain_day
48         ,ticks_roiding, ticks_roided
49         ,raid.tick AS last_raid, raid
50 FROM galaxies g
51         JOIN (SELECT x,y,count(CASE WHEN size_gain > 0 THEN 1 ELSE NULL END) AS ticks_roiding
52                         ,count(CASE WHEN size_gain < 0 THEN 1 ELSE NULL END) AS ticks_roided
53                 FROM galaxies GROUP BY x,y) ga USING (x,y)
54         LEFT OUTER JOIN (
55                 SELECT DISTINCT ON (x,y) x,y,raid, tick
56                 FROM (
57                         SELECT raid,p.tick,x,y,count(*), sum(size) AS size
58                         FROM raids r
59                                 JOIN raid_targets rt ON r.id = rt.raid
60                                 JOIN planet_stats p USING (pid)
61                         WHERE x = $1 and y = $2 AND p.tick = r.tick-12
62                         GROUP BY raid,p.tick,x,y
63                         ) AS a
64                         JOIN galaxies g USING (tick,x,y)
65                 WHERE a.count::float / NULLIF(g.planets,0) >= 0.5
66                 ORDER BY x,y,tick
67         ) AS raid USING (x,y)
68
69 WHERE g.tick = ( SELECT max(tick) AS max FROM galaxies)
70         AND x = $1 AND y = $2;
71                 });
72
73         $query->execute($x,$y);
74         my $g = $query->fetchrow_hashref;
75         $c->detach('/default') unless $g;
76         $c->stash(g => $g);
77
78
79         my $extra_columns = '';
80         if ($c->check_user_roles(qw/stats_intel/)){
81                 $c->stash(intel => 1);
82                 $extra_columns = ",planet_status,hit_us, alliance,relationship,nick";
83         }
84         if ($c->check_user_roles(qw/stats_details/)){
85                 $c->stash( details => 1);
86                 $extra_columns .= q{
87                         ,gov, p.value - p.size*200 -
88                         COALESCE(ps.metal+ps.crystal+ps.eonium,0)/150 -
89                         COALESCE(ds.total ,(SELECT COALESCE(avg(total),0)
90                                 FROM current_development_scans)::int)*1500 AS fleetvalue
91                         ,(metal+crystal+eonium)/100 AS resvalue
92                 };
93         }
94
95         $query = $dbh->prepare(qq{SELECT DISTINCT ON (x,y,z,pid)
96                 pid AS id,coords(x,y,z), ruler, p.planet,race,
97                 size, size_gain, size_gain_day,
98                 score,score_gain,score_gain_day,
99                 value,value_gain,value_gain_day,
100                 xp,xp_gain,xp_gain_day,
101                 sizerank,sizerank_gain,sizerank_gain_day,
102                 scorerank,scorerank_gain,scorerank_gain_day,
103                 valuerank,valuerank_gain,valuerank_gain_day,
104                 xprank,xprank_gain,xprank_gain_day
105                 $extra_columns
106                 FROM current_planet_stats_full p
107                         LEFT OUTER JOIN planet_scans ps USING (pid)
108                         LEFT OUTER JOIN current_development_scans ds USING (pid)
109                 WHERE x = ? AND y = ? AND COALESCE(z = ?,TRUE)
110                 ORDER BY x,y,z,pid,ps.tick DESC, ps.id DESC, ds.tick DESC, ds.id DESC
111                 });
112
113         $query->execute($x,$y,$z);
114         $c->stash(planets => $query->fetchall_arrayref({}) );
115
116         $query = $dbh->prepare(q{
117 WITH p AS (
118         SELECT x,y FROM galaxies
119         WHERE tick = tick() AND (x <= $1 AND y < $2 OR x < $1)
120         ORDER BY x DESC, y DESC LIMIT 1
121 ), n AS (
122         SELECT x,y FROM galaxies
123         WHERE tick = tick() AND (x >= $1 AND y > $2 OR x > $1)
124         ORDER BY x ASC, y ASC LIMIT 1
125 )
126 TABLE p UNION TABLE n
127                 });
128         $query->execute($x,$y);
129         $c->stash(browse => $query->fetchall_arrayref({}) );
130 }
131
132 sub planet : Local {
133         my ( $self, $c, $id ) = @_;
134         my $dbh = $c->model;
135
136         my $p = $dbh->selectrow_hashref(q{SELECT pid AS id,x,y,z FROM current_planet_stats
137                 WHERE pid = $1},undef,$id);
138
139         $c->detach('/default') unless $p;
140
141         $c->forward('galaxy',[$p->{x},$p->{y},$p->{z}]);
142         $c->stash(p => $p);
143
144         if ($c->check_user_roles(qw/stats_missions/)){
145                 my $query = $dbh->prepare(q{
146 (
147         SELECT DISTINCT ON (mission,name) fid,mission,name,tick, NULL AS eta
148                 ,amount, NULL AS coords, pid AS planet, NULL AS back
149         FROM fleets f
150         WHERE pid = $1 AND tick <= tick() AND (
151                         fid IN (SELECT fid FROM fleet_scans)
152                 ) AND (
153                         mission = 'Full fleet'
154                         OR tick >= tick() - 12
155                 )
156         ORDER BY mission,name,tick DESC
157 ) UNION (
158         SELECT DISTINCT ON (tick,x,y,z,mission,name,amount)
159                 NULL as fid, i.mission, i.name, i.tick,eta
160                 , i.amount, coords(x,y,z), pid AS planet, back
161         FROM intel i
162         LEFT OUTER JOIN current_planet_stats t ON i.target = pid
163         WHERE uid = -1 AND i.sender = $1 AND i.tick > tick() - 14 AND i.tick < tick() + 14
164         ORDER BY i.tick,x,y,z,mission,name,amount,back
165 )
166                 });
167                 $query->execute($id);
168                 my $ships = $dbh->prepare(q{SELECT ship,amount FROM fleet_ships
169                         WHERE fid = ? ORDER BY num
170                 });
171                 my @missions;
172                 while (my $mission = $query->fetchrow_hashref){
173                         my @ships;
174                         if ($mission->{fid}){
175                                 $ships->execute($mission->{fid});
176                                 while (my $ship = $ships->fetchrow_hashref){
177                                         push @ships,$ship;
178                                 }
179                                 push @ships, {ship => 'No', amount => 'ships'} if @ships == 0;
180                                 $mission->{ships} = \@ships;
181                         }
182                         push @missions,$mission;
183                 }
184                 $c->stash(outgoings => \@missions);
185
186                 $query = $dbh->prepare(q{
187                         SELECT DISTINCT ON (i.tick,x,y,z,pid,i.name,i.mission,i.amount) i.id,i.mission, i.name, i.tick,eta
188                                                 , i.amount, coords(x,y,z) AS coords, pid AS planet
189                         FROM intel i
190                         LEFT OUTER JOIN (planets
191                                 NATURAL JOIN planet_stats) s ON i.sender = pid
192                                         AND s.tick = ( SELECT MAX(tick) FROM planet_stats)
193                         WHERE  i.uid = -1
194                                 AND i.target = ?
195                                 AND i.tick > tick() - 3
196                         ORDER BY i.tick,x,y,z,pid,i.name,i.mission,i.amount,i.eta
197                 });
198                 $query->execute($id);
199                 my @incomings;
200                 while (my $mission = $query->fetchrow_hashref){
201                         my @ships;
202                         $ships->execute($mission->{id});
203                         if ($ships->rows != 0){
204                                 while (my $ship = $ships->fetchrow_hashref){
205                                         push @ships,$ship;
206                                 }
207                                 $mission->{ships} = \@ships;
208                         }
209                         push @incomings,$mission;
210                 }
211                 $c->stash(incomings => \@incomings);
212         }
213
214         if ($c->check_user_roles(qw/stats_scans/)){
215                 my $query = $dbh->prepare(q{SELECT type,scan_id, tick FROM scans
216                         WHERE pid = ? AND tick > tick() - 168
217                         ORDER BY tick,type DESC
218                 });
219                 $query->execute($id);
220                 $c->stash(scans => $query->fetchall_arrayref({}) );
221         }
222
223         if ($c->check_user_roles(qw/stats_planetdata/)){
224                 $c->stash(planetscan => $dbh->selectrow_hashref(q{SELECT *
225                         FROM current_planet_scans WHERE pid = $1},undef,$id));
226                 $c->stash(devscan => $dbh->selectrow_hashref(q{SELECT *
227                         FROM current_development_scans WHERE pid = $1},undef,$id));
228         }
229
230         my $query = $dbh->prepare(q{SELECT value,value_gain AS gain,tick FROM planet_stats
231                 WHERE pid = ? AND tick > tick() - 24});
232         $query->execute($id);
233         $c->stash(values => $query->fetchall_arrayref({}) );
234
235         $query = $dbh->prepare(q{SELECT x,y,z,tick FROM planet_stats
236                 WHERE pid = ? ORDER BY tick ASC});
237         $query->execute($id);
238         my @coords;
239         my $co = {x => 0, y => 0, z => 0};
240         while (my $c2 = $query->fetchrow_hashref){
241                 if ($co->{x} != $c2->{x} || $co->{y} != $c2->{y} || $co->{z} != $c2->{z}){
242                         $co = $c2;
243                         push @coords,$co;
244                 }
245         }
246         $c->stash(oldcoords => \@coords);
247
248 }
249
250 sub find : Local {
251         my ( $self, $c, $find ) = @_;
252         my $dbh = $c->model;
253
254         local $_ = $find || $c->req->param('coords');
255         $c->stash(searchterm => $_);
256
257         if (/(\d+)(?: |:)(\d+)(?: |:)(\d+)(?:(?: |:)(\d+))?/){
258                 my $planet = $dbh->selectrow_array(q{SELECT planetid($1,$2,$3,$4)}
259                         ,undef,$1,$2,$3,$4);
260                 $c->res->redirect($c->uri_for('planet',$planet));
261         }elsif (/(\d+)(?: |:)(\d+)/){
262                 $c->res->redirect($c->uri_for('galaxy',$1,$2));
263         }elsif($c->check_user_roles(qw/stats_find_nick/)) {
264                 my $query = $dbh->prepare(q{SELECT pid AS id,coords(x,y,z),nick
265                         FROM current_planet_stats p
266                         WHERE nick ilike $1
267                 });
268                 $query->execute($_);
269                 my $planets = $query->fetchall_arrayref({});
270                 if (@{$planets} == 1){
271                         $c->res->redirect($c->uri_for('planet',$planets->[0]->{id}));
272                 }else{
273                         $c->stash(planets => $planets);
274                 }
275         }
276 }
277
278 sub tags : Local {
279         my ( $self, $c ) = @_;
280         my $dbh = $c->model;
281
282         my @tags = $c->req->param('tags');
283         $c->stash(tags => \@tags);
284         my $query = $dbh->prepare(q{
285 SELECT tag, count(*)
286 FROM planet_tags pt
287 WHERE tag <> ALL($1)
288         AND ($3 OR uid = $2)
289 GROUP BY tag
290                 });
291         $query->execute(\@tags, $c->user->id, $c->check_user_roles('stats_tags_all') // 0);
292         my $cloud = HTML::TagCloud->new;
293         while (my $tag = $query->fetchrow_hashref){
294                 my @t = @tags;
295                 push @t, $tag->{tag};
296                 my %param = (tags => \@t);
297                 $cloud->add($tag->{tag}, $c->uri_for('tags',\%param), $tag->{count});
298         }
299         $c->stash(cloud => $cloud->html);
300         $c->stash(css => $cloud->css);
301
302         $query = $dbh->prepare(q{
303 WITH p AS (SELECT pid, coords(x,y,z) FROM current_planet_stats
304 ), t AS (SELECT pid,tag,bool_or(uid = $2) AS own,max(time) AS time
305         FROM planet_tags
306         WHERE ($3 OR uid = $2)
307         GROUP BY pid,tag
308         ORDER BY time DESC
309 ), tags AS (SELECT pid, array_agg(tag) AS tags
310         FROM t GROUP BY pid
311 )
312 SELECT p.*k,array_to_string(tags,', ') AS tags FROM p JOIN tags USING (pid) WHERE tags @> $1;
313                 });
314         $query->execute(\@tags, $c->user->id, $c->check_user_roles('stats_tags_all') // 0);
315         $c->stash(planets => $query->fetchall_arrayref({}));
316 }
317
318 =head1 AUTHOR
319
320 Michael Andreen (harv@ruin.nu)
321
322 =head1 LICENSE
323
324 GPL 2.0, or later.
325
326 =cut
327
328 1;