Skip to content

Commit

Permalink
#9 separated test bots from the main one
Browse files Browse the repository at this point in the history
  • Loading branch information
UncleVasya committed Dec 13, 2016
1 parent 5b2bed6 commit 0f626e9
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 127 deletions.
247 changes: 120 additions & 127 deletions app/balancer/management/commands/dota_bot.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from time import sleep
from django.core.management.base import BaseCommand
import thread
from django.core.urlresolvers import reverse
from django.db import transaction
import gevent
from app.balancer import models
from app.balancer.balancer import balance_teams
from app.ladder.models import Player
Expand All @@ -15,30 +14,54 @@
from dota2.enums import DOTA_GC_TEAM


bots = []
class Command(BaseCommand):
def __init__(self):
self.bots = []

def add_arguments(self, parser):
parser.add_argument('-n', '--number',
nargs='?', type=int, default=1, const=1)

def handle(self, *args, **options):
bots_num = options['number']

credentials = [
{
'login': 'login%d' % i,
'password': 'password%d' % i,
} for i in xrange(1, bots_num+1)
]

try:
gevent.joinall([
gevent.spawn(self.start_bot, c) for c in credentials
])
except KeyboardInterrupt:
for bot in self.bots:
bot.exit()
bot.steam.logout()


def start_bot(credentials):
client = SteamClient()
dota = Dota2Client(client)
def start_bot(self, credentials):
client = SteamClient()
dota = Dota2Client(client)

bots.append(dota)
self.bots.append(dota)

client.verbose_debug = True
dota.verbose_debug = True
client.verbose_debug = True
dota.verbose_debug = True

@client.on('logged_on')
def start_dota():
dota.launch()
@client.on('logged_on')
def start_dota():
dota.launch()

@dota.on('ready')
def dota_started():
print 'Logged in: %s %s' % (dota.steam.username, dota.account_id)
@dota.on('ready')
def dota_started():
print 'Logged in: %s %s' % (dota.steam.username, dota.account_id)

# if lobby is hung up from previous session, leave it
dota.leave_practice_lobby()
# if lobby is hung up from previous session, leave it
dota.leave_practice_lobby()

if dota == bots[0]:
dota.create_practice_lobby(password='eu', options={
'game_name': 'Inhouse Ladder',
'game_mode': dota2.enums.DOTA_GameMode.DOTA_GAMEMODE_CD,
Expand All @@ -51,117 +74,87 @@ def dota_started():
'pause_setting': 1,
})

@dota.on(dota2.features.Lobby.EVENT_LOBBY_NEW)
def lobby_new(lobby):
if dota != bots[0]:
@dota.on(dota2.features.Lobby.EVENT_LOBBY_NEW)
def lobby_new(lobby):
print '%s joined lobby %s' % (dota.steam.username, lobby.lobby_id)

dota.join_practice_lobby_team() # jump to unassigned players
dota.join_lobby_chat()

# @dota.on(dota2.features.Lobby.EVENT_LOBBY_CHANGED)
# def lobby_changed(lobby):
# if dota == bots[0]:
# print 'Lobby update!'
# print lobby

@dota.on(dota2.features.Chat.EVENT_CHAT_JOINED)
def chat_joined(channel):
print '%s joined chat channel %s' % (dota.steam.username, channel.channel_name)
# print channel

@dota.on(dota2.features.Chat.EVENT_CHAT_MESSAGE)
def chat_message(channel, sender, text, msg_obj):
# process known commands
if text.startswith('!balance'):
self.balance_command(dota)
elif text.startswith('!start'):
dota.send_lobby_message('Start requested')
else:
dota.send_lobby_message('Fuck off, %s!' % sender)

client.login(credentials['login'], credentials['password'])
client.run_forever()

@staticmethod
def balance_command(bot):
print
print 'Balancing players'

# convert steam64 into 32bit dota id and build a dic of {id: player}
players_steam = {
SteamID(player.id).as_32: player for player in bot.lobby.members
if player.team in (DOTA_GC_TEAM.GOOD_GUYS, DOTA_GC_TEAM.BAD_GUYS)
}

if len(players_steam) < 10:
bot.send_lobby_message('We don\'t have 10 players')
return

print 'New lobby!'
# print lobby

dota.join_practice_lobby_team() # jump to unassigned players
dota.join_lobby_chat()

# let's wait for other bots to login
while sum(1 if bot.ready else 0 for bot in bots) < 10:
sleep(1)

for i, bot in enumerate(bots[1:]):
print '%s is joining lobby' % bot.steam.username
bot.join_practice_lobby(lobby.lobby_id, lobby.pass_key)

team = i / 5
slot = i % 5 + 1
bot.join_practice_lobby_team(slot, team)

# @dota.on(dota2.features.Lobby.EVENT_LOBBY_CHANGED)
# def lobby_changed(lobby):
# if dota == bots[0]:
# print 'Lobby update!'
# print lobby

@dota.on(dota2.features.Chat.EVENT_CHAT_JOINED)
def chat_joined(channel):
print 'Joined chat!'
# print channel

@dota.on(dota2.features.Chat.EVENT_CHAT_MESSAGE)
def chat_message(channel, sender, text, msg_obj):
# process known commands
if text.startswith('!balance'):
balance_command(dota)
elif text.startswith('!start'):
dota.send_lobby_message('Start requested')
else:
dota.send_lobby_message('Fuck off, %s!' % sender)

client.login(credentials['login'], credentials['password'])
client.run_forever()


def balance_command(bot):
print
print 'Balancing players'
# get players from DB using dota id
players = Player.objects.filter(dota_id__in=players_steam.keys())
players = {player.dota_id: player for player in players}

# convert steam64 into 32bit dota id and build a dic of {id: player}
players_steam = {
SteamID(player.id).as_32: player for player in bot.lobby.members
if player.team in (DOTA_GC_TEAM.GOOD_GUYS, DOTA_GC_TEAM.BAD_GUYS)
}
unregistered = [players_steam[p].name for p in players_steam.keys() if str(p) not in players]

if len(players_steam) < 10:
bot.send_lobby_message('We don\'t have 10 players')
return

# get players from DB using dota id
players = Player.objects.filter(dota_id__in=players_steam.keys())
players = {player.dota_id: player for player in players}

unregistered = [players_steam[p].name for p in players_steam.keys() if str(p) not in players]

if unregistered:
bot.send_lobby_message('I don\'t know these guys: %s' %
', '.join(unregistered))
return

print players

# TODO: move this to BalancerResultManager
players = [(p.name, p.ladder_mmr) for p in players.values()]

# balance teams and save result
mmr_exponent = 3
answers = balance_teams(players, mmr_exponent)

with transaction.atomic():
result = models.BalanceResult.objects.create(mmr_exponent=mmr_exponent)
for answer in answers:
models.BalanceAnswer.objects.create(
teams=answer['teams'],
mmr_diff=answer['mmr_diff'],
mmr_diff_exp=answer['mmr_diff_exp'],
result=result
)

url = reverse('balancer:balancer-result', args=(result.id,))
url = os.environ.get('BASE_URL', 'localhost:8000') + url

bot.send_lobby_message('Balancer result: %s' % url)


class Command(BaseCommand):
def handle(self, *args, **options):
bots_num = 10

credentials = [
{
'login': '***%d' % i,
'password': '***%d' % i,
} for i in xrange(1, bots_num+1)
]

for c in credentials:
thread.start_new_thread(start_bot, (c,))
if unregistered:
bot.send_lobby_message('I don\'t know these guys: %s' %
', '.join(unregistered))
return

while True:
sleep(0.1)
print players

# TODO: move this to BalancerResultManager
players = [(p.name, p.ladder_mmr) for p in players.values()]

# balance teams and save result
mmr_exponent = 3
answers = balance_teams(players, mmr_exponent)

with transaction.atomic():
result = models.BalanceResult.objects.create(mmr_exponent=mmr_exponent)
for answer in answers:
models.BalanceAnswer.objects.create(
teams=answer['teams'],
mmr_diff=answer['mmr_diff'],
mmr_diff_exp=answer['mmr_diff_exp'],
result=result
)

url = reverse('balancer:balancer-result', args=(result.id,))
url = os.environ.get('BASE_URL', 'localhost:8000') + url

answer = answers[0]
for i, team in enumerate(answer['teams']):
player_names = [p[0] for p in team['players']]
bot.send_lobby_message('Team %d: %s' % (i+1, ' | '.join(player_names)))
bot.send_lobby_message(url)
72 changes: 72 additions & 0 deletions app/balancer/management/commands/dota_test_bots.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from django.core.management.base import BaseCommand
import gevent
import dota2
from steam import SteamClient
from dota2 import Dota2Client


class Command(BaseCommand):
def __init__(self):
self.bots = []
self.lobby = None
self.password = None

def add_arguments(self, parser):
parser.add_argument('-l', '--lobby', type=int)
parser.add_argument('-p', '--password',
nargs='?', type=str, default='eu', const='eu')

def handle(self, *args, **options):
self.lobby = options['lobby']
self.password = options['password']

bots_num = 9

credentials = [
{
'login': 'login%d' % i,
'password': 'password%d' % i,
} for i in xrange(2, bots_num+2)
]

try:
gevent.joinall([
gevent.spawn(self.start_bot, c) for c in credentials
])
except KeyboardInterrupt:
for bot in self.bots:
bot.exit()
bot.steam.logout()

def start_bot(self, credentials):
client = SteamClient()
dota = Dota2Client(client)

self.bots.append(dota)

client.verbose_debug = True
dota.verbose_debug = True

@client.on('logged_on')
def start_dota():
dota.launch()

@dota.on('ready')
def dota_started():
print 'Logged in: %s %s' % (dota.steam.username, dota.account_id)

# if lobby is hung up from previous session, leave it
dota.leave_practice_lobby()
dota.join_practice_lobby(self.lobby, self.password)

@dota.on(dota2.features.Lobby.EVENT_LOBBY_NEW)
def lobby_new(lobby):
print '%s joined lobby %s' % (dota.steam.username, lobby.lobby_id)

ind = self.bots.index(dota)
team = ind / 5
slot = ind % 5 + 1
dota.join_practice_lobby_team(slot, team)

client.login(credentials['login'], credentials['password'])
client.run_forever()

0 comments on commit 0f626e9

Please sign in to comment.