Gheek.net

September 30, 2011

REDCOM DCT Translation Tester (100% offline)

Filed under: perl, REDCOM — lancevermilion @ 5:45 pm

I took some time today to write a fairly simple Perl script to walking through REDCOM Dial Code Tables(DCT) and preform the translations in a 100% offline mode. You will need to get a copy of each of your DCTs and make them a CSV format.

The script works for basic stuff, but it does not evaluate the SC, NEXT (except when used with TYPE=sup), SB/SNU, SST/NST, TID fields because I don’t see a need for them in my testing. The script does not handle using ac-x, ac+x, etc in the PRE, POS, or MARK fields. There is no support for patterns that contain # symbols (again no need for me to figure out why my script doesn’t like them).

I need to do some cleanup, more inline comments, add strict usage, and some other things. This is a functional script. If you do use it then please let me know what you think of it and also if you make changes to it that are for the positive please let me know of those since I shared this with you.

The Code:

#!/usr/bin/perl
# Author:  Lance Vermilion
# Purpose: Walk through Redcom Dial Code Tables and determine
#          what entry the digits would hit if it was ran
#          through a Redcom.
# Script:  dct.pl
# Date:    9/30/2011
# Rev:     0.1
# Syntax:  dct.pl <starting dct> <digits dialed>
# Example: dct.pl dct0 4352348763
#################################################################

#################################################################
# Instructions:
# Copy the all each entry (row) in the DCT to a CSV file named dct[n].csv.
# Do not copy the headers, footers, other data, etc.
# All possible dial code tables should be in one directory.
# Sample Output
# [root@localhost dct]$ ls -als
# total 60
# 8 drwxrwxr-x  2 root root 4096 Sep 30 16:48 .
# 8 drwx------ 33 root root 4096 Sep 30 16:48 ..
# 8 -rw-rw-r--  1 root root  260 Sep 30 15:38 dct0.csv
# 8 -rw-rw-r--  1 root root   92 Sep 30 15:11 dct6.csv
# 8 -rw-rw-r--  1 root root  202 Sep 30 15:16 dct7.csv
# 8 -rw-rw-r--  1 root root  285 Sep 30 15:14 dct8.csv
#12 -rw-rw-r--  1 root root 6410 Sep 30 16:44 dct.pl
#################################################################

#################################################################
# Not supported yet
# TYPE (other than dct, rte, int, stn, sup)
# SC
# PRE  (does support any variation of ac- ac+)
# POS  (does support any variation of ac- ac+)
# MARK (does support any variation of ac- ac+)
# Next (Only jumps to that dct)
# SB
# SST
# TID
#
# Pattern that uses a # in the pattern
#################################################################

my $inputfile = "$ARGV[0]";
my $dialeddigits = $ARGV[1];

sub help()
{
  print "Syntax:  dct.pl <starting dct> <digits dialed>\n";
  print "Example: dct.pl dct0 4352348763\n";
  exit;
}

if ( scalar(@ARGV) ne 2 )
{
  print "You didn't provide enough variables\n"
  &help();
}

&work($inputfile,$dialeddigits,0,0,0);

sub work($$$$$)
{

  # DCT file in csv format or type
  my $type = shift;

  # Since we wrap back on our self to walk DCTs we need to make sure we exit on types of int,etc
  if ( $type =~ /^(int|int\d+)/ )
  {
    print "User will be sent to an intercept message\n";
    exit;
  }
  elsif ( $type =~ /^(rte|rte?\d+)/ )
  {
    print "Digits will be sent to Route: $type\n";
    exit;
  }
  elsif ( $type =~ /^(stn|stn?\d+)/ )
  {
    print "Digits will be sent to a local station.\n";
    exit;
  }

  # numbers dialed
  my $digits = shift;
  chomp($digits);

  # Adjust digits based on pre, pos, and mark
  my $pre = shift;
  my $pos = shift;
  my $mark = shift;
  $digits = substr($digits, $pre)  if ( $pre > 0 );
  $digits = substr($digits, -$pos) if ( $pos > 0 );
  $digits = substr($digits, $mark)  if ( $mark > 0 );

  # DCT to be used that is passed by commandline
  my $dct = {};
  if ( -f "$type.csv" )
  {
    print "Reading DCT file: \"$type.csv\"\n";
  }
  else
  {
    print "File: \"$type.csv\" does not exist. :: $!\n";
    exit;
  }
  my @dctarr = `cat "$type.csv"`;

  for my $dctentry (@dctarr)
  {
    my ($ent, $patt, $sc, $type, $val, $pre, $pos, $mark, $next, $sb, $sst, $tid);
    ($ent, $patt, $sc, $type, $val, $pre, $pos, $mark, $next, $sb, $sst, $tid) = split(/,/, $dctentry);
    $dct->{$ent}->{'origpatt'} = $patt;
    $patt =~ s/n/[2-9]/g;
    $patt =~ s/x/[0-9]/g;
    $patt =~ s/q/[0-4]/g;
    $patt =~ s/Q/[5-9]/g;
    $patt =~ s/X/[2-8]/g;
    $patt =~ s/\~/\\d+/g;
    $patt =~ s/\*/\\*/g;
    $patt =~ s/\#/\\#/g;
    $patt =~ s/\?/[0-9]/g;
    $patt =~ s/w//g;
    $dct->{$ent}->{'patt'} = $patt;
    $dct->{$ent}->{'sc'}   = $sc;
    $dct->{$ent}->{'type'} = $type;
    $dct->{$ent}->{'val'}  = $val;
    $dct->{$ent}->{'pre'}  = $pre;
    $dct->{$ent}->{'pos'}  = $pos;
    $dct->{$ent}->{'mark'} = $mark;
    $dct->{$ent}->{'next'} = $next;
    $dct->{$ent}->{'sb'} = $sb;
    $dct->{$ent}->{'sst'} = $sst;
    $dct->{$ent}->{'tid'} = $tid;
  }

  # Create a pattern hash keyed by pattern with entry and value
  my $patt_ref = {};
  for my $key ( sort keys %$dct )
  {
    $patt_ref->{$dct->{$key}->{'origpatt'}} = $key;
  }

  print "Proccessing " . length($digits) . " Digit Dialed Number \"$digits\"\n";

  my $charcnt = 0;

  # Print DCT in really short form
  print "DCT = $type\n";
  print "ENTRY PATTERN         PATTERN (as seen by Perl)\n";
  for my $key ( sort { $a <=> $b } keys %$dct )
  {
    printf ("%-5s %-14s %s\n", $key,$dct->{$key}->{'origpatt'},($dct->{$key}->{'patt'}));
  }

  # Sub-routine to print DCT
  sub printdct ($$$$$$$$)
  {
    my $printent  = shift;
    my $printpatt = shift;
    my $printsc   = shift;
    my $printtype = shift;
    my $printval  = shift;
    my $printpre  = shift;
    my $printpos  = shift;
    my $printmark = shift;
    my $printnext = shift;
    my $printsb = shift;
    my $printsst = shift;
    my $printtid = shift;

    print "ENTRY PATTERN         SC TYPE VAL PRE POS MARK NEXT SB/SNU  SST/NST  TID    \n";
format DCTREPORT =
@<<<< @<<<<<<<<<<<<<< @< @<<< @<< @<< @<< @<<< @<<< @<<<<<  @<<<<<<  @<<
$printent $printpatt $printsc $printtype $printval $printpre $printpos $printmark $printnext $printsb $printsst $printtid
.
    $~ = 'DCTREPORT';
    write;
  }

  # Check for an exact match first
  for my $patt_orig (sort keys %$patt_ref)
  {
    my $dctentry = $patt_ref->{$patt_orig};
    my $patt = $dct->{$dctentry}->{'patt'};
    if ( $dctentry eq 0 )
    {
      next;
    }
    if ( $digits =~ /^$patt$/ )
    {
      print "\nFound exact match!\n";
      &printdct($dctentry,$dct->{$dctentry}->{'origpatt'},$dct->{$dctentry}->{'sc'},$dct->{$dctentry}->{'type'},$dct->{$dctentry}->{'val'},$dct->{$dctentry}->{'pre'},$dct->{$dctentry}->{'pos'},$dct->{$dctentry}->{'mark'},$dct->{$dctentry}->{'next'},$dct->{$dctentry}->{'sb'},$dct->{$dctentry}->{'sst'},$dct->{$dctentry}->{'tid'});
      if ( $dct->{$dctentry}->{'type'} eq 'sup' )
      {
        print "User will be sent to a DCT equal to the Next field with Supervision\n";
        $dct->{$dctentry}->{'type'} = 'dct';
        $dct->{$dctentry}->{'val'} = $dct->{$dctentry}->{'next'}
      }
      &work("$dct->{$dctentry}->{'type'}$dct->{$dctentry}->{'val'}",$digits,$dct->{$dctentry}->{'pre'},$dct->{$dctentry}->{'pos'},length($patt));
    }
    else
    {
      if ( substr($digits, 0, length($dct->{$dctentry}->{'origpatt'})) =~ /^$patt$/ )
      {
        print "\nFound DbyD exact match!\n";
        &printdct($dctentry,$dct->{$dctentry}->{'origpatt'},$dct->{$dctentry}->{'sc'},$dct->{$dctentry}->{'type'},$dct->{$dctentry}->{'val'},$dct->{$dctentry}->{'pre'},$dct->{$dctentry}->{'pos'},$dct->{$dctentry}->{'mark'},$dct->{$dctentry}->{'next'},$dct->{$dctentry}->{'sb'},$dct->{$dctentry}->{'sst'},$dct->{$dctentry}->{'tid'});
        if ( $dct->{$dctentry}->{'type'} eq 'sup' )
        {
          print "User will be sent to a DCT equal to the Next field with Supervision\n";
          $dct->{$dctentry}->{'type'} = 'dct';
          $dct->{$dctentry}->{'val'} = $dct->{$dctentry}->{'next'}
        }
        &work("$dct->{$dctentry}->{'type'}$dct->{$dctentry}->{'val'}",$digits,$dct->{$dctentry}->{'pre'},$dct->{$dctentry}->{'pos'},length($patt));
      }
    }
  }

  print "\nNo match using Default.\n";
  &printdct(0,$dct->{'0'}->{'origpatt'},$dct->{'0'}->{'sc'},$dct->{'0'}->{'type'},$dct->{'0'}->{'val'},$dct->{'0'}->{'pre'},$dct->{'0'}->{'pos'},$dct->{'0'}->{'mark'},$dct->{'0'}->{'next'},$dct->{'0'}->{'sb'},$dct->{'0'}->{'sst'},$dct->{'0'}->{'tid'});
  if ( $dct->{'0'}->{'type'} eq 'sup' )
  {
    print "User will be sent to a DCT equal to the Next field with Supervision\n";
    $dct->{'0'}->{'type'} = 'dct';
    $dct->{'0'}->{'val'} = $dct->{$dctentry}->{'next'}
  }
  &work("$dct->{'0'}->{'type'}$dct->{'0'}->{'val'}",$digits,$dct->{'0'}->{'pre'},$dct->{'0'}->{'pos'},0);
}

# make sure we exit incase we don't make it into the subroutines
exit;

Here are my sample Dial Code Table files.

::::::::::::::
dct0.csv
::::::::::::::

0,-default-,0,dct,6,0,0,0,
1,*,0,dct,1,0,0,ac,
2,#,0,dct,2,0,0,ac,
3,?111,0,rte,1,0,0,0,
4,zxxxx,0,rte,3,0,0,0,
5,1nxxnxxxxxx,0,rte,1,0,0,0,
6,011~w,0,rte,1,0,0,0,
7,011~#,0,rte,1,0,0,0,
8,1800nxxxxxx,0,rte,1,0,0,0,
9,911,0,rte,1,0,0,0,
10,011~,0,rte,1,0,0,0,

::::::::::::::
dct6.csv
::::::::::::::

0,-default-,0,dct,7,0,0,0,
1,623,0,dct,7,0,0,ac,
2,480,0,dct,7,0,0,ac,
3,xxx,0,rte,1,0,0,0,

::::::::::::::
dct7.csv
::::::::::::::

0,-default-,0,int,0,0,ac,,,0,,
1,959,0,dct,8,0,0,ac,,,0,,
2,4x21207,0,dct,8,0,0,ac,,,0,,
3,738,0,dct,8,0,0,ac,,,0,,
4,525,0,dct,8,0,0,ac,,,0,,
5,4x21206,0,dct,8,0,0,ac,,,0,,
6,4x21,0,dct,8,0,0,ac,,,0,,

::::::::::::::
dct8.csv
::::::::::::::

0,-default-,0,int,,0,0,ac,,,0,,
1,1155,0,sup,,ac,0,ac,17,,0,,
2,11xx,0,stn,0,0,0,ac,,,0,,
3,12xx,0,stn,0,0,0,ac,,,0,,
4,25xx,0,stn,0,0,0,ac,,,0,,
5,26xx,0,stn,0,0,0,ac,,,0,,
6,93xx,0,stn,0,0,0,ac,,,0,,
7,94xx,0,stn,0,0,0,ac,,,0,,
8,95xx,0,stn,0,0,0,ac,,,0,,
9,xxxx,0,rte,1,0,0,0,,,0,,

::::::::::::::
dct17.csv
::::::::::::::

0,-default-,0,int,,0,0,ac,,,0,,
1,1155,0,sup,,ac,0,ac,17,,0,,
2,11xx,0,stn,0,0,0,ac,,,0,,
3,12xx,0,stn,0,0,0,ac,,,0,,
4,25xx,0,stn,0,0,0,ac,,,0,,
5,26xx,0,stn,0,0,0,ac,,,0,,
6,93xx,0,stn,0,0,0,ac,,,0,,
7,94xx,0,stn,0,0,0,ac,,,0,,
8,95xx,0,stn,0,0,0,ac,,,0,,
9,xxxx,0,rte,1,0,0,0,,,0,,

Blog at WordPress.com.