eq2go/internal/languages/integration_example_test.go

392 lines
12 KiB
Go

package languages
import (
"fmt"
"testing"
)
// This file demonstrates how to integrate the languages package with entity systems
// ExamplePlayer shows how a Player struct might embed the language adapter
type ExamplePlayer struct {
id int32
name string
characterID int32
languageAdapter *PlayerLanguageAdapter
}
// NewExamplePlayer creates a new example player with language support
func NewExamplePlayer(id int32, name string, languageManager *Manager, logger Logger) *ExamplePlayer {
return &ExamplePlayer{
id: id,
name: name,
characterID: id, // In real implementation, this might be different
languageAdapter: NewPlayerLanguageAdapter(languageManager, logger),
}
}
// Implement the Entity interface
func (ep *ExamplePlayer) GetID() int32 { return ep.id }
func (ep *ExamplePlayer) GetName() string { return ep.name }
func (ep *ExamplePlayer) IsPlayer() bool { return true }
func (ep *ExamplePlayer) IsNPC() bool { return false }
func (ep *ExamplePlayer) IsBot() bool { return false }
// Implement the Player interface
func (ep *ExamplePlayer) GetCharacterID() int32 { return ep.characterID }
func (ep *ExamplePlayer) SendMessage(message string) {
// In real implementation, this would send a message to the client
}
// Implement the LanguageAware interface by delegating to the adapter
func (ep *ExamplePlayer) GetKnownLanguages() *PlayerLanguagesList {
return ep.languageAdapter.GetKnownLanguages()
}
func (ep *ExamplePlayer) KnowsLanguage(languageID int32) bool {
return ep.languageAdapter.KnowsLanguage(languageID)
}
func (ep *ExamplePlayer) GetPrimaryLanguage() int32 {
return ep.languageAdapter.GetPrimaryLanguage()
}
func (ep *ExamplePlayer) SetPrimaryLanguage(languageID int32) {
ep.languageAdapter.SetPrimaryLanguage(languageID)
}
func (ep *ExamplePlayer) CanUnderstand(languageID int32) bool {
return ep.languageAdapter.CanUnderstand(languageID)
}
func (ep *ExamplePlayer) LearnLanguage(languageID int32) error {
return ep.languageAdapter.LearnLanguage(languageID)
}
func (ep *ExamplePlayer) ForgetLanguage(languageID int32) error {
return ep.languageAdapter.ForgetLanguage(languageID)
}
// Database integration methods
func (ep *ExamplePlayer) LoadLanguagesFromDatabase(database Database) error {
return ep.languageAdapter.LoadPlayerLanguages(database, ep.characterID)
}
func (ep *ExamplePlayer) SaveLanguagesToDatabase(database Database) error {
return ep.languageAdapter.SavePlayerLanguages(database, ep.characterID)
}
// ExampleNPC shows how an NPC might implement basic language interfaces
type ExampleNPC struct {
id int32
name string
knownLanguageIDs []int32
primaryLanguage int32
}
func NewExampleNPC(id int32, name string, knownLanguages []int32) *ExampleNPC {
primaryLang := int32(LanguageIDCommon)
if len(knownLanguages) > 0 {
primaryLang = knownLanguages[0]
}
return &ExampleNPC{
id: id,
name: name,
knownLanguageIDs: knownLanguages,
primaryLanguage: primaryLang,
}
}
// Implement the Entity interface
func (en *ExampleNPC) GetID() int32 { return en.id }
func (en *ExampleNPC) GetName() string { return en.name }
func (en *ExampleNPC) IsPlayer() bool { return false }
func (en *ExampleNPC) IsNPC() bool { return true }
func (en *ExampleNPC) IsBot() bool { return false }
// Implement the Player interface (NPCs can also be treated as players for some language operations)
func (en *ExampleNPC) GetCharacterID() int32 { return en.id }
func (en *ExampleNPC) SendMessage(message string) {
// NPCs don't typically receive messages, but implement for interface compatibility
}
// Simple language support for NPCs (they don't learn/forget languages)
func (en *ExampleNPC) KnowsLanguage(languageID int32) bool {
for _, id := range en.knownLanguageIDs {
if id == languageID {
return true
}
}
return languageID == LanguageIDCommon // NPCs always understand common
}
func (en *ExampleNPC) GetPrimaryLanguage() int32 {
return en.primaryLanguage
}
func (en *ExampleNPC) CanUnderstand(languageID int32) bool {
return en.KnowsLanguage(languageID)
}
// TestEntityIntegration demonstrates how entities work with the language system
func TestEntityIntegration(t *testing.T) {
// Set up language system
database := NewMockDatabase()
logger := NewMockLogger()
manager := NewManager(database, logger)
// Add some languages
languages := []*Language{
createLanguage(LanguageIDCommon, "Common"),
createLanguage(LanguageIDElvish, "Elvish"),
createLanguage(LanguageIDDwarven, "Dwarven"),
createLanguage(LanguageIDOgrish, "Ogrish"),
}
for _, lang := range languages {
manager.AddLanguage(lang)
}
// Create a player
player := NewExamplePlayer(1, "TestPlayer", manager, logger)
// Player should know Common language by default
if !player.KnowsLanguage(LanguageIDCommon) {
t.Error("Player should know Common language by default")
}
// Test learning a language
err := player.LearnLanguage(LanguageIDElvish)
if err != nil {
t.Fatalf("Failed to learn Elvish: %v", err)
}
if !player.KnowsLanguage(LanguageIDElvish) {
t.Error("Player should know Elvish after learning")
}
// Test setting primary language
player.SetPrimaryLanguage(LanguageIDElvish)
if player.GetPrimaryLanguage() != LanguageIDElvish {
t.Error("Primary language should be Elvish")
}
// Test database persistence
err = player.SaveLanguagesToDatabase(database)
if err != nil {
t.Fatalf("Failed to save languages to database: %v", err)
}
// Create new player and load languages
newPlayer := NewExamplePlayer(1, "TestPlayer", manager, logger)
err = newPlayer.LoadLanguagesFromDatabase(database)
if err != nil {
t.Fatalf("Failed to load languages from database: %v", err)
}
if !newPlayer.KnowsLanguage(LanguageIDElvish) {
t.Error("New player should know Elvish after loading from database")
}
// Create an NPC with specific languages
npc := NewExampleNPC(100, "Elven Merchant", []int32{LanguageIDCommon, LanguageIDElvish})
if !npc.KnowsLanguage(LanguageIDElvish) {
t.Error("Elven NPC should know Elvish")
}
if npc.KnowsLanguage(LanguageIDDwarven) {
t.Error("Elven NPC should not know Dwarven")
}
// Test chat processing
processor := NewChatLanguageProcessor(manager, logger)
// Player speaking in Elvish
message := "Mae govannen!" // Elvish greeting
processed, err := processor.ProcessMessage(player, message, LanguageIDElvish)
if err != nil {
t.Fatalf("Failed to process Elvish message: %v", err)
}
if processed != message {
t.Errorf("Expected message '%s', got '%s'", message, processed)
}
// Test message filtering for understanding
filtered := processor.FilterMessage(npc, message, LanguageIDElvish)
if filtered != message {
t.Errorf("NPC should understand Elvish message, got '%s'", filtered)
}
}
// TestLanguageSystemIntegration demonstrates a complete language system workflow
func TestLanguageSystemIntegration(t *testing.T) {
// Set up a complete language system
database := NewMockDatabase()
logger := NewMockLogger()
// Create manager and initialize with standard EQ2 languages
manager := NewManager(database, logger)
eq2Languages := map[int32]string{
LanguageIDCommon: "Common",
LanguageIDElvish: "Elvish",
LanguageIDDwarven: "Dwarven",
LanguageIDHalfling: "Halfling",
LanguageIDGnomish: "Gnomish",
LanguageIDIksar: "Iksar",
LanguageIDTrollish: "Trollish",
LanguageIDOgrish: "Ogrish",
LanguageIDFae: "Fae",
LanguageIDArasai: "Arasai",
LanguageIDSarnak: "Sarnak",
LanguageIDFroglok: "Froglok",
}
for id, name := range eq2Languages {
lang := createLanguage(id, name)
manager.AddLanguage(lang)
}
if err := manager.Initialize(); err != nil {
t.Fatalf("Failed to initialize manager: %v", err)
}
// Create players of different races (represented by knowing different racial languages)
humanPlayer := NewExamplePlayer(1, "Human", manager, logger)
elfPlayer := NewExamplePlayer(2, "Elf", manager, logger)
dwarfPlayer := NewExamplePlayer(3, "Dwarf", manager, logger)
// Elven player learns Elvish at creation (racial language)
elfPlayer.LearnLanguage(LanguageIDElvish)
elfPlayer.SetPrimaryLanguage(LanguageIDElvish)
// Dwarven player learns Dwarven
dwarfPlayer.LearnLanguage(LanguageIDDwarven)
dwarfPlayer.SetPrimaryLanguage(LanguageIDDwarven)
// Test cross-racial communication
processor := NewChatLanguageProcessor(manager, logger)
// Elf speaks in Elvish
elvishMessage := "Elen sila lumenn omentielvo"
processed, _ := processor.ProcessMessage(elfPlayer, elvishMessage, LanguageIDElvish)
// Human doesn't understand Elvish (would be scrambled in real implementation)
humanHeard := processor.FilterMessage(humanPlayer, processed, LanguageIDElvish)
_ = humanHeard // In real implementation, this would be scrambled
// Dwarf doesn't understand Elvish either
dwarfHeard := processor.FilterMessage(dwarfPlayer, processed, LanguageIDElvish)
_ = dwarfHeard // In real implementation, this would be scrambled
// Everyone understands Common
commonMessage := "Hello everyone!"
processed, _ = processor.ProcessMessage(humanPlayer, commonMessage, LanguageIDCommon)
humanHeardCommon := processor.FilterMessage(humanPlayer, processed, LanguageIDCommon)
if humanHeardCommon != commonMessage {
t.Error("All players should understand Common")
}
elfHeardCommon := processor.FilterMessage(elfPlayer, processed, LanguageIDCommon)
if elfHeardCommon != commonMessage {
t.Error("All players should understand Common")
}
dwarfHeardCommon := processor.FilterMessage(dwarfPlayer, processed, LanguageIDCommon)
if dwarfHeardCommon != commonMessage {
t.Error("All players should understand Common")
}
// Test statistics
stats := manager.GetStatistics()
if stats.TotalLanguages != len(eq2Languages) {
t.Errorf("Expected %d languages, got %d", len(eq2Languages), stats.TotalLanguages)
}
// Test validation
issues := manager.ValidateAllLanguages()
if len(issues) > 0 {
t.Errorf("Expected no validation issues, got: %v", issues)
}
}
// Helper function to create languages
func createLanguage(id int32, name string) *Language {
lang := NewLanguage()
lang.SetID(id)
lang.SetName(name)
return lang
}
// TestLanguageAwareInterface demonstrates the LanguageAware interface usage
func TestLanguageAwareInterface(t *testing.T) {
database := NewMockDatabase()
logger := NewMockLogger()
manager := NewManager(database, logger)
// Add languages
manager.AddLanguage(createLanguage(LanguageIDCommon, "Common"))
manager.AddLanguage(createLanguage(LanguageIDElvish, "Elvish"))
// Create a player that implements LanguageAware
player := NewExamplePlayer(1, "TestPlayer", manager, logger)
// Test LanguageAware interface methods
var languageAware LanguageAware = player
// Should know Common by default
if !languageAware.KnowsLanguage(LanguageIDCommon) {
t.Error("LanguageAware entity should know Common by default")
}
// Learn a new language
err := languageAware.LearnLanguage(LanguageIDElvish)
if err != nil {
t.Fatalf("Failed to learn language through LanguageAware interface: %v", err)
}
// Check understanding
if !languageAware.CanUnderstand(LanguageIDElvish) {
t.Error("Should understand Elvish after learning")
}
// Set primary language
languageAware.SetPrimaryLanguage(LanguageIDElvish)
if languageAware.GetPrimaryLanguage() != LanguageIDElvish {
t.Error("Primary language should be Elvish")
}
// Get known languages
knownLanguages := languageAware.GetKnownLanguages()
if knownLanguages.Size() != 2 { // Common + Elvish
t.Errorf("Expected 2 known languages, got %d", knownLanguages.Size())
}
}
// Benchmark integration performance
func BenchmarkIntegratedPlayerLanguageOperations(b *testing.B) {
database := NewMockDatabase()
logger := NewMockLogger()
manager := NewManager(database, logger)
// Add languages
for i := 0; i < 50; i++ {
lang := createLanguage(int32(i), fmt.Sprintf("Language_%d", i))
manager.AddLanguage(lang)
}
player := NewExamplePlayer(1, "BenchmarkPlayer", manager, logger)
b.ResetTimer()
for i := 0; i < b.N; i++ {
langID := int32(i % 50)
if !player.KnowsLanguage(langID) {
player.LearnLanguage(langID)
}
player.CanUnderstand(langID)
}
}