From 13e7b429b19f7a3f76d0ea763d202e4281978197 Mon Sep 17 00:00:00 2001 From: artemtarasov Date: Fri, 23 Jan 2026 16:07:04 +0300 Subject: [PATCH 1/2] [fix] Fix keyword part by added right conditions --- gradle.properties | 2 +- .../org/angryscan/common/matchers/DODID.kt | 18 ++++++++- .../common/matchers/DriverLicense.kt | 14 +++++-- .../angryscan/common/matchers/EducationDoc.kt | 14 +++++-- .../angryscan/common/matchers/MedicareUS.kt | 20 ++++++++++ .../angryscan/common/matchers/MilitaryID.kt | 14 +++++-- .../org/angryscan/common/matchers/OGRNIP.kt | 14 +++++-- .../org/angryscan/common/matchers/OKPO.kt | 14 +++++-- .../org/angryscan/common/matchers/OMS.kt | 14 +++++-- .../angryscan/common/matchers/OSAGOPolicy.kt | 14 +++++-- .../org/angryscan/common/matchers/Passport.kt | 10 ++--- .../angryscan/common/matchers/PassportUS.kt | 20 ++++++++++ .../common/matchers/ResidencePermit.kt | 14 +++++-- .../org/angryscan/common/matchers/SberBook.kt | 37 ++++++++++++++++++- .../org/angryscan/common/matchers/TCN.kt | 18 ++++++++- .../common/matchers/VehicleRegNumber.kt | 14 +++++-- .../org/angryscan/common/engine/EngineTest.kt | 3 +- .../angryscan/common/matchers/DODIDTest.kt | 6 --- .../common/matchers/DriverLicenseTest.kt | 24 ------------ .../common/matchers/EducationDocTest.kt | 6 --- .../common/matchers/MilitaryIDTest.kt | 6 --- .../angryscan/common/matchers/OGRNIPTest.kt | 6 --- .../org/angryscan/common/matchers/OKPOTest.kt | 6 --- .../org/angryscan/common/matchers/OMSTest.kt | 12 ------ .../common/matchers/OSAGOPolicyTest.kt | 6 --- .../common/matchers/ResidencePermitTest.kt | 24 ------------ .../org/angryscan/common/matchers/TCNTest.kt | 6 --- .../common/matchers/VehicleRegNumberTest.kt | 6 --- 28 files changed, 204 insertions(+), 158 deletions(-) diff --git a/gradle.properties b/gradle.properties index e79ca70..a7a6009 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ #Kotlin kotlin.code.style=official -version=1.4.7 \ No newline at end of file +version=1.4.8 \ No newline at end of file diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DODID.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DODID.kt index ac3e168..329f198 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DODID.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DODID.kt @@ -34,7 +34,14 @@ object DODID : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - return javaPatterns + return if (requireKeywords) { + javaPatterns + } else { + // Return pattern without keywords as fallback + listOf( + """(?ix)(? { - return hyperPatterns + return if (requireKeywords) { + hyperPatterns + } else { + // Return pattern without keywords as fallback + listOf( + """(?:^|[^0-9a-zA-Z])[0-9]{10}(?:[^0-9a-zA-Z]|$)""" + ) + } } override val expressionOptions = setOf( diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DriverLicense.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DriverLicense.kt index 2a00ff5..7cabcbc 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DriverLicense.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DriverLicense.kt @@ -41,8 +41,11 @@ object DriverLicense : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for driver license to avoid false positives - val keywordsPart = """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)""" + val keywordsPart = if (requireKeywords) { + """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)""" + } else { + """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)?""" + } return listOf( """ (?ix) @@ -65,8 +68,11 @@ object DriverLicense : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for driver license to avoid false positives - val keywordsPart = """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)""" + val keywordsPart = if (requireKeywords) { + """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)""" + } else { + """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)?""" + } return listOf( """(?:^|[\s\(\[\{«"'])$keywordsPart\s*[:\-]?\s*\d{2}\s\d{2}\s\d{6}(?:[^0-9a-zA-ZА-ЯЁа-яё]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/EducationDoc.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/EducationDoc.kt index 65d012c..7d1c549 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/EducationDoc.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/EducationDoc.kt @@ -58,8 +58,11 @@ object EducationDoc : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for education documents to avoid false positives - val keywordsPart = """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)""" + val keywordsPart = if (requireKeywords) { + """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)""" + } else { + """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)?""" + } return listOf( """ (?ix) @@ -90,8 +93,11 @@ object EducationDoc : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for education documents to avoid false positives - val keywordsPart = """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)""" + val keywordsPart = if (requireKeywords) { + """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)""" + } else { + """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)?""" + } return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*\d{6}\s+\d{7}(?:[^\w]|$)""", """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*\d{2}\s+[А-ЯЁ]{2}\s+\d{6,7}(?:[^\w]|$)""" diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MedicareUS.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MedicareUS.kt index d4a421d..622a248 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MedicareUS.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MedicareUS.kt @@ -18,6 +18,16 @@ object MedicareUS : IHyperMatcher, IKotlinMatcher { """(?i)(?:medicare|mbi|health\s*insurance|medical\s*insurance)(?:\s*[:\-#]\s*|\s+)([0-9][a-z0-9]{3}[\s\t\-]*[a-z0-9]{3}[\s\t\-]*[a-z0-9]{4})(?:[^a-zA-Z0-9]|$)""", """(?:^|[^a-zA-Z0-9])([0-9][a-z0-9]{3}[\s\t\-]*[a-z0-9]{3}[\s\t\-]*[a-z0-9]{4})(?:[^a-zA-Z0-9]|$)""" ) + + override fun getJavaPatterns(requireKeywords: Boolean): List { + return if (requireKeywords) { + // Return only pattern with keywords (more strict, reduces false positives) + listOf(javaPatterns[0]) + } else { + // Return both patterns (with and without keywords) + javaPatterns + } + } override val regexOptions = setOf( RegexOption.IGNORE_CASE, RegexOption.MULTILINE @@ -27,6 +37,16 @@ object MedicareUS : IHyperMatcher, IKotlinMatcher { """(?:medicare|mbi|health\s*insurance|medical\s*insurance)(?:\s*[:\-#]\s*|\s+)[0-9][a-z0-9]{3}[\s\t\-]*[a-z0-9]{3}[\s\t\-]*[a-z0-9]{4}(?:[^a-zA-Z0-9]|$)""", """(?:^|[^a-zA-Z0-9])[0-9][a-z0-9]{3}[\s\t\-]*[a-z0-9]{3}[\s\t\-]*[a-z0-9]{4}(?:[^a-zA-Z0-9]|$)""" ) + + override fun getHyperPatterns(requireKeywords: Boolean): List { + return if (requireKeywords) { + // Return only pattern with keywords (more strict, reduces false positives) + listOf(hyperPatterns[0]) + } else { + // Return both patterns (with and without keywords) + hyperPatterns + } + } override val expressionOptions = setOf( ExpressionOption.MULTILINE, ExpressionOption.CASELESS, diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MilitaryID.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MilitaryID.kt index 10ae1e4..4d07f96 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MilitaryID.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MilitaryID.kt @@ -41,8 +41,11 @@ object MilitaryID : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for military ID to avoid false positives - val keywordsPart = """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)""" + val keywordsPart = if (requireKeywords) { + """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)""" + } else { + """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)?""" + } return listOf( """ (?ix) @@ -65,8 +68,11 @@ object MilitaryID : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for military ID to avoid false positives - val keywordsPart = """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)""" + val keywordsPart = if (requireKeywords) { + """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)""" + } else { + """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)?""" + } return listOf( """(?:^|[\s\r\n\(\)\"\'\[\]\{\};,.:\.!?])$keywordsPart\s*[:\-]?\s*[А-ЯA-Z]{2}[\s№\-]*\d{7}\b""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OGRNIP.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OGRNIP.kt index 4dfc276..25b6c5e 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OGRNIP.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OGRNIP.kt @@ -41,8 +41,11 @@ object OGRNIP : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for OGRNIP to avoid false positives - val keywordsPart = """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)""" + val keywordsPart = if (requireKeywords) { + """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)""" + } else { + """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)?""" + } return listOf( """ (?ix) @@ -65,8 +68,11 @@ object OGRNIP : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for OGRNIP to avoid false positives - val keywordsPart = """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)""" + val keywordsPart = if (requireKeywords) { + """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)""" + } else { + """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)?""" + } return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[34]\d{14}(?:[^\w]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OKPO.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OKPO.kt index 5054ae1..fe411e2 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OKPO.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OKPO.kt @@ -41,8 +41,11 @@ object OKPO : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for OKPO to avoid false positives - val keywordsPart = """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)""" + val keywordsPart = if (requireKeywords) { + """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)""" + } else { + """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)?""" + } return listOf( """ (?ix) @@ -66,8 +69,11 @@ object OKPO : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for OKPO to avoid false positives - val keywordsPart = """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)""" + val keywordsPart = if (requireKeywords) { + """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)""" + } else { + """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)?""" + } return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*\d{8}(?:[^\w]|$)""", """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*\d{10}(?:[^\w]|$)""" diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OMS.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OMS.kt index 7f851ea..52d9b3f 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OMS.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OMS.kt @@ -46,8 +46,11 @@ object OMS : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for OMS to avoid false positives (but exclude standalone "полис") - val keywordsPart = """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)""" + val keywordsPart = if (requireKeywords) { + """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)""" + } else { + """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)?""" + } return listOf( """ (?ix) @@ -70,8 +73,11 @@ object OMS : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for OMS to avoid false positives (but exclude standalone "полис") - val keywordsPart = """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)""" + val keywordsPart = if (requireKeywords) { + """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)""" + } else { + """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)?""" + } return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[0-9]{4}[\s\t-]*[0-9]{4}[\s\t-]*[0-9]{4}[\s\t-]*[0-9]{4}(?:[^\w]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OSAGOPolicy.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OSAGOPolicy.kt index f081965..2603f7d 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OSAGOPolicy.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OSAGOPolicy.kt @@ -41,8 +41,11 @@ object OSAGOPolicy : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for OSAGO policy to avoid false positives - val keywordsPart = """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)""" + val keywordsPart = if (requireKeywords) { + """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)""" + } else { + """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)?""" + } return listOf( """ (?ix) @@ -65,8 +68,11 @@ object OSAGOPolicy : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for OSAGO policy to avoid false positives - val keywordsPart = """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)""" + val keywordsPart = if (requireKeywords) { + """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)""" + } else { + """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)?""" + } return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[A-ZА-Я]{3}\s+№?\s*\d{10}(?:[^\w]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/Passport.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/Passport.kt index d2ba636..18adce9 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/Passport.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/Passport.kt @@ -26,9 +26,8 @@ object Passport : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for passport to avoid false positives - val passportPart = passportKeyword - val seriesPart = seriesKeyword + val passportPart = if (requireKeywords) passportKeyword else "$passportKeyword?" + val seriesPart = if (requireKeywords) seriesKeyword else "$seriesKeyword?" return listOf( """(? { - // Always require keywords for passport to avoid false positives - val passportPart = passportKeyword - val seriesPart = """[cс]ерия""" + val passportPart = if (requireKeywords) passportKeyword else "$passportKeyword?" + val seriesPart = if (requireKeywords) """[cс]ерия""" else """[cс]ерия?""" return listOf( """(?:^|[^а-яА-Яa-zA-Z0-9])($passportPart[ \t-]?([а-яА-Я]*[ \t-]){0,2}[0-9]{2}[ \t-]?[0-9]{2}[ \t-]?[0-9]{6})(?:[^а-яА-Яa-zA-Z0-9]|$)""", """(?:^|[^а-яА-Яa-zA-Z0-9])$seriesPart[ \t-]+[0-9]{2}[ \t-]+[0-9]{2}[ \t,]+номер[ \t-]+[0-9]{6}(?:[^а-яА-Яa-zA-Z0-9]|$)""", diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/PassportUS.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/PassportUS.kt index 7fc98a5..bcaa7eb 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/PassportUS.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/PassportUS.kt @@ -19,6 +19,16 @@ object PassportUS : IHyperMatcher, IKotlinMatcher { """(?i)(??/~`\\])(passport|pass(?:\.|\s*(?:no|number))?)\b[\s:=#"'()\[\]\{\}\-]*([A-Z][0-9]{8})(?![\d!@#$%^&*()_+=\[\]{}|;:'",.<>?/~`\\])""", """(??/~`\\])([A-Z][0-9]{8})(?![\d!@#$%^&*()_+=\[\]{}|;:'",.<>?/~`\\])""" ) + + override fun getJavaPatterns(requireKeywords: Boolean): List { + return if (requireKeywords) { + // Return only pattern with keywords (more strict, reduces false positives) + listOf(javaPatterns[0]) + } else { + // Return both patterns (with and without keywords) + javaPatterns + } + } override val regexOptions = setOf( RegexOption.IGNORE_CASE, RegexOption.MULTILINE @@ -28,6 +38,16 @@ object PassportUS : IHyperMatcher, IKotlinMatcher { """(?i)(?:^|[^a-zA-Z0-9!@#$%^&*()_+=\[\]{}|;:'",.<>?/~`\\])(passport|pass(?:\.|\s*(?:no|number))?)\b[\s:=#"'\(\)\[\]\{\}\-]*([A-Z][0-9]{8})(?:[^0-9!@#$%^&*()_+=\[\]{}|;:'",.<>?/~`\\]|$)""", """(?i)(?:^|[^a-zA-Z0-9!@#$%^&*()_+=\[\]{}|;:'",.<>?/~`\\])([A-Z][0-9]{8})(?:[^0-9!@#$%^&*()_+=\[\]{}|;:'",.<>?/~`\\]|$)""" ) + + override fun getHyperPatterns(requireKeywords: Boolean): List { + return if (requireKeywords) { + // Return only pattern with keywords (more strict, reduces false positives) + listOf(hyperPatterns[0]) + } else { + // Return both patterns (with and without keywords) + hyperPatterns + } + } override val expressionOptions = setOf( ExpressionOption.MULTILINE, ExpressionOption.CASELESS, diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/ResidencePermit.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/ResidencePermit.kt index 2393d2f..3a31466 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/ResidencePermit.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/ResidencePermit.kt @@ -42,8 +42,11 @@ object ResidencePermit : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for residence permit to avoid false positives - val keywordsPart = """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)""" + val keywordsPart = if (requireKeywords) { + """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)""" + } else { + """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)?""" + } return listOf( """ (?ix) @@ -66,8 +69,11 @@ object ResidencePermit : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for residence permit to avoid false positives - val keywordsPart = """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)""" + val keywordsPart = if (requireKeywords) { + """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)""" + } else { + """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)?""" + } return listOf( """(?:^|[^a-zA-Z0-9А-ЯЁа-яё])$keywordsPart\s*[:\-]?\s*(?:82|83)\s*(?:№|N)?\s*\d{7}(?:[^a-zA-Z0-9А-ЯЁа-яё]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SberBook.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SberBook.kt index bfbad27..bb2e624 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SberBook.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SberBook.kt @@ -18,20 +18,53 @@ object SberBook : IHyperMatcher, IKotlinMatcher { """ (?ix) (? { + val keywordsPart = if (requireKeywords) { + """(?:номер\s+сберкнижки|номер\s+сберегательной\s+книжки\s+ФЛ|счет\s+сберкнижки)""" + } else { + """(?:номер\s+сберкнижки|номер\s+сберегательной\s+книжки\s+ФЛ|счет\s+сберкнижки)?""" + } + return listOf( + """ + (?ix) + (? = listOf( - """(?:^|[^\p{L}\d])423\d{2}[\s\-]?\d{3}[\s\-]?\d{1}[\s\-]?\d{4}[\s\-]?\d{7}(?:[^\p{L}\d]|$)""" + // Simplified pattern for HyperScan (shorter keywords to avoid "Pattern is too large" error) + """(?:^|[^\p{L}\d])(?:номер\s+сберкнижки|счет\s+сберкнижки)\s*[:\-]?\s*423\d{2}[\s\-]?\d{3}[\s\-]?\d{1}[\s\-]?\d{4}[\s\-]?\d{7}(?:[^\p{L}\d]|$)""" ) + + override fun getHyperPatterns(requireKeywords: Boolean): List { + return if (requireKeywords) { + // Simplified pattern for HyperScan (shorter keywords to avoid "Pattern is too large" error) + listOf( + """(?:^|[^\p{L}\d])(?:номер\s+сберкнижки|счет\s+сберкнижки)\s*[:\-]?\s*423\d{2}[\s\-]?\d{3}[\s\-]?\d{1}[\s\-]?\d{4}[\s\-]?\d{7}(?:[^\p{L}\d]|$)""" + ) + } else { + // Return pattern without keywords when requireKeywords = false + listOf( + """(?:^|[^\p{L}\d])423\d{2}[\s\-]?\d{3}[\s\-]?\d{1}[\s\-]?\d{4}[\s\-]?\d{7}(?:[^\p{L}\d]|$)""" + ) + } + } override val expressionOptions = setOf( ExpressionOption.MULTILINE, ExpressionOption.CASELESS, diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/TCN.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/TCN.kt index a35a46d..02f95f8 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/TCN.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/TCN.kt @@ -37,7 +37,14 @@ object TCN : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - return javaPatterns + return if (requireKeywords) { + javaPatterns + } else { + // Return pattern without keywords as fallback + listOf( + """(?ix)(? { - return hyperPatterns + return if (requireKeywords) { + hyperPatterns + } else { + // Return pattern without keywords as fallback + listOf( + """(?:^|[^a-zA-Z0-9])[A-Z0-9]{17}(?:[^a-zA-Z0-9]|$)""" + ) + } } override val expressionOptions = setOf( diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/VehicleRegNumber.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/VehicleRegNumber.kt index 1b6ab9a..fd3c99d 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/VehicleRegNumber.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/VehicleRegNumber.kt @@ -52,8 +52,11 @@ object VehicleRegNumber : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - // Always require keywords for vehicle registration number to avoid false positives - val keywordsPart = """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)""" + val keywordsPart = if (requireKeywords) { + """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)""" + } else { + """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)?""" + } return listOf( """ (?ix) @@ -82,8 +85,11 @@ object VehicleRegNumber : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - // Always require keywords for vehicle registration number to avoid false positives - val keywordsPart = """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)""" + val keywordsPart = if (requireKeywords) { + """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)""" + } else { + """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)?""" + } return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[АВБГДЕКМНОРСТУХ]\d{3}[АВБГДЕКМНОРСТУХ]{2}\s+(?:$regionCodes)(?:[^\w]|$)""", """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[ABEKMHOPCTYX]\d{3}[ABEKMHOPCTYX]{2}\s+(?:$regionCodes)(?:[^\w]|$)""", diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/engine/EngineTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/engine/EngineTest.kt index e9eadee..e7f8209 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/engine/EngineTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/engine/EngineTest.kt @@ -122,7 +122,8 @@ internal class EngineTest { "Alien Registration Number", "APO/FPO/DPO", "Address US", - "Medicare US" + "Medicare US", + "Sberbank Book" ) for (attribute in Matchers.filterIsInstance()) { diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/DODIDTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/DODIDTest.kt index ebde5c5..16210ee 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/DODIDTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/DODIDTest.kt @@ -164,12 +164,6 @@ internal class DODIDTest : MatcherTestBase(DODID) { assertEquals(0, scanText(text), "DOD ID с буквами не должен находиться") } - @Test - fun testNoKeywords() { - val text = "1234567890" // Нет ключевых слов - assertEquals(0, scanText(text), "DOD ID без ключевых слов не должен находиться") - } - @Test fun testAllZeros() { val text = "DOD ID: 0000000000" // Все нули diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/DriverLicenseTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/DriverLicenseTest.kt index a38ba0f..06ee9ca 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/DriverLicenseTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/DriverLicenseTest.kt @@ -307,18 +307,6 @@ internal class DriverLicenseTest : MatcherTestBase(DriverLicense) { assertEquals(0, scanText(text), "ВУ внутри длинной цифровой последовательности не должно находиться") } - @Test - fun testStickingToAlphabeticChar() { - val text = "licenseводительское удостоверение 12 34 123456" - assertEquals(0, scanText(text), "ВУ, прилипшее к буквам, не должно находиться") - } - - @Test - fun testStickingToNumericChar() { - val text = "123номер удостоверения 12 34 123456" - assertEquals(0, scanText(text), "ВУ, прилипшее к цифрам, не должно находиться") - } - @Test fun testWithInvalidSeparators() { val text = "водительское удостоверение 12@34@123456" @@ -331,18 +319,6 @@ internal class DriverLicenseTest : MatcherTestBase(DriverLicense) { assertEquals(0, scanText(text), "Частичное ВУ не должно находиться") } - @Test - fun testInCode() { - val text = "functionводительское удостоверение 12 34 123456()" - assertEquals(0, scanText(text), "ВУ внутри кода не должно находиться") - } - - @Test - fun testWithoutKeywords() { - val text = "12 34 123456" - assertEquals(0, scanText(text), "ВУ без ключевых слов не должно находиться") - } - @Test fun testWithVoditelskoeUdo() { val text = "водительское удостоверение 12 34 123456" diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/EducationDocTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/EducationDocTest.kt index 6a62771..66361fc 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/EducationDocTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/EducationDocTest.kt @@ -275,12 +275,6 @@ internal class EducationDocTest : MatcherTestBase(EducationDoc) { assertTrue(scanText(text) >= 1, "Документ об образовании в конце текста должен быть найден") } - @Test - fun testWithoutKeywords() { - val text = "123456 1234567" - assertEquals(0, scanText(text), "Документ об образовании без ключевых слов не должен находиться") - } - @Test fun testWithDiplomKeyword() { val text = "диплом 123456 1234567" diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/MilitaryIDTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/MilitaryIDTest.kt index 9d8d903..433683e 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/MilitaryIDTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/MilitaryIDTest.kt @@ -339,12 +339,6 @@ internal class MilitaryIDTest : MatcherTestBase(MilitaryID) { assertTrue(scanText(text) >= 1, "Валидное УЛВ должно быть найдено") } - @Test - fun testWithoutKeywords() { - val text = "АБ 3847291" - assertEquals(0, scanText(text), "УЛВ без ключевых слов не должно находиться") - } - @Test fun testWithUdoverenieLichnosti() { val text = "удостоверение личности военнослужащего АБ 3847291" diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OGRNIPTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OGRNIPTest.kt index b5a53ad..9025848 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OGRNIPTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OGRNIPTest.kt @@ -308,12 +308,6 @@ internal class OGRNIPTest : MatcherTestBase(OGRNIP) { assertTrue(scanText(text) >= 1, "ОГРНИП в конце текста должен быть найден") } - @Test - fun testWithoutKeywords() { - val text = "304500116000157" - assertEquals(0, scanText(text), "ОГРНИП без ключевых слов не должен находиться") - } - @Test fun testWithOGRNIPKeyword() { val text = "ОГРНИП 304500116000157" diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OKPOTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OKPOTest.kt index 5f6d8a7..a98970a 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OKPOTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OKPOTest.kt @@ -350,11 +350,5 @@ internal class OKPOTest : MatcherTestBase(OKPO) { val text = "серия и номер ОКПО 23456783" assertTrue(scanText(text) >= 1, "ОКПО с ключевым словом 'серия и номер ОКПО' должен быть найден") } - - @Test - fun testWithoutKeywords() { - val text = "23456783" - assertEquals(0, scanText(text), "ОКПО без ключевых слов не должен находиться") - } } diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OMSTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OMSTest.kt index 6cb7944..d726010 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OMSTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OMSTest.kt @@ -332,24 +332,12 @@ internal class OMSTest : MatcherTestBase(OMS) { assertTrue(scanText(text) >= 1, "ОМС с ключевым словом 'полис ОМС' должен быть найден") } - @Test - fun testWithoutPolisAlone() { - val text = "полис 1234 5678 9012 3452" - assertEquals(0, scanText(text), "ОМС с отдельно стоящим 'полис' не должен находиться") - } - @Test fun testWithStrahovkaKeyword() { val text = "страховка 1234 5678 9012 3452" assertTrue(scanText(text) >= 1, "ОМС с ключевым словом 'страховка' должен быть найден") } - @Test - fun testWithoutKeywords() { - val text = "1234 5678 9012 3452" - assertEquals(0, scanText(text), "ОМС без ключевых слов не должен находиться") - } - @Test fun testWithPolisObyazatelnogo() { val text = "полис обязательного медицинского страхования 1234 5678 9012 3452" diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OSAGOPolicyTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OSAGOPolicyTest.kt index cc37a3b..9f0f5a6 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OSAGOPolicyTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/OSAGOPolicyTest.kt @@ -281,12 +281,6 @@ internal class OSAGOPolicyTest : MatcherTestBase(OSAGOPolicy) { assertTrue(scanText(text) >= 1, "Полис ОСАГО в конце текста должен быть найден") } - @Test - fun testWithoutKeywords() { - val text = "BBB 1234567890" - assertEquals(0, scanText(text), "Полис ОСАГО без ключевых слов не должен находиться") - } - @Test fun testWithOSAGOKeyword() { val text = "ОСАГО BBB 1234567890" diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/ResidencePermitTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/ResidencePermitTest.kt index 9ef4efb..547e02a 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/ResidencePermitTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/ResidencePermitTest.kt @@ -341,12 +341,6 @@ internal class ResidencePermitTest : MatcherTestBase(ResidencePermit) { assertTrue(scanText(text) >= 1, "ВНЖ с ключевым словом 'документ вида на жительство' должно быть найдено") } - @Test - fun testWithoutKeywords() { - val text = "82 1234567" - assertEquals(0, scanText(text), "ВНЖ без ключевых слов не должно находиться") - } - // ========== 5. Негативные сценарии ========== @Test @@ -367,28 +361,10 @@ internal class ResidencePermitTest : MatcherTestBase(ResidencePermit) { assertEquals(0, scanText(text), "ВНЖ с недопустимой серией не должно находиться") } - @Test - fun testStickingToAlphabeticChar() { - val text = "permitВНЖ 82 1234567" - assertEquals(0, scanText(text), "ВНЖ, прилипшее к буквам, не должно находиться") - } - - @Test - fun testStickingToNumericChar() { - val text = "123ВНЖ 82 1234567" - assertEquals(0, scanText(text), "ВНЖ, прилипшее к цифрам, не должно находиться") - } - @Test fun testPartialResidencePermit() { val text = "ВНЖ 82" assertEquals(0, scanText(text), "Частичное ВНЖ не должно находиться") } - - @Test - fun testInCode() { - val text = "functionВНЖ 82 1234567()" - assertEquals(0, scanText(text), "ВНЖ внутри кода не должно находиться") - } } diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/TCNTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/TCNTest.kt index f556417..a429c75 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/TCNTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/TCNTest.kt @@ -164,12 +164,6 @@ internal class TCNTest : MatcherTestBase(TCN) { assertEquals(0, scanText(text), "Текст без TCN не должен находить совпадения") } - @Test - fun testNoKeyword() { - val text = "HKR0627116X001XXX" // Нет ключевого слова TCN - assertEquals(0, scanText(text), "TCN без ключевого слова не должен находиться") - } - @Test fun testTooShort() { val text = "TCN: HKR0627116X001XX" // 16 символов вместо 17 diff --git a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/VehicleRegNumberTest.kt b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/VehicleRegNumberTest.kt index eb2c453..7ebefd8 100644 --- a/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/VehicleRegNumberTest.kt +++ b/kotlin-lib/src/jvmTest/kotlin/org/angryscan/common/matchers/VehicleRegNumberTest.kt @@ -293,12 +293,6 @@ internal class VehicleRegNumberTest : MatcherTestBase(VehicleRegNumber) { assertTrue(scanText(text) >= 1, "Госномер с ключевым словом должен быть найден") } - @Test - fun testWithoutKeywords() { - val text = "А123БВ 77" - assertEquals(0, scanText(text), "Госномер без ключевых слов не должен находиться") - } - @Test fun testWithGosnomerKeywordAlone() { val text = "госномер А123БВ 77" From f500884b5423b3bd55b47a05fb0d8ce135c6cfc2 Mon Sep 17 00:00:00 2001 From: artemtarasov Date: Fri, 23 Jan 2026 16:17:46 +0300 Subject: [PATCH 2/2] [fix] Fix duplicated keywords --- .../org/angryscan/common/matchers/DriverLicense.kt | 14 ++++---------- .../org/angryscan/common/matchers/EducationDoc.kt | 14 ++++---------- .../org/angryscan/common/matchers/MilitaryID.kt | 14 ++++---------- .../kotlin/org/angryscan/common/matchers/OGRNIP.kt | 14 ++++---------- .../kotlin/org/angryscan/common/matchers/OKPO.kt | 14 ++++---------- .../kotlin/org/angryscan/common/matchers/OMS.kt | 14 ++++---------- .../org/angryscan/common/matchers/OSAGOPolicy.kt | 14 ++++---------- .../org/angryscan/common/matchers/Passport.kt | 9 +++++---- .../angryscan/common/matchers/ResidencePermit.kt | 14 ++++---------- .../kotlin/org/angryscan/common/matchers/SNILS.kt | 14 ++++---------- .../org/angryscan/common/matchers/SberBook.kt | 7 ++----- .../angryscan/common/matchers/VehicleRegNumber.kt | 14 ++++---------- 12 files changed, 47 insertions(+), 109 deletions(-) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DriverLicense.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DriverLicense.kt index 7cabcbc..ec96187 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DriverLicense.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/DriverLicense.kt @@ -41,11 +41,8 @@ object DriverLicense : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)""" - } else { - """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)?""" - } + val baseKeywords = """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -68,11 +65,8 @@ object DriverLicense : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)""" - } else { - """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)?""" - } + val baseKeywords = """(?:водительское\s+удостоверение|номер\s+водительского\s+удостоверения|номер\s+удостоверения|номер\s+ВУ|ВУ\s+№|driver\s+license|license\s+number|driving\s+license)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[\s\(\[\{«"'])$keywordsPart\s*[:\-]?\s*\d{2}\s\d{2}\s\d{6}(?:[^0-9a-zA-ZА-ЯЁа-яё]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/EducationDoc.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/EducationDoc.kt index 7d1c549..d15316e 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/EducationDoc.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/EducationDoc.kt @@ -58,11 +58,8 @@ object EducationDoc : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)""" - } else { - """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)?""" - } + val baseKeywords = """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -93,11 +90,8 @@ object EducationDoc : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)""" - } else { - """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)?""" - } + val baseKeywords = """(?:диплом|аттестат|свидетельство\s+об\s+образовании|сертификат|удостоверение|документ\s+об\s+образовании|образовательный\s+документ|номер\s+диплома|серия\s+и\s+номер\s+диплома|номер\s+аттестата|серия\s+и\s+номер\s+аттестата|номер\s+свидетельства|серия\s+и\s+номер\s+свидетельства)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*\d{6}\s+\d{7}(?:[^\w]|$)""", """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*\d{2}\s+[А-ЯЁ]{2}\s+\d{6,7}(?:[^\w]|$)""" diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MilitaryID.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MilitaryID.kt index 4d07f96..67c3a04 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MilitaryID.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/MilitaryID.kt @@ -41,11 +41,8 @@ object MilitaryID : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)""" - } else { - """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)?""" - } + val baseKeywords = """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -68,11 +65,8 @@ object MilitaryID : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)""" - } else { - """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)?""" - } + val baseKeywords = """(?:удостоверение\s+личности\s+военнослужащего|номер\s+удостоверения\s+личности\s+военнослужащего|серия\s+и\s+номер\s+удостоверения\s+личности\s+военнослужащего|номер\s+УЛВ|УЛВ\s+№|военный\s+билет|номер\s+военного\s+билета)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[\s\r\n\(\)\"\'\[\]\{\};,.:\.!?])$keywordsPart\s*[:\-]?\s*[А-ЯA-Z]{2}[\s№\-]*\d{7}\b""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OGRNIP.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OGRNIP.kt index 25b6c5e..9978298 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OGRNIP.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OGRNIP.kt @@ -41,11 +41,8 @@ object OGRNIP : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)""" - } else { - """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)?""" - } + val baseKeywords = """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -68,11 +65,8 @@ object OGRNIP : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)""" - } else { - """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)?""" - } + val baseKeywords = """(?:ОГРНИП|основной\s+государственный\s+регистрационный\s+номер\s+индивидуального\s+предпринимателя|регистрационный\s+номер\s+в\s+реестре\s+ФЛ\s+ЧП|регистрационный\s+номер\s+индивидуального\s+предпринимателя|государственный\s+регистрационный\s+номер\s+ИП|номер\s+ОГРНИП|серия\s+и\s+номер\s+ОГРНИП)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[34]\d{14}(?:[^\w]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OKPO.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OKPO.kt index fe411e2..d845e34 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OKPO.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OKPO.kt @@ -41,11 +41,8 @@ object OKPO : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)""" - } else { - """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)?""" - } + val baseKeywords = """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -69,11 +66,8 @@ object OKPO : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)""" - } else { - """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)?""" - } + val baseKeywords = """(?:ОКПО|код\s+ОКПО|номер\s+ОКПО|общероссийский\s+классификатор\s+предприятий\s+и\s+организаций|классификатор\s+предприятий\s+и\s+организаций|серия\s+и\s+номер\s+ОКПО)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*\d{8}(?:[^\w]|$)""", """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*\d{10}(?:[^\w]|$)""" diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OMS.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OMS.kt index 52d9b3f..788207f 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OMS.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OMS.kt @@ -46,11 +46,8 @@ object OMS : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)""" - } else { - """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)?""" - } + val baseKeywords = """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -73,11 +70,8 @@ object OMS : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)""" - } else { - """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)?""" - } + val baseKeywords = """(?:полис\s+обязательного\s+медицинского\s+страхования|номер\s+полиса\s+ОМС|номер\s+полиса\s+обязательного\s+медицинского\s+страхования|серия\s+и\s+номер\s+полиса\s+ОМС|серия\s+и\s+номер\s+полиса|номер\s+полиса|полис\s+ОМС|ОМС\s+№|омс|страховка|страхование)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[0-9]{4}[\s\t-]*[0-9]{4}[\s\t-]*[0-9]{4}[\s\t-]*[0-9]{4}(?:[^\w]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OSAGOPolicy.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OSAGOPolicy.kt index 2603f7d..f2fbd39 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OSAGOPolicy.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/OSAGOPolicy.kt @@ -41,11 +41,8 @@ object OSAGOPolicy : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)""" - } else { - """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)?""" - } + val baseKeywords = """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -68,11 +65,8 @@ object OSAGOPolicy : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)""" - } else { - """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)?""" - } + val baseKeywords = """(?:ОСАГО|полис\s+ОСАГО|полис\s+обязательного\s+страхования\s+автогражданской\s+ответственности|номер\s+полиса\s+ОСАГО|серия\s+и\s+номер\s+полиса\s+ОСАГО|страховой\s+полис\s+ОСАГО|страховка\s+ОСАГО)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[A-ZА-Я]{3}\s+№?\s*\d{10}(?:[^\w]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/Passport.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/Passport.kt index 18adce9..afcfb38 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/Passport.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/Passport.kt @@ -26,8 +26,8 @@ object Passport : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val passportPart = if (requireKeywords) passportKeyword else "$passportKeyword?" - val seriesPart = if (requireKeywords) seriesKeyword else "$seriesKeyword?" + val passportPart = passportKeyword + if (!requireKeywords) "?" else "" + val seriesPart = seriesKeyword + if (!requireKeywords) "?" else "" return listOf( """(? { - val passportPart = if (requireKeywords) passportKeyword else "$passportKeyword?" - val seriesPart = if (requireKeywords) """[cс]ерия""" else """[cс]ерия?""" + val baseSeriesKeyword = """[cс]ерия""" + val passportPart = passportKeyword + if (!requireKeywords) "?" else "" + val seriesPart = baseSeriesKeyword + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^а-яА-Яa-zA-Z0-9])($passportPart[ \t-]?([а-яА-Я]*[ \t-]){0,2}[0-9]{2}[ \t-]?[0-9]{2}[ \t-]?[0-9]{6})(?:[^а-яА-Яa-zA-Z0-9]|$)""", """(?:^|[^а-яА-Яa-zA-Z0-9])$seriesPart[ \t-]+[0-9]{2}[ \t-]+[0-9]{2}[ \t,]+номер[ \t-]+[0-9]{6}(?:[^а-яА-Яa-zA-Z0-9]|$)""", diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/ResidencePermit.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/ResidencePermit.kt index 3a31466..7966576 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/ResidencePermit.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/ResidencePermit.kt @@ -42,11 +42,8 @@ object ResidencePermit : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)""" - } else { - """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)?""" - } + val baseKeywords = """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -69,11 +66,8 @@ object ResidencePermit : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)""" - } else { - """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)?""" - } + val baseKeywords = """(?:ВНЖ|вид\s+на\s+жительство|номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+вида\s+на\s+жительство|серия\s+и\s+номер\s+ВНЖ|номер\s+ВНЖ|документ\s+вида\s+на\s+жительство)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^a-zA-Z0-9А-ЯЁа-яё])$keywordsPart\s*[:\-]?\s*(?:82|83)\s*(?:№|N)?\s*\d{7}(?:[^a-zA-Z0-9А-ЯЁа-яё]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SNILS.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SNILS.kt index af97aaf..54e5c37 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SNILS.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SNILS.kt @@ -44,11 +44,8 @@ object SNILS : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:СНИЛС|страховой\s+номер\s+индивидуального\s+лицевого\s+счёта|страховой\s+номер\s+индивидуального\s+лицевого\s+счета|страховой\s+номер|номер\s+индивидуального\s+лицевого\s+счёта|номер\s+индивидуального\s+лицевого\s+счета|номер\s+СНИЛС|серия\s+и\s+номер\s+СНИЛС)""" - } else { - """(?:СНИЛС|страховой\s+номер\s+индивидуального\s+лицевого\s+счёта|страховой\s+номер\s+индивидуального\s+лицевого\s+счета|страховой\s+номер|номер\s+индивидуального\s+лицевого\s+счёта|номер\s+индивидуального\s+лицевого\s+счета|номер\s+СНИЛС|серия\s+и\s+номер\s+СНИЛС)?""" - } + val baseKeywords = """(?:СНИЛС|страховой\s+номер\s+индивидуального\s+лицевого\s+счёта|страховой\s+номер\s+индивидуального\s+лицевого\s+счета|страховой\s+номер|номер\s+индивидуального\s+лицевого\s+счёта|номер\s+индивидуального\s+лицевого\s+счета|номер\s+СНИЛС|серия\s+и\s+номер\s+СНИЛС)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -72,11 +69,8 @@ object SNILS : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:СНИЛС|страховой\s+номер\s+индивидуального\s+лицевого\s+счёта|страховой\s+номер\s+индивидуального\s+лицевого\s+счета|страховой\s+номер|номер\s+индивидуального\s+лицевого\s+счёта|номер\s+индивидуального\s+лицевого\s+счета|номер\s+СНИЛС|серия\s+и\s+номер\s+СНИЛС)""" - } else { - """(?:СНИЛС|страховой\s+номер\s+индивидуального\s+лицевого\s+счёта|страховой\s+номер\s+индивидуального\s+лицевого\s+счета|страховой\s+номер|номер\s+индивидуального\s+лицевого\s+счёта|номер\s+индивидуального\s+лицевого\s+счета|номер\s+СНИЛС|серия\s+и\s+номер\s+СНИЛС)?""" - } + val baseKeywords = """(?:СНИЛС|страховой\s+номер\s+индивидуального\s+лицевого\s+счёта|страховой\s+номер\s+индивидуального\s+лицевого\s+счета|страховой\s+номер|номер\s+индивидуального\s+лицевого\s+счёта|номер\s+индивидуального\s+лицевого\s+счета|номер\s+СНИЛС|серия\s+и\s+номер\s+СНИЛС)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^а-яА-Яa-zA-Z0-9])$keywordsPart\s*[:\-/\s]*\s*[^0-9]*?([0-9]{3}[\s\-]?[0-9]{3}[\s\-]?[0-9]{3}[\s\-]?[0-9]{2}|[0-9]{11})(?:[^а-яА-Яa-zA-Z0-9]|$)""" ) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SberBook.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SberBook.kt index bb2e624..fb229d1 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SberBook.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/SberBook.kt @@ -26,11 +26,8 @@ object SberBook : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:номер\s+сберкнижки|номер\s+сберегательной\s+книжки\s+ФЛ|счет\s+сберкнижки)""" - } else { - """(?:номер\s+сберкнижки|номер\s+сберегательной\s+книжки\s+ФЛ|счет\s+сберкнижки)?""" - } + val baseKeywords = """(?:номер\s+сберкнижки|номер\s+сберегательной\s+книжки\s+ФЛ|счет\s+сберкнижки)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) diff --git a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/VehicleRegNumber.kt b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/VehicleRegNumber.kt index fd3c99d..f7cfe62 100644 --- a/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/VehicleRegNumber.kt +++ b/kotlin-lib/src/commonMain/kotlin/org/angryscan/common/matchers/VehicleRegNumber.kt @@ -52,11 +52,8 @@ object VehicleRegNumber : IHyperMatcher, IKotlinMatcher { ) override fun getJavaPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)""" - } else { - """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)?""" - } + val baseKeywords = """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """ (?ix) @@ -85,11 +82,8 @@ object VehicleRegNumber : IHyperMatcher, IKotlinMatcher { ) override fun getHyperPatterns(requireKeywords: Boolean): List { - val keywordsPart = if (requireKeywords) { - """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)""" - } else { - """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)?""" - } + val baseKeywords = """(?:регистрационный\s+номер\s+ТС|регистрационный\s+номер\s+транспортного\s+средства|госномер|гос\.\s*номер|государственный\s+номер|номерной\s+знак\s+ТС|номерной\s+знак\s+транспортного\s+средства|автомобильный\s+номер|номер\s+автомобиля|регистрационный\s+знак\s+транспортного\s+средства|регистрационный\s+знак\s+ТС|номер\s+ТС)""" + val keywordsPart = baseKeywords + if (!requireKeywords) "?" else "" return listOf( """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[АВБГДЕКМНОРСТУХ]\d{3}[АВБГДЕКМНОРСТУХ]{2}\s+(?:$regionCodes)(?:[^\w]|$)""", """(?:^|[^\w])$keywordsPart\s*[:\-]?\s*[ABEKMHOPCTYX]\d{3}[ABEKMHOPCTYX]{2}\s+(?:$regionCodes)(?:[^\w]|$)""",