M3: japanska skyltar – pixelfont, ordbok, kunskap, delvis översättning, hjälp
All checks were successful
release / build-release (push) Successful in 1m42s
All checks were successful
release / build-release (push) Successful in 1m42s
- resources/text/fonts: PixelMplus 10/12 px (M+ FONT LICENSE) + licens; all text ritas via text/v2 på heltalspositioner, debugfonten är borta - internal/lang: ordbok (60 ord, validerad), tokenisering med längsta matchning, Knowledge (ord + kana, nivå 0–5, hintar), Render (kända ord markerade/översatta, okända kvar, kana som romaji), EnglishShare/ ShowEnglish per svårighet (deterministiskt per bana+position), HelpSeconds; datatest kräver att all japanska i banorna finns i ordboken - sim.Run: AskHelp (H) med väntetid efter nivå, avbryts om man går, avslöjar skylten och lär första okända ordet; Knowledge delas mellan banor - game: skylt- och avgångstavlor renderade genom kunskapen med färgkodning, engelsk rad på lätta banor, hjälp-förlopp, "Nytt ord"-notis, HUD visar resmålet på japanska från nivå 1 och japanska-nivå; meny med svårighet; pixelbaserad radbrytning av färgade textsegment; -know-flagga - tools/shots: tre skyltbilder (skylt, hjälp, nytt ord) med förkunskap - docs/README/wiki uppdaterade Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
90
internal/lang/render.go
Normal file
90
internal/lang/render.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package lang
|
||||
|
||||
import "strings"
|
||||
|
||||
// Shown är en bit text som spelaren ser, med hur den ska färgas.
|
||||
type Shown struct {
|
||||
Text string
|
||||
Known bool // ordet är känt (översatt/markerat)
|
||||
Reading bool // kana-ord som kan läsas men inte förstås
|
||||
Romaji string // läsning att visa under kända ord vid ShowsReadings
|
||||
}
|
||||
|
||||
// Rendered är en skylt sedd genom spelarens kunskap.
|
||||
type Rendered struct {
|
||||
Original []Shown // originaltexten med kända ord markerade
|
||||
Partial []Shown // delvis översättning: kända ord översatta, resten kvar på japanska
|
||||
Complete bool // allt gick att läsa
|
||||
}
|
||||
|
||||
// Render tolkar en japansk text med spelarens kunskap. k == nil betyder
|
||||
// "kan allt" (används när en skylt är avslöjad via hjälp).
|
||||
//
|
||||
// Japanska skrivs utan mellanslag, men när ett ord översätts till svenska
|
||||
// behöver det luft mot grannorden, annars blir det "新宿mot". Därför får
|
||||
// översatta ord ett mellanslag mot intilliggande text i den delvisa raden.
|
||||
func Render(d *Dictionary, k *Knowledge, s, uiLang string) Rendered {
|
||||
var out Rendered
|
||||
out.Complete = true
|
||||
prevTranslated := false // förra delen i Partial var ett översatt/läst ord
|
||||
addPartial := func(sh Shown, translated bool) {
|
||||
if n := len(out.Partial); n > 0 && (translated || prevTranslated) {
|
||||
prev := &out.Partial[n-1]
|
||||
if prev.Text != "" && !strings.HasSuffix(prev.Text, " ") && !strings.HasPrefix(sh.Text, " ") {
|
||||
prev.Text += " "
|
||||
}
|
||||
}
|
||||
out.Partial = append(out.Partial, sh)
|
||||
prevTranslated = translated
|
||||
}
|
||||
for _, seg := range d.Tokenize(s) {
|
||||
switch seg.Kind {
|
||||
case Word:
|
||||
known := k == nil || k.Knows(seg.Text)
|
||||
canRead := !known && k != nil && k.Kana && IsAllKana(seg.Text)
|
||||
orig := Shown{Text: seg.Text, Known: known, Reading: canRead}
|
||||
if known && k != nil && k.ShowsReadings() {
|
||||
orig.Romaji = seg.Entry.Romaji
|
||||
}
|
||||
out.Original = append(out.Original, orig)
|
||||
switch {
|
||||
case known:
|
||||
addPartial(Shown{Text: seg.Entry.Translation(uiLang), Known: true}, true)
|
||||
case canRead:
|
||||
addPartial(Shown{Text: seg.Entry.Romaji, Reading: true}, true)
|
||||
out.Complete = false
|
||||
default:
|
||||
addPartial(Shown{Text: seg.Text}, false)
|
||||
out.Complete = false
|
||||
}
|
||||
case Unknown:
|
||||
out.Original = append(out.Original, Shown{Text: seg.Text})
|
||||
addPartial(Shown{Text: seg.Text}, false)
|
||||
out.Complete = false
|
||||
default:
|
||||
out.Original = append(out.Original, Shown{Text: seg.Text, Known: true})
|
||||
addPartial(Shown{Text: seg.Text, Known: true}, false)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// PlainText slår ihop en rad till en sträng.
|
||||
func PlainText(line []Shown) string {
|
||||
s := ""
|
||||
for _, sh := range line {
|
||||
s += sh.Text
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FirstUnknownWord returnerar det första ordboksordet i texten som spelaren
|
||||
// inte kan, eller "" om hen kan alla.
|
||||
func FirstUnknownWord(d *Dictionary, k *Knowledge, s string) string {
|
||||
for _, w := range d.WordsIn(s) {
|
||||
if !k.Knows(w) {
|
||||
return w
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user