diff --git a/docs/Intro.pod b/docs/Intro.pod index 2d89fe03..91b65d69 100644 --- a/docs/Intro.pod +++ b/docs/Intro.pod @@ -131,7 +131,17 @@ Most methods will provide a status block as part of the response. This is used t "x" : [ -15, 15 ], "y" : [ -15, 15 ], "z" : [ -15, 15 ] - } + }, + "promotions" : [ + { + "description" : "With a purchase of essentia, receive a 50% bonus!", + "end_date" : "31 10 2015 00:00:00 +0000", + "start_date : "01 10 2015 00:00:00 +0000", + "type" : "Bonus50", + "min_purchase" : null, # essentia, not $ + "max_purchase" : null # essentia, not $ + } + ] }, "empire" : { # this block is not always included See get_status() in Empire diff --git a/lib/Lacuna/DB/Result/Promotion.pm b/lib/Lacuna/DB/Result/Promotion.pm new file mode 100644 index 00000000..cfdacaaa --- /dev/null +++ b/lib/Lacuna/DB/Result/Promotion.pm @@ -0,0 +1,98 @@ +package Lacuna::DB::Result::Promotion; + +use Moose; +use utf8; +extends 'Lacuna::DB::Result'; +use Lacuna::Util qw(format_date); + +__PACKAGE__->load_components('DynamicSubclass'); +__PACKAGE__->table('promotion'); +__PACKAGE__->add_columns( + start_date => { data_type => 'datetime', is_nullable => 0 }, + end_date => { data_type => 'datetime', is_nullable => 0 }, + type => { data_type => 'varchar', size => 30, is_nullable => 0 }, # Look at typecast_map below + min_purchase => { data_type => 'int', is_nullable => 1, }, + max_purchase => { data_type => 'int', is_nullable => 1, }, + payload => { data_type => 'mediumblob', is_nullable => 1, 'serializer_class' => 'JSON' }, +); + +our @types = qw( + Bonus50 + ); + +__PACKAGE__->typecast_map(type => { + map { $_ => __PACKAGE__ . '::' . $_ } @types +}); + +sub ui_details { + my ($self) = @_; + + my @with; + push @with, sprintf "minimum purchase of %d", $self->min_purchase if defined $self->min_purchase; + push @with, sprintf "maximum purchase of %d", $self->max_purchase if defined $self->max_purchase; + + my $description = ''; + if (@with) { + if (@with == 2 && $self->min_purchase == $self->max_purchase) + { + $description = sprintf "With a purchase of %d essentia, "; + } + else + { + $description = sprintf "With a %s essentia, ", join ' and ', @with if @with; + } + $description .= $self->description; + } + else + { + $description = "With a purchase of essentia, " . $self->description; + } + + return { + start_date => format_date($self->start_date), + end_date => format_date($self->end_date), + type => $self->type, + min_purchase => $self->min_purchase, + max_purchase => $self->max_purchase, + description => ucfirst $description, + }; +} + + +# checks min/max purchase amounts (if any) +sub purchase_applies +{ + my ($self, $opts) = @_; + + return 0 if defined $self->min_purchase && $opts->{amount} < $self->min_purchase; + return 0 if defined $self->max_purchase && $opts->{amount} > $self->max_purchase; + + return 1; +} + +# opts: +# amount (essentia) +# empire (object) +# cost (in USD) +# transaction_id +# type (iTransact, Paypal, etc.) + +sub essentia_purchased +{ + my ($self, $opts) = @_; + + return; # not all promotions are necessarily E-based? +} + +around essentia_purchased => sub { + my ($orig, $self, $opts) = @_; + + # pre-check this automatically. + return unless $self->purchase_applies($opts); + + return $self->$orig($opts); +}; + + +no Moose; +__PACKAGE__->meta->make_immutable(inline_constructor => 0); diff --git a/lib/Lacuna/DB/Result/Promotion/Bonus50.pm b/lib/Lacuna/DB/Result/Promotion/Bonus50.pm new file mode 100644 index 00000000..5fa76655 --- /dev/null +++ b/lib/Lacuna/DB/Result/Promotion/Bonus50.pm @@ -0,0 +1,11 @@ +package Lacuna::DB::Result::Promotion::Bonus50; + +use Moose; +use utf8; +no warnings qw(uninitialized); +extends 'Lacuna::DB::Result::Promotion::BonusEssentia'; + +use constant bonus_percent => 50; + +no Moose; +__PACKAGE__->meta->make_immutable(inline_constructor => 0); diff --git a/lib/Lacuna/DB/Result/Promotion/BonusEssentia.pm b/lib/Lacuna/DB/Result/Promotion/BonusEssentia.pm new file mode 100644 index 00000000..8db1c0eb --- /dev/null +++ b/lib/Lacuna/DB/Result/Promotion/BonusEssentia.pm @@ -0,0 +1,37 @@ +package Lacuna::DB::Result::Promotion::BonusEssentia; + +use Moose; +use utf8; +no warnings qw(uninitialized); +extends 'Lacuna::DB::Result::Promotion'; + +sub essentia_purchased +{ + my ($self, $opts) = @_; + + my $bonus = int( $opts->{amount} * $self->bonus_percent() / 10 + 0.5 ) / 10; + my $empire = $opts->{empire}; + + $empire->add_essentia({ + amount => $bonus, + reason => sprintf('Bonus %d%%', $self->bonus_percent()), + type => 'paid', + transaction_id => $opts->{transaction_id}, + }); + $empire->update; + $empire->send_predefined_message( + tags => ['Alert'], + filename => 'promo/bonus_essentia.txt', + params => [$self->bonus_percent(), $bonus, $opts->{transaction_id}], + ); + +} + +sub description { + my ($self) = @_; + + sprintf "receive a %d%% bonus!", $self->bonus_percent; +} + +no Moose; +__PACKAGE__->meta->make_immutable(inline_constructor => 0); diff --git a/lib/Lacuna/DB/ResultSet/Promotion.pm b/lib/Lacuna/DB/ResultSet/Promotion.pm new file mode 100644 index 00000000..ad86bf5e --- /dev/null +++ b/lib/Lacuna/DB/ResultSet/Promotion.pm @@ -0,0 +1,26 @@ +package Lacuna::DB::ResultSet::Promotion; + +use Moose; +use utf8; +no warnings qw(uninitialized); + +extends 'Lacuna::DB::ResultSet'; + +sub current_promotions_rs +{ + my $self = shift; + + $self->search( + { + start_date => [ undef, { '<=' => \q{UTC_TIMESTAMP()} }], + end_date => [ undef, { '>' => \q{UTC_TIMESTAMP()} }], + }); +} + +sub current_promotions { + my ($self) = @_; + $self->current_promotions_rs->all; +} + +no Moose; +__PACKAGE__->meta->make_immutable(inline_constructor => 0); diff --git a/lib/Lacuna/RPC.pm b/lib/Lacuna/RPC.pm index 0a489a36..29c1852c 100644 --- a/lib/Lacuna/RPC.pm +++ b/lib/Lacuna/RPC.pm @@ -55,7 +55,7 @@ sub get_empire_by_session { } my $ipm = $session->ip_address eq $ipr; my @caller; - for (my $i = 1;!@caller || $caller[0] !~ /Lacuna::RPC/;++$i) { + for (my $i = 1;@caller and $caller[0] !~ /Lacuna::RPC/;++$i) { @caller = caller($i); } $log->info(sprintf "ACTUAL:ipr=%s,ipe=%s,ipm=%s,ses=%s,sat:%d,rpc=%s", $ipr, $session->ip_address, $ipm, $session_id, $session->is_sitter ? 1 : 0, $caller[3]); @@ -157,6 +157,11 @@ sub format_status { $out{server}{announcement} = 1; } $out{empire} = $empire->get_status; + + if (my @promos = Lacuna->db->resultset('Promotion')->current_promotions) + { + $out{server}{promotions} = [ map $_->ui_details, @promos ]; + } } if (defined $body) { $out{body} = $body->get_status($empire); diff --git a/lib/Lacuna/Web/Pay.pm b/lib/Lacuna/Web/Pay.pm index 4ba9005a..bb636930 100644 --- a/lib/Lacuna/Web/Pay.pm +++ b/lib/Lacuna/Web/Pay.pm @@ -559,9 +559,16 @@ sub www_buy_currency_cc { $empire->send_predefined_message( tags => ['Alert'], filename => 'purchase_essentia.txt', - params => [$amount, $transaction_id], + params => [$amount, $transaction_id], ); - + $self->_run_promotions({ + amount => $amount, + empire => $empire, + cost => $request->param('total'), + type => 'iTransact', + transaction_id => $transaction_id + }); + my $script = " try { window.opener.YAHOO.lacuna.Essentia.paymentFinished(); @@ -727,6 +734,13 @@ sub www_paypal_ec_checkout { filename => 'purchase_essentia.txt', params => [$amount, $transaction_id], ); + $self->_run_promotions({ + amount => $amount, + empire => $empire, + cost => $order->{total}, + type => 'PayPal', + transaction_id => $transaction_id + }); Lacuna->cache->delete( 'paypal_order', $user_id ); my $script = " @@ -738,6 +752,17 @@ sub www_paypal_ec_checkout { return $self->wrap('Thank you! The essentia will be added to your account momentarily.'); } +sub _run_promotions +{ + my ($self, $opts) = @_; + + my $rs = Lacuna->db->resultset("Promotion")->current_promotions_rs; + while (my $promo = $rs->next()) + { + $promo->essentia_purchased($opts); + } +} + no Moose; __PACKAGE__->meta->make_immutable(inline_constructor => 0); diff --git a/var/messages/promo/bonus_essentia.txt b/var/messages/promo/bonus_essentia.txt new file mode 100644 index 00000000..2789cb3f --- /dev/null +++ b/var/messages/promo/bonus_essentia.txt @@ -0,0 +1,5 @@ +Promotional Essentia Added +~~~ +Due to the current %s%%-bonus promotions, an extra %s has been credited to your empire. + +Transaction ID: %s diff --git a/var/upgrades/3.0915.sql b/var/upgrades/3.0915.sql new file mode 100644 index 00000000..5f9d4365 --- /dev/null +++ b/var/upgrades/3.0915.sql @@ -0,0 +1,10 @@ +CREATE TABLE promotion ( + id integer(11) NOT NULL auto_increment, + start_date datetime NOT NULL, + end_date datetime NOT NULL, + type varchar(30) NOT NULL, + min_purchase integer NULL, + max_purchase integer NULL, + payload mediumblob NULL, + PRIMARY KEY (id) +); diff --git a/var/www/public/changes.txt b/var/www/public/changes.txt index 057ba7fd..5e396877 100644 --- a/var/www/public/changes.txt +++ b/var/www/public/changes.txt @@ -1,6 +1,7 @@ 3.0915: - Fix: Reduce the wild resource fluctuations during planet ticking. - Mod: Evein plans get an extra 5 days start time for building. + - Add: Lacuna promotions. 3.0914: - UI : Evein draining re-added.