"""MinerCoin. How it works: - On !minercoin, generate a mathematical challenge and present it in a non-bot-parseable way. Store the answer for later. - On the next message in the channel the challenges are presented and issued from by said user, check and see if the answer is correct. - If the answer is correct, reward the user with MinerCoins. - If not, no reward is issued. - Only let the user try a challenge every hour.""" import plugin, time, random, traceback, datetime from pluralslib import plural from dictdata import DictData challenges = DictData("challenges.json") last_used = DictData("times.json") count = DictData("minercoin.json") def username(f): def __username(bot,channel,nick,*args): return f(bot,channel,nick,bot.event.source.user.strip(),*args) return __username def get(username): return count.get(username,0), last_used.get(username,0), challenges.get(username) def set(source,ncount,nlast_used,nchallenge=None): username = source.user count[username]=ncount last_used[username]=nlast_used challenges[username]=nchallenge names = "Alice Bob Carol Danvers Eve Frank Gerald Hope Indiana Jared Kate Larry Monica Nathan Orion Peter Quibley Ryan Stewart Tobias Uriah Violet Warren Xylia Yvonne Zelda".split() # OK, this needs explaining. # [int count, lambda verify, lambda answer, string question] # count = how many numbers to generate questions = [ # [2,lambda x,y: (x>=0 and x<=100),lambda x,y: int(round((x/100.)*y)),"Calculate {}% of {}. (round to the nearest whole number)"], [1,lambda x: (x<182),lambda x: names[x%26],"If I introduce you to {}, what is their name?",lambda x: [names[x%26]]], [2,lambda x,y: (x<195 and y<195),lambda x,y: (x%13)*(y%13),"Calculate {} times {}.",lambda x,y: [(i%13) for i in (x,y)]] ] def safelist(n): try: return list(n) except TypeError: return [n] def get_question(): q = random.choice(questions) nums = [random.randint(0,200) for x in range(q[0])] while not q[1](*nums): nums = [random.randint(0,200) for x in range(q[0])] cha = str(q[2](*nums)) if len(q)==5: nums = safelist(q[4](*nums)) chq = q[3].format(*nums) return chq, cha @plugin.group("minercoin","") def minercoin(bot,channel,nick,*args): if args[0] not in "ask count cooldown score wait".split(): bot.say(channel,"{}: Usage: !minercoin ".format(nick)) return True # only allow selected subcommands elif channel!="#bots": bot.say(channel,"{}: MinerCoin is only awarded in #bots, same as tildes!".format(nick)) return True return False leadins = ["pro-minercoin question","anti-autoasker question","pro-login question","pro-minerobber challenge"] @minercoin.command("ask") @username def minercoin_ask(bot,channel,nick,username,*args): cnt, last, challenge = get(username) if (int(time.time())-last)<(60*60): # if it hasn't been an hour since the last one... bot.say(channel,"{} is a doodoo head and needs to wait longer between attempts! (1 hour between attempts)".format(nick)) return try: question, challenge = get_question() bot.say(channel,"{}: {}: {}".format(nick,random.choice(leadins),question)) set(bot.event.source,cnt,int(time.time()),challenge) except: traceback.print_exc() @plugin.listener("minercoin_answer") @username def minercoin_listen(bot,channel,nick,username,message): cnt, last, challenge = get(username) if challenge is None: return elif message==challenge: payout = random.randint(1,5) bot.say(channel,"{}: You are a winner and get {}!".format(nick,plural(payout,"MinerCoin"))) cnt+=payout else: bot.say(channel,"{} is a quitter and gets no MinerCoin!".format(nick)) set(bot.event.source,cnt,last,None) @minercoin.command("count") @username def minercoin_count(bot,channel,nick,username,*args): if username in count: cnt = get(username)[0] bot.say(channel,"{}: You have {}!".format(nick,plural(cnt,"MinerCoin"))) else: bot.say(channel,"{}: You don't have any MinerCoin! Get some by asking! (!minercoin ask)".format(nick)) minercoin.command("score")(username(minercoin_count)) @minercoin.command("cooldown") @username def minercoin_cooldown(bot,channel,nick,username,*args): last = get(username)[1] if last==0: # special case: never used before bot.say(channel,"{}: You can ask for more MinerCoin right away!".format(nick)) else: delta = 3600-(int(time.time())-last) delta = int(round(delta)) if delta<0: bot.say(channel,"{}: You can ask for more MinerCoin right away!".format(nick)) return minutes,seconds = divmod(delta,60) timedesc = "" if minutes: timedesc += plural(minutes,"minute")+" and " timedesc += plural(seconds,"second") bot.say(channel,"{}: Please wait {} before asking for more MinerCoin.".format(nick,timedesc)) minercoin.command("wait")(minercoin_cooldown)