classify static method

DocumentClassificationResult classify(
  1. String rawText, {
  2. Map<String, String>? fields,
  3. ScanMode? mode,
})

Classifies OCR raw text or scan result into a DocumentCategory.

Implementation

static DocumentClassificationResult classify(
  String rawText, {
  Map<String, String>? fields,
  ScanMode? mode,
}) {
  if (rawText.isEmpty) {
    return const DocumentClassificationResult(
      category: DocumentCategory.generalDocument,
      confidence: 0.50,
      detectedKeywords: [],
      description: 'Unclassified Empty Document',
    );
  }

  final upper = rawText.toUpperCase();
  final keywords = <String>[];

  // Barcode & QR code check (checked first for barcode/QR modes unless explicit identity card payload exists)
  if (mode == ScanMode.qr ||
      mode == ScanMode.barcode ||
      mode == ScanMode.pdf417 ||
      mode == ScanMode.multiCode) {
    if (upper.contains('<?XML') ||
        upper.contains('<PRINTLETTERBARCODEDATA') ||
        upper.contains('AADHAAR')) {
      keywords.addAll(['AADHAAR', 'UID']);
      return DocumentClassificationResult(
        category: DocumentCategory.aadhaar,
        confidence: 0.99,
        detectedKeywords: keywords,
        description: 'Indian Aadhaar Identity Card (Secure QR)',
      );
    }
    if (upper.contains('INCOME TAX') || upper.contains('PERMANENT ACCOUNT')) {
      keywords.addAll(['PAN', 'INCOME TAX']);
      return DocumentClassificationResult(
        category: DocumentCategory.pan,
        confidence: 0.98,
        detectedKeywords: keywords,
        description: 'Indian Income Tax PAN Card QR',
      );
    }
    return DocumentClassificationResult(
      category: DocumentCategory.barcode,
      confidence: 0.99,
      detectedKeywords: [mode?.name.toUpperCase() ?? 'BARCODE'],
      description: '1D/2D Barcode Data Payload',
    );
  }

  // Bank Cheque check
  if (upper.contains('PAY TO THE ORDER OF') || upper.contains('CHEQUE') || upper.contains('MICR') || upper.contains('⑈') || upper.contains('⑆') || (mode == ScanMode.cheque) || RegExp(r'c[0-9]{6}c\s*[0-9]{9}a').hasMatch(rawText)) {
    keywords.addAll(['CHEQUE', 'MICR', 'BANK']);
    return DocumentClassificationResult(
      category: DocumentCategory.cheque,
      confidence: 0.98,
      detectedKeywords: keywords,
      description: 'Bank Cheque Financial Document',
    );
  }

  // Passport MRZ check
  if (upper.contains('P<') || upper.contains('PASSPORT') || upper.contains('ICAO') || (mode == ScanMode.passport)) {
    keywords.addAll(['PASSPORT', 'MRZ', 'P<']);
    return DocumentClassificationResult(
      category: DocumentCategory.passport,
      confidence: upper.contains('P<') ? 0.99 : 0.90,
      detectedKeywords: keywords,
      description: 'International Passport Document',
    );
  }

  // Aadhaar Card check
  if (upper.contains('AADHAAR') ||
      upper.contains('GOVERNMENT OF INDIA') ||
      upper.contains('UNIQUE IDENTIFICATION') ||
      RegExp(r'\b[2-9]\d{3}\s?\d{4}\s?\d{4}\b').hasMatch(upper) ||
      (mode == ScanMode.aadhaar)) {
    keywords.addAll(['AADHAAR', 'UID', 'GOVT OF INDIA']);
    return DocumentClassificationResult(
      category: DocumentCategory.aadhaar,
      confidence: 0.98,
      detectedKeywords: keywords,
      description: 'Indian Aadhaar Identity Card',
    );
  }

  // PAN Card check
  if (upper.contains('INCOME TAX') || upper.contains('PERMANENT ACCOUNT') || (mode == ScanMode.pan)) {
    keywords.addAll(['PAN', 'INCOME TAX', 'GOVT OF INDIA']);
    return DocumentClassificationResult(
      category: DocumentCategory.pan,
      confidence: 0.98,
      detectedKeywords: keywords,
      description: 'Indian Income Tax PAN Card',
    );
  }

  // Driving License check
  if (upper.contains('DRIVING LICENSE') || upper.contains('LICENCE') || upper.contains('DL NO') || upper.contains('ANSI ') || (mode == ScanMode.drivingLicense)) {
    keywords.addAll(['DRIVING LICENSE', 'DL']);
    return DocumentClassificationResult(
      category: DocumentCategory.drivingLicense,
      confidence: 0.95,
      detectedKeywords: keywords,
      description: 'Driving License Identity Document',
    );
  }

  // Invoice check
  if (upper.contains('INVOICE') || upper.contains('BILL TO') || upper.contains('TAX INVOICE') || upper.contains('DUE DATE') || (mode == ScanMode.invoice)) {
    keywords.addAll(['INVOICE', 'BILL TO', 'TAX INVOICE']);
    return DocumentClassificationResult(
      category: DocumentCategory.invoice,
      confidence: 0.95,
      detectedKeywords: keywords,
      description: 'Commercial Invoice & Billing Document',
    );
  }

  // Receipt check
  if (upper.contains('TOTAL') && (upper.contains('CHANGE') || upper.contains('SUBTOTAL') || upper.contains('CASH') || upper.contains('THANK YOU')) || (mode == ScanMode.receipt)) {
    keywords.addAll(['RECEIPT', 'TOTAL', 'SUBTOTAL']);
    return DocumentClassificationResult(
      category: DocumentCategory.receipt,
      confidence: 0.93,
      detectedKeywords: keywords,
      description: 'Retail Store Sales Receipt',
    );
  }

  // Business Card check
  if (upper.contains('ENGINEER') || upper.contains('MANAGER') || upper.contains('DIRECTOR') || upper.contains('SOFTWARE') || (upper.contains('@') && upper.contains('WWW.')) || (mode == ScanMode.businessCard)) {
    keywords.addAll(['BUSINESS CARD', 'EMAIL', 'TITLE']);
    return DocumentClassificationResult(
      category: DocumentCategory.businessCard,
      confidence: 0.90,
      detectedKeywords: keywords,
      description: 'Professional Business Contact Card',
    );
  }

  // VIN Number check
  if (upper.contains('VIN') || (upper.length == 17 && RegExp(r'^[A-HJ-NPR-Z0-9]{17}$').hasMatch(upper)) || (mode == ScanMode.vin)) {
    keywords.addAll(['VIN', 'VEHICLE ID']);
    return DocumentClassificationResult(
      category: DocumentCategory.vin,
      confidence: 0.96,
      detectedKeywords: keywords,
      description: 'Vehicle Identification Number (VIN)',
    );
  }

  // Barcode check
  if (mode == ScanMode.qr || mode == ScanMode.barcode || mode == ScanMode.pdf417 || mode == ScanMode.multiCode) {
    return DocumentClassificationResult(
      category: DocumentCategory.barcode,
      confidence: 0.99,
      detectedKeywords: [mode?.name.toUpperCase() ?? 'BARCODE'],
      description: '1D/2D Barcode Data Payload',
    );
  }

  // Fallback general document
  return DocumentClassificationResult(
    category: DocumentCategory.generalDocument,
    confidence: 0.75,
    detectedKeywords: ['TEXT', 'DOCUMENT'],
    description: 'Standard Text Document',
  );
}