import random
from collections import defaultdict
from typing import List, Tuple
class Player:
def init(self, id: int, br: int, squad_id: int = None):
self.id = id
self.br = br # Боевой рейтинг (1-5)
self.squad_id = squad_id # ID взвода (None для одиночных игроков)
class Matchmaker:
def init(self):
self.queues = defaultdict(list) # Очереди по БР
self.squad_counter = 0 # Счетчик для генерации ID взводов
def add_player(self, player: Player) -> int:
"""Добавляет игрока в очередь и возвращает ID его взвода"""
if player.squad_id is None:
player.squad_id = self.squad_counter
self.squad_counter += 1
self.queues[player.br].append(player)
return player.squad_id
def find_match(self) -> Tuple[List[Player], List[Player]]:
"""Пытается найти матч, возвращает две команды или None"""
# Сначала ищем полные взводы из 4 игроков
for br in range(1, 6):
squad_groups = self._group_by_squads(self.queues[br])
for squad_id, players in squad_groups.items():
if len(players) == 4:
# Нашли полный взвод - ищем противников
enemy_team = self._find_enemy_for_squad(br, players)
if enemy_team:
# Удаляем игроков из очереди
self._remove_players_from_queue(players + enemy_team)
return (players, enemy_team)
# Если не нашли взводы, формируем случайные команды
return self._create_random_teams()
def _find_enemy_for_squad(self, br: int, squad: List[Player]) -> List[Player]:
"""Ищет противников для взвода"""
# 1. Ищем такой же взвод на том же БР
squad_groups = self._group_by_squads(self.queues[br])
for enemy_squad_id, enemy_players in squad_groups.items():
if enemy_squad_id != squad[0].squad_id and len(enemy_players) == 4:
return enemy_players
# 2. Если не нашли, ищем на БР выше (но не для 5 БР)
if br < 5:
higher_br = br + 1
# Берем любых 4 игроков с более высоким БР
candidates = []
for player in self.queues[higher_br]:
if player.squad_id is None or len(self._get_squad_players(player.squad_id, higher_br)) < 4:
candidates.append(player)
if len(candidates) == 4:
return candidates
# 3. Для 5 БР ждем такого же взвода
return None
def _group_by_squads(self, players: List[Player]) -> dict:
"""Группирует игроков по ID взвода"""
squads = defaultdict(list)
for player in players:
squads[player.squad_id].append(player)
return squads
def _get_squad_players(self, squad_id: int, br: int) -> List[Player]:
"""Возвращает всех игроков взвода с указанным БР"""
return [p for p in self.queues[br] if p.squad_id == squad_id]
def _remove_players_from_queue(self, players: List[Player]):
"""Удаляет игроков из очереди"""
for player in players:
if player in self.queues[player.br]:
self.queues[player.br].remove(player)
def _create_random_teams(self) -> Tuple[List[Player], List[Player]]:
"""Создает случайные команды из одиночных игроков"""
all_players = []
for br in range(1, 6):
all_players.extend(self.queues[br])
# Фильтруем одиночных игроков
solo_players = [p for p in all_players if p.squad_id is None or len(self._get_squad_players(p.squad_id, p.br)) < 4]
if len(solo_players) >= 10:
selected = random.sample(solo_players, 10)
team1 = selected[:5]
team2 = selected[5:]
self._remove_players_from_queue(team1 + team2)
return (team1, team2)
return None
Пример использования
matchmaker = Matchmaker()
Добавляем игроков
for i in range(100):
br = random.randint(1, 5)
# 25% chance to be in a squad of 4
if random.random() < 0.25 and i % 4 == 0:
squad_id = i // 4
for j in range(4):
matchmaker.add_player(Player(i+j, br, squad_id))
else:
matchmaker.add_player(Player(i, br))
Пытаемся найти матч
match = matchmaker.find_match()
if match:
team1, team2 = match
print(f"Team 1 BRs: {[p.br for p in team1]}“)
print(f"Team 2 BRs: {[p.br for p in team2]}”)
else:
print(“Not enough players for a match”)