handle static method
Implementation
static OcrMrzResult? handle(OcrData ocr, void Function(OcrMrzLog log)? mrzLogger) {
OcrMrzValidation validation = OcrMrzValidation();
DocumentStandardType? type;
String? format;
String? docNumber;
String? firstName;
String? lastName;
DateTime? birthDate;
DateTime? expiryDate;
DateTime? issueDate;
String? countryCode;
String? nationality;
String? issuing;
String? docCode;
String? sex;
String? optional;
MrzName? name;
String finalCheckValue = "";
List<String> rawLines = ocr.lines.map((a) => a.text).toList();
List<String> rawMrzLines = [];
List<String> otherLines = [];
if (rawLines.any((a) => a.contains("<<"))) {
String firstLine = rawLines.firstWhere((a) => a.contains("<<"));
int firstLineIndex = rawLines.indexOf(firstLine);
rawMrzLines.add(firstLine);
if (firstLineIndex < rawLines.length - 1) {
String secondLine = rawLines[firstLineIndex + 1];
rawMrzLines.add(secondLine);
}
if (firstLineIndex < rawLines.length - 2) {
String thirdLine = rawLines[firstLineIndex + 2];
if (thirdLine.contains("<")) {
rawMrzLines.add(thirdLine);
}
}
List<String> fixedMrzLines;
if (rawMrzLines.length < 3) {
if (rawMrzLines.first.length > 40) {
type = DocumentStandardType.td3;
format = "td3";
fixedMrzLines = rawMrzLines.map((a) => normalize(a, len: 44)).toList();
} else {
type = DocumentStandardType.td2;
format = "td2";
fixedMrzLines = rawMrzLines.map((a) => normalize(a, len: 36)).toList();
}
} else {
format = "td1";
type = DocumentStandardType.td1;
fixedMrzLines = rawMrzLines.map((a) => normalize(a, len: 30)).toList();
}
log("\n${fixedMrzLines.join("\n")}");
otherLines = [...rawLines].where((a) => !rawMrzLines.contains(a)).toList();
if (fixedMrzLines.length < 2) return null;
validation.linesLengthValid = true;
final firstLineFixed = fixedMrzLines.first;
final secondLineFixed = fixedMrzLines[1];
docCode = firstLineFixed.substring(0, 2);
countryCode = firstLineFixed.substring(2, 5);
issuing = firstLineFixed.substring(2, 5);
validation.docCodeValid = DocumentCodeHelper.isValid(docCode);
validation.countryValid = isValidMrzCountry(countryCode);
if(!validation.countryValid){
log("country $countryCode is not valid");
}
final mrzDatesSex = RegExp(r'(\d{6})(\d)([MFX<])(\d{6})(\d)', caseSensitive: false);
final dateSexMatch = mrzDatesSex.firstMatch(secondLineFixed);
if (dateSexMatch != null) {
final birthDateStr = dateSexMatch.group(1);
final birthCheck = dateSexMatch.group(2);
final sexStr = dateSexMatch.group(3);
final expiryDateStr = dateSexMatch.group(4);
final expiryCheck = dateSexMatch.group(5);
validation.birthDateValid = _computeMrzCheckDigit(birthDateStr!) == birthCheck;
validation.expiryDateValid = _computeMrzCheckDigit(expiryDateStr!) == expiryCheck;
birthDate = _parseMrzDate(birthDateStr);
expiryDate = _parseMrzDate(expiryDateStr);
sex = sexStr;
}
if (type == DocumentStandardType.td3) {
final td3DocNumber = RegExp(r'^([A-Z0-9<]{9})(\d)', caseSensitive: false);
final td3DocNumberMatch = td3DocNumber.firstMatch(secondLineFixed);
if (td3DocNumberMatch != null) {
final docNumberStr = td3DocNumberMatch.group(1);
final docNumberCheckStr = td3DocNumberMatch.group(2);
docNumber = docNumberStr;
validation.docNumberValid = _computeMrzCheckDigit(docNumberStr ?? '') == docNumberCheckStr;
finalCheckValue += docNumberStr ?? '';
finalCheckValue += docNumberCheckStr ?? '';
}
final td3Nationality = RegExp(r'^[A-Z0-9<]{10}([A-Z0-9<]{3})', caseSensitive: false);
final td3NationalityMatch = td3Nationality.firstMatch(secondLineFixed);
if (td3NationalityMatch != null) {
final nationalityStr = fixAlphaOnlyField(td3NationalityMatch.group(1)!);
nationality = nationalityStr;
validation.nationalityValid = isValidMrzCountry(nationalityStr);
}
if(!validation.docNumberValid){
final oldFixes = parseOldNumNat(secondLineFixed);
if(oldFixes.length == 2){
docNumber = oldFixes[0];
nationality = oldFixes[1];
validation.docNumberValid = true;
validation.nationalityValid = true;
}
}
if (dateSexMatch != null) {
finalCheckValue += stripSexFromDateSex(dateSexMatch.group(0)!);
}
final td3OptionalFinal = RegExp(r'^.{28}([A-Z0-9<]{15})(\d)$', caseSensitive: false);
final td3OptionalFinalMatch = td3OptionalFinal.firstMatch(secondLineFixed);
if (td3OptionalFinalMatch != null) {
final optionalStr = td3OptionalFinalMatch.group(1);
final finalCheckStr = td3OptionalFinalMatch.group(2);
optional = optionalStr;
finalCheckValue += (optionalStr ?? '');
validation.personalNumberValid = true;
validation.hasFinalCheck = true;
validation.finalCheckValid = _computeMrzCheckDigit(finalCheckValue) == finalCheckStr;
final issueDateMatch = issueDateYYMMDD.firstMatch(optionalStr??'');
if (issueDateMatch != null) {
final issueDateStr = issueDateMatch.group(0); // "220620"
issueDate = _parseMrzDate(issueDateStr!);
}
}
name = parseNamesTd3OrTd2(firstLineFixed);
} else if (type == DocumentStandardType.td2) {
final td2DocNumber = RegExp(r'^([A-Z0-9<]{9})(\d)', caseSensitive: false);
final td2DocNumberMatch = td2DocNumber.firstMatch(secondLineFixed);
if (td2DocNumberMatch != null) {
final docNumberStr = td2DocNumberMatch.group(1);
final docNumberCheckStr = td2DocNumberMatch.group(2);
docNumber = docNumberStr;
validation.docNumberValid = _computeMrzCheckDigit(docNumberStr ?? '') == docNumberCheckStr;
finalCheckValue += (docNumberStr ?? '');
finalCheckValue += (docNumberCheckStr ?? '');
}
final td2Nationality = RegExp(r'^[A-Z0-9<]{10}([A-Z<]{3})', caseSensitive: false);
final td2NationalityMatch = td2Nationality.firstMatch(secondLineFixed);
if (td2NationalityMatch != null) {
final nationalityStr = fixAlphaOnlyField(td2NationalityMatch.group(1)!);
nationality = nationalityStr;
validation.nationalityValid = isValidMrzCountry(nationalityStr);
finalCheckValue += nationalityStr;
}
if (dateSexMatch != null) {
finalCheckValue += dateSexMatch.group(0)!;
}
final td2OptionalFinal = RegExp(r'^.{28}([A-Z0-9<]{7})(\d)$', caseSensitive: false);
final td2OptionalFinalMatch = td2OptionalFinal.firstMatch(secondLineFixed);
if (td2OptionalFinalMatch != null) {
final optionalStr = td2OptionalFinalMatch.group(1);
final finalCheckStr = td2OptionalFinalMatch.group(2);
if (docCode.startsWith("V")) {
validation.hasFinalCheck = true;
validation.personalNumberValid = true;
validation.finalCheckValid = true;
} else {
optional = optionalStr;
finalCheckValue += (optionalStr ?? '');
validation.personalNumberValid = true;
validation.hasFinalCheck = true;
validation.finalCheckValid = _computeMrzCheckDigit(finalCheckValue) == finalCheckStr;
final issueDateMatch = issueDateYYMMDD.firstMatch(optionalStr??'');
if (issueDateMatch != null) {
final issueDateStr = issueDateMatch.group(0);
issueDate = _parseMrzDate(issueDateStr!);
}
}
}
name = parseNamesTd3OrTd2(firstLineFixed);
} else if (type == DocumentStandardType.td1) {
docNumber = firstLineFixed.substring(5, 14);
final docNumberCheck = firstLineFixed[14];
validation.docNumberValid = _computeMrzCheckDigit(docNumber) == docNumberCheck;
finalCheckValue += firstLineFixed.substring(5, 30);
if (dateSexMatch != null) {
finalCheckValue += stripSexFromDateSex(dateSexMatch.group(0)!);
}
final td1Nationality = RegExp(r'^.{15}([A-Z<]{3})', caseSensitive: false);
final td1NationalityMatch = td1Nationality.firstMatch(secondLineFixed);
if (td1NationalityMatch != null) {
final nationalityStr = fixAlphaOnlyField(td1NationalityMatch.group(1)!);
nationality = nationalityStr;
validation.nationalityValid = isValidMrzCountry(nationalityStr);
}
final td1OptionalFinal = RegExp(r'^.{18}([A-Z0-9<]{11})(\d)$', caseSensitive: false);
final td1OptionalFinalMatch = td1OptionalFinal.firstMatch(secondLineFixed);
if (td1OptionalFinalMatch != null) {
final optionalStr = td1OptionalFinalMatch.group(1);
final finalCheckStr = td1OptionalFinalMatch.group(2);
optional = optionalStr;
final issueDateMatch = issueDateYYMMDD.firstMatch(optionalStr??'');
if (issueDateMatch != null) {
final issueDateStr = issueDateMatch.group(0);
issueDate = _parseMrzDate(issueDateStr!);
}
finalCheckValue += (optionalStr ?? '');
validation.personalNumberValid = true;
validation.hasFinalCheck = true;
validation.finalCheckValid = _computeMrzCheckDigit(finalCheckValue) == finalCheckStr;
}
String nameLine = fixedMrzLines.last;
name = parseNamesTd1(nameLine);
}
if (name != null) {
firstName = name.givenNames.join(" ");
lastName = name.surname;
validation.nameValid = name.validateNames(otherLines,OcrMrzSetting(nameValidationMode: NameValidationMode.exact),[]).$1;
}
log(validation.toString());
log("-" * 100);
OcrMrzResult result = OcrMrzResult(
line1: firstLineFixed,
line2: secondLineFixed,
format: format,
documentCode: docCode,
documentType: type.name.toUpperCase(),
mrzFormat: format,
issueDate: issueDate,
countryCode: fixExceptionalCountry(countryCode),
issuingState: fixExceptionalCountry(issuing),
lastName: lastName ?? '',
firstName: firstName ?? '',
documentNumber: docNumber?.replaceAll("<", "") ?? '',
nationality: fixExceptionalCountry(nationality ?? ''),
birthDate: birthDate,
expiryDate: expiryDate,
sex: sex ?? '',
personalNumber: optional ?? '',
optionalData: optional ?? '',
valid: validation,
checkDigits: CheckDigits(document: true, birth: true, expiry: true, optional: true),
ocrData: ocr,
);
mrzLogger?.call(OcrMrzLog(rawText: ocr.text, rawMrzLines: rawMrzLines, fixedMrzLines: fixedMrzLines, validation: validation, extractedData: result.toJson()));
return result;
} else {
// log("No Ocr");
}
return null;
}