File Coverage

blib/lib/Acme/Partitioner.pm
Criterion Covered Total %
statement 18 78 23.0
branch 0 8 0.0
condition 0 5 0.0
subroutine 6 16 37.5
pod 6 6 100.0
total 30 113 26.5


line stmt bran cond sub pod time code
1             package Acme::Partitioner;
2 3     3   45536 use 5.012000;
  3         8  
  3         101  
3 3     3   14 use strict;
  3         3  
  3         87  
4 3     3   12 use warnings;
  3         12  
  3         967  
5            
6             require Exporter;
7            
8             our @ISA = qw(Exporter);
9            
10             our %EXPORT_TAGS = ( 'all' => [ qw(
11             ) ] );
12            
13             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
14            
15             our @EXPORT = qw(
16             );
17            
18             our $VERSION = '0.01';
19            
20             sub using {
21 0     0 1   my ($class, @list) = @_;
22 0           bless {
23 0           by_string => { map { $_ => 0 } @list },
24             sublists => [\@list],
25             }, $class;
26             }
27            
28             sub once_by {
29 0     0 1   my ($self, $sub) = @_;
30 0           Acme::Partitioner::Actor::_new(undef, "once", $sub, $self);
31             }
32            
33             sub partition_of {
34 0     0 1   my ($self, $item) = @_;
35 0           $self->{by_string}{$item};
36             }
37            
38             sub items_in {
39 0     0 1   my ($self, $partition) = @_;
40 0           @{ $self->{sublists}[$partition] }
  0            
41             }
42            
43             sub size {
44 0     0 1   my ($self) = @_;
45 0           scalar @{ $self->{sublists} }
  0            
46             }
47            
48             sub all_partitions {
49 0     0 1   my ($self) = @_;
50 0           map { [@$_] } @{ $self->{sublists} }
  0            
  0            
51             }
52            
53             package Acme::Partitioner::Actor;
54 3     3   42 use 5.012000;
  3         7  
  3         71  
55 3     3   15 use strict;
  3         3  
  3         74  
56 3     3   10 use warnings;
  3         3  
  3         1175  
57            
58             sub _new {
59 0     0     my ($old, $type, $sub, $partitioner) = @_;
60 0   0       $partitioner //= $old->{partitioner};
61 0           bless {
62             partitioner => $partitioner,
63             subs => [
64 0 0         ($old ? @{ $old->{subs} } : ()),
65             [$type, $sub],
66             ],
67             }, __PACKAGE__
68             }
69            
70             sub once_by {
71 0     0     my ($self, $sub) = @_;
72 0           _new($self, "once", $sub);
73             }
74            
75             sub then_by {
76 0     0     my ($self, $sub) = @_;
77 0           _new($self, "then", $sub);
78             }
79            
80             sub refine {
81 0     0     my ($self) = @_;
82            
83 0 0         unless (@{ $self->{subs} }) {
  0            
84 0           warn "Attempt to refine partitions without active refiners";
85 0           return;
86             }
87            
88 0           my $old_size = $self->{partitioner}->size();
89 0           my $next_id = $old_size;
90            
91 0           for (my $ix = 0; $ix < @{ $self->{subs} }; ++$ix) {
  0            
92            
93 0           my @temp;
94 0           for my $sublist (@{ $self->{partitioner}{sublists} }) {
  0            
95 0           my %h;
96 0           for my $item (@{ $sublist }) {
  0            
97 0           local $_ = $item;
98 0           my $key = $self->{subs}[$ix][1]->($item);
99 0           push @{ $h{$key} }, $item;
  0            
100             }
101 0           push @temp, values %h;
102             }
103            
104             #################################################################
105             #
106             #################################################################
107 0           my %occupied;
108             my @new_list;
109            
110 0           for (my $ix = 0; $ix < @temp; ++$ix) {
111 0           my $first = $temp[$ix]->[0];
112 0   0       my $first_id = $self->{partitioner}->partition_of($first) // 0;
113 0 0         if (not $occupied{ $first_id }++) {
114 0           $new_list[ $first_id ] = $temp[$ix];
115 0           next;
116             }
117 0           my $new_id = $next_id++;
118 0           $new_list[ $new_id ] = $temp[$ix];
119 0           $self->{partitioner}{by_string}{$_} = $new_id
120 0           for @{ $temp[$ix] };
121             }
122            
123 0           $self->{partitioner}{sublists} = \@new_list;
124            
125             #################################################################
126             #
127             #################################################################
128 0 0         splice @{ $self->{ subs } }, $ix--, 1
  0            
129             if $self->{subs}[$ix]->[0] eq 'once';
130             }
131            
132 0           return $self->{partitioner}->size() != $old_size;
133             }
134            
135            
136             1;
137            
138             __END__