sync current state
This commit is contained in:
@@ -194,6 +194,11 @@ final class ImportFlowViewModel: ObservableObject {
|
||||
.dateGermanDayMonthYearHourMinuteToISO8601,
|
||||
.dateUnixSecondsToISO8601
|
||||
]
|
||||
case .number:
|
||||
return [
|
||||
.passthrough,
|
||||
.integerLookupToNumber
|
||||
]
|
||||
default:
|
||||
return [.passthrough]
|
||||
}
|
||||
@@ -203,6 +208,8 @@ final class ImportFlowViewModel: ObservableObject {
|
||||
switch type {
|
||||
case .passthrough:
|
||||
return String(localized: "formatter.option.passthrough")
|
||||
case .integerLookupToNumber:
|
||||
return String(localized: "formatter.option.integer_lookup")
|
||||
case .dateISO8601ToISO8601:
|
||||
return String(localized: "formatter.option.date_iso")
|
||||
case .dateGermanDayMonthYearToISO8601:
|
||||
@@ -214,6 +221,89 @@ final class ImportFlowViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func distinctSourceValues(for field: TemplateField) -> [String] {
|
||||
let sourceKey = mappedSourceKey(for: field.id)
|
||||
guard !sourceKey.isEmpty else {
|
||||
return []
|
||||
}
|
||||
|
||||
let values = entries
|
||||
.compactMap { $0.sourceDictionary[sourceKey]?.sourceString() }
|
||||
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
|
||||
.filter { !$0.isEmpty }
|
||||
|
||||
let unique = Array(Set(values))
|
||||
|
||||
return unique.sorted { lhs, rhs in
|
||||
if let left = Double(lhs), let right = Double(rhs) {
|
||||
return left < right
|
||||
}
|
||||
return lhs.localizedCaseInsensitiveCompare(rhs) == .orderedAscending
|
||||
}
|
||||
}
|
||||
|
||||
func sourceValueHistogram(for field: TemplateField) -> [(value: String, count: Int)] {
|
||||
let sourceKey = mappedSourceKey(for: field.id)
|
||||
guard !sourceKey.isEmpty else {
|
||||
return []
|
||||
}
|
||||
|
||||
var counts: [String: Int] = [:]
|
||||
for entry in entries {
|
||||
guard let value = entry.sourceDictionary[sourceKey]?.sourceString() else {
|
||||
continue
|
||||
}
|
||||
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !trimmed.isEmpty else {
|
||||
continue
|
||||
}
|
||||
counts[trimmed, default: 0] += 1
|
||||
}
|
||||
|
||||
return counts
|
||||
.map { (key: $0.key, value: $0.value) }
|
||||
.sorted { lhs, rhs in
|
||||
if let left = Double(lhs.key), let right = Double(rhs.key) {
|
||||
return left < right
|
||||
}
|
||||
return lhs.key.localizedCaseInsensitiveCompare(rhs.key) == .orderedAscending
|
||||
}
|
||||
.map { (value: $0.key, count: $0.value) }
|
||||
}
|
||||
|
||||
func isValidTargetValue(for field: TemplateField, value: String) -> Bool {
|
||||
MoodwellStateOfMindTemplate.validateFormattedTarget(
|
||||
fieldID: field.id,
|
||||
formatted: value,
|
||||
moodValenceScale: moodValenceScale
|
||||
)
|
||||
}
|
||||
|
||||
func integerLookupCoverage(for field: TemplateField) -> (mappedDistinct: Int, totalDistinct: Int, mappedRows: Int, totalRows: Int) {
|
||||
let histogram = sourceValueHistogram(for: field)
|
||||
let totalRows = histogram.reduce(0) { $0 + $1.count }
|
||||
let formatter = formatter(for: field.id)
|
||||
|
||||
guard formatter.formatterType == .integerLookupToNumber else {
|
||||
return (0, histogram.count, 0, totalRows)
|
||||
}
|
||||
|
||||
var mappedDistinct = 0
|
||||
var mappedRows = 0
|
||||
|
||||
for item in histogram {
|
||||
guard let mapped = formatter.integerLookup[item.value]?.trimmingCharacters(in: .whitespacesAndNewlines), !mapped.isEmpty else {
|
||||
continue
|
||||
}
|
||||
if isValidTargetValue(for: field, value: mapped) {
|
||||
mappedDistinct += 1
|
||||
mappedRows += item.count
|
||||
}
|
||||
}
|
||||
|
||||
return (mappedDistinct, histogram.count, mappedRows, totalRows)
|
||||
}
|
||||
|
||||
func fieldState(for field: TemplateField) -> FieldMappingState {
|
||||
let sourceKey = mappedSourceKey(for: field.id)
|
||||
guard !sourceKey.isEmpty else {
|
||||
|
||||
Reference in New Issue
Block a user