RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1361304
Accepted
S_Smerch
S_Smerch
Asked:2022-05-15 18:58:46 +0000 UTC2022-05-15 18:58:46 +0000 UTC 2022-05-15 18:58:46 +0000 UTC

如何改进和缩短 discord.py 中的关卡和 Xp 系统?

  • 772

我有这样的代码:

from webserver import keep_alive
import discord
import json
import sqlite3
import re
import os
from discord.ext import commands
import datetime
import random
from pymongo import MongoClient
import asyncio
import levelsys

cogs = [levelsys]

client = commands.Bot(command_prefix = "!", intents=discord.Intents.all());

bot_channel = 702341394014011425
talk_channels = [702341394014011425]

level = ["🥉Bronze🥉", "🥈Iron🥈", "🥇Gold🥇", "💎Diamond💎", "👑Elite👑"]
levelnum = [5, 10, 20, 30, 50]

cluster = MongoClient("mongodb+srv://<ss>:<12345>@cluster0.vraiu.mongodb.net/Cluster0?retryWrites=true&w=majority")

levelling = cluster["discord"]["levelling"]

class levelsys(commands.Cog):
    def __init__(self, client):
        self.client = client

    @commands.Cog.listener()
    async def on_ready(self):
        print("ready!")

    @commands.Cog.listener()
    async def on_message(self, message):
        if message.channel.id in talk_channels:
            stats = levelling.find_one({"id" : message.author.id})
            if not message.author.bot:
                if stats is None:
                    newuser = {"id" : message.author.id, "xp" : 100}
                    levelling.insert_one(newuser)
                else:
                    xp = stats["xp"] + 5
                    levelling.update_one({"id":message.author.id}, {"$set":{"xp":xp}})
                    lvl = 0
                    while True:
                        if xp < ((50*(lvl**2))+(50*lvl)):
                            break
                        lvl += 1
                    xp -= ((50*((lvl-1)**2))+(50*(lvl-1)))
                    if xp == 0:
                        await message.channel.send(f'У {message.author.mention} повысился уровень до **{lvl}**!')
                        for i in range(len(level)):
                            if lvl == levelnum[1]:
                                await message.author.add_roles(discord.utils.get(message.author.guild.roles, name=level[1]))
                                embed = discord.Embed(description=f"{message.author.mention} ты получил роль **{level[1]}**!")
                                embed.set_thumbnail(url=message.author.avatar_url)
                                await message.channel.send(embed=embed)

    @commands.command()
    async def ранг(self, ctx):
        if ctx.channel.id == bot_channel:
            stats = levelling.find_one({"id" : ctx.author.id})
            if stats is None:
                embed = discord.Embed(description="Вы не отправляли ни одного сообщения!")
                await ctx.channel.send(embed=embed)
            else:
                xp = stats["xp"]
                lvl = 0
                rank = 0
                while True:
                        if xp < ((50*(lvl**2))+(50*lvl)):
                            break
                        lvl += 1
                xp -= ((50*((lvl-1)**2))+(50*(lvl-1)))
                boxes = int((xp/(200*((1/2) * lvl)))*20)
                rankings = levelling.find().sort("xp",-1)
                for x in rankings:
                    rank += 1
                    if stats["id"] == x["id"]:
                        break
                embed = discord.Embed(title="{} статистика уровней".format(ctx.author.name))
                embed.add_field(name="Имя", value=ctx.author.mention, inline=True)
                embed.add_field(name="XP", value=f"{xp}/{int(200*((1/2)*lvl))}", inline=True)
                embed.add_field(name="Ранг", value=f"{rank}/{ctx.guild.member_count}", inline=True)
                embed.add_field(name="Progress Bar [lvl]", value=boxes * ":blue_square:" + (20-boxes) * ":white_large_square:", inline=False)
                embed.set_thumbnail(url=ctx.author.avatar_url)
                await ctx.channel.send(embed=embed)

    @commands.command()
    async def лидеры(self, ctx):
        if (ctx.channel.id == bot_channel):
            rankings = levelling.find().sort("xp",-1)
            i = 1
            embed = discord.Embed(title="Рейтинг участнков:")
            for x in rankings:
                try:
                    temp = ctx.guild.get_member(x["id"])
                    tempxp = x["xp"]
                    embed.add_field(name=f"{i}: {temp.name}", value=f"Всего опыта: {tempxp}", inline=False)
                    i += 1
                except:
                    pass
                if i == 11:
                    break
            await ctx.channel.send(embed=embed)

但是他:

  1. 不工作
  2. 长(在我看来)

如何改善和减少?

我写在replit上

python
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Be3y4uu_K0T
    2022-05-15T23:32:29Z2022-05-15T23:32:29Z

    我建议你在这里重写这部分:

    lvl = 0
    while True:
        if xp < ((50*(lvl**2))+(50*lvl)):
            break
        lvl += 1
    xp -= ((50*((lvl-1)**2))+(50*(lvl-1)))
    

    简单的数学:

    (50*(lvl**2)) + (50*lvl) = xp
    50*lvl**2 + 50*lvl = xp
    50*(lvl**2 + lvl) = xp
    lvl**2 + lvl = xp/50
    lvl**2 + lvl - xp/50 = 0
    D = b**2 -4*a*c = 1 + 4*xp/50
    lvl = (math.sqrt(4*xp/50 + 1) - 1) / 2
    

    最好把它放在一个函数中:

    def get_level(xp: int) -> float:
        k = 50
        return (math.sqrt(4*xp/k + 1) - 1) / 2
    
    def get_current_level(xp: int) -> float:
        k = 50
        return (math.sqrt(4*xp/k + 1) - 1) // 2
    
    def get_xp(level: int) -> int:
        k = 50
        return k*level*(level + 1)
    
    >>> get_level(2800)
    7.0
    >>> get_level(2700)
    6.865459931328117
    >>> get_current_level(2800)
    7.0
    >>> get_current_level(2700)
    6.0 
    

    同时搜索排名:

    rankings = levelling.find().sort("xp",-1)
    for user in rankings:
        rank += 1
        if stats['id'] == user['id']:
            break
    
    rank = levelling.count_documents({'xp': {'$gt': xp}}) + 1
    

    您还可以组合这三行:

    stats = levelling.find_one({"id" : message.author.id})
    ...
    xp = stats["xp"] + 5
    levelling.update_one({"id":message.author.id}, {"$set":{"xp":xp}})
    
    stats = levelling.find_one_and_update(
        {'_id': message.author.id}, {'$inc': {'xp': 5}},
        return_document=pymongo.ReturnDocument.AFTER
    )
    

    我的最终代码:

    from discord.ext import commands
    import pymongo as mg
    import discord as ds
    import math
    
    bot = commands.Bot(command_prefix='!', intents=ds.Intents.all())
    
    bot_channel = ...
    talk_channels = {...}
    
    levels = {
        5: '🥉Bronze🥉',
        10: '🥈Iron🥈',
        20: '🥇Gold🥇',
        30: '💎Diamond💎',
        50: '👑Elite👑',
    }
    
    client = mg.MongoClient('mongodb://127.0.0.1:27017/', connect=False)
    db = client.discord
    
    def get_level(xp: int) -> float:
        k = 50
        return (math.sqrt(4*xp/k + 1) - 1) / 2
    
    def get_current_level(xp: int) -> float:
        k = 50
        return (math.sqrt(4*xp/k + 1) - 1) // 2
    
    def get_xp(level: int) -> int:
        k = 50
        return k*level*(level + 1)
    
    @bot.event
    async def on_ready():
        print('ready!')
    
    @bot.event
    async def on_message(message):
        if message.channel.id not in talk_channels:
            return
        
        if message.author.bot:
            return 
    
        if message.content.startswith(bot.command_prefix):
            return await bot.process_commands(message)
    
        user = db.levelling.find_one_and_update(
            {'_id': message.author.id}, {'$inc': {'xp': 100}},
            return_document=mg.ReturnDocument.AFTER
        )
    
        if user is None:
            new_user = {'_id' : message.author.id, 'xp' : 100}
            db.levelling.insert_one(new_user)
        else:
            level = get_level(user['xp'])
            print(user['xp'], level, level.is_integer())
            if level.is_integer():
                await message.channel.send(
                    f'У {message.author.mention} повысился уровень до **{int(level)}**!'
                )
                if rank := levels.get(level):
                    await message.author.add_roles(ds.utils.get(message.author.guild.roles, name=rank))
                    embed = ds.Embed(description=f'{message.author.mention} ты получил роль **{rank}**!')
                    embed.set_thumbnail(url=message.author.avatar_url)
                    await message.channel.send(embed=embed)
    
    @bot.command()
    async def ранг(ctx):
        if ctx.channel.id != bot_channel:
            return
        
        stats = db.levelling.find_one({'_id' : ctx.author.id})
        if stats is None:
            embed = ds.Embed(description='Вы не отправляли ни одного сообщения!')
            await ctx.channel.send(embed=embed)
        else:
            xp = stats['xp']
            lvl = get_current_level(xp)
            next_xp = get_xp(lvl + 1)
            rank = db.levelling.count_documents({'xp': {'$gt': xp}}) + 1
    
            length_bar = 20
            boxes = int(length_bar * xp / next_xp)
            
            embed = ds.Embed(title=f'{ctx.author.name} статистика уровней')
            embed.add_field(name='Имя', value=ctx.author.mention, inline=True)
            embed.add_field(name='XP', value=f'{xp}/{next_xp}', inline=True)
            embed.add_field(name='Ранг', value=f'{rank}/{ctx.guild.member_count}', inline=True)
            embed.add_field(
                name='Progress Bar [lvl]',
                value=boxes * ':blue_square:' + (length_bar-boxes) * ':white_large_square:',
                inline=False
            )
            embed.set_thumbnail(url=ctx.author.avatar_url)
            await ctx.channel.send(embed=embed)
    
    @bot.command()
    async def лидеры(ctx):
        if ctx.channel.id != bot_channel:
            return
        
        embed = ds.Embed(title='Рейтинг участнков:')
        rankings = db.levelling.aggregate([
            {'$limit': 10},
            {
                '$setWindowFields': {
                    'sortBy': {'xp': mg.DESCENDING},
                    'output': {
                        'rank': {'$rank': {}},
                    },
                }
            }
        ])
    
        for user in rankings:
            xp = user['xp']
            member = ctx.guild.get_member(user['_id'])
            embed.add_field(
                name=f'{user["rank"]}: {member.name}',
                value=f'Всего опыта: {xp}',
                inline=False
            )
        await ctx.channel.send(embed=embed)
    
    bot.run('<token>')
    
    • 0

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5