2013-02-21 09:21:42 -08:00
package DDG::Goodie::FedEx ;
2014-08-20 11:45:33 -07:00
# ABSTRACT: Track a package through FedEx
2013-02-21 09:21:42 -08:00
2015-02-22 12:09:29 -08:00
use strict ;
2013-02-21 09:21:42 -08:00
use DDG::Goodie ;
zci is_cached = > 1 ;
zci answer_type = > "fedex" ;
2013-02-21 09:35:37 -08:00
# Regex for fedex.
my $ fedex_qr = qr/fed(?:eral|)ex(?:press|)/ io ;
my $ tracking_qr = qr/package|track(?:ing|)|num(?:ber|)|\#/ i ;
triggers query_nowhitespace_nodash = > qr /
2014-02-17 18:22:23 -08:00
^ $ fedex_qr . * ? ( ? <the_number> [ \ d ] { 9 , } ) $|
^ ( ? <the_number> [ \ d ] { 9 , } ) . * ? $ fedex_qr $|
2014-05-11 07:08:20 -07:00
^ ( ? : $ tracking_qr | $ fedex_qr | ) * ? ( ? <extra_numbers> \ d * ? ) ( ? <to_checksum> [ \ d ] { 15 } ) ( ? : $ tracking_qr | $ fedex_qr | ) * $|
2014-02-17 18:22:23 -08:00
^ ( ? : $ tracking_qr | $ fedex_qr | ) * ? ( ? <extra_numbers> \ d * ? ) ( ? <to_checksum> [ \ d ] { 12 } ) ( ? : $ tracking_qr | $ fedex_qr | ) * $
2013-02-21 09:35:37 -08:00
/ xio ;
2013-02-21 09:21:42 -08:00
2013-02-21 10:43:13 -08:00
# Fedex package tracking.
2014-05-11 07:37:42 -07:00
#
2015-04-22 10:34:44 -07:00
# For detailed specification:
# http://images.fedex.com/us/solutions/ppe/FedEx_Ground_Label_Layout_Specification.pdf
#
2014-05-11 07:37:42 -07:00
# For brief description see:
# http://answers.google.com/answers/main?cmd=threadview&id=207899
#
2013-02-21 09:21:42 -08:00
handle query_nowhitespace_nodash = > sub {
2013-02-21 09:35:37 -08:00
# If a Fedex package number (2 for exclusively).
my $ is_fedex = 0 ;
# Tracking number.
my $ package_number = '' ;
2014-02-17 18:22:23 -08:00
# Exclusive trigger.
if ( $+ { the_number } ) {
$ package_number = $+ { the_number } ;
2013-02-21 09:35:37 -08:00
$ is_fedex = 2 ;
# No exclusive trigger, do checksum.
# Since the package numbers are just numbers,
# we are more strict in regex (e.g. than UPS).
# 15 has to be before 12 or it will block.
}
2014-02-17 18:22:23 -08:00
elsif ( $+ { to_checksum } ) {
2014-02-18 09:22:17 -08:00
my $ package_beg = $+ { extra_numbers } ;
2014-02-17 18:22:23 -08:00
$ package_number = $+ { to_checksum } ;
2013-02-21 09:35:37 -08:00
my $ checksum = - 1 ;
my @ chars = split ( // , $ package_number ) ;
my $ length = scalar ( @ chars ) ;
my $ char_count = 0 ;
my $ sum = 0 ;
# Ground.
if ( $ length == 15 ) {
my $ odd_sum = 0 ;
my $ even_sum = 0 ;
foreach my $ char ( reverse @ chars ) {
$ char_count + + ;
# Skip check digit.
next if $ char_count == 1 ;
if ( $ char_count % 2 == 0 ) {
$ even_sum += $ char ;
}
else {
$ odd_sum += $ char ;
}
}
$ even_sum *= 3 ;
if ( ( $ odd_sum + $ even_sum ) > 0 ) {
$ checksum = ( $ odd_sum + $ even_sum ) % 10 ;
$ checksum = 10 - $ checksum if $ checksum ;
}
}
else {
foreach my $ char ( @ chars ) {
if ( $ char_count % 3 == 0 ) {
$ sum += $ char * 3 ;
}
elsif ( $ char_count % 3 == 1 ) {
$ sum += $ char * 1 ;
}
else {
$ sum += $ char * 7 ;
}
$ char_count + + ;
last if $ char_count == 11 ;
}
$ checksum = ( $ sum % 11 ) % 10 if $ sum ;
}
2013-02-21 10:43:13 -08:00
if ( ( $ length == 15 && $ checksum eq $ chars [ - 1 ] ) || ( $ length != 15 && $ checksum eq $ chars [ 11 ] ) ) {
2013-02-21 09:35:37 -08:00
$ is_fedex = 1 ;
$ package_number = qq( $package_beg$package_number ) if $ package_beg ;
}
}
if ( $ is_fedex ) {
2015-07-08 12:12:43 -07:00
return $ package_number , heading = > 'FedEx Shipment Tracking' , html = > qq( Track this shipment at <a href="https://www.fedex.com/apps/fedextrack/?tracknumbers=$package_number&action=track">FedEx</a>. ) ;
2013-02-21 09:35:37 -08:00
}
2013-02-21 09:21:42 -08:00
return ;
} ;
2014-02-17 18:22:23 -08:00
1 ;