mirror of
https://git.wownero.com/wownero/tippero.git
synced 2024-08-15 00:33:14 +00:00
Add pinata module
This commit is contained in:
parent
f99f10d56c
commit
4da435b9d2
2 changed files with 200 additions and 0 deletions
|
@ -92,3 +92,11 @@ blackjack_max_loss_ratio = 0.05
|
|||
bookie_fee = 0.01
|
||||
bookie_min_bet = 0.001
|
||||
bookie_max_bet = 1000
|
||||
|
||||
pinata_start_amount = 0.75
|
||||
pinata_base_target = 2
|
||||
pinata_num_increments = 20
|
||||
pinata_target_increment = 0.01
|
||||
pinata_winner_base_share = 0.75
|
||||
pinata_rain_remainder_share = 0.8
|
||||
pinata_carry_remainder_share = 0.17
|
||||
|
|
192
tipbot/modules/pinata.py
Normal file
192
tipbot/modules/pinata.py
Normal file
|
@ -0,0 +1,192 @@
|
|||
#!/bin/python
|
||||
#
|
||||
# Cryptonote tipbot - pinata commands
|
||||
# Copyright 2015 moneromooo
|
||||
#
|
||||
# The Cryptonote tipbot is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
import redis
|
||||
import hashlib
|
||||
import time
|
||||
import string
|
||||
import random
|
||||
import math
|
||||
import tipbot.config as config
|
||||
from tipbot.log import log_error, log_warn, log_info, log_log
|
||||
import tipbot.coinspecs as coinspecs
|
||||
from tipbot.utils import *
|
||||
from tipbot.command_manager import *
|
||||
from tipbot.redisdb import *
|
||||
from tipbot.betutils import *
|
||||
|
||||
def GetTarget(units):
|
||||
umod = long(config.pinata_target_increment * coinspecs.atomic_units + 0.5)
|
||||
units = long(float(units)+0.5)
|
||||
units -= units % umod
|
||||
return units
|
||||
|
||||
def PreparePinata(reset=False,units=None):
|
||||
p=redis_pipeline()
|
||||
if reset or not redis_hexists('pinata','target'):
|
||||
target=GetTarget((config.pinata_base_target+config.pinata_target_increment*random.randint(0,config.pinata_num_increments))*coinspecs.atomic_units)
|
||||
log_log('PreparePinata: target %s' % target)
|
||||
p.hset('pinata','target',target)
|
||||
if reset or not redis_hexists('pinata','units'):
|
||||
units=long(units or config.pinata_start_amount*coinspecs.atomic_units)
|
||||
if units < config.pinata_start_amount*coinspecs.atomic_units:
|
||||
units = long(config.pinata_start_amount*coinspecs.atomic_units)
|
||||
p.hset('pinata','units',units)
|
||||
p.hincrby('pinata','profit',-units)
|
||||
p.hincrby('earmarked','pinata',units)
|
||||
p.execute()
|
||||
|
||||
def Pinata(link,cmd):
|
||||
# Make sure there is always one
|
||||
PreparePinata()
|
||||
|
||||
identity=link.identity()
|
||||
group=link.group
|
||||
if not group:
|
||||
link.send("There is no pinata around, they only appear in IRC channels")
|
||||
return
|
||||
|
||||
try:
|
||||
pinata_units = long(redis_hget('pinata','units'))
|
||||
except Exception,e:
|
||||
log_error('Failed to get pinata units: %s' % str(e))
|
||||
link.send('An error occured')
|
||||
return
|
||||
|
||||
min_target=GetTarget(config.pinata_base_target*coinspecs.atomic_units)
|
||||
max_target=GetTarget((config.pinata_base_target+(config.pinata_num_increments-1)*config.pinata_target_increment)*coinspecs.atomic_units)
|
||||
|
||||
if not GetParam(cmd,1):
|
||||
min_win_units = (pinata_units + config.pinata_base_target*coinspecs.atomic_units) * config.pinata_winner_base_share
|
||||
link.send("The pinata is filled with %s, and can be hit with %s - %s (in increments of %s) - min win %s" % (AmountToString(pinata_units),AmountToString(min_target),AmountToString(max_target),AmountToString(config.pinata_target_increment*coinspecs.atomic_units),AmountToString(min_win_units)))
|
||||
return
|
||||
|
||||
try:
|
||||
amount=float(cmd[1])
|
||||
units=long(amount*coinspecs.atomic_units+0.5)
|
||||
aim = GetTarget(units)
|
||||
except Exception,e:
|
||||
link.send("Usage: !pinata <amount>")
|
||||
return
|
||||
if aim < min_target:
|
||||
link.send("The pinata can only be hit by at least %s" % AmountToString(min_target))
|
||||
return
|
||||
if aim > max_target:
|
||||
link.send("The pinata can only be hit by at most %s" % AmountToString(max_target))
|
||||
return
|
||||
|
||||
try:
|
||||
target = long(redis_hget('pinata','target'))
|
||||
except Exception,e:
|
||||
log_error('Failed to get pinata target: %s' % str(e))
|
||||
link.send('An error occured')
|
||||
return
|
||||
|
||||
if target < min_target or target > max_target:
|
||||
log_error('Pinata target out of range: %s' % target)
|
||||
link.send('An error occured')
|
||||
return
|
||||
|
||||
account = GetAccount(identity)
|
||||
log_info("Pinata: %s wants to swing %s at the pinata, aim is %d, target is %d" % (identity, amount, aim, target))
|
||||
valid,reason = IsBetValid(link,amount,None,None,0,0,0)
|
||||
if not valid:
|
||||
log_info("Pinata: %s's bet refused: %s" % (identity, reason))
|
||||
link.send("%s: %s" % (link.user.nick, reason))
|
||||
return
|
||||
|
||||
try:
|
||||
if target==aim:
|
||||
log_info("Pinata: %s hits the pinata containing %s" % (identity, AmountToString(pinata_units)))
|
||||
|
||||
winner_ratio = config.pinata_winner_base_share * aim / min_target
|
||||
rain_ratio = (1-winner_ratio) * config.pinata_rain_remainder_share
|
||||
carry_ratio = (1-winner_ratio) * config.pinata_carry_remainder_share
|
||||
winner_units = long(pinata_units * winner_ratio)
|
||||
rain_units = long(pinata_units * rain_ratio)
|
||||
carry_units = long(pinata_units * carry_ratio)
|
||||
profit_units = pinata_units - winner_units - rain_units
|
||||
|
||||
log_log("Pinata: %s to winner, %s to rain, %s carry" % (AmountToString(winner_units),AmountToString(rain_units),AmountToString(carry_units)))
|
||||
|
||||
p=redis_pipeline()
|
||||
p.hincrby('earmarked','pinata',-pinata_units)
|
||||
p.hincrby('balances',account,winner_units)
|
||||
link.send('%s swings at the pinata with %s and hits!' % (link.user.nick,AmountToString(units)))
|
||||
link.send('%s gets splashed by %s' % (link.user.nick,AmountToString(winner_units)))
|
||||
|
||||
userlist=link.network.get_users(group.name)
|
||||
log_log("users in %s: %s" % (group.name,str([user.identity() for user in userlist])))
|
||||
userlist.remove(link)
|
||||
for n in config.no_rain_to_nicks:
|
||||
i=IdentityFromString(link,n)
|
||||
l=Link(link.network,User(link.network,NickFromIdentity(i)),group)
|
||||
if l in userlist:
|
||||
userlist.remove(l)
|
||||
|
||||
if len(userlist) > 0:
|
||||
user_units = long(rain_units / len(userlist))
|
||||
log_log("The pinata rains %s on: %s" % (AmountToString(user_units),str([user.identity() for user in userlist])))
|
||||
link.send('%s rains on everyone else' % (AmountToString(user_units)))
|
||||
for n in userlist:
|
||||
a = GetAccount(n)
|
||||
p.hincrby('balances',a,user_units)
|
||||
|
||||
p.hincrby('pinata','games',1)
|
||||
p.hincrby('pinata','profit',profit_units)
|
||||
p.execute()
|
||||
PreparePinata(True,carry_units)
|
||||
link.send('A new pinata appears filled with %s!' % AmountToString(carry_units))
|
||||
else:
|
||||
p=redis_pipeline()
|
||||
p.hincrby('balances',account,-units)
|
||||
p.hincrby('pinata','units',units)
|
||||
p.hincrby('earmarked','pinata',units)
|
||||
p.execute()
|
||||
link.send('%s swings at the pinata with %s and misses! The pinata now contains %s' % (link.user.nick,AmountToString(units),AmountToString(pinata_units+units)))
|
||||
except Exception,e:
|
||||
log_error('Pinata: error: %s' % str(e))
|
||||
link.send('An error occured')
|
||||
return
|
||||
|
||||
def PinataHelp(link):
|
||||
link.send_private("A pinata full of %s is floating in the air. Swing some %s at it!" % (coinspecs.name,coinspecs.name))
|
||||
link.send_private("This pinata can only be smashed by a secret amount of %s," % (coinspecs.name))
|
||||
min_target=GetTarget(config.pinata_base_target*coinspecs.atomic_units)
|
||||
max_target=GetTarget((config.pinata_base_target+(config.pinata_num_increments-1)*config.pinata_target_increment)*coinspecs.atomic_units)
|
||||
link.send_private("between %s and %s (inclusive), in %s increments" % (AmountToString(min_target),AmountToString(max_target),AmountToString(config.pinata_target_increment*coinspecs.atomic_units)))
|
||||
min_winner_share=config.pinata_winner_base_share
|
||||
max_winner_share=config.pinata_winner_base_share*(config.pinata_base_target+(config.pinata_num_increments-1)*config.pinata_target_increment)/config.pinata_base_target
|
||||
link.send_private("If you hit with the secret amount, it breaks and you get %u%% - %u%% of the %s in it," % (100*min_winner_share,100*max_winner_share,coinspecs.name))
|
||||
link.send_private("%u%% of the rest rains down on others in the channel, and %u%% are placed" % (100*config.pinata_rain_remainder_share,100*config.pinata_carry_remainder_share))
|
||||
link.send_private("in a new pinata. If you miss it, your %s end up in the pinata," % (coinspecs.name))
|
||||
link.send_private("increasing the bounty for next attempt")
|
||||
link.send_private("The winner's share is proportional to the amount of %s on the winning hit," % coinspecs.name)
|
||||
link.send_private("so you don't lose out by trying higher amounts")
|
||||
link.send_private("Remember, only one particular amount will manage to smash the pinata, try to find it!")
|
||||
|
||||
|
||||
|
||||
random.seed(time.time())
|
||||
RegisterModule({
|
||||
'name': __name__,
|
||||
'help': PinataHelp,
|
||||
})
|
||||
RegisterCommand({
|
||||
'module': __name__,
|
||||
'name': 'pinata',
|
||||
'parms': '<amount-in-monero>',
|
||||
'function': Pinata,
|
||||
'registered': True,
|
||||
'help': "swing some %s at the pinata" % (coinspecs.name)
|
||||
})
|
Loading…
Reference in a new issue