+sub findDuplicateFleet : Private {
+ my ( $self, $c, $m ) = @_;
+ my $dbh = $c->model;
+
+ my $findfleet = $dbh->prepare(q{
+SELECT fid FROM fleets f
+ LEFT JOIN launch_confirmations lc USING (fid)
+WHERE f.pid = (SELECT pid FROM users WHERE uid = $1)
+ AND mission = $3 AND amount = $4 AND (mission <> 'Full fleet' OR tick > $6 - 6)
+ AND COALESCE(uid = $1 AND num = $2 AND lc.pid = $5 AND landing_tick = $6, TRUE)
+ });
+ my $fid = $dbh->selectrow_array($findfleet,undef,$c->user->id,$m->{num}
+ ,$m->{mission},$m->{amount}, $m->{pid}, $m->{tick});
+ $c->forward("matchShips", [$m,$fid]);
+ $m->{fid} = $fid if $m->{match};
+}
+
+sub addAttackFleet : Private {
+ my ( $self, $c, $m ) = @_;
+ my $dbh = $c->model;
+
+ my $findattacktarget = $dbh->prepare(q{
+SELECT c.target,c.wave,c.launched
+FROM raid_claims c
+ JOIN raid_targets t ON c.target = t.id
+ JOIN raids r ON t.raid = r.id
+WHERE c.uid = ? AND r.tick+c.wave-1 = ? AND t.pid = ?
+ AND r.open AND not r.removed
+ });
+ my $launchedtarget = $dbh->prepare(q{
+UPDATE raid_claims SET launched = TRUE
+WHERE uid = ? AND target = ? AND wave = ?
+ });
+ my $claim = $dbh->selectrow_hashref($findattacktarget,undef,$c->user->id,$m->{tick},$m->{pid});
+ if ($claim->{launched}){
+ $m->{warning} = "Already launched on this target:$claim->{target},$claim->{wave},$claim->{launched}";
+ }elsif(defined $claim->{launched}){
+ $launchedtarget->execute($c->user->id,$claim->{target},$claim->{wave});
+ $m->{warning} = "OK:$claim->{target},$claim->{wave},$claim->{launched}";
+ }else{
+ $m->{warning} = "You haven't claimed this target";
+ }
+}
+
+sub addDefendFleet : Private {
+ my ( $self, $c, $m ) = @_;
+ my $dbh = $c->model;
+
+ my $finddefensetarget = $dbh->prepare(q{
+SELECT call FROM calls c
+ JOIN users u USING (uid)
+WHERE u.pid = $1 AND c.landing_tick = $2
+ });
+ my $informDefChannel = $dbh->prepare(q{
+INSERT INTO defense_missions (fleet,call) VALUES (?,?)
+ });
+ my $call = $dbh->selectrow_hashref($finddefensetarget,undef,$m->{pid},$m->{tick});
+ if ($call->{call}){
+ $informDefChannel->execute($m->{fleet},$call->{call});
+ }else{
+ $m->{warning} = "No call for $m->{target} landing tick $m->{tick}";
+ }
+}
+
+sub addReturnFleet : Private {
+ my ( $self, $c, $m ) = @_;
+ my $dbh = $c->model;
+
+ my $findfleet = $dbh->prepare(q{
+SELECT fid FROM fleets f
+ JOIN launch_confirmations lc USING (fid)
+WHERE uid = $1 AND num = $2 AND amount = $3
+ AND back >= $4
+ });
+ my $fid = $dbh->selectrow_array($findfleet,undef,$c->user->id,$m->{num}
+ ,$m->{amount}, $m->{tick});
+ $c->forward("matchShips", [$m,$fid]);
+ if ($m->{match}){
+ $m->{fid} = $fid;
+ $m->{warning} = "Return fleet, changed back tick to match the return eta.";
+ } else {
+ $m->{warning} = "Couldn't find a fleet matching this returning fleet, so adding a new fleet that is returning";
+ }
+}
+
+sub matchShips : Private {
+ my ( $self, $c, $m, $fid ) = @_;
+ return unless $fid;
+ my $dbh = $c->model;
+
+ my $ships = $dbh->prepare(q{
+SELECT ship, amount FROM fleet_ships WHERE fid = $1 ORDER BY num
+ });
+ $ships->execute($fid);
+ for my $s (@{$m->{ships}}){
+ my $s2 = $ships->fetchrow_hashref;
+ return unless $s->{ship} eq $s2->{ship} && $s->{amount} == $s2->{amount};
+ }
+ $m->{match} = 1;
+
+}
+
+sub defenders : Local {
+ my ( $self, $c, $order ) = @_;
+ my $dbh = $c->model;
+
+ my $defenders = $dbh->prepare(q{
+SELECT uid,pid AS planet,username, to_char(NOW() AT TIME ZONE timezone,'HH24:MI') AS time
+ ,sms_note, call_if_needed, race, timezone
+FROM users u
+ JOIN current_planet_stats p USING (pid)
+WHERE uid IN (SELECT uid FROM groupmembers WHERE gid = 'M')
+ORDER BY call_if_needed DESC, username
+ });
+ $defenders->execute;
+
+ my $available = $dbh->prepare(q{
+SELECT ship,amount FROM available_ships WHERE pid = $1
+ });
+
+ my @members;
+ while (my $member = $defenders->fetchrow_hashref){
+
+ $member->{fleets} = member_fleets($dbh, $member->{uid}, $member->{planet});
+ $available->execute($member->{planet});
+ my $fleet = {fid => $member->{username}, mission => 'Available', name => 'At home'
+ , ships => $available->fetchall_arrayref({})
+ };
+ push @{$member->{fleets}}, $fleet;
+ push @members,$member;
+ }
+ $c->stash(members => \@members);
+}
+
+sub member_fleets {
+ my ( $dbh, $uid, $planet ) = @_;
+
+ my $query = $dbh->prepare(q{
+(
+ SELECT DISTINCT ON (mission,name) fid,name,tick, NULL AS eta
+ ,amount, NULL AS coords, pid AS target, NULL AS back
+ ,NULL AS recalled, mission
+ FROM fleets f
+ WHERE pid = $2 AND tick <= tick() AND tick >= tick() - 24
+ AND name IN ('Main','Advanced Unit') AND mission = 'Full fleet'
+ ORDER BY mission,name,tick DESC, fid DESC
+) UNION (
+ SELECT fid,name,landing_tick AS tick, eta, amount
+ , coords(x,y,z), lc.pid AS target, back
+ , (back <> landing_tick + eta - 1) AS recalled
+ ,CASE WHEN landing_tick <= tick() OR (back <> landing_tick + eta - 1)
+ THEN 'Returning' ELSE mission END AS mission
+ FROM launch_confirmations lc
+ LEFT OUTER JOIN current_planet_stats t USING (pid)
+ JOIN fleets f USING (fid)
+ WHERE uid = $1 AND f.pid = $2 AND back > tick()
+ AND landing_tick - eta - 12 < tick()
+)
+ });
+
+ my $ships = $dbh->prepare(q{SELECT ship,amount FROM fleet_ships
+ WHERE fid = ? ORDER BY num
+ });
+
+ $query->execute($uid,$planet);
+ my @fleets;
+ while (my $fleet = $query->fetchrow_hashref){
+ my @ships;
+ $ships->execute($fleet->{fid});
+ while (my $ship = $ships->fetchrow_hashref){
+ push @ships,$ship;
+ }
+ $fleet->{ships} = \@ships;
+ push @fleets,$fleet;
+ }
+ return \@fleets;