Prepare for refresh
This commit is contained in:
parent
d4d13edc1a
commit
36d26f5004
|
@ -2,3 +2,4 @@ assets/
|
|||
node_modules
|
||||
package.lock
|
||||
*.pyc
|
||||
config.js
|
||||
|
|
2
pytron
2
pytron
|
@ -1 +1 @@
|
|||
Subproject commit b2504f49f9e30e3ffa07ec3ab11d6b465829b593
|
||||
Subproject commit 8d27a9293e2ffbb1119b9c3c453aec76be612a50
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
63
server.js
63
server.js
|
@ -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,
|
||||
|
||||
for (let key in content) {
|
||||
let battlers = key.split('/');
|
||||
let ai1 = battlers[0];
|
||||
let ai2 = battlers[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);
|
||||
}
|
||||
|
||||
for (let key in content.battles) {
|
||||
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];
|
||||
|
||||
let realAi1 = parsed.ais.find((x) => x.name == ai1);
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue