Добавил поиск метаданных по каталогам
This commit is contained in:
@@ -76,15 +76,72 @@ func validateSchema(p *Plan, in Input) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// decide считает решение модели уверенности. В Ф2 метабазы выключены, а без
|
||||
// подтверждённого матча в базе авто-раскладка не делается (recognition.md),
|
||||
// поэтому Auto всегда false; здесь же копим структурные предупреждения и
|
||||
// расхождения с пред-парсом — они объясняют ревью человеку.
|
||||
func decide(p Plan, pre PreParse) Decision {
|
||||
reasons := []string{"матч в базе не подтверждён (метабазы отключены в Ф2) → review"}
|
||||
// decide считает решение модели уверенности (см. recognition.md). Авто —
|
||||
// только если выполнено всё: подтверждённый единичный матч в базе; чистая
|
||||
// структурная валидация (для сериала — число серий бьётся с базой);
|
||||
// согласованность с пред-парсом; самооценка LLM не ниже порога. Любая
|
||||
// невыполненная — причина ухода в review.
|
||||
func decide(p Plan, pre PreParse, match *Match, metadataEnabled bool, threshold float64) Decision {
|
||||
var reasons []string
|
||||
|
||||
switch {
|
||||
case !metadataEnabled:
|
||||
reasons = append(reasons, "метабазы отключены → авто-раскладка недоступна")
|
||||
case match == nil:
|
||||
reasons = append(reasons, "не найдено в базе или несколько кандидатов")
|
||||
}
|
||||
|
||||
reasons = append(reasons, structuralWarnings(p)...)
|
||||
|
||||
if match != nil && p.Type == MediaSeries {
|
||||
reasons = append(reasons, episodeCountWarnings(p, match.SeasonEpisodeCounts)...)
|
||||
}
|
||||
|
||||
reasons = append(reasons, consistencyWarnings(p, pre)...)
|
||||
return Decision{Auto: false, Reasons: reasons}
|
||||
|
||||
if p.Confidence < threshold {
|
||||
reasons = append(reasons,
|
||||
fmt.Sprintf("уверенность %.2f ниже порога %.2f", p.Confidence, threshold))
|
||||
}
|
||||
|
||||
return Decision{Auto: len(reasons) == 0, Reasons: reasons}
|
||||
}
|
||||
|
||||
// episodeCountWarnings сверяет число распознанных серий по сезонам с базой.
|
||||
// Нет данных по сезону → блокируем авто (полноту пака не подтвердить).
|
||||
func episodeCountWarnings(p Plan, counts map[int]int) []string {
|
||||
recognized := map[int]int{}
|
||||
for _, f := range p.Files {
|
||||
if f.Role == RoleEpisode && f.Episode != nil {
|
||||
season := 0
|
||||
if f.Season != nil {
|
||||
season = *f.Season
|
||||
}
|
||||
recognized[season]++
|
||||
}
|
||||
}
|
||||
var w []string
|
||||
for _, season := range sortedKeys(toSlices(recognized)) {
|
||||
rc := recognized[season]
|
||||
dbc, ok := counts[season]
|
||||
switch {
|
||||
case !ok || dbc == 0:
|
||||
w = append(w, fmt.Sprintf("сезон %d: в базе нет данных о числе серий", season))
|
||||
case rc != dbc:
|
||||
w = append(w, fmt.Sprintf("сезон %d: распознано серий %d, в базе %d", season, rc, dbc))
|
||||
}
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
||||
// toSlices превращает map[int]int в map[int][]int для sortedKeys (нужны
|
||||
// только ключи).
|
||||
func toSlices(m map[int]int) map[int][]int {
|
||||
out := make(map[int][]int, len(m))
|
||||
for k := range m {
|
||||
out[k] = nil
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// structuralWarnings — нарушения структуры плана (мягкие, не блокируют разбор).
|
||||
|
||||
Reference in New Issue
Block a user