From 2abbf4bc19fdce65136e3227bc831e58b81dde0b Mon Sep 17 00:00:00 2001 From: Ian Docherty Date: Fri, 30 Nov 2012 17:18:15 -0500 Subject: [PATCH] API for SpacePort and ShipYard now look to be complete --- docs/SpacePort.pod | 301 +++++++++++-------- lib/Lacuna/DB/Result/Fleet/SpyPod.pm | 1 + lib/Lacuna/RPC/Building/SpacePort.pm | 433 +++++++++++++++++---------- 3 files changed, 463 insertions(+), 272 deletions(-) diff --git a/docs/SpacePort.pod b/docs/SpacePort.pod index a826305c..cfa1ac8e 100644 --- a/docs/SpacePort.pod +++ b/docs/SpacePort.pod @@ -157,7 +157,6 @@ This buildings ID =head2 view_all_fleets - Accepts either fixed arguments or a hash of named parameters ( session_id, building_id ) @@ -901,187 +900,250 @@ The array reference B shows each fleet and the B of ships -=head2 prepare_send_spies ( session_id, on_body_id, to_body_id ) +=head2 prepare_send_spies Gathers the information needed to call the C method. - { - "status" : { ... }, - "ships" : [ - { - "id" : "id-goes-here", - "name" : "CS4", - "hold_size" : 1100, - "speed" : 400, - "type" : "cargo_ship", - "estimated_travel_time" : 3600, # in seconds - ... - }, - ... - ], - "spies" : [ - { - "id" : "id-goes-here", - "level" : 12, - "name" : "Jack Bauer", - "assigned_to" : { - "body_id" : "id-goes-here", - "name" : "Earth" - }, - ... - }, - ... - ] - } - -B Only a certain number of spies can fit in each type of ship. Spy Pods can hold 1. Spy Shuttles can hold 4. And ships with a cargo hold can hold 1 for every 350 units of hold size. - -=head3 session_id - -A session id. +Accepts either fixed arguments or a hash of named parameters -=head3 on_body_id + ( session_id, on_body_id, to_body_id ) + ( parameter_hash ) + +=head3 session_id (required) + +A session ID + +=head3 on_body_id (required) The unique id of the planet that the spies are on and ship will be dispatched from. =head3 to_body_id -The unique id of the planet that the spies should be sent to. +The unique id of the planet that the spies should be sent to. This is a required parameter +if using fixed arguments. With named arguments you can use either C or C +=head3 to_body +The planet where you want to send spies to. This can be used instead of C if +you are using named arguments. This is a hash reference. See C for examples although the +target may only be an occupied Planet. (named, by ID or by x,y) - -=head2 send_spies ( session_id, on_body_id, to_body_id, ship_id, spy_ids ) - -Sends one or more of spies to a planet using a selected ship. See also C. +=head3 RESPONSE { - "ship" : { - "id" : "id-goes-here", - "name" : "CS4", - "hold_size" : 1100, - "speed" : 400, - "type" : "cargo_ship", - "date_arrives" : "01 31 2010 13:09:05 +0600", - ... + "status" : { ... }, + "fleets" : [ + { + "id" : "id-goes-here", + "quantity" : 1, + "name" : "CS4", + "hold_size" : 1100, + "speed" : 400, + "type" : "cargo_ship", + "estimated_travel_time" : 3600, # in seconds + ... + }, + ... + ], + "spies" : [ + { + "id" : "id-goes-here", + "level" : 12, + "name" : "Jack Bauer", + "assigned_to" : { + "body_id" : "id-goes-here", + "name" : "Earth" + }, + ... }, - "spies_sent" : ["id-goes-here","id-goes-here","id-goes-here"], # should be identical to "spy_ids" - "spies_not_sent" : ["id-goes-here","id-goes-here","id-goes-here"], # should only contain something if you're cheating, or a spy dies/turns between RPC calls - "status" : { ... } + ... + ] } + +B Only a certain number of spies can fit in each type of ship. Spy Pods can hold 1. Spy Shuttles can hold 4. +and ships with a cargo hold can hold 1 for every 350 units of hold size. Note however that a fleet of (say) 10 spy pods +can hold 10 spies. -=head3 session_id -A session id. +=head2 send_spies -=head3 on_body_id +Send one or more spies to a target using a selected fleet. See also C + +Accepts either fixed arguments or a hash of named parameters + + ( session_id, on_body_id, to_body_id, fleet_id, spy_ids ) + ( parameter_hash ) + +=head3 session_id (required) + +A session ID + +=head3 on_body_id (required) -The unique id of the planet that should send the ship and that has the spies. +The unique id of the planet that the spies are on and fleet will be dispatched from. =head3 to_body_id -The unique id of the planet that the spies should be sent to. +The unique id of the planet that the spies should be sent to. This is a required parameter +if using fixed arguments. With named arguments you can use either C or C -=head3 ship_id +=head3 fleet_id (required) -The unique id of the ship to send. +The unique ID of the fleet. -=head3 spy_ids +=head3 spy_ids (required) -An array reference of spy ids to send. +An array reference of spy ids to send +=head3 ship_quantity +The number of ships to send from the fleet (defaults to 1) +=head3 to_body -=head2 prepare_fetch_spies ( session_id, on_body_id, to_body_id ) +The planet where you want to send spies to. This can be used instead of C if +you are using named arguments. See -Gathers the information needed to call the C method. +=head3 arrival_date (optional) - { - "status" : { ... }, - "ships" : [ - { - "id" : "id-goes-here", - "name" : "CS4", - "hold_size" : 1100, - "speed" : 400, - "type" : "cargo_ship", - "estimated_travel_time" : 3600, # in seconds - ... - }, - ... - ], - "spies" : [ - { - "id" : "id-goes-here", - "level" : 12, - "name" : "Jack Bauer", - "assigned_to" : { - "body_id" : "id-goes-here", - "name" : "Earth" - }, - ... - }, - ... - ] - } +See C for details. If not specified will send fleet to arrive at the soonest time. +May only be specified with the named arguments calling convention. -=head3 session_id +=head3 RESPONSE -A session id. + { + "fleet" : { + "id" : "id-goes-here", + "quantity" : 1, + "name" : "CS4", + "hold_size" : 1100, + "speed" : 400, + "type" : "cargo_ship", + "date_arrives" : "01 31 2010 13:09:05 +0600", + ... + }, + "spies_sent" : ["id-goes-here","id-goes-here","id-goes-here"], # should be identical to "spy_ids" + "spies_not_sent" : ["id-goes-here","id-goes-here","id-goes-here"], # should only contain something if you're cheating, or a spy dies/turns between RPC calls + "status" : { ... } + } -=head3 on_body_id -The unique id of the planet that the spies are on. +=head2 prepare_fetch_spies -=head3 to_body_id +Gathers the information needed to call the C method. -The unique id of the planet that the spies should be sent to, and the ship will be dispatched from. +Accepts either fixed arguments or a hash of named parameters + ( session_id, on_body_id, to_body_id) + ( parameter_hash ) + +=head3 session_id (required) + +A session ID + +=head3 on_body_id +The unique id of the planet that the spies are on. This is a required parameter if using +fixed argument call. With named arguments you can either use C or C +=head3 to_body_id +The unique ID of the planet to return the spies to. This is the planet from which the fleet +is sent from. -=head2 fetch_spies ( session_id, on_body_id, to_body_id, ship_id, spy_ids ) +=head3 on_body -Sends a specified ship to fetch specified spies from C, and bring them back to C. See also C. +This is an alternative way of specifying C using a hash ref (see C) but +you can only specify the ID, name or x,y of an occupied Planet. Not available when using the +fixed argument call method. -B If the spies are not Idle when the ship arrives, they will not be picked up. +=head3 RESPONSE { - "ship" : { - "id" : "id-goes-here", - "name" : "CS4", - "hold_size" : 1100, - "speed" : 400, - "type" : "cargo_ship", - "date_arrives" : "01 31 2010 13:09:05 +0600", - ... + "status" : { ... }, + "fleets" : [ + { + "id" : "id-goes-here", + "name" : "CS4", + "hold_size" : 1100, + "speed" : 400, + "type" : "cargo_ship", + "estimated_travel_time" : 3600, # in seconds + ... + }, + ... + ], + "spies" : [ + { + "id" : "id-goes-here", + "level" : 12, + "name" : "Jack Bauer", + "assigned_to" : { + "body_id" : "id-goes-here", + "name" : "Earth" + }, + ... }, - "status" : { ... } + ... + ] } -=head3 session_id -A session id. +=head2 fetch_spies + +Sends a specified fleet to fetch specified spies from C or C, and bring them +back to C. See also C +Accepts either fixed arguments or a hash of named parameters + + ( session_id, on_body_id, to_body_id, fleet_id, spy_ids) + ( parameter_hash ) + +=head3 session_id (required) + +A session ID + =head3 on_body_id -The unique id of the planet that the spies are on. +The unique id of the planet that the spies are on. This is a required parameter if using +fixed argument call. With named arguments you can either use C or C -=head3 to_body_id +=head3 to_body_id (required) -The unique id of the planet that the spies should be sent to, and the ship will be dispatched from. +The unique ID of the planet to return the spies to. This is the planet from which the fleet +is sent from. -=head3 ship_id +=head3 on_body -The unique id of the ship to use to fetch the spies. +This is an alternative way of specifying C using a hash ref (see C) but +you can only specify the ID, name or x,y of an occupied Planet. Not available when using the +fixed argument call method. -=head3 spy_ids +=head3 fleet_id (required) -An array reference of spy ids to send. +The unique ID of the fleet to send. The number of ships sent will be calculated based on the +number of spies to fetch and the max occupants of the ship type. +=head3 spy_ids (required) +An array reference of unique spy IDs to fetch. +B If the spies are not Idle when the ship arrives, they will not be picked up. + +=head3 RESPONSE + + { + "fleet" : { + "id" : "id-goes-here", + "quantity" : 3, + "name" : "CS4", + "hold_size" : 1100, + "speed" : 400, + "type" : "cargo_ship", + "date_arrives" : "01 31 2010 13:09:05 +0600", + ... + }, + "status" : { ... } + } =head2 view_battle_logs @@ -1125,3 +1187,4 @@ See above for this option. } =cut + diff --git a/lib/Lacuna/DB/Result/Fleet/SpyPod.pm b/lib/Lacuna/DB/Result/Fleet/SpyPod.pm index 474a2933..7cdb59f0 100644 --- a/lib/Lacuna/DB/Result/Fleet/SpyPod.pm +++ b/lib/Lacuna/DB/Result/Fleet/SpyPod.pm @@ -30,3 +30,4 @@ with "Lacuna::Role::Ship::Arrive::Scuttle"; no Moose; __PACKAGE__->meta->make_immutable(inline_constructor => 0); + diff --git a/lib/Lacuna/RPC/Building/SpacePort.pm b/lib/Lacuna/RPC/Building/SpacePort.pm index b1cd9cd5..195df561 100644 --- a/lib/Lacuna/RPC/Building/SpacePort.pm +++ b/lib/Lacuna/RPC/Building/SpacePort.pm @@ -7,6 +7,7 @@ extends 'Lacuna::RPC::Building'; use Lacuna::Constants qw(SHIP_TYPES); use Lacuna::Util qw(format_date); use Data::Dumper; +use POSIX qw(ceil); use feature "switch"; @@ -183,43 +184,7 @@ sub send_fleet { $new_fleet->send(target => $target); } else { - my $month = $args->{arrival_date}{month}; - my $date = $args->{arrival_date}{date}; - my $hour = $args->{arrival_date}{hour}; - my $minute = $args->{arrival_date}{minute}; - my $second = $args->{arrival_date}{second}; - if ($second != 0 and $second != 15 and $second != 30 and $second != 45) { - confess [1009, 'Seconds can only be one of 0,15,30 or 45']; - } - if ($minute < 0 or $minute > 59 or $minute != int($minute)) { - confess [1009, 'Minutes must be an integer between 0 and 59']; - } - if ($hour < 0 or $hour > 23 or $hour != int($hour)) { - confess [1009, 'Hours must be an integer between 0 and 23']; - } - if ($month < 1 or $month > 12 or $month != int($month)) { - confess [1009, 'Month must be an integer between 1 and 12']; - } - my $now = DateTime->now; - my $month_now = $now->month; - my $year_now = $now->year; - my $year = $year_now; - # if it is for a date next year - if ($month < $month_now) { - $year = $year_now + 1; - } - my $arrival_date = DateTime->new( - year => $year, - month => $month, - day => $date, - hour => $hour, - minute => $minute, - second => $second, - ); - my $earliest_arrival = DateTime->now->add(seconds=>$fleet->calculate_travel_time($target)); - if ($arrival_date < $earliest_arrival) { - confess [1009, 'The fleet is not fast enough to arrive by that date']; - } + my $arrival_date = $self->calculate_arrival($fleet, $target, $args->{arrival_date}); $new_fleet->send(target => $target, arrival => $arrival_date); } return { @@ -228,6 +193,52 @@ sub send_fleet { }; } + +# calculate arrival time +# +sub calculate_arrival { + my ($self, $fleet, $target, $args) = @_; + + my $month = $args->{month}; + my $date = $args->{date}; + my $hour = $args->{hour}; + my $minute = $args->{minute}; + my $second = $args->{second}; + if ($second != 0 and $second != 15 and $second != 30 and $second != 45) { + confess [1009, 'Seconds can only be one of 0,15,30 or 45']; + } + if ($minute < 0 or $minute > 59 or $minute != int($minute)) { + confess [1009, 'Minutes must be an integer between 0 and 59']; + } + if ($hour < 0 or $hour > 23 or $hour != int($hour)) { + confess [1009, 'Hours must be an integer between 0 and 23']; + } + if ($month < 1 or $month > 12 or $month != int($month)) { + confess [1009, 'Month must be an integer between 1 and 12']; + } + my $now = DateTime->now; + my $month_now = $now->month; + my $year_now = $now->year; + my $year = $year_now; + # if it is for a date next year + if ($month < $month_now) { + $year = $year_now + 1; + } + my $arrival_date = DateTime->new( + year => $year, + month => $month, + day => $date, + hour => $hour, + minute => $minute, + second => $second, + ); + my $earliest_arrival = DateTime->now->add(seconds => $fleet->calculate_travel_time($target)); + if ($arrival_date < $earliest_arrival) { + confess [1009, 'The fleet is not fast enough to arrive by that date']; + } + return $arrival_date; +} + sub recall_fleet { my $self = shift; my $args = shift; @@ -246,7 +257,7 @@ sub recall_fleet { confess [1002, 'Could not locate that fleet.']; } if ($fleet->body->empire->id != $empire->id) { - confess [1010, 'You do not own that ship.']; + confess [1010, 'You do not own that fleet.']; } $fleet->has_that_quantity($qty); $fleet->can_recall; @@ -264,12 +275,26 @@ sub recall_fleet { sub prepare_send_spies { - my ($self, $session_id, $on_body_id, $to_body_id) = @_; - my $empire = $self->get_empire_by_session($session_id); - my $on_body = $self->get_body($empire, $on_body_id); - my $to_body = Lacuna->db->resultset('Lacuna::DB::Result::Map::Body')->find($to_body_id); - - unless ($to_body->empire_id) { + my $self = shift; + my $args = shift; + + if (ref($args) ne "HASH") { + $args = { + session_id => $args, + on_body_id => shift, + to_body_id => shift, + }; + } + my $empire = $self->get_empire_by_session($args->{session_id}); + if ($args->{to_body_id}) { + $args->{to_body} = { body_id => $args->{to_body_id}}; + } + my $on_body = $self->get_body($empire, $args->{on_body_id}); + my $to_body = $self->find_target($args->{to_body}); + if (not $to_body->isa('Lacuna::DB::Result::Map::Body::Planet')) { + confess [1009, "Can only send spies to a planet."]; + } + if (not $to_body->empire_id) { confess [1009, "Cannot send spies to an uninhabited body."]; } if ($to_body->empire->is_isolationist) { @@ -285,21 +310,27 @@ sub prepare_send_spies { $max_berth = 1; } - my $ships = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search( - {type => { in => [qw(spy_pod cargo_ship smuggler_ship dory spy_shuttle barge)]}, - task=>'Docked', body_id => $on_body_id, - berth_level => {'<=' => $max_berth } }, - {order_by => 'name', rows=>100} - ); - my @ships; - while (my $ship = $ships->next) { - push @ships, $ship->get_status($to_body); - } - - my $spies = Lacuna->db->resultset('Lacuna::DB::Result::Spies')->search( - {on_body_id => $on_body->id, empire_id => $empire->id }, - {order_by => 'name', rows=>100} - ); + my $fleets_rs = Lacuna->db->resultset('Fleet')->search({ + type => { in => [qw(spy_pod cargo_ship smuggler_ship dory spy_shuttle barge)]}, + task => 'Docked', + body_id => $on_body->id, + berth_level => {'<=' => $max_berth }, + },{ + order_by => 'name', + rows => 100, + }); + my @fleets; + while (my $fleet = $fleets_rs->next) { + push @fleets, $fleet->get_status($to_body); + } + # TODO factor out the 'available spies' code + my $spies = Lacuna->db->resultset('Spies')->search({ + on_body_id => $on_body->id, + empire_id => $empire->id, + },{ + order_by => 'name', + rows => 100, + }); my @spies; while (my $spy = $spies->next) { $spy->on_body($on_body); @@ -310,20 +341,38 @@ sub prepare_send_spies { return { status => $self->format_status($empire), - ships => \@ships, + fleets => \@fleets, spies => \@spies, }; } sub send_spies { - my ($self, $session_id, $on_body_id, $to_body_id, $ship_id, $spy_ids) = @_; - my $empire = $self->get_empire_by_session($session_id); - my $on_body = $self->get_body($empire, $on_body_id); - my $to_body = Lacuna->db->resultset('Lacuna::DB::Result::Map::Body')->find($to_body_id); - - # make sure it's a valid target - unless ($to_body->empire_id) { - confess [ 1009, 'Cannot send spies to an uninhabited body.']; + my $self = shift; + my $args = shift; + + if (ref($args) ne "HASH") { + $args = { + session_id => $args, + on_body_id => shift, + to_body_id => shift, + fleet_id => shift, + spy_ids => shift, + }; + } + $args->{ship_quantity} = $args->{ship_quantity} || 1; + $args->{arrival_date} = {soonest => 1} if not defined $args->{arrival_date}; + + my $empire = $self->get_empire_by_session($args->{session_id}); + if ($args->{to_body_id}) { + $args->{to_body} = { body_id => $args->{to_body_id}}; + } + my $on_body = $self->get_body($empire, $args->{on_body_id}); + my $to_body = $self->find_target($args->{to_body}); + if (not $to_body->isa('Lacuna::DB::Result::Map::Body::Planet')) { + confess [1009, "Can only send spies to a planet."]; + } + if (not $to_body->empire_id) { + confess [1009, "Cannot send spies to an uninhabited body."]; } if ($to_body->empire->is_isolationist) { confess [ 1013, sprintf('%s is an isolationist empire, and must be left alone.',$to_body->empire->name)]; @@ -333,43 +382,50 @@ sub send_spies { $empire->current_session->check_captcha; } - # get the ship - my $ship = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->find($ship_id); - unless (defined $ship) { - confess [1002, "Ship not found."]; + # get the fleet + my $fleet = Lacuna->db->resultset('Fleet')->find($args->{fleet_id}); + if (not defined $fleet) { + confess [1002, "Fleet not found."]; } - unless ($ship->is_available) { - confess [1010, "That ship is not available."]; + if (not $fleet->is_available) { + confess [1010, "That fleet is not available."]; } my $max_berth = $on_body->max_berth; - unless ($ship->berth_level <= $max_berth) { - confess [1010, "Your spaceport level is not high enough to support a ship with a Berth Level of ".$ship->berth_level."."]; + if ($fleet->berth_level > $max_berth) { + confess [1010, "Your spaceport level is not high enough to support a fleet with a Berth Level of ".$fleet->berth_level."."]; + } + if ($fleet->quantity < $args->{ship_quantity}) { + confess [1009, "That fleet does not have ".$args->{ship_quantity}." ships in it."]; } # check size - unless (scalar(@{$spy_ids})) { - confess [1013, "You can't send a ship with no spies."]; - } - - if ($ship->type eq 'spy_pod' && scalar(@{$spy_ids}) == 1) { - # we're ok - } - elsif ($ship->type eq 'spy_shuttle' && scalar(@{$spy_ids}) <= 4) { - # we're ok + my $spies_to_send = scalar(@{$args->{spy_ids}}); + + if ($spies_to_send < 1) { + confess [1013, "You can't send a fleet with no spies."]; } - elsif ($ship->hold_size <= (scalar(@{$spy_ids}) * 350)) { - confess [1010, "The ship cannot hold the spies selected."]; + + if ($fleet->max_occupants * $args->{ship_quantity} < $spies_to_send) { + confess [1010, "That number of ships cannot hold the spies selected."]; } - - # get a spies + + # get the spies my @ids_sent; my @ids_not_sent; - my $spies = Lacuna->db->resultset('Lacuna::DB::Result::Spies'); - foreach my $id (@{$spy_ids}) { + my $spies = Lacuna->db->resultset('Spies'); + my $arrives; + + if ($args->{arrival_date}{soonest}) { + $arrives = DateTime->now->add(seconds => $fleet->calculate_travel_time($to_body)); + } + else { + $arrives = $self->calculate_arrival($fleet, $to_body, $args->{arrival_date}); + } + + foreach my $id (@{$args->{spy_ids}}) { my $spy = $spies->find($id); - if ($spy->is_available and $spy->on_body_id == $on_body_id) { + if ($spy->is_available and $spy->on_body_id == $on_body->id) { if ($spy->empire_id == $empire->id) { - my $arrives = DateTime->now->add(seconds=>$ship->calculate_travel_time($to_body)); push @ids_sent, $spy->id; $spy->send($to_body->id, $arrives)->update; } @@ -383,13 +439,14 @@ sub send_spies { } if (scalar @ids_sent) { # send it - $ship->send( + my $fleet = $fleet->split($args->{ship_quantity}); + $fleet->send( target => $to_body, payload => {spies => \@ids_sent }, # add the spies to the payload when we send, otherwise they'll get added again ); } return { - ship => $ship->get_status, + fleet => $fleet->get_status, spies_sent => \@ids_sent, spies_not_sent => \@ids_not_sent, status => $self->format_status($empire, $on_body) @@ -397,46 +454,64 @@ sub send_spies { } sub prepare_fetch_spies { - my ($self, $session_id, $on_body_id, $to_body_id) = @_; - my $empire = $self->get_empire_by_session($session_id); - my $to_body = $self->get_body($empire, $to_body_id); - my $on_body = Lacuna->db->resultset('Lacuna::DB::Result::Map::Body')->find($on_body_id); - unless ($on_body->empire_id) { - confess [1013, "Cannot fetch spies from an uninhabited planet."]; - } + my $self = shift; + my $args = shift; - my $max_berth = $to_body->max_berth; - unless ($max_berth) { - $max_berth = 1; + if (ref($args) ne "HASH") { + $args = { + session_id => $args, + on_body_id => shift, + to_body_id => shift, + }; } - - my $ships = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search( - {type => { in => [qw(spy_pod cargo_ship smuggler_ship dory spy_shuttle barge)]}, - task=>'Docked', body_id => $to_body_id, - berth_level => {'<=' => $max_berth } }, - {order_by => 'name', rows=>100} - ); - my @ships; - while (my $ship = $ships->next) { - push @ships, $ship->get_status($on_body); + my $empire = $self->get_empire_by_session($args->{session_id}); + if ($args->{on_body_id}) { + $args->{on_body} = { body_id => $args->{on_body_id}}; } - - my $spies = Lacuna->db->resultset('Lacuna::DB::Result::Spies')->search( - { - on_body_id => $on_body->id, - empire_id => $empire->id, - -or => [ - task => { in => [ 'Idle', 'Counter Espionage' ], }, - -and => [ - task => { in => [ 'Unconscious', 'Debriefing' ], }, - available_on => { '<' => '\NOW()' }, - ], + my $to_body = $self->get_body($empire, $args->{to_body_id}); + my $on_body = $self->find_target($args->{on_body}); + if (not $on_body->isa('Lacuna::DB::Result::Map::Body::Planet')) { + confess [1009, "Can only fetch spies from a planet."]; + } + if (not $on_body->empire_id) { + confess [1013, "Cannot fetch spies from an uninhabited body."]; + } + + my $max_berth = $to_body->max_berth || 1; + + my $fleets_rs = Lacuna->db->resultset('Fleet')->search({ + type => { in => [qw(spy_pod cargo_ship smuggler_ship dory spy_shuttle barge)]}, + task => 'Docked', + body_id => $to_body->id, + berth_level => {'<=' => $max_berth }, + },{ + order_by => 'name', + rows => 100, + }); + my @fleets; + while (my $fleet = $fleets_rs->next) { + push @fleets, $fleet->get_status($on_body); + } + + # Get all available spies (is this common enough to code in Spies?) + my $spies_rs = Lacuna->db->resultset('Spies')->search({ + on_body_id => $on_body->id, + empire_id => $empire->id, + -or => [ + task => { in => [ 'Idle', 'Counter Espionage' ], }, + -and => [ + task => { in => [ 'Unconscious', 'Debriefing' ], }, + available_on => { '<' => '\NOW()' }, ], - }, - {order_by => 'name', rows=>100} + ], + },{ + order_by => 'name', + rows => 100, + } ); + my @spies; - while (my $spy = $spies->next) { + while (my $spy = $spies_rs->next) { $spy->on_body($on_body); if ($spy->is_available) { push @spies, $spy->get_status; @@ -445,56 +520,74 @@ sub prepare_fetch_spies { return { status => $self->format_status($empire), - ships => \@ships, + fleets => \@fleets, spies => \@spies, }; } sub fetch_spies { - my ($self, $session_id, $on_body_id, $to_body_id, $ship_id, $spy_ids) = @_; - my $empire = $self->get_empire_by_session($session_id); - my $to_body = $self->get_body($empire, $to_body_id); - my $on_body = Lacuna->db->resultset('Lacuna::DB::Result::Map::Body')->find($on_body_id); + my $self = shift; + my $args = shift; + if (ref($args) ne "HASH") { + $args = { + session_id => $args, + on_body_id => shift, + to_body_id => shift, + fleet_id => shift, + spy_ids => shift, + }; + } + my $empire = $self->get_empire_by_session($args->{session_id}); + if ($args->{on_body_id}) { + $args->{on_body} = { body_id => $args->{on_body_id}}; + } + my $to_body = $self->get_body($empire, $args->{to_body_id}); + my $on_body = $self->find_target($args->{on_body}); + if (not $on_body->isa('Lacuna::DB::Result::Map::Body::Planet')) { + confess [1009, "Can only fetch spies from a planet."]; + } + if (not $on_body->empire_id) { + confess [1013, "Cannot fetch spies from an uninhabited body."]; + } my $max_berth = $to_body->max_berth; - # get the ship - my $ship = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->find($ship_id); - unless (defined $ship) { - confess [1002, "Ship not found."]; + # get the fleet + my $fleet = Lacuna->db->resultset('Fleet')->find($args->{fleet_id}); + unless (defined $fleet) { + confess [1002, "Fleet not found."]; } - unless ($ship->is_available || ($ship->can_recall && $ship->foreign_body_id == $on_body_id)) { - confess [1010, "That ship is not available."]; + unless ($fleet->is_available || ($fleet->can_recall && $fleet->foreign_body_id == $on_body->id)) { + confess [1010, "That fleet is not available."]; } - unless ($ship->berth_level <= $max_berth) { - confess [1010, "Your spaceport level is not high enough to support a ship with a Berth Level of ".$ship->berth_level."."]; + if ($fleet->berth_level > $max_berth) { + confess [1010, "Your spaceport level is not high enough to support a fleet with a Berth Level of ".$fleet->berth_level."."]; } - unless ($on_body->empire_id) { + if (not $on_body->empire_id) { confess [1013, "Cannot fetch spies from an uninhabited planet."]; } - unless (scalar(@{$spy_ids})) { - confess [1013, "You can't send a ship to collect no spies."]; + if (not scalar(@{$args->{spy_ids}})) { + confess [1013, "You can't send a fleet to collect no spies."]; } # check size - if ($ship->type eq 'spy_shuttle' && scalar(@{$spy_ids}) <= 4) { - # we're ok - } - elsif ($ship->hold_size <= (scalar(@{$spy_ids}) * 350)) { - confess [1013, "The ship cannot hold the spies selected."]; + my $no_of_ships = ceil(scalar(@{$args->{spy_ids}}) / $fleet->max_occupants); + if ($fleet->quantity < $no_of_ships) { + confess [1013, "The fleet cannot hold the spies selected."]; } # send it - $ship->send( + $fleet = $fleet->split($no_of_ships); + $fleet->send( target => $on_body, - payload => { fetch_spies => $spy_ids }, + payload => { fetch_spies => $args->{spy_ids}}, ); return { - ship => $ship->get_status, + fleet => $fleet->get_status, status => $self->format_status($empire, $to_body), }; } @@ -712,6 +805,40 @@ sub view_orbiting_fleets { return $self->_view_fleets($args); } +sub view_mining_platforms { + my $self = shift; + my $args = shift; + + if (ref($args) ne "HASH") { + $args = { + session_id => $args, + target => shift, + }; + } + my $empire = $self->get_empire_by_session($args->{session_id}); + my $target = $self->find_target($args->{target}); + my $platform_rs = Lacuna->db->resultset('MiningPlatforms'); + if (not $target->isa('Lacuna::DB::Result::Map::Body::Asteroid')) { + confess [1002, 'Target is not an Asteroid.']; + } + $platform_rs = $platform_rs->search({ + asteroid_id => $target->id, + },{ + prefetch => {planet => 'empire'}, + }); + my @platforms; + while (my $platform = $platform_rs->next) { + push @platforms, { + empire_id => $platform->planet->empire_id, + empire_name => $platform->planet->empire->name, + }; + } + my %out = ( + status => $self->format_status($empire), + mining_platforms => \@platforms, + ); + return \%out; +} -- 2.51.2