package Particle;
use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Deepcopy = 1;
$Data::Dumper::Sortkeys = 1;
our %param;
our %REGISTRY;
sub new {
my $class = shift;
$param{is_movable} = 0;
@{ $param{history} } = ();
$param{position} = { x => 0, y => 0, z => 0, };
$param{movement} = { dx => 0, dy => 0, dz => 0, };
$param{is_active} = 0;
my $self = bless \%param, $class;
if ( scalar @_ ) {
$self->init(@_);
}
$REGISTRY{$self} = $self;
# my $format_str = qq{Class: %s\n\tKey: %s\n\tref(): %s\n};
# my $t = ref( $REGISTRY{$self} );
# print sprintf $format_str, $class, $self, $t;
return $self;
}
sub init {
my $self = shift;
my ($data) = @_;
foreach my $k ( keys %{$data} ) {
$self->set( $k, \$data->{$k} );
}
}
sub get {
my $self = shift;
my $k = shift;
if ( $k =~ m/^p_?(.)/i ) {
return $self->{position}{$1};
}
elsif ( $k =~ m/^m_?d?(.)/i or $k =~ m/^d(.)/i ) {
return $self->{movement}{ q{d} . $1 };
}
elsif ( $k =~ m/^is_a/i ) {
return $self->{is_active};
}
elsif ( $k =~ m/^is_m/i ) {
return $self->{is_movable};
}
elsif ( $k =~ m/^h_?(\d+)/i ) {
return $self->{history}[$1];
}
elsif ( $k =~ m/^hc/i ) {
return scalar @{ $self->{history} };
}
}
sub set {
my $self = shift;
my $k = shift;
if ( $k =~ m/^h_?self/i ) {
push @{ $self->{history} },
{
time => time,
position => \$self->{position},
movement => \$self->{movement},
};
return;
}
my $v = shift;
if ( ref $v eq q{REF} ) {
if ( $k =~ m/^position/i ) {
$self->{position} = $$v;
}
elsif ( ref $v eq q{REF} and $k =~ m/^movement/i ) {
$self->{movement} = $$v;
}
}
else {
if ( $k =~ m/^p_?(.)/i ) {
$self->{position}{$1} = $v;
}
elsif ( $k =~ m/^m_?d?(.)/i or $k =~ m/^d(.)/i ) {
$self->{movement}{ q{d} . $1 } = $v;
}
elsif ( $k =~ m/^is_a/i ) {
$self->{is_active} = $v;
}
elsif ( $k =~ m/^is_m/i ) {
$self->{is_movable} = $v;
}
elsif ( $k =~ m/^h_?(\d+)/i ) {
$self->{history}[$1] = $v;
}
elsif ( $k =~ m/^h/i ) {
push @{ $self->{history} }, $v;
}
}
}
sub total_count {
my $class = shift;
print __FILE__, q{:}, __LINE__, q{ }, $class, qq{\n};
# print Data::Dumper->Dump(
# [ \%REGISTRY, ],
# [ qw( *REGISTRY ) ]
# ), qq{\n};
my $format_str = qq{Class: %s\n\tKey: %s\n\tref(): %s\n};
foreach my $k ( keys %REGISTRY ) {
my $t = ref( $REGISTRY{$k} );
print sprintf $format_str, $class, $k, $t;
}
return
scalar
grep { ref( $REGISTRY{$_} ) eq $class }
keys %REGISTRY;
}
1;
####
package MoveableParticle;
use parent 'Particle';
use Data::Dumper;
$Data::Dumper::Deepcopy = 1;
$Data::Dumper::Sortkeys = 1;
our @ISA = ( 'Particle', );
our %REGISTRY;
sub new {
my $class = shift;
my $self = $class->SUPER::new( @_ );
$self->set( 'is_moveable', 1 );
return $self;
}
1;
##
##
package StationaryParticle;
use parent 'Particle';
use Data::Dumper;
$Data::Dumper::Deepcopy = 1;
$Data::Dumper::Sortkeys = 1;
our @ISA = ( 'Particle', );
our %REGISTRY;
sub new {
my $class = shift;
my $self = $class->SUPER::new( @_ );
$self->set( 'is_moveable', 0 );
return $self;
}
1;
##
##
#!/usr/bin/perl
use strict;
use warnings;
use Carp::Always;
use Data::Dumper;
use Test::More;
use StationaryParticle;
use MoveableParticle;
$| = 1;
srand();
$Data::Dumper::Deepcopy = 1;
$Data::Dumper::Sortkeys = 1;
my @particles;
push @particles, MoveableParticle->new(
{
position => { x => 10, y => 10, z => 10, },
movement => { dx => 5, dy => -5, dz => 0, },
}
);
# print Data::Dumper->Dump( [ \@particles, ], [ qw( *particles ) ] ),
# qq{\n};
$particles[0]->set( 'is_active', 0, );
isa_ok( $particles[0], 'MoveableParticle' );
isa_ok( $particles[0], 'Particle' );
isa_ok( $particles[0], 'StationaryParticle' );
print qq{Object 0: }, ref( $particles[0] ), qq{\n};
print qq{\n};
push @particles, StationaryParticle->new(
{ position => { x => 20, y => 20, z => 0, }, },
);
isa_ok( $particles[1], 'MoveableParticle' );
isa_ok( $particles[1], 'Particle' );
isa_ok( $particles[1], 'StationaryParticle' );
print qq{Object 1: }, ref( $particles[1] ), qq{\n};
print qq{\n};
# print Data::Dumper->Dump( [ \@particles, ], [ qw( *particles ) ] ),
# qq{\n};
print qq{Particle count: },
Particle->total_count, qq{\n};
print qq{\n};
print qq{Stationary particle count: },
StationaryParticle->total_count, qq{\n};
print qq{\n};
print qq{Moveable particle count: },
MoveableParticle->total_count, qq{\n};
print qq{\n};
Test::More::done_testing();
##
##
Class: MoveableParticle
Key: MoveableParticle=HASH(0x264e050)
ref(): MoveableParticle
ok 1 - The object isa MoveableParticle
ok 2 - The object isa Particle
not ok 3 - The object isa StationaryParticle
# Failed test 'The object isa StationaryParticle'
# at module_test.20140103.pl line 28.
# The object isn't a 'StationaryParticle' it's a 'MoveableParticle'
Object 0: MoveableParticle
Class: StationaryParticle
Key: StationaryParticle=HASH(0x264e050)
ref(): StationaryParticle
not ok 4 - The object isa MoveableParticle
# Failed test 'The object isa MoveableParticle'
# at module_test.20140103.pl line 35.
# The object isn't a 'MoveableParticle' it's a 'StationaryParticle'
ok 5 - The object isa Particle
ok 6 - The object isa StationaryParticle
Object 1: StationaryParticle
Particle.pm:307 Particle
Class: Particle
Key: StationaryParticle=HASH(0x264e050)
ref(): StationaryParticle
Class: Particle
Key: MoveableParticle=HASH(0x264e050)
ref(): StationaryParticle
Particle count: 0
Particle.pm:307 StationaryParticle
Class: StationaryParticle
Key: StationaryParticle=HASH(0x264e050)
ref(): StationaryParticle
Class: StationaryParticle
Key: MoveableParticle=HASH(0x264e050)
ref(): StationaryParticle
Stationary particle count: 2
Particle.pm:307 MoveableParticle
Class: MoveableParticle
Key: StationaryParticle=HASH(0x264e050)
ref(): StationaryParticle
Class: MoveableParticle
Key: MoveableParticle=HASH(0x264e050)
ref(): StationaryParticle
Moveable particle count: 0
1..6
# Looks like you failed 2 tests of 6.