Prepare for refresh

This commit is contained in:
Thomas Forgione 2019-03-28 10:56:22 +01:00
parent d4d13edc1a
commit 36d26f5004
No known key found for this signature in database
GPG Key ID: 203DAEA747F48F41
7 changed files with 203 additions and 89 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ assets/
node_modules
package.lock
*.pyc
config.js

2
pytron

@ -1 +1 @@
Subproject commit b2504f49f9e30e3ffa07ec3ab11d6b465829b593
Subproject commit 8d27a9293e2ffbb1119b9c3c453aec76be612a50

View File

@ -1,4 +1,34 @@
from os.path import dirname, basename, isfile
import glob
modules = glob.glob(dirname(__file__)+"/*/ai.py")
__all__ = ['.'.join(f.split('.')[:-1]) for f in modules if isfile(f)]
from os.path import dirname, basename, isfile, getmtime
from importlib import import_module
from glob import glob
modules = glob(dirname(__file__)+"/*/ai.py")
__all__ = []
class UploadedAi:
def __init__(self, name, module, constructor, date):
self.name = name
self.module = module
self.constructor = constructor
self.date = date
for path in [f for f in modules if isfile(f)]:
# Remove the .py
toto = '.'.join(path.split('.')[:-1])
# Compute the name
name = toto.split('/')[-2]
# Find the module
module = import_module('.'.join(toto.split('/')[-3:]))
# Find the constructor
constructor = getattr(module, 'Ai')
# Moment when the file was last modified
date = getmtime(path)
# Append to the list of uploaded ais
__all__.append(UploadedAi(name, module, constructor, date))
__all__ = sorted(__all__, key = lambda ai: ai.name)

77
pytron_run/refresh.py Executable file
View File

@ -0,0 +1,77 @@
#!/usr/bin/env python3
import os
import pathlib
import sys
import json
sys.path.append('../pytron')
from tron.map import Map
from tron.game import Game, PositionPlayer
from tron.player import Direction, ConstantPlayer
import ai_manager
from utils import run_battle
ASSETS_PATH = "assets/data.json"
LAST_REFRESH_PATH = "assets/refresh.dat"
width = 10
height = 10
def main():
print('Welcome to pytron refresh!')
sys.stdout.flush()
# Read the last moment when this script was run
last_refresh = os.path.getmtime(LAST_REFRESH_PATH)
# Set last update time
pathlib.Path(LAST_REFRESH_PATH).touch()
# Find the ais that need to be refreshed
ais_to_refresh = [ai for ai in ai_manager.__all__ if ai.date > last_refresh]
print('New ais: ', list(map(lambda x: x.name, ais_to_refresh)))
print('Ais: ', list(map(lambda x: x.name, ai_manager.__all__)))
# Read current state
with open(ASSETS_PATH, 'r') as file:
dictionnary = json.loads(file.read())
# Dictionnary to record battles that already occured
battles_done = {}
for ai1 in ais_to_refresh:
for ai2 in ai_manager.__all__:
if ai1.name == ai2.name:
continue
# Sort ais by name just to be sure
if ai1.name > ai2.name:
(sai2, sai1) = (ai1, ai2)
else:
(sai1, sai2) = (ai1, ai2)
slash_name = sai1.name + "/" + sai2.name
# Record battle to be done, skip if already done
if battles_done.get(slash_name, None) is None:
battles_done[slash_name] = True
else:
continue
print("Battling {} vs {}".format(sai1.name, sai2.name))
sys.stdout.flush()
(score1, score2, nulls) = run_battle(sai1, sai2, width, height)
dictionnary[slash_name] = [score1, score2, nulls]
with open(ASSETS_PATH, "w") as f:
f.write(json.dumps(dictionnary))
print('Pytron run has finished')
if __name__ == '__main__':
main()

View File

@ -2,82 +2,43 @@
import sys
import json
import pathlib
sys.path.append('../pytron')
from tron.map import Map
from tron.game import Game, PositionPlayer
from tron.player import Direction, ConstantPlayer
from importlib import import_module
import positions
import ai_manager
from utils import run_battle
# Find all the AIs
class AiClass:
def __init__(self, name, builder):
self.name = name
self.builder = builder
ais = []
for real_ai in ai_manager.__all__:
ai_name = real_ai.split('/')[-2]
ai_module = import_module('.'.join(real_ai.split('/')[-3:]))
ai_class = getattr(ai_module, "Ai")
ais.append(AiClass(ai_name, ai_class))
# This script shows how to create a game with AI, that will run automatically.
# It is made to be fast and not to be used by humans. It especially doesn't
# display and window and doesn't listen to any keystrokes.
ASSETS_PATH = "assets/data.json"
LAST_REFRESH_PATH = "assets/refresh.dat"
width = 10
height = 10
def run_battle(ai1, ai2):
games = 50
ai1_victories = 0
ai2_victories = 0
for (initial_position_one, initial_position_two) in positions.positions():
game = Game(width, height, [
PositionPlayer(1, ai1.builder(), initial_position_one),
PositionPlayer(2, ai2.builder(), initial_position_two),
])
game.main_loop()
if game.winner == 1:
ai1_victories += 1
elif game.winner == 2:
ai2_victories += 1
# Inverse positions and replay to be symmetrical
game = Game(width, height, [
PositionPlayer(1, ai2.builder(), initial_position_one),
PositionPlayer(2, ai1.builder(), initial_position_two),
])
game.main_loop()
if game.winner == 1:
ai2_victories += 1
elif game.winner == 2:
ai1_victories += 1
return (ai1_victories, ai2_victories, 2 * games - ai1_victories - ai2_victories)
def main():
print('Welcome to pytron run!')
dictionnary = {"ais": list(map(lambda x: x.name, ais)), "battles": {}}
dictionnary = {}
for (id1, ai1) in enumerate(ais):
for (id2, ai2) in enumerate(ais):
# Set last update time
pathlib.Path(LAST_REFRESH_PATH).touch()
for (id1, ai1) in enumerate(ai_manager.__all__):
for (id2, ai2) in enumerate(ai_manager.__all__):
if id1 >= id2:
continue
print("Battling {} vs {}".format(ai1.name, ai2.name))
(score1, score2, nulls) = run_battle(ai1, ai2)
dictionnary["battles"][ai1.name + "/" + ai2.name] = [score1, score2, nulls]
# Sort ais by name just to be sure
if ai1.name > ai2.name:
(sai2, sai1) = (ai1, ai2)
else:
(sai1, sai2) = (ai1, ai2)
print("Battling {} vs {}".format(sai1.name, sai2.name))
(score1, score2, nulls) = run_battle(sai1, sai2, width, height)
dictionnary[sai1.name + "/" + sai2.name] = [score1, score2, nulls]
with open("assets/data.json", "w") as f:
f.write(json.dumps(dictionnary))

34
pytron_run/utils.py Normal file
View File

@ -0,0 +1,34 @@
from positions import positions
from tron.game import Game, PositionPlayer
def run_battle(ai1, ai2, width, height):
games = 50
ai1_victories = 0
ai2_victories = 0
for (initial_position_one, initial_position_two) in positions():
game = Game(width, height, [
PositionPlayer(1, ai1.constructor(), initial_position_one),
PositionPlayer(2, ai2.constructor(), initial_position_two),
])
game.main_loop()
if game.winner == 1:
ai1_victories += 1
elif game.winner == 2:
ai2_victories += 1
# Inverse positions and replay to be symmetrical
game = Game(width, height, [
PositionPlayer(1, ai2.constructor(), initial_position_one),
PositionPlayer(2, ai1.constructor(), initial_position_two),
])
game.main_loop()
if game.winner == 1:
ai2_victories += 1
elif game.winner == 2:
ai1_victories += 1
return (ai1_victories, ai2_victories, 2 * games - ai1_victories - ai2_victories)

View File

@ -9,13 +9,7 @@ const pug = require('pug');
const unzip = require('unzip');
const touch = require('touch');
const bcrypt = require('bcryptjs');
// Consts
const port = 8000;
const pythonPath = '/home/pytron/miniconda3/envs/pytron/bin/python'
const aisPath = 'pytron_run/ai_manager/'
const aisPathOld = 'pytron_run/ai_manager_old'
const hashPath = "__bcrypt__hash.txt"
const { port, pythonPath, aisPath, aisPathOld, hashPath } = require('./config');
// Create the directories to store the files
try { fs.mkdirSync(aisPath); } catch { }
@ -34,7 +28,7 @@ function runPython() {
}
process.stdout.write('\n');
let p = spawn(pythonPath, ['run.py'], {cwd: 'pytron_run'});
let p = spawn(pythonPath, ['refresh.py'], {cwd: 'pytron_run'});
p.stdout.on('data', (data) => {
let content = data.toString().split('\n');
for (let line of content) {
@ -62,35 +56,52 @@ function runPython() {
}
});
}
// parsed.ais.push({
// });
function parse(data) {
let content = JSON.parse(data);
let parsed = {ais: [], battles: {}};
for (let ai of content.ais) {
parsed.ais.push({
name: ai,
victories: 0,
defeats: 0,
nulls: 0,
score: 0,
});
}
for (let key in content.battles) {
for (let key in content) {
let battlers = key.split('/');
let ai1 = battlers[0];
let ai2 = battlers[1];
parsed.battles[ai1 + '/' + ai2] = content.battles[key][0];
parsed.battles[ai2 + '/' + ai1] = content.battles[key][1];
parsed.battles[ai1 + '/' + ai2] = content[key][0];
parsed.battles[ai2 + '/' + ai1] = content[key][1];
let realAi1 = parsed.ais.find((x) => x.name == ai1);
if (realAi1 === undefined) {
realAi1 = {
name: ai1,
victories: 0,
defeats: 0,
nulls: 0,
score: 0,
};
parsed.ais.push(realAi1);
}
let realAi2 = parsed.ais.find((x) => x.name == ai2);
realAi1.victories += content.battles[key][0];
realAi1.defeats += content.battles[key][1];
realAi2.victories += content.battles[key][1];
realAi2.defeats += content.battles[key][0];
realAi1.nulls += content.battles[key][2];
realAi2.nulls += content.battles[key][2];
if (realAi2 === undefined) {
realAi2 = {
name: ai2,
victories: 0,
defeats: 0,
nulls: 0,
score: 0,
};
parsed.ais.push(realAi2);
}
realAi1.victories += content[key][0];
realAi1.defeats += content[key][1];
realAi2.victories += content[key][1];
realAi2.defeats += content[key][0];
realAi1.nulls += content[key][2];
realAi2.nulls += content[key][2];
}
parsed.sortedAis = parsed.ais.slice(0);