init
This commit is contained in:
commit
be14648dfd
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
data/
|
||||||
|
venv/
|
||||||
|
.idea/
|
7
cogs/sacrifice/__init__.py
Normal file
7
cogs/sacrifice/__init__.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from .sacrifice import SacrificeCog
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot):
|
||||||
|
n = SacrificeCog(bot)
|
||||||
|
bot.add_cog(n)
|
160
cogs/sacrifice/sacrifice.py
Normal file
160
cogs/sacrifice/sacrifice.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
|
from redbot.core import commands
|
||||||
|
from redbot.core import Config, checks
|
||||||
|
import discord
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class SacrificeCog(commands.Cog):
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.config = Config.get_conf(self, identifier=154776548)
|
||||||
|
default_global = {
|
||||||
|
"elo": {},
|
||||||
|
"tracked_msgs": {}
|
||||||
|
}
|
||||||
|
self.config.register_global(**default_global)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_valid_winloss(s):
|
||||||
|
r = r"[wWlL]+"
|
||||||
|
regx = re.compile(r)
|
||||||
|
fm = regx.fullmatch(s)
|
||||||
|
return fm
|
||||||
|
|
||||||
|
async def get_rank(self, discord_id: str):
|
||||||
|
elos = await self.config.elo()
|
||||||
|
if discord_id not in elos:
|
||||||
|
return None, None
|
||||||
|
sorted_players = sorted(elos, key=elos.get, reverse=True)
|
||||||
|
return sorted_players.index(discord_id) + 1, len(sorted_players)
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_raw_reaction_add(self, payload):
|
||||||
|
tracked = await self.config.tracked_msgs()
|
||||||
|
print(str(payload.message_id))
|
||||||
|
print(tracked.keys())
|
||||||
|
if str(payload.message_id) in tracked.keys():
|
||||||
|
# fetch channel
|
||||||
|
channel = await self.bot.fetch_channel(531832488901738508) # channel
|
||||||
|
if not channel:
|
||||||
|
print("not channel")
|
||||||
|
tracked.remove(payload.message_id)
|
||||||
|
await self.config.tracked_msgs.set(tracked)
|
||||||
|
return
|
||||||
|
# fetch msg
|
||||||
|
orig_msg = await channel.fetch_message(payload.message_id)
|
||||||
|
if not orig_msg:
|
||||||
|
print("not msg")
|
||||||
|
tracked.remove(payload.message_id)
|
||||||
|
await self.config.tracked_msgs.set(tracked)
|
||||||
|
return
|
||||||
|
opponents = orig_msg.mentions
|
||||||
|
if not opponents:
|
||||||
|
print("not opponent")
|
||||||
|
tracked.remove(payload.message_id)
|
||||||
|
await self.config.tracked_msgs.set(tracked)
|
||||||
|
return
|
||||||
|
|
||||||
|
opponent = opponents[0]
|
||||||
|
|
||||||
|
print("not yet")
|
||||||
|
print(str(payload.user_id))
|
||||||
|
print(str(opponent.id))
|
||||||
|
print(payload.emoji)
|
||||||
|
if str(payload.user_id) == str(opponent.id) and payload.emoji.name == "👍":
|
||||||
|
print("true")
|
||||||
|
outcome = orig_msg.content.split(" ")[2]
|
||||||
|
print(outcome) # DEBUG
|
||||||
|
if SacrificeCog.is_valid_winloss(outcome):
|
||||||
|
for c in outcome:
|
||||||
|
if c.lower() == "w":
|
||||||
|
await self.win(str(orig_msg.author.id), str(opponent.id))
|
||||||
|
elif c.lower() == "l":
|
||||||
|
await self.win(str(opponent.id), str(orig_msg.author.id))
|
||||||
|
|
||||||
|
new_elo = await self.get_elo(str(orig_msg.author.id))
|
||||||
|
new_elo_2 = await self.get_elo(str(opponent.id))
|
||||||
|
|
||||||
|
bot_msg = await channel.fetch_message(tracked[str(payload.message_id)])
|
||||||
|
|
||||||
|
await bot_msg.edit(content="**%s**, your new ELO is: **%s**\n**%s**, your new ELO is: **%s**" % (
|
||||||
|
orig_msg.author.mention, round(new_elo), opponent.mention, round(new_elo_2))
|
||||||
|
)
|
||||||
|
|
||||||
|
del tracked[str(payload.message_id)]
|
||||||
|
await self.config.tracked_msgs.set(tracked)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
print("not valid winloss: %s" % outcome)
|
||||||
|
else:
|
||||||
|
print("not tracked")
|
||||||
|
|
||||||
|
async def track_msg(self, orig_message_id: str, bot_msg_id: str):
|
||||||
|
tracked = await self.config.tracked_msgs()
|
||||||
|
tracked[orig_message_id] = bot_msg_id
|
||||||
|
await self.config.tracked_msgs.set(tracked)
|
||||||
|
|
||||||
|
@commands.command()
|
||||||
|
async def rank(self, ctx, opponent: discord.Member = None, winloss: str = None):
|
||||||
|
author_id = str(ctx.author.id)
|
||||||
|
if not opponent and not winloss:
|
||||||
|
# send elo to player
|
||||||
|
rank, count = await self.get_rank(author_id)
|
||||||
|
if rank:
|
||||||
|
elo = await self.get_elo(author_id)
|
||||||
|
await ctx.send("**%s**, your ELO is: **%s** (ranked #%s/%s)" % (ctx.author.mention, round(elo), rank, count))
|
||||||
|
else:
|
||||||
|
await ctx.send("**%s**, you are not ranked yet" % ctx.author.mention)
|
||||||
|
return
|
||||||
|
elif opponent and not winloss:
|
||||||
|
# show opponent rank
|
||||||
|
opponent_id = str(opponent.id)
|
||||||
|
rank, count = await self.get_rank(opponent_id)
|
||||||
|
if rank:
|
||||||
|
elo = await self.get_elo(opponent_id)
|
||||||
|
await ctx.send("**%s**' ELO is: **%s** (ranked #%s/%s)" % (opponent.display_name, round(elo), rank, count))
|
||||||
|
else:
|
||||||
|
await ctx.send("**%s** is not ranked yet" % opponent.display_name)
|
||||||
|
return
|
||||||
|
elif opponent and winloss:
|
||||||
|
if not SacrificeCog.is_valid_winloss(winloss):
|
||||||
|
await ctx.send("Invalid win/losses")
|
||||||
|
return
|
||||||
|
|
||||||
|
bot_msg = await ctx.send("Waiting for %s' :thumbsup: reaction to previous message..." % opponent.display_name)
|
||||||
|
await self.track_msg(str(ctx.message.id), str(bot_msg.id))
|
||||||
|
return
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def expection(d):
|
||||||
|
return 1/(1+math.pow(10, -d/400)) # https://fr.wikipedia.org/wiki/Classement_Elo#Relation_entre_diff%C3%A9rence_de_points_Elo_et_probabilit%C3%A9_de_gain
|
||||||
|
|
||||||
|
async def win(self, winner_id: str, looser_id: str) -> None:
|
||||||
|
elo_winner = await self.get_elo(winner_id)
|
||||||
|
elo_looser = await self.get_elo(looser_id)
|
||||||
|
diff = elo_winner - elo_looser
|
||||||
|
expection_winner = SacrificeCog.expection(diff)
|
||||||
|
expection_looser = SacrificeCog.expection(-diff)
|
||||||
|
k_winner = 40 # TODO: should be lowered after many games
|
||||||
|
k_looser = 40 # TODO: should be lowered after many games
|
||||||
|
new_elo_winner = elo_winner + k_winner * (1 - expection_winner)
|
||||||
|
print("%s = %s + %s * (1 - %s)" % (new_elo_winner, elo_winner, k_winner, expection_winner))
|
||||||
|
new_elo_looser = elo_looser + k_looser * (0 - expection_looser)
|
||||||
|
await self.save_elo({winner_id: new_elo_winner, looser_id: new_elo_looser})
|
||||||
|
|
||||||
|
async def save_elo(self, scores: dict) -> None:
|
||||||
|
elos = await self.config.elo()
|
||||||
|
elos.update(scores)
|
||||||
|
print(scores)
|
||||||
|
print(elos)
|
||||||
|
await self.config.elo.set(elos)
|
||||||
|
|
||||||
|
async def get_elo(self, discord_id: str) -> int:
|
||||||
|
elos = await self.config.elo()
|
||||||
|
if discord_id in elos:
|
||||||
|
return elos[discord_id]
|
||||||
|
else:
|
||||||
|
# calculate new elo
|
||||||
|
return 1500
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Red-DiscordBot
|
Loading…
Reference in New Issue
Block a user