- PVSM.RU - https://www.pvsm.ru -
Что имеем на входе:
На выходе хотим получить список масок для определения номеров московских сотовых операторов (МСС, Билайн, МТС, МегаФон). Для этого за пару часов был написан небольшой скрипт, который наверняка может пригодиться кому-то еще и при небольших изменениях может быть переделан под других операторов или другие регионы.
<?php
$linecode = '98'; // код для звонков на мобильные
// берем таблицу
$file = fopen('http://www.rossvyaz.ru/docs/articles/DEF-9x.html', 'r');
// получаем и разбираем таблицу
$defs = array();
while(($line = fgets($file)) && ($line !== FALSE)) {
$line = iconv('WINDOWS-1251', 'UTF-8', $line);
if(preg_match('|<tr>s*<td>s*(d+)s*</td>s*<td>s*(d+)s*</td>s*<td>s*(d+)s*</td>s*<td>s*(d+)s*</td>s*<td>s*(.+?)s*</td>s*<td>s*(.+?)s*</td>s*</tr>|', $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 "nn=== $op ===nn";
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];
}
?>
В настоящий момент получил следующий результат: из таблицы по состоянию на 01.09.2012 [4].
P.S.: код жестоко привязан к выдаче Россвязи, так что начало интервала всегда оканчивается нулями, а конец — девятками. Это DEF-коды — так что семь цифр.
P.P.S.: на всякий случай уточню — да, это не самый красивый код, но когда нужен вспомогательный скрипт — то можно и так =)
Автор: RSM
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/14376
Ссылки в тексте:
[1] rossvyaz.ru: http://www.rossvyaz.ru/docs/articles/DEF-9x.html
[2] Asterisk: http://www.asterisk.org
[3] Elastix: http://www.elastix.org
[4] из таблицы по состоянию на 01.09.2012: http://pastebin.com/xAwdv118
Нажмите здесь для печати.