| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package WebService::Nextbus::Agency; | 
| 2 | 1 |  |  | 1 |  | 21700 | use 5.006; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 38 |  | 
| 3 | 1 |  |  | 1 |  | 6 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 37 |  | 
| 4 | 1 |  |  | 1 |  | 6 | use warnings; | 
|  | 1 |  |  |  |  | 6 |  | 
|  | 1 |  |  |  |  | 27 |  | 
| 5 | 1 |  |  | 1 |  | 896 | use integer; | 
|  | 1 |  |  |  |  | 10 |  | 
|  | 1 |  |  |  |  | 4 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | our $VERSION = '0.12'; | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | sub new { | 
| 10 | 2 |  |  | 2 | 0 | 11 | my $proto = shift; | 
| 11 | 2 |  | 33 |  |  | 10 | my $class = ref($proto) || $proto; | 
| 12 |  |  |  |  |  |  |  | 
| 13 | 2 |  |  |  |  | 10 | my $self = { | 
| 14 |  |  |  |  |  |  | _nameCode		=> undef, | 
| 15 |  |  |  |  |  |  | _routeRegExp	=> undef, | 
| 16 |  |  |  |  |  |  | _dirRegExp		=> undef, | 
| 17 |  |  |  |  |  |  | _routes		=> {}, | 
| 18 |  |  |  |  |  |  | }; | 
| 19 | 2 |  |  |  |  | 9 | bless ($self, $class); | 
| 20 |  |  |  |  |  |  | } | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | # Input or check the name code for this agency, e.g. sf-muni | 
| 23 |  |  |  |  |  |  | sub nameCode { | 
| 24 | 2 |  |  | 2 | 0 | 638 | my $self = shift; | 
| 25 | 2 | 100 |  |  |  | 9 | if (@_) { $self->{_nameCode} = shift } | 
|  | 1 |  |  |  |  | 7 |  | 
| 26 | 2 |  |  |  |  | 10 | return $self->{_nameCode}; | 
| 27 |  |  |  |  |  |  | } | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | # Input or check the RegExps used for default parsing | 
| 30 |  |  |  |  |  |  | sub routeRegExp { | 
| 31 | 1 |  |  | 1 | 0 | 2 | my $self = shift; | 
| 32 | 1 | 50 |  |  |  | 4 | if (@_) { $self->{_routeRegExp} = shift } | 
|  | 1 |  |  |  |  | 3 |  | 
| 33 | 1 |  |  |  |  | 3 | return $self->{_routeRegExp}; | 
| 34 |  |  |  |  |  |  | } | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | sub dirRegExp { | 
| 37 | 1 |  |  | 1 | 0 | 2 | my $self = shift; | 
| 38 | 1 | 50 |  |  |  | 3 | if (@_) { $self->{_dirRegExp} = shift } | 
|  | 1 |  |  |  |  | 3 |  | 
| 39 | 1 |  |  |  |  | 2 | return $self->{_dirRegExp}; | 
| 40 |  |  |  |  |  |  | } | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | # For building or checking the tree structure of routes, dirs, stops | 
| 43 |  |  |  |  |  |  | sub routes { | 
| 44 | 5 |  |  | 5 | 0 | 727 | my $self = shift; | 
| 45 | 5 | 100 |  |  |  | 11 | if (@_) { %{$self->{_routes}} = %{$_[0]} } | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 5 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 46 | 5 |  |  |  |  | 6 | return \%{$self->{_routes}}; | 
|  | 5 |  |  |  |  | 47 |  | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | sub dirs { | 
| 50 | 4 |  |  | 4 | 0 | 5 | my $self = shift; | 
| 51 | 4 |  |  |  |  | 4 | my ($route, $newDirs) = @_; | 
| 52 | 4 | 50 |  |  |  | 8 | if ($newDirs) { %{$self->routes()->{$route}} = %$newDirs } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 53 | 4 |  |  |  |  | 3 | return \%{$self->routes()->{$route}}; | 
|  | 4 |  |  |  |  | 9 |  | 
| 54 |  |  |  |  |  |  | } | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | sub stops { | 
| 57 | 4 |  |  | 4 | 0 | 5 | my $self = shift; | 
| 58 | 4 |  |  |  |  | 4 | my ($route, $dir, $newStops) = @_; | 
| 59 | 4 | 50 |  |  |  | 10 | if ($newStops) { %{$self->dirs($route)->{$dir}} = %$newStops } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 60 | 4 |  |  |  |  | 4 | return \%{$self->dirs($route)->{$dir}}; | 
|  | 4 |  |  |  |  | 11 |  | 
| 61 |  |  |  |  |  |  | } | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | # Input or check a particular stop code given the route, dir, and name of stop. | 
| 64 |  |  |  |  |  |  | sub stopCode { | 
| 65 | 2 |  |  | 2 | 0 | 3 | my $self = shift; | 
| 66 | 2 |  |  |  |  | 5 | my ($route, $dir, $stopName, $newCode) = @_; | 
| 67 | 2 | 50 |  |  |  | 20 | if ($newCode) { $self->stops($route, $dir)->{$stopName} = $newCode } | 
|  | 0 |  |  |  |  | 0 |  | 
| 68 | 2 |  |  |  |  | 9 | return $self->stops($route, $dir)->{$stopName}; | 
| 69 |  |  |  |  |  |  | } | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | # Spit out the stop names (keys) or codes (values) | 
| 72 |  |  |  |  |  |  | sub allStopNames { | 
| 73 | 1 |  |  | 1 | 0 | 2 | my $self = shift; | 
| 74 | 1 |  |  |  |  | 2 | my ($route, $dir) = @_; | 
| 75 | 1 |  |  |  |  | 1 | return keys(%{$self->stops($route, $dir)}); | 
|  | 1 |  |  |  |  | 2 |  | 
| 76 |  |  |  |  |  |  | } | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | sub allStopCodes { | 
| 79 | 1 |  |  | 1 | 0 | 1 | my $self = shift; | 
| 80 | 1 |  |  |  |  | 2 | my ($route, $dir) = @_; | 
| 81 | 1 |  |  |  |  | 1 | return values(%{$self->stops($route, $dir)}); | 
|  | 1 |  |  |  |  | 3 |  | 
| 82 |  |  |  |  |  |  | } | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | # Default parsing of input string according to object's stored RegExps | 
| 85 |  |  |  |  |  |  | sub parseRoute { | 
| 86 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 87 | 0 |  |  |  |  | 0 | my ($str) = @_; | 
| 88 | 0 |  |  |  |  | 0 | my $routeRegExp = $self->routeRegExp(); | 
| 89 | 0 |  |  |  |  | 0 | my ($route) = ($str =~ /$routeRegExp/i); | 
| 90 |  |  |  |  |  |  |  | 
| 91 | 0 |  |  |  |  | 0 | $str =~ s/$route\s*//; | 
| 92 | 0 |  |  |  |  | 0 | return (ucfirst($route), $str); | 
| 93 |  |  |  |  |  |  | } | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | sub parseDir { | 
| 96 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 97 | 0 |  |  |  |  | 0 | my ($str) = @_; | 
| 98 | 0 |  |  |  |  | 0 | my $dirRegExp = $self->dirRegExp(); | 
| 99 | 0 |  |  |  |  | 0 | my ($dir) = ($str =~ /$dirRegExp/i); | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 0 |  |  |  |  | 0 | $str =~ s/$dir\s*//; | 
| 102 | 0 |  |  |  |  | 0 | return ($dir, $str); | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | # Search for stop codes in current tree.  First, check whether the input string | 
| 106 |  |  |  |  |  |  | # directly matches a stop code.  Otherwise, assume the input string is a stop | 
| 107 |  |  |  |  |  |  | # name and search the names for a match.  The matching is done word by word: | 
| 108 |  |  |  |  |  |  | # first split the input at whitespaces, then match each word in turn, narrowing | 
| 109 |  |  |  |  |  |  | # the list of stopnames at each step (but if the word makes no matches, then | 
| 110 |  |  |  |  |  |  | # leave the list alone).  At the end, return all remaining matches. | 
| 111 |  |  |  |  |  |  | sub str2stopCodes { | 
| 112 | 1 |  |  | 1 | 0 | 2 | my $self = shift; | 
| 113 | 1 |  |  |  |  | 2 | my ($route, $dir, $stopStr) = @_; | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 1 |  |  |  |  | 8 | my @stopCodes = $self->allStopCodes($route, $dir); | 
| 116 | 1 | 50 |  |  |  | 26 | if ((my @retCodes = grep(/$stopStr/i, @stopCodes)) == 1) { | 
| 117 | 0 |  |  |  |  | 0 | return @retCodes; | 
| 118 |  |  |  |  |  |  | } | 
| 119 |  |  |  |  |  |  |  | 
| 120 | 1 |  |  |  |  | 6 | my @stopNames = $self->allStopNames($route, $dir); | 
| 121 | 1 |  |  |  |  | 5 | foreach my $word (split(/\s+/, $stopStr)) { | 
| 122 | 2 | 50 |  |  |  | 39 | if (my @temp = grep(/$word/i, @stopNames)) { | 
| 123 | 2 |  |  |  |  | 8 | @stopNames = @temp; | 
| 124 |  |  |  |  |  |  | } | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  |  | 
| 127 | 1 |  |  |  |  | 2 | my @retCodes; | 
| 128 | 1 |  |  |  |  | 2 | foreach my $stopName (@stopNames) { | 
| 129 | 1 |  |  |  |  | 3 | my $retCode = $self->stopCode($route, $dir, $stopName); | 
| 130 | 1 |  |  |  |  | 4 | push(@retCodes, $retCode); | 
| 131 |  |  |  |  |  |  | } | 
| 132 | 1 |  |  |  |  | 6 | return @retCodes; | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | # To dump the routes tree in human readable format.  Essentially the same as | 
| 136 |  |  |  |  |  |  | # Data::Dumper in case you don't want to load that library. | 
| 137 |  |  |  |  |  |  | sub routesAsString { | 
| 138 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 0 |  |  |  |  |  | foreach my $routeKey (keys(%{$self->routes()})) { | 
|  | 0 |  |  |  |  |  |  | 
| 141 | 0 |  |  |  |  |  | print "$routeKey =>\n"; | 
| 142 | 0 |  |  |  |  |  | my $routeVal = $self->routes()->{$routeKey}; | 
| 143 | 0 |  |  |  |  |  | foreach my $dirKey (keys(%$routeVal)) { | 
| 144 | 0 |  |  |  |  |  | print "	$dirKey =>\n"; | 
| 145 | 0 |  |  |  |  |  | my $dirVal = $routeVal->{$dirKey}; | 
| 146 | 0 |  |  |  |  |  | foreach my $stopKey (keys(%$dirVal)) { | 
| 147 | 0 |  |  |  |  |  | print "		$stopKey => "; | 
| 148 | 0 |  |  |  |  |  | my $stopVal = $dirVal->{$stopKey}; | 
| 149 | 0 |  |  |  |  |  | print $stopVal . "\n"; | 
| 150 |  |  |  |  |  |  | } | 
| 151 |  |  |  |  |  |  | } | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | 1 | 
| 156 |  |  |  |  |  |  | __END__ |