"януари",2=>"февруари",3=>"март",4=>"април", 5=>"май",6=>"юни",7=>"юли",8=>"август",9=>"септември", 10 => "октомври",11=>"ноември",12=>"декември"); $EGN_REGIONS_LAST_NUM = array(); $EGN_REGIONS_FIRST_NUM = array(); $first_region_num = 0; foreach ($EGN_REGIONS as $region => $last_region_num) { $EGN_REGIONS_FIRST_NUM[$first_region_num] = $last_region_num; $EGN_REGIONS_LAST_NUM[$last_region_num] = $first_region_num; $first_region_num = $last_region_num+1; } /* Check if EGN is valid */ /* See: http://www.grao.bg/esgraon.html */ function egn_valid($egn) { global $EGN_WEIGHTS; if (strlen($egn) != 10) return false; $year = substr($egn,0,2); $mon = substr($egn,2,2); $day = substr($egn,4,2); if ($mon > 40) { if (!checkdate($mon-40, $day, $year+2000)) return false; } else if ($mon > 20) { if (!checkdate($mon-20, $day, $year+1800)) return false; } else { if (!checkdate($mon, $day, $year+1900)) return false; } $checksum = substr($egn,9,1); $egnsum = 0; for ($i=0;$i<9;$i++) $egnsum += substr($egn,$i,1) * $EGN_WEIGHTS[$i]; $valid_checksum = $egnsum % 11; if ($valid_checksum == 10) $valid_checksum = 0; if ($checksum == $valid_checksum) return true; } /* Return array with EGN info */ function egn_parse($egn) { global $EGN_REGIONS; global $MONTHS_BG; if (!egn_valid($egn)) return false; $ret = array(); $ret["year"] = substr($egn,0,2); $ret["month"] = substr($egn,2,2); $ret["day"] = substr($egn,4,2); if ($ret["month"] > 40) { $ret["month"] -= 40; $ret["year"] += 2000; } else if ($ret["month"] > 20) { $ret["month"] -= 20; $ret["year"] += 1800; } else { $ret["year"] += 1900; } $ret["birthday_text"] = (int)$ret["day"]." ".$MONTHS_BG[(int)$ret["month"]]." ".$ret["year"]." г."; $region = substr($egn,6,3); $ret["region_num"] = $region; $ret["sex"] = substr($egn,8,1) % 2; $ret["sex_text"] = "жена"; if (!$ret["sex"]) $ret["sex_text"] = "мъж"; $first_region_num = 0; foreach ($EGN_REGIONS as $region_name => $last_region_num) { if ($region >= $first_region_num && $region <= $last_region_num) { $ret["region_text"] = $region_name; break; } $first_region_num = $last_region_num+1; } if (substr($egn,8,1) % 2 != 0) $region--; $ret["birthnumber"] = ($region - $first_region_num) / 2 + 1; return $ret; } /* Return text with EGN info */ function egn_info($egn) { if (!egn_valid($egn)) { return "" . htmlspecialchars($egn) ." невалиден ЕГН"; } $data = egn_parse($egn); $ret = "".htmlspecialchars($egn)." е ЕГН на {$data['sex_text']}, "; $ret .= "роден".($data["sex"]?"а":"")." на {$data['birthday_text']} в "; $ret .= "регион {$data['region_text']} "; if ($data["birthnumber"]-1) { $ret .= "като преди ".($data["sex"]?"нея":"него")." "; if ($data["birthnumber"]-1 > 1) { $ret .= "в този ден и регион са се родили ".($data["birthnumber"]-1).""; $ret .= $data["sex"]?" момичета":" момчета"; } else { $ret .= "в този ден и регион се е родило 1"; $ret .= $data["sex"]?" момиче":" момче"; } } else { $ret .= "като е ".($data["sex"]?"била":"бил")." "; $ret .= "първото ".($data["sex"]?" момиче":" момче")." "; $ret .= "родено в този ден и регион"; } return $ret; } /* Generate EGN. When parameter is 0 || false it is randomized */ function egn_generate($day=0,$mon=0,$year=0,$sex=0,$region=false) { global $EGN_WEIGHTS; global $EGN_REGIONS_FIRST_NUM; $day = $day > 0 ? min($day, 31) : ($day < 0 ? 0 : $day); $mon = $mon > 0 ? min($mon, 12) : ($mon < 0 ? 0 : $mon); $year= $year > 1799 ? min($year, 2099) : ($year == 0 ? $year : 1800); $region = isset($EGN_REGIONS_FIRST_NUM[$region]) ? $region : false; $iter = 0; do { $gday = $day ? $day : rand(1,31); $gmon = $mon ? $mon : rand(1,12); $gyear = $year ? $year : rand(1900,2010); $iter++; } while (!checkdate($gmon, $gday, $gyear) && $iter < 3); $cent = $gyear-($gyear % 100); if ($iter > 3) return false; /* Fixes for other centuries */ switch ($cent) { case 1800: $gmon += 20; break; case 2000: $gmon += 40; break; } /* Generate region/sex */ if ($region === false) $gregion = rand(0,999); else $gregion = rand($region,$EGN_REGIONS_FIRST_NUM[$region]); /* Make it odd */ if ($sex == 1 && ($gregion % 2 != 0)) $gregion--; /* Make it even */ if ($sex == 2 && ($gregion % 2 == 0)) $gregion++; /* Create EGN */ $egn = str_pad($gyear-$cent, 2, "0", STR_PAD_LEFT) . str_pad($gmon, 2, "0", STR_PAD_LEFT) . str_pad($gday, 2, "0", STR_PAD_LEFT) . str_pad($gregion, 3, "0", STR_PAD_LEFT); /* Calculate checksum */ $egnsum = 0; for ($i=0;$i<9;$i++) $egnsum += substr($egn,$i,1) * $EGN_WEIGHTS[$i]; $valid_checksum = $egnsum % 11; if ($valid_checksum == 10) $valid_checksum = 0; $egn .= $valid_checksum; return $egn; } /* ********************************************************************* */ /* *************************** Example usage *************************** */ /* ********************************************************************* */ if (isset($_SERVER["PATH_INFO"]) && $_SERVER["PATH_INFO"] == "/view/" ) { show_source("egn.php"); exit; } if (isset($_SERVER["PATH_INFO"]) && $_SERVER["PATH_INFO"] == "/get/" ) { header("Content-Type: text/plain; charset=UTF-8"); header("Content-Disposition: attachment; filename=egn.php.txt"); readfile("egn.php"); exit; } header("Content-type: text/html; charset=UTF-8"); ?>
Алгоритъмът за валидация на единен граждански номер (ЕГН) е публичен и е публикуван на официалния сайт на ЕСГРАОН. Кодът на страницата е базиран на този алгоритъм плюс данните за статистическото разпределение на ражданията по региони. В кода няма нищо тайнствено. Дори и без наличието този ЕГН генератор/валидатор, всеки с елементарни познания по математика и с публичната информация от страницата на ЕСГРАОН може да валидира и генерира ЕГН.
Ако сте убедени, че сте роден(а) в даден регион, а проверката тук показва друг, не е задължително това да е грешка. В системата ЕСГРАОН, когато се родят твърде много деца в даден регион и ден, се използват номера "на заем" от друг регион. Броят на отпуснатите раждания за ден е определен по статистически принцип за всеки регион. Например за регион Пазарджик са предвидени 36 номера, което значи, че ако се родят повече от 18 момчета или момичета в един ден, за последните в полето регион на ЕГН няма да е отбелязан Пазарджик. На регион по колко раждания за ден са отредени, можете да видите като в секцията "Генериране на ЕГН по заявка" изберете региона и след това бутона Генерирай ЕГН.
Друг/Неизвестен регион се ползва по различни причини без определен принцип, доколкото ми е известно.
Информация за ЕГН: "; print egn_info($egn); print "\n"; } ?>Ако вашият ЕГН не се появи в списъка на генерираните, не се стряскайте! Генераторът вади на случаен принцип номера, които отговарят на зададените критерии. За всеки регион на ден са предвидени повече от едно раждания, а на всяко родено дете трябва да се даде валидно ЕГН. Ако държите да видите своят номер в списъка, просто увеличете броят на генерираните номера.
0 ? min($day, 31) : ($day < 0 ? 0 : $day); $mon = $mon > 0 ? min($mon, 12) : ($mon < 0 ? 0 : $mon); $year= $year > 1799 ? min($year, 2099) : ($year == 0 ? $year : 1800); $use_region = !isset($EGN_REGIONS_LAST_NUM[$region]) ? false : $EGN_REGIONS_LAST_NUM[$region]; if (@$_GET["a"] == "gen") { print "";
if (!($use_region === false)) {
$max = $region-$EGN_REGIONS_LAST_NUM[$region]+1;
$max2 = $max / 2;
print "В регион ".array_search($region, $EGN_REGIONS)." са предвидени номера за ";
print "{$max} раждания в един ден ({$max2} момчета и {$max2} момичета).
";
} else {
print "Изберете регион, за да видите колко раждания са предвидени за него.
";
}
print "Генерирани ЕГН:
Вижте изходния код на програмата
Автор Георги Чорбаджийски. За коментари и предложения пишете в Дневника.
<- Към страничката на Георги