Prepare for refresh
This commit is contained in:
parent
d4d13edc1a
commit
36d26f5004
|
@ -2,3 +2,4 @@ assets/
|
||||||
node_modules
|
node_modules
|
||||||
package.lock
|
package.lock
|
||||||
*.pyc
|
*.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
|
from os.path import dirname, basename, isfile, getmtime
|
||||||
import glob
|
from importlib import import_module
|
||||||
modules = glob.glob(dirname(__file__)+"/*/ai.py")
|
from glob import glob
|
||||||
__all__ = ['.'.join(f.split('.')[:-1]) for f in modules if isfile(f)]
|
|
||||||
|
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 sys
|
||||||
import json
|
import json
|
||||||
|
import pathlib
|
||||||
sys.path.append('../pytron')
|
sys.path.append('../pytron')
|
||||||
|
|
||||||
from tron.map import Map
|
from tron.map import Map
|
||||||
from tron.game import Game, PositionPlayer
|
from tron.game import Game, PositionPlayer
|
||||||
from tron.player import Direction, ConstantPlayer
|
from tron.player import Direction, ConstantPlayer
|
||||||
|
|
||||||
from importlib import import_module
|
|
||||||
|
|
||||||
import positions
|
|
||||||
import ai_manager
|
import ai_manager
|
||||||
|
from utils import run_battle
|
||||||
|
|
||||||
# Find all the AIs
|
ASSETS_PATH = "assets/data.json"
|
||||||
class AiClass:
|
LAST_REFRESH_PATH = "assets/refresh.dat"
|
||||||
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.
|
|
||||||
|
|
||||||
width = 10
|
width = 10
|
||||||
height = 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():
|
def main():
|
||||||
|
|
||||||
print('Welcome to pytron run!')
|
print('Welcome to pytron run!')
|
||||||
dictionnary = {"ais": list(map(lambda x: x.name, ais)), "battles": {}}
|
dictionnary = {}
|
||||||
|
|
||||||
for (id1, ai1) in enumerate(ais):
|
# Set last update time
|
||||||
for (id2, ai2) in enumerate(ais):
|
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:
|
if id1 >= id2:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print("Battling {} vs {}".format(ai1.name, ai2.name))
|
# Sort ais by name just to be sure
|
||||||
(score1, score2, nulls) = run_battle(ai1, ai2)
|
if ai1.name > ai2.name:
|
||||||
dictionnary["battles"][ai1.name + "/" + ai2.name] = [score1, score2, nulls]
|
(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:
|
with open("assets/data.json", "w") as f:
|
||||||
f.write(json.dumps(dictionnary))
|
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 unzip = require('unzip');
|
||||||
const touch = require('touch');
|
const touch = require('touch');
|
||||||
const bcrypt = require('bcryptjs');
|
const bcrypt = require('bcryptjs');
|
||||||
|
const { port, pythonPath, aisPath, aisPathOld, hashPath } = require('./config');
|
||||||
// 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"
|
|
||||||
|
|
||||||
// Create the directories to store the files
|
// Create the directories to store the files
|
||||||
try { fs.mkdirSync(aisPath); } catch { }
|
try { fs.mkdirSync(aisPath); } catch { }
|
||||||
|
@ -34,7 +28,7 @@ function runPython() {
|
||||||
}
|
}
|
||||||
process.stdout.write('\n');
|
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) => {
|
p.stdout.on('data', (data) => {
|
||||||
let content = data.toString().split('\n');
|
let content = data.toString().split('\n');
|
||||||
for (let line of content) {
|
for (let line of content) {
|
||||||
|
@ -62,35 +56,52 @@ function runPython() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// parsed.ais.push({
|
||||||
|
|
||||||
|
// });
|
||||||
function parse(data) {
|
function parse(data) {
|
||||||
let content = JSON.parse(data);
|
let content = JSON.parse(data);
|
||||||
let parsed = {ais: [], battles: {}};
|
let parsed = {ais: [], battles: {}};
|
||||||
for (let ai of content.ais) {
|
|
||||||
parsed.ais.push({
|
for (let key in content) {
|
||||||
name: ai,
|
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,
|
victories: 0,
|
||||||
defeats: 0,
|
defeats: 0,
|
||||||
nulls: 0,
|
nulls: 0,
|
||||||
score: 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);
|
let realAi2 = parsed.ais.find((x) => x.name == ai2);
|
||||||
realAi1.victories += content.battles[key][0];
|
|
||||||
realAi1.defeats += content.battles[key][1];
|
if (realAi2 === undefined) {
|
||||||
realAi2.victories += content.battles[key][1];
|
realAi2 = {
|
||||||
realAi2.defeats += content.battles[key][0];
|
name: ai2,
|
||||||
realAi1.nulls += content.battles[key][2];
|
victories: 0,
|
||||||
realAi2.nulls += content.battles[key][2];
|
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);
|
parsed.sortedAis = parsed.ais.slice(0);
|
||||||
|
|
Loading…
Reference in New Issue