From 50b4e0d7534e9951008aca49ae69d31af5592307 Mon Sep 17 00:00:00 2001 From: ian docherty Date: Mon, 7 May 2012 04:54:34 -0400 Subject: [PATCH 1/9] Added code for resource-chains --- docs/Trade.pod | 162 ++++++++++++++++++++- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 85 +++++++++-- lib/Lacuna/DB/Result/ResourceChain.pm | 44 ++++++ lib/Lacuna/DB/Result/Ships.pm | 2 +- lib/Lacuna/DB/Result/Ships/Barge.pm | 2 +- lib/Lacuna/DB/Result/Ships/CargoShip.pm | 2 +- lib/Lacuna/DB/Result/Ships/Dory.pm | 2 +- lib/Lacuna/DB/Result/Ships/Freighter.pm | 2 +- lib/Lacuna/DB/Result/Ships/Galleon.pm | 2 +- lib/Lacuna/DB/Result/Ships/Hulk.pm | 2 +- lib/Lacuna/DB/Result/Ships/HulkFast.pm | 2 +- lib/Lacuna/DB/Result/Ships/HulkHuge.pm | 2 +- lib/Lacuna/DB/Result/Ships/Scow.pm | 2 +- lib/Lacuna/DB/Result/Ships/ScowFast.pm | 2 +- lib/Lacuna/DB/Result/Ships/ScowLarge.pm | 2 +- lib/Lacuna/DB/Result/Ships/ScowMega.pm | 2 +- lib/Lacuna/DB/Result/Ships/SmugglerShip.pm | 2 +- lib/Lacuna/RPC/Building/Trade.pm | 153 ++++++++++++++++++- var/upgrades/3.0850.sql | 18 +++ var/www/public/changes.txt | 5 + 20 files changed, 463 insertions(+), 32 deletions(-) create mode 100644 lib/Lacuna/DB/Result/ResourceChain.pm create mode 100644 var/upgrades/3.0850.sql diff --git a/docs/Trade.pod b/docs/Trade.pod index cda8f0d2..854430cf 100644 --- a/docs/Trade.pod +++ b/docs/Trade.pod @@ -561,6 +561,79 @@ A session id. The unique id of the trade ministry. + +=head2 get_resource_ships ( session_id, building_id ) + +Returns a list of the ships that are either working to transport resources or available. + + { + "status" : { ... }, + "ships" : [ + { + "id" : "id-goes-here", + "type" : "hulk", + "task" : "Resource Chain", + "name" : "Big Momma 1", + "speed" : 1000, + "hold_size" : 4000000, + }, + ... + ] + } + + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of the trade ministry. + + +=head2 view_resource_chains ( session_id, building_id ) + +Returns a list of the resource chains currently controlled by this Trade Ministry + + { + "status" : { ... }, + "resource_chain" : [ + { + "id" : "id-goes-here", + "body" : { + "id" : "id-goes-here", + "name" : "Mars", + "x" : 0, + "y" : -123, + ... + }, + "building_id" : 1234567, + "resource_hour" : 10000000, + "resource_type" : 'water', + "percent_transferred" : 95, + } + ] + } + +You can set up three resource-chains for each level of your Trade Ministry. Each +resource-chain can transfer any amount of any one resource (food type, ore type +energy, waste or water). + +The B is the identifier for the Trade Ministry that is the source of the +resource chain. + +The B is the name of the resource you wish to transfer (e.g. 'Gold'); + +The B is the amount of that resource you wish to transfer each hour. + +The B is the percentage of B that is actually transferred. +This is based on the number of ships you have servicing the chain. If you have no ships then +the B will be zero. If it is below 100 then you need to add ships so that +it is at or above 100. Above 100 and you have more ship capacity than you need, but you will +still only transfer the specified B, it just means some ships will be idle or not +fully filled. + + =head2 view_waste_chains ( session_id, building_id ) Returns a list of the waste chains currently controlled by this Trade Ministry @@ -583,6 +656,8 @@ Returns a list of the waste chains currently controlled by this Trade Ministry ] } +Note, there is no need to create a waste chain, all planets have a waste chain by default. + There should only be one waste-chain in action, to your local star. There is no point in setting up a waste-chain to any other star. @@ -595,15 +670,77 @@ it is at or above 100. Above 100 and you have more ship capacity than you need, still only transfer the specified B, it just means some ships will be idle or not fully filled. + +=head2 create_resource_chain (session_id, building_id, resource_type, resource_hour) + +Create a new resource chain. + +B is the identifier of the Trade Ministry building. + +B is the resource you want to push, e.g. 'waste','water','gold','energy','apple' + +B is the amount of the resource you want to transfer each hour. + +Returns the same as the call to B + + +=head2 delete_resource_chain (session_id, building_id, resource_chain_id) + +Delete the resource chain identified by the B + +Returns the same as the call to B + + +=head2 update_resource_chain ( session_id, building_id, waste_chain_id, resource_type, resource_hour) + +Change the B and B for the Resource Chain specified by B + +Returns the same as the call to B + +Note, the B may drop below 100% as a result of changing the amount of +B if you don't have enough ships to transfer the amount of resorces in all +resource chains. + +You may set the resource_hour to zero if you want to suspend the resource chain to the target planet. + +If you want to remove the resource chain totally then call B + =head2 update_waste_chain ( session_id, building_id, waste_chain_id, waste_hour) Change the B for the Waste Chain specified by B Returns the same as the call to B -Note, the B may be modified as a result of changing the amount of +Note, the B may drop below 100% as a result of changing the amount of B if you don't have enough ships to transfer the full amount of waste. +Note, there is no B because all planets have a waste chain by default. + +You may set the B to zero if you want to stop transferring waste. + +=head2 add_resource_ship_to_fleet (session_id, building_id, ship_id ) + +Take a ship from your space port and add it to the ships servicing the resource chains. + + { + "status" : { ... }, + } + +Throws 1009. + +=head3 session_id + +A Session ID. + +=head3 building_id + +The unique ID of the Trade Ministry. + +=head3 ship_id + +The unique ID of the ship you want to add to the fleet. + + =head2 add_waste_ship_to_fleet (session_id, building_id, ship_id ) Take a scow from your space port and add it to the ships servicing the waste pushes. @@ -626,6 +763,29 @@ The unique ID of the Trade Ministry. The unique ID of the ship you want to add to the fleet. +=head2 remove_resource_ship_from_fleet (session_id, building_id, ship_id ) + +Remove a ship from servicing your resource chains and tell it to return to the space port. + + { + "status" : { ... }, + } + +Throws 1009. + +=head3 session_id + +A Session ID. + +=head3 building_id + +The unique ID of the Trade Ministry. + +=head3 ship_id + +The unique ID of the ship you want to remove from the fleet. + + =head2 remove_waste_ship_from_fleet (session_id, building_id, ship_id ) Remove a ship from servicing you waste management and tell it to return to the space port. diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 331bce6e..1a8d3195 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -6,7 +6,7 @@ use utf8; no warnings qw(uninitialized); extends 'Lacuna::DB::Result::Map::Body'; use Lacuna::Constants qw(FOOD_TYPES ORE_TYPES BUILDABLE_CLASSES SPACE_STATION_MODULES); -use List::Util qw(shuffle); +use List::Util qw(shuffle max); use Lacuna::Util qw(randint format_date); use DateTime; no warnings 'uninitialized'; @@ -873,6 +873,35 @@ has total_ore_concentration => ( }, ); +sub is_food { + my ($self, $resource) = @_; + + if (grep {$resource eq $_} (FOOD_TYPES)) { + return 1; + } + return; +} + +sub is_ore { + my ($self, $resource) = @_; + + if (grep {$resource eq $_} (ORE_TYPES)) { + return 1; + } + return; +} + +# convert a resource name into a planet attribute name +# +sub resource_name { + my ($self,$resource) = @_; + + if ($self->is_food($resource)) { + return $resource.'_production_hour'; + } + return $resource.'_hour'; +} + sub recalc_stats { my ($self) = @_; @@ -884,6 +913,9 @@ sub recalc_stats { foreach my $type (FOOD_TYPES) { $stats{$type.'_production_hour'} = 0; } + foreach my $type (ORE_TYPES) { + $stats{$type.'_hour'} = 0; + } #calculate building production my ($gas_giant_platforms, $terraforming_platforms, $station_command, $pantheon_of_hagness, $total_ore_production_hour, $ore_production_hour, $ore_consumption_hour) = 0; while (my $building = $buildings->next) { @@ -917,17 +949,25 @@ sub recalc_stats { # Calculate the amount of waste to deduct based on the waste_chains my $waste_chains = Lacuna->db->resultset('Lacuna::DB::Result::WasteChain')->search({planet_id => $self->id}); while (my $waste_chain = $waste_chains->next) { - my $waste_hour = 0; - if ($waste_chain->percent_transferred > 0) { - if ($waste_chain->percent_transferred >= 100) { - $waste_hour = $waste_chain->waste_hour; - } - else { - $waste_hour = sprintf('%.0f',$waste_chain->waste_hour * $waste_chain->percent_transferred / 100); - } - } + my $percent = $waste_chain->percent_transferred; + $percent = $percent > 100 ? 100 : $percent; + $percent *= $building->efficiency; + my $waste_hour = sprintf('%.0f',$waste_chain->waste_hour * $percent / 100); $stats{waste_hour} -= $waste_hour; } + # calculate the resources being chained *from* this planet + my $output_chains = Lacuna->db->resultset('Lacuna::DB::Result::ResourceChain')->search({planet_id => $self->id}); + while (my $out_chain = $output_chains->next) { + my $percent = $out_chain->percent_transferred; + $percent = $percent > 100 ? 100 : $percent; + $percent *= $building->efficiency / 100; + my $resource_hour = sprintf('%.0f',$out_chain->resource_hour * $percent / 100); + my $resource_name = $self->resource_name($out_chain->resource_type); + $stats{$resource_name} -= $resource_hour; + if ($self->is_ore($out_chain->resource_type)) { + $total_ore_production_hour -= $resource_hour; + } + } } if ($building->isa('Lacuna::DB::Result::Building::Permanent::GasGiantPlatform')) { $gas_giant_platforms += $building->level; @@ -943,6 +983,23 @@ sub recalc_stats { } } + # resource chains sent *to* this planet + my $input_chains = Lacuna->db->resultset('Lacuna::DB::Result::ResourceChain')->search({ + target_id => $self->id, + },{prefetch => 'building'} + ); + while (my $in_chain = $input_chains->next) { + my $percent = $in_chain->percent_transferred; + $percent = $percent > 100 ? 100 : $percent; + $percent *= $in_chain->building->efficiency / 100; + my $resource_hour = sprintf('%.0f',$in_chain->resource_hour * $percent / 100); + my $resource_name = $self->resource_name($in_chain->resource_type); + $stats{$resource_name} += $resource_hour; + if ($self->is_ore($in_chain->resource_type)) { + $total_ore_production_hour += $resource_hour; + } + } + # local ore production foreach my $type (ORE_TYPES) { my $method = $type.'_hour'; @@ -961,12 +1018,8 @@ sub recalc_stats { $stats{ore_hour} = $total_ore_production_hour - $ore_consumption_hour; # deal with negative amounts stored - if ($self->water_stored < 0) { - $self->water_stored(0); - } - if ($self->energy_stored < 0) { - $self->energy_stored(0); - } + $self->water_stored = 0 if $self->water_stored < 0; + $self->energy_stored = 0 if $self->energy_stored < 0; for my $type (FOOD_TYPES, ORE_TYPES) { my $stype = $type.'_stored'; $self->$stype(0) if ($self->$stype < 0); diff --git a/lib/Lacuna/DB/Result/ResourceChain.pm b/lib/Lacuna/DB/Result/ResourceChain.pm new file mode 100644 index 00000000..09827434 --- /dev/null +++ b/lib/Lacuna/DB/Result/ResourceChain.pm @@ -0,0 +1,44 @@ +package Lacuna::DB::Result::ResourceChain; + +use Moose; +use utf8; +no warnings qw(uninitialized); +extends 'Lacuna::DB::Result'; + +__PACKAGE__->table('resource_chain'); +__PACKAGE__->add_columns( + planet_id => { data_type => 'int', size => 11, is_nullable => 0 }, + building_id => { data_type => 'int', size => 11, is_nullable => 0 }, + target_id => { data_type => 'int', size => 11, is_nullable => 0 }, + resource_hour => { data_type => 'int', size => 11, default_value => 0 }, + resource_type => { data_type => 'varchar', default_value => '' }, + percent_transferred => { data_type => 'int', size => 11, default_value => 0 }, +); + +__PACKAGE__->belongs_to('target', 'Lacuna::DB::Result::Map::Body', 'target_id'); +__PACKAGE__->belongs_to('building', 'Lacuna::DB::Result::Building', 'building_id'); +__PACKAGE__->belongs_to('planet', 'Lacuna::DB::Result::Map::Body', 'planet_id'); + +sub get_status { + my ($self) = @_; + + my $target = $self->target; + return { + id => $self->id, + body => { + id => $target->id, + name => $target->name, + x => $target->x, + y => $target->y, + image => $target->image, + }, + building_id => $self->building_id, + resource_hour => $self->resource_hour, + resource_type => $self->resource_type, + percent_transferred => $self->percent_transferred, + }; +} + + +no Moose; +__PACKAGE__->meta->make_immutable(inline_constructor => 0); diff --git a/lib/Lacuna/DB/Result/Ships.pm b/lib/Lacuna/DB/Result/Ships.pm index 131cdeb6..c6ccc5d8 100644 --- a/lib/Lacuna/DB/Result/Ships.pm +++ b/lib/Lacuna/DB/Result/Ships.pm @@ -236,7 +236,7 @@ sub get_status { $status{from} = $from; $status{date_arrives} = $status{date_available}; } - elsif ($self->task ~~ [qw(Defend Orbiting)]) { + elsif ($self->task ~~ [qw(Defend Orbiting)]) { my $body = $self->body; my $from = { id => $body->id, diff --git a/lib/Lacuna/DB/Result/Ships/Barge.pm b/lib/Lacuna/DB/Result/Ships/Barge.pm index b7aa7afb..6ab8a3b4 100644 --- a/lib/Lacuna/DB/Result/Ships/Barge.pm +++ b/lib/Lacuna/DB/Result/Ships/Barge.pm @@ -17,7 +17,7 @@ use constant base_stealth => 2450; use constant base_hold_size => 800; use constant base_berth_level => 1; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining Intelligence)]; +use constant build_tags => [qw(Trade Mining Intelligence ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CaptureWithSpies"; diff --git a/lib/Lacuna/DB/Result/Ships/CargoShip.pm b/lib/Lacuna/DB/Result/Ships/CargoShip.pm index 69e1b1d6..a2ec938a 100644 --- a/lib/Lacuna/DB/Result/Ships/CargoShip.pm +++ b/lib/Lacuna/DB/Result/Ships/CargoShip.pm @@ -17,7 +17,7 @@ use constant base_stealth => 1500; use constant base_hold_size => 1700; use constant base_berth_level => 5; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining Intelligence)]; +use constant build_tags => [qw(Trade Mining Intelligence ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CaptureWithSpies"; diff --git a/lib/Lacuna/DB/Result/Ships/Dory.pm b/lib/Lacuna/DB/Result/Ships/Dory.pm index 4dcb73a7..40fb9d14 100644 --- a/lib/Lacuna/DB/Result/Ships/Dory.pm +++ b/lib/Lacuna/DB/Result/Ships/Dory.pm @@ -17,7 +17,7 @@ use constant base_stealth => 4100; use constant base_hold_size => 400; use constant base_berth_level => 1; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining Intelligence)]; +use constant build_tags => [qw(Trade Mining Intelligence ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CaptureWithSpies"; diff --git a/lib/Lacuna/DB/Result/Ships/Freighter.pm b/lib/Lacuna/DB/Result/Ships/Freighter.pm index e9a50957..68693aa3 100644 --- a/lib/Lacuna/DB/Result/Ships/Freighter.pm +++ b/lib/Lacuna/DB/Result/Ships/Freighter.pm @@ -18,7 +18,7 @@ use constant base_stealth => 0; use constant base_hold_size => 4000; use constant base_berth_level => 15; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining)]; +use constant build_tags => [qw(Trade Mining ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/Galleon.pm b/lib/Lacuna/DB/Result/Ships/Galleon.pm index 8f84eb24..e1861392 100644 --- a/lib/Lacuna/DB/Result/Ships/Galleon.pm +++ b/lib/Lacuna/DB/Result/Ships/Galleon.pm @@ -17,7 +17,7 @@ use constant base_stealth => 0; use constant base_hold_size => 1750; use constant base_berth_level => 10; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining)]; +use constant build_tags => [qw(Trade Mining ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/Hulk.pm b/lib/Lacuna/DB/Result/Ships/Hulk.pm index 6af5e52b..b5760ac9 100644 --- a/lib/Lacuna/DB/Result/Ships/Hulk.pm +++ b/lib/Lacuna/DB/Result/Ships/Hulk.pm @@ -18,7 +18,7 @@ use constant base_stealth => 0; use constant base_hold_size => 7900; use constant base_berth_level => 20; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining)]; +use constant build_tags => [qw(Trade Mining ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/HulkFast.pm b/lib/Lacuna/DB/Result/Ships/HulkFast.pm index 97938a72..be95bedc 100644 --- a/lib/Lacuna/DB/Result/Ships/HulkFast.pm +++ b/lib/Lacuna/DB/Result/Ships/HulkFast.pm @@ -19,7 +19,7 @@ use constant base_stealth => 0; use constant base_hold_size => 10000; use constant base_berth_level => 25; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining)]; +use constant build_tags => [qw(Trade Mining ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/HulkHuge.pm b/lib/Lacuna/DB/Result/Ships/HulkHuge.pm index 133b6e9b..3308fd34 100644 --- a/lib/Lacuna/DB/Result/Ships/HulkHuge.pm +++ b/lib/Lacuna/DB/Result/Ships/HulkHuge.pm @@ -18,7 +18,7 @@ use constant base_stealth => 0; use constant base_hold_size => 170100; use constant base_berth_level => 30; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining)]; +use constant build_tags => [qw(Trade Mining ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/Scow.pm b/lib/Lacuna/DB/Result/Ships/Scow.pm index 043720b6..249dc2ab 100644 --- a/lib/Lacuna/DB/Result/Ships/Scow.pm +++ b/lib/Lacuna/DB/Result/Ships/Scow.pm @@ -16,7 +16,7 @@ use constant base_speed => 420; use constant base_combat => 500; use constant base_stealth => 0; use constant base_hold_size => 2000; -use constant build_tags => [qw(War Trade)]; +use constant build_tags => [qw(War WasteChain)]; with "Lacuna::Role::Ship::Send::PlanetAndStar"; with "Lacuna::Role::Ship::Send::MaybeHostile"; diff --git a/lib/Lacuna/DB/Result/Ships/ScowFast.pm b/lib/Lacuna/DB/Result/Ships/ScowFast.pm index 087c37d9..43e7b752 100644 --- a/lib/Lacuna/DB/Result/Ships/ScowFast.pm +++ b/lib/Lacuna/DB/Result/Ships/ScowFast.pm @@ -18,7 +18,7 @@ use constant base_combat => 500; use constant base_stealth => 0; use constant base_hold_size => 2000; use constant base_berth_level => 20; -use constant build_tags => [qw(War Trade)]; +use constant build_tags => [qw(War WasteChain)]; with "Lacuna::Role::Ship::Send::PlanetAndStar"; with "Lacuna::Role::Ship::Send::MaybeHostile"; diff --git a/lib/Lacuna/DB/Result/Ships/ScowLarge.pm b/lib/Lacuna/DB/Result/Ships/ScowLarge.pm index d466a4f1..2a3c1d1f 100644 --- a/lib/Lacuna/DB/Result/Ships/ScowLarge.pm +++ b/lib/Lacuna/DB/Result/Ships/ScowLarge.pm @@ -17,7 +17,7 @@ use constant base_combat => 600; use constant base_stealth => 0; use constant base_hold_size => 12000; use constant base_berth_level => 15; -use constant build_tags => [qw(War Trade)]; +use constant build_tags => [qw(War WasteChain)]; with "Lacuna::Role::Ship::Send::PlanetAndStar"; with "Lacuna::Role::Ship::Send::MaybeHostile"; diff --git a/lib/Lacuna/DB/Result/Ships/ScowMega.pm b/lib/Lacuna/DB/Result/Ships/ScowMega.pm index ec4e1e94..cadb28ad 100644 --- a/lib/Lacuna/DB/Result/Ships/ScowMega.pm +++ b/lib/Lacuna/DB/Result/Ships/ScowMega.pm @@ -17,7 +17,7 @@ use constant base_combat => 0; use constant base_stealth => 0; use constant base_hold_size => 300000; use constant base_berth_level => 25; -use constant build_tags => [qw(War Trade)]; +use constant build_tags => [qw(War WasteChain)]; with "Lacuna::Role::Ship::Send::PlanetAndStar"; with "Lacuna::Role::Ship::Send::MaybeHostile"; diff --git a/lib/Lacuna/DB/Result/Ships/SmugglerShip.pm b/lib/Lacuna/DB/Result/Ships/SmugglerShip.pm index 374a01d8..22a9e23c 100644 --- a/lib/Lacuna/DB/Result/Ships/SmugglerShip.pm +++ b/lib/Lacuna/DB/Result/Ships/SmugglerShip.pm @@ -17,7 +17,7 @@ use constant base_stealth => 5000; use constant base_hold_size => 520; use constant base_berth_level => 10; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining Intelligence)]; +use constant build_tags => [qw(Trade Mining Intelligence ResourceChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CaptureWithSpies"; diff --git a/lib/Lacuna/RPC/Building/Trade.pm b/lib/Lacuna/RPC/Building/Trade.pm index a14585a8..2c7bb497 100644 --- a/lib/Lacuna/RPC/Building/Trade.pm +++ b/lib/Lacuna/RPC/Building/Trade.pm @@ -6,6 +6,8 @@ use utf8; no warnings qw(uninitialized); extends 'Lacuna::RPC::Building'; use Guard; +use List::Util qw(first); +use Lacuna::Constants qw(FOOD_TYPES ORE_TYPES); with 'Lacuna::Role::TraderRpc','Lacuna::Role::Ship::Trade'; @@ -34,10 +36,47 @@ sub get_trade_ships { }; } +sub add_resource_ship_to_fleet { + my ($self, $session_id, $building_id, $ship_id) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + unless (defined $building) { + confess [1002, "Building not found."]; + } + my $ship = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->find($ship_id); + unless (defined $ship) { + confess [1002, "Ship not found."]; + } + unless ($ship->task eq 'Docked') { + confess [1009, "That ship is not available."]; + } + unless ($ship->hold_size > 0) { + confess [1009, 'That ship has no cargo hold.']; + } + unless ($ship->body_id eq $building->body_id) { + confess [1013, "You can't manage a ship that is not yours."]; + } + unless (first {$ship->type eq $_} (qw(cargo_ship smuggler_ship freighter dory barge galleon hulk hulk_huge hulk_fast))) { + confess [1009, 'You can only add transport ships to a resource chain.']; + } + my $max_berth = $building->body->max_berth; + + unless ($ship->berth_level <= $max_berth) { + confess [1009, "You don't have a high enough berth for this ship."]; + } + $building->add_resource_ship($ship); + return { + status =>$self->format_status($empire, $building->body), + }; +} + sub add_waste_ship_to_fleet { my ($self, $session_id, $building_id, $ship_id) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); + unless (defined $building) { + confess [1002, "Building not found."]; + } my $ship = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->find($ship_id); unless (defined $ship) { confess [1002, "Ship not found."]; @@ -65,10 +104,46 @@ sub add_waste_ship_to_fleet { }; } +sub remove_resource_ship_from_fleet { + my ($self, $session_id, $building_id, $ship_id) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + unless (defined $building) { + confess [1002, "Building not found."]; + } + + my $ship = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->find($ship_id); + unless (defined $ship) { + confess [1002, "Ship not found."]; + } + unless ($ship->task eq 'Resource Chain') { + confess [1009, "That ship is not in a Resource Chain."]; + } + unless ($ship->body_id eq $building->body_id) { + confess [1013, "You can't manage a ship that is not yours."]; + } + + my $resource_chain = $building->resource_chains->search({},{rows => 1})->single; + if (defined $resource_chain) { + my $from = $resource_chain->target_id; + $building->send_waste_ship_home($from, $ship); + } + else { + $ship->land->update; + } + return { + status => $self->format_status($empire, $building->body), + }; +} + sub remove_waste_ship_from_fleet { my ($self, $session_id, $building_id, $ship_id) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); + unless (defined $building) { + confess [1002, "Building not found."]; + } + my $ship = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->find($ship_id); unless (defined $ship) { confess [1002, "Ship not found."]; @@ -93,6 +168,23 @@ sub remove_waste_ship_from_fleet { }; } +sub get_resource_ships { + my ($self, $session_id, $building_id) = @_; + + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + + my @ships; + my $ships = $building->all_resource_ships; + while (my $ship = $ships->next) { + push @ships, $ship->get_status; + } + return { + status => $self->format_status($empire, $building->body), + ships => \@ships, + }; +} + sub get_waste_ships { my ($self, $session_id, $building_id) = @_; my $empire = $self->get_empire_by_session($session_id); @@ -111,10 +203,34 @@ sub get_waste_ships { }; } +sub view_resource_chains { + my ($self, $session_id, $building_id) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + unless ($building) { + confess [1002, "Cannot find that building."]; + } + + my $body = $building->body; + my @resource_chains; + my $chains = $building->resource_chains; + while (my $chain = $chains->next) { + push @resource_chains, $chain->get_status; + } + return { + status => $self->format_status($empire, $building->body), + resource_chain => \@resource_chain, + }; +} + + sub view_waste_chains { my ($self, $session_id, $building_id) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); + unless ($building) { + confess [1002, "Cannot find that building."]; + } my $body = $building->body; my @waste_chain; my $chains = $building->waste_chains; @@ -127,10 +243,45 @@ sub view_waste_chains { }; } +sub update_resource_chain { + my ($self, $session_id, $building_id, $resource_chain_id, $resource_type, $resource_hour) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + unless ($building) { + confess [1002, "Cannot find that building."]; + } + my $body = $building->body; + unless ($resource_chain_id) { + confess [1002, "You must specify a resource chain id."]; + } + unless (defined $resource_hour) { + confess [1002, "You must specify an amount for resource_hour."]; + } + unless ($resource_hour >= 0) { + confess [1002, "Resource per Hour must be positive or zero."]; + } + unless (first {$resource_type eq $_} (FOOD_TYPES, ORE_TYPES, qw(water waste energy))) { + confess [1002, "That is not a valid resource type."]; + } + my $chain = $building->resource_chains->find($resource_chain_id); + unless ($chain) { + confess [1002, "That Resource Chain does not exist on this planet."]; + } + $chain->resource_hour(int($resource_hour)); + $chain->resource_type($resource_type); + $chain->update; + $building->recalc_resource_production; + + return $self->view_resource_chains($session_id, $building_id); +} + sub update_waste_chain { my ($self, $session_id, $building_id, $waste_chain_id, $waste_hour) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); + unless ($building) { + confess [1002, "Cannot find that building."]; + } my $body = $building->body; unless ($waste_chain_id) { confess [1002, "You must specify a waste chain id."]; @@ -306,7 +457,7 @@ sub add_to_market { -__PACKAGE__->register_rpc_method_names(qw(get_waste_ships view_waste_chains add_waste_ship_to_fleet remove_waste_ship_from_fleet update_waste_chain report_abuse view_my_market view_market accept_from_market withdraw_from_market add_to_market push_items get_trade_ships get_stored_resources get_ships get_ship_summary get_prisoners get_plans get_plan_summary get_glyphs get_glyph_summary)); +__PACKAGE__->register_rpc_method_names(qw(get_resource_ships view_resource_chains add_resource_ship_to_fleet remove_resource_ship_from_fleet create_resource_chain delete_resource_chain update_resource_chain get_waste_ships view_waste_chains add_waste_ship_to_fleet remove_waste_ship_from_fleet update_waste_chain report_abuse view_my_market view_market accept_from_market withdraw_from_market add_to_market push_items get_trade_ships get_stored_resources get_ships get_ship_summary get_prisoners get_plans get_plan_summary get_glyphs get_glyph_summary)); no Moose; diff --git a/var/upgrades/3.0850.sql b/var/upgrades/3.0850.sql new file mode 100644 index 00000000..35a34e47 --- /dev/null +++ b/var/upgrades/3.0850.sql @@ -0,0 +1,18 @@ + +create table resource_chain ( + id int(11) not null auto_increment, + planet_id int(11) not null, + building_id int(11) not null, + target_id int(11) not null, + resource_hour int(11) not null default 0, + resource_type varchar(32) not null, + percent_transferred int(11) not null default 0, + primary key (id), + key rc_idx_planet_id (planet_id), + key rc_idx_building_id (building_id), + key rc_idx_target_id (target_id), + constraint rc_fk_planet_id foreign key (planet_id) references planet (id), + constraint rc_fk_building_id foreign key (building_id) references building (id), + constraint rc_fk_target_id foreign key (target_id) references planet (id) +); + diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index a7d7c389..07d81838 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,3 +1,8 @@ +2.0850: + - Add: API only, continuous push (resource chain) to any planet or SS. Note. No UI support yet. + - Fix: Damaged Trade Ministry reduces the waste transferred in a waste chain. + - Fix: Scows are no longer are tagged with 'Trade' + 3.0849: - Add: API only, continuous push (waste chain) to local star. Note. no UI support yet. -- 2.51.2 From 95daced94a8e07542f8597f97bcd40914db1a9e8 Mon Sep 17 00:00:00 2001 From: ian docherty Date: Thu, 10 May 2012 04:54:31 -0400 Subject: [PATCH 2/9] Refactor and more testing for Supply Chains --- docs/Trade.pod | 50 ++-- lib/Lacuna/Constants.pm | 11 +- lib/Lacuna/DB/Result/Building/Trade.pm | 123 ++++++--- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 42 +-- lib/Lacuna/DB/Result/Ships.pm | 2 - lib/Lacuna/DB/Result/Ships/Barge.pm | 2 +- lib/Lacuna/DB/Result/Ships/CargoShip.pm | 2 +- lib/Lacuna/DB/Result/Ships/Dory.pm | 2 +- lib/Lacuna/DB/Result/Ships/Freighter.pm | 2 +- lib/Lacuna/DB/Result/Ships/Galleon.pm | 2 +- lib/Lacuna/DB/Result/Ships/Hulk.pm | 2 +- lib/Lacuna/DB/Result/Ships/HulkFast.pm | 2 +- lib/Lacuna/DB/Result/Ships/HulkHuge.pm | 2 +- lib/Lacuna/DB/Result/Ships/SmugglerShip.pm | 2 +- .../{ResourceChain.pm => SupplyChain.pm} | 4 +- lib/Lacuna/RPC.pm | 2 +- lib/Lacuna/RPC/Building/MiningMinistry.pm | 9 +- lib/Lacuna/RPC/Building/Trade.pm | 68 ++--- t/410_Fleet_Actions.t | 245 +---------------- t/430_Supply_Chain.t | 93 +++++++ t/TestHelper.pm | 246 ++++++++++++++++++ var/upgrades/3.0850.sql | 2 +- var/www/public/changes.txt | 2 +- 23 files changed, 547 insertions(+), 370 deletions(-) rename lib/Lacuna/DB/Result/{ResourceChain.pm => SupplyChain.pm} (94%) create mode 100644 t/430_Supply_Chain.t diff --git a/docs/Trade.pod b/docs/Trade.pod index 854430cf..a54bad92 100644 --- a/docs/Trade.pod +++ b/docs/Trade.pod @@ -562,9 +562,9 @@ A session id. The unique id of the trade ministry. -=head2 get_resource_ships ( session_id, building_id ) +=head2 get_supply_ships ( session_id, building_id ) -Returns a list of the ships that are either working to transport resources or available. +Returns a list of the ships that are either working to transport supplies or available. { "status" : { ... }, @@ -591,13 +591,13 @@ A session id. The unique id of the trade ministry. -=head2 view_resource_chains ( session_id, building_id ) +=head2 view_supply_chains ( session_id, building_id ) -Returns a list of the resource chains currently controlled by this Trade Ministry +Returns a list of the supply chains currently controlled by this Trade Ministry { "status" : { ... }, - "resource_chain" : [ + "supply_chains" : [ { "id" : "id-goes-here", "body" : { @@ -615,12 +615,12 @@ Returns a list of the resource chains currently controlled by this Trade Ministr ] } -You can set up three resource-chains for each level of your Trade Ministry. Each -resource-chain can transfer any amount of any one resource (food type, ore type +You can set up three supply-chains for each level of your Trade Ministry. Each +supply-chain can transfer any amount of any one resource (food type, ore type energy, waste or water). The B is the identifier for the Trade Ministry that is the source of the -resource chain. +supply chain. The B is the name of the resource you wish to transfer (e.g. 'Gold'); @@ -671,9 +671,9 @@ still only transfer the specified B, it just means some ships will b fully filled. -=head2 create_resource_chain (session_id, building_id, resource_type, resource_hour) +=head2 create_supply_chain (session_id, building_id, resource_type, resource_hour) -Create a new resource chain. +Create a new supply chain. B is the identifier of the Trade Ministry building. @@ -681,29 +681,29 @@ B is the resource you want to push, e.g. 'waste','water','gold',' B is the amount of the resource you want to transfer each hour. -Returns the same as the call to B +Returns the same as the call to B -=head2 delete_resource_chain (session_id, building_id, resource_chain_id) +=head2 delete_supply_chain (session_id, building_id, supply_chain_id) -Delete the resource chain identified by the B +Delete the supply chain identified by the B -Returns the same as the call to B +Returns the same as the call to B -=head2 update_resource_chain ( session_id, building_id, waste_chain_id, resource_type, resource_hour) +=head2 update_supply_chain ( session_id, building_id, supply_chain_id, resource_type, resource_hour) -Change the B and B for the Resource Chain specified by B +Change the B and B for the supply Chain specified by B -Returns the same as the call to B +Returns the same as the call to B Note, the B may drop below 100% as a result of changing the amount of -B if you don't have enough ships to transfer the amount of resorces in all -resource chains. +B if you don't have enough ships to transfer the amount of resources in all +supply chains. -You may set the resource_hour to zero if you want to suspend the resource chain to the target planet. +You may set the resource_hour to zero if you want to suspend the supply chain to the target planet. -If you want to remove the resource chain totally then call B +If you want to remove the supply chain totally then call B =head2 update_waste_chain ( session_id, building_id, waste_chain_id, waste_hour) @@ -718,9 +718,9 @@ Note, there is no B because all planets have a waste chain b You may set the B to zero if you want to stop transferring waste. -=head2 add_resource_ship_to_fleet (session_id, building_id, ship_id ) +=head2 add_supply_ship_to_fleet (session_id, building_id, ship_id ) -Take a ship from your space port and add it to the ships servicing the resource chains. +Take a ship from your space port and add it to the ships servicing the supply chains. { "status" : { ... }, @@ -763,9 +763,9 @@ The unique ID of the Trade Ministry. The unique ID of the ship you want to add to the fleet. -=head2 remove_resource_ship_from_fleet (session_id, building_id, ship_id ) +=head2 remove_supply_ship_from_fleet (session_id, building_id, ship_id ) -Remove a ship from servicing your resource chains and tell it to return to the space port. +Remove a ship from servicing your supply chains and tell it to return to the space port. { "status" : { ... }, diff --git a/lib/Lacuna/Constants.pm b/lib/Lacuna/Constants.pm index 36150e81..3a4d7453 100644 --- a/lib/Lacuna/Constants.pm +++ b/lib/Lacuna/Constants.pm @@ -115,7 +115,12 @@ use constant SHIP_TYPES => (qw( probe short_range_colony_ship colony_ship spy_po spaceport_seeker excavator detonator scanner barge hulk hulk_fast hulk_huge galleon stake placebo placebo2 placebo3 placebo4 placebo5 placebo6 bleeder sweeper )); - +use constant SHIP_TRADE_TYPES => (qw( + cargo_ship smuggler_ship freighter dory barge galleon hulk hulk_huge hulk_fast +)); +use constant SHIP_WASTE_TYPES => (qw( + scow scow_fast scow_large scow_mega +)); our @EXPORT_OK = qw( INFLATION @@ -125,6 +130,8 @@ our @EXPORT_OK = qw( BUILDABLE_CLASSES SPACE_STATION_MODULES SHIP_TYPES + SHIP_TRADE_TYPES + SHIP_WASTE_TYPES ); our %EXPORT_TAGS = ( @@ -136,6 +143,8 @@ our %EXPORT_TAGS = ( BUILDABLE_CLASSES SPACE_STATION_MODULES SHIP_TYPES + SHIP_TRADE_TYPES + SHIP_WASTE_TYPES )], ); diff --git a/lib/Lacuna/DB/Result/Building/Trade.pm b/lib/Lacuna/DB/Result/Building/Trade.pm index 8835c714..1ce04735 100644 --- a/lib/Lacuna/DB/Result/Building/Trade.pm +++ b/lib/Lacuna/DB/Result/Building/Trade.pm @@ -7,6 +7,7 @@ use Carp; use utf8; use List::Util qw(max); use Data::Dumper; +use Lacuna::Constants qw(SHIP_TRADE_TYPES SHIP_WASTE_TYPES); no warnings qw(uninitialized); extends 'Lacuna::DB::Result::Building'; @@ -50,6 +51,13 @@ use constant water_consumption => 5; use constant waste_production => 1; +sub supply_chains { + my ($self) = @_; + + return Lacuna->db->resultset('Lacuna::DB::Result::SupplyChain')->search({ planet_id => $self->body_id }); +} + + sub waste_chains { my $self = shift; @@ -65,65 +73,70 @@ sub waste_chains { } return Lacuna->db->resultset('Lacuna::DB::Result::WasteChain')->search({ planet_id => $self->body_id }); } + +# Ships that are currently in a supply chain sub supply_ships { - my $self = shift; + my ($self) = @_; + return Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({ body_id => $self->body_id, task => 'Supply Chain', }); } +# Ships that are currently in a waste chain +sub waste_ships { + my ($self) = @_; + + return Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({ + body_id => $self->body_id, + task => 'Waste Chain', + }); +} + +# All ships that are either in a supply chain, or available to be so sub all_supply_ships { my $self = shift; + my $max_level = Lacuna->db->resultset('Lacuna::DB::Result::Building')->search({ + class => 'Lacuna::DB::Result::Building::SpacePort', + body_id => $self->body_id, + efficiency => 100, + })->get_column('level')->max || 0; return Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({ - body_id => $self->body_id, + body_id => $self->body_id, -or => { task => 'Supply Chain', -and => [ task => 'Docked', - type => { '=', [ - 'cargo_ship', - 'smuggler_ship', - 'freighter', - 'dory', - 'barge', - 'galleon', - 'hulk', - 'hulk_fast', - 'hulk_huge', - ]} + berth_level => {'<=' => $max_level}, + type => { '=', [SHIP_TRADE_TYPES]}, ] - } - }); -} - -# Ships that are currently in a waste chain -sub waste_ships { - my ($self) = @_; - - return Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({ - body_id => $self->body_id, - task => 'Waste Chain', + } + },{ + order_by => {-desc => [qw(task hold_size)]}, }); } # All ships that are either in a waste chain, or available to be so sub all_waste_ships { my $self = shift; + my $max_level = Lacuna->db->resultset('Lacuna::DB::Result::Building')->search({ + class => 'Lacuna::DB::Result::Building::SpacePort', + body_id => $self->body_id, + efficiency => 100, + })->get_column('level')->max || 0; return Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({ body_id => $self->body_id, -or => { task => 'Waste Chain', -and => [ task => 'Docked', - type => { '=', [ - 'scow', - 'scow_large', - 'scow_mega', - 'scow_fast', - ]} + berth_level => {'<=' => $max_level}, + type => { '=', [SHIP_WASTE_TYPES]}, ] } + },{ + order_by => {-desc => [qw(task hold_size)]}, }); } @@ -194,6 +207,52 @@ sub remove_waste_chain { return $self; } +sub remove_supply_chain { + my ($self, $supply_chain) = @_; + if ($self->supply_chain->count == 1) { + my $ships = $self->supply_ships; + while (my $ship = $ships->next) { + $self->sent_supply_ship_home($supply_chain->target, $ship); + } + } + $supply_chain->delete; + $self->recalc_supply_production; + return $self; +} + +sub recalc_supply_production { + my ($self) = @_; + my $body = $self->body; + + # Determine the resourc/hour/distance for the ship + my $ship_rphpd = 0; + my $ships = $self->supply_ships; + while (my $ship = $ships->next) { + $ship_rphpd += $ship->hold_size * $ship->speed; + } + # Determine the resource/hour for supply chains + my $chain_rphpd = 0; + my $supply_chains = $self->supply_chains; + while (my $supply_chain = $supply_chains->next) { + $chain_rphpd += $body->calculate_distance_to_target($supply_chain->target) * 2 * $supply_chain->resource_hour; + } + my $shipping_capacity = $chain_rphpd ? sprintf('%.0f',($ship_rphpd / $chain_rphpd) * 100) : 0; + + $supply_chains->reset; + while (my $supply_chain = $supply_chains->next) { + $supply_chain->percent_transferred($shipping_capacity); + $supply_chain->update; + } + + $body->needs_recalc(1); + $body->update; + + # TODO Do we need to recalc all target bodies? + # + return $self; +} + + sub recalc_waste_production { my ($self) = @_; my $body = $self->body; @@ -315,10 +374,10 @@ sub trade_ships { class => 'Lacuna::DB::Result::Building::SpacePort', body_id => $self->body_id, efficiency => 100, - } )->get_column('level')->max; + } )->get_column('level')->max || 0; return Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({ task => 'Docked', - type => { 'in' => [qw(dory barge galleon hulk hulk_huge hulk_fast cargo_ship freighter smuggler_ship)] }, + type => { 'in' => [SHIP_TRADE_TYPES] }, body_id => $self->body_id, berth_level => {'<=' => $max_level } }, diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 1a8d3195..67866f0f 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -14,7 +14,9 @@ no warnings 'uninitialized'; __PACKAGE__->has_many('ships','Lacuna::DB::Result::Ships','body_id'); __PACKAGE__->has_many('plans','Lacuna::DB::Result::Plans','body_id'); __PACKAGE__->has_many('glyphs','Lacuna::DB::Result::Glyphs','body_id'); - +__PACKAGE__->has_many('waste_chains', 'Lacuna::DB::Result::WasteChain','planet_id'); +__PACKAGE__->has_many('out_supply_chains', 'Lacuna::DB::Result::SupplyChain','planet_id'); +__PACKAGE__->has_many('in_supply_chains', 'Lacuna::DB::Result::SupplyChain','target_id'); sub surface { my $self = shift; @@ -126,6 +128,14 @@ sub sanitize { $self->alliance_id(undef); $self->plans->delete; $self->glyphs->delete; + $self->waste_chains->delete; + # do indivitual deletes so the remote ends can be titied up too + foreach my $chain ($self->out_supply_chains) { + $chain->delete; + } + foreach my $chain ($self->in_supply_chains) { + $chain->delete; + } my $incoming = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({foreign_body_id => $self->id, direction => 'out'}); while (my $ship = $incoming->next) { $ship->turn_around->update; @@ -647,8 +657,8 @@ sub has_resources_to_operate { my ($self, $building) = @_; # get future - my $future = $self->future_operating_resources; - + my $future = $self->future_operating_resources; + # get change for this building my $after = $building->stats_after_upgrade; @@ -956,16 +966,16 @@ sub recalc_stats { $stats{waste_hour} -= $waste_hour; } # calculate the resources being chained *from* this planet - my $output_chains = Lacuna->db->resultset('Lacuna::DB::Result::ResourceChain')->search({planet_id => $self->id}); + my $output_chains = Lacuna->db->resultset('Lacuna::DB::Result::SupplyChain')->search({planet_id => $self->id}); while (my $out_chain = $output_chains->next) { my $percent = $out_chain->percent_transferred; $percent = $percent > 100 ? 100 : $percent; $percent *= $building->efficiency / 100; - my $resource_hour = sprintf('%.0f',$out_chain->resource_hour * $percent / 100); - my $resource_name = $self->resource_name($out_chain->resource_type); - $stats{$resource_name} -= $resource_hour; - if ($self->is_ore($out_chain->resource_type)) { - $total_ore_production_hour -= $resource_hour; + my $supply_hour = sprintf('%.0f',$out_chain->supply_hour * $percent / 100); + my $resource_name = $self->resource_name($out_chain->supply_type); + $stats{$resource_name} -= $supply_hour; + if ($self->is_ore($out_chain->supply_type)) { + $total_ore_production_hour -= $supply_hour; } } } @@ -983,8 +993,8 @@ sub recalc_stats { } } - # resource chains sent *to* this planet - my $input_chains = Lacuna->db->resultset('Lacuna::DB::Result::ResourceChain')->search({ + # supply chains sent *to* this planet + my $input_chains = Lacuna->db->resultset('Lacuna::DB::Result::SupplyChain')->search({ target_id => $self->id, },{prefetch => 'building'} ); @@ -992,11 +1002,11 @@ sub recalc_stats { my $percent = $in_chain->percent_transferred; $percent = $percent > 100 ? 100 : $percent; $percent *= $in_chain->building->efficiency / 100; - my $resource_hour = sprintf('%.0f',$in_chain->resource_hour * $percent / 100); - my $resource_name = $self->resource_name($in_chain->resource_type); - $stats{$resource_name} += $resource_hour; - if ($self->is_ore($in_chain->resource_type)) { - $total_ore_production_hour += $resource_hour; + my $supply_hour = sprintf('%.0f',$in_chain->supply_hour * $percent / 100); + my $resource_name = $self->resource_name($in_chain->supply_type); + $stats{$resource_name} += $supply_hour; + if ($self->is_ore($in_chain->supply_type)) { + $total_ore_production_hour += $supply_hour; } } diff --git a/lib/Lacuna/DB/Result/Ships.pm b/lib/Lacuna/DB/Result/Ships.pm index c6ccc5d8..57908408 100644 --- a/lib/Lacuna/DB/Result/Ships.pm +++ b/lib/Lacuna/DB/Result/Ships.pm @@ -347,7 +347,5 @@ sub calculate_travel_time { return sprintf('%.0f', $seconds); } - - no Moose; __PACKAGE__->meta->make_immutable(inline_constructor => 0); diff --git a/lib/Lacuna/DB/Result/Ships/Barge.pm b/lib/Lacuna/DB/Result/Ships/Barge.pm index 6ab8a3b4..1ad3e389 100644 --- a/lib/Lacuna/DB/Result/Ships/Barge.pm +++ b/lib/Lacuna/DB/Result/Ships/Barge.pm @@ -17,7 +17,7 @@ use constant base_stealth => 2450; use constant base_hold_size => 800; use constant base_berth_level => 1; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining Intelligence ResourceChain)]; +use constant build_tags => [qw(Trade Mining Intelligence SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CaptureWithSpies"; diff --git a/lib/Lacuna/DB/Result/Ships/CargoShip.pm b/lib/Lacuna/DB/Result/Ships/CargoShip.pm index a2ec938a..a589e453 100644 --- a/lib/Lacuna/DB/Result/Ships/CargoShip.pm +++ b/lib/Lacuna/DB/Result/Ships/CargoShip.pm @@ -17,7 +17,7 @@ use constant base_stealth => 1500; use constant base_hold_size => 1700; use constant base_berth_level => 5; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining Intelligence ResourceChain)]; +use constant build_tags => [qw(Trade Mining Intelligence SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CaptureWithSpies"; diff --git a/lib/Lacuna/DB/Result/Ships/Dory.pm b/lib/Lacuna/DB/Result/Ships/Dory.pm index 40fb9d14..7028fa17 100644 --- a/lib/Lacuna/DB/Result/Ships/Dory.pm +++ b/lib/Lacuna/DB/Result/Ships/Dory.pm @@ -17,7 +17,7 @@ use constant base_stealth => 4100; use constant base_hold_size => 400; use constant base_berth_level => 1; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining Intelligence ResourceChain)]; +use constant build_tags => [qw(Trade Mining Intelligence SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CaptureWithSpies"; diff --git a/lib/Lacuna/DB/Result/Ships/Freighter.pm b/lib/Lacuna/DB/Result/Ships/Freighter.pm index 68693aa3..65d123fa 100644 --- a/lib/Lacuna/DB/Result/Ships/Freighter.pm +++ b/lib/Lacuna/DB/Result/Ships/Freighter.pm @@ -18,7 +18,7 @@ use constant base_stealth => 0; use constant base_hold_size => 4000; use constant base_berth_level => 15; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining ResourceChain)]; +use constant build_tags => [qw(Trade Mining SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/Galleon.pm b/lib/Lacuna/DB/Result/Ships/Galleon.pm index e1861392..02db4609 100644 --- a/lib/Lacuna/DB/Result/Ships/Galleon.pm +++ b/lib/Lacuna/DB/Result/Ships/Galleon.pm @@ -17,7 +17,7 @@ use constant base_stealth => 0; use constant base_hold_size => 1750; use constant base_berth_level => 10; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining ResourceChain)]; +use constant build_tags => [qw(Trade Mining SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/Hulk.pm b/lib/Lacuna/DB/Result/Ships/Hulk.pm index b5760ac9..cd4ee9c2 100644 --- a/lib/Lacuna/DB/Result/Ships/Hulk.pm +++ b/lib/Lacuna/DB/Result/Ships/Hulk.pm @@ -18,7 +18,7 @@ use constant base_stealth => 0; use constant base_hold_size => 7900; use constant base_berth_level => 20; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining ResourceChain)]; +use constant build_tags => [qw(Trade Mining SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/HulkFast.pm b/lib/Lacuna/DB/Result/Ships/HulkFast.pm index be95bedc..cc251dbf 100644 --- a/lib/Lacuna/DB/Result/Ships/HulkFast.pm +++ b/lib/Lacuna/DB/Result/Ships/HulkFast.pm @@ -19,7 +19,7 @@ use constant base_stealth => 0; use constant base_hold_size => 10000; use constant base_berth_level => 25; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining ResourceChain)]; +use constant build_tags => [qw(Trade Mining SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/HulkHuge.pm b/lib/Lacuna/DB/Result/Ships/HulkHuge.pm index 3308fd34..9409a0c0 100644 --- a/lib/Lacuna/DB/Result/Ships/HulkHuge.pm +++ b/lib/Lacuna/DB/Result/Ships/HulkHuge.pm @@ -18,7 +18,7 @@ use constant base_stealth => 0; use constant base_hold_size => 170100; use constant base_berth_level => 30; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining ResourceChain)]; +use constant build_tags => [qw(Trade Mining SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CargoExchange"; diff --git a/lib/Lacuna/DB/Result/Ships/SmugglerShip.pm b/lib/Lacuna/DB/Result/Ships/SmugglerShip.pm index 22a9e23c..77110b7b 100644 --- a/lib/Lacuna/DB/Result/Ships/SmugglerShip.pm +++ b/lib/Lacuna/DB/Result/Ships/SmugglerShip.pm @@ -17,7 +17,7 @@ use constant base_stealth => 5000; use constant base_hold_size => 520; use constant base_berth_level => 10; use constant pilotable => 1; -use constant build_tags => [qw(Trade Mining Intelligence ResourceChain)]; +use constant build_tags => [qw(Trade Mining Intelligence SupplyChain)]; with "Lacuna::Role::Ship::Send::UsePush"; with "Lacuna::Role::Ship::Arrive::CaptureWithSpies"; diff --git a/lib/Lacuna/DB/Result/ResourceChain.pm b/lib/Lacuna/DB/Result/SupplyChain.pm similarity index 94% rename from lib/Lacuna/DB/Result/ResourceChain.pm rename to lib/Lacuna/DB/Result/SupplyChain.pm index 09827434..dca1fdb8 100644 --- a/lib/Lacuna/DB/Result/ResourceChain.pm +++ b/lib/Lacuna/DB/Result/SupplyChain.pm @@ -1,11 +1,11 @@ -package Lacuna::DB::Result::ResourceChain; +package Lacuna::DB::Result::SupplyChain; use Moose; use utf8; no warnings qw(uninitialized); extends 'Lacuna::DB::Result'; -__PACKAGE__->table('resource_chain'); +__PACKAGE__->table('supply_chain'); __PACKAGE__->add_columns( planet_id => { data_type => 'int', size => 11, is_nullable => 0 }, building_id => { data_type => 'int', size => 11, is_nullable => 0 }, diff --git a/lib/Lacuna/RPC.pm b/lib/Lacuna/RPC.pm index e69dd8e3..9c259c7c 100644 --- a/lib/Lacuna/RPC.pm +++ b/lib/Lacuna/RPC.pm @@ -61,7 +61,7 @@ sub get_body { # makes for uniform error handling, and prevents staleness unless (defined $body) { confess [1002, 'Body does not exist.', $body_id]; } - unless ($body->empire_id eq $empire->id) { + if ($body->empire_id ne $empire->id) { if ($body->isa('Lacuna::DB::Result::Map::Body::Planet::Station')) { if ($body->empire->alliance_id eq $empire->alliance_id) { $body->tick; diff --git a/lib/Lacuna/RPC/Building/MiningMinistry.pm b/lib/Lacuna/RPC/Building/MiningMinistry.pm index f41411eb..e0b2e663 100644 --- a/lib/Lacuna/RPC/Building/MiningMinistry.pm +++ b/lib/Lacuna/RPC/Building/MiningMinistry.pm @@ -2,6 +2,7 @@ package Lacuna::RPC::Building::MiningMinistry; use Moose; use utf8; +use Lacuna::Constants qw(SHIP_TRADE_TYPES); no warnings qw(uninitialized); extends 'Lacuna::RPC::Building'; @@ -17,9 +18,11 @@ sub view_ships { my ($self, $session_id, $building_id) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); - my $ships = Lacuna->db->resultset('Lacuna::DB::Result::Ships') - ->search({ body_id => $building->body_id, task => { in => ['Mining', 'Docked']}, - type => { 'in' => [qw(cargo_ship dory hulk hulk_fast hulk_huge barge galleon freighter smuggler_ship)] } }); + my $ships = Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({ + body_id => $building->body_id, + task => { in => ['Mining', 'Docked']}, + type => { in => [SHIP_TRADE_TYPES] }, + }); my @fleet; while (my $ship = $ships->next) { push @fleet, { diff --git a/lib/Lacuna/RPC/Building/Trade.pm b/lib/Lacuna/RPC/Building/Trade.pm index 2c7bb497..cfe8047f 100644 --- a/lib/Lacuna/RPC/Building/Trade.pm +++ b/lib/Lacuna/RPC/Building/Trade.pm @@ -7,7 +7,7 @@ no warnings qw(uninitialized); extends 'Lacuna::RPC::Building'; use Guard; use List::Util qw(first); -use Lacuna::Constants qw(FOOD_TYPES ORE_TYPES); +use Lacuna::Constants qw(FOOD_TYPES ORE_TYPES SHIP_WASTE_TYPES SHIP_TRADE_TYPES); with 'Lacuna::Role::TraderRpc','Lacuna::Role::Ship::Trade'; @@ -36,7 +36,7 @@ sub get_trade_ships { }; } -sub add_resource_ship_to_fleet { +sub add_supply_ship_to_fleet { my ($self, $session_id, $building_id, $ship_id) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); @@ -56,15 +56,15 @@ sub add_resource_ship_to_fleet { unless ($ship->body_id eq $building->body_id) { confess [1013, "You can't manage a ship that is not yours."]; } - unless (first {$ship->type eq $_} (qw(cargo_ship smuggler_ship freighter dory barge galleon hulk hulk_huge hulk_fast))) { - confess [1009, 'You can only add transport ships to a resource chain.']; + unless (first {$ship->type eq $_} (SHIP_TRADE_TYPES)) { + confess [1009, 'You can only add transport ships to a supply chain.']; } my $max_berth = $building->body->max_berth; unless ($ship->berth_level <= $max_berth) { confess [1009, "You don't have a high enough berth for this ship."]; } - $building->add_resource_ship($ship); + $building->add_supply_ship($ship); return { status =>$self->format_status($empire, $building->body), }; @@ -104,7 +104,7 @@ sub add_waste_ship_to_fleet { }; } -sub remove_resource_ship_from_fleet { +sub remove_supply_ship_from_fleet { my ($self, $session_id, $building_id, $ship_id) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); @@ -116,17 +116,17 @@ sub remove_resource_ship_from_fleet { unless (defined $ship) { confess [1002, "Ship not found."]; } - unless ($ship->task eq 'Resource Chain') { - confess [1009, "That ship is not in a Resource Chain."]; + unless ($ship->task eq 'Supply Chain') { + confess [1009, "That ship is not in a Supply Chain."]; } unless ($ship->body_id eq $building->body_id) { confess [1013, "You can't manage a ship that is not yours."]; } - my $resource_chain = $building->resource_chains->search({},{rows => 1})->single; - if (defined $resource_chain) { - my $from = $resource_chain->target_id; - $building->send_waste_ship_home($from, $ship); + my $supply_chain = $building->supply_chains->search({},{rows => 1})->single; + if (defined $supply_chain) { + my $from = $supply_chain->target_id; + $building->send_supply_ship_home($from, $ship); } else { $ship->land->update; @@ -168,14 +168,14 @@ sub remove_waste_ship_from_fleet { }; } -sub get_resource_ships { +sub get_supply_ships { my ($self, $session_id, $building_id) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); my @ships; - my $ships = $building->all_resource_ships; + my $ships = $building->all_supply_ships; while (my $ship = $ships->next) { push @ships, $ship->get_status; } @@ -203,7 +203,7 @@ sub get_waste_ships { }; } -sub view_resource_chains { +sub view_supply_chains { my ($self, $session_id, $building_id) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); @@ -212,14 +212,14 @@ sub view_resource_chains { } my $body = $building->body; - my @resource_chains; - my $chains = $building->resource_chains; + my @supply_chains; + my $chains = $building->supply_chains; while (my $chain = $chains->next) { - push @resource_chains, $chain->get_status; + push @supply_chains, $chain->get_status; } return { status => $self->format_status($empire, $building->body), - resource_chain => \@resource_chain, + supply_chain => \@supply_chains, }; } @@ -243,36 +243,36 @@ sub view_waste_chains { }; } -sub update_resource_chain { - my ($self, $session_id, $building_id, $resource_chain_id, $resource_type, $resource_hour) = @_; +sub update_supply_chain { + my ($self, $session_id, $building_id, $supply_chain_id, $supply_type, $supply_hour) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); unless ($building) { confess [1002, "Cannot find that building."]; } my $body = $building->body; - unless ($resource_chain_id) { - confess [1002, "You must specify a resource chain id."]; + unless ($supply_chain_id) { + confess [1002, "You must specify a supply chain id."]; } - unless (defined $resource_hour) { - confess [1002, "You must specify an amount for resource_hour."]; + unless (defined $supply_hour) { + confess [1002, "You must specify an amount for supply_hour."]; } - unless ($resource_hour >= 0) { + unless ($supply_hour >= 0) { confess [1002, "Resource per Hour must be positive or zero."]; } - unless (first {$resource_type eq $_} (FOOD_TYPES, ORE_TYPES, qw(water waste energy))) { - confess [1002, "That is not a valid resource type."]; + unless (first {$supply_type eq $_} (FOOD_TYPES, ORE_TYPES, qw(water waste energy))) { + confess [1002, "That is not a valid supply type."]; } - my $chain = $building->resource_chains->find($resource_chain_id); + my $chain = $building->supply_chains->find($supply_chain_id); unless ($chain) { - confess [1002, "That Resource Chain does not exist on this planet."]; + confess [1002, "That Supply Chain does not exist on this planet."]; } - $chain->resource_hour(int($resource_hour)); - $chain->resource_type($resource_type); + $chain->supply_hour(int($supply_hour)); + $chain->supply_type($supply_type); $chain->update; $building->recalc_resource_production; - return $self->view_resource_chains($session_id, $building_id); + return $self->view_supply_chains($session_id, $building_id); } sub update_waste_chain { @@ -457,7 +457,7 @@ sub add_to_market { -__PACKAGE__->register_rpc_method_names(qw(get_resource_ships view_resource_chains add_resource_ship_to_fleet remove_resource_ship_from_fleet create_resource_chain delete_resource_chain update_resource_chain get_waste_ships view_waste_chains add_waste_ship_to_fleet remove_waste_ship_from_fleet update_waste_chain report_abuse view_my_market view_market accept_from_market withdraw_from_market add_to_market push_items get_trade_ships get_stored_resources get_ships get_ship_summary get_prisoners get_plans get_plan_summary get_glyphs get_glyph_summary)); +__PACKAGE__->register_rpc_method_names(qw(get_supply_ships view_supply_chains add_supply_ship_to_fleet remove_supply_ship_from_fleet create_supply_chain delete_supply_chain update_supply_chain get_waste_ships view_waste_chains add_waste_ship_to_fleet remove_waste_ship_from_fleet update_waste_chain report_abuse view_my_market view_market accept_from_market withdraw_from_market add_to_market push_items get_trade_ships get_stored_resources get_ships get_ship_summary get_prisoners get_plans get_plan_summary get_glyphs get_glyph_summary)); no Moose; diff --git a/t/410_Fleet_Actions.t b/t/410_Fleet_Actions.t index 37f031ae..4f8acb35 100644 --- a/t/410_Fleet_Actions.t +++ b/t/410_Fleet_Actions.t @@ -11,248 +11,7 @@ my $tester = TestHelper->new({empire_name => 'TLE Test Empire'}); my $empire = $tester->empire; my $session = $empire->start_session({api_key => 'tester'}); -my ($planet) = Lacuna->db->resultset('Map::Body::Planet')->search({name => 'Test-10'}); +my ($planet) = Lacuna->db->resultset('Map::Body::Planet')->search({name => 'Smith 3'}); -build_big_colony($tester, $planet); - -sub build_big_colony { - my ($tester, $planet) = @_; - - my $empire = $planet->empire; - $planet->buildings->search({})->delete_all; - $planet->ships->delete_all; - Lacuna->db->resultset('Spies')->search({from_body_id => $planet->id})->delete_all; - - my $layout = { - 'PlanetaryCommand' => [ - { x => 0, y => 0, level => 30 }, - ], - 'SpacePort' => [ - { x => -2, y => -2, level => 22 }, - { x => -1, y => -2, level => 22 }, - { x => 0, y => -2, level => 22 }, - { x => 1, y => -2, level => 22 }, - { x => 2, y => -2, level => 22 }, - { x => -2, y => -1, level => 22 }, - { x => -1, y => -1, level => 22 }, - { x => 0, y => -1, level => 22 }, - { x => 1, y => -1, level => 22 }, - { x => 2, y => -1, level => 22 }, - { x => -2, y => 0, level => 22 }, - { x => -1, y => 0, level => 22 }, - { x => 1, y => 0, level => 22 }, - { x => 2, y => 0, level => 22 }, - { x => -2, y => 1, level => 22 }, - { x => -1, y => 1, level => 22 }, - { x => 0, y => 1, level => 22 }, - { x => 1, y => 1, level => 22 }, - { x => 2, y => 1, level => 22 }, - { x => -2, y => 2, level => 22 }, - { x => -1, y => 2, level => 22 }, - { x => 0, y => 2, level => 22 }, - { x => 1, y => 2, level => 22 }, - { x => 2, y => 2, level => 22 }, - { x => 4, y => -4, level => 22 }, - { x => 4, y => -3, level => 22 }, - { x => 4, y => -2, level => 22 }, - { x => 4, y => -1, level => 22 }, - { x => 4, y => 0, level => 22 }, - { x => 4, y => 1, level => 22 }, - { x => 4, y => 2, level => 22 }, - { x => 4, y => 3, level => 22 }, - { x => 4, y => 4, level => 22 }, - { x => -4, y => -4, level => 22 }, - { x => -4, y => -3, level => 22 }, - { x => -4, y => -2, level => 22 }, - { x => -4, y => -1, level => 22 }, - { x => -4, y => 0, level => 22 }, - { x => -4, y => 1, level => 22 }, - { x => -4, y => 2, level => 22 }, - { x => -4, y => 3, level => 22 }, - { x => -4, y => 4, level => 22 }, - { x => -3, y => -4, level => 22 }, - { x => -2, y => -4, level => 22 }, - { x => -1, y => -4, level => 22 }, - { x => 0, y => -4, level => 22 }, - { x => 1, y => -4, level => 22 }, - { x => 2, y => -4, level => 22 }, - { x => 3, y => -4, level => 22 }, - { x => -3, y => 4, level => 22 }, - { x => -2, y => 4, level => 22 }, - { x => -1, y => 4, level => 22 }, - { x => 0, y => 4, level => 22 }, - { x => 1, y => 4, level => 22 }, - { x => 2, y => 4, level => 22 }, - { x => 3, y => 4, level => 22 }, - ], - 'Permanent::Volcano' => [ { x => 1, y => -3, level => 30 }, ], - 'Permanent::InterDimensionalRift' => [ { x => 2, y => -3, level => 30 }, ], - 'Archaeology' => [ { x => 3, y => -3, level => 30 }, ], - 'Development' => [ { x => 0, y => -3, level => 30 }, ], - 'Permanent::GeoThermalVent' => [ { x => -1, y => -3, level => 30 }, ], - 'Espionage' => [ { x => -2, y => -3, level => 30 }, ], - 'Security' => [ { x => -3, y => -3, level => 30 }, ], - 'Intelligence' => [ { x => -3, y => -2, level => 30 }, ], - 'Embassy' => [ { x => -3, y => 0, level => 30 }, ], - 'Trade' => [ { x => 0, y => 3, level => 30 }, ], - 'Transporter' => [ { x => 3, y => 0, level => 30 }, ], - 'University' => [ { x => 3, y => -1, level => 30 }, ], - 'Observatory' => [ { x => 3, y => -2, level => 30 }, ], - 'TheftTraining' => [ { x => -3, y => 1, level => 30 }, ], - 'IntelTraining' => [ { x => -3, y => 2, level => 30 }, ], - 'MayhemTraining' => [ { x => -3, y => 3, level => 30 }, ], - 'PoliticsTraining' => [ { x => -2, y => 3, level => 30 }, ], - 'Permanent::NaturalSpring' => [ { x => -1, y => 3, level => 30 }, ], - 'Permanent::CrashedShipSite' => [ { x => 1, y => 3, level => 30 }, ], - 'CloakingLab' => [ { x => 2, y => 3, level => 30 }, ], - 'MunitionsLab' => [ { x => 3, y => 3, level => 30 }, ], - 'PilotTraining' => [ { x => 3, y => 2, level => 30 }, ], - 'Propulsion' => [ { x => 3, y => 1, level => 30 }, ], - 'Permanent::DentonBrambles' => [ { x => -5, y => 2, level => 30 }, ], - 'Permanent::AlgaePond' => [ { x => -5, y => 1, level => 30 }, ], - 'MercenariesGuild' => [ { x => -3, y => -1, level => 30 }, ], - 'Permanent::SpaceJunkPark' => [ { x => -5, y => -1, level => 30 }, ], - 'Permanent::PyramidJunkSculpture' => [ { x => -5, y => -2, level => 30 }, ], - 'Permanent::GratchsGauntlet' => [ { x => 5, y => 2, level => 30 }, ], - 'Permanent::Ravine' => [ { x => 5, y => 1, level => 30 }, ], - 'Permanent::JunkHengeSculpture' => [ { x => 5, y => -1, level => 30 }, ], - 'Permanent::MetalJunkArches' => [ { x => 5, y => -2, level => 30 }, ], -# '' => [ { x => , y => , level => 30 }, ], - 'Permanent::GasGiantPlatform' => [ - { x => 5, y => 5, level => 30 }, - { x => 5, y => -5, level => 30 }, - { x => -5, y => 5, level => 30 }, - { x => -5, y => -5, level => 30 }, - ], - 'Shipyard' => [ - { x => -2, y => 5, level => 30 }, - { x => -1, y => 5, level => 30 }, - { x => 1, y => 5, level => 30 }, - { x => 2, y => 5, level => 30 }, - { x => -2, y => -5, level => 30 }, - { x => -1, y => -5, level => 30 }, - { x => 1, y => -5, level => 30 }, - { x => 2, y => -5, level => 30 }, - ], - 'SAW' => [ - { x => -4, y => 5, level => 30 }, - { x => 4, y => 5, level => 30 }, - { x => -4, y => -5, level => 30 }, - { x => 4, y => -5, level => 30 }, - { x => -5, y => 4, level => 30 }, - { x => 5, y => 4, level => 30 }, - { x => -5, y => -4, level => 30 }, - { x => 5, y => -4, level => 30 }, - { x => 0, y => 5, level => 30 }, - { x => 0, y => -5, level => 30 }, - ], - }; - - diag("Generating buildings"); - for my $class (keys %$layout ) { - for my $location (@{$layout->{$class}}) { - my $building = Lacuna->db->resultset('Building')->new({ - x => $location->{x}, - y => $location->{y}, - class => "Lacuna::DB::Result::Building::$class", - level => $location->{level} - 1, - }); - $planet->build_building($building); - $building->finish_upgrade; - } - } - $planet->bauxite_stored(19,000,000,000); - $planet->algae_stored(19,000,000,000); - $planet->energy_stored(19,000,000,000); - $planet->water_stored(19,000,000,000); - $planet->needs_recalc(1); - $planet->update; - $planet->tick; - - # Add ships - my ($shipyard) = $planet->buildings->search({ class => 'Lacuna::DB::Result::Building::Shipyard' }); - diag("Generating ships [".$session->id."][".$shipyard->id."]"); - my $ships = { - excavator => 30, - probe => 20, - sweeper => 1300, - fighter => 500, - hulk => 250, - detonator => 20, - security_ministry_seeker=> 20, - smuggler_ship => 20, - snark3 => 200, - spy_pod => 20, - spy_shuttle => 20, - supply_pod4 => 10, - - }; - for my $ship (keys %$ships) { - # Create one ship as a 'template' - my $result = $tester->post('shipyard', 'build_ship', [$session->id, $shipyard->id, $ship]); - $tester->finish_ships( $shipyard->id ); - if ($ships->{$ship} > 1) { - my $ship_id = $result->{result}{ships_building}[0]{id}; - my $example = Lacuna->db->resultset('Ships')->find($ship_id); - diag("Building more ships of type [$ship] id [$ship_id][$example]"); - - for (1..$ships->{$ship}) { - Lacuna->db->resultset('Ships')->create({ - body_id => $example->body_id, - shipyard_id => $example->shipyard_id, - date_started => $example->date_started, - date_available => $example->date_available, - type => $example->type, - task => $example->task, - name => $example->name, - speed => $example->speed, - stealth => $example->stealth, - combat => $example->combat, - hold_size => $example->hold_size, - payload => $example->payload, - roundtrip => $example->roundtrip, - direction => $example->direction, - foreign_body_id => $example->foreign_body_id, - foreign_star_id => $example->foreign_star_id, - fleet_speed => $example->fleet_speed, - }); - } - } - } - - # Add Spies - diag("Generating Spies"); - for (1..1000) { - my $spy = $empire->add_to_spies({ - name => 'Null', - from_body_id => $planet->id, - on_body_id => $planet->id, - task => 'Counter Espionage', - started_assignment => '2012-01-01 12:00:00', - available_on => '2012-01-01 12:00:00', - offense => 2600, - defense => 2600, - date_created => DateTime->now(), - offense_mission_count => 10 + int(rand(10)), - defense_mission_count => 10 + int(rand(10)), - offense_mission_successes => int(rand(3)), - defense_mission_successes => int(rand(3)), - times_captured => 0, - times_turned => 0, - seeds_planted => 0, - spies_turned => 0, - spies_captured => 0, - spies_killed => 0, - things_destroyed => int(rand(3)), - things_stolen => int(rand(5)), - intel_xp => 95 + int(rand(5)), - mayhem_xp => 95 + int(rand(5)), - politics_xp => 95 + int(rand(5)), - theft_xp => 95 + int(rand(5)), - level => 27 + int(rand(10)), - }); - $spy->name("ICY ".$spy->id); - $spy->update; - } -} +$tester->build_big_colony($session, $planet); diff --git a/t/430_Supply_Chain.t b/t/430_Supply_Chain.t new file mode 100644 index 00000000..0fd32d76 --- /dev/null +++ b/t/430_Supply_Chain.t @@ -0,0 +1,93 @@ +use lib '../lib'; + +use strict; +use warnings; + +use Test::More tests => 25; +use Test::Deep; +use Data::Dumper; +use 5.010; +use DateTime; + +use TestHelper; +my $tester = TestHelper->new->use_existing_test_empire; +my $session_id = $tester->session->id; +my $empire = $tester->empire; +my $home = $empire->home_planet; +my $command = $home->command; + +my $result; + +diag("Create a station"); + +my $station = Lacuna->db->resultset('Map::Body')->search({ + class => 'Lacuna::DB::Result::Map::Body::Planet::Station', + empire_id => $empire->id, + },{ + rows=>1, +})->single; + +if (not $station) { + $station = Lacuna->db->resultset('Map::Body')->search({ + class => {like => 'Lacuna::DB::Result::Map::Body::Planet::P%'}, + empire_id => undef, + },{ + rows=>1, + })->single; + + $station->convert_to_station($empire); + $station = $station->discard_changes; # just in case + $station->alliance_id($empire->alliance_id); + $station->update; +} + +# make sure the station has resources +$station->apple_stored(4500); +$station->water_stored(4500); +$station->energy_stored(4500); +$station->gold_stored(4500); +$station->update; +$station->tick; + +my $trade = Lacuna->db->resultset('Building')->search({ + class => 'Lacuna::DB::Result::Building::Trade', + body_id => $home->id, + },{ + rows => 1, +})->single; + +diag "Trade id =[".$trade->id."]"; +$result = $tester->post('trade','get_supply_ships', [$session_id, $trade->id]); +#diag(Dumper($result->{result}{ships})); + +# remove any existing ships from the supply chain +my @ship_ids = map {$_->{id} } grep {$_->{task} eq 'Supply Chain'} @{$result->{result}{ships}}; +diag Dumper(\@ship_ids); + +foreach my $ship_id ( @ship_ids ) { + diag "### remove ship [$ship_id] ###"; + $result = $tester->post('trade', 'remove_supply_ship_from_fleet', [$session_id, $trade->id, $ship_id]); +} +exit; + +# get a single ships to add to the supply chain +my ($ship_id) = map {$_->{id} } grep {$_->{task} eq 'Docked' and $_->{type} eq 'hulk'} @{$result->{result}{ships}}; +diag("Ship [$ship_id]"); +ok($ship_id, "We have a ship"); + +$result = $tester->post('trade','add_supply_ship_to_fleet',[$session_id, $trade->id, $ship_id]); +is(1, 1, "Added a ship to the fleet"); + + + +#my @temp = map { {task => $_->{task}, type => $_->{type} } } @{$result->{result}{ships}}; +#my @comp = ({type=>'scow',task=>'Docked'},{type=>'scow_large',task=>'Docked'}); +#cmp_deeply(\@comp,\@temp, "All ships docked"); +# +# + + + +END { +# TestHelper->clear_all_test_empires; +} diff --git a/t/TestHelper.pm b/t/TestHelper.pm index 48d1369c..63d88d1f 100644 --- a/t/TestHelper.pm +++ b/t/TestHelper.pm @@ -9,6 +9,7 @@ use LWP::UserAgent; use JSON qw(to_json from_json); use Data::Dumper; use 5.010; +use Test::More; has ua => ( is => 'ro', @@ -71,6 +72,16 @@ sub clear_all_test_empires { } } +sub use_existing_test_empire { + my ($self) = @_; + + my ($empire) = Lacuna->db->resultset('Lacuna::DB::Result::Empire')->search({ + name => $self->empire_name, + }); + $self->session($empire->start_session({api_key => 'tester'})); + $self->empire($empire); + return $self; +} sub generate_test_empire { my $self = shift; @@ -231,5 +242,240 @@ sub finish_ships { Lacuna->db->resultset('Lacuna::DB::Result::Ships')->search({shipyard_id=>$shipyard_id})->update({date_available=>$finish, task=>'Docked'}); } +sub build_big_colony { + my ($self, $planet) = @_; + + my $empire = $planet->empire; + $planet->buildings->search({})->delete_all; + $planet->ships->delete_all; + Lacuna->db->resultset('Spies')->search({from_body_id => $planet->id})->delete_all; + + my $layout = { + 'PlanetaryCommand' => [ + { x => 0, y => 0, level => 30 }, + ], + 'SpacePort' => [ + { x => -2, y => -2, level => 22 }, + { x => -1, y => -2, level => 22 }, + { x => 0, y => -2, level => 22 }, + { x => 1, y => -2, level => 22 }, + { x => 2, y => -2, level => 22 }, + { x => -2, y => -1, level => 22 }, + { x => -1, y => -1, level => 22 }, + { x => 0, y => -1, level => 22 }, + { x => 1, y => -1, level => 22 }, + { x => 2, y => -1, level => 22 }, + { x => -2, y => 0, level => 22 }, + { x => -1, y => 0, level => 22 }, + { x => 1, y => 0, level => 22 }, + { x => 2, y => 0, level => 22 }, + { x => -2, y => 1, level => 22 }, + { x => -1, y => 1, level => 22 }, + { x => 0, y => 1, level => 22 }, + { x => 1, y => 1, level => 22 }, + { x => 2, y => 1, level => 22 }, + { x => -2, y => 2, level => 22 }, + { x => -1, y => 2, level => 22 }, + { x => 0, y => 2, level => 22 }, + { x => 1, y => 2, level => 22 }, + { x => 2, y => 2, level => 22 }, + { x => 4, y => -4, level => 22 }, + { x => 4, y => -3, level => 22 }, + { x => 4, y => -2, level => 22 }, + { x => 4, y => -1, level => 22 }, + { x => 4, y => 0, level => 22 }, + { x => 4, y => 1, level => 22 }, + { x => 4, y => 2, level => 22 }, + { x => 4, y => 3, level => 22 }, + { x => 4, y => 4, level => 22 }, + { x => -4, y => -4, level => 22 }, + { x => -4, y => -3, level => 22 }, + { x => -4, y => -2, level => 22 }, + { x => -4, y => -1, level => 22 }, + { x => -4, y => 0, level => 22 }, + { x => -4, y => 1, level => 22 }, + { x => -4, y => 2, level => 22 }, + { x => -4, y => 3, level => 22 }, + { x => -4, y => 4, level => 22 }, + { x => -3, y => -4, level => 22 }, + { x => -2, y => -4, level => 22 }, + { x => -1, y => -4, level => 22 }, + { x => 0, y => -4, level => 22 }, + { x => 1, y => -4, level => 22 }, + { x => 2, y => -4, level => 22 }, + { x => 3, y => -4, level => 22 }, + { x => -3, y => 4, level => 22 }, + { x => -2, y => 4, level => 22 }, + { x => -1, y => 4, level => 22 }, + { x => 0, y => 4, level => 22 }, + { x => 1, y => 4, level => 22 }, + { x => 2, y => 4, level => 22 }, + { x => 3, y => 4, level => 22 }, + ], + 'Permanent::Volcano' => [ { x => 1, y => -3, level => 30 }, ], + 'Permanent::InterDimensionalRift' => [ { x => 2, y => -3, level => 30 }, ], + 'Archaeology' => [ { x => 3, y => -3, level => 30 }, ], + 'Development' => [ { x => 0, y => -3, level => 30 }, ], + 'Permanent::GeoThermalVent' => [ { x => -1, y => -3, level => 30 }, ], + 'Espionage' => [ { x => -2, y => -3, level => 30 }, ], + 'Security' => [ { x => -3, y => -3, level => 30 }, ], + 'Intelligence' => [ { x => -3, y => -2, level => 30 }, ], + 'Embassy' => [ { x => -3, y => 0, level => 30 }, ], + 'Trade' => [ { x => 0, y => 3, level => 30 }, ], + 'Transporter' => [ { x => 3, y => 0, level => 30 }, ], + 'University' => [ { x => 3, y => -1, level => 30 }, ], + 'Observatory' => [ { x => 3, y => -2, level => 30 }, ], + 'TheftTraining' => [ { x => -3, y => 1, level => 30 }, ], + 'IntelTraining' => [ { x => -3, y => 2, level => 30 }, ], + 'MayhemTraining' => [ { x => -3, y => 3, level => 30 }, ], + 'PoliticsTraining' => [ { x => -2, y => 3, level => 30 }, ], + 'Permanent::NaturalSpring' => [ { x => -1, y => 3, level => 30 }, ], + 'Permanent::CrashedShipSite' => [ { x => 1, y => 3, level => 30 }, ], + 'CloakingLab' => [ { x => 2, y => 3, level => 30 }, ], + 'MunitionsLab' => [ { x => 3, y => 3, level => 30 }, ], + 'PilotTraining' => [ { x => 3, y => 2, level => 30 }, ], + 'Propulsion' => [ { x => 3, y => 1, level => 30 }, ], + 'Permanent::DentonBrambles' => [ { x => -5, y => 2, level => 30 }, ], + 'Permanent::AlgaePond' => [ { x => -5, y => 1, level => 30 }, ], + 'MercenariesGuild' => [ { x => -3, y => -1, level => 30 }, ], + 'Permanent::SpaceJunkPark' => [ { x => -5, y => -1, level => 30 }, ], + 'Permanent::PyramidJunkSculpture' => [ { x => -5, y => -2, level => 30 }, ], + 'Permanent::GratchsGauntlet' => [ { x => 5, y => 2, level => 30 }, ], + 'Permanent::Ravine' => [ { x => 5, y => 1, level => 30 }, ], + 'Permanent::JunkHengeSculpture' => [ { x => 5, y => -1, level => 30 }, ], + 'Permanent::MetalJunkArches' => [ { x => 5, y => -2, level => 30 }, ], + 'Permanent::GasGiantPlatform' => [ + { x => 5, y => 5, level => 30 }, + { x => 5, y => -5, level => 30 }, + { x => -5, y => 5, level => 30 }, + { x => -5, y => -5, level => 30 }, + ], + 'Shipyard' => [ + { x => -2, y => 5, level => 30 }, + { x => -1, y => 5, level => 30 }, + { x => 1, y => 5, level => 30 }, + { x => 2, y => 5, level => 30 }, + { x => -2, y => -5, level => 30 }, + { x => -1, y => -5, level => 30 }, + { x => 1, y => -5, level => 30 }, + { x => 2, y => -5, level => 30 }, + ], + 'SAW' => [ + { x => -4, y => 5, level => 30 }, + { x => 4, y => 5, level => 30 }, + { x => -4, y => -5, level => 30 }, + { x => 4, y => -5, level => 30 }, + { x => -5, y => 4, level => 30 }, + { x => 5, y => 4, level => 30 }, + { x => -5, y => -4, level => 30 }, + { x => 5, y => -4, level => 30 }, + { x => 0, y => 5, level => 30 }, + { x => 0, y => -5, level => 30 }, + ], + }; + + diag("Generating buildings"); + for my $class (keys %$layout ) { + for my $location (@{$layout->{$class}}) { + my $building = Lacuna->db->resultset('Building')->new({ + x => $location->{x}, + y => $location->{y}, + class => "Lacuna::DB::Result::Building::$class", + level => $location->{level} - 1, + }); + $planet->build_building($building); + $building->finish_upgrade; + } + } + $planet->bauxite_stored(19,000,000,000); + $planet->algae_stored(19,000,000,000); + $planet->energy_stored(19,000,000,000); + $planet->water_stored(19,000,000,000); + $planet->needs_recalc(1); + $planet->update; + $planet->tick; + + my ($shipyard) = $planet->buildings->search({ class => 'Lacuna::DB::Result::Building::Shipyard' }); + diag("Generating ships [".$self->session->id."][".$shipyard->id."]"); + my $ships = { + excavator => 30, + probe => 20, + sweeper => 1300, + fighter => 500, + hulk => 250, + detonator => 20, + security_ministry_seeker=> 20, + smuggler_ship => 20, + snark3 => 200, + spy_pod => 20, + spy_shuttle => 20, + supply_pod4 => 10, + + }; + for my $ship (keys %$ships) { + my $result = $self->post('shipyard', 'build_ship', [$self->session->id, $shipyard->id, $ship]); + $self->finish_ships( $shipyard->id ); + if ($ships->{$ship} > 1) { + my $ship_id = $result->{result}{ships_building}[0]{id}; + my $example = Lacuna->db->resultset('Ships')->find($ship_id); + diag("Building more ships of type [$ship] id [$ship_id][$example]"); + + for (1..$ships->{$ship}) { + Lacuna->db->resultset('Ships')->create({ + body_id => $example->body_id, + shipyard_id => $example->shipyard_id, + date_started => $example->date_started, + date_available => $example->date_available, + type => $example->type, + task => $example->task, + name => $example->name, + speed => $example->speed, + stealth => $example->stealth, + combat => $example->combat, + hold_size => $example->hold_size, + payload => $example->payload, + roundtrip => $example->roundtrip, + direction => $example->direction, + foreign_body_id => $example->foreign_body_id, + foreign_star_id => $example->foreign_star_id, + fleet_speed => $example->fleet_speed, + }); + } + } + } + diag("Generating Spies"); + for (1..1000) { + my $spy = $empire->add_to_spies({ + name => 'Null', + from_body_id => $planet->id, + on_body_id => $planet->id, + task => 'Counter Espionage', + started_assignment => '2012-01-01 12:00:00', + available_on => '2012-01-01 12:00:00', + offense => 2600, + defense => 2600, + date_created => DateTime->now(), + offense_mission_count => 10 + int(rand(10)), + defense_mission_count => 10 + int(rand(10)), + offense_mission_successes => int(rand(3)), + defense_mission_successes => int(rand(3)), + times_captured => 0, + times_turned => 0, + seeds_planted => 0, + spies_turned => 0, + spies_captured => 0, + spies_killed => 0, + things_destroyed => int(rand(3)), + things_stolen => int(rand(5)), + intel_xp => 95 + int(rand(5)), + mayhem_xp => 95 + int(rand(5)), + politics_xp => 95 + int(rand(5)), + theft_xp => 95 + int(rand(5)), + level => 27 + int(rand(10)), + }); + $spy->name("ICY ".$spy->id); + $spy->update; + } +} 1; diff --git a/var/upgrades/3.0850.sql b/var/upgrades/3.0850.sql index 35a34e47..e060195c 100644 --- a/var/upgrades/3.0850.sql +++ b/var/upgrades/3.0850.sql @@ -1,5 +1,5 @@ -create table resource_chain ( +create table supply_chain ( id int(11) not null auto_increment, planet_id int(11) not null, building_id int(11) not null, diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 07d81838..e1af66e4 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,5 +1,5 @@ 2.0850: - - Add: API only, continuous push (resource chain) to any planet or SS. Note. No UI support yet. + - Add: API only, supply chain to any planet or SS. Note. No UI support yet. - Fix: Damaged Trade Ministry reduces the waste transferred in a waste chain. - Fix: Scows are no longer are tagged with 'Trade' -- 2.51.2 From 42e7bfdbdd6d2bd2e171bcc6151de4e2b7a8bd7e Mon Sep 17 00:00:00 2001 From: ian docherty Date: Thu, 10 May 2012 09:24:54 -0400 Subject: [PATCH 3/9] Further testing of supply-chains --- docs/Trade.pod | 4 +- lib/Lacuna/DB/Result/Building/Trade.pm | 7 ++- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 24 ++++---- lib/Lacuna/RPC/Building/Trade.pm | 79 ++++++++++++++++++++----- t/430_Supply_Chain.t | 53 ++++++++++++----- t/TestHelper.pm | 6 ++ 6 files changed, 129 insertions(+), 44 deletions(-) diff --git a/docs/Trade.pod b/docs/Trade.pod index a54bad92..0683d67d 100644 --- a/docs/Trade.pod +++ b/docs/Trade.pod @@ -671,10 +671,12 @@ still only transfer the specified B, it just means some ships will b fully filled. -=head2 create_supply_chain (session_id, building_id, resource_type, resource_hour) +=head2 create_supply_chain (session_id, building_id, target_id, resource_type, resource_hour) Create a new supply chain. +B is the ID of the target planet (or space station). + B is the identifier of the Trade Ministry building. B is the resource you want to push, e.g. 'waste','water','gold','energy','apple' diff --git a/lib/Lacuna/DB/Result/Building/Trade.pm b/lib/Lacuna/DB/Result/Building/Trade.pm index 1ce04735..2d5bca60 100644 --- a/lib/Lacuna/DB/Result/Building/Trade.pm +++ b/lib/Lacuna/DB/Result/Building/Trade.pm @@ -232,7 +232,7 @@ sub recalc_supply_production { } # Determine the resource/hour for supply chains my $chain_rphpd = 0; - my $supply_chains = $self->supply_chains; + my $supply_chains = $self->supply_chains->search({},{prefetch => 'target'}); while (my $supply_chain = $supply_chains->next) { $chain_rphpd += $body->calculate_distance_to_target($supply_chain->target) * 2 * $supply_chain->resource_hour; } @@ -242,13 +242,14 @@ sub recalc_supply_production { while (my $supply_chain = $supply_chains->next) { $supply_chain->percent_transferred($shipping_capacity); $supply_chain->update; + my $target = $supply_chain->target; + $target->needs_recalc(1); + $target->update; } $body->needs_recalc(1); $body->update; - # TODO Do we need to recalc all target bodies? - # return $self; } diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 67866f0f..861a3937 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -9,6 +9,7 @@ use Lacuna::Constants qw(FOOD_TYPES ORE_TYPES BUILDABLE_CLASSES SPACE_STATION_MO use List::Util qw(shuffle max); use Lacuna::Util qw(randint format_date); use DateTime; +use Data::Dumper; no warnings 'uninitialized'; __PACKAGE__->has_many('ships','Lacuna::DB::Result::Ships','body_id'); @@ -971,11 +972,11 @@ sub recalc_stats { my $percent = $out_chain->percent_transferred; $percent = $percent > 100 ? 100 : $percent; $percent *= $building->efficiency / 100; - my $supply_hour = sprintf('%.0f',$out_chain->supply_hour * $percent / 100); - my $resource_name = $self->resource_name($out_chain->supply_type); - $stats{$resource_name} -= $supply_hour; - if ($self->is_ore($out_chain->supply_type)) { - $total_ore_production_hour -= $supply_hour; + my $resource_hour = sprintf('%.0f',$out_chain->resource_hour * $percent / 100); + my $resource_name = $self->resource_name($out_chain->resource_type); + $stats{$resource_name} -= $resource_hour; + if ($self->is_ore($out_chain->resource_type)) { + $total_ore_production_hour -= $resource_hour; } } } @@ -999,14 +1000,17 @@ sub recalc_stats { },{prefetch => 'building'} ); while (my $in_chain = $input_chains->next) { + my $percent = $in_chain->percent_transferred; $percent = $percent > 100 ? 100 : $percent; $percent *= $in_chain->building->efficiency / 100; - my $supply_hour = sprintf('%.0f',$in_chain->supply_hour * $percent / 100); - my $resource_name = $self->resource_name($in_chain->supply_type); - $stats{$resource_name} += $supply_hour; - if ($self->is_ore($in_chain->supply_type)) { - $total_ore_production_hour += $supply_hour; + my $resource_hour = sprintf('%.0f',$in_chain->resource_hour * $percent / 100); + my $resource_name = $self->resource_name($in_chain->resource_type); + $stats{$resource_name} += $resource_hour; +carp "###>>> In Chain [$resource_hour][$resource_name] <<<###\n"; +#print STDERR Dumper($in_chain); + if ($self->is_ore($in_chain->resource_type)) { + $total_ore_production_hour += $resource_hour; } } diff --git a/lib/Lacuna/RPC/Building/Trade.pm b/lib/Lacuna/RPC/Building/Trade.pm index cfe8047f..36d91fac 100644 --- a/lib/Lacuna/RPC/Building/Trade.pm +++ b/lib/Lacuna/RPC/Building/Trade.pm @@ -125,7 +125,7 @@ sub remove_supply_ship_from_fleet { my $supply_chain = $building->supply_chains->search({},{rows => 1})->single; if (defined $supply_chain) { - my $from = $supply_chain->target_id; + my $from = $supply_chain->target; $building->send_supply_ship_home($from, $ship); } else { @@ -219,7 +219,7 @@ sub view_supply_chains { } return { status => $self->format_status($empire, $building->body), - supply_chain => \@supply_chains, + supply_chains => \@supply_chains, }; } @@ -232,19 +232,70 @@ sub view_waste_chains { confess [1002, "Cannot find that building."]; } my $body = $building->body; - my @waste_chain; + my @waste_chains; my $chains = $building->waste_chains; while (my $waste_push = $chains->next) { - push @waste_chain, $waste_push->get_status; + push @waste_chains, $waste_push->get_status; } return { status => $self->format_status($empire, $building->body), - waste_chain => \@waste_chain, + waste_chain => \@waste_chains, }; } +sub delete_supply_chain { + my ($self, $session_id, $building_id, $supply_chain_id) = @_; + + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + unless ($building) { + confess [1002, "Cannot find that building."]; + } + + my $chain = Lacuna->db->resultset('Lacuna::DB::Result::SupplyChain')->find($supply_chain_id); + if ($chain) { + $chain->delete; + } + return $self->view_supply_chains($session_id, $building_id); +} + +sub create_supply_chain { + my ($self, $session_id, $building_id, $target_id, $resource_type, $resource_hour) = @_; + + my $empire = $self->get_empire_by_session($session_id); + my $building = $self->get_building($empire, $building_id); + unless ($building) { + confess [1002, "Cannot find that building."]; + } + my $body = $building->body; + unless (defined $resource_hour) { + confess [1002, "You must specify an amount for resource_hour."]; + } + unless ($resource_hour >= 0) { + confess [1002, "Resource per Hour must be positive or zero."]; + } + unless (first {$resource_type eq $_} (FOOD_TYPES, ORE_TYPES, qw(water waste energy))) { + confess [1002, "That is not a valid resource_type."]; + } + + my $chain = $building->supply_chains->create({ + planet_id => $body->id, + building_id => $building_id, + target_id => $target_id, + resource_hour => $resource_hour, + resource_type => $resource_type, + percent_transferred => 0, + }); + unless ($chain) { + confess [1002, "Cannot create a supply chain."]; + } + $building->recalc_supply_production; + + return $self->view_supply_chains($session_id, $building_id); +} + sub update_supply_chain { - my ($self, $session_id, $building_id, $supply_chain_id, $supply_type, $supply_hour) = @_; + my ($self, $session_id, $building_id, $supply_chain_id, $resource_type, $resource_hour) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $self->get_building($empire, $building_id); unless ($building) { @@ -254,23 +305,23 @@ sub update_supply_chain { unless ($supply_chain_id) { confess [1002, "You must specify a supply chain id."]; } - unless (defined $supply_hour) { - confess [1002, "You must specify an amount for supply_hour."]; + unless (defined $resource_hour) { + confess [1002, "You must specify an amount for resource_hour."]; } - unless ($supply_hour >= 0) { + unless ($resource_hour >= 0) { confess [1002, "Resource per Hour must be positive or zero."]; } - unless (first {$supply_type eq $_} (FOOD_TYPES, ORE_TYPES, qw(water waste energy))) { - confess [1002, "That is not a valid supply type."]; + unless (first {$resource_type eq $_} (FOOD_TYPES, ORE_TYPES, qw(water waste energy))) { + confess [1002, "That is not a valid resource_type."]; } my $chain = $building->supply_chains->find($supply_chain_id); unless ($chain) { confess [1002, "That Supply Chain does not exist on this planet."]; } - $chain->supply_hour(int($supply_hour)); - $chain->supply_type($supply_type); + $chain->resource_hour(int($resource_hour)); + $chain->resource_type($resource_type); $chain->update; - $building->recalc_resource_production; + $building->recalc_supply__production; return $self->view_supply_chains($session_id, $building_id); } diff --git a/t/430_Supply_Chain.t b/t/430_Supply_Chain.t index 0fd32d76..a8b81a2f 100644 --- a/t/430_Supply_Chain.t +++ b/t/430_Supply_Chain.t @@ -3,7 +3,7 @@ use lib '../lib'; use strict; use warnings; -use Test::More tests => 25; +use Test::More tests => 10; use Test::Deep; use Data::Dumper; use 5.010; @@ -56,21 +56,38 @@ my $trade = Lacuna->db->resultset('Building')->search({ rows => 1, })->single; -diag "Trade id =[".$trade->id."]"; -$result = $tester->post('trade','get_supply_ships', [$session_id, $trade->id]); -#diag(Dumper($result->{result}{ships})); - # remove any existing ships from the supply chain +$result = $tester->post('trade','get_supply_ships', [$session_id, $trade->id]); my @ship_ids = map {$_->{id} } grep {$_->{task} eq 'Supply Chain'} @{$result->{result}{ships}}; -diag Dumper(\@ship_ids); - foreach my $ship_id ( @ship_ids ) { diag "### remove ship [$ship_id] ###"; $result = $tester->post('trade', 'remove_supply_ship_from_fleet', [$session_id, $trade->id, $ship_id]); } -exit; + +# remove any existing supply chains +$result = $tester->post('trade','view_supply_chains', [$session_id, $trade->id]); +my @chain_ids = map {$_->{id} } @{$result->{result}{supply_chains}}; +foreach my $chain_id (@chain_ids) { + diag "Remove supply chain [$chain_id]"; + $result = $tester->post('trade', 'delete_supply_chain', [$session_id, $trade->id, $chain_id]); +} + +# Determine the current resource production of the SS +$result = $tester->post('body','get_status', [$session_id, $station->id]); +my $ore_hour = $result->{result}{body}{ore_hour}; +my $water_hour = $result->{result}{body}{water_hour}; +my $energy_hour = $result->{result}{body}{energy_hour}; +my $food_hour = $result->{result}{body}{food_hour}; +diag "ore_hour=[$ore_hour] water_hour=[$water_hour] energy_hour=[$energy_hour] food_hour=[$food_hour]"; + +# Create supply chains to the SS +$result = $tester->post('trade','create_supply_chain',[$session_id, $trade->id, $station->id, 'water', -$water_hour]); +$result = $tester->post('trade','create_supply_chain',[$session_id, $trade->id, $station->id, 'trona', -$ore_hour]); +$result = $tester->post('trade','create_supply_chain',[$session_id, $trade->id, $station->id, 'energy',-$energy_hour]); +$result = $tester->post('trade','create_supply_chain',[$session_id, $trade->id, $station->id, 'algae', -$food_hour]); # get a single ships to add to the supply chain +$result = $tester->post('trade','get_supply_ships', [$session_id, $trade->id]); my ($ship_id) = map {$_->{id} } grep {$_->{task} eq 'Docked' and $_->{type} eq 'hulk'} @{$result->{result}{ships}}; diag("Ship [$ship_id]"); ok($ship_id, "We have a ship"); @@ -78,15 +95,19 @@ ok($ship_id, "We have a ship"); $result = $tester->post('trade','add_supply_ship_to_fleet',[$session_id, $trade->id, $ship_id]); is(1, 1, "Added a ship to the fleet"); +# Check the status of the supply chain +$result = $tester->post('trade','view_supply_chains', [$session_id, $trade->id]); +my @chains = @{$result->{result}{supply_chains}}; +foreach my $chain (@chains) { + cmp_ok($chain->{percent_transferred}, ">=", 100, "Transfer enough ".$chain->{resource_type}); +} - -#my @temp = map { {task => $_->{task}, type => $_->{type} } } @{$result->{result}{ships}}; -#my @comp = ({type=>'scow',task=>'Docked'},{type=>'scow_large',task=>'Docked'}); -#cmp_deeply(\@comp,\@temp, "All ships docked"); -# -# - - +# check that the station is at equilibrium +$result = $tester->post('body','get_status', [$session_id, $station->id]); +is($result->{result}{body}{ore_hour}, 0, "Zero ore"); +is($result->{result}{body}{water_hour}, 0, "Zero water"); +is($result->{result}{body}{energy_hour}, 0, "Zero energy"); +is($result->{result}{body}{food_hour}, 0, "Zero food"); END { # TestHelper->clear_all_test_empires; diff --git a/t/TestHelper.pm b/t/TestHelper.pm index 63d88d1f..6c126229 100644 --- a/t/TestHelper.pm +++ b/t/TestHelper.pm @@ -78,6 +78,12 @@ sub use_existing_test_empire { my ($empire) = Lacuna->db->resultset('Lacuna::DB::Result::Empire')->search({ name => $self->empire_name, }); + if (not $empire) { + $self->generate_test_empire; + my $home = $self->empire->home_planet; + $self->build_big_colony($home); + $empire = $self->empire; + } $self->session($empire->start_session({api_key => 'tester'})); $self->empire($empire); return $self; -- 2.51.2 From 8d27e5c557709799a278b8143bd9f95742560a0c Mon Sep 17 00:00:00 2001 From: ian docherty Date: Thu, 10 May 2012 10:31:45 -0400 Subject: [PATCH 4/9] Supply change testing bug fixes --- docs/Trade.pod | 14 -------------- lib/Lacuna/RPC/Building/Trade.pm | 2 +- t/430_Supply_Chain.t | 9 +++++++++ 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/docs/Trade.pod b/docs/Trade.pod index 0683d67d..f41dc1cd 100644 --- a/docs/Trade.pod +++ b/docs/Trade.pod @@ -1,14 +1,3 @@ -=head1 Trade Ministry Diagram - -The Trade Ministry is a complex beast, so to help you wrap your brain around it we've created a little flow diagram of how the methods come together. - -=begin html - - -
-OmniGraffle Version - -=end html =head1 Trade Ministry Methods @@ -16,9 +5,6 @@ The Trade Ministry is accessible via the URL C. It allows you to send ca The list of methods below represents changes and additions to the methods that all L share. - - - =head2 add_to_market ( session_id, building_id, offer, ask, options ) Queues a trade for others to see. Returns: diff --git a/lib/Lacuna/RPC/Building/Trade.pm b/lib/Lacuna/RPC/Building/Trade.pm index 36d91fac..e178044c 100644 --- a/lib/Lacuna/RPC/Building/Trade.pm +++ b/lib/Lacuna/RPC/Building/Trade.pm @@ -321,7 +321,7 @@ sub update_supply_chain { $chain->resource_hour(int($resource_hour)); $chain->resource_type($resource_type); $chain->update; - $building->recalc_supply__production; + $building->recalc_supply_production; return $self->view_supply_chains($session_id, $building_id); } diff --git a/t/430_Supply_Chain.t b/t/430_Supply_Chain.t index a8b81a2f..ca454520 100644 --- a/t/430_Supply_Chain.t +++ b/t/430_Supply_Chain.t @@ -86,6 +86,12 @@ $result = $tester->post('trade','create_supply_chain',[$session_id, $trade->id, $result = $tester->post('trade','create_supply_chain',[$session_id, $trade->id, $station->id, 'energy',-$energy_hour]); $result = $tester->post('trade','create_supply_chain',[$session_id, $trade->id, $station->id, 'algae', -$food_hour]); +my $supply_chains; +my @chains = @{$result->{result}{supply_chains}}; +foreach my $chain (@chains) { + $supply_chains->{$chain->{resource_type}} = $chain->{id}; +} + # get a single ships to add to the supply chain $result = $tester->post('trade','get_supply_ships', [$session_id, $trade->id]); my ($ship_id) = map {$_->{id} } grep {$_->{task} eq 'Docked' and $_->{type} eq 'hulk'} @{$result->{result}{ships}}; @@ -109,6 +115,9 @@ is($result->{result}{body}{water_hour}, 0, "Zero water"); is($result->{result}{body}{energy_hour}, 0, "Zero energy"); is($result->{result}{body}{food_hour}, 0, "Zero food"); +# modify a supply chain +$result = $tester->post('trade','update_supply_chain', [$session_id, $trade->id, $supply_chains->{water}, 'energy', 100]); + END { # TestHelper->clear_all_test_empires; } -- 2.51.2 From 032fec4686fbca2a46bedfc4ce581da15240ea35 Mon Sep 17 00:00:00 2001 From: ian docherty Date: Thu, 10 May 2012 17:15:23 -0400 Subject: [PATCH 5/9] Ensure that moving a body with BHG recalculates waste and supply chains --- lib/Lacuna/DB/Result/Building/Trade.pm | 2 +- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 17 +++++++++++++++-- lib/Lacuna/RPC/Body.pm | 2 +- lib/Lacuna/RPC/Building/BlackHoleGenerator.pm | 3 +++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/Lacuna/DB/Result/Building/Trade.pm b/lib/Lacuna/DB/Result/Building/Trade.pm index 2d5bca60..9d7a7599 100644 --- a/lib/Lacuna/DB/Result/Building/Trade.pm +++ b/lib/Lacuna/DB/Result/Building/Trade.pm @@ -224,7 +224,7 @@ sub recalc_supply_production { my ($self) = @_; my $body = $self->body; - # Determine the resourc/hour/distance for the ship + # Determine the resource/hour/distance for the ship my $ship_rphpd = 0; my $ships = $self->supply_ships; while (my $ship = $ships->next) { diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 861a3937..624af18f 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -913,6 +913,21 @@ sub resource_name { return $resource.'_hour'; } +# Recalculate waste and supply chains for this body +# +sub recalc_chains { + my ($self) = @_; + + # find the Trade Ministry + my ($trade_min) = $self->buildings->search({ + class => 'Lacuna::DB::Result::Building::Trade', + }); + if ($trade_min) { + $trade_min->recalc_supply_production; + $trade_min->recalc_waste_production; + } +} + sub recalc_stats { my ($self) = @_; @@ -1007,8 +1022,6 @@ sub recalc_stats { my $resource_hour = sprintf('%.0f',$in_chain->resource_hour * $percent / 100); my $resource_name = $self->resource_name($in_chain->resource_type); $stats{$resource_name} += $resource_hour; -carp "###>>> In Chain [$resource_hour][$resource_name] <<<###\n"; -#print STDERR Dumper($in_chain); if ($self->is_ore($in_chain->resource_type)) { $total_ore_production_hour += $resource_hour; } diff --git a/lib/Lacuna/RPC/Body.pm b/lib/Lacuna/RPC/Body.pm index 05213ca9..c6b499f9 100644 --- a/lib/Lacuna/RPC/Body.pm +++ b/lib/Lacuna/RPC/Body.pm @@ -9,6 +9,7 @@ use Lacuna::Constants qw(BUILDABLE_CLASSES); use DateTime; use Lacuna::Util qw(randint); use List::MoreUtils qw(uniq); +use Carp; use feature 'switch'; sub get_status { @@ -392,7 +393,6 @@ sub get_buildable { push @buildable, $plan->class->controller_class; $plans{$plan->class} = $plan->extra_build_level; } - foreach my $class (uniq @buildable) { $properties{class} = $class->model_class; my $building = $building_rs->new(\%properties); diff --git a/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm b/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm index 3a40c0a9..40e89494 100644 --- a/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm +++ b/lib/Lacuna/RPC/Building/BlackHoleGenerator.pm @@ -480,6 +480,8 @@ sub bhg_swap { star_id => $new_data->{star_id}, orbit => $new_data->{orbit}, }); + $body->recalc_chains; + #confess [ 9999, 'in swap!' ]; unless ($new_data->{type} eq "empty") { $target->update({ @@ -490,6 +492,7 @@ sub bhg_swap { star_id => $old_data->{star}, orbit => $old_data->{orbit}, }); + $target->recalc_chains; } return { message => "Swapped Places", -- 2.51.2 From f1364303ce0d6a7cc6081d4ad3da1c580554cd0a Mon Sep 17 00:00:00 2001 From: ian docherty Date: Fri, 11 May 2012 16:29:57 -0400 Subject: [PATCH 6/9] Supply chains now stall when resources reach zero --- lib/Lacuna/DB/Result/Map/Body/Planet.pm | 54 ++++++++++++++++++++----- lib/Lacuna/DB/Result/SupplyChain.pm | 1 + var/upgrades/3.0851.sql | 6 +-- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/lib/Lacuna/DB/Result/Map/Body/Planet.pm b/lib/Lacuna/DB/Result/Map/Body/Planet.pm index 624af18f..f9455c04 100644 --- a/lib/Lacuna/DB/Result/Map/Body/Planet.pm +++ b/lib/Lacuna/DB/Result/Map/Body/Planet.pm @@ -931,8 +931,6 @@ sub recalc_chains { sub recalc_stats { my ($self) = @_; -# carp "#### recalc_stats ####\n"; - my %stats = ( needs_recalc => 0 ); my $buildings = $self->buildings; #reset foods @@ -977,7 +975,7 @@ sub recalc_stats { while (my $waste_chain = $waste_chains->next) { my $percent = $waste_chain->percent_transferred; $percent = $percent > 100 ? 100 : $percent; - $percent *= $building->efficiency; + $percent *= $building->efficiency / 100; my $waste_hour = sprintf('%.0f',$waste_chain->waste_hour * $percent / 100); $stats{waste_hour} -= $waste_hour; } @@ -1009,9 +1007,10 @@ sub recalc_stats { } } - # supply chains sent *to* this planet + # active supply chains sent *to* this planet my $input_chains = Lacuna->db->resultset('Lacuna::DB::Result::SupplyChain')->search({ - target_id => $self->id, + target_id => $self->id, + stalled => 0, },{prefetch => 'building'} ); while (my $in_chain = $input_chains->next) { @@ -1348,19 +1347,52 @@ sub tick_to { } } # deal with negative amounts stored - if ($self->water_stored < 0) { - $self->water_stored(0); + # and deal with any supply-chains + if ($self->water_stored <= 0) { + $self->water_stored(0); + $self->toggle_supply_chain('water', 1) + } + else { + $self->toggle_supply_chain('water', 0); } - if ($self->energy_stored < 0) { - $self->energy_stored(0); + if ($self->energy_stored <= 0) { + $self->energy_stored(0); + $self->toggle_supply_chain('energy', 1); + } + else { + $self->toggle_supply_chain('energy', 0); } + for my $type (FOOD_TYPES, ORE_TYPES) { - my $stype = $type.'_stored'; - $self->$stype(0) if ($self->$stype < 0); + my $stype = $type.'_stored'; + if ($self->$stype <= 0) { + $self->$stype(0); + $self->toggle_supply_chain($type, 1); + } + else { + $self->toggle_supply_chain($type, 0); + } } $self->update; } +sub toggle_supply_chain { + my ($self, $resource, $new_state) = @_; + + my $chain_rs = $self->out_supply_chains->search({ + stalled => $new_state ? 0 : 1, + resource_type => $resource, + },{ + prefetch => 'target', + }); + while (my $chain = $chain_rs->next) { + $chain->stalled($new_state); + $chain->update; + $chain->target->needs_recalc(1); + $chain->target->update; + } +} + sub type_stored { my ($self, $type, $value) = @_; my $stored_method = $type.'_stored'; diff --git a/lib/Lacuna/DB/Result/SupplyChain.pm b/lib/Lacuna/DB/Result/SupplyChain.pm index dca1fdb8..f34a9c72 100644 --- a/lib/Lacuna/DB/Result/SupplyChain.pm +++ b/lib/Lacuna/DB/Result/SupplyChain.pm @@ -13,6 +13,7 @@ __PACKAGE__->add_columns( resource_hour => { data_type => 'int', size => 11, default_value => 0 }, resource_type => { data_type => 'varchar', default_value => '' }, percent_transferred => { data_type => 'int', size => 11, default_value => 0 }, + stalled => { data_type => 'int', size => 11, default_value => 0 }, ); __PACKAGE__->belongs_to('target', 'Lacuna::DB::Result::Map::Body', 'target_id'); diff --git a/var/upgrades/3.0851.sql b/var/upgrades/3.0851.sql index 0859ef8d..4155c359 100644 --- a/var/upgrades/3.0851.sql +++ b/var/upgrades/3.0851.sql @@ -7,13 +7,11 @@ create table supply_chain ( resource_hour bigint not null default 0, resource_type varchar(32) not null, percent_transferred int(11) not null default 0, + stalled int(11) not null default 0, primary key (id), key rc_idx_planet_id (planet_id), key rc_idx_building_id (building_id), - key rc_idx_target_id (target_id), - constraint rc_fk_planet_id foreign key (planet_id) references planet (id), - constraint rc_fk_building_id foreign key (building_id) references building (id), - constraint rc_fk_target_id foreign key (target_id) references planet (id) + key rc_idx_target_id (target_id) ); alter table waste_chain modify waste_hour bigint; -- 2.51.2 From 08da538f9a57b1c509f498cdea51bef3d21ed452 Mon Sep 17 00:00:00 2001 From: ian docherty Date: Fri, 11 May 2012 19:31:03 -0400 Subject: [PATCH 7/9] Limit number of Supply Chains based on level of Trade Ministry --- lib/Lacuna/RPC/Building/Trade.pm | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/Lacuna/RPC/Building/Trade.pm b/lib/Lacuna/RPC/Building/Trade.pm index e178044c..45707fdb 100644 --- a/lib/Lacuna/RPC/Building/Trade.pm +++ b/lib/Lacuna/RPC/Building/Trade.pm @@ -263,20 +263,47 @@ sub create_supply_chain { my ($self, $session_id, $building_id, $target_id, $resource_type, $resource_hour) = @_; my $empire = $self->get_empire_by_session($session_id); + unless (defined $building_id) { + confess [1002, "You must specify a building."]; + } + my $building = $self->get_building($empire, $building_id); unless ($building) { confess [1002, "Cannot find that building."]; } my $body = $building->body; + my $max_chains = $building->level * 3; + if ($body->supply_chains->count >= $max_chains) { + confess [1002, "You cannot create any more supply chains."]; + } + unless (defined $resource_hour) { confess [1002, "You must specify an amount for resource_hour."]; } - unless ($resource_hour >= 0) { + if ($resource_hour < 0) { confess [1002, "Resource per Hour must be positive or zero."]; } unless (first {$resource_type eq $_} (FOOD_TYPES, ORE_TYPES, qw(water waste energy))) { confess [1002, "That is not a valid resource_type."]; } + if ($self->id == $target_id) { + confess [1002, "You can't set up a supply chain to yourself."]; + } + my $target = Lacuna->db->resultset('Lacuna::DB::Result::Map::Body')->find($target_id); + unless ($target) { + confess [1002, "Cannot find that target body."]; + } + # Target must be own empire, or alliance SS + if ($target->empire_id != $empire->id) { + if ($target->class eq 'Lacuna::DB::Result::Map::Body::Planet::Station') { + if ($target->alliance_id != $empire->alliance_id) { + confess [1002, "You can only target one of your own alliances Space Stations."]; + } + } + else { + confess [1002, "You must only target one of your own colonies."]; + } + } my $chain = $building->supply_chains->create({ planet_id => $body->id, -- 2.51.2 From fce7b40962ca2bc5c2b9f3e8569fa159dfbcdc2d Mon Sep 17 00:00:00 2001 From: ian docherty Date: Fri, 11 May 2012 19:36:04 -0400 Subject: [PATCH 8/9] Set the maximum number of Supply Chains a trade ministry can handle. --- docs/Trade.pod | 9 +++++---- lib/Lacuna/RPC/Building/Trade.pm | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/Trade.pod b/docs/Trade.pod index f41dc1cd..12bb177f 100644 --- a/docs/Trade.pod +++ b/docs/Trade.pod @@ -598,12 +598,13 @@ Returns a list of the supply chains currently controlled by this Trade Ministry "resource_type" : 'water', "percent_transferred" : 95, } - ] + ], + "max_supply_chains" : 30 } -You can set up three supply-chains for each level of your Trade Ministry. Each -supply-chain can transfer any amount of any one resource (food type, ore type -energy, waste or water). +Each supply-chain can transfer any amount of any one resource (food type, ore type +energy, waste or water). B shows you how many Supply Chains +your Trade Ministry can handle. The B is the identifier for the Trade Ministry that is the source of the supply chain. diff --git a/lib/Lacuna/RPC/Building/Trade.pm b/lib/Lacuna/RPC/Building/Trade.pm index 45707fdb..c162a8c4 100644 --- a/lib/Lacuna/RPC/Building/Trade.pm +++ b/lib/Lacuna/RPC/Building/Trade.pm @@ -211,6 +211,7 @@ sub view_supply_chains { confess [1002, "Cannot find that building."]; } + my $max_chains = $building->level * 3; my $body = $building->body; my @supply_chains; my $chains = $building->supply_chains; @@ -220,6 +221,7 @@ sub view_supply_chains { return { status => $self->format_status($empire, $building->body), supply_chains => \@supply_chains, + max_supply_chains => $max_chains, }; } -- 2.51.2 From 5edac05e8b7e67f03bcadd0202662f4511507b54 Mon Sep 17 00:00:00 2001 From: lemming552 Date: Sat, 12 May 2012 09:45:37 -0600 Subject: [PATCH 9/9] out_supply_chains for checking number of supply chains from planet. --- lib/Lacuna/RPC/Building/Trade.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Lacuna/RPC/Building/Trade.pm b/lib/Lacuna/RPC/Building/Trade.pm index c162a8c4..de38cd32 100644 --- a/lib/Lacuna/RPC/Building/Trade.pm +++ b/lib/Lacuna/RPC/Building/Trade.pm @@ -275,8 +275,8 @@ sub create_supply_chain { } my $body = $building->body; my $max_chains = $building->level * 3; - if ($body->supply_chains->count >= $max_chains) { - confess [1002, "You cannot create any more supply chains."]; + if ($body->out_supply_chains->count >= $max_chains) { + confess [1002, "You cannot create any more supply chains outgoing from this planet."]; } unless (defined $resource_hour) { -- 2.51.2