///|
/// Quality counters for dictionary ingestion pipelines.
pub(all) struct DictionaryQuality {
entry_count : Int
valid_count : Int
invalid_count : Int
duplicate_count : Int
label_count : Int
minimum_keyword_length : Int
maximum_keyword_length : Int
average_keyword_length : Int
} derive(Debug, Eq, ToJson)
///|
/// Inspect entries before compilation and return deterministic quality data.
///
/// Importers can use this report to reject malformed input without losing the
/// rest of the batch. Duplicate identities are counted after validation so a
/// malformed duplicate is still reported as malformed rather than hidden.
pub fn assess_dictionary(entries : ArrayView[Entry]) -> DictionaryQuality {
let mut valid = 0
let mut invalid = 0
let mut duplicates = 0
let mut total_length = 0
let mut minimum = 0
let mut maximum = 0
let labels : Map[String, Bool] = Map([])
let identities : Map[String, Bool] = Map([])
for item in entries {
let issues = validate_entry(item)
if issues.length() == 0 {
valid += 1
} else {
invalid += 1
}
let length = item.keyword.length()
total_length += length
if minimum == 0 || length < minimum {
minimum = length
}
if length > maximum {
maximum = length
}
labels[item.label] = true
let identity = entry_key(item)
if identities.contains(identity) {
duplicates += 1
} else {
identities[identity] = true
}
}
{
entry_count: entries.length(),
valid_count: valid,
invalid_count: invalid,
duplicate_count: duplicates,
label_count: labels.length(),
minimum_keyword_length: minimum,
maximum_keyword_length: maximum,
average_keyword_length: if entries.length() == 0 {
0
} else {
total_length / entries.length()
},
}
}
///|
/// Return whether a dictionary is safe to compile without data loss.
pub fn dictionary_quality_is_usable(report : DictionaryQuality) -> Bool {
report.entry_count > 0 &&
report.invalid_count == 0 &&
report.duplicate_count == 0
}
///|
/// Return the number of valid entries in a batch.
pub fn valid_entry_count(entries : ArrayView[Entry]) -> Int {
assess_dictionary(entries).valid_count
}
///|
/// Return the number of repeated keyword/label identities in a batch.
pub fn duplicate_entry_count(entries : ArrayView[Entry]) -> Int {
assess_dictionary(entries).duplicate_count
}
///|
/// Render a stable one-row report for import logs and CI artifacts.
pub fn dictionary_quality_tsv(report : DictionaryQuality) -> String {
let header = "entries\tvalid\tinvalid\tduplicates\tlabels\tmin_length\tmax_length\taverage_length\n"
let row = "\{report.entry_count}\t\{report.valid_count}\t\{report.invalid_count}\t\{report.duplicate_count}\t\{report.label_count}\t\{report.minimum_keyword_length}\t\{report.maximum_keyword_length}\t\{report.average_keyword_length}\n"
header + row
}