Skip to content

Instantly share code, notes, and snippets.

@wchristian
Created November 25, 2010 17:27
Show Gist options
  • Save wchristian/715670 to your computer and use it in GitHub Desktop.
Save wchristian/715670 to your computer and use it in GitHub Desktop.
use strict;
use warnings;
package TFX::Flight::Conex;
use Moose;
use MooseX::HasDefaults::RO;
use List::Util qw( min reduce );
use lib '../..';
use TFX::Flight::Conex::LegAccessors;
use TFX::Flight::Conex::Leg;
extends 'TFX::Flight';
has [qw( itinerary half_return )] => ( isa => 'HashRef', required => 1 );
has [qw(
operator flight_type flight_sequence min_advance_days flight_tariff flight_kind seat_count special_code
price_two_way direction rate1_type rate1_min_age rate1_max_age rate1_price rate2_type rate2_min_age
rate2_max_age rate2_price rate3_type rate3_min_age rate3_max_age rate3_price
)] => ( isa => 'Any' );
has legs => ( isa => 'ArrayRef', lazy_build => 1 );
sub _build_table_name { "OWF" }
sub _build_data_type { "F" }
sub _build_version { "3.0" }
sub _build_via_codes {
my ( $self ) = @_;
my ( undef, @additional_legs ) = @{$self->legs};
return if !@additional_legs;
my @via_codes = map { $_->depart_code } @additional_legs;
return join ',', @via_codes;
}
sub _build_currency { $_[0]->price->{currencyIsoCode} }
sub _build_price_one_way { $_[0]->price->{value} }
sub _build_combination_id { $_[0]->air_rule_set->{openJawCombinationGroup}{name} }
sub _build_season_surcharge {
my ( $self ) = @_;
my $tax_list = $self->half_return->{taxQuoteList}[0]{taxList};
my @taxes = values %{$tax_list};
no warnings 'once';
return reduce { $a + $b->{price}{value} } 0, @taxes;
}
sub _build_duration_rules {
my ( $self ) = @_;
my @rules = map $self->convert_duration( $_ ), qw( minimumStay maximumStay );
my $sunday_rule = $self->air_rule_set->{minimumStay}{sundayRule};
push @rules, 'SUN' if $sunday_rule and $sunday_rule eq 'true';
return join ',', @rules;
}
sub _build_flight_class {
my ( $self ) = @_;
my $class_id = $self->air_rule_set->{cabinClass}{id};
my %classes = (
CAB_ECONOMY => 'Y',
CAB_BUSINESS => 'C',
);
return $classes{$class_id} || die "Unknown class id: $class_id";
}
# helpers
sub _build_legs {
my ( $self ) = @_;
my @legs = @{ $self->itinerary->{segmentList} };
@legs = map TFX::Flight::Conex::Leg->new( raw => $_ ), @legs;
return \@legs;
}
sub leg { $_[0]->legs->[$_[1]] || TFX::Flight::Conex::Leg->new( raw => {} ) }
sub air_rule_set { $_[0]->half_return->{airRuleSet} }
sub price { $_[0]->half_return->{farePassengerTypePriceList}[0]{purchasePrice} }
sub convert_duration {
my ( $self, $type ) = @_;
my $duration = $self->air_rule_set->{$type};
die "duration type missing: '$type'" if !$duration;
my $prefix = $self->get_duration_rule_prefix( $type );
$duration->{value} = min( $duration->{value}, 99 );
return $prefix . "99" if $duration->{value} > 3 and $duration->{unit}{id} eq 'STU_MONTHS';
return $prefix . "99" if $duration->{value} >= 1 and $duration->{unit}{id} eq 'STU_YEARS';
return sprintf( "%s%02d", $prefix, $duration->{value} ) if $duration->{unit}{id} eq 'STU_DAYS';
return sprintf( "%s%02d", $prefix, $duration->{value} * 30 ) if $duration->{unit}{id} eq 'STU_MONTHS';
die "unknown duration unit id '$duration->{unit}{id}' with value '$duration->{value}'";
}
sub get_duration_rule_prefix {
my ( $self, $type ) = @_;
return 'A' if $type eq 'minimumStay';
return 'B' if $type eq 'maximumStay';
die "unknown duration type";
}
1;
use strict;
use warnings;
package TFX::Flight;
use Moose;
use MooseX::HasDefaults::RO;
use Class::Load 'load_class';
use lib '..';
use TFX::Sealtix;
has [ TFX::Sealtix->get_fields ] => ( isa => 'Any', lazy_build => 1 );
sub build {
my ( $class, %args ) = @_;
my $source = delete $args{source};
my $engine = "$class\::$source";
load_class( $engine );
return $engine->new( $args{data} );
}
sub as_hash {
my ( $self ) = @_;
my @fields = $self->hash_fields;
my %hash = map $self->_get_field_value($_), @fields;
return \%hash;
}
sub hash_fields {
my ( $self ) = @_;
my @fields = TFX::Sealtix->get_fields;
# trim multi leg flight fields if it's a single leg flight
@fields = grep { !/^leg\d_/ } @fields if @{ $self->legs } < 2;
# trim certain flight fields if it's a multi leg flight
@fields = grep { $_ ne 'flight_carrier' and $_ ne 'flight_number' } @fields if @{ $self->legs } > 1;
return @fields;
}
sub _get_field_value {
my ( $self, $field ) = @_;
return ( $field => $self->$field ) if defined $self->$field;
return;
}
1;
use strict;
use warnings;
package TFX::Flight::Conex::Leg;
use Moose;
has raw => ( isa => 'HashRef', is => 'ro' );
sub flight_carrier { $_[0]->raw->{operatingAirline}{code} }
sub flight_number { $_[0]->raw->{flightNumber} }
sub depart_code { $_[0]->raw->{departure}{code} }
sub arrive_code { $_[0]->raw->{destination}{code} }
sub depart_date { $_[0]->regex_filter( 'departureDate' ) }
sub depart_time { $_[0]->regex_filter( 'departureTimestamp' ) }
sub arrive_time { $_[0]->regex_filter( 'arrivalTimestamp' ) }
sub regex_filter {
my ( $self, $key ) = @_;
my $value = $self->raw->{$key};
return if !$value;
$value =~ s/^.*T(\d+):(\d+):.*$/$1$2/ if grep { $_ eq $key } qw( departureTimestamp arrivalTimestamp );
$value =~ s:(\d+)-(\d+)-(\d+):$3.$2.$1: if grep { $_ eq $key } qw( departureDate );
return $value;
}
1;
use strict;
use warnings;
package TFX::Flight::Conex::LegAccessors;
# ABSTRACT: generate and export 21 attribute accessor subs so we don't need to copy-paste
use Sub::Exporter -setup => { groups => { default => \'_build_leg_accessors' } };
use Sub::Curry 'curry';
sub _build_leg_accessors {
my @legs = qw( 1 2 3 );
my %main_subs = map build_main_accessors( @{$_} ), main_sub_data();
my %leg_subs = map build_accessors_per_leg($_), @legs;
return { %main_subs, %leg_subs };
}
sub main_sub_data {
return (
[ 0, 'flight_carrier' ],
[ 0, 'flight_number' ],
[ 0, 'depart_code' ],
[ -1, 'arrive_code' ],
[ 0, 'depart_date' ],
[ 0, 'depart_time' ],
[ -1, 'arrive_time' ],
);
}
sub build_main_accessors {
my ( $id, $field ) = @_;
return "_build_$field" => curry( \&accessor_base, $field, $id );
}
sub build_accessors_per_leg {
my ( $leg ) = @_;
my @fields = qw( flight_carrier flight_number depart_code arrive_code depart_date depart_time arrive_time );
return map build_accessors_per_field( $leg, $_ ), @fields;
}
sub build_accessors_per_field {
my ( $leg, $field ) = @_;
my $sub = "leg$leg\_$field";
my $id = $leg - 1;
my $accessor = curry( \&accessor_base, $field, $id );
return $sub => $accessor;
}
sub accessor_base {
my ( $field, $id, $self ) = @_;
my $value = $self->leg( $id )->$field;
return $value;
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment