fixed a new prescene layout
This commit is contained in:
@@ -5,8 +5,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"git.kplus.net.ua/yevhen/resource-scraper/internal/releaseparser"
|
||||
)
|
||||
|
||||
@@ -58,31 +56,31 @@ func Parse(raw string) releaseparser.ParsedRelease {
|
||||
return result
|
||||
}
|
||||
|
||||
// Where the dictionary-driven tail zone begins: after the resolved
|
||||
// Artist/Title core (2 tokens by default, 3 with an artist dictionary hit).
|
||||
// Left core boundary: after the resolved Artist (2 tokens by default,
|
||||
// 3 with an artist dictionary hit, or fixed by an override).
|
||||
start := 2
|
||||
|
||||
// Level 1: exact-lookup override table fixes Artist/Title only;
|
||||
// the tail zone is parsed as usual below.
|
||||
// the tail zone is parsed as usual below. The override is
|
||||
// authoritative about the core: leftover tokens are plain unknowns,
|
||||
// not part of the title.
|
||||
if o, ok := Profile.Overrides[result.Raw]; ok {
|
||||
result.Artist, result.Title = o.Artist, o.Title
|
||||
start = overrideCoreLength(tokens, o)
|
||||
}
|
||||
|
||||
// Level 2: artist dictionary — "[0]-[1]" whitelisted as a hyphenated
|
||||
// artist shifts the core by one token.
|
||||
switch {
|
||||
case result.Artist != "":
|
||||
// An override already fixed the core — leave it alone.
|
||||
case len(tokens) >= 3 &&
|
||||
Profile.ArtistTokens[strings.ToUpper(tokens[0]+"-"+tokens[1])]:
|
||||
result.Artist = tokens[0] + "-" + tokens[1]
|
||||
result.Title = tokens[2]
|
||||
start = 3
|
||||
default:
|
||||
result.Artist = tokens[0]
|
||||
if len(tokens) > 1 {
|
||||
result.Title = tokens[1]
|
||||
// Level 2: artist dictionary — a hyphenated artist may span ANY number
|
||||
// of leading tokens ("Shadu-Nar-Mattaru" = 3). The LONGEST whitelisted
|
||||
// prefix wins; the title is the token right after it. At least one
|
||||
// title token and one tail token must remain.
|
||||
artistDict := false
|
||||
if result.Artist == "" {
|
||||
for k := len(tokens) - 2; k >= 2; k-- {
|
||||
if Profile.ArtistTokens[strings.ToUpper(strings.Join(tokens[:k], "-"))] {
|
||||
artistDict = true
|
||||
start = k + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,8 +91,41 @@ func Parse(raw string) releaseparser.ParsedRelease {
|
||||
end = len(tokens) - 2
|
||||
}
|
||||
|
||||
// Right core boundary: the first dictionary-known token after the
|
||||
// resolved artist. The boundary is contextual, but the title itself
|
||||
// stays a single token ([1], or [2] with an artist dictionary hit).
|
||||
// Unknown tokens inside the core region ([start .. tailStart)) are
|
||||
// REPORTED in UnknownTokens — never eaten, never glued into the title.
|
||||
tailStart := end
|
||||
for i := start; i < end; i++ {
|
||||
if isKnownToken(tokens[i]) {
|
||||
tailStart = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve Artist/Title from the core unless the override already did.
|
||||
if result.Artist == "" {
|
||||
if artistDict {
|
||||
// The artist spans tokens [0 .. start-2]; re-join them.
|
||||
result.Artist = strings.Join(tokens[:start-1], "-")
|
||||
} else {
|
||||
result.Artist = tokens[0]
|
||||
}
|
||||
if len(tokens) > start-1 {
|
||||
result.Title = tokens[start-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Core-region leftovers (e.g. the rest of a wildcards title after an
|
||||
// override, or a hyphenated title fragment without an artist entry):
|
||||
// visible in UnknownTokens for review.
|
||||
for _, tok := range tokens[start:tailStart] {
|
||||
result.UnknownTokens = append(result.UnknownTokens, tok)
|
||||
}
|
||||
|
||||
// Level 3: dictionary-driven tail zone, starting after the resolved core.
|
||||
parseTailZone(start, tokens[start:end], &result)
|
||||
parseTailZone(tokens[tailStart:end], &result)
|
||||
|
||||
score(&result)
|
||||
return result
|
||||
@@ -160,12 +191,24 @@ func catalogNumber(token string) string {
|
||||
return token[1 : len(token)-1]
|
||||
}
|
||||
|
||||
// isKnownToken reports whether the token belongs to the tail zone: it
|
||||
// matches one of the profile dictionaries or is a parenthesized catalogue
|
||||
// number. The first such token after the core marks the right core
|
||||
// boundary.
|
||||
func isKnownToken(tok string) bool {
|
||||
up := strings.ToUpper(tok)
|
||||
return Profile.FormatTokens[up] || Profile.SourceTokens[up] ||
|
||||
Profile.BitDepthTokens[up] || Profile.ResolutionTokens[up] ||
|
||||
Profile.EditionTokens[up] || Profile.LanguageMarkers[up] ||
|
||||
catalogNumber(tok) != ""
|
||||
}
|
||||
|
||||
// parseTailZone resolves middle-zone tokens against the dictionaries.
|
||||
// The first match wins for each field; catalogue numbers are recognized
|
||||
// from parenthesized tokens, and anything unrecognized is appended to
|
||||
// UnknownTokens so that it can be reviewed and curated into a dictionary.
|
||||
func parseTailZone(start int, zone []string, result *releaseparser.ParsedRelease) {
|
||||
for i, tok := range zone {
|
||||
func parseTailZone(zone []string, result *releaseparser.ParsedRelease) {
|
||||
for _, tok := range zone {
|
||||
up := strings.ToUpper(tok)
|
||||
switch {
|
||||
case Profile.FormatTokens[up]:
|
||||
@@ -197,13 +240,6 @@ func parseTailZone(start int, zone []string, result *releaseparser.ParsedRelease
|
||||
default:
|
||||
if cat := catalogNumber(tok); cat != "" && result.CatalogNo == "" {
|
||||
result.CatalogNo = cat
|
||||
} else if hasLaterKnownToken(zone, i) {
|
||||
// suspected title continuation: the core is probably longer
|
||||
// than 2 tokens. Not eaten, not unknown — review section.
|
||||
result.TitleExtra = append(result.TitleExtra, tok)
|
||||
if !slices.Contains(result.Warnings, "suspected title continuation") {
|
||||
result.Warnings = append(result.Warnings, "suspected title continuation")
|
||||
}
|
||||
} else {
|
||||
result.UnknownTokens = append(result.UnknownTokens, tok)
|
||||
}
|
||||
@@ -220,20 +256,6 @@ func applyType(tok string, result *releaseparser.ParsedRelease) {
|
||||
}
|
||||
}
|
||||
|
||||
// hasLaterKnownToken reports whether any token after index i in the zone
|
||||
// matches one of the profile dictionaries.
|
||||
func hasLaterKnownToken(zone []string, i int) bool {
|
||||
for _, later := range zone[i+1:] {
|
||||
up := strings.ToUpper(later)
|
||||
if Profile.FormatTokens[up] || Profile.SourceTokens[up] ||
|
||||
Profile.BitDepthTokens[up] || Profile.ResolutionTokens[up] ||
|
||||
Profile.EditionTokens[up] || Profile.LanguageMarkers[up] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// overrideCoreLength returns the number of leading tokens covered by the
|
||||
// override's Artist and Title (each may span several hyphen-separated
|
||||
// tokens), falling back to the default 2-token core when the raw tokens
|
||||
|
||||
Reference in New Issue
Block a user