# Station.pm - WWW::Velib::Station
#
# Copyright (c) 2007 David Landgren
# All rights reserved
package WWW::Velib::Station;
use strict;
use LWP::Simple;
use Math::Trig qw(deg2rad great_circle_distance);
use XML::Twig;
use vars '$VERSION';
$VERSION = '0.01';
use constant DETAILS => 'http://www.velib.paris.fr/service/stationdetails/';
sub new {
my $class = shift;
my $self = bless {number => shift}, $class;
$self->refresh;
return $self;
}
sub make {
my $class = shift;
my $self = {};
@{$self}{qw(number name address fullAddress lat lng open)} = @_;
@{$self}{qw(theta phi)} = _theta_phi(@{$self}{qw(lat lng)});
return bless $self, $class;
}
sub _theta_phi { deg2rad($_[0]), deg2rad(90 - $_[1]) }
sub load_v1 {
my $class = shift;
my $self = {};
@{$self}{qw(number open lat lng theta phi name address fullAddress)} = @_;
return bless $self, $class;
}
sub coords {
my $self = shift;
return @{$self}{qw(theta phi)};
}
sub distance_from {
my $self = shift;
my $there = shift;
my $scale = shift || 5;
$self->{dist} = $scale * sprintf( '%0.0f',
great_circle_distance( $there->coords, $self->coords, 6378249)
/ $scale);
return $self->{dist};
}
sub refresh {
my $self = shift;
if (my $content = get(DETAILS . $self->number)) {
$self->{_html} = $content;
my $twig = XML::Twig->new(
twig_handlers => {
available => sub {$self->{available} = $_[1]->text},
free => sub {$self->{free } = $_[1]->text},
total => sub {$self->{total } = $_[1]->text},
ticket => sub {$self->{ticket } = $_[1]->text},
},
);
$twig->parse($content);
}
else {
@{$self}{qw(available free total ticket)} = (-1) x 4;
};
return $self;
}
sub number {return $_[0]->{number }}
sub open {return $_[0]->{open }}
sub name {return $_[0]->{name }}
sub latitude {return $_[0]->{lat }}
sub longitude {return $_[0]->{lng }}
sub address {return $_[0]->{address }}
sub full_address {return $_[0]->{fullAddress}}
sub available {return $_[0]->{available }}
sub free {return $_[0]->{free }}
sub total {return $_[0]->{total }}
sub disabled {
return $_[0]->total == -1
? -1
: $_[0]->total - ($_[0]->free + $_[0]->available)
;
}
'The Lusty Decadent Delights of Imperial Pompeii';
__END__
=head1 NAME
WWW::Velib::Station - Details of Velib' station bicycle and parking availability
=head1 VERSION
This document describes version 0.01 of WWW::Velib::Station, released
2007-11-13.
=head1 SYNOPSIS
use WWW::Velib::Station;
my $s = WWW::Velib::Station->new(2007);
print $s->available, $/; # hopefully a positive number
=head1 DESCRIPTION
=head1 METHODS
=over 4
=item new
Create a WWW::Velib::Station object. A single input parameter
is given, representing the station number.
=item make
Create a WWW::Velib::Station object, based on the geographic
information provided by WWW::Velib::Map. Not expected to be called
from client code.
=item load_v1
Create a WWW::Velib::Station object, based on locally-cached contents
of the geographic information provided by WWW::Velib::Map. Not
expected to be called from client code.
=item coords
Returns a two-element list containing the theta and phi coordinates
of the station.
=item distance_from
Returns the distance in metres of a station from the current station.
The result is rounded by default to the nearest 5 metres.
my $depart; # two WWW::Velib::Station objects
my $arrive;
my $distance = $depart->distance_from($arrive);
To round off to another interval, specify the rounding as a second
parameter:
my $dist_km = $depart->distance_from($arrive, 1000);
=item number
Returns the number (indentifier) of the station.
=item open
Indicates whether the station is open for business or not.
=item name
Returns the name of the station.
=item latitude
Returns the station's latitude, in degrees.
=item longitude
Returns the station's longitude, in degrees.
=item address
Returns the short address of the station.
=item full_address
Returns the full address of the station.
=item refresh
If a station has been built by loading a map, the following details
will not be loaded (it takes time to fetch a couple of thousand web
pages). This method will fetch the current status of the station
(bikes available, slots available). On a long-running process, may
be called repeatedly (at a suitable interval) to update the status.
=item available
Returns the number of bicycles available at the specified station.
=item total
Returns the total number of bicycle posts installed at the station.
=item free
Returns the number of bicycle posts that are able to receive a
bicycle.
=item disabled
Returns the number of bicycle posts that are locked or have a
locked bicycle attached.
=back
=head1 AUTHOR
David Landgren, copyright (C) 2007. All rights reserved.
http://www.landgren.net/perl/
If you (find a) use this module, I'd love to hear about it. If you
want to be informed of updates, send me a note. You know my first
name, you know my domain. Can you guess my e-mail address?
=head1 LICENSE
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.