...
 
Commits (17)
......@@ -4,9 +4,12 @@
/conf*.json
/test.py
/problems/*
/problems-gen/*
!/problems/.gitkeep
/solutions/*
/solutions-gen/*
!/solutions/.gitkeep
/sds_trace_data.dat
# Byte-compiled / optimized / DLL files
......
......@@ -13,3 +13,6 @@
[submodule "solvers/nszw"]
path = solvers/nszw
url = git@togawa-gitlab:adc2019/nszw-solver.git
[submodule "adc2019"]
path = adc2019
url = https://github.com/dasadc/adc2019.git
......@@ -2,3 +2,5 @@
.PHONY: clean
clean:
rm -rf ./solutions/*
rm -rf ./solvers/hsgw/P*.txt
rm -rf ./solvers/kwmr/A*.txt
Subproject commit 5535fc645b2138f1641b633fd17e7756bed5600a
......@@ -44,11 +44,17 @@ def webui_part_solver_status():
else:
return abort(404)
@webui.route('/part/request/<problem_name>')
def webui_part_request_status(problem_name=None):
# @webui.route('/part/request/<problem_name>')
@webui.route('/part/problem_status/<problem_name>')
def webui_part_problem_status_list(problem_name=None):
if (adc2019system.role is not None) and (adc2019system.role.type == 'host'):
problem = adc2019system.role.get_problem(problem_name)
solutions = reversed(sorted(problem.get_solutions().items(), key=lambda x:x[1].timestamp))
request_status = adc2019system.role.get_request_by_problem(problem_name)
return render_template('part_request_status.html', status=request_status)
if problem is None:
return abort(404)
else:
return render_template('part_problem_status_list.html', problem=problem, solutions=solutions, status=request_status)
else:
return abort(404)
......@@ -61,11 +67,10 @@ def webui_part_problem_status(name=None):
if (adc2019system.role is not None) and (adc2019system.role.type == 'host'):
problem = adc2019system.role.get_problem(name)
workers = adc2019system.role.get_workers()
solutions = reversed(sorted(problem.get_solutions().items(), key=lambda x:x[1].timestamp))
if problem is None:
return abort(404)
else:
return render_template('part_problem_status.html', problem=problem, workers=workers, solutions=solutions)
return render_template('part_problem_status.html', problem=problem, workers=workers)
else:
return abort(404)
......
This diff is collapsed.
......@@ -37,9 +37,9 @@ class Solver(object):
def __repr__(self):
return "Solver"
def set_status(self, status):
def set_status(self, status, params=dict()):
self.status = status
self.post('worker/status', {'address': self.address, 'status': self.status})
self.post('worker/status', {'address': self.address, 'status': self.status, 'params': params})
def solver_thread(self):
......@@ -48,7 +48,7 @@ class Solver(object):
print("I: Solver started")
_, params = self.queue.popitem(last=False)
self.solving = params
self.set_status(f'Running ({len(self.queue)} in queue)')
self.set_status(f'Running ({len(self.queue)} in queue)', params={'request_id': params['request_id']})
try:
self.solve(params)
except Exception as e:
......@@ -115,7 +115,8 @@ class Solver(object):
data = {
'request_id': params['request_id'],
'problem': params['name'],
'worker': self.address
'worker': self.address,
'merge_solvers': params['merge_solvers']
}
data.update(solution)
self.post('problem/solution', data)
......
Subproject commit 7dd663551ea23c24f9c47b233f3cb533040ecea8
Subproject commit 8bab511f44f1a6cac261e31fe74caecbd16713da
Subproject commit 230bc3fea9889df34866a792fecd981c23cc8972
Subproject commit f1f703eb80c922560f8168e6cb856a11079d4916
Subproject commit 849bed357f03a753050aafbf429ed406bd354195
Subproject commit 7be869e7f22527c8496c6ac96b4801a2a5c5c4c7
Subproject commit efe5a32e55fb0436a22753f8e3e49cf25fb93c23
Subproject commit a1f4bafd374681503b490180a89e24da2341a948
......@@ -41,11 +41,8 @@ class StatusView {
_this.fire('refresh');
});
_this.container.find('.solution-detail-row.valid-solution td').click((e) => {
var solution_id = $(e.target).parent("tr").data("solution-id");
var problem_name = $(e.target).parent("tr").data("problem");
var viewer_url = "/viewer#" + problem_name + "/" + solution_id;
window.open(viewer_url, "_blank");
_this.container.find('.submit-button').click(()=>{
_this.upload_solution();
});
_this.container.find('#chk-solver-all').prop('checked', false);
......@@ -64,7 +61,7 @@ class StatusView {
}).trigger('change');
_this.request_refresh_timer = setInterval((function _t(){
_this.get_request_status();
_this.update_status_view();
return _t;
}()), 1000);
});
......@@ -97,24 +94,6 @@ class StatusView {
contentType: 'application/json'
}).done((d) => {
console.log(d);
// var request_id = d['request_id'];
// var timeout = d['timeout'];
// _this.container.find('#solver-processing-modal').modal({
// backdrop: 'static',
// keyboard: false,
// show: true
// });
// _this.container.find('#solver-processing-modal').on('hidden.bs.modal', function(e){
// clearInterval(_this.request_refresh_timer);
// _this.show_problem();
// _this.fire('refresh');
// })
// _this.container.find('.stop-button').click(()=>{
// _this.stop_solver();
// });
});
}
......@@ -169,16 +148,52 @@ class StatusView {
_this.show_problem();
});
}
// アップロード
upload_solution(){
var _this = this;
$.ajax({
type: "POST",
dataType: "json",
url: "/api/adccli/upload-solution",
data: JSON.stringify({
"problem": _this.problem_key
}),
contentType: 'application/json'
}).done((d) => {
alert(d['status']);
});
}
get_request_status(){
update_status_view(){
var _this = this;
var solvers = new Array();
_this.container.find('#solver-list-table-wrapper .chk-solver:checked').each((i, el) => {
var _val = $(el).val();
solvers.push(_val);
});
console.log(solvers);
$.ajax({
type: 'GET',
dataType: 'html',
url: '/part/request/' + _this.problem_key
url: '/part/problem_status/' + _this.problem_key
}).done((d) => {
_this.container.find('#request-table-container').empty();
_this.container.find('#request-table-container').html(d);
_this.container.find('#problem-status-list-container').empty();
_this.container.find('#problem-status-list-container').html(d);
_this.container.find('.solution-detail-row.valid-solution td').click((e) => {
var solution_id = $(e.target).parent("tr").data("solution-id");
var problem_name = $(e.target).parent("tr").data("problem");
var viewer_url = "/viewer#" + problem_name + "/" + solution_id;
window.open(viewer_url, "_blank");
});
_this.fire('refresh');
});
}
......@@ -194,6 +209,8 @@ class StatusView {
_this.container.empty();
_this.container.html(d);
clearInterval(_this.request_refresh_timer);
var button_action_with_ajax = function($obj, url){
$obj.prop("disabled", "disabled");
$.ajax({
......@@ -202,7 +219,7 @@ class StatusView {
dataType: "json",
}).done((data)=>{
$obj.prop("disabled", false);
alert(data['message']);
alert(data['status']);
});
};
......@@ -234,21 +251,21 @@ class StatusView {
});
$("#adccli-login-button").click(function(){
button_action_with_ajax($(this), "/adccli-login");
button_action_with_ajax($(this), "/api/adccli/login");
});
$("#adccli-logout-button").click(function(){
button_action_with_ajax($(this), "/adccli-logout");
button_action_with_ajax($(this), "/api/adccli/logout");
});
$("#adccli-get-all-q").click(function(){
button_action_with_ajax($(this), "/adccli-get-all-q");
button_action_with_ajax($(this), "/api/adccli/download-problem");
});
$.ajax({
type: "GET",
url: "/adccli-whoami",
url: "/api/adccli/whoami",
dataType: "json",
}).done((data)=>{
if(data['status'])
if(data['is_logged_in'])
$("#adccli-status").text("ログイン中");
else
$("#adccli-status").text("ログアウト");
......
......@@ -47,42 +47,7 @@
</div>
</div>
<div id="request-list-container">
<h4>リクエスト一覧</h4>
<div id="request-table-container">
</div>
</div>
<div id='solution-list-container'>
<h4>処理結果一覧</h4>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Timestamp</th>
<th>Client</th>
<th>Score</th>
</tr>
</thead>
<tbody>
{% for k, v in solutions %}
{% set tr_class = '' %}
{% set tr_class = tr_class + ' submit-solution' if k == problem.best_solution else '' %}
{% set tr_class = tr_class + ' valid-solution' if v.is_valid_solution() else '' %}
<tr class="solution-detail-row {{tr_class}}" data-solution-id="{{k}}" data-problem="{{problem.name}}">
<td>{{v.timestamp_str}}</td>
<td>{{v.worker}}</td>
<td>
{% if v.is_valid_solution() %}
{{v.score}} ({{v.size_str}})
{% else %}
{{v.status}}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div id="problem-status-list-container">
</div>
</div>
<div id="request-list-container">
<h4>リクエスト一覧</h4>
<div id="request-table-container">
<table class="table table-bordered table-sm">
<tbody>
{% for r in status %}
<tr>
<td>{{r['worker']}}</td>
<td>{{r['status']}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div id='solution-list-container'>
<h4>処理結果一覧</h4>
<div id="solution-table-container">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Timestamp</th>
<th>Client</th>
<th>Score</th>
</tr>
</thead>
<tbody>
{% for k, v in solutions %}
{% set tr_class = '' %}
{% set tr_class = tr_class + ' submit-solution' if k == problem.best_solution else '' %}
{% set tr_class = tr_class + ' valid-solution' if v.is_valid_solution() else '' %}
<tr class="solution-detail-row {{tr_class}}" data-solution-id="{{k}}" data-problem="{{problem.name}}">
<td>{{v.timestamp_str}} ({{v.request_id}})</td>
<td>{{v.worker}}</td>
<td>
{% if v.is_valid_solution() %}
{{v.score}} ({{v.size_str}})
{% else %}
{{v.status}}
{% endif %}
{{v.nlcheck}}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div>
<table class="table table-bordered table-sm">
<tbody>
{% for r in status %}
<tr>
<td>{{r['worker']}}</td>
<td>{{r['status']}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Timestamp</th>
<th>Client</th>
<th>Score</th>
</tr>
</thead>
<tbody>
{% for k, v in solutions %}
{% set tr_class = '' %}
{% set tr_class = tr_class + ' submit-solution' if k == problem.best_solution else '' %}
{% set tr_class = tr_class + ' valid-solution' if v.is_valid_solution() else '' %}
<tr class="solution-detail-row {{tr_class}}" data-solution-id="{{k}}" data-problem="{{problem.name}}">
<td>{{v.timestamp_str}}</td>
<td>{{v.worker}}</td>
<td>
{% if v.is_valid_solution() %}
{{v.score}} ({{v.size_str}})
{% else %}
{{v.status}}
{% endif %}
{{v.nlcheck}}
</td>
</tr>
{% endfor %}
</tbody>
</table>
#!/usr/bin/env python3
import os
import subprocess
PYTHON2 = "/usr/bin/python"
ADCCLI = "/home/pi/adc2018/conmgr/client/adccli"
PYTHON_BIN = "python3"
BASEDIR = os.path.abspath(os.path.dirname(__file__))
ADCCLI = f"{BASEDIR}/../adc2019/client/adccli"
def _exec_adccli(cmd):
exec_cmd = "{} {} {}".format(PYTHON2, ADCCLI, cmd).strip()
exec_cmd = f"{PYTHON_BIN} {ADCCLI} {cmd}".strip()
print("ADCCLI: {}".format(exec_cmd))
p = subprocess.run(exec_cmd, stdout=subprocess.PIPE, shell=True)
res = p.stdout.decode().strip()
......@@ -14,7 +14,7 @@ def _exec_adccli(cmd):
return res
def login(url, username, password):
cmd = "--URL='{}' --username='{}' --password='{}' login".format(url, username, password)
cmd = f"--URL='{url}' --username='{username}' --password='{password}' login"
return _exec_adccli(cmd)
def logout():
......@@ -26,7 +26,7 @@ def whoami():
return _exec_adccli(cmd)
def put_message(message):
cmd = "put-user-alive '{}'"
cmd = "put-user-alile '{}'"
return _exec_adccli(cmd)
def post_user_q(qnum, filepath):
......@@ -35,15 +35,16 @@ def post_user_q(qnum, filepath):
def get_q_all(outpath):
cmd = "get-q"
question_list = _exec_adccli(cmd).split("\n")
question_list = _exec_adccli(cmd).splitlines()
print("--- ADCCLI questions ---")
print(question_list)
for v in question_list:
if v.startswith("Q"):
qnumber = int(v.replace("Q", ""))
out_file_path = "{}/NL_Q{:02d}.txt".format(outpath, qnumber)
for l in question_list:
if l.startswith("Q"):
v = l.split()
qnumber = int(v[0].replace("Q", ""))
out_file_path = "{}/Q{:02d}.txt".format(outpath, qnumber)
cmd = "--output {} get-q {}".format(out_file_path, qnumber)
r = _exec_adccli(cmd)
......
......@@ -5,6 +5,7 @@ import math
import os
import queue
import re
import subprocess
import time
import uuid
......@@ -31,7 +32,7 @@ class Problem(object):
self._load_problem(problem_path)
if not self.solution_path is None:
solution_files = glob.glob(f'{self.solution_path}/{self.name}/*.json')
solution_files = glob.glob(f'{self.solution_path}/{self.name}/tmp-*.json')
for v in solution_files:
solution = Solution(solution_file=v)
solution_id = solution.get_id()
......@@ -353,17 +354,43 @@ class Problem(object):
print(f'I: Put a solution: {solution_id}')
self.solutions[solution_id] = solution
if solution.status == 'done':
outdir = f"{self.solution_path}/{self.name}"
if not os.path.exists(outdir):
os.mkdir(outdir)
problem_path = self.path
solution_path = f'{outdir}/tmp-{solution.request_id}-{solution.worker}.txt'
with open(solution_path, 'w') as fp:
fp.write(solution.solution)
BASEDIR = os.path.abspath(os.path.dirname(__file__))
NLCHECK = f"{BASEDIR}/../adc2019/server/adc2019.py"
exec_cmd = f"python3 {NLCHECK} --Q-file {problem_path} --A-file {solution_path}".strip()
print("ADCCLI: {}".format(exec_cmd))
p = subprocess.run(exec_cmd, stdout=subprocess.PIPE, shell=True)
try:
res = float(p.stdout.decode().strip())
except:
res = -1
solution.nlcheck = res
# Save solution
solution.save(self.solution_path)
def put_partial_solution(self, data):
idx = int(data['part_id'])
self.partial_solutions[idx].append(data)
print([len(v)>0 for v in self.partial_solutions])
outdir = f"{self.solution_path}/{self.name}"
if not os.path.exists(outdir):
os.mkdir(outdir)
outpath = f"{outdir}/part-{data['request_id']}-{data['worker']}-p{data['part_id']}.json".replace(":", ".")
with open(outpath, 'w') as fp:
json.dump(self.get_dict(), fp, indent=4)
if all([len(v)>0 for v in self.partial_solutions]):
# for v in self.partial_solutions:
# print(v[0])
return True
else:
return False
......@@ -418,6 +445,11 @@ class Solution(object):
self.elapsed_time = data['elapsed_time']
self.solution = data['solution']
self.status = data['status']
if 'nlcheck' in data:
self.nlcheck = data['nlcheck']
else:
self.nlcheck = -1
self.size = (None, None)
self.map = None
......@@ -495,6 +527,10 @@ class Solution(object):
else:
return '-'
@property
def nlcheck_str(self):
return f'{self.nlcheck:.4f}'
def is_valid_solution(self):
return self.status == 'done'
......@@ -510,7 +546,8 @@ class Solution(object):
'elapsed_time': self.elapsed_time,
'problem': self.problem,
'solution': self.solution,
'status': self.status
'status': self.status,
'nlcheck': self.nlcheck
}
def get_d3json(self):
......@@ -534,7 +571,7 @@ class Solution(object):
outdir = f"{basedir}/{self.problem}"
if not os.path.exists(outdir):
os.mkdir(outdir)
outpath = f"{outdir}/{self.request_id}-{self.worker}.json".replace(":", ".")
outpath = f"{outdir}/tmp-{self.request_id}-{self.worker}.json".replace(":", ".")
with open(outpath, 'w') as fp:
json.dump(self.get_dict(), fp, indent=4)
......