# coding=utf-8 import re import time import random import sys import threading from datetime import timedelta from datetime import datetime from datetime import date from xml.dom.minidom import parse from xml.dom.minidom import parseString from xml.dom.minidom import getDOMImplementation filename = "" channels = "#nemutest #42sh #ykar #epitagueule" MANCHE = None QUESTIONS = list() SCORES = dict () LASTSEEN = dict () temps = dict () class Score: 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 self.triche = 0 self.last = None self.changed = False def parse(self, item): self.ftt = int(item.getAttribute("fourtytwo")) self.twt = int(item.getAttribute("twentythree")) self.pi = int(item.getAttribute("pi")) self.notfound = int(item.getAttribute("notfound")) self.tententen = int(item.getAttribute("tententen")) self.leet = int(item.getAttribute("leet")) self.great = int(item.getAttribute("great")) self.bad = int(item.getAttribute("bad")) self.triche = int(item.getAttribute("triche")) 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 self.triche += other.triche 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 self.triche = 0 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 def playSuite(self): self.canPlay() self.twt += 1 self.great += 1 def playPi(self): if self.canPlay(): self.pi += 1 def playNotfound(self): 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 def playTriche(self): self.triche += 1 def oupsTriche(self): self.triche -= 1 def bonusQuestion(self): return def toTuple(self): return (self.ftt, self.twt, self.pi, self.notfound, self.tententen, self.leet, self.great, self.bad, self.triche) def canPlay(self): 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 def hasChanged(self): if self.changed: self.changed = False self.last = datetime.now() return True else: return False def score(self): 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) def details(self): 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()) def xmlparse(node): """Parse the given node and add scores to the global list.""" global SCORES, MANCHE for item in node.getElementsByTagName("score"): SCORES[item.getAttribute("name")] = Score () SCORES[item.getAttribute("name")].parse(item) for item in node.getElementsByTagName("question"): QUESTIONS.append((item.getAttribute("question"),item.getAttribute("regexp"),item.getAttribute("great"))) manche = node.getElementsByTagName("manche")[0] MANCHE = (int(manche.getAttribute("number")), manche.getAttribute("winner"), int(manche.getAttribute("winner_score")), manche.getAttribute("who"), # datetime.now ()) datetime.fromtimestamp (time.mktime (time.strptime (manche.getAttribute("date")[:19], "%Y-%m-%d %H:%M:%S")))) def load_module(datas_path): """Load this module""" global MANCHE, SCORES, filename MANCHE = None SCORES = dict () filename = datas_path + "/42.xml" sys.stdout.write ("Loading 42scores ... ") dom = parse(filename) xmlparse (dom.documentElement) print ("done (%d loaded, %d questions, currently in round %d)" % (len(SCORES), len(QUESTIONS), -42)) def save_module(): """Save the scores""" global filename sys.stdout.write ("Saving 42scores ... ") impl = getDOMImplementation() newdoc = impl.createDocument(None, 'game', None) top = newdoc.documentElement for name in SCORES.keys(): scr = 'fourtytwo="%d" twentythree="%d" pi="%d" notfound="%d" tententen="%d" leet="%d" great="%d" bad="%d" triche="%d"'% SCORES[name].toTuple() item = parseString ('' % (name, scr)).documentElement top.appendChild(item); top.appendChild(parseString ('' % MANCHE).documentElement) for q in QUESTIONS: top.appendChild(parseString ('' % q).documentElement) with open(filename, "w") as f: newdoc.writexml (f) print ("done") 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" def rev (tupl): (k, v) = tupl return (v.score(), k) def parseanswer (msg): if msg.cmd[0] == "42" or msg.cmd[0] == "score" or msg.cmd[0] == "scores": global SCORES, MANCHE 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() 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"): 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") elif len(msg.cmd) > 1 and (msg.cmd[1] == "manche" or msg.cmd[1] == "round"): msg.send_chn ("Nous sommes dans la %de manche, gagnée par %s avec %d points et commencée par %s le %s"%MANCHE) #elif msg.channel == "#nemutest": else: phrase = "" if len(msg.cmd) > 1: if msg.cmd[1] in SCORES: phrase += " " + msg.cmd[1] + ": " + SCORES[msg.cmd[1]].details() else: phrase = " %s n'a encore jamais joué,"%(msg.cmd[1]) else: for nom, scr in sorted(SCORES.items(), key=rev, reverse=True): score = scr.score() if score != 0: if phrase == "": phrase = " *%s.%s: %d*,"%(nom[0:1], nom[1:len(nom)], score) else: phrase += " %s.%s: %d,"%(nom[0:1], nom[1:len(nom)], score) msg.send_chn ("Scores :%s" % (phrase[0:len(phrase)-1])) return True else: return False def win(msg): global SCORES, MANCHE who = msg.sender (num_manche, winner, nb_points, whosef, dayte) = MANCHE maxi_scor = 0 maxi_name = None for player in SCORES.keys(): scr = SCORES[player].score() if scr > maxi_scor: maxi_scor = scr maxi_name = player #Reset ! SCORES = dict() # SCORES[maxi_name] = (-10, 0, -4, 0, 0, -2, 0) # SCORES[maxi_name] = (0, 0, 0, 0, 0, 0, 0) SCORES[who] = Score() SCORES[who].newWinner() if who != maxi_name: msg.send_chn ("Félicitations %s, tu remportes cette manche terminée par %s, avec un score de %d !"%(maxi_name, who, maxi_scor)) else: msg.send_chn ("Félicitations %s, tu remportes cette manche avec %d points !"%(maxi_name, maxi_scor)) MANCHE = (num_manche + 1, maxi_name, maxi_scor, who, datetime.now ()) print ("Nouvelle manche :", MANCHE) save_module () def parseask (msg): if len(DELAYED) > 0: if msg.sender in DELAYED: DELAYED[msg.sender].msg = msg.content[9:] DELAYED[msg.sender].delayEvnt.set() return True return False def getUser(name): global SCORES if name not in SCORES: SCORES[name] = Score() return SCORES[name] def parselisten (msg): 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) bfrseen = None if msg.realname in LASTSEEN: bfrseen = LASTSEEN[msg.realname] LASTSEEN[msg.realname] = datetime.now() # if msg.channel == "#nemutest" and msg.sender not in DELAYED: if msg.channel != "#nemutest" and msg.sender not in DELAYED: if re.match("^(42|quarante[- ]?deux).{,2}$", msg.content.strip().lower()): if msg.time.minute == 10 and msg.time.second == 10 and msg.time.hour == 10: getUser(msg.sender).playTen() getUser(msg.sender).playGreat() elif msg.time.minute == 42: if msg.time.second == 0: getUser(msg.sender).playGreat() getUser(msg.sender).playFtt() else: getUser(msg.sender).playBad() if re.match("^(23|vingt[ -]?trois).{,2}$", msg.content.strip().lower()): if msg.time.minute == 23: if msg.time.second == 0: getUser(msg.sender).playGreat() getUser(msg.sender).playTwt() else: getUser(msg.sender).playBad() if re.match("^(10){3}.{,2}$", msg.content.strip().lower()): if msg.time.minute == 10 and msg.time.hour == 10: if msg.time.second == 10: getUser(msg.sender).playGreat() getUser(msg.sender).playTen() else: getUser(msg.sender).playBad() if re.match("^0?12345.{,2}$", msg.content.strip().lower()): 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() else: getUser(msg.sender).playBad() if re.match("^[1l][e3]{2}[t7] ?t?ime.{,2}$", msg.content.strip().lower()): if msg.time.hour == 13 and msg.time.minute == 37: if msg.time.second == 0: getUser(msg.sender).playGreat() getUser(msg.sender).playLeet() else: getUser(msg.sender).playBad() if re.match("^(pi|3.14) ?time.{,2}$", msg.content.strip().lower()): if msg.time.hour == 3 and msg.time.minute == 14: if msg.time.second == 15 or msg.time.second == 16: getUser(msg.sender).playGreat() getUser(msg.sender).playPi() else: getUser(msg.sender).playBad() if re.match("^(404( ?time)?|time ?not ?found).{,2}$", msg.content.strip().lower()): if msg.time.hour == 4 and msg.time.minute == 4: if msg.time.second == 0 or msg.time.second == 4: getUser(msg.sender).playGreat() getUser(msg.sender).playNotfound() else: getUser(msg.sender).playBad() if getUser(msg.sender).isWinner(): print ("Nous avons un vainqueur ! Nouvelle manche :p") win(msg) return True elif getUser(msg.sender).hasChanged(): gu = GameUpdater(msg, bfrseen) gu.start() return True return False DELAYED = dict() class DelayedTuple: def __init__(self, regexp, great): self.delayEvnt = threading.Event() self.msg = None self.regexp = regexp self.great = great def triche(self, res): if res is not None: return re.match(".*" + self.regexp + ".*", res.lower() + " ") is None else: return True def perfect(self, res): if res is not None: return re.match(".*" + self.great + ".*", res.lower() + " ") is not None else: return False # # def wait(self, timeout): self.delayEvnt.wait(timeout) LASTQUESTION = 99999 class GameUpdater(threading.Thread): def __init__(self, msg, bfrseen): self.msg = msg self.bfrseen = bfrseen threading.Thread.__init__(self) def run(self): global DELAYED, QUESTIONS, LASTQUESTION seen = datetime.now() - self.bfrseen rnd = random.randint(0, seen.seconds/90) if rnd != 0: if self.msg.channel == "#nemutest": quest = 9 else: if LASTQUESTION >= len(QUESTIONS): random.shuffle(QUESTIONS) LASTQUESTION = 0 quest = LASTQUESTION LASTQUESTION += 1 (question, regexp, great) = QUESTIONS[quest] self.msg.send_chn("%s: %s" % (self.msg.sender, question)) DELAYED[self.msg.sender] = DelayedTuple(regexp, great) 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) 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) else: self.msg.send_chn("%s: J'accepte" % self.msg.sender) del DELAYED[self.msg.sender] save_module ()