122 lines
2.8 KiB
Go
122 lines
2.8 KiB
Go
package companion
|
|
|
|
import (
|
|
"log/slog"
|
|
"sync"
|
|
|
|
"git.db123.ir/db123/divacode/internal/storage"
|
|
"git.db123.ir/db123/divacode/pkg/personality"
|
|
)
|
|
|
|
type RelationshipEngine struct {
|
|
mu sync.Mutex
|
|
db *storage.DB
|
|
}
|
|
|
|
func NewRelationshipEngine(db *storage.DB) *RelationshipEngine {
|
|
e := &RelationshipEngine{db: db}
|
|
e.seed()
|
|
return e
|
|
}
|
|
|
|
func (e *RelationshipEngine) seed() {
|
|
defaults := map[string]float64{
|
|
"familiarity": 0.0,
|
|
"trust": 0.3,
|
|
}
|
|
for metric, val := range defaults {
|
|
err := e.db.Exec(
|
|
"INSERT OR IGNORE INTO relationship_metrics (id, metric, value) VALUES (?, ?, ?)",
|
|
"rel_"+metric, metric, val,
|
|
)
|
|
if err != nil {
|
|
slog.Warn("seed metric failed", "metric", metric, "error", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (e *RelationshipEngine) Current() *personality.RelationshipMetrics {
|
|
e.mu.Lock()
|
|
defer e.mu.Unlock()
|
|
|
|
rm := &personality.RelationshipMetrics{}
|
|
|
|
row := e.db.QueryRow("SELECT value FROM relationship_metrics WHERE metric = 'familiarity'")
|
|
row.Scan(&rm.Familiarity)
|
|
|
|
row = e.db.QueryRow("SELECT value FROM relationship_metrics WHERE metric = 'trust'")
|
|
row.Scan(&rm.Trust)
|
|
|
|
topics, _ := e.db.Query("SELECT topic FROM shared_topics ORDER BY count DESC LIMIT 20")
|
|
if topics != nil {
|
|
defer topics.Close()
|
|
for topics.Next() {
|
|
var t string
|
|
topics.Scan(&t)
|
|
rm.SharedTopics = append(rm.SharedTopics, t)
|
|
}
|
|
}
|
|
|
|
jokes, _ := e.db.Query("SELECT joke FROM inside_jokes LIMIT 20")
|
|
if jokes != nil {
|
|
defer jokes.Close()
|
|
for jokes.Next() {
|
|
var j string
|
|
jokes.Scan(&j)
|
|
rm.InsideJokes = append(rm.InsideJokes, j)
|
|
}
|
|
}
|
|
|
|
return rm
|
|
}
|
|
|
|
func (e *RelationshipEngine) Trust() float64 {
|
|
var v float64
|
|
err := e.db.QueryRow("SELECT value FROM relationship_metrics WHERE metric = 'trust'").Scan(&v)
|
|
if err != nil {
|
|
return 0.3
|
|
}
|
|
return v
|
|
}
|
|
|
|
func (e *RelationshipEngine) UpdateFamiliarity(delta float64) error {
|
|
return e.adjust("familiarity", delta)
|
|
}
|
|
|
|
func (e *RelationshipEngine) UpdateTrust(delta float64) error {
|
|
return e.adjust("trust", delta)
|
|
}
|
|
|
|
func (e *RelationshipEngine) AddSharedTopic(topic string) error {
|
|
return e.db.Exec(
|
|
`INSERT INTO shared_topics (id, topic, count, last_discussed)
|
|
VALUES (?, ?, 1, datetime('now'))
|
|
ON CONFLICT(topic) DO UPDATE SET count = count + 1, last_discussed = datetime('now')`,
|
|
"topic_"+topic, topic,
|
|
)
|
|
}
|
|
|
|
func (e *RelationshipEngine) adjust(metric string, delta float64) error {
|
|
e.mu.Lock()
|
|
defer e.mu.Unlock()
|
|
|
|
var current float64
|
|
row := e.db.QueryRow("SELECT value FROM relationship_metrics WHERE metric = ?", metric)
|
|
if err := row.Scan(¤t); err != nil {
|
|
current = 0
|
|
}
|
|
|
|
newVal := current + delta
|
|
if newVal < 0 {
|
|
newVal = 0
|
|
}
|
|
if newVal > 1 {
|
|
newVal = 1
|
|
}
|
|
|
|
return e.db.Exec(
|
|
"UPDATE relationship_metrics SET value = ?, updated_at = datetime('now') WHERE metric = ?",
|
|
newVal, metric,
|
|
)
|
|
}
|