package WebService::ForecastIo::DataBlock; use Moo; use namespace::autoclean; use Types::Standard -all; use WebService::ForecastIo::Types -all; use WebService::ForecastIo::DataSpan; has [qw(summary icon)] => ( is => 'ro', isa => Str, ); has data => ( is => 'ro', isa => DataPointArray, coerce => DataPointArray->coercion, ); sub data_points { @{$_[0]->data} } sub spans_by_string { my ($self,$field) = @_; $self->_spans( $field, sub { $_[0] eq $_[1] } ); } sub spans_by_number { my ($self,$field,$tolerance) = @_; $self->_spans( $field, sub { abs($_[0] - $_[1]) <= $tolerance } ); } sub slice { my ($self,%opts) = @_; my $from = $opts{from} // 0-'Inf'; my $to = $opts{to} // 0+'Inf'; return ref($self)->new({ summary => $self->summary, icon => $self->icon, data => [ grep { $_->time >= $from && $_->time <= $to } $self->data_points ], }); } sub _spans { my ($self,$field,$comp) = @_; my $out; for my $dp ($self->data_points) { next unless $dp->time; my $v = $dp->$field; if (!$out) { $out = [ WebService::ForecastIo::DataSpan->new({ start_time => $dp->time, stop_time => $dp->time, value => $v, }) ]; } else { my $prev = $out->[-1]->value; $out->[-1]->_set_stop_time($dp->time); if (not $comp->($prev,$v)) { # new span push @$out, WebService::ForecastIo::DataSpan->new({ start_time => $dp->time, stop_time => $dp->time, value => $v, }); } } } if (@$out) { $out->[-1]->_set_stop_time($self->data->[-1]->time); } return $out; } 1;