1 package NDWeb::Controller::Members;
7 use parent 'Catalyst::Controller';
13 NDWeb::Controller::Members - Catalyst Controller
28 sub index : Path : Args(0) {
29 my ( $self, $c, $order ) = @_;
32 $c->stash(error => $c->flash->{error});
34 $c->stash(u => $dbh->selectrow_hashref(q{SELECT pid AS planet,defense_points
35 ,attack_points,scan_points,humor_points
36 , (attack_points+defense_points+scan_points/20)::NUMERIC(5,1) as total_points
37 , sms,rank,hostmask,call_if_needed,sms_note,defprio
38 FROM users_defprio WHERE uid = ?
42 $c->stash(groups => $dbh->selectrow_array(q{SELECT array_agg(groupname)
43 FROM groups g NATURAL JOIN groupmembers gm
48 $c->stash(p => $dbh->selectrow_hashref(q{SELECT pid AS id,x,y,z, ruler, planet,race,
49 size, size_gain, size_gain_day,
50 score,score_gain,score_gain_day,
51 value,value_gain,value_gain_day,
52 xp,xp_gain,xp_gain_day,
53 sizerank,sizerank_gain,sizerank_gain_day,
54 scorerank,scorerank_gain,scorerank_gain_day,
55 valuerank,valuerank_gain,valuerank_gain_day,
56 xprank,xprank_gain,xprank_gain_day
57 from current_planet_stats_full p
59 },undef,$c->user->planet)
62 $c->stash(fleets => member_fleets($dbh, $c->user->id,$c->user->planet));
64 my $announcements = $dbh->prepare(q{SELECT ft.ftid, u.username,ft.subject,
65 count(NULLIF(COALESCE(fp.time > ftv.time,TRUE),FALSE)) AS unread,count(fp.fpid) AS posts,
66 date_trunc('seconds',max(fp.time)::timestamp) as last_post,
67 min(fp.time)::date as posting_date, ft.sticky
68 FROM forum_threads ft JOIN forum_posts fp USING (ftid)
69 JOIN users u ON u.uid = ft.uid
70 LEFT OUTER JOIN (SELECT * FROM forum_thread_visits WHERE uid = $1) ftv ON ftv.ftid = ft.ftid
72 GROUP BY ft.ftid, ft.subject,ft.sticky,u.username
73 HAVING count(NULLIF(COALESCE(fp.time > ftv.time,TRUE),FALSE)) >= 1
74 ORDER BY sticky DESC,last_post DESC
76 $announcements->execute($c->user->id);
77 $c->stash(announcements => $announcements->fetchall_arrayref({}) );
79 my ($attackgroups) = $dbh->selectrow_array(q{
80 SELECT array_agg(gid) FROM groupmembers WHERE gid IN ('x','y','z') AND uid = $1
81 }, undef, $c->user->id);
82 $c->stash(attackgroups => $attackgroups);
86 sub posthostupdate : Local {
87 my ( $self, $c ) = @_;
90 my $hostname = html_escape $c->req->param('hostname');
91 $dbh->do(q{UPDATE users SET hostmask = ? WHERE uid = ?
92 },undef, $hostname, $c->user->id);
94 $c->res->redirect($c->uri_for(''));
97 sub postattackgroups : Local {
98 my ( $self, $c ) = @_;
101 my @groups = $c->req->param('class');
102 $dbh->do(q{DELETE FROM groupmembers WHERE gid IN ('x','y','z') AND gid <> ALL($1) AND uid = $2
103 },undef, \@groups, $c->user->id);
105 $dbh->do(q{INSERT INTO groupmembers (uid,gid) (
106 SELECT $2, gid FROM unnest($1::text[]) AS gid WHERE gid IN ('x','y','z')
108 SELECT uid,gid FROM groupmembers WHERE uid = $2
109 )},undef, \@groups, $c->user->id);
111 $c->res->redirect($c->uri_for(''));
114 sub postsmsupdate : Local {
115 my ( $self, $c ) = @_;
118 my $callme = $c->req->param('callme') || 0;
119 my $sms = html_escape $c->req->param('sms');
120 my $smsnote = $c->req->param('smsnote');
122 UPDATE users SET sms = $1, call_if_needed = $2, sms_note = $3 WHERE uid = $4
123 },undef, $sms, $callme, $smsnote, $c->user->id);
125 $c->res->redirect($c->uri_for(''));
128 sub postowncoords : Local {
129 my ( $self, $c ) = @_;
132 if ($c->user->planet){
133 $c->flash(error => 'You already have a planet set.'
134 .' Contact a HC if they need to be changed');
135 }elsif (my ($x,$y,$z) = $c->req->param('planet') =~ m/(\d+)\D+(\d+)\D+(\d+)/){
136 my $planet = $dbh->selectrow_array(q{SELECT planetid($1,$2,$3,TICK())
141 $dbh->do(q{UPDATE users SET pid = ? WHERE uid = ?
142 },undef, $planet , $c->user->id);
146 when (/duplicate key value violates/){
147 $c->flash(error => "The coords $x:$y:$z are already in use. Talk to hc if these are really your coords.")
150 $c->flash(error => $@)
154 $c->flash(error => "No planet at coords: $x:$y:$z");
157 my $error = $c->req->param('planet') . " are not valid coords.";
158 $c->flash(error => $error);
161 $c->res->redirect($c->uri_for('/'.$c->session->{referrer}));
164 sub postfleetsupdates : Local {
165 my ( $self, $c ) = @_;
168 my $log = $dbh->prepare(q{INSERT INTO forum_posts (ftid,uid,message) VALUES(
169 (SELECT ftid FROM users WHERE uid = $1),$1,$2)
172 if ($c->req->param('cmd') eq 'Recall Fleets'){
173 my $updatefleets = $dbh->prepare(q{UPDATE launch_confirmations
174 SET back = tick() + (tick() - (landing_tick - eta))
175 WHERE uid = ? AND fid = ? AND back >= tick()+eta
178 for my $param ($c->req->param()){
179 if ($param =~ /^change:(\d+)$/){
180 $updatefleets->execute($c->user->id,$1);
181 $log->execute($c->user->id,"Member recalled fleet $1");
184 }elsif ($c->req->param('cmd') eq 'Change Fleets'){
185 my $updatefleets = $dbh->prepare(q{UPDATE launch_confirmations
186 SET back = ? WHERE uid = ? AND fid = ?});
188 for my $param ($c->req->param()){
189 if ($param =~ /^change:(\d+)$/){
190 my $back = $c->req->param("back:$1");
191 $updatefleets->execute($back,$c->user->id,$1);
192 $log->execute($c->user->id,"Member set fleet $1 to be back tick: $back");
198 $c->res->redirect($c->uri_for(''));
201 sub ircrequest : Local {
202 my ( $self, $c ) = @_;
205 $c->stash(reply => $c->flash->{reply});
206 $c->stash(channels => ['scan','members','def']);
209 sub postircrequest : Local {
210 my ( $self, $c ) = @_;
213 my $message = $c->req->param('message');
214 if ($c->req->param('channel')){
215 my $query = $dbh->prepare(q{
216 INSERT INTO irc_requests (uid,channel,message) VALUES($1,$2,$3)
218 my $channel = $c->user->id,$c->req->param('channel');
219 $query->execute($channel, $message);
222 $c->flash(reply => "Msg sent to: ".$channel);
223 $c->res->redirect($c->uri_for('ircrequest'));
225 $c->stash(ircmessage => $message);
226 $c->go('ircrequest');
231 my ( $self, $c, $order ) = @_;
234 $order //= 'total_points';
235 if ($order ~~ /^((?:defense|attack|total|humor|scan|raid)_points)$/
236 || $order ~~ /^(defprio)$/){
239 $order = 'total_points DESC';
242 my $limit = 'LIMIT 10';
243 $limit = '' if $c->check_user_roles(qw/members_points_nolimit/);
245 my $query = $dbh->prepare(q{
246 SELECT username,defense_points,attack_points
247 ,scan_points,humor_points,defprio
248 ,(attack_points+defense_points+scan_points/20)::NUMERIC(4,0) as total_points
249 , count(NULLIF(rc.launched,FALSE)) AS raid_points
250 FROM users_defprio u LEFT OUTER JOIN raid_claims rc USING (uid)
251 WHERE uid IN (SELECT uid FROM groupmembers WHERE gid = 'M')
252 GROUP BY username,defense_points,attack_points,scan_points,humor_points,defprio
253 ORDER BY } . "$order $limit"
256 $c->stash(members => $query->fetchall_arrayref({}));
260 my ( $self, $c, $order ) = @_;
264 if ($order ~~ /^(scre|value|xp|size|race)$/){
267 $order = 'scorerank';
269 $order .= ',race' if $order eq 'racerank';
271 my $limit = 'LIMIT 10';
272 $limit = '' if $c->check_user_roles(qw/members_points_nolimit/);
274 my ($races) = $dbh->selectrow_array(q{SELECT enum_range(null::race)::text[]});
275 $c->stash(races => $races);
276 my $query = $dbh->prepare(q{
278 ,rank() OVER(ORDER BY score DESC) AS scorerank
279 ,rank() OVER(ORDER BY value DESC) AS valuerank
280 ,rank() OVER(ORDER BY xp DESC) AS xprank
281 ,rank() OVER(ORDER BY size DESC) AS sizerank
282 ,rank() OVER(PARTITION BY race ORDER BY score DESC) AS racerank
284 FROM current_planet_stats
285 WHERE alliance = 'NewDawn'
287 ORDER BY } . "$order $limit");
288 my @race = $c->req->param('race');
289 my %race = map { $_ => 1 } @race;
290 $c->stash(race => \%race);
294 $query->execute(\@race);
295 $c->stash(members => $query->fetchall_arrayref({}));
298 sub addintel : Local {
299 my ( $self, $c, $order ) = @_;
301 $c->stash(intel => $c->flash->{intel});
302 $c->stash(scans => $c->flash->{scans});
303 $c->stash(intelmessage => $c->flash->{intelmessage});
306 sub postintel : Local {
307 my ( $self, $c, $order ) = @_;
309 $c->forward('insertintel');
311 $c->res->redirect($c->uri_for('addintel'));
314 sub postintelmessage : Local {
315 my ( $self, $c, $order ) = @_;
317 unless ($c->req->param('subject')){
318 if ($c->req->param('message') =~ /(.*\w.*)/){
319 $c->req->param(subject => $1);
323 my ($coords,$tick) = $c->model->selectrow_array(q{
324 SELECT coords(x,y,z), tick() FROM current_planet_stats WHERE pid = $1
325 }, undef, $c->user->planet);
327 my $message = "[i]Posted by $coords at tick $tick [/i]\n\n" . $c->req->param('message');
328 $c->req->param(message => $message);
329 $c->forward('/forum/insertThread',[12]);
330 $c->forward('/forum/insertPost',[$c->stash->{thread}]);
331 $c->flash(intelmessage => 1);
333 $c->forward('insertintel');
335 $c->res->redirect($c->uri_for('addintel'));
338 sub insertintel : Private {
339 my ( $self, $c, $order ) = @_;
343 my $findscan = $dbh->prepare(q{SELECT scan_id FROM scans
344 WHERE scan_id = LOWER(?) AND tick >= tick() - 168 AND groupscan = ?
346 my $addscan = $dbh->prepare(q{INSERT INTO scans (scan_id,tick,uid,groupscan)
347 VALUES (LOWER(?),tick(),?,?)
349 my $addpoint = $dbh->prepare(q{UPDATE users SET scan_points = scan_points + 1
353 my $intel = $c->req->param('message');
354 while ($intel =~ m{https?://[\w.]+/.+?scan(_id|_grp)?=(\w+)}g){
355 my $groupscan = (defined $1 && $1 eq '_grp') || 0;
358 $scan{group} = $groupscan;
359 $findscan->execute($2,$groupscan);
360 if ($findscan->rows == 0){
361 if ($addscan->execute($2,$c->user->id,$groupscan)){
362 $addpoint->execute($c->user->id) unless $groupscan;
366 $scan{message} = 'already exists';
370 my $tick = $c->req->param('tick');
371 unless ($tick =~ /^(\d+)$/){
372 $tick = $c->stash->{game}->{tick};
374 my $addintel = $dbh->prepare(q{INSERT INTO intel
375 (name,mission,tick,target,sender,eta,amount,ingal,back,uid)
376 VALUES($1,$2,$3,planetid($4,$5,$6,$10),planetid($7,$8,$9,$10)
377 ,$11,$12,$13,$14,$15)
380 while ($intel =~ m/(\d+):(\d+):(\d+)\*?\s+(\d+):(\d+):(\d+)
381 \*?\s+(A|D)\s+(.+?)\s+(?:(?:\w+)\s+)?(\d+)\s+(\d+)/gx){
382 my $ingal = ($1 == $4 && $2 == $5) || 0;
383 my $lt = $tick + $10;
384 my $back = ($ingal ? $lt + 4 : undef);
385 my $mission = $7 eq 'A' ? 'Attack' : 'Defend';
387 $addintel->execute($8,$mission,$lt,$1,$2,$3,$4,$5,$6,$tick,$10,$9
388 ,$ingal,$back, $c->user->id);
389 push @intel,"Added $&";
392 push @intel,"Couldn't add $&: ".$dbh->errstr;
396 $c->flash(intel => \@intel);
397 $c->flash(scans => \@scans);
400 sub launchConfirmation : Local {
401 my ( $self, $c ) = @_;
403 $c->stash(error => $c->flash->{error});
404 $c->stash(missions => $c->flash->{missions});
407 sub postconfirmation : Local {
408 my ( $self, $c ) = @_;
412 my $findplanet = $dbh->prepare(q{SELECT planetid(?,?,?,tick())});
413 my $addfleet = $dbh->prepare(q{INSERT INTO fleets
414 (name,mission,pid,tick,amount)
415 VALUES ($2,$3,(SELECT pid FROM users WHERE uid = $1),tick(),$4)
418 my $updatefleet = $dbh->prepare(q{
419 UPDATE launch_confirmations SET back = $2 WHERE fid = $1
421 my $addconfirmation = $dbh->prepare(q{INSERT INTO launch_confirmations
422 (fid,uid,pid,landing_tick,eta,back,num) VALUES ($1,$2,$3,$4,$5,$6,$7)
424 my $addships = $dbh->prepare(q{INSERT INTO fleet_ships (fid,ship,amount)
427 my $log = $dbh->prepare(q{INSERT INTO forum_posts (ftid,uid,message) VALUES(
428 (SELECT ftid FROM users WHERE uid = $1),$1,$2)
430 my $return = $dbh->prepare(q{
431 UPDATE launch_confirmations SET back = tick()
432 WHERE uid = $1 AND num = $2 AND back > tick()
434 my $fullfleet = $dbh->prepare(q{INSERT INTO full_fleets
435 (fid,uid) VALUES (?,?)});
437 my $mission = $c->req->param('mission');
438 my @missions = parseconfirmations($mission, $c->stash->{TICK});
439 for my $m (@missions){
440 if ($m->{mission} eq 'Return'){
441 $c->forward("addReturnFleet", [$m]);
443 $updatefleet->execute($m->{fid},$m->{back});
446 $m->{pid} = $c->user->planet;
448 }elsif ($m->{target} ~~ /^(\d+):(\d+):(\d+)$/) {
449 $m->{pid} = $dbh->selectrow_array($findplanet,undef,$1,$2,$3);
451 $m->{warning} = "No planet at $m->{target}, try again next tick.";
456 #Recall fleets with same slot number
457 $return->execute($c->user->id,$m->{num});
459 unless ($m->{mission}){
460 $m->{warning} = "Not on a mission, but matching fleets recalled";
464 $c->forward("findDuplicateFleet", [$m]);
466 $m->{warning} = "Already confirmed this fleet, updating changed information";
467 $updatefleet->execute($m->{fid},$m->{back}) if $m->{pid};
472 $m->{fleet} = $dbh->selectrow_array($addfleet,undef,$c->user->id,$m->{name}
473 ,$m->{mission},$m->{amount});
475 if ($m->{mission} eq 'Full fleet'){
476 $fullfleet->execute($m->{fleet},$c->user->id);
478 $addconfirmation->execute($m->{fleet},$c->user->id,$m->{pid},$m->{tick},$m->{eta},$m->{back},$m->{num});
481 if ($m->{mission} eq 'Attack'){
482 $c->forward("addAttackFleet", [$m]);
483 }elsif ($m->{mission} eq 'Defend'){
484 $c->forward("addDefendFleet", [$m]);
487 for my $ship (@{$m->{ships}}){
488 $addships->execute($m->{fleet},$ship->{ship},$ship->{amount});
490 $log->execute($c->user->id,"Pasted confirmation for $m->{mission} mission to $m->{target}, landing tick $m->{tick}");
492 $c->flash(missions => \@missions);
497 when (/insert or update on table "fleet_ships" violates foreign key constraint "fleet_ships_ship_fkey"\s+DETAIL:\s+Key \(ship\)=\(([^)]+)\)/){
498 $c->flash( error => "'$1' is NOT a valid ship");
501 $c->flash( error => $_);
504 $c->res->redirect($c->uri_for('launchConfirmation'));
507 sub parseconfirmations {
508 my ( $missions, $tick ) = @_;
509 return unless $missions;
511 $missions =~ s/\s?,\s?//g;
512 $missions =~ s/\s*([:+])\s*/$1/g;
513 $missions =~ s/\(\s/(/g;
514 $missions =~ s/\s\)/)/g;
515 my $returnetare = qr/(\d+) \s+
517 my $missionetare = qr/\s* (\d+ \+ \s*)? (\d+) \s+
519 \QReturn ETA:\E\s*(?:(?<eta>Instant) \s+ Cancel \s+ Order
520 | (?<eta>\d+) \s+ Ticks \s+ Recall \s+ Fleet)/sx;
521 my $etare = qr/(Galaxy:\d+Universe:\d+(?:Alliance:\d+)?
524 my $missre = qr/((?:Alliance\ Standby)|(?:(?:Fake\ )?\w+))\s*/x;
526 Ships \s+ Cla \s+ T\s?1 \s+ T\s?2 \s+ T\s?3 \s+ ETA \s+ Base \s+ \(i\) \s (?<name>.+?) \s+ \(i\) \s+ (?<name>.+?) \s+ \(i\) \s+ (?<name>.+?) \s+ \(i\) \s+ TOTAL \s+
528 \QTotal Ships in Fleet\E \s+ (\d+) \s+ (?<amount>\d+) \s+ (?<amount>\d+) \s+ (?<amount>\d+) \s+
529 Mission: \s* (?<missions>(?:$missre)*) \s*
530 Target: \s* (?<targets>((\d+:\d+:\d+)?\s)*) \s*
531 \QLaunch Tick:\E \s* (?<lts>(\d+\s+)*) \s*
532 ETA: \s* (?<etas>(?:$etare)*)
535 my @targets = split /\s+/, $+{targets};
536 my @lts = split /\s+/, $+{lts};
549 name => $match{name}->[$i],
551 amount => $match{amount}->[$i],
555 if ($mission{amount} == 0){
556 push @slots,\%mission;
560 if ($missions[0] eq 'Alliance Standby'){
562 push @slots,\%mission;
567 when(/$missionetare/sx){
569 $mission{eta} = $2 + $+{eta};
570 $mission{back} = $3 + $mission{eta} - 1;
571 $mission{target} = shift @targets;
572 $mission{lt} = shift @lts;
573 $mission{mission} = shift @missions;
575 when(/$returnetare/sx){
579 $mission{target} = shift @targets;
580 $mission{lt} = shift @lts;
581 $mission{mission} = shift @missions;
582 die "Did you forget some at the end? '$mission{mission}'" if $mission{mission} ne 'Return';
585 push @slots,\%mission;
590 mission => 'Full fleet',
595 while ($match{ships}->[0] =~ m/(\w[ \w]+?)\s+(FI|CO|FR|DE|CR|BS|--)[^\d]+\d+\s+((?:\d+\s*){5})/g){
597 my @amounts = split /\D+/, $3;
598 my $base = shift @amounts;
599 die "Ships don't sum up properly" if $amounts[3] != $base + $amounts[0] + $amounts[1] + $amounts[2];
601 push @{$slots[$i]->{ships}},{ship => $ship, amount => $amounts[$i]} if $amounts[$i] > 0;
603 $slots[3]->{amount} += $amounts[3];
609 sub findDuplicateFleet : Private {
610 my ( $self, $c, $m ) = @_;
613 my $findfleet = $dbh->prepare(q{
614 SELECT fid FROM fleets f
615 LEFT JOIN launch_confirmations lc USING (fid)
616 WHERE f.pid = (SELECT pid FROM users WHERE uid = $1)
617 AND mission = $3 AND amount = $4 AND (mission <> 'Full fleet' OR tick > $6 - 6)
618 AND COALESCE(uid = $1 AND num = $2 AND lc.pid = $5 AND landing_tick = $6, TRUE)
620 my $fid = $dbh->selectrow_array($findfleet,undef,$c->user->id,$m->{num}
621 ,$m->{mission},$m->{amount}, $m->{pid}, $m->{tick});
622 $c->forward("matchShips", [$m,$fid]);
623 $m->{fid} = $fid if $m->{match};
626 sub addAttackFleet : Private {
627 my ( $self, $c, $m ) = @_;
630 my $findattacktarget = $dbh->prepare(q{
631 SELECT c.target,c.wave,c.launched
633 JOIN raid_targets t ON c.target = t.id
634 JOIN raids r ON t.raid = r.id
635 WHERE c.uid = ? AND r.tick+c.wave-1 = ? AND t.pid = ?
636 AND r.open AND not r.removed
638 my $launchedtarget = $dbh->prepare(q{
639 UPDATE raid_claims SET launched = TRUE
640 WHERE uid = ? AND target = ? AND wave = ?
642 my $claim = $dbh->selectrow_hashref($findattacktarget,undef,$c->user->id,$m->{tick},$m->{pid});
643 if ($claim->{launched}){
644 $m->{warning} = "Already launched on this target:$claim->{target},$claim->{wave},$claim->{launched}";
645 }elsif(defined $claim->{launched}){
646 $launchedtarget->execute($c->user->id,$claim->{target},$claim->{wave});
647 $m->{warning} = "OK:$claim->{target},$claim->{wave},$claim->{launched}";
649 $m->{warning} = "You haven't claimed this target";
653 sub addDefendFleet : Private {
654 my ( $self, $c, $m ) = @_;
657 my $finddefensetarget = $dbh->prepare(q{
658 SELECT call FROM calls c
659 JOIN users u USING (uid)
660 WHERE u.pid = $1 AND c.landing_tick = $2
662 my $informDefChannel = $dbh->prepare(q{
663 INSERT INTO defense_missions (fleet,call) VALUES (?,?)
665 my $call = $dbh->selectrow_hashref($finddefensetarget,undef,$m->{pid},$m->{tick});
667 $informDefChannel->execute($m->{fleet},$call->{call});
669 $m->{warning} = "No call for $m->{target} landing tick $m->{tick}";
673 sub addReturnFleet : Private {
674 my ( $self, $c, $m ) = @_;
677 my $findfleet = $dbh->prepare(q{
678 SELECT fid FROM fleets f
679 JOIN launch_confirmations lc USING (fid)
680 WHERE uid = $1 AND num = $2 AND amount = $3
683 my $fid = $dbh->selectrow_array($findfleet,undef,$c->user->id,$m->{num}
684 ,$m->{amount}, $m->{tick});
685 $c->forward("matchShips", [$m,$fid]);
688 $m->{warning} = "Return fleet, changed back tick to match the return eta.";
690 $m->{warning} = "Couldn't find a fleet matching this returning fleet, so adding a new fleet that is returning";
694 sub matchShips : Private {
695 my ( $self, $c, $m, $fid ) = @_;
699 my $ships = $dbh->prepare(q{
700 SELECT ship, amount FROM fleet_ships WHERE fid = $1 ORDER BY num
702 $ships->execute($fid);
703 for my $s (@{$m->{ships}}){
704 my $s2 = $ships->fetchrow_hashref;
705 return unless $s->{ship} eq $s2->{ship} && $s->{amount} == $s2->{amount};
711 sub defenders : Local {
712 my ( $self, $c, $order ) = @_;
715 my $defenders = $dbh->prepare(q{
716 SELECT uid,pid AS planet,username, to_char(NOW() AT TIME ZONE timezone,'HH24:MI') AS time
717 ,sms_note, call_if_needed, race, timezone
719 JOIN current_planet_stats p USING (pid)
720 WHERE uid IN (SELECT uid FROM groupmembers WHERE gid = 'M')
721 ORDER BY call_if_needed DESC, username
725 my $available = $dbh->prepare(q{
726 SELECT ship,amount FROM available_ships WHERE pid = $1
730 while (my $member = $defenders->fetchrow_hashref){
732 $member->{fleets} = member_fleets($dbh, $member->{uid}, $member->{planet});
733 $available->execute($member->{planet});
734 my $fleet = {fid => $member->{username}, mission => 'Available', name => 'At home'
735 , ships => $available->fetchall_arrayref({})
737 push @{$member->{fleets}}, $fleet;
738 push @members,$member;
740 $c->stash(members => \@members);
744 my ( $dbh, $uid, $planet ) = @_;
746 my $query = $dbh->prepare(q{
748 SELECT DISTINCT ON (mission,name) fid,name,tick, NULL AS eta
749 ,amount, NULL AS coords, pid AS target, NULL AS back
750 ,NULL AS recalled, mission
752 WHERE pid = $2 AND tick <= tick() AND tick >= tick() - 24
753 AND name IN ('Main','Advanced Unit') AND mission = 'Full fleet'
754 ORDER BY mission,name,tick DESC, fid DESC
756 SELECT fid,name,landing_tick AS tick, eta, amount
757 , coords(x,y,z), lc.pid AS target, back
758 , (back <> landing_tick + eta - 1) AS recalled
759 ,CASE WHEN landing_tick <= tick() OR (back <> landing_tick + eta - 1)
760 THEN 'Returning' ELSE mission END AS mission
761 FROM launch_confirmations lc
762 LEFT OUTER JOIN current_planet_stats t USING (pid)
763 JOIN fleets f USING (fid)
764 WHERE uid = $1 AND f.pid = $2 AND back > tick()
765 AND landing_tick - eta - 12 < tick()
769 my $ships = $dbh->prepare(q{SELECT ship,amount FROM fleet_ships
770 WHERE fid = ? ORDER BY num
773 $query->execute($uid,$planet);
775 while (my $fleet = $query->fetchrow_hashref){
777 $ships->execute($fleet->{fid});
778 while (my $ship = $ships->fetchrow_hashref){
781 $fleet->{ships} = \@ships;
789 Michael Andreen (harv@ruin.nu)