unit MedProcLib;
// для медучреждений
interface
uses SysUtils, SVAProcLib;
function ControlDs(d:string):boolean;
function CorrDs(var s:string):boolean;
procedure DivFIO(FIO:string; var F,I,O:string);
function Control_FIO(var s:string):boolean;
function ControlFIO(var s:string; Style:byte; Digit:boolean):boolean;
function OtToPol(s:string):string;
function ControlSNILS(var s:string):boolean;
function CheckSNILS(s:string):boolean;
function FullControlSNILS(s:string):boolean;
function ControlINN(s:string):boolean;
implementation
{ ----- Контроль (строгий) кода диагноза ----- }
function ControlDs(d:string):boolean;
var j:integer;
begin
Result:= false;
if d = '' then exit;
if not (d[1] in ['A'..'Z']) then exit;
j:= 2;
if d[2] = ' ' then j:= 3; // отс. нач-ся 1-я пара цифр
try
StrToInt(Copy(d,j,2)); // 1-я пара цифр
except
exit
end;
if length(d) = j+1 then begin
Result:= true; exit
end;
if d[j+2] <> '.' then exit;
inc(j,3);
if length(d) < j then begin
Result:= true; exit
end;
try
StrToInt(Copy(d, j, length(d)+1-j)); // второе число
Result:= true;
except
end;
end;
{ --- Контроль и авто-корректировка КОДА ДИАГНОЗА --- }
function CorrDs(var s:string):boolean;
var d: string[7];
begin
Result:= false; // автокорректировке не поддается
if s = '' then exit;
d:= AnsiUpperCase(s);
if not (d[1] in ['A'..'Z','А','В','Е','К','М','Н','О','Р','С','Т','У','Х'])
then exit; { - совсем некорректные буквы }
if not(d[1] in ['A'..'Z']) then
{ рус --> lat }
case d[1] of
'А': d[1]:='A';
'В': d[1]:='B';
'Е': d[1]:='E';
'К': d[1]:='K';
'М': d[1]:='M';
'Н': d[1]:='H';
'О': d[1]:='O';
'Р': d[1]:='P';
'С': d[1]:='C';
'Т': d[1]:='T';
'У': d[1]:='Y';
'Х': d[1]:='X';
end;
s[1]:= d[1]; { - с буквой разобрались }
if length(s) = 1 then exit;
if s[2] = ' ' then
delete(s,2,1); { - убрали необязательный пробел }
if length(s) = 2 then insert('0',s,2);
if not ControlNumber(Copy(s,2,2), 2) then exit;
if length(s)= 3 then begin
Result:= true;
exit; { A99 }
end;
if s[4] <> '.' then
if (s[4] in ['0'..'9']) then exit
else s[4]:= '.';
if length(s) = 4 then begin
SetLength(s,3);
Result:= true;
exit { A99.-> A99 - точку удаляем ! }
end;
if length(s) > 6 then exit;
if length(s) > 4 then
if not ControlNumber(Copy(s,5,2), 0) then exit;
Result:= true // автокорректировка удалась
end; { CorrDs }
{ ------ Извлечение Ф. И. О. из строки FIO ------ }
// для простого случая - когда фамилия (имя) без пробелов внутри
procedure DivFIO(FIO:string; var F,I,O:string);
var s: string; k,p: integer;
begin
F:= ''; I:= ''; O:= '';
s:= Trim(FIO);
Del2Space(s);
// поверим, чтобы после точки был пробел (или вставим его)
k:= pos('.', s);
while (k > 0) and (k < length(s)) do begin
p:= k+1;
if not(s[p] in [' ', '-']) then insert(' ', s, p);
k:= Find('.', s, p);
end;
k:= pos(' ', s);
if k > 0 then begin
F:= Copy(s, 1, k-1);
delete(s,1,k);
k:= pos(' ', s);
if k > 0 then begin
I:= Copy(s, 1, k-1);
delete(s,1,k);
O:= s
end
else I:= s;
end
else F:= s
end;
{ ---- Ищем 1-й из 3-х символов в строке ---- }
function Pos3(c1,c2,c3:char; s:string; var c:char):integer; // local
var k1, k2, k3: integer;
begin
Result:= 0;
k1:= pos(c1, s);
k2:= pos(c2, s);
k3:= pos(c3, s);
if (k1 = 0) and (k2 = 0) and (k3 = 0) then exit;
if (k1 > 0) and (k2 = 0) and (k3 = 0) then Result:= k1
else if (k1 = 0) and (k2 > 0) and (k3 = 0) then Result:= k2
else if (k1 = 0) and (k2 = 0) and (k3 > 0) then Result:= k3
else if k1 = 0 then Result:= Min2(k2, k3)
else if k2 = 0 then Result:= Min2(k1, k3)
else if k3 = 0 then Result:= Min2(k1, k2)
else Result:= Min2(Min2(k1,k2), k3);
if Result = k1 then c:= c1
else if Result = k2 then c:= c2
else if Result = k3 then c:= c3
end;
{ ---- Ищем 1-й из 2-х символов в строке ---- }
function Pos2(c1,c2:char; s:string; var c:char):integer; // local
var k1, k2: integer;
begin
Result:= 0;
k1:= pos(c1, s);
k2:= pos(c2, s);
if (k1 = 0) and (k2 = 0) then exit;
if (k1 > 0) and (k2 = 0) then Result:= k1
else if (k1 = 0) and (k2 > 0) then Result:= k2
else Result:= Min2(k1, k2);
if Result = k1 then c:= c1
else if Result = k2 then c:= c2
end;
{ ======= Контроль Ф.И.О. ======== }
function Control_FIO(var s:string):boolean;
// допускаются внутри "-" и " " (пробел)
var
ff,f,st: string; k: integer; c: char;
function f1(var f:string):boolean; // одиночное имя
var
i: integer; a: string;
begin
if f = '' then begin
Result:= true; exit
end;
Result:= false;
a:= AnsiUpperCase(f);
for i:= 1 to length(a) do
if not(a[i] in ['А'..'Я','Ё']) then exit;
f:= AnsiLowerCase(f);
f[1]:= a[1];
if f[1] = ' ' then f[2]:= a[2];
Result:= true;
end;
begin { ControlFIO }
Result:= false;
s:= Trim(s);
if s = '' then begin
Result:= true; exit; // пустое не проверяем
end;
Del2Space(s);
Del2Minus(s);
// ' - ', '- ', ' -' => '-'
while pos(' -', s) > 0 do delete(s, pos(' -',s), 1);
while pos('- ', s) > 0 do delete(s, pos('- ',s) + 1, 1);
f:= s; // рабочая (изменяемая часть)
ff:= ''; // готовая часть (в конце ff => s )
k:= pos2('-', ' ', f, c);
try
while k > 0 do begin
st:= Copy(f, 1, k-1);
if not f1(st) then exit; // часть имени до "-"
if ff = '' then ff:= st + c // это первая часть имени
else ff:= ff + st + c;
delete(f,1,k); // удаляем проверенную часть
k:= pos2('-', ' ', f, c);
end;
if not f1(f) then exit;
if ff = '' then ff:= f // было одиночное имя
else ff:= ff + f;
k:= pos('-Оглы', ff); if k > 0 then ff[k+1]:='о';
k:= pos('-Кызы', ff); if k > 0 then ff[k+1]:='к';
except
exit;
end;
s:= ff;
Result:=true
end;
{ ------- Контроль Ф.И.О. -------- }
// к "-" добавлено ".", " ", "'"
function ControlFIO(var s:string; Style:byte; Digit:boolean):boolean;
// Style: 0 - удобные (Фам Имя Отч), 1 - Прописные, 2 - Не изменять
// если Digit=true - разрешается использовать цифры
var ff,f,st: string; k: integer; c:char;
function f1(var f:string):boolean; // одиночное имя
var
i: integer; a,b: string;
GoodChar: set of char;
begin
if f = '' then begin
Result:= true; exit
end;
Result:= false;
b:= f;
a:= AnsiUpperCase(f);
GoodChar:= [#39,'А'..'Я','Ё'];
if Digit then GoodChar:= GoodChar + ['0'..'9'];
for i:= 1 to length(a) do
if not(a[i] in GoodChar) then exit;
Result:= true;
if Style = 2 then exit; // ничего не измен. - только провер.
if Style = 1 then begin
f:= a; exit // все буквы прописные
end;
f:= AnsiLowerCase(f);
f[1]:= a[1];
if f[1] = ' ' then f[2]:= a[2];
i:= pos(#39, a);
if (i > 0) and (i < length(f)) then begin
if f[i+1] <> #39 then f[i+1]:= b[i+1]
else if i+2 <= length(f) then f[i+2]:= b[i+2];
end;
if i > 1 then f[i-1]:= b[i-1];
Result:= true;
end;
begin
Result:= false;
s:= Trim(s);
if s = '' then begin
Result:= true; exit; // пустое не проверяем
end;
Del2Space(s);
Del2Minus(s);
// ' - ', '- ', ' -' => '-'
while pos(' -', s) > 0 do delete(s, pos(' -',s), 1);
while pos('- ', s) > 0 do delete(s, pos('- ',s) + 1, 1);
while pos(' .', s) > 0 do delete(s, pos(' .',s), 1);
k:= pos(' '' ', s); // O ' Hen => O'Hen
while k > 0 do begin
delete(s, k, 1);
delete(s, k+1, 1);
k:= pos(' '' ', s);
end;
f:= s; // рабочая (изменяемая часть)
ff:= ''; // готовая часть (в конце ff => s )
if Digit then k:= pos3('-', '.', ' ', f, c) // там где цифры, там и точка
else k:= pos2('-', ' ', f, c);
try
while k > 0 do begin
st:= Copy(f, 1, k-1);
if not f1(st) then exit; // часть имени до "-"
if ff = '' then ff:= st + c // это первая часть имени
else ff:= ff + st + c;
delete(f,1,k); // удаляем проверенную часть
if Digit then k:= pos3('-', '.', ' ', f, c)
else k:= pos2('-', ' ', f, c);
end;
if not f1(f) then exit;
if ff = '' then ff:= f // было одиночное имя
else ff:= ff + f;
if Style = 0 then begin
k:= pos('-Оглы', ff); if k > 0 then ff[k+1]:='о';
k:= pos('-Кызы', ff); if k > 0 then ff[k+1]:='к';
end;
except
exit;
end;
s:= ff;
Result:=true
end;
{ --- По отчеству определить пол --- }
function OtToPol(s:string):string;
var so: string;
begin
Result:= '';
if length(s) < 3 then exit;
so:= Copy(s, length(s)-1, 2);
if (so = 'ич') or (so = 'лы') then Result:='М'
else begin
so:= Copy(s, length(s)-2, 3);
if (so = 'вна') or (so = 'чна') or (so = 'ызы') then Result:='Ж';
end
end;
{ ======= Контроль формата СНИЛСа ======== }
function ControlSNILS(var s:string):boolean;
var i:integer;
begin
Result:= false;
if length(s) <> 14 then exit;
for i:= 1 to 14 do
case i of
4,8: if s[i] in ['0'..'9'] then exit
else s[i]:= '-';
12: if s[i] in ['0'..'9'] then exit
else s[i]:= ' ';
else if not(s[i] in ['0'..'9']) then exit;
end; { case }
Result:= true;
end;
{ ======= Контроль кода СНИЛСа ======== }
{ после ControlSNILS }
function CheckSNILS(s:string):boolean;
var i,sum:integer; sNum: string;
begin
sNum:= Copy(s,1,11); Delete(sNum,8,1); Delete(sNum,4,1);
sum:= 0;
for i:= 1 to 9 do
sum:= sum + (ord(sNum[i]) - 48) * (10 - i);
Result:= (sum mod 101) mod 100 = StrToInt(Copy(s,13,2));
end;
{ ======= Полный контроль СНИЛСа ======== }
function FullControlSNILS(s:string):boolean;
begin
Result:= false;
if ControlSNILS(s) then
Result:= CheckSNILS(s)
end;
{ ======= Контроль ИНН ======== }
function ControlINN(s:string):boolean;
begin
if not(length(s) in [10,12]) then Result:=false
else Result:= ControlNumber(s, length(s))
end;
end.
