Generator of masks from intervals of DEF codes for Asterisk

    What we have at the entrance:
    1. several SIP operators for outgoing calls, and some have more “tasty" tariffs for a particular mobile operator;
    2. data on DEF codes on rossvyaz.ru for selected operators, but broken into intervals, including adjacent ones (especially noticeable for MegaFon);
    3. configured by Asterisk as an Elastix distribution .

    At the output, we want to get a list of masks for determining the numbers of Moscow mobile operators (MCC, Beeline, MTS, MegaFon). To do this, a small script was written in a couple of hours, which probably can be useful to someone else and, with small changes, can be redone for other operators or other regions.

    Upd .: DEF-code mask generator for Asterisk - now online =).

    \s*\s*(\d+)\s*\s*\s*(\d+)\s*\s*\s*(\d+)\s*\s*\s*(\d+)\s*\s*\s*(.+?)\s*\s*\s*(.+?)\s*\s*|', $line, $matches)) {
            if(!isset($defs[$matches[6]])) {
                $defs[$matches[6]] = array();
            }
            if(!isset($defs[$matches[6]][$matches[5]])) {
                $defs[$matches[6]][$matches[5]] = array();
            }
            $defs[$matches[6]][$matches[5]][] = array($matches[1],$matches[2],$matches[3]);
        }
    }
    fclose($file);
    // выбираем интересующие нас записи и объединяем смежные интервалы
    $selected = array();
    foreach($defs as $reg => $ops) {
        if($reg == 'Москва и Московская область') {
            foreach($ops as $op => $cs) {
                usort($cs, "cmp_defs");
                switch($op) {
                    case 'Московская сотовая связь':
                    case 'Вымпел-Коммуникации':
                    case 'Мобильные ТелеСистемы':
                    case 'МегаФон':
                        if(!isset($selected[$op])) {
                            $selected[$op] = array();
                        }
                        $newset = true; $cnt = 1;
                        foreach($cs as $cid => $c) {
                            if($newset) {
                                $selected[$op][] = array($c[0], $c[1]);
                            }
                            if(isset($cs[$cid+1]) && ($c[0] == $cs[$cid+1][0]) && (($c[2] + 1) == $cs[$cid+1][1])) {
                                $newset = false;
                                $cnt++;
                            } else {
                                $selected[$op][count($selected[$op]) - 1][2] = $c[2];
                                $newset = true;
                                $cnt = 1;
                            }
                        }
                        break;
                }
            }
        }
    }
    // генерируем маски для Asterisk
    $regs = array();
    foreach($selected as $op => $defs) {
        $regs[$op] = array();
        foreach($defs as $def) {
            // если кто будет разбираться, то здесь мозг отказал мне
            // $leq - это про правую часть, а $req про левую =)
            $pref = $def[0];
            $first = $def[1];
            $last = $def[2];
            if($first > $last) {
                $tmp = $first;
                $first = $last;
                $last = $tmp;
            }
            // маски разбиваем на три массива и вгоняем через unshift/push исключительно с целью удобства поиска ошибок =)
            $r = array();
            $rf = array();
            $rl = array();
            $req = 0;
            for($i = 0; $i < 7; $i++) {
                if($first[$i] === $last[$i]) {
                    $req++;
                } else {
                    break;
                }
            }
            $leq = 0;
            for($i = 6; $i >= 0; $i--) {
                if(($first[$i]) === "0" && ($last[$i] === "9")) {
                    $leq++;
                } else {
                    break;
                }
            }
            $zf = true;
            $nl = true;
            if($leq + $req < 6)
                for($i = $leq; $i + $req < 6; $i++) {
                    $sl = 6 - $i;
                    $pf = substr($first, 0, 6 - $i);
                    $pl = substr($last, 0, 6 - $i);
                    if($pf < $pl) {
                        $x = $first[6 - $i];
                        if(!$zf || ($x != '0')) {
                            switch($x) {
                                case '9':
                                    array_push($rf, $pref . $pf . '9' . str_repeat('X', $i));
                                    break;
                                case '8':
                                    array_push($rf, $pref . $pf . '[89]' . str_repeat('X', $i));
                                    break;
                                default:
                                    array_push($rf, $pref . $pf . '[' . $x . '-9]' . str_repeat('X', $i));
                            }
                            $first = sprintf('%0' . $sl . 'd', substr($first, 0, $sl) + 1 ) . str_repeat('0', 7 - $sl);
                            $zf = false;
                        }
                        $x = $last[6 - $i];
                        if(!$nl || ($x != 9)) {
                            switch($x) {
                                case '0':
                                    array_unshift($rl, $pref . $pl . '0' . str_repeat('X', $i));
                                    break;
                                case '1':
                                    array_unshift($rl, $pref . $pl . '[01]' . str_repeat('X', $i));
                                    break;
                                default:
                                    array_unshift($rl, $pref . $pl . '[0-' . $x . ']' . str_repeat('X', $i));
                            }
                            $last = sprintf('%0' . $sl . 'd', substr($last, 0, $sl) - 1 ) . str_repeat('9', 7 - $sl);
                            $nl = false;
                        }
                    }
                    $leq++;
                }
            if($leq + $req <= 7) {
                if($leq < 7) {
                    $sl = 6 - $leq;
                    $pf = substr($first, 0, 6 - $leq);
                    $pl = substr($last, 0, 6 - $leq);
                    $xf = $first[6 - $leq];
                    $xl = $last[6 - $leq];
                    if(($pf == $pl) && ($xf <= $xl)) {
                        if($xf == $xl) {
                            $r[] = $pref . $pf . $xf . str_repeat('X', $leq);
                        } elseif($xf + 1 == $xl) {
                            $r[] = $pref . $pf . '[' . $xf . $xl . ']' . str_repeat('X', $leq);
                        } else {
                            $r[] = $pref . $pf . '[' . $xf . '-' . $xl . ']' . str_repeat('X', $leq);
                        }
                    }
                } else {
                    $r[] = $pref . str_repeat('X', $leq);
                }
            }
            $regs[$op] = array_merge($regs[$op], $rf, $r, $rl);
        }
    }
    foreach($regs as $op => $reg) {
        echo "\n\n=== $op ===\n\n";
        foreach($reg as $r) {
            echo $linecode . $r . "\n";
        }
    }
    function cmp_defs($a, $b) {
        if($a[0] != $b[0])
            return $a[0] - $b[0];
        return $a[1] - $b[1];
    }
    ?>
    

    Currently I got the following result: from the table as of September 1, 2012 .

    PS: the code is cruelly tied to the issuance of Rossvyaz, so the beginning of the interval always ends with zeros, and the end with nines. These are DEF codes - so there are seven digits.
    PPS: just in case, I’ll clarify - yes, this is not the most beautiful code, but when you need an auxiliary script, then it’s possible =)

    Also popular now: