2016-05-09 20:45:02 +00:00
// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors.
package babbler
import (
2017-05-10 12:41:41 +00:00
"database/sql"
2017-05-09 23:41:40 +00:00
"errors"
2016-05-09 20:45:02 +00:00
"fmt"
2017-05-09 23:41:40 +00:00
"log"
2016-05-09 20:45:02 +00:00
"math/rand"
"strings"
"github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
2016-05-11 01:15:52 +00:00
"github.com/velour/catbase/config"
2016-05-09 20:45:02 +00:00
)
2017-05-10 13:42:27 +00:00
var (
2017-05-17 14:06:10 +00:00
NO_BABBLER = errors . New ( "babbler not found" )
2017-05-10 13:42:27 +00:00
SAID_NOTHING = errors . New ( "hasn't said anything yet" )
2017-05-17 14:06:10 +00:00
NEVER_SAID = errors . New ( "never said that" )
2017-05-10 12:41:41 +00:00
)
2016-05-09 20:45:02 +00:00
type BabblerPlugin struct {
2017-05-09 23:41:40 +00:00
Bot bot . Bot
db * sqlx . DB
config * config . Config
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
type Babbler struct {
BabblerId int64 ` db:"id" `
Name string ` db:"babbler" `
}
type BabblerWord struct {
WordId int64 ` db:"id" `
Word string ` db:"word" `
}
type BabblerNode struct {
NodeId int64 ` db:"id" `
BabblerId int64 ` db:"babblerId" `
WordId int64 ` db:"wordId" `
Root int64 ` db:"root" `
RootFrequency int64 ` db:"rootFrequency" `
}
type BabblerArc struct {
ArcId int64 ` db:"id" `
FromNodeId int64 ` db:"fromNodeId" `
ToNodeId int64 ` db:"toNodeId" `
Frequency int64 ` db:"frequency" `
}
2017-05-09 23:41:40 +00:00
func New ( bot bot . Bot ) * BabblerPlugin {
log . SetFlags ( log . LstdFlags | log . Lshortfile )
if bot . DBVersion ( ) == 1 {
if _ , err := bot . DB ( ) . Exec ( ` create table if not exists babblers (
id integer primary key ,
babbler string
) ; ` ) ; err != nil {
log . Fatal ( err )
}
2017-05-10 15:59:35 +00:00
2017-05-09 23:41:40 +00:00
if _ , err := bot . DB ( ) . Exec ( ` create table if not exists babblerWords (
2017-05-10 15:59:35 +00:00
id integer primary key ,
word string
) ; ` ) ; err != nil {
log . Fatal ( err )
}
if _ , err := bot . DB ( ) . Exec ( ` create table if not exists babblerNodes (
2017-05-09 23:41:40 +00:00
id integer primary key ,
babblerId integer ,
2017-05-10 15:59:35 +00:00
wordId integer ,
2017-05-09 23:41:40 +00:00
root integer ,
rootFrequency integer
) ; ` ) ; err != nil {
log . Fatal ( err )
}
2016-05-09 20:45:02 +00:00
2017-05-09 23:41:40 +00:00
if _ , err := bot . DB ( ) . Exec ( ` create table if not exists babblerArcs (
id integer primary key ,
2017-05-17 14:06:10 +00:00
fromNodeId integer ,
toNodeId interger ,
2017-05-09 23:41:40 +00:00
frequency integer
) ; ` ) ; err != nil {
log . Fatal ( err )
}
}
2016-05-09 20:45:02 +00:00
plugin := & BabblerPlugin {
2017-05-09 23:41:40 +00:00
Bot : bot ,
db : bot . DB ( ) ,
config : bot . Config ( ) ,
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
plugin . createNewWord ( "" )
2016-05-11 01:15:52 +00:00
return plugin
}
2016-05-09 20:45:02 +00:00
func ( p * BabblerPlugin ) Message ( message msg . Message ) bool {
lowercase := strings . ToLower ( message . Body )
tokens := strings . Fields ( lowercase )
2016-10-19 23:34:16 +00:00
numTokens := len ( tokens )
2016-05-09 20:45:02 +00:00
2017-05-10 13:42:27 +00:00
saidSomething := false
saidWhat := ""
2017-05-09 23:41:40 +00:00
2017-05-10 13:42:27 +00:00
if numTokens >= 2 && tokens [ 1 ] == "says" {
saidWhat , saidSomething = p . getBabble ( tokens )
2016-05-11 17:07:16 +00:00
} else if len ( tokens ) == 4 && strings . Index ( lowercase , "initialize babbler for " ) == 0 {
2017-05-10 13:42:27 +00:00
saidWhat , saidSomething = p . initializeBabbler ( tokens )
2016-05-11 17:07:16 +00:00
} else if strings . Index ( lowercase , "batch learn for " ) == 0 {
2017-05-10 13:42:27 +00:00
saidWhat , saidSomething = p . batchLearn ( tokens )
2016-05-26 15:06:22 +00:00
} else if len ( tokens ) == 5 && strings . Index ( lowercase , "merge babbler" ) == 0 {
2017-05-10 13:42:27 +00:00
saidWhat , saidSomething = p . merge ( tokens )
2016-05-11 16:11:21 +00:00
} else {
2017-05-10 13:42:27 +00:00
//this should always return "", false
saidWhat , saidSomething = p . addToBabbler ( message . User . Name , lowercase )
2016-05-09 20:45:02 +00:00
}
2017-05-10 13:42:27 +00:00
if saidSomething {
p . Bot . SendMessage ( message . Channel , saidWhat )
}
return saidSomething
2016-05-09 20:45:02 +00:00
}
func ( p * BabblerPlugin ) Help ( channel string , parts [ ] string ) {
2016-05-11 01:15:52 +00:00
p . Bot . SendMessage ( channel , "initialize babbler for seabass\n\nseabass says" )
2016-05-09 20:45:02 +00:00
}
func ( p * BabblerPlugin ) Event ( kind string , message msg . Message ) bool {
return false
}
func ( p * BabblerPlugin ) BotMessage ( message msg . Message ) bool {
return false
}
func ( p * BabblerPlugin ) RegisterWeb ( ) * string {
return nil
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) makeBabbler ( name string ) ( * Babbler , error ) {
res , err := p . db . Exec ( ` insert into babblers (babbler) values (?); ` , name )
2017-05-09 23:41:40 +00:00
if err == nil {
2017-05-17 14:06:10 +00:00
id , err := res . LastInsertId ( )
if err != nil {
log . Print ( err )
return nil , err
}
return & Babbler {
BabblerId : id ,
Name : name ,
} , nil
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
return nil , err
2017-05-09 23:41:40 +00:00
}
2016-05-09 20:45:02 +00:00
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getBabbler ( name string ) ( * Babbler , error ) {
var bblr Babbler
err := p . db . QueryRowx ( ` select * from babblers where babbler = ? LIMIT 1; ` , name ) . StructScan ( & bblr )
if err != nil {
if err == sql . ErrNoRows {
log . Printf ( "failed to find babbler" )
return nil , NO_BABBLER
}
log . Printf ( "encountered problem in babbler lookup" )
log . Print ( err )
return nil , err
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
return & bblr , nil
2017-05-09 23:41:40 +00:00
}
2016-05-09 20:45:02 +00:00
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getOrCreateBabbler ( name string ) ( * Babbler , error ) {
babbler , err := p . getBabbler ( name )
if err == NO_BABBLER {
babbler , err = p . makeBabbler ( name )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
return nil , err
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
rows , err := p . db . Queryx ( fmt . Sprintf ( "select tidbit from factoid where fact like '%s quotes';" , babbler . Name ) )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
return babbler , nil
2017-05-09 23:41:40 +00:00
}
2017-05-10 13:50:37 +00:00
defer rows . Close ( )
2017-05-10 12:41:41 +00:00
2017-05-10 13:50:37 +00:00
tidbits := [ ] string { }
2017-05-09 23:41:40 +00:00
for rows . Next ( ) {
var tidbit string
err := rows . Scan ( & tidbit )
2017-05-17 14:06:10 +00:00
log . Print ( tidbit )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
return babbler , err
2016-05-09 20:45:02 +00:00
}
2017-05-10 13:50:37 +00:00
tidbits = append ( tidbits , tidbit )
}
for _ , tidbit := range tidbits {
2017-05-17 14:06:10 +00:00
if err = p . addToMarkovChain ( babbler , tidbit ) ; err != nil {
log . Print ( err )
}
2016-05-09 20:45:02 +00:00
}
}
2017-05-17 14:06:10 +00:00
return babbler , err
2017-05-09 23:41:40 +00:00
}
2016-05-09 20:45:02 +00:00
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getWord ( word string ) ( * BabblerWord , error ) {
var w BabblerWord
err := p . db . QueryRowx ( ` select * from babblerWords where word = ? LIMIT 1; ` , word ) . StructScan ( & w )
if err != nil {
if err == sql . ErrNoRows {
return nil , NEVER_SAID
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
return nil , err
2017-05-10 14:11:49 +00:00
}
2017-05-17 14:06:10 +00:00
return & w , nil
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) createNewWord ( word string ) ( * BabblerWord , error ) {
res , err := p . db . Exec ( ` insert into babblerWords (word) values (?); ` , word )
if err != nil {
log . Print ( err )
return nil , err
}
id , err := res . LastInsertId ( )
if err != nil {
log . Print ( err )
return nil , err
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
return & BabblerWord {
WordId : id ,
Word : word ,
} , nil
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getOrCreateWord ( word string ) ( * BabblerWord , error ) {
if w , err := p . getWord ( word ) ; err == NEVER_SAID {
2017-05-10 15:59:35 +00:00
return p . createNewWord ( word )
} else {
2017-05-17 14:06:10 +00:00
if err != nil {
log . Print ( err )
}
return w , err
2017-05-10 15:59:35 +00:00
}
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getBabblerNode ( babbler * Babbler , word string ) ( * BabblerNode , error ) {
w , err := p . getWord ( word )
if err != nil {
return nil , err
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
var node BabblerNode
err = p . db . QueryRowx ( ` select * from babblerNodes where babblerId = ? and wordId = ? LIMIT 1; ` , babbler . BabblerId , w . WordId ) . StructScan ( & node )
if err != nil {
if err == sql . ErrNoRows {
return nil , NEVER_SAID
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
return nil , err
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
return & node , nil
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) createBabblerNode ( babbler * Babbler , word string ) ( * BabblerNode , error ) {
w , err := p . getOrCreateWord ( word )
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , err
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
res , err := p . db . Exec ( ` insert into babblerNodes (babblerId, wordId, root, rootFrequency) values (?, ?, 0, 0) ` , babbler . BabblerId , w . WordId )
if err != nil {
log . Print ( err )
return nil , err
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
id , err := res . LastInsertId ( )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , err
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
return & BabblerNode {
NodeId : id ,
WordId : w . WordId ,
Root : 0 ,
RootFrequency : 0 ,
} , nil
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getOrCreateBabblerNode ( babbler * Babbler , word string ) ( * BabblerNode , error ) {
node , err := p . getBabblerNode ( babbler , word )
if err != nil {
return p . createBabblerNode ( babbler , word )
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
return node , nil
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) incrementRootWordFrequency ( babbler * Babbler , word string ) ( * BabblerNode , error ) {
node , err := p . getOrCreateBabblerNode ( babbler , word )
if err != nil {
log . Print ( err )
return nil , err
}
_ , err = p . db . Exec ( ` update babblerNodes set rootFrequency = rootFrequency + 1, root = 1 where id = ?; ` , node . NodeId )
if err != nil {
log . Print ( err )
return nil , err
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
node . RootFrequency += 1
return node , nil
}
2017-05-10 15:59:35 +00:00
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getBabblerArc ( fromNode , toNode * BabblerNode ) ( * BabblerArc , error ) {
var arc BabblerArc
err := p . db . QueryRowx ( ` select * from babblerArcs where fromNodeId = ? and toNodeId = ?; ` , fromNode . NodeId , toNode . NodeId ) . StructScan ( & arc )
if err != nil {
if err == sql . ErrNoRows {
return nil , NEVER_SAID
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
return nil , err
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
return & arc , nil
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) incrementWordArc ( fromNode , toNode * BabblerNode ) ( * BabblerArc , error ) {
res , err := p . db . Exec ( ` update babblerArcs set frequency = frequency + 1 where fromNodeId = ? and toNodeId = ?; ` , fromNode . NodeId , toNode . NodeId )
2017-05-10 15:59:35 +00:00
if err != nil {
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , err
2017-05-10 15:59:35 +00:00
}
2017-05-09 23:41:40 +00:00
affectedRows := int64 ( 0 )
if err == nil {
affectedRows , _ = res . RowsAffected ( )
}
2017-05-17 14:06:10 +00:00
if affectedRows == 0 {
res , err = p . db . Exec ( ` insert into babblerArcs (fromNodeId, toNodeId, frequency) values (?, ?, 1); ` , fromNode . NodeId , toNode . NodeId )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , err
2016-05-09 20:45:02 +00:00
}
}
2017-05-17 14:06:10 +00:00
return p . getBabblerArc ( fromNode , toNode )
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) incrementFinalWordArcHelper ( babbler * Babbler , node * BabblerNode ) ( * BabblerArc , error ) {
nextNode , err := p . getOrCreateBabblerNode ( babbler , " " )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
return nil , err
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
return p . incrementWordArc ( node , nextNode )
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) addToMarkovChain ( babbler * Babbler , phrase string ) error {
2017-05-09 23:41:40 +00:00
words := strings . Fields ( strings . ToLower ( phrase ) )
2017-05-10 13:42:27 +00:00
if len ( words ) <= 0 {
2017-05-17 14:06:10 +00:00
return nil
2017-05-10 13:42:27 +00:00
}
2017-05-17 14:06:10 +00:00
curNode , err := p . incrementRootWordFrequency ( babbler , words [ 0 ] )
2016-05-09 20:45:02 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return err
2016-05-09 20:45:02 +00:00
}
2017-05-09 23:41:40 +00:00
for i := 1 ; i < len ( words ) ; i ++ {
2017-05-17 14:06:10 +00:00
nextNode , err := p . getOrCreateBabblerNode ( babbler , words [ i ] )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return err
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
_ , err = p . incrementWordArc ( curNode , nextNode )
if err != nil {
log . Print ( err )
return err
}
curNode = nextNode
2017-05-09 23:41:40 +00:00
}
2016-05-09 20:45:02 +00:00
2017-05-17 14:06:10 +00:00
_ , err = p . incrementFinalWordArcHelper ( babbler , curNode )
return err
2017-05-09 23:41:40 +00:00
}
2016-05-09 20:45:02 +00:00
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getWeightedRootNode ( babbler * Babbler ) ( * BabblerNode , * BabblerWord , error ) {
rows , err := p . db . Queryx ( ` select * from babblerNodes where babblerId = ? and root = 1; ` , babbler . BabblerId )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , nil , err
2017-05-09 23:41:40 +00:00
}
defer rows . Close ( )
2017-05-17 14:06:10 +00:00
rootNodes := [ ] * BabblerNode { }
2017-05-09 23:41:40 +00:00
total := int64 ( 0 )
for rows . Next ( ) {
2017-05-17 14:06:10 +00:00
var node BabblerNode
err = rows . StructScan ( & node )
2016-05-09 20:45:02 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , nil , err
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
rootNodes = append ( rootNodes , & node )
total += node . RootFrequency
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
if len ( rootNodes ) == 0 {
return nil , nil , SAID_NOTHING
2017-05-10 12:41:41 +00:00
}
2017-05-09 23:41:40 +00:00
which := rand . Int63n ( total )
total = 0
2017-05-17 14:06:10 +00:00
for _ , node := range rootNodes {
total += node . RootFrequency
if total >= which {
var w BabblerWord
err := p . db . QueryRowx ( ` select * from babblerWords where id = ? LIMIT 1; ` , node . WordId ) . StructScan ( & w )
2017-05-10 15:59:35 +00:00
if err != nil {
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , nil , err
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
return node , & w , nil
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
2017-05-09 23:41:40 +00:00
}
log . Fatalf ( "shouldn't happen" )
2017-05-17 14:06:10 +00:00
return nil , nil , errors . New ( "failed to find weighted root word" )
2016-10-19 23:34:16 +00:00
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) getWeightedNextWord ( fromNode * BabblerNode ) ( * BabblerNode , * BabblerWord , error ) {
rows , err := p . db . Queryx ( ` select * from babblerArcs where fromNodeId = ?; ` , fromNode . NodeId )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , nil , err
2017-05-09 23:41:40 +00:00
}
defer rows . Close ( )
2017-05-17 14:06:10 +00:00
arcs := [ ] * BabblerArc { }
2017-05-09 23:41:40 +00:00
total := int64 ( 0 )
for rows . Next ( ) {
2017-05-17 14:06:10 +00:00
var arc BabblerArc
err = rows . StructScan ( & arc )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , nil , err
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
arcs = append ( arcs , & arc )
total += arc . Frequency
2017-05-09 23:41:40 +00:00
}
2017-04-07 19:35:18 +00:00
2017-05-17 14:06:10 +00:00
if len ( arcs ) == 0 {
return nil , nil , errors . New ( "missing arcs" )
2017-05-10 12:41:41 +00:00
}
2017-05-09 23:41:40 +00:00
which := rand . Int63n ( total )
total = 0
2017-05-17 14:06:10 +00:00
for _ , arc := range arcs {
2017-04-07 19:35:18 +00:00
2017-05-17 14:06:10 +00:00
total += arc . Frequency
if total >= which {
var node BabblerNode
err := p . db . QueryRowx ( ` select * from babblerNodes where id = ? LIMIT 1; ` , arc . ToNodeId ) . StructScan ( & node )
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , nil , err
2017-05-10 15:59:35 +00:00
}
2017-05-17 14:06:10 +00:00
var w BabblerWord
err = p . db . QueryRowx ( ` select * from babblerWords where id = ? LIMIT 1; ` , node . WordId ) . StructScan ( & w )
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-17 14:06:10 +00:00
return nil , nil , err
2017-04-07 19:35:18 +00:00
}
2017-05-17 14:06:10 +00:00
return & node , & w , nil
2017-04-07 19:35:18 +00:00
}
2017-05-17 14:06:10 +00:00
2017-05-09 23:41:40 +00:00
}
log . Fatalf ( "shouldn't happen" )
2017-05-17 14:06:10 +00:00
return nil , nil , errors . New ( "failed to find weighted next word" )
2017-05-09 23:41:40 +00:00
}
2017-04-07 19:35:18 +00:00
2017-05-09 23:41:40 +00:00
func ( p * BabblerPlugin ) babble ( who string ) ( string , error ) {
return p . babbleSeed ( who , [ ] string { } )
}
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) babbleSeed ( babblerName string , seed [ ] string ) ( string , error ) {
babbler , err := p . getBabbler ( babblerName )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return "" , nil
}
words := seed
2017-05-17 14:06:10 +00:00
var curNode * BabblerNode
var curWord * BabblerWord
2017-05-09 23:41:40 +00:00
if len ( seed ) == 0 {
2017-05-17 14:06:10 +00:00
curNode , curWord , err = p . getWeightedRootNode ( babbler )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return "" , err
}
2017-05-17 14:06:10 +00:00
words = append ( words , curWord . Word )
2017-05-09 23:41:40 +00:00
} else {
2017-05-17 14:06:10 +00:00
curNode , err = p . getBabblerNode ( babbler , seed [ 0 ] )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return "" , err
}
for i := 1 ; i < len ( seed ) ; i ++ {
2017-05-17 14:06:10 +00:00
nextNode , err := p . getBabblerNode ( babbler , seed [ i ] )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return "" , err
2016-05-09 20:45:02 +00:00
}
2017-05-17 14:06:10 +00:00
_ , err = p . getBabblerArc ( curNode , nextNode )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return "" , err
}
2017-05-17 14:06:10 +00:00
curNode = nextNode
2016-05-09 20:45:02 +00:00
}
2017-05-09 23:41:40 +00:00
}
2016-05-09 20:45:02 +00:00
2017-05-09 23:41:40 +00:00
for {
2017-05-17 14:06:10 +00:00
curNode , curWord , err = p . getWeightedNextWord ( curNode )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return "" , err
}
2017-05-17 14:06:10 +00:00
if curWord . Word == " " {
2017-05-09 23:41:40 +00:00
break
}
2017-05-17 14:06:10 +00:00
words = append ( words , curWord . Word )
2016-05-09 20:45:02 +00:00
}
2017-05-09 23:41:40 +00:00
return strings . TrimSpace ( strings . Join ( words , " " ) ) , nil
2016-05-11 01:15:52 +00:00
}
2016-05-26 15:06:22 +00:00
2017-05-17 14:06:10 +00:00
func ( p * BabblerPlugin ) mergeBabblers ( intoBabbler , otherBabbler * Babbler , intoName , otherName string ) error {
intoNode , err := p . getOrCreateBabblerNode ( intoBabbler , "<" + intoName + ">" )
2017-05-10 15:59:35 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-10 15:59:35 +00:00
return err
}
2017-05-17 14:06:10 +00:00
otherNode , err := p . getOrCreateBabblerNode ( otherBabbler , "<" + otherName + ">" )
2017-05-10 15:59:35 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-10 15:59:35 +00:00
return err
}
2017-05-17 14:06:10 +00:00
mapping := map [ int64 ] * BabblerNode { }
2016-05-26 15:06:22 +00:00
2017-05-17 14:06:10 +00:00
rows , err := p . db . Queryx ( "select * from babblerNodes where babblerId = ?;" , otherBabbler . BabblerId )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return err
}
defer rows . Close ( )
2017-05-17 14:06:10 +00:00
nodes := [ ] * BabblerNode { }
2017-05-09 23:41:40 +00:00
for rows . Next ( ) {
2017-05-17 14:06:10 +00:00
var node BabblerNode
err = rows . StructScan ( & node )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return err
2016-05-26 15:06:22 +00:00
}
2017-05-17 14:06:10 +00:00
nodes = append ( nodes , & node )
2017-05-09 23:41:40 +00:00
}
2016-05-26 15:06:22 +00:00
2017-05-17 14:06:10 +00:00
for _ , node := range nodes {
var res sql . Result
2017-05-09 23:41:40 +00:00
2017-05-17 14:06:10 +00:00
if node . NodeId == otherNode . NodeId {
node . WordId = intoNode . WordId
2016-05-26 15:06:22 +00:00
}
2017-05-17 14:06:10 +00:00
if node . Root > 0 {
res , err = p . db . Exec ( ` update babblerNodes set rootFrequency = rootFrequency + ?, root = 1 where babblerId = ? and wordId = ?; ` , node . RootFrequency , intoBabbler . BabblerId , node . WordId )
if err != nil {
log . Print ( err )
}
2017-05-09 23:41:40 +00:00
} else {
2017-05-17 14:06:10 +00:00
res , err = p . db . Exec ( ` update babblerNodes set rootFrequency = rootFrequency + ? where babblerId = ? and wordId = ?; ` , node . RootFrequency , intoBabbler . BabblerId , node . WordId )
if err != nil {
log . Print ( err )
}
2017-05-09 23:41:40 +00:00
}
2016-05-26 15:06:22 +00:00
2017-05-10 15:59:35 +00:00
rowsAffected := int64 ( - 1 )
if err == nil {
rowsAffected , _ = res . RowsAffected ( )
}
if err != nil || rowsAffected == 0 {
2017-05-17 14:06:10 +00:00
res , err = p . db . Exec ( ` insert into babblerNodes (babblerId, wordId, root, rootFrequency) values (?,?,?,?) ; ` , intoBabbler . BabblerId , node . WordId , node . Root , node . RootFrequency )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-10 15:59:35 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return err
2016-05-26 15:06:22 +00:00
}
}
2017-05-09 23:41:40 +00:00
2017-05-17 14:06:10 +00:00
var updatedNode BabblerNode
err = p . db . QueryRowx ( ` select * from babblerNodes where babblerId = ? and wordId = ? LIMIT 1; ` , intoBabbler . BabblerId , node . WordId ) . StructScan ( & updatedNode )
if err != nil {
log . Print ( err )
return err
2017-05-10 15:59:35 +00:00
}
2016-05-26 15:06:22 +00:00
2017-05-17 14:06:10 +00:00
mapping [ node . NodeId ] = & updatedNode
2017-05-09 23:41:40 +00:00
}
2017-05-17 14:06:10 +00:00
for oldNodeId , newNode := range mapping {
rows , err := p . db . Queryx ( "select * from babblerArcs where fromNodeId = ?;" , oldNodeId )
2017-05-09 23:41:40 +00:00
if err != nil {
return err
}
defer rows . Close ( )
2017-05-17 14:06:10 +00:00
arcs := [ ] * BabblerArc { }
2016-05-26 15:06:22 +00:00
2017-05-09 23:41:40 +00:00
for rows . Next ( ) {
2017-05-17 14:06:10 +00:00
var arc BabblerArc
err = rows . StructScan ( & arc )
2017-05-09 23:41:40 +00:00
if err != nil {
2017-05-17 14:06:10 +00:00
log . Print ( err )
2017-05-09 23:41:40 +00:00
return err
}
2017-05-17 14:06:10 +00:00
arcs = append ( arcs , & arc )
2016-05-26 15:06:22 +00:00
}
2017-05-09 23:41:40 +00:00
for _ , arc := range arcs {
2017-05-17 14:06:10 +00:00
_ , err := p . incrementWordArc ( newNode , mapping [ arc . ToNodeId ] )
if err != nil {
return err
2016-05-26 15:06:22 +00:00
}
}
}
2017-05-17 14:06:10 +00:00
return err
2016-05-26 15:06:22 +00:00
}