#!/usr/bin/perl use strict; use warnings; use Moose::Autobox; sub Moose::Autobox::SCALAR::split { my $self = shift; my $delim = shift; [ split( $delim, $self ) ]; } sub Moose::Autobox::SCALAR::sprintf { my $self = shift; sprintf( $self, @_ ); } sub Moose::Autobox::ARRAY::stringify { my $self = shift; my $delim = shift || " "; join $delim, map { $_->stringify } @{$self}; } use MooseX::Declare; class Property { use MooseX::Has::Sugar; use MooseX::Types::Moose (':all'); use Moose::Autobox; use Carp; has name => ( isa => Str, rw, required, ); has income => ( isa => Num, rw, required, ); has cost => ( isa => Num, rw, required, ); has owned => ( isa => Num, rw, required, ); has effectiveness => ( isa => Num, rw, lazy_build, ); has units_buildable => ( isa => Num, rw, default => 0, ); has cash_needed => ( isa => Num, rw, default => 0, ); method income_expected { $self->income * $self->owned; } method parse( ClassName $class: $str ) { my $tokens = $str->split(qr/ /); return $class->new( name => $tokens->at(0), income => $tokens->at(1), cost => $tokens->at(2), owned => $tokens->at(3), ); }; method build( Num $bank , Num $play ) { $self->units_buildable( int( ( $bank + $play ) / $self->cost ) ); if ( $self->units_buildable < 1 ) { $self->units_buildable(0); } elsif ( $self->units_buildable < 5 ) { $self->units_buildable(1); } elsif ( $self->units_buildable < 10 ) { $self->units_buildable(5); } elsif ( $self->units_buildable > 10 ) { $self->units_buildable(10); } $self->cash_needed( ( $self->units_buildable * $self->cost ) - $play ); if ( $self->cash_needed < 0 ) { $self->cash_needed(0); } return $self; }; method _build_effectiveness { ( $self->income / $self->cost ) * 100; }; method compare( Property $other, Str $field ) { my $mymethod = $self->can($field); my $othermethod = $other->can($field); unless ( $mymethod && $othermethod ) { croak("No Field $field"); } my $x = $self->$mymethod(); my $y = $other->$othermethod(); return $x <=> $y; }; method header( ClassName $class: ) { my $h = ' Property: [ Cost , Income , ROI/Turn , Build, Cashout , Owned , Net ]'; # my $fm = '%20s: [ %13s , %11s , roi/t %2.3f%%, b %2.0f, cn %7.0f ]'; # $d = $fm->sprintf( 'Property', 'Cost', 'Income', 'ROI/Turn', 'Buildable','BuildCost' ); $h .= ( "\n" . "-" x length($h) ); $h; }; method stringify { my $fm = '%20s: [ $%12.0f , $%8.0f , %8.5f%%, b %2.0f, cn %7.0f , %3.0f u , %10.0f]'; $fm->sprintf( $self->name, $self->cost, $self->income, $self->effectiveness, $self->units_buildable, $self->cash_needed, $self->owned, $self->income_expected ); }; } my $d = <<'EOF'; GarageWarehouse 100 21000 33 AutoBodyShop 400 66000 23 Nightclub 2000 310000 21 BallerMansion 7000 840000 14 MalibuEstate 65000 9000000 20 Casino 150000 168800000 4 PrivateIsland 200000 50000000 10 TopsyTurvy 14000 999999999999 1 EOF my $data = $d->split(qr/\n/)->map( sub { Property->parse($_); } ); my $total = 0; $data->map( sub { $total += $_->income_expected; } ); # Bank , Working Balance $data->map( sub { $_->build( 4_244, 3_982_961 ); } ); my $buildable = $data->grep( sub { $_->units_buildable > 0 } ); Property->header->say(); $data->sort( sub { $_[0]->compare( $_[1], 'effectiveness' ) } )->stringify("\n")->say; $total->say;