Diff
checker
Texte
Texte
Images
Documents
Excel
Dossiers
Legal
Enterprise
Application de bureau
Prix
Se connecter
Télécharger Diffchecker Desktop
Comparer le texte
Trouver la différence entre deux fichiers texte
Outils
Historique
Éditeur live
Cacher identiques
Sans retour à la ligne
Vue
Divisé
Unifié
Niveau de précision
Intelligent
Mot
Caractère
Coloration syntaxique
Choisir la syntaxe
Ignorer
Transformer le texte
Aller au premier écart
Modifier l'entrée
Diffchecker Desktop
La façon la plus sécurisée d'utiliser Diffchecker. Obtenez l'application Diffchecker Desktop : vos diffs ne quittent jamais votre ordinateur !
Obtenir Desktop
Cog diff
Créé
l’année dernière
Le diff n'expire jamais
Effacer
Exporter
Partager
Expliquer
1 suppression
Lignes
Total
Supprimé
Caractères
Total
Supprimé
Pour continuer à utiliser cette fonctionnalité, passez à
Diff
checker
Pro
Voir les prix
159 lignes
Copier tout
7 ajouts
Lignes
Total
Ajouté
Caractères
Total
Ajouté
Pour continuer à utiliser cette fonctionnalité, passez à
Diff
checker
Pro
Voir les prix
159 lignes
Copier tout
import discord
import discord
import numpy as np
import numpy as np
from discord.ext import commands, pages
from discord.ext import commands, pages
import os
import os
from discord_bot.utils.cr_functions import combine_cards, get_deck_strings, build_paginator_embeds
from discord_bot.utils.cr_functions import combine_cards, get_deck_strings, build_paginator_embeds
from discord_bot.utils import emoji_cache
from discord_bot.utils import emoji_cache
Copier
Copié
Copier
Copié
from discord_bot.utils.embeds import not_in_database
, database_error, error_embed
from discord_bot.utils.embeds import not_in_database
from discord_bot.utils.emoji_cache import MISC_EMOJIS
from discord_bot.utils.emoji_cache import MISC_EMOJIS
# https://guide.pycord.dev/popular-topics/cogs
# https://guide.pycord.dev/popular-topics/cogs
Copier
Copié
Copier
Copié
class Player
(commands.Cog):
class Player
Test
(commands.Cog):
def __init__(self, bot):
def __init__(self, bot):
self.bot = bot
self.bot = bot
async def check_valid_playertag(self, playertag):
async def check_valid_playertag(self, playertag):
print(playertag, '#' + playertag.replace('#', '').strip().upper().replace('O', '0'))
print(playertag, '#' + playertag.replace('#', '').strip().upper().replace('O', '0'))
playertag = '#' + playertag.replace('#', '').strip().upper().replace('O', '0')
playertag = '#' + playertag.replace('#', '').strip().upper().replace('O', '0')
playertag_exists = await self.bot.pool.fetchval(f"SELECT EXISTS "
playertag_exists = await self.bot.pool.fetchval(f"SELECT EXISTS "
f"(SELECT 1 FROM players WHERE playertag = $1)", playertag)
f"(SELECT 1 FROM players WHERE playertag = $1)", playertag)
if not playertag_exists:
if not playertag_exists:
return False, not_in_database('playertag', playertag)
return False, not_in_database('playertag', playertag)
return True, playertag
return True, playertag
Copier
Copié
Copier
Copié
player
= discord.SlashCommandGroup('player
', 'Player related commands.')
player
2
= discord.SlashCommandGroup('player
2
', 'Player related commands.')
@discord.option('playertag', type=str)
@discord.option('playertag', type=str)
Copier
Copié
Copier
Copié
@player
.command(description='Show a basic overview for this playertag.')
@player
2
.command(description='Show a basic overview for this playertag.')
async def basic_info(self, ctx, playertag):
async def basic_info(self, ctx, playertag):
await ctx.defer()
await ctx.defer()
is_valid, result = await self.check_valid_playertag(playertag) # Check if exists in db, else return non-existent
is_valid, result = await self.check_valid_playertag(playertag) # Check if exists in db, else return non-existent
if not is_valid:
if not is_valid:
return await ctx.respond(embed=result)
return await ctx.respond(embed=result)
playertag = result
playertag = result
query = """
query = """
SELECT
SELECT
p.player_name,
p.player_name,
COUNT(*) FILTER (WHERE TRUE) AS total,
COUNT(*) FILTER (WHERE TRUE) AS total,
COUNT(*) FILTER (WHERE match_result = 'win') AS wins,
COUNT(*) FILTER (WHERE match_result = 'win') AS wins,
COUNT(*) FILTER (WHERE match_result = 'loss') AS losses,
COUNT(*) FILTER (WHERE match_result = 'loss') AS losses,
COUNT(*) FILTER (WHERE match_result = 'throw') AS throws,
COUNT(*) FILTER (WHERE match_result = 'throw') AS throws,
COUNT(*) FILTER (WHERE match_result = 'tie') AS ties
COUNT(*) FILTER (WHERE match_result = 'tie') AS ties
FROM matches m
FROM matches m
JOIN players p on m.playertag = p.playertag
JOIN players p on m.playertag = p.playertag
WHERE m.playertag = $1
WHERE m.playertag = $1
GROUP BY p.player_name
GROUP BY p.player_name
"""
"""
row = await self.bot.pool.fetchrow(query, playertag)
row = await self.bot.pool.fetchrow(query, playertag)
total_matches = row["total"]
total_matches = row["total"]
wins = row["wins"]
wins = row["wins"]
losses = row["losses"]
losses = row["losses"]
throws = row["throws"]
throws = row["throws"]
ties = row["ties"]
ties = row["ties"]
name = row["player_name"]
name = row["player_name"]
if wins + losses == 0:
if wins + losses == 0:
win_rate = 0
win_rate = 0
else:
else:
win_rate = (wins / (wins + losses)) * 100
win_rate = (wins / (wins + losses)) * 100
embed = discord.Embed(
embed = discord.Embed(
title=f'{name} ({playertag})',
title=f'{name} ({playertag})',
color=discord.Color.dark_blue(),
color=discord.Color.dark_blue(),
)
)
embed.set_footer(text='Basic Overview')
embed.set_footer(text='Basic Overview')
embed.set_thumbnail(url=os.getenv('BOT_IMAGE'))
embed.set_thumbnail(url=os.getenv('BOT_IMAGE'))
embed.add_field(name=f'__Matches__ {MISC_EMOJIS.get('clan_war_wins')}', value=f'{total_matches}')
embed.add_field(name=f'__Matches__ {MISC_EMOJIS.get('clan_war_wins')}', value=f'{total_matches}')
embed.add_field(name=f'__Win Rate__ 📈', value=f'{win_rate:.2f}%', inline=True)
embed.add_field(name=f'__Win Rate__ 📈', value=f'{win_rate:.2f}%', inline=True)
embed.add_field(name=f'__Wins__ {MISC_EMOJIS.get('win3crowns')}', value=wins, inline=True)
embed.add_field(name=f'__Wins__ {MISC_EMOJIS.get('win3crowns')}', value=wins, inline=True)
embed.add_field(name=f'__Losses__ {MISC_EMOJIS.get('lose3crowns')}', value=losses, inline=True)
embed.add_field(name=f'__Losses__ {MISC_EMOJIS.get('lose3crowns')}', value=losses, inline=True)
embed.add_field(name=f'__Throws__', value=throws)
embed.add_field(name=f'__Throws__', value=throws)
embed.add_field(name=f'__Ties__ {MISC_EMOJIS.get('blue_crown')}{MISC_EMOJIS.get('red_crown')}', value=ties)
embed.add_field(name=f'__Ties__ {MISC_EMOJIS.get('blue_crown')}{MISC_EMOJIS.get('red_crown')}', value=ties)
await ctx.respond(embed=embed)
await ctx.respond(embed=embed)
Copier
Copié
Copier
Copié
@player
.command(description='Show the war decks for this playertag.')
@player
2
.command(description='Show the war decks for this playertag.')
@discord.option('playertag', type=str)
@discord.option('playertag', type=str)
Copier
Copié
Copier
Copié
async def decks
(self, ctx, playertag):
async def decks
_fail
(self, ctx, playertag):
await ctx.defer()
await ctx.defer()
is_valid, result = await self.check_valid_playertag(playertag) # Check if exists in db, else return it didnt exist
is_valid, result = await self.check_valid_playertag(playertag) # Check if exists in db, else return it didnt exist
if not is_valid:
if not is_valid:
return await ctx.respond(embed=result)
return await ctx.respond(embed=result)
playertag = result
playertag = result
query = """
query = """
SELECT
SELECT
m.playertag,
m.playertag,
m.player_deck_id,
m.player_deck_id,
m.clan_league,
m.clan_league,
ds.cards,
ds.cards,
ds.evolutions,
ds.evolutions,
MAX(m.player_name) AS player_name, -- optional, latest name
MAX(m.player_name) AS player_name, -- optional, latest name
COUNT(*) FILTER (WHERE m.match_result = 'win') AS wins,
COUNT(*) FILTER (WHERE m.match_result = 'win') AS wins,
COUNT(*) FILTER (WHERE m.match_result = 'loss') AS losses
COUNT(*) FILTER (WHERE m.match_result = 'loss') AS losses
FROM matches m
FROM matches m
JOIN deck_signatures ds ON m.player_deck_id = ds.deck_id
JOIN deck_signatures ds ON m.player_deck_id = ds.deck_id
WHERE m.playertag = $1
WHERE m.playertag = $1
GROUP BY m.playertag, m.player_deck_id, m.clan_league, ds.cards, ds.evolutions
GROUP BY m.playertag, m.player_deck_id, m.clan_league, ds.cards, ds.evolutions
"""
"""
rows = await self.bot.pool.fetch(query, playertag)
rows = await self.bot.pool.fetch(query, playertag)
deck_rows3 = []
deck_rows3 = []
deck_rows4 = []
deck_rows4 = []
deck_rows5 = []
deck_rows5 = []
name = ''
name = ''
for row in rows:
for row in rows:
clan_league = int(np.clip(row.get('clan_league') // 1000, 0, 5))
clan_league = int(np.clip(row.get('clan_league') // 1000, 0, 5))
if name == '':
if name == '':
name = row.get('player_name')
name = row.get('player_name')
full_deck = combine_cards(row.get('evolutions'), row.get('cards'))
full_deck = combine_cards(row.get('evolutions'), row.get('cards'))
deck_data = {
deck_data = {
'cards': full_deck,
'cards': full_deck,
'wins': row.get('wins'),
'wins': row.get('wins'),
'losses': row.get('losses')
'losses': row.get('losses')
}
}
if clan_league == 5:
if clan_league == 5:
deck_rows5.append(deck_data)
deck_rows5.append(deck_data)
elif clan_league == 4:
elif clan_league == 4:
deck_rows4.append(deck_data)
deck_rows4.append(deck_data)
else:
else:
deck_rows3.append(deck_data)
deck_rows3.append(deck_data)
for deck_list in [deck_rows3, deck_rows4, deck_rows5]:
for deck_list in [deck_rows3, deck_rows4, deck_rows5]:
deck_list.sort(key=lambda x: (-x.get('wins'), x.get('losses')))
deck_list.sort(key=lambda x: (-x.get('wins'), x.get('losses')))
try:
try:
success3, pages3 = build_paginator_embeds(get_deck_strings(deck_rows3), name, playertag, '0-3')
success3, pages3 = build_paginator_embeds(get_deck_strings(deck_rows3), name, playertag, '0-3')
success4, pages4 = build_paginator_embeds(get_deck_strings(deck_rows4), name, playertag, '4')
success4, pages4 = build_paginator_embeds(get_deck_strings(deck_rows4), name, playertag, '4')
success5, pages5 = build_paginator_embeds(get_deck_strings(deck_rows5), name, playertag, '5')
success5, pages5 = build_paginator_embeds(get_deck_strings(deck_rows5), name, playertag, '5')
except ValueError as e:
except ValueError as e:
return await ctx.respond(embed=discord.Embed(description=str(e), color=discord.Color.red()))
return await ctx.respond(embed=discord.Embed(description=str(e), color=discord.Color.red()))
page_groups = []
page_groups = []
if success3:
if success3:
page_groups.append(pages.PageGroup(pages=pages3, label='League 0-3'))
page_groups.append(pages.PageGroup(pages=pages3, label='League 0-3'))
if success4:
if success4:
page_groups.append(pages.PageGroup(pages=pages4, label='League 4'))
page_groups.append(pages.PageGroup(pages=pages4, label='League 4'))
if success5:
if success5:
page_groups.append(pages.PageGroup(pages=pages5, label='League 5', default=True))
page_groups.append(pages.PageGroup(pages=pages5, label='League 5', default=True))
if not page_groups:
if not page_groups:
return await ctx.respond(
return await ctx.respond(
embed=discord.Embed(
embed=discord.Embed(
description="No decks available for any league.",
description="No decks available for any league.",
color=discord.Color.red()
color=discord.Color.red()
)
)
)
)
paginator = pages.Paginator(
paginator = pages.Paginator(
pages=page_groups,
pages=page_groups,
show_menu=True, menu_placeholder=f'Select League',
show_menu=True, menu_placeholder=f'Select League',
show_disabled=False, show_indicator=True
show_disabled=False, show_indicator=True
)
)
await paginator.respond(ctx.interaction, ephemeral=False)
await paginator.respond(ctx.interaction, ephemeral=False)
def setup(bot):
def setup(bot):
Copier
Copié
Copier
Copié
bot.add_cog(Player
(bot))
bot.add_cog(Player
Test
(bot))
Différences enregistrées
Texte d'origine
Ouvrir un fichier
import discord import numpy as np from discord.ext import commands, pages import os from discord_bot.utils.cr_functions import combine_cards, get_deck_strings, build_paginator_embeds from discord_bot.utils import emoji_cache from discord_bot.utils.embeds import not_in_database, database_error, error_embed from discord_bot.utils.emoji_cache import MISC_EMOJIS # https://guide.pycord.dev/popular-topics/cogs class Player(commands.Cog): def __init__(self, bot): self.bot = bot async def check_valid_playertag(self, playertag): print(playertag, '#' + playertag.replace('#', '').strip().upper().replace('O', '0')) playertag = '#' + playertag.replace('#', '').strip().upper().replace('O', '0') playertag_exists = await self.bot.pool.fetchval(f"SELECT EXISTS " f"(SELECT 1 FROM players WHERE playertag = $1)", playertag) if not playertag_exists: return False, not_in_database('playertag', playertag) return True, playertag player = discord.SlashCommandGroup('player', 'Player related commands.') @discord.option('playertag', type=str) @player.command(description='Show a basic overview for this playertag.') async def basic_info(self, ctx, playertag): await ctx.defer() is_valid, result = await self.check_valid_playertag(playertag) # Check if exists in db, else return non-existent if not is_valid: return await ctx.respond(embed=result) playertag = result query = """ SELECT p.player_name, COUNT(*) FILTER (WHERE TRUE) AS total, COUNT(*) FILTER (WHERE match_result = 'win') AS wins, COUNT(*) FILTER (WHERE match_result = 'loss') AS losses, COUNT(*) FILTER (WHERE match_result = 'throw') AS throws, COUNT(*) FILTER (WHERE match_result = 'tie') AS ties FROM matches m JOIN players p on m.playertag = p.playertag WHERE m.playertag = $1 GROUP BY p.player_name """ row = await self.bot.pool.fetchrow(query, playertag) total_matches = row["total"] wins = row["wins"] losses = row["losses"] throws = row["throws"] ties = row["ties"] name = row["player_name"] if wins + losses == 0: win_rate = 0 else: win_rate = (wins / (wins + losses)) * 100 embed = discord.Embed( title=f'{name} ({playertag})', color=discord.Color.dark_blue(), ) embed.set_footer(text='Basic Overview') embed.set_thumbnail(url=os.getenv('BOT_IMAGE')) embed.add_field(name=f'__Matches__ {MISC_EMOJIS.get('clan_war_wins')}', value=f'{total_matches}') embed.add_field(name=f'__Win Rate__ 📈', value=f'{win_rate:.2f}%', inline=True) embed.add_field(name=f'__Wins__ {MISC_EMOJIS.get('win3crowns')}', value=wins, inline=True) embed.add_field(name=f'__Losses__ {MISC_EMOJIS.get('lose3crowns')}', value=losses, inline=True) embed.add_field(name=f'__Throws__', value=throws) embed.add_field(name=f'__Ties__ {MISC_EMOJIS.get('blue_crown')}{MISC_EMOJIS.get('red_crown')}', value=ties) await ctx.respond(embed=embed) @player.command(description='Show the war decks for this playertag.') @discord.option('playertag', type=str) async def decks(self, ctx, playertag): await ctx.defer() is_valid, result = await self.check_valid_playertag(playertag) # Check if exists in db, else return it didnt exist if not is_valid: return await ctx.respond(embed=result) playertag = result query = """ SELECT m.playertag, m.player_deck_id, m.clan_league, ds.cards, ds.evolutions, MAX(m.player_name) AS player_name, -- optional, latest name COUNT(*) FILTER (WHERE m.match_result = 'win') AS wins, COUNT(*) FILTER (WHERE m.match_result = 'loss') AS losses FROM matches m JOIN deck_signatures ds ON m.player_deck_id = ds.deck_id WHERE m.playertag = $1 GROUP BY m.playertag, m.player_deck_id, m.clan_league, ds.cards, ds.evolutions """ rows = await self.bot.pool.fetch(query, playertag) deck_rows3 = [] deck_rows4 = [] deck_rows5 = [] name = '' for row in rows: clan_league = int(np.clip(row.get('clan_league') // 1000, 0, 5)) if name == '': name = row.get('player_name') full_deck = combine_cards(row.get('evolutions'), row.get('cards')) deck_data = { 'cards': full_deck, 'wins': row.get('wins'), 'losses': row.get('losses') } if clan_league == 5: deck_rows5.append(deck_data) elif clan_league == 4: deck_rows4.append(deck_data) else: deck_rows3.append(deck_data) for deck_list in [deck_rows3, deck_rows4, deck_rows5]: deck_list.sort(key=lambda x: (-x.get('wins'), x.get('losses'))) try: success3, pages3 = build_paginator_embeds(get_deck_strings(deck_rows3), name, playertag, '0-3') success4, pages4 = build_paginator_embeds(get_deck_strings(deck_rows4), name, playertag, '4') success5, pages5 = build_paginator_embeds(get_deck_strings(deck_rows5), name, playertag, '5') except ValueError as e: return await ctx.respond(embed=discord.Embed(description=str(e), color=discord.Color.red())) page_groups = [] if success3: page_groups.append(pages.PageGroup(pages=pages3, label='League 0-3')) if success4: page_groups.append(pages.PageGroup(pages=pages4, label='League 4')) if success5: page_groups.append(pages.PageGroup(pages=pages5, label='League 5', default=True)) if not page_groups: return await ctx.respond( embed=discord.Embed( description="No decks available for any league.", color=discord.Color.red() ) ) paginator = pages.Paginator( pages=page_groups, show_menu=True, menu_placeholder=f'Select League', show_disabled=False, show_indicator=True ) await paginator.respond(ctx.interaction, ephemeral=False) def setup(bot): bot.add_cog(Player(bot))
Texte modifié
Ouvrir un fichier
import discord import numpy as np from discord.ext import commands, pages import os from discord_bot.utils.cr_functions import combine_cards, get_deck_strings, build_paginator_embeds from discord_bot.utils import emoji_cache from discord_bot.utils.embeds import not_in_database from discord_bot.utils.emoji_cache import MISC_EMOJIS # https://guide.pycord.dev/popular-topics/cogs class PlayerTest(commands.Cog): def __init__(self, bot): self.bot = bot async def check_valid_playertag(self, playertag): print(playertag, '#' + playertag.replace('#', '').strip().upper().replace('O', '0')) playertag = '#' + playertag.replace('#', '').strip().upper().replace('O', '0') playertag_exists = await self.bot.pool.fetchval(f"SELECT EXISTS " f"(SELECT 1 FROM players WHERE playertag = $1)", playertag) if not playertag_exists: return False, not_in_database('playertag', playertag) return True, playertag player2 = discord.SlashCommandGroup('player2', 'Player related commands.') @discord.option('playertag', type=str) @player2.command(description='Show a basic overview for this playertag.') async def basic_info(self, ctx, playertag): await ctx.defer() is_valid, result = await self.check_valid_playertag(playertag) # Check if exists in db, else return non-existent if not is_valid: return await ctx.respond(embed=result) playertag = result query = """ SELECT p.player_name, COUNT(*) FILTER (WHERE TRUE) AS total, COUNT(*) FILTER (WHERE match_result = 'win') AS wins, COUNT(*) FILTER (WHERE match_result = 'loss') AS losses, COUNT(*) FILTER (WHERE match_result = 'throw') AS throws, COUNT(*) FILTER (WHERE match_result = 'tie') AS ties FROM matches m JOIN players p on m.playertag = p.playertag WHERE m.playertag = $1 GROUP BY p.player_name """ row = await self.bot.pool.fetchrow(query, playertag) total_matches = row["total"] wins = row["wins"] losses = row["losses"] throws = row["throws"] ties = row["ties"] name = row["player_name"] if wins + losses == 0: win_rate = 0 else: win_rate = (wins / (wins + losses)) * 100 embed = discord.Embed( title=f'{name} ({playertag})', color=discord.Color.dark_blue(), ) embed.set_footer(text='Basic Overview') embed.set_thumbnail(url=os.getenv('BOT_IMAGE')) embed.add_field(name=f'__Matches__ {MISC_EMOJIS.get('clan_war_wins')}', value=f'{total_matches}') embed.add_field(name=f'__Win Rate__ 📈', value=f'{win_rate:.2f}%', inline=True) embed.add_field(name=f'__Wins__ {MISC_EMOJIS.get('win3crowns')}', value=wins, inline=True) embed.add_field(name=f'__Losses__ {MISC_EMOJIS.get('lose3crowns')}', value=losses, inline=True) embed.add_field(name=f'__Throws__', value=throws) embed.add_field(name=f'__Ties__ {MISC_EMOJIS.get('blue_crown')}{MISC_EMOJIS.get('red_crown')}', value=ties) await ctx.respond(embed=embed) @player2.command(description='Show the war decks for this playertag.') @discord.option('playertag', type=str) async def decks_fail(self, ctx, playertag): await ctx.defer() is_valid, result = await self.check_valid_playertag(playertag) # Check if exists in db, else return it didnt exist if not is_valid: return await ctx.respond(embed=result) playertag = result query = """ SELECT m.playertag, m.player_deck_id, m.clan_league, ds.cards, ds.evolutions, MAX(m.player_name) AS player_name, -- optional, latest name COUNT(*) FILTER (WHERE m.match_result = 'win') AS wins, COUNT(*) FILTER (WHERE m.match_result = 'loss') AS losses FROM matches m JOIN deck_signatures ds ON m.player_deck_id = ds.deck_id WHERE m.playertag = $1 GROUP BY m.playertag, m.player_deck_id, m.clan_league, ds.cards, ds.evolutions """ rows = await self.bot.pool.fetch(query, playertag) deck_rows3 = [] deck_rows4 = [] deck_rows5 = [] name = '' for row in rows: clan_league = int(np.clip(row.get('clan_league') // 1000, 0, 5)) if name == '': name = row.get('player_name') full_deck = combine_cards(row.get('evolutions'), row.get('cards')) deck_data = { 'cards': full_deck, 'wins': row.get('wins'), 'losses': row.get('losses') } if clan_league == 5: deck_rows5.append(deck_data) elif clan_league == 4: deck_rows4.append(deck_data) else: deck_rows3.append(deck_data) for deck_list in [deck_rows3, deck_rows4, deck_rows5]: deck_list.sort(key=lambda x: (-x.get('wins'), x.get('losses'))) try: success3, pages3 = build_paginator_embeds(get_deck_strings(deck_rows3), name, playertag, '0-3') success4, pages4 = build_paginator_embeds(get_deck_strings(deck_rows4), name, playertag, '4') success5, pages5 = build_paginator_embeds(get_deck_strings(deck_rows5), name, playertag, '5') except ValueError as e: return await ctx.respond(embed=discord.Embed(description=str(e), color=discord.Color.red())) page_groups = [] if success3: page_groups.append(pages.PageGroup(pages=pages3, label='League 0-3')) if success4: page_groups.append(pages.PageGroup(pages=pages4, label='League 4')) if success5: page_groups.append(pages.PageGroup(pages=pages5, label='League 5', default=True)) if not page_groups: return await ctx.respond( embed=discord.Embed( description="No decks available for any league.", color=discord.Color.red() ) ) paginator = pages.Paginator( pages=page_groups, show_menu=True, menu_placeholder=f'Select League', show_disabled=False, show_indicator=True ) await paginator.respond(ctx.interaction, ephemeral=False) def setup(bot): bot.add_cog(PlayerTest(bot))
Trouver la différence