mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-27 13:19:24 +01:00
Markov *finally* works again. Yay!
This commit is contained in:
parent
3313080eef
commit
fbc1b04cae
@ -46,6 +46,7 @@ import random
|
|||||||
import os.path
|
import os.path
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
import supybot.world as world
|
||||||
import supybot.ircmsgs as ircmsgs
|
import supybot.ircmsgs as ircmsgs
|
||||||
import supybot.ircutils as ircutils
|
import supybot.ircutils as ircutils
|
||||||
import supybot.privmsgs as privmsgs
|
import supybot.privmsgs as privmsgs
|
||||||
@ -54,14 +55,14 @@ import supybot.callbacks as callbacks
|
|||||||
class MarkovDBInterface(object):
|
class MarkovDBInterface(object):
|
||||||
def close(self):
|
def close(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def addPair(self, channel, first, second, follower,
|
def addPair(self, channel, first, second, follower,
|
||||||
isFirst=False, isLast=False):
|
isFirst=False, isLast=False):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getFirstPair(self, channel):
|
def getFirstPair(self, channel):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getPair(self, channel, first, second):
|
def getPair(self, channel, first, second):
|
||||||
# Returns (follower, last) tuple.
|
# Returns (follower, last) tuple.
|
||||||
pass
|
pass
|
||||||
@ -73,16 +74,16 @@ class SqliteMarkovDB(object):
|
|||||||
|
|
||||||
def getFirstPair(self, channel):
|
def getFirstPair(self, channel):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getFollower(self, channel, first, second):
|
def getFollower(self, channel, first, second):
|
||||||
# Returns (follower, last) tuple.
|
# Returns (follower, last) tuple.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class DbmMarkovDB(object):
|
class DbmMarkovDB(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.dbs = ircutils.IrcDict()
|
self.dbs = ircutils.IrcDict()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
for db in self.dbs.values():
|
for db in self.dbs.values():
|
||||||
db.close()
|
db.close()
|
||||||
@ -92,39 +93,30 @@ class DbmMarkovDB(object):
|
|||||||
# Stupid anydbm seems to append .db to the end of this.
|
# Stupid anydbm seems to append .db to the end of this.
|
||||||
filename = plugins.makeChannelFilename(channel, 'DbmMarkovDB')
|
filename = plugins.makeChannelFilename(channel, 'DbmMarkovDB')
|
||||||
self.dbs[channel] = anydbm.open(filename, 'c')
|
self.dbs[channel] = anydbm.open(filename, 'c')
|
||||||
self.dbs[channel]['lasts'] = ''
|
|
||||||
self.dbs[channel]['firsts'] = ''
|
|
||||||
return self.dbs[channel]
|
return self.dbs[channel]
|
||||||
|
|
||||||
def _addFirst(self, db, combined):
|
|
||||||
db['firsts'] = db['firsts'] + (combined + '\n')
|
|
||||||
|
|
||||||
def _addLast(self, db, second, follower):
|
|
||||||
combined = self._combine(second, follower)
|
|
||||||
db['lasts'] = db['lasts'] + (combined + '\n')
|
|
||||||
|
|
||||||
def addPair(self, channel, first, second, follower,
|
def addPair(self, channel, first, second, follower,
|
||||||
isFirst=False, isLast=False):
|
isFirst=False, isLast=False):
|
||||||
db = self._getDb(channel)
|
db = self._getDb(channel)
|
||||||
combined = self._combine(first, second)
|
combined = self._combine(first, second)
|
||||||
if isFirst:
|
if combined in db: # EW!
|
||||||
self._addFirst(db, combined)
|
db[combined] = ' '.join([db[combined], follower])
|
||||||
elif isLast:
|
|
||||||
self._addLast(db, second, follower)
|
|
||||||
else:
|
else:
|
||||||
if db.has_key(combined): # EW!
|
db[combined] = follower
|
||||||
db[combined] = db[combined] + (' ' + follower)
|
if follower == '\n':
|
||||||
|
if '\n' in db:
|
||||||
|
db['\n'] = ' '.join([db['\n'], second])
|
||||||
else:
|
else:
|
||||||
db[combined] = follower
|
db['\n'] = second
|
||||||
#db.flush()
|
db.sync()
|
||||||
|
|
||||||
def getFirstPair(self, channel):
|
def getFirstPair(self, channel):
|
||||||
db = self._getDb(channel)
|
db = self._getDb(channel)
|
||||||
firsts = db['firsts'].splitlines()
|
firsts = db['\r \r'].split()
|
||||||
if firsts:
|
if firsts:
|
||||||
firsts.pop() # Empty line.
|
firsts.pop() # Empty line.
|
||||||
if firsts:
|
if firsts:
|
||||||
return random.choice(firsts).split()
|
return ('\r', random.choice(firsts))
|
||||||
else:
|
else:
|
||||||
raise KeyError, 'No firsts for %s.' % channel
|
raise KeyError, 'No firsts for %s.' % channel
|
||||||
else:
|
else:
|
||||||
@ -137,11 +129,31 @@ class DbmMarkovDB(object):
|
|||||||
db = self._getDb(channel)
|
db = self._getDb(channel)
|
||||||
followers = db[self._combine(first, second)]
|
followers = db[self._combine(first, second)]
|
||||||
follower = random.choice(followers.split())
|
follower = random.choice(followers.split())
|
||||||
if self._combine(second, follower) in db['lasts']:
|
return (follower, follower == '\n')
|
||||||
last = True
|
|
||||||
|
def firsts(self, channel):
|
||||||
|
db = self._getDb(channel)
|
||||||
|
if '\r \r' in db:
|
||||||
|
return len(db['\r \r'].split())
|
||||||
else:
|
else:
|
||||||
last = False
|
return 0
|
||||||
return (follower, last)
|
|
||||||
|
def lasts(self, channel):
|
||||||
|
db = self._getDb(channel)
|
||||||
|
if '\n' in db:
|
||||||
|
return len(db['\n'].split())
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def pairs(self, channel):
|
||||||
|
db = self._getDb(channel)
|
||||||
|
pairs = [k for k in db.keys() if '\n' not in k]
|
||||||
|
return len(pairs)
|
||||||
|
|
||||||
|
def follows(self, channel):
|
||||||
|
db = self._getDb(channel)
|
||||||
|
follows = [len(v.split()) for (k,v) in db.iteritems() if '\n' not in k]
|
||||||
|
return sum(follows)
|
||||||
|
|
||||||
def MarkovDB():
|
def MarkovDB():
|
||||||
return DbmMarkovDB()
|
return DbmMarkovDB()
|
||||||
@ -170,15 +182,15 @@ class MarkovWorkQueue(threading.Thread):
|
|||||||
if f is not None:
|
if f is not None:
|
||||||
f(self.db)
|
f(self.db)
|
||||||
self.db.close()
|
self.db.close()
|
||||||
|
|
||||||
class Markov(callbacks.Privmsg):
|
class Markov(callbacks.Privmsg):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.q = MarkovWorkQueue()
|
self.q = MarkovWorkQueue()
|
||||||
callbacks.Privmsg.__init__(self)
|
callbacks.Privmsg.__init__(self)
|
||||||
|
|
||||||
def die(self):
|
def die(self):
|
||||||
self.q.die()
|
self.q.die()
|
||||||
|
|
||||||
def tokenize(self, s):
|
def tokenize(self, s):
|
||||||
# XXX: Should this be smarter?
|
# XXX: Should this be smarter?
|
||||||
return s.split()
|
return s.split()
|
||||||
@ -187,18 +199,14 @@ class Markov(callbacks.Privmsg):
|
|||||||
channel = msg.args[0]
|
channel = msg.args[0]
|
||||||
if ircutils.isChannel(channel):
|
if ircutils.isChannel(channel):
|
||||||
words = self.tokenize(msg.args[1])
|
words = self.tokenize(msg.args[1])
|
||||||
if len(words) >= 3:
|
words.insert(0, '\r')
|
||||||
def doPrivmsg(db):
|
words.insert(0, '\r')
|
||||||
db.addPair(channel, words[0], words[1], words[2],
|
words.insert(-1, '\n')
|
||||||
isFirst=True)
|
def doPrivmsg(db):
|
||||||
db.addPair(channel, words[-3], words[-2], words[-1],
|
for (first, second, follower) in window(words, 3):
|
||||||
isLast=True)
|
db.addPair(channel, first, second, follower)
|
||||||
del words[0] # Remove first.
|
self.q.enqueue(doPrivmsg)
|
||||||
del words[-1] # Remove last.
|
|
||||||
for (first, second, follower) in window(words, 3):
|
|
||||||
db.addPair(channel, first, second, follower)
|
|
||||||
self.q.enqueue(doPrivmsg)
|
|
||||||
|
|
||||||
def markov(self, irc, msg, args):
|
def markov(self, irc, msg, args):
|
||||||
"""[<channel>]
|
"""[<channel>]
|
||||||
|
|
||||||
@ -213,12 +221,64 @@ class Markov(callbacks.Privmsg):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
irc.error('I don\'t have any first pairs for %s.' % channel)
|
irc.error('I don\'t have any first pairs for %s.' % channel)
|
||||||
return
|
return
|
||||||
|
# words[-2:] is of the form ('\r', word)
|
||||||
|
follower = words[-1]
|
||||||
last = False
|
last = False
|
||||||
|
resp = []
|
||||||
while not last:
|
while not last:
|
||||||
|
resp.append(follower)
|
||||||
(follower,last) = db.getFollower(channel, words[-2], words[-1])
|
(follower,last) = db.getFollower(channel, words[-2], words[-1])
|
||||||
words.append(follower)
|
words.append(follower)
|
||||||
irc.reply(' '.join(words))
|
irc.reply(' '.join(resp))
|
||||||
self.q.enqueue(markov)
|
self.q.enqueue(markov)
|
||||||
|
|
||||||
|
def firsts(self, irc, msg, args):
|
||||||
|
"""[<channel>]
|
||||||
|
|
||||||
|
Returns the number of Markov's first links in the database for
|
||||||
|
<channel>.
|
||||||
|
"""
|
||||||
|
channel = privmsgs.getChannel(msg, args)
|
||||||
|
def firsts(db):
|
||||||
|
s = 'There are %s firsts in my Markov database for %s.'
|
||||||
|
irc.reply(s % (db.firsts(channel), channel))
|
||||||
|
self.q.enqueue(firsts)
|
||||||
|
|
||||||
|
def lasts(self, irc, msg, args):
|
||||||
|
"""[<channel>]
|
||||||
|
|
||||||
|
Returns the number of Markov's last links in the database for
|
||||||
|
<channel>.
|
||||||
|
"""
|
||||||
|
channel = privmsgs.getChannel(msg, args)
|
||||||
|
def lasts(db):
|
||||||
|
s = 'There are %s lasts in my Markov database for %s.'
|
||||||
|
irc.reply(s % (db.lasts(channel), channel))
|
||||||
|
self.q.enqueue(lasts)
|
||||||
|
|
||||||
|
def pairs(self, irc, msg, args):
|
||||||
|
"""[<channel>]
|
||||||
|
|
||||||
|
Returns the number of Markov's chain links in the database for
|
||||||
|
<channel>.
|
||||||
|
"""
|
||||||
|
channel = privmsgs.getChannel(msg, args)
|
||||||
|
def pairs(db):
|
||||||
|
s = 'There are %s pairs in my Markov database for %s.'
|
||||||
|
irc.reply(s % (db.pairs(channel), channel))
|
||||||
|
self.q.enqueue(pairs)
|
||||||
|
|
||||||
|
def follows(self, irc, msg, args):
|
||||||
|
"""[<channel>]
|
||||||
|
|
||||||
|
Returns the number of Markov's third links in the database for
|
||||||
|
<channel>.
|
||||||
|
"""
|
||||||
|
channel = privmsgs.getChannel(msg, args)
|
||||||
|
def follows(db):
|
||||||
|
s = 'There are %s follows in my Markov database for %s.'
|
||||||
|
irc.reply(s % (db.follows(channel), channel))
|
||||||
|
self.q.enqueue(follows)
|
||||||
|
|
||||||
|
|
||||||
Class = Markov
|
Class = Markov
|
||||||
|
Loading…
Reference in New Issue
Block a user