diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Block.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Block.pm new file mode 100644 index 0000000..c2683d8 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Block.pm @@ -0,0 +1,42 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Block; +use strict; + +## no critic + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( + +); + +sub new { + + my $class = shift; + my $self = bless {}, $class; + my %params = @_; + ( + $self->{name}, + ) = @params{qw/ + name + /}; + + return $self; + +} + +sub print { + my $self = shift; + + +} + +sub get_block_descriptor_word { + my $self = shift; + #return total length in bytes (up to 256*256 bytes) +} + +sub pad { + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Field.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Field.pm new file mode 100644 index 0000000..dc044b2 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Field.pm @@ -0,0 +1,87 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Field; +use strict; + +## no critic + +use NGCP::BulkProcessor::LogError qw( + notimplementederror +); + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( + $TERMINATOR +); + +our $TERMINATOR = 'c'; + +sub new { + + my $base_class = shift; + my $class = shift; + my $self = bless {}, $class; + my %params = @_; + ( + $self->{name}, + $self->{length}, + $self->{instance}, + ) = @params{qw/ + name + length + instance + /}; + $self->_set_params(@_); + + return $self; + +} + +sub _get_params { + my $self = shift; + my %params = @_; + my @vals = (); + foreach my $param_name ($self->_get_param_names()) { + push(@vals,$params{$param_name} // $self->{$param_name}); + } + return @vals; +} + +sub _set_params { + my $self = shift; + my %params = @_; + foreach my $param_name ($self->_get_param_names()) { + $self->{$param_name} = $params{$param_name}; + } +} + +sub get_name { + my $self = shift; + return $self->{name}; +} + +sub get_hex { + + my $self = shift; + my (@params) = @_; + + notimplementederror((ref $self) . ': ' . (caller(0))[3] . ' not implemented',getlogger(__PACKAGE__)); + return undef; + +} + +sub _get_param_names { + + my $self = shift; + + notimplementederror((ref $self) . ': ' . (caller(0))[3] . ' not implemented',getlogger(__PACKAGE__)); + return undef; + +} + +sub get_length { + my $self = shift; + return $self->{length} if defined $self->{length}; + return length($self->get_hex(@_)); +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/FieldSet.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/FieldSet.pm new file mode 100644 index 0000000..e95cc9c --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/FieldSet.pm @@ -0,0 +1,87 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::FieldSet; +use strict; + +## no critic + +use NGCP::BulkProcessor::LogError qw( + notimplementederror +); + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( + +); + +my $field_separator = ": "; +my $line_terminator = "\n"; +my $padding = ' '; + +sub new { + + my $base_class = shift; + my $class = shift; + my $self = bless {}, $class; + my %params = @_; + ( + $self->{length}, + ) = @params{qw/ + length + /}; + $self->{fields} = []; + + return $self; + +} + +sub _add_field { + my $self = shift; + push(@{$self->{fields}},@_); +} + +sub get_name { + my $self = shift; + #my (@params) = @_; + + notimplementederror((ref $self) . ': ' . (caller(0))[3] . ' not implemented',getlogger(__PACKAGE__)); + return undef; +} + +sub get_hex { + + my $self = shift; + my $result = ''; + foreach my $field (@{$self->{fields}}) { + $result .= $field->get_hex(@_); + } + return $result; +} + +sub get_length { + my $self = shift; + return $self->{length} if defined $self->{length}; + my $length = 0; + foreach my $field (@{$self->{fields}}) { + $length += $field->get_length(@_); + } + return $length; +} + +sub to_string { + + my $self = shift; + my @lines = (); + my $maxlen = 0; + if (length($padding) > 0) { + foreach my $field (@{$self->{fields}}) { + $maxlen = length($field->get_name()) if $maxlen < length($field->get_name()); + } + } + foreach my $field (@{$self->{fields}}) { + push(@lines,uc($field->get_name()) . $field_separator . ($maxlen > 0 ? ($padding x ($maxlen - length($field->get_name()))) : '') . uc($field->get_hex(@_))); + } + return join($line_terminator,@lines); + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/CallTypeCode.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/CallTypeCode.pm new file mode 100644 index 0000000..eceb8d0 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/CallTypeCode.pm @@ -0,0 +1,64 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CallTypeCode; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + $STATION_PAID + $STATION_SPECIAL_CALLING + $FLAT_RATE + $FREE_CALL + $OPERATING_COMPANY_NUMBER_SERVICE_CALLS + $MDRRAO + $ON_NET_PRIVATE_VIRTUAL_NETWORK + $OFF_NET_PRIVATE_VIRTUAL_NETWORK +); + +my $field_name = "call type code"; +my $length = 4; +my @param_names = qw/call_type_code/; + +our $STATION_PAID = '006'; +our $STATION_SPECIAL_CALLING = '015'; +our $FLAT_RATE = '067'; +our $FREE_CALL = '074'; +our $OPERATING_COMPANY_NUMBER_SERVICE_CALLS = '142'; +our $MDRRAO = '159'; +our $ON_NET_PRIVATE_VIRTUAL_NETWORK = '160'; +our $OFF_NET_PRIVATE_VIRTUAL_NETWORK = '160'; +#800-999 = Generic Record + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($call_type_code) = $self->_get_params(@_); + die("invalid call type code '$call_type_code'") unless length($call_type_code) == 3; + return $call_type_code . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/CalledPartyOffHook.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/CalledPartyOffHook.pm new file mode 100644 index 0000000..3594612 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/CalledPartyOffHook.pm @@ -0,0 +1,50 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CalledPartyOffHook; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "called party off-hook"; +my $length = 2; +my @param_names = qw/unanswered/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{unanswered} //= 0; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($unanswered) = $self->_get_params(@_); + #die("invalid recording office type '$recording_office_type'") unless contains($recording_office_type,[$NOT_USED, $DMS_100_FAMILY]); + return ($unanswered ? '1' : '0') . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ConnectTime.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ConnectTime.pm new file mode 100644 index 0000000..6b1af82 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ConnectTime.pm @@ -0,0 +1,60 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ConnectTime; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Utils qw(zerofill); +#use NGCP::BulkProcessor::Calendar qw(datetime_from_string); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + get_connect_time +); + +my $field_name = "connect time"; +my $length = 8; +my @param_names = qw/connect_time/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{padding} //= 0; + #$self->{sensor_id} = substr($self->{sensor_id},1( if defined $self->{sensor_id}; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($connect_time) = $self->_get_params(@_); + die("invalid connect time '$connect_time'") unless length($connect_time) == 7; + return $connect_time . $TERMINATOR; + +} + +sub get_connect_time { + + my $dt = shift; #datetime_from_string(shift); + return sprintf('%02d',$dt->hour()) . sprintf('%02d',$dt->minute()) . sprintf('%02d',$dt->second()) . + substr(sprintf("%03d",$dt->millisecond // 0),0,1); + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/Date.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/Date.pm new file mode 100644 index 0000000..e294784 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/Date.pm @@ -0,0 +1,59 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::Date; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Utils qw(zerofill); +#use NGCP::BulkProcessor::Calendar qw(datetime_from_string); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + get_ama_date +); + +my $field_name = "date"; +my $length = 6; +my @param_names = qw/date/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{padding} //= 0; + #$self->{sensor_id} = substr($self->{sensor_id},1( if defined $self->{sensor_id}; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($date) = $self->_get_params(@_); + die("invalid date '$date'") unless length($date) == 5; + return $date . $TERMINATOR; + +} + +sub get_ama_date { + + my $dt = shift; #datetime_from_string(shift); + return substr($dt->year(),-1) . sprintf('%02d',$dt->month()) . sprintf('%02d',$dt->day()); + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/DomesticInternational.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/DomesticInternational.pm new file mode 100644 index 0000000..5776638 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/DomesticInternational.pm @@ -0,0 +1,74 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::DomesticInternational; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Settings qw( + $domestic_destination_pattern + $international_destination_pattern +); + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + get_number_domestic_international +); + +my $field_name = "domestic/international indicator"; +my $length = 2; +my @param_names = qw/domestic_international/; + +my @domestic_international_modes = (); +our $DOMESTIC = '1'; +push(@domestic_international_modes,$DOMESTIC); +our $INTERNATIONAL = '2'; +push(@domestic_international_modes,$INTERNATIONAL); +our $UNKNOWN = '9'; +push(@domestic_international_modes,$UNKNOWN); + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($domestic_international) = $self->_get_params(@_); + die("invalid domestic international '$domestic_international'") unless contains($domestic_international,\@domestic_international_modes); + return $domestic_international . $TERMINATOR; + +} + +sub get_number_domestic_international { + my $number = shift; #called number (destination) + if (defined $number) { + if (defined $domestic_destination_pattern and $number =~ $domestic_destination_pattern) { + return $DOMESTIC; + } elsif (defined $international_destination_pattern and $number =~ $international_destination_pattern) { + return $INTERNATIONAL; + } + } + return $UNKNOWN; +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ElapsedTime.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ElapsedTime.pm new file mode 100644 index 0000000..9e130f3 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ElapsedTime.pm @@ -0,0 +1,60 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ElapsedTime; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +use NGCP::BulkProcessor::Utils qw(to_duration_string); +#use NGCP::BulkProcessor::Calendar qw(datetime_from_string); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + get_elapsed_time +); + +my $field_name = "elapsed time"; +my $length = 10; +my @param_names = qw/elapsed_time/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{padding} //= 0; + #$self->{sensor_id} = substr($self->{sensor_id},1( if defined $self->{sensor_id}; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($elapsed_time) = $self->_get_params(@_); + die("invalid elapsed time '$elapsed_time'") unless length($elapsed_time) == 9; + return $elapsed_time . $TERMINATOR; + +} + +sub get_elapsed_time { + + my $duration_secs = shift; + my ($pretty,$years,$months,$days,$hours,$minutes,$seconds) = to_duration_string($duration_secs,'minutes','seconds',3,undef); + return '0' . sprintf('%05d',$minutes) . sprintf('%02d',$seconds) . substr(sprintf("%03d",int(($seconds - int($seconds)) * 1000.0)),0,1); + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/HexId.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/HexId.pm new file mode 100644 index 0000000..bc08c0a --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/HexId.pm @@ -0,0 +1,47 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::HexId; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw(); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "hex id"; +my $length = 2; +my @param_names = qw/is_error/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{is_error} //= 0; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($is_error) = $self->_get_params(@_); + return ($is_error ? 'ab' : 'aa'); + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OperatorAction.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OperatorAction.pm new file mode 100644 index 0000000..e7c1f30 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OperatorAction.pm @@ -0,0 +1,49 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OperatorAction; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "operator action"; +my $length = 2; +my @param_names = (); + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + #my ($unanswered) = $self->_get_params(@_); + #die("invalid recording office type '$recording_office_type'") unless contains($recording_office_type,[$NOT_USED, $DMS_100_FAMILY]); + return '0' . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingChargeInformation.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingChargeInformation.pm new file mode 100644 index 0000000..a27e86c --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingChargeInformation.pm @@ -0,0 +1,53 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingChargeInformation; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "originating charge information"; +my $length = 4; +my @param_names = qw/originating_charge_information/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($originating_charge_information) = $self->_get_params(@_); + if (length($originating_charge_information) > 0) { + die("invalid originating charge information '$originating_charge_information'") unless length($originating_charge_information) == 3; #($originating_charge_information < 0 or $originating_charge_information > 255); + return $originating_charge_information . $TERMINATOR; + } else { + return 'ffff'; + } + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingOpenDigits1.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingOpenDigits1.pm new file mode 100644 index 0000000..8610b8b --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingOpenDigits1.pm @@ -0,0 +1,50 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingOpenDigits1; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "originating open digits 1"; +my $length = 12; +my @param_names = qw/originating_open_digits_1/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{significant_digits} //= 0; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($originating_open_digits_1) = $self->_get_params(@_); + die("invalid originating open digits 1 '$originating_open_digits_1'") unless $originating_open_digits_1 =~ /^\d{1,11}$/; + return sprintf('%011d',$originating_open_digits_1) . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingOpenDigits2.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingOpenDigits2.pm new file mode 100644 index 0000000..5c449f7 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/OriginatingOpenDigits2.pm @@ -0,0 +1,54 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingOpenDigits2; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "originating open digits 2"; +my $length = 10; +my @param_names = qw/originating_open_digits_2/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{significant_digits} //= 0; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($originating_open_digits_2) = $self->_get_params(@_); + if (length($originating_open_digits_2) > 0) { + die("invalid originating open digits 2 '$originating_open_digits_2'") unless $originating_open_digits_2 =~ /^\d{1,9}$/; + return sprintf('%09d',$originating_open_digits_2) . $TERMINATOR; + } else { + return 'ffffffffff'; + } + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/RecordingOfficeId.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/RecordingOfficeId.pm new file mode 100644 index 0000000..17fc372 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/RecordingOfficeId.pm @@ -0,0 +1,51 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::RecordingOfficeId; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Utils qw(zerofill); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "recording office id"; +my $length = 8; +my @param_names = qw/padding recording_office_id/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{padding} //= 0; + #$self->{sensor_id} = substr($self->{sensor_id},1( if defined $self->{sensor_id}; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($padding,$recording_office_id) = $self->_get_params(@_); + die("invalid recording office id '$recording_office_id'") unless length($recording_office_id) == 6; + return ($padding ? '1' : '0') . $recording_office_id . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/RecordingOfficeType.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/RecordingOfficeType.pm new file mode 100644 index 0000000..2e7b0ca --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/RecordingOfficeType.pm @@ -0,0 +1,51 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::RecordingOfficeType; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SensorType qw($NOT_USED $DMS_100_FAMILY); + +use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "recording office type"; +my $length = 4; +my @param_names = qw/recording_office_type/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{recording_office_type} //= $DMS_100_FAMILY; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($recording_office_type) = $self->_get_params(@_); + die("invalid recording office type '$recording_office_type'") unless contains($recording_office_type,[$NOT_USED, $DMS_100_FAMILY]); + return $recording_office_type . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SensorId.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SensorId.pm new file mode 100644 index 0000000..6aba18e --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SensorId.pm @@ -0,0 +1,51 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SensorId; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Utils qw(zerofill); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "sensor id"; +my $length = 8; +my @param_names = qw/rewritten sensor_id/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{rewritten} //= 0; + #$self->{sensor_id} = substr($self->{sensor_id},1( if defined $self->{sensor_id}; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($rewritten,$sensor_id) = $self->_get_params(@_); + die("invalid sensor id '$sensor_id'") unless length($sensor_id) == 6; + return ($rewritten ? '1' : '0') . $sensor_id . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SensorType.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SensorType.pm new file mode 100644 index 0000000..8e04d4c --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SensorType.pm @@ -0,0 +1,54 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SensorType; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + $NOT_USED + $DMS_100_FAMILY +); + +my $field_name = "sensor type"; +my $length = 4; +my @param_names = qw/sensor_type/; + +our $NOT_USED = '000'; +our $DMS_100_FAMILY = '036'; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{sensor_type} //= $DMS_100_FAMILY; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($sensor_type) = $self->_get_params(@_); + die("invalid sensor type '$sensor_type'") unless contains($sensor_type,[$NOT_USED, $DMS_100_FAMILY]); + return $sensor_type . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ServiceFeature.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ServiceFeature.pm new file mode 100644 index 0000000..c75f4e8 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ServiceFeature.pm @@ -0,0 +1,63 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceFeature; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + $OTHER + $THREE_WAY + $CF_LEG + $CFB_LEG + $BTUP_CBWF + $ROUTE_OPT_IND +); + +my $field_name = "service feature"; +my $length = 4; +my @param_names = qw/service_feature_code/; + +our $OTHER = '000'; +our $THREE_WAY = '010'; +our $CF_LEG = '012'; +our $CFB_LEG = '014'; +our $BTUP_CBWF = '029'; +our $ROUTE_OPT_IND = '156'; +#800-999 = generic value + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{service_feature_code} //= 0; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($service_feature_code) = $self->_get_params(@_); + die("invalid service feature code '$service_feature_code'") unless length($service_feature_code) == 3; + return $service_feature_code . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ServiceObserved.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ServiceObserved.pm new file mode 100644 index 0000000..5fe6540 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/ServiceObserved.pm @@ -0,0 +1,75 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceObserved; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + $NOT_OBSERVED_NOT_SAMPLED + $OBSERVED_NOT_SAMPLED + $NOT_OBSERVED_SAMPLED + $OBSERVED_SAMPLED + $SMDR_APPLICABLE + $OBSERVED_NOT_SAMPLED_SMDR_APPLICABLE + $NOT_OBSERVED_SAMPLED_SMDR_APPLICABLE + $OBSERVED_SAMPLED_SMDR_APPLICABLE +); + +my $field_name = "service observed"; +my $length = 2; +my @param_names = qw/observed_sampled/; + +my @observed_sampled_modes = (); +our $NOT_OBSERVED_NOT_SAMPLED = '0'; +push(@observed_sampled_modes,$NOT_OBSERVED_NOT_SAMPLED); +our $OBSERVED_NOT_SAMPLED = '1'; +push(@observed_sampled_modes,$OBSERVED_NOT_SAMPLED); +our $NOT_OBSERVED_SAMPLED = '2'; +push(@observed_sampled_modes,$NOT_OBSERVED_SAMPLED); +our $OBSERVED_SAMPLED = '3'; +push(@observed_sampled_modes,$OBSERVED_SAMPLED); +our $SMDR_APPLICABLE = '4'; +push(@observed_sampled_modes,$SMDR_APPLICABLE); +our $OBSERVED_NOT_SAMPLED_SMDR_APPLICABLE = '5'; +push(@observed_sampled_modes,$OBSERVED_NOT_SAMPLED_SMDR_APPLICABLE); +our $NOT_OBSERVED_SAMPLED_SMDR_APPLICABLE = '6'; +push(@observed_sampled_modes,$NOT_OBSERVED_SAMPLED_SMDR_APPLICABLE); +our $OBSERVED_SAMPLED_SMDR_APPLICABLE = '7'; +push(@observed_sampled_modes,$OBSERVED_SAMPLED_SMDR_APPLICABLE); + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{observed_sampled} //= $NOT_OBSERVED_NOT_SAMPLED; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($observed_sampled) = $self->_get_params(@_); + die("invalid observed sampled '$observed_sampled'") unless contains($observed_sampled,\@observed_sampled_modes); + return $observed_sampled . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SignificantDigitsNextField.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SignificantDigitsNextField.pm new file mode 100644 index 0000000..bde0902 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/SignificantDigitsNextField.pm @@ -0,0 +1,68 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + get_number_length + get_number_digits_1 + get_number_digits_2 +); + +my $field_name = "significant digits in next field"; +my $length = 4; +#my @param_names = qw/significant_digits/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{significant_digits} //= 0; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + if (defined $self->{instance}) { + return ($self->{instance} . '_significant_digits'); + } else { + return ('significant_digits'); + } + +} + +sub get_hex { + + my $self = shift; + my ($significant_digits) = $self->_get_params(@_); + die('invalid ' . (defined $self->{instance} ? $self->{instance} . ' ' : '') . "significant digits '$significant_digits'") if ($significant_digits <= 0 or $significant_digits > 20); + return sprintf('%03d',$significant_digits) . $TERMINATOR; + +} + +sub get_number_length { + return length(shift); +} + +sub get_number_digits_1 { + return substr(shift,0,11); +} + +sub get_number_digits_2 { + return substr(shift,11); +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/StructureCode.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/StructureCode.pm new file mode 100644 index 0000000..3b4f76f --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/StructureCode.pm @@ -0,0 +1,86 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::StructureCode; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + $STRUCTURE_CODE_0510 + $STRUCTURE_CODE_0511 + $STRUCTURE_CODE_0512 + $STRUCTURE_CODE_0513 + $STRUCTURE_CODE_0514 + + $STRUCTURE_CODE_9013 + $STRUCTURE_CODE_9014 +); + +my $field_name = "structure code"; +my $length = 6; +my @param_names = qw/has_modules structure_code/; + +my @structure_codes = (); +our $STRUCTURE_CODE_0510 = '0510'; +push(@structure_codes,$STRUCTURE_CODE_0510); +our $STRUCTURE_CODE_0511 = '0511'; +push(@structure_codes,$STRUCTURE_CODE_0511); +our $STRUCTURE_CODE_0512 = '0512'; +push(@structure_codes,$STRUCTURE_CODE_0512); +our $STRUCTURE_CODE_0513 = '0513'; +push(@structure_codes,$STRUCTURE_CODE_0513); +our $STRUCTURE_CODE_0514 = '0514'; +push(@structure_codes,$STRUCTURE_CODE_0514); +our $STRUCTURE_CODE_9013 = '9013'; +push(@structure_codes,$STRUCTURE_CODE_9013); +our $STRUCTURE_CODE_9014 = '9014'; +push(@structure_codes,$STRUCTURE_CODE_9014); + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub set_has_modules { + + my $self = shift; + $self->{has_modules} = shift; + +} + +sub get_structure_code { + + my $self = shift; + return $self->{structure_code}; + +} + +sub get_hex { + + my $self = shift; + my ($has_modules,$structure_code) = $self->_get_params(@_); + die("invalid structure code '$structure_code'") unless contains($structure_code,\@structure_codes); + return ($has_modules ? '4' : '0') . $structure_code . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/StudyIndicator.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/StudyIndicator.pm new file mode 100644 index 0000000..71c397f --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/StudyIndicator.pm @@ -0,0 +1,103 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::StudyIndicator; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Utils qw(zerofill); +use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + $STUDY_TYPE_A_NA + $STUDY_TYPE_A_SLUS + $STUDY_TYPE_B_NA + $STUDY_TYPE_B_OBSERVED + $STUDY_TYPE_B_UNANSWERED_CALL_RECORDING + $STUDY_TYPE_B_OBSERVED_UNANSWERED_CALL_RECORDING + $STUDY_TYPE_C_NA + $STUDY_TYPE_C_GENERATED + $TEST_CALL_NA + $TEST_CALL + $NUMBER_NANP_NA + $NUMBER_NANP_CALLER + $NUMBER_NANP_CALLEE + $NUMBER_NANP_CALLER_CALLEE +); + +my $field_name = "study indicator"; +my $length = 8; +my @param_names = qw/study_type_a study_type_b study_type_c test_call_ind number_nanp_ind/; + +my @study_a_modes = (); +our $STUDY_TYPE_A_NA = '0'; +push(@study_a_modes,$STUDY_TYPE_A_NA); +our $STUDY_TYPE_A_SLUS = '2'; +push(@study_a_modes,$STUDY_TYPE_A_SLUS); +my @study_b_modes = (); +our $STUDY_TYPE_B_NA = '0'; +push(@study_b_modes,$STUDY_TYPE_B_NA); +our $STUDY_TYPE_B_OBSERVED = '1'; +push(@study_b_modes,$STUDY_TYPE_B_OBSERVED); +our $STUDY_TYPE_B_UNANSWERED_CALL_RECORDING = '2'; +push(@study_b_modes,$STUDY_TYPE_B_UNANSWERED_CALL_RECORDING); +our $STUDY_TYPE_B_OBSERVED_UNANSWERED_CALL_RECORDING = '3'; +push(@study_b_modes,$STUDY_TYPE_B_OBSERVED_UNANSWERED_CALL_RECORDING); +my @study_c_modes = (); +our $STUDY_TYPE_C_NA = '0'; +push(@study_c_modes,$STUDY_TYPE_C_NA); +our $STUDY_TYPE_C_GENERATED = '2'; +push(@study_c_modes,$STUDY_TYPE_C_GENERATED); +our $TEST_CALL_NA = '0'; +our $TEST_CALL = '1'; +my @number_nanp_modes = (); +our $NUMBER_NANP_NA = '0'; +push(@number_nanp_modes,$NUMBER_NANP_NA); +our $NUMBER_NANP_CALLER = '1'; +push(@number_nanp_modes,$NUMBER_NANP_CALLER); +our $NUMBER_NANP_CALLEE = '2'; +push(@number_nanp_modes,$NUMBER_NANP_CALLEE); +our $NUMBER_NANP_CALLER_CALLEE = '3'; +push(@number_nanp_modes,$NUMBER_NANP_CALLER_CALLEE); + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{study_type_a} //= $STUDY_TYPE_A_NA; + $self->{study_type_b} //= $STUDY_TYPE_B_NA; + $self->{study_type_c} //= $STUDY_TYPE_C_NA; + $self->{test_call_ind} //= $TEST_CALL_NA; + $self->{number_nanp_ind} //= $NUMBER_NANP_NA; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($study_type_a,$study_type_b,$study_type_c,$test_call_ind,$number_nanp_ind) = $self->_get_params(@_); + die("invalid study type a '$study_type_a'") unless contains($study_type_a,\@study_a_modes); + die("invalid study type b '$study_type_b'") unless contains($study_type_b,\@study_b_modes); + die("invalid study type c '$study_type_c'") unless contains($study_type_c,\@study_c_modes); + die("invalid test call ind '$test_call_ind'") unless contains($test_call_ind,[$TEST_CALL_NA, $TEST_CALL]); + die("invalid number nanp ind '$number_nanp_ind'") unless contains($number_nanp_ind,\@number_nanp_modes); + return $study_type_a . $study_type_b . $study_type_c . $test_call_ind . '0' . $number_nanp_ind . '0' . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TerminatingOpenDigits1.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TerminatingOpenDigits1.pm new file mode 100644 index 0000000..e32b6c6 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TerminatingOpenDigits1.pm @@ -0,0 +1,50 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TerminatingOpenDigits1; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "terminating open digits 1"; +my $length = 12; +my @param_names = qw/terminating_open_digits_1/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{significant_digits} //= 0; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($terminating_open_digits_1) = $self->_get_params(@_); + die("invalid terminating open digits 1 '$terminating_open_digits_1'") unless $terminating_open_digits_1 =~ /^\d{1,11}$/; + return sprintf('%011d',$terminating_open_digits_1) . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TerminatingOpenDigits2.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TerminatingOpenDigits2.pm new file mode 100644 index 0000000..73bec68 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TerminatingOpenDigits2.pm @@ -0,0 +1,54 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TerminatingOpenDigits2; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + +); + +my $field_name = "terminating open digits 2"; +my $length = 10; +my @param_names = qw/terminating_open_digits_2/; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + #$self->{significant_digits} //= 0; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($terminating_open_digits_2) = $self->_get_params(@_); + if (length($terminating_open_digits_2) > 0) { + die("invalid terminating open digits 2 '$terminating_open_digits_2'") unless $terminating_open_digits_2 =~ /^\d{1,9}$/; + return sprintf('%09d',$terminating_open_digits_2) . $TERMINATOR; + } else { + return 'ffffffffff'; + } + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TimingIndicator.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TimingIndicator.pm new file mode 100644 index 0000000..d8acff1 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Fields/TimingIndicator.pm @@ -0,0 +1,76 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TimingIndicator; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Field qw($TERMINATOR); + +#use NGCP::BulkProcessor::Utils qw(zerofill); +use NGCP::BulkProcessor::Array qw(contains); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::Field); +our @EXPORT_OK = qw( + $TIMING_GUARD_DEFAULT + $TIMING_GUARD_ELAPSED_TIME_ESTIMATED + $CALLED_PARTY_DEFAULT + $CALLED_PARTY_OFF_HOOK + $LONG_DURATION_DEFAULT + $LONG_DURATION_START + $LONG_DURATION_CONTINUE + $LONG_DURATION_END +); + +my $field_name = "timing indicator"; +my $length = 6; +my @param_names = qw/timing_guard called_party long_duration/; + +our $TIMING_GUARD_DEFAULT = '0'; +our $TIMING_GUARD_ELAPSED_TIME_ESTIMATED = '2'; +our $CALLED_PARTY_DEFAULT = '0'; +our $CALLED_PARTY_OFF_HOOK = '1'; +my @long_duration_modes = (); +our $LONG_DURATION_DEFAULT = '0'; +push(@long_duration_modes,$LONG_DURATION_DEFAULT); +our $LONG_DURATION_START = '1'; +push(@long_duration_modes,$LONG_DURATION_START); +our $LONG_DURATION_CONTINUE = '2'; +push(@long_duration_modes,$LONG_DURATION_CONTINUE); +our $LONG_DURATION_END = '3'; +push(@long_duration_modes,$LONG_DURATION_END); + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Field->new( + $class, + name => $field_name, + length => $length, + @_); + $self->{timing_guard} //= $TIMING_GUARD_DEFAULT; + $self->{called_party} //= $CALLED_PARTY_DEFAULT; + $self->{long_duration} //= $LONG_DURATION_DEFAULT; + + return $self; + +} + +sub _get_param_names { + + my $self = shift; + return @param_names; + +} + +sub get_hex { + + my $self = shift; + my ($timing_guard,$called_party,$long_duration) = $self->_get_params(@_); + die("invalid timing guard '$timing_guard'") unless contains($timing_guard,[$TIMING_GUARD_DEFAULT, $TIMING_GUARD_ELAPSED_TIME_ESTIMATED]); + die("invalid called party '$called_party'") unless contains($called_party,[$CALLED_PARTY_DEFAULT, $CALLED_PARTY_OFF_HOOK]); + die("invalid long duration '$long_duration'") unless contains($long_duration,\@long_duration_modes); + return $timing_guard . $called_party . $long_duration . '00' . $TERMINATOR; + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Module.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Module.pm new file mode 100644 index 0000000..f1355f6 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Module.pm @@ -0,0 +1,57 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Module; +use strict; + +## no critic + +use NGCP::BulkProcessor::LogError qw( + notimplementederror +); + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::FieldSet qw(); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::FieldSet); +our @EXPORT_OK = qw( + +); + +sub new { + + my $base_class = shift; + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::FieldSet->new( + $class, + @_); + my %params = @_; + ( + $self->{enabled}, + ) = @params{qw/ + enabled + /}; + $self->{enabled} //= 1; + + return $self; + +} + +sub get_module_code_field { + + my $self = shift; + #my (@params) = @_; + + notimplementederror((ref $self) . ': ' . (caller(0))[3] . ' not implemented',getlogger(__PACKAGE__)); + return undef; + +} + +sub get_name { + my $self = shift; + return $self->get_module_code_field()->get_module_code(); +} + +sub get_enabled { + my $self = shift; + return $self->{enabled}; +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Modules/Module199.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Modules/Module199.pm new file mode 100644 index 0000000..e69de29 diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Modules/Module611.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Modules/Module611.pm new file mode 100644 index 0000000..e69de29 diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Record.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Record.pm new file mode 100644 index 0000000..629320e --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Record.pm @@ -0,0 +1,54 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Record; +use strict; + +## no critic + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw( + +); + +sub new { + + my $class = shift; + my $self = bless {}, $class; + $self->{structure} = shift; + $self->{modules} = [ @_ ]; + $self->{structure}->get_structure_code_field()->set_has_modules((scalar @{$self->{modules}}) > 0); + + return $self; + +} + +sub get_hex { + + my $self = shift; + my $result = $self->_get_record_descriptor_word(@_); + $result .= $self->{structure}->get_hex(@_); + foreach my $module (@{$self->{modules}}) { + next unless $module->get_enabled(@_); + $result .= $module->get_hex(@_); + } + return $result; +} + +sub get_length { + my $self = shift; + my $length = 8; #RDW + $length += $self->{structure}->get_length(@_); + foreach my $module (@{$self->{modules}}) { + next unless $module->get_enabled(@_); + $length += $module->get_length(@_); + } + return $length; +} + + +sub _get_record_descriptor_word { + my $self = shift; + return sprintf('%04x',$self->get_length(@_) / 2) . '0000'; + #return total length in bytes (up to 256*256 bytes) +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Structure.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Structure.pm new file mode 100644 index 0000000..09baaa5 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Structure.pm @@ -0,0 +1,47 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Structure; +use strict; + +## no critic + +use NGCP::BulkProcessor::LogError qw( + notimplementederror +); + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::FieldSet qw(); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::FieldSet); +our @EXPORT_OK = qw( + +); + +sub new { + + my $base_class = shift; + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::FieldSet->new( + $class, + @_); + + return $self; + +} + +sub get_structure_code_field { + + my $self = shift; + #my (@params) = @_; + + notimplementederror((ref $self) . ': ' . (caller(0))[3] . ' not implemented',getlogger(__PACKAGE__)); + return undef; + +} + +sub get_name { + + my $self = shift; + return $self->get_structure_code_field()->get_structure_code(); + +} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Structures/Structure0510.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Structures/Structure0510.pm new file mode 100644 index 0000000..f6fd735 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Format/Structures/Structure0510.pm @@ -0,0 +1,142 @@ +package NGCP::BulkProcessor::Projects::Export::Ama::Format::Structures::Structure0510; +use strict; + +## no critic + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Structure qw(); + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::HexId qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::StructureCode qw($STRUCTURE_CODE_0510); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CallTypeCode qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SensorType qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SensorId qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::RecordingOfficeType qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::RecordingOfficeId qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::Date qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TimingIndicator qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::StudyIndicator qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CalledPartyOffHook qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceObserved qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OperatorAction qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceFeature qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingOpenDigits1 qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingOpenDigits2 qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingChargeInformation qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::DomesticInternational qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TerminatingOpenDigits1 qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TerminatingOpenDigits2 qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ConnectTime qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ElapsedTime qw(); + +require Exporter; +our @ISA = qw(Exporter NGCP::BulkProcessor::Projects::Export::Ama::Format::FieldSet NGCP::BulkProcessor::Projects::Export::Ama::Format::Structure); +our @EXPORT_OK = qw( + +); +#get_instance + +#my $structure_name = 'structure ' . $STRUCTURE_CODE_0510; + +#my $INSTANCE = __PACKAGE__->new(); + +my $length = 142; + +sub new { + + my $class = shift; + my $self = NGCP::BulkProcessor::Projects::Export::Ama::Format::Structure->new( + $class, + length => $length, + #structure_name => $structure_name, + @_); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::HexId->new( + @_, + )); + $self->{structure_code} = NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::StructureCode->new( + structure_code => $STRUCTURE_CODE_0510, + @_, + ); + $self->_add_field($self->{structure_code}); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CallTypeCode->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SensorType->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SensorId->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::RecordingOfficeType->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::RecordingOfficeId->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::Date->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TimingIndicator->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::StudyIndicator->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CalledPartyOffHook->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceObserved->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OperatorAction->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceFeature->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField->new( + instance => 'originating', + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingOpenDigits1->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingOpenDigits2->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::OriginatingChargeInformation->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::DomesticInternational->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField->new( + instance => 'terminating', + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TerminatingOpenDigits1->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::TerminatingOpenDigits2->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ConnectTime->new( + @_, + )); + $self->_add_field(NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ElapsedTime->new( + @_, + )); + return $self; + +} + +sub get_structure_code_field { + my $self = shift; + return $self->{structure_code}; +} + +#sub get_instance { +# return +#} + +1; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Settings.pm b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Settings.pm index b73fdea..c5497f5 100644 --- a/lib/NGCP/BulkProcessor/Projects/Export/Ama/Settings.pm +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/Settings.pm @@ -53,6 +53,9 @@ our @EXPORT_OK = qw( $export_cdr_conditions $export_cdr_limit $export_cdr_stream + + $domestic_destination_pattern + $international_destination_pattern ); #update_provider_config #$deadlock_retries @@ -75,6 +78,8 @@ our $export_cdr_conditions = []; our $export_cdr_limit = undef; our $export_cdr_stream = undef; +our $domestic_destination_pattern = undef; +our $international_destination_pattern = undef; sub update_settings { @@ -105,7 +110,9 @@ sub update_settings { my $parse_result; ($parse_result,$export_cdr_joins) = _parse_export_joins($data->{export_cdr_joins},$configfile); + $result &= $parse_result; ($parse_result,$export_cdr_conditions) = _parse_export_joins($data->{export_cdr_conditions},$configfile); + $result &= $parse_result; $export_cdr_limit = $data->{export_cdr_limit} if exists $data->{export_cdr_limit}; $export_cdr_stream = $data->{export_cdr_stream} if exists $data->{export_cdr_stream}; @@ -113,6 +120,13 @@ sub update_settings { #if ((confval("MAINTENANCE") // 'no') eq 'yes') { # exit(0); #} + my $regexp_result; + $domestic_destination_pattern = $data->{domestic_destination_pattern} if exists $data->{domestic_destination_pattern}; + ($regexp_result,$domestic_destination_pattern) = parse_regexp($domestic_destination_pattern,$configfile); + $result &= $regexp_result; + $international_destination_pattern = $data->{international_destination_pattern} if exists $data->{international_destination_pattern}; + ($regexp_result,$international_destination_pattern) = parse_regexp($international_destination_pattern,$configfile); + $result &= $regexp_result; return $result; diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/test.ama b/lib/NGCP/BulkProcessor/Projects/Export/Ama/test.ama new file mode 100644 index 0000000..f171579 Binary files /dev/null and b/lib/NGCP/BulkProcessor/Projects/Export/Ama/test.ama differ diff --git a/lib/NGCP/BulkProcessor/Projects/Export/Ama/test.pl b/lib/NGCP/BulkProcessor/Projects/Export/Ama/test.pl new file mode 100644 index 0000000..9feb567 --- /dev/null +++ b/lib/NGCP/BulkProcessor/Projects/Export/Ama/test.pl @@ -0,0 +1,68 @@ +use strict; + +## no critic + +use File::Basename; +use Cwd; +use lib Cwd::abs_path(File::Basename::dirname(__FILE__) . '/../../../../../'); + +use NGCP::BulkProcessor::Calendar qw(current_local); + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Record qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Structures::Structure0510 qw(); + +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CallTypeCode qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::Date qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceFeature qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::DomesticInternational qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ConnectTime qw(); +use NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ElapsedTime qw(); + +my $dt = current_local(); +my $source = "43011001"; +my $destination = "43011002"; +my $duration = 123.456; + +my $test = NGCP::BulkProcessor::Projects::Export::Ama::Format::Record->new( + NGCP::BulkProcessor::Projects::Export::Ama::Format::Structures::Structure0510->new( + call_type_code => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::CallTypeCode::STATION_PAID, + + rewritten => 0, + sensor_id => '008708', # Graz + + padding => 0, + recording_office_id => '008708', + + date => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::Date::get_ama_date($dt), + + service_feature_code => $NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ServiceFeature::OTHER, + + originating_significant_digits => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_length($source), + originating_open_digits_1 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_1($source), + originating_open_digits_2 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_2($source), + + domestic_international => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::DomesticInternational::get_number_domestic_international($destination), + + terminating_significant_digits => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_length($destination), + terminating_open_digits_1 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_1($destination), + terminating_open_digits_2 => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::SignificantDigitsNextField::get_number_digits_2($destination), + + connect_time => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ConnectTime::get_connect_time($dt), + elapsed_time => NGCP::BulkProcessor::Projects::Export::Ama::Format::Fields::ElapsedTime::get_elapsed_time($duration), + ) +); + +print $test->{structure}->to_string()."\n"; +print $test->get_hex(); + +unlink 'test.ama'; +if (open(my $fh,">:raw",'test.ama')) { + print $fh pack('H*','004f0000' . $test->get_hex()); + close $fh; + #restdebug($self,"$self->{crt_path} saved",getlogger(__PACKAGE__)); +} else { + #fileerror("failed to open $self->{crt_path}: $!",getlogger(__PACKAGE__)); +} + + diff --git a/lib/NGCP/BulkProcessor/Utils.pm b/lib/NGCP/BulkProcessor/Utils.pm index 143c98b..709e651 100755 --- a/lib/NGCP/BulkProcessor/Utils.pm +++ b/lib/NGCP/BulkProcessor/Utils.pm @@ -6,7 +6,7 @@ use strict; use threads; #use POSIX qw(strtod); -use POSIX qw(strtod locale_h); +use POSIX qw(strtod locale_h floor fmod); setlocale(LC_NUMERIC, 'C'); use Data::UUID qw(); @@ -74,6 +74,7 @@ our @EXPORT_OK = qw( get_year get_year_month get_year_month_day + to_duration_string secs_to_years zerofill trim @@ -828,6 +829,288 @@ sub secs_to_years { } } +sub to_duration_string { + my ($duration_secs,$most_significant,$least_significant,$least_significant_decimals,$loc_code) = @_; + $most_significant //= 'years'; + $least_significant //= 'seconds'; + #$loc_code //= sub { return shift; }; + my $abs = abs($duration_secs); + my ($years,$months,$days,$hours,$minutes,$seconds); + my $result = ''; + if ('seconds' ne $least_significant) { + $abs = $abs / 60.0; #minutes + if ('minutes' ne $least_significant) { + $abs = $abs / 60.0; #hours + if ('hours' ne $least_significant) { + $abs = $abs / 24.0; #days + if ('days' ne $least_significant) { + $abs = $abs / 30.0; #months + if ('months' ne $least_significant) { + $abs = $abs / 12.0; #years + if ('years' ne $least_significant) { + die("unknown least significant duration unit-of-time: '$least_significant'"); + } else { + $seconds = 0.0; + $minutes = 0.0; + $hours = 0.0; + $days = 0.0; + $months = 0.0; + if ('years' eq $most_significant) { + $years = $abs; + } else { + die("most significant duration unit-of-time '$most_significant' lower than least significant duration unit-of-time '$least_significant'"); + } + } + } else { + $seconds = 0.0; + $minutes = 0.0; + $hours = 0.0; + $days = 0.0; + $years = 0.0; + if ('months' eq $most_significant) { + $months = $abs; + } else { + $months = ($abs >= 12.0) ? fmod($abs,12.0) : $abs; + $abs = $abs / 12.0; + if ('years' eq $most_significant) { + $years = floor($abs); + } else { + die("most significant duration unit-of-time '$most_significant' lower than least significant duration unit-of-time '$least_significant'"); + } + } + } + } else { + $seconds = 0.0; + $minutes = 0.0; + $hours = 0.0; + $months = 0.0; + $years = 0.0; + if ('days' eq $most_significant) { + $days = $abs; + } else { + $days = ($abs >= 30.0) ? fmod($abs,30.0) : $abs; + $abs = $abs / 30.0; + if ('months' eq $most_significant) { + $months = floor($abs); + } else { + $months = ($abs >= 12.0) ? fmod($abs,12.0) : $abs; + $abs = $abs / 12.0; + if ('years' eq $most_significant) { + $years = floor($abs); + } else { + die("most significant duration unit-of-time '$most_significant' lower than least significant duration unit-of-time '$least_significant'"); + } + } + } + } + } else { + $seconds = 0.0; + $minutes = 0.0; + $days = 0.0; + $months = 0.0; + $years = 0.0; + if ('hours' eq $most_significant) { + $hours = $abs; + } else { + $hours = ($abs >= 24.0) ? fmod($abs,24.0) : $abs; + $abs = $abs / 24.0; + if ('days' eq $most_significant) { + $days = floor($abs); + } else { + $days = ($abs >= 30.0) ? fmod($abs,30) : $abs; + $abs = $abs / 30.0; + if ('months' eq $most_significant) { + $months = floor($abs); + } else { + $months = ($abs >= 12.0) ? fmod($abs,12.0) : $abs; + $abs = $abs / 12.0; + if ('years' eq $most_significant) { + $years = floor($abs); + } else { + die("most significant duration unit-of-time '$most_significant' lower than least significant duration unit-of-time '$least_significant'"); + } + } + } + } + } + } else { + $seconds = 0.0; + $hours = 0.0; + $days = 0.0; + $months = 0.0; + $years = 0.0; + if ('minutes' eq $most_significant) { + $minutes = $abs; + } else { + $minutes = ($abs >= 60.0) ? fmod($abs,60.0) : $abs; + $abs = $abs / 60.0; + if ('hours' eq $most_significant) { + $hours = floor($abs); + } else { + $hours = ($abs >= 24.0) ? fmod($abs,24.0) : $abs; + $abs = $abs / 24.0; + if ('days' eq $most_significant) { + $days = floor($abs); + } else { + $days = ($abs >= 30.0) ? fmod($abs,30.0) : $abs; + $abs = $abs / 30.0; + if ('months' eq $most_significant) { + $months = floor($abs); + } else { + $months = ($abs >= 12.0) ? fmod($abs,12.0) : $abs; + $abs = $abs / 12.0; + if ('years' eq $most_significant) { + $years = floor($abs); + } else { + die("most significant duration unit-of-time '$most_significant' lower than least significant duration unit-of-time '$least_significant'"); + } + } + } + } + } + } + } else { + $minutes = 0.0; + $hours = 0.0; + $days = 0.0; + $months = 0.0; + $years = 0.0; + if ('seconds' eq $most_significant) { + $seconds = $abs; + } else { + $seconds = ($abs >= 60.0) ? fmod($abs,60.0) : $abs; + $abs = $abs / 60.0; + if ('minutes' eq $most_significant) { + $minutes = floor($abs); + } else { + $minutes = ($abs >= 60.0) ? fmod($abs,60.0) : $abs; + $abs = $abs / 60.0; + if ('hours' eq $most_significant) { + $hours = floor($abs); + } else { + $hours = ($abs >= 24.0) ? fmod($abs,24.0) : $abs; + $abs = $abs / 24.0; + if ('days' eq $most_significant) { + $days = floor($abs); + } else { + $days = ($abs >= 30.0) ? fmod($abs,30.0) : $abs; + $abs = $abs / 30.0; + if ('minutes' eq $most_significant) { + $months = floor($abs); + } else { + $months = ($abs >= 12.0) ? fmod($abs,12.0) : $abs; + $abs = $abs / 12.0; + if ('years' eq $most_significant) { + $years = floor($abs); + } else { + die("most significant duration unit-of-time '$most_significant' lower than least significant duration unit-of-time '$least_significant'"); + } + } + } + } + } + } + } + if ($years > 0.0) { + if ($months > 0.0 || $days > 0.0 || $hours > 0.0 || $minutes > 0.0 || $seconds > 0.0) { + $result .= _duration_unit_of_time_value_to_string($loc_code,$years, 0, 'years'); + } else { + $result .= _duration_unit_of_time_value_to_string($loc_code,$years, $least_significant_decimals, 'years'); + } + } + if ($months > 0.0) { + if ($years > 0.0) { + $result .= ', '; + } + if ($days > 0.0 || $hours > 0.0 || $minutes > 0.0 || $seconds > 0.0) { + $result .= _duration_unit_of_time_value_to_string($loc_code,$months, 0, 'months'); + } else { + $result .= _duration_unit_of_time_value_to_string($loc_code,$months, $least_significant_decimals, 'months'); + } + } + if ($days > 0.0) { + if ($years > 0.0 || $months > 0.0) { + $result .= ', '; + } + if ($hours > 0.0 || $minutes > 0.0 || $seconds > 0.0) { + $result .= _duration_unit_of_time_value_to_string($loc_code,$days, 0, 'days'); + } else { + $result .= _duration_unit_of_time_value_to_string($loc_code,$days, $least_significant_decimals, 'days'); + } + } + if ($hours > 0.0) { + if ($years > 0.0 || $months > 0.0 || $days > 0.0) { + $result .= ', '; + } + if ($minutes > 0.0 || $seconds > 0.0) { + $result .= _duration_unit_of_time_value_to_string($loc_code,$hours, 0, 'hours'); + } else { + $result .= _duration_unit_of_time_value_to_string($loc_code,$hours, $least_significant_decimals, 'hours'); + } + } + if ($minutes > 0.0) { + if ($years > 0.0 || $months > 0.0 || $days > 0.0 || $hours > 0.0) { + $result .= ', '; + } + if ($seconds > 0.0) { + $result .= _duration_unit_of_time_value_to_string($loc_code,$minutes, 0, 'minutes'); + } else { + $result .= _duration_unit_of_time_value_to_string($loc_code,$minutes, $least_significant_decimals, 'minutes'); + } + } + if ($seconds > 0.0) { + if ($years > 0.0 || $months > 0.0 || $days > 0.0 || $hours > 0.0 || $minutes > 0.0) { + $result .= ', '; + } + $result .= _duration_unit_of_time_value_to_string($loc_code,$seconds, $least_significant_decimals, 'seconds'); + } + if (length($result) == 0) { + $result .= _duration_unit_of_time_value_to_string($loc_code,0.0, $least_significant_decimals, $least_significant); + } + return ($result,$years,$months,$days,$hours,$minutes,$seconds); +} + +sub _duration_unit_of_time_value_to_string { + my ($loc_code,$value, $decimals, $unit_of_time) = @_; + my $result = ''; + my $unit_label_plural = ''; + my $unit_label_singular = ''; + if (defined $loc_code) { + if ('seconds' eq $unit_of_time) { + $unit_label_plural = ' ' . &$loc_code('seconds'); + $unit_label_singular = ' ' . &$loc_code("second"); + } elsif ('minutes' eq $unit_of_time) { + $unit_label_plural = ' ' . &$loc_code('minutes'); + $unit_label_singular = ' ' . &$loc_code("minute"); + } elsif ('hours' eq $unit_of_time) { + $unit_label_plural = ' ' . &$loc_code('hours'); + $unit_label_singular = ' ' . &$loc_code("hour"); + } elsif ('days' eq $unit_of_time) { + $unit_label_plural = ' ' . &$loc_code('days'); + $unit_label_singular = ' ' . &$loc_code("day"); + } elsif ('months' eq $unit_of_time) { + $unit_label_plural = ' ' . &$loc_code('months'); + $unit_label_singular = ' ' . &$loc_code("month"); + } elsif ('years' eq $unit_of_time) { + $unit_label_plural = ' ' . &$loc_code('years'); + $unit_label_singular = ' ' . &$loc_code("year"); + } + } + if ($decimals < 1) { + if (int($value) == 1) { + $result .= '1'; + $result .= $unit_label_singular; + } else { + $result .= int($value); + $result .= $unit_label_plural; + } + } else { + $result .= sprintf('%.' . $decimals . 'f', $value); + $result .= $unit_label_plural; + } + return $result; +} + sub get_cpucount { my $cpucount = Sys::CpuAffinity::getNumCpus() + 0; return ($cpucount > 0) ? $cpucount : 1;