File Coverage

blib/lib/Feed/PhaseCheck.pm
Criterion Covered Total %
statement 39 52 75.0
branch 11 22 50.0
condition 9 20 45.0
subroutine 5 6 83.3
pod 1 1 100.0
total 65 101 64.3


line stmt bran cond sub pod time code
1             package Feed::PhaseCheck;
2              
3 1     1   79123 use 5.006;
  1         13  
4 1     1   6 use strict;
  1         12  
  1         19  
5 1     1   5 use warnings;
  1         2  
  1         38  
6              
7 1     1   6 use Exporter qw(import);
  1         2  
  1         639  
8              
9             our @EXPORT_OK = qw(compare_feeds);
10              
11             # ABSTRACT: Finds the relative time delay between two feed segments.
12              
13             =head1 NAME
14              
15             Feed::PhaseCheck
16              
17             Finds the relative time delay between two feed segments.
18              
19             Accomplished by shifting one feed relative to the other and then computing the error (absolute difference).
20              
21             The shift that yields the lowest error corresponds to the relative delay between he two input feeds.
22              
23             The output consists of the delay found, and the error in delayed point.
24              
25             =cut
26              
27             our $VERSION = '0.07';
28              
29             =head1 SYNOPSIS
30              
31             use Feed::PhaseCheck qw(compare_feeds);
32             my $sample = {
33             "1451276654" => "1.097655",
34             "1451276655" => "1.09765",
35             #...
36             "1451276763" => "1.0976",
37             "1451276764" => "1.097595"
38             };
39             my $compare_to = {
40             "1451276629" => "1.09765",
41             "1451276630" => "1.09764916666667",
42             #...
43             "1451276791" => "1.097595",
44             "1451276792" => "1.097595"
45             };
46             my $max_delay_check = 30; # seconds
47             my ($errors,$delay_with_min_err) = compare_feeds($sample,$compare_to,$max_delay_check);
48              
49             =cut
50              
51             =head1 METHODS
52              
53             =head2 compare_feeds
54              
55             =cut
56              
57             sub compare_feeds {
58 1     1 1 262 my $sample = shift;
59 1         2 my $main_data = shift;
60 1   50     4 my $max_delay_check = shift || 0;
61              
62 1 50       9 if ($max_delay_check !~ /^\d+$/) {
63 0         0 return;
64             }
65              
66 1 50 33     11 if (ref $sample ne 'HASH' || scalar keys %$sample < 2) {
67 0         0 return;
68             }
69              
70 1 50 33     18 if (ref $main_data ne 'HASH' || scalar keys %$main_data < 2) {
71 0         0 return;
72             }
73              
74 1         82 my @main_epoches = sort keys %$main_data;
75 1         9 foreach (@main_epoches) {
76 164 50 33     538 if (int($_) != $_ || abs($main_data->{$_}) != $main_data->{$_}) {
77 0         0 return;
78             }
79             }
80              
81 1         21 my @sample_epoches = sort keys %$sample;
82 1         7 foreach (@sample_epoches) {
83 26 50 33     88 if (int($_) != $_ || abs($sample->{$_}) != $sample->{$_}) {
84 0         0 return;
85             }
86             }
87              
88 1 50 33     6 if ($sample_epoches[0] < $main_epoches[0] || $sample_epoches[-1] > $main_epoches[-1]) {
89 0         0 return;
90             }
91 1         82 my %main_data = %$main_data;
92 1         9 my %error = ();
93 1         2 my ($min_error, $delay_for_min_error);
94 1 50       6 my $delay1 = $sample_epoches[0] - $main_epoches[0] < $max_delay_check ? $sample_epoches[0] - $main_epoches[0] : $max_delay_check;
95 1 50       12 my $delay2 = $main_epoches[-1] - $sample_epoches[-1] < $max_delay_check ? $main_epoches[-1] - $sample_epoches[-1] : $max_delay_check;
96 1         5 for (my $delay = -$delay1; $delay <= $delay2; $delay++) {
97 54         85 $error{$delay} = 0;
98 54         80 foreach my $epoch (@sample_epoches) {
99 1404         1826 my $sample_epoch = $epoch + $delay;
100 1404 50       2393 if (!defined $main_data{$sample_epoch}) {
101 0         0 for (my $i = 1; $i < scalar keys @main_epoches; $i++) {
102 0 0       0 if ($main_epoches[$i] > $sample_epoch) {
103             $main_data{$sample_epoch} = _interpolate(
104             $main_epoches[$i - 1],
105             $main_data{$main_epoches[$i - 1]},
106 0         0 $main_epoches[$i], $main_data{$main_epoches[$i]},
107             $sample_epoch
108             );
109 0         0 last;
110             }
111             }
112             }
113 1404         2448 $error{$delay} += ($main_data{$sample_epoch} - $sample->{$epoch})**2;
114             }
115 54 100 100     160 if (!defined $min_error || $error{$delay} < $min_error) {
116 25         43 $min_error = $error{$delay};
117 25         44 $delay_for_min_error = $delay;
118             }
119             # $error{$delay} =~ s/(\d{8}).+?e/$1e/;
120             }
121              
122 1         24 return (\%error, $delay_for_min_error);
123             }
124              
125             sub _interpolate {
126 0     0     my ($x1, $y1, $x2, $y2, $x) = @_;
127 0           my $y = $y1 + ($x - $x1) * ($y2 - $y1) / ($x2 - $x1);
128 0           return $y;
129             }
130              
131             =head1 AUTHOR
132              
133             Maksym Kotielnikov, C<< >>
134              
135             =head1 BUGS
136              
137             Please report any bugs or feature requests to C, or through
138             the web interface at L. I will be notified, and then you'll
139             automatically be notified of progress on your bug as I make changes.
140              
141              
142              
143              
144             =head1 SUPPORT
145              
146             You can find documentation for this module with the perldoc command.
147              
148             perldoc Feed::PhaseCheck
149              
150              
151             You can also look for information at:
152              
153             =over 4
154              
155             =item * RT: CPAN's request tracker (report bugs here)
156              
157             L
158              
159             =item * AnnoCPAN: Annotated CPAN documentation
160              
161             L
162              
163             =item * CPAN Ratings
164              
165             L
166              
167             =item * Search CPAN
168              
169             L
170              
171             =back
172              
173              
174             =head1 ACKNOWLEDGEMENTS
175              
176              
177              
178             =cut
179              
180             1; # End of Feed::PhaseCheck