new position logic for the lemmatizer and toggler; still need non-linear positions
[scpubgit/stemmatology.git] / lib / Text / Tradition / Collation / Position.pm
CommitLineData
45456358 1package Text::Tradition::Collation::Position;
2
3use Moose;
4
5has 'common' => (
6 is => 'rw',
7 isa => 'Int',
8 required => 1,
9 );
10
11has 'min' => (
12 is => 'rw',
13 isa => 'Int',
14 required => 1,
15 );
16
17has 'max' => (
18 is => 'rw',
19 isa => 'Int',
20 required => 1,
21 );
22
4cdd82f1 23# This gets set if we are tracking a more specifically-positioned
24# reading.
25has 'matched' => (
26 is => 'rw',
27 isa => 'Bool',
28 );
29
45456358 30around BUILDARGS => sub {
31 my $orig = shift;
32 my $class = shift;
33
34 # Two ways we can be called - with the arguments we expect, or with a
35 # single argument to be parsed out into a position.
36 my %args;
37 if( @_ == 1 ) {
38 my( $common, $min, $max ) = parse_reference( $_[0] );
39 %args = ( 'common' => $common,
40 'min' => $min,
41 'max' => $max );
42 } elsif ( 2 <= @_ && @_ <= 3 ) {
43 my( $common, $min, $max ) = @_;
44 $max = $min unless $max;
45 %args = ( 'common' => $common,
46 'min' => $min,
47 'max' => $max );
48 } else {
49 %args = @_;
50 }
51
52 return $class->$orig( %args );
53};
54
55sub BUILD {
56 my $self = shift;
57 if( $self->min > $self->max ) {
58 die "Position minimum cannot be higher than maximum";
59 }
60}
61
62sub parse_reference {
63 my( $ref ) = @_;
64 if( $ref =~ /^(\d+),(\d+)(\-(\d+))?$/ ) {
65 my( $common, $min, $max ) = ( $1, $2, $4 );
66 $max = $min unless defined $max;
67 return( $common, $min, $max );
68 } else {
69 warn "Bad argument $ref passed to Position constructor";
70 return undef;
71 }
72}
73
74# Instance method
75sub cmp_with {
76 my( $self, $other ) = @_;
77 return _cmp_bits( [ $self->common, $self->min, $self->max ],
78 [ $other->common, $other->min, $other->max ] );
79}
80
81# Class method
82sub str_cmp {
83 my( $a, $b ) = @_;
84 my @abits = parse_reference( $a );
85 my @bbits = parse_reference( $b );
86 return _cmp_bits( \@abits, \@bbits );
87}
88
89sub _cmp_bits {
90 my( $a, $b ) = @_;
91 return $a->[0] <=> $b->[0]
92 unless $a->[0] == $b->[0];
93 return $a->[1] <=> $b->[1]
94 unless $a->[1] == $b->[1];
95 return $a->[2] <=> $b->[2];
96}
97
98sub minref {
99 my $self = shift;
100 return join(',', $self->common, $self->min );
101}
102
103sub maxref {
104 my $self = shift;
105 return join(',', $self->common, $self->max );
106}
107
108sub reference {
109 my $self = shift;
110 my $answer = join( ',', $self->common, $self->min );
111 $answer .= '-'. $self->max unless $self->min == $self->max;
112 return $answer;
113}
114
115sub fixed {
116 my $self = shift;
117 return $self->min == $self->max;
118}
119
120sub is_colocated {
121 my( $self, $other, $strict ) = @_;
122 if( $strict ) {
123 return $self->common == $other->common
124 && $self->min == $other->min
125 && $self->max == $other->max;
126 } else {
127 return $self->common == $other->common
128 && $self->min <= $other->max
129 && $self->max >= $other->min;
130 }
131}
132
133# Return all the possible fixed position refs.
134sub possible_positions {
135 my $self = shift;
136 my @possible = map { join( ',', $self->common, $_ ) } ( $self->min .. $self->max );
137 return @possible;
138}
139
140no Moose;
141__PACKAGE__->meta->make_immutable;