2012-03-21 22:12:16 +00:00
# coding=utf-8
2012-04-09 02:19:39 +00:00
import re
import time
2012-05-14 15:50:11 +00:00
import random
2012-04-11 15:33:57 +00:00
import sys
2012-05-14 15:50:11 +00:00
import threading
2012-03-21 22:12:16 +00:00
from datetime import timedelta
2012-04-09 02:19:39 +00:00
from datetime import datetime
from datetime import date
2012-03-21 22:12:16 +00:00
2012-05-30 09:58:27 +00:00
from module_state import ModuleState
2012-06-16 20:49:31 +00:00
from wrapper import Wrapper
2012-05-30 09:58:27 +00:00
nemubotversion = 3.0
2012-05-18 09:38:50 +00:00
channels = " #nemutest #42sh #ykar #epitagueule "
2012-05-21 07:12:15 +00:00
LASTSEEN = dict ( )
2012-04-09 02:19:39 +00:00
temps = dict ( )
2012-06-16 20:49:31 +00:00
SCORES = None
2012-05-30 09:58:27 +00:00
2012-06-16 20:49:31 +00:00
def load ( ) :
global DATAS , SCORES
DATAS . setIndex ( " name " , " player " )
SCORES = QDWrapper ( )
2012-05-30 09:58:27 +00:00
2012-06-16 20:49:31 +00:00
def help_tiny ( ) :
""" Line inserted in the response to the command !help """
return " 42 game! "
def help_full ( ) :
return " !42: display scores \n !42 help: display the performed calculate \n !42 manche: display information about current round \n !42 /who/: show the /who/ ' s scores "
class QDWrapper ( Wrapper ) :
def __init__ ( self ) :
2012-05-30 09:58:27 +00:00
global DATAS
2012-06-16 20:49:31 +00:00
Wrapper . __init__ ( self )
self . DATAS = DATAS
self . stateName = " player "
self . attName = " name "
2012-05-30 09:58:27 +00:00
def __getitem__ ( self , i ) :
if i in self . cache :
return self . cache [ i ]
else :
sc = Score ( )
2012-06-16 20:49:31 +00:00
sc . parse ( Wrapper . __getitem__ ( self , i ) )
2012-05-30 09:58:27 +00:00
self . cache [ i ] = sc
return sc
2012-04-11 15:33:57 +00:00
class Score :
2012-06-16 20:49:31 +00:00
""" Manage the user ' s scores """
2012-04-11 15:33:57 +00:00
def __init__ ( self ) :
#FourtyTwo
self . ftt = 0
#TwentyThree
self . twt = 0
self . pi = 0
self . notfound = 0
self . tententen = 0
self . leet = 0
self . great = 0
self . bad = 0
2012-05-21 07:12:15 +00:00
self . triche = 0
2012-04-11 15:33:57 +00:00
self . last = None
self . changed = False
def parse ( self , item ) :
2012-05-30 09:58:27 +00:00
self . ftt = item . getInt ( " fourtytwo " )
self . twt = item . getInt ( " twentythree " )
self . pi = item . getInt ( " pi " )
self . notfound = item . getInt ( " notfound " )
self . tententen = item . getInt ( " tententen " )
self . leet = item . getInt ( " leet " )
self . great = item . getInt ( " great " )
self . bad = item . getInt ( " bad " )
self . triche = item . getInt ( " triche " )
def save ( self , state ) :
state . setAttribute ( " fourtytwo " , self . ftt )
state . setAttribute ( " twentythree " , self . twt )
state . setAttribute ( " pi " , self . pi )
state . setAttribute ( " notfound " , self . notfound )
state . setAttribute ( " tententen " , self . tententen )
state . setAttribute ( " leet " , self . leet )
state . setAttribute ( " great " , self . great )
state . setAttribute ( " bad " , self . bad )
state . setAttribute ( " triche " , self . triche )
2012-04-11 15:33:57 +00:00
2012-05-03 14:16:38 +00:00
def merge ( self , other ) :
self . ftt + = other . ftt
self . twt + = other . twt
self . pi + = other . pi
self . notfound + = other . notfound
self . tententen + = other . tententen
self . leet + = other . leet
self . great + = other . great
self . bad + = other . bad
2012-05-21 07:12:15 +00:00
self . triche + = other . triche
2012-05-03 14:16:38 +00:00
2012-04-11 15:33:57 +00:00
def newWinner ( self ) :
self . ftt = 0
self . twt = 0
self . pi = 1
self . notfound = 1
self . tententen = 0
self . leet = 1
self . great = - 1
self . bad = - 4
2012-05-21 07:12:15 +00:00
self . triche = 0
2012-04-11 15:33:57 +00:00
def isWinner ( self ) :
return self . great > = 42
def playFtt ( self ) :
if self . canPlay ( ) :
self . ftt + = 1
def playTwt ( self ) :
if self . canPlay ( ) :
self . twt + = 1
2012-05-14 15:50:11 +00:00
def playSuite ( self ) :
self . canPlay ( )
self . twt + = 1
self . great + = 1
2012-04-11 15:33:57 +00:00
def playPi ( self ) :
if self . canPlay ( ) :
self . pi + = 1
2012-05-14 15:50:11 +00:00
def playNotfound ( self ) :
2012-04-11 15:33:57 +00:00
if self . canPlay ( ) :
self . notfound + = 1
def playTen ( self ) :
if self . canPlay ( ) :
self . tententen + = 1
def playLeet ( self ) :
if self . canPlay ( ) :
self . leet + = 1
def playGreat ( self ) :
if self . canPlay ( ) :
self . great + = 1
def playBad ( self ) :
if self . canPlay ( ) :
self . bad + = 1
2012-05-30 09:58:27 +00:00
self . great + = 1
2012-05-14 15:50:11 +00:00
def playTriche ( self ) :
2012-05-21 07:12:15 +00:00
self . triche + = 1
2012-05-14 15:50:11 +00:00
def oupsTriche ( self ) :
2012-05-21 07:12:15 +00:00
self . triche - = 1
2012-05-18 09:38:50 +00:00
def bonusQuestion ( self ) :
2012-05-21 07:12:15 +00:00
return
2012-04-11 15:33:57 +00:00
def toTuple ( self ) :
2012-05-21 07:12:15 +00:00
return ( self . ftt , self . twt , self . pi , self . notfound , self . tententen , self . leet , self . great , self . bad , self . triche )
2012-04-11 15:33:57 +00:00
def canPlay ( self ) :
2012-05-18 09:38:50 +00:00
ret = self . last == None or self . last . minute != datetime . now ( ) . minute or self . last . hour != datetime . now ( ) . hour or self . last . day != datetime . now ( ) . day
self . changed = self . changed or ret
return ret
2012-04-11 15:33:57 +00:00
def hasChanged ( self ) :
if self . changed :
self . changed = False
2012-04-30 16:22:10 +00:00
self . last = datetime . now ( )
2012-04-11 15:33:57 +00:00
return True
else :
return False
def score ( self ) :
2012-05-21 07:12:15 +00:00
return ( self . ftt * 2 + self . great * 5 + self . leet * 13.37 + ( self . pi + 1 ) * 3.1415 * ( self . notfound + 1 ) + self . tententen * 10 + self . twt - ( self . bad + 1 ) * 10 * ( self . triche * 5 + 1 ) + 7 )
2012-04-11 15:33:57 +00:00
def details ( self ) :
2012-05-21 07:12:15 +00:00
return " 42: %d , 23: %d , leet: %d , pi: %d , 404: %d , 10: %d , great: %d , bad: %d , triche: %d = %d . " % ( self . ftt , self . twt , self . leet , self . pi , self . notfound , self . tententen , self . great , self . bad , self . triche , self . score ( ) )
2012-04-11 15:33:57 +00:00
2012-04-09 02:19:39 +00:00
def rev ( tupl ) :
( k , v ) = tupl
2012-04-11 15:33:57 +00:00
return ( v . score ( ) , k )
2012-04-09 02:19:39 +00:00
def parseanswer ( msg ) :
if msg . cmd [ 0 ] == " 42 " or msg . cmd [ 0 ] == " score " or msg . cmd [ 0 ] == " scores " :
2012-05-30 09:58:27 +00:00
global SCORES
2012-05-14 15:50:11 +00:00
if len ( msg . cmd ) > 2 and msg . is_owner and ( ( msg . cmd [ 1 ] == " merge " and len ( msg . cmd ) > 3 ) or msg . cmd [ 1 ] == " oupstriche " ) :
if msg . cmd [ 2 ] in SCORES and ( len ( msg . cmd ) < = 3 or msg . cmd [ 3 ] in SCORES ) :
if msg . cmd [ 1 ] == " merge " :
SCORES [ msg . cmd [ 2 ] ] . merge ( SCORES [ msg . cmd [ 3 ] ] )
del SCORES [ msg . cmd [ 3 ] ]
msg . send_chn ( " %s a été correctement fusionné avec %s . " % ( msg . cmd [ 3 ] , msg . cmd [ 2 ] ) )
elif msg . cmd [ 1 ] == " oupstriche " :
SCORES [ msg . cmd [ 2 ] ] . oupsTriche ( )
2012-05-03 14:16:38 +00:00
else :
if msg . cmd [ 2 ] not in SCORES :
msg . send_chn ( " %s n ' est pas un joueur connu. " % msg . cmd [ 2 ] )
elif msg . cmd [ 3 ] not in SCORES :
msg . send_chn ( " %s n ' est pas un joueur connu. " % msg . cmd [ 3 ] )
elif len ( msg . cmd ) > 1 and ( msg . cmd [ 1 ] == " help " or msg . cmd [ 1 ] == " aide " ) :
2012-05-21 07:12:15 +00:00
msg . send_chn ( " Formule : \" 42 \" * 2 + great * 5 + leet * 13.37 + (pi + 1) * 3.1415 * (not_found + 1) + tententen * 10 + \" 23 \" - (bad + 1) * 10 * (triche * 5 + 1) + 7 " )
2012-04-09 02:19:39 +00:00
elif len ( msg . cmd ) > 1 and ( msg . cmd [ 1 ] == " manche " or msg . cmd [ 1 ] == " round " ) :
2012-05-30 09:58:27 +00:00
manche = DATAS . getNode ( " manche " )
msg . send_chn ( " Nous sommes dans la %d e manche, gagnée par %s avec %d points et commencée par %s le %s . " % ( manche . getInt ( " number " ) , manche [ " winner " ] , manche . getInt ( " winner_score " ) , manche [ " who " ] , manche . getDate ( " date " ) ) )
2012-05-21 07:12:15 +00:00
#elif msg.channel == "#nemutest":
2012-03-21 22:12:16 +00:00
else :
2012-04-09 02:19:39 +00:00
phrase = " "
2012-03-21 22:12:16 +00:00
2012-04-09 02:19:39 +00:00
if len ( msg . cmd ) > 1 :
2012-05-03 14:16:38 +00:00
if msg . cmd [ 1 ] in SCORES :
phrase + = " " + msg . cmd [ 1 ] + " : " + SCORES [ msg . cmd [ 1 ] ] . details ( )
2012-04-09 02:19:39 +00:00
else :
phrase = " %s n ' a encore jamais joué, " % ( msg . cmd [ 1 ] )
2012-03-21 22:12:16 +00:00
else :
2012-04-11 15:33:57 +00:00
for nom , scr in sorted ( SCORES . items ( ) , key = rev , reverse = True ) :
2012-04-30 16:22:10 +00:00
score = scr . score ( )
if score != 0 :
if phrase == " " :
2012-05-14 15:50:11 +00:00
phrase = " * %s . %s : %d *, " % ( nom [ 0 : 1 ] , nom [ 1 : len ( nom ) ] , score )
2012-04-30 16:22:10 +00:00
else :
2012-05-14 15:50:11 +00:00
phrase + = " %s . %s : %d , " % ( nom [ 0 : 1 ] , nom [ 1 : len ( nom ) ] , score )
2012-03-21 22:12:16 +00:00
2012-04-09 02:19:39 +00:00
msg . send_chn ( " Scores : %s " % ( phrase [ 0 : len ( phrase ) - 1 ] ) )
return True
else :
return False
2012-03-21 22:12:16 +00:00
2012-04-30 16:22:10 +00:00
def win ( msg ) :
2012-05-30 09:58:27 +00:00
global SCORES
2012-05-03 14:16:38 +00:00
who = msg . sender
2012-03-21 22:12:16 +00:00
2012-05-30 09:58:27 +00:00
manche = DATAS . getNode ( " manche " )
2012-03-21 22:12:16 +00:00
maxi_scor = 0
maxi_name = None
2012-05-30 09:58:27 +00:00
for player in DATAS . index . keys ( ) :
2012-04-30 16:22:10 +00:00
scr = SCORES [ player ] . score ( )
2012-03-21 22:12:16 +00:00
if scr > maxi_scor :
maxi_scor = scr
maxi_name = player
2012-06-16 20:49:31 +00:00
for player in DATAS . index . keys ( ) :
scr = SCORES [ player ] . score ( )
if scr > maxi_scor / 3 :
del SCORES [ player ]
else :
DATAS . index [ player ] [ " great " ] = 0
SCORES . flush ( )
2012-04-09 02:19:39 +00:00
if who != maxi_name :
2012-04-30 16:22:10 +00:00
msg . send_chn ( " Félicitations %s , tu remportes cette manche terminée par %s , avec un score de %d ! " % ( maxi_name , who , maxi_scor ) )
2012-04-09 02:19:39 +00:00
else :
2012-04-30 16:22:10 +00:00
msg . send_chn ( " Félicitations %s , tu remportes cette manche avec %d points ! " % ( maxi_name , maxi_scor ) )
2012-04-09 02:19:39 +00:00
2012-05-30 09:58:27 +00:00
manche . setAttribute ( " number " , manche . getInt ( " number " ) + 1 )
manche . setAttribute ( " winner " , maxi_name )
manche . setAttribute ( " winner_score " , maxi_scor )
manche . setAttribute ( " who " , who )
manche . setAttribute ( " date " , datetime . now ( ) )
2012-03-21 22:12:16 +00:00
2012-05-30 09:58:27 +00:00
print ( " Nouvelle manche ! " )
save ( )
2012-03-21 22:12:16 +00:00
2012-04-09 02:19:39 +00:00
def parseask ( msg ) :
2012-05-14 15:50:11 +00:00
if len ( DELAYED ) > 0 :
if msg . sender in DELAYED :
2012-06-16 20:49:31 +00:00
DELAYED [ msg . sender ] . msg = msg . content
2012-05-14 15:50:11 +00:00
DELAYED [ msg . sender ] . delayEvnt . set ( )
return True
2012-04-09 02:19:39 +00:00
return False
2012-03-21 22:12:16 +00:00
2012-04-11 15:33:57 +00:00
def getUser ( name ) :
global SCORES
if name not in SCORES :
SCORES [ name ] = Score ( )
return SCORES [ name ]
2012-04-09 02:19:39 +00:00
def parselisten ( msg ) :
2012-05-18 09:38:50 +00:00
if len ( DELAYED ) > 0 and msg . sender in DELAYED and DELAYED [ msg . sender ] . good ( msg . content ) :
msg . send_chn ( " %s : n ' oublie pas le nemubot: devant ta réponse pour qu ' elle soit prise en compte ! " % msg . sender )
2012-05-21 07:12:15 +00:00
bfrseen = None
if msg . realname in LASTSEEN :
bfrseen = LASTSEEN [ msg . realname ]
LASTSEEN [ msg . realname ] = datetime . now ( )
2012-06-16 20:49:31 +00:00
# if msg.channel == "#nemutest" and msg.sender not in DELAYED:
if msg . channel != " #nemutest " and msg . sender not in DELAYED :
2012-05-14 15:50:11 +00:00
2012-05-21 07:12:15 +00:00
if re . match ( " ^(42|quarante[- ]?deux). { ,2}$ " , msg . content . strip ( ) . lower ( ) ) :
2012-04-30 16:22:10 +00:00
if msg . time . minute == 10 and msg . time . second == 10 and msg . time . hour == 10 :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playTen ( )
getUser ( msg . sender ) . playGreat ( )
2012-04-30 16:22:10 +00:00
elif msg . time . minute == 42 :
if msg . time . second == 0 :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playGreat ( )
getUser ( msg . sender ) . playFtt ( )
2012-04-09 02:19:39 +00:00
else :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playBad ( )
2012-04-09 02:19:39 +00:00
2012-05-21 07:12:15 +00:00
if re . match ( " ^(23|vingt[ -]?trois). { ,2}$ " , msg . content . strip ( ) . lower ( ) ) :
2012-04-30 16:22:10 +00:00
if msg . time . minute == 23 :
if msg . time . second == 0 :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playGreat ( )
getUser ( msg . sender ) . playTwt ( )
2012-04-09 02:19:39 +00:00
else :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playBad ( )
2012-04-09 02:19:39 +00:00
2012-05-21 07:12:15 +00:00
if re . match ( " ^(10) {3} . { ,2}$ " , msg . content . strip ( ) . lower ( ) ) :
2012-04-30 16:22:10 +00:00
if msg . time . minute == 10 and msg . time . hour == 10 :
if msg . time . second == 10 :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playGreat ( )
getUser ( msg . sender ) . playTen ( )
2012-04-09 02:19:39 +00:00
else :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playBad ( )
2012-04-09 02:19:39 +00:00
2012-05-21 07:12:15 +00:00
if re . match ( " ^0?12345. { ,2}$ " , msg . content . strip ( ) . lower ( ) ) :
2012-05-14 15:50:11 +00:00
if msg . time . hour == 1 and msg . time . minute == 23 and ( msg . time . second == 45 or ( msg . time . second == 46 and msg . time . microsecond < 330000 ) ) :
getUser ( msg . sender ) . playSuite ( )
2012-04-09 02:19:39 +00:00
else :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playBad ( )
2012-04-09 02:19:39 +00:00
2012-05-21 07:12:15 +00:00
if re . match ( " ^[1l][e3] {2} [t7] ?t?ime. { ,2}$ " , msg . content . strip ( ) . lower ( ) ) :
2012-04-30 16:22:10 +00:00
if msg . time . hour == 13 and msg . time . minute == 37 :
if msg . time . second == 0 :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playGreat ( )
getUser ( msg . sender ) . playLeet ( )
2012-04-09 02:19:39 +00:00
else :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playBad ( )
2012-03-21 22:12:16 +00:00
2012-05-21 07:12:15 +00:00
if re . match ( " ^(pi|3.14) ?time. { ,2}$ " , msg . content . strip ( ) . lower ( ) ) :
2012-04-30 16:22:10 +00:00
if msg . time . hour == 3 and msg . time . minute == 14 :
if msg . time . second == 15 or msg . time . second == 16 :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playGreat ( )
getUser ( msg . sender ) . playPi ( )
2012-04-09 02:19:39 +00:00
else :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playBad ( )
2012-04-09 02:19:39 +00:00
2012-05-21 07:12:15 +00:00
if re . match ( " ^(404( ?time)?|time ?not ?found). { ,2}$ " , msg . content . strip ( ) . lower ( ) ) :
2012-04-30 16:22:10 +00:00
if msg . time . hour == 4 and msg . time . minute == 4 :
if msg . time . second == 0 or msg . time . second == 4 :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playGreat ( )
getUser ( msg . sender ) . playNotfound ( )
2012-04-09 02:19:39 +00:00
else :
2012-04-11 15:33:57 +00:00
getUser ( msg . sender ) . playBad ( )
2012-04-09 02:19:39 +00:00
2012-04-11 15:33:57 +00:00
if getUser ( msg . sender ) . isWinner ( ) :
print ( " Nous avons un vainqueur ! Nouvelle manche :p " )
2012-04-30 16:22:10 +00:00
win ( msg )
2012-05-14 15:50:11 +00:00
return True
2012-04-11 15:33:57 +00:00
elif getUser ( msg . sender ) . hasChanged ( ) :
2012-05-21 07:12:15 +00:00
gu = GameUpdater ( msg , bfrseen )
2012-05-14 15:50:11 +00:00
gu . start ( )
return True
2012-04-09 02:19:39 +00:00
return False
2012-05-14 15:50:11 +00:00
DELAYED = dict ( )
class DelayedTuple :
2012-05-18 09:38:50 +00:00
def __init__ ( self , regexp , great ) :
2012-05-14 15:50:11 +00:00
self . delayEvnt = threading . Event ( )
self . msg = None
self . regexp = regexp
2012-05-18 09:38:50 +00:00
self . great = great
2012-05-14 15:50:11 +00:00
def triche ( self , res ) :
if res is not None :
return re . match ( " .* " + self . regexp + " .* " , res . lower ( ) + " " ) is None
else :
return True
2012-05-18 09:38:50 +00:00
def perfect ( self , res ) :
if res is not None :
return re . match ( " .* " + self . great + " .* " , res . lower ( ) + " " ) is not None
else :
return False
2012-05-14 15:50:11 +00:00
def wait ( self , timeout ) :
self . delayEvnt . wait ( timeout )
2012-05-18 09:38:50 +00:00
LASTQUESTION = 99999
2012-05-14 15:50:11 +00:00
class GameUpdater ( threading . Thread ) :
2012-05-21 07:12:15 +00:00
def __init__ ( self , msg , bfrseen ) :
2012-05-14 15:50:11 +00:00
self . msg = msg
2012-05-21 07:12:15 +00:00
self . bfrseen = bfrseen
2012-05-14 15:50:11 +00:00
threading . Thread . __init__ ( self )
def run ( self ) :
2012-05-30 09:58:27 +00:00
global DELAYED , LASTQUESTION
2012-05-14 15:50:11 +00:00
2012-05-30 09:58:27 +00:00
if self . bfrseen is not None :
seen = datetime . now ( ) - self . bfrseen
rnd = random . randint ( 0 , int ( seen . seconds / 90 ) )
else :
rnd = 1
2012-05-21 07:12:15 +00:00
if rnd != 0 :
2012-05-30 09:58:27 +00:00
QUESTIONS = CONF . getNodes ( " question " )
2012-06-16 20:49:31 +00:00
print ( QUESTIONS )
2012-05-30 09:58:27 +00:00
2012-05-18 09:38:50 +00:00
if self . msg . channel == " #nemutest " :
quest = 9
else :
if LASTQUESTION > = len ( QUESTIONS ) :
random . shuffle ( QUESTIONS )
LASTQUESTION = 0
quest = LASTQUESTION
LASTQUESTION + = 1
2012-05-14 15:50:11 +00:00
2012-05-30 09:58:27 +00:00
question = QUESTIONS [ quest ] [ " question " ]
regexp = QUESTIONS [ quest ] [ " regexp " ]
great = QUESTIONS [ quest ] [ " great " ]
2012-05-14 15:50:11 +00:00
self . msg . send_chn ( " %s : %s " % ( self . msg . sender , question ) )
2012-05-18 09:38:50 +00:00
DELAYED [ self . msg . sender ] = DelayedTuple ( regexp , great )
2012-05-14 15:50:11 +00:00
DELAYED [ self . msg . sender ] . wait ( 20 )
if DELAYED [ self . msg . sender ] . triche ( DELAYED [ self . msg . sender ] . msg ) :
getUser ( self . msg . sender ) . playTriche ( )
self . msg . send_chn ( " %s : Tricheur ! " % self . msg . sender )
2012-05-18 09:38:50 +00:00
elif DELAYED [ self . msg . sender ] . perfect ( DELAYED [ self . msg . sender ] . msg ) :
if random . randint ( 0 , 10 ) == 1 :
getUser ( self . msg . sender ) . bonusQuestion ( )
self . msg . send_chn ( " %s : Correct ! " % self . msg . sender )
2012-05-21 07:12:15 +00:00
else :
self . msg . send_chn ( " %s : J ' accepte " % self . msg . sender )
2012-05-14 15:50:11 +00:00
del DELAYED [ self . msg . sender ]
2012-05-30 09:58:27 +00:00
SCORES . save ( self . msg . sender )
save ( )