Commit ca2e8c1b authored by Kento HASEGAWA's avatar Kento HASEGAWA

Merge branch 'comm' into 'master'

Add support for resolver and improve UI

See merge request adc2018/adc2018-system!9
parents 4cffa912 5e4c621e
......@@ -3,6 +3,8 @@
.DS_Store
*.txt
*.tmp
*.json
# Object files
*.o
......@@ -17,3 +19,7 @@ solver
# Python files
*.pyc
__pycache__/
# client-icons
client-icon/
......@@ -21,7 +21,6 @@ import adc2018solver as pynqrouter
app = Flask(__name__)
args = {}
# pynq_thread = None
client_baseurl = ""
@app.route('/start', methods=["POST"])
......@@ -45,10 +44,15 @@ def start():
qseed = request.form["qseed"]
boardstr = BoardStr.conv_boardstr(qstr.split('\n'), 'random', int(qseed))
option = {"name": qname, "host": args['host'], "client": client_baseurl}
option = {
"name": qname,
"host": args['host'],
"client": client_baseurl,
"req_id": request.form['req_id'],
"resolver": request.form['resolver']
}
pynqrouter.start_solver(boardstr, qseed, option)
# pynq_thread = pynqrouter.start_solver(boardstr, qseed, option)
# 実行だけ開始する
ans["status"] = "Processing"
......@@ -64,8 +68,6 @@ def start():
@app.route('/stop')
def stop():
# global pynq_thread
if pynqrouter.solver_thread is None:
ans = {"status": "No threads"}
else:
......@@ -73,15 +75,11 @@ def stop():
pynqrouter.stop_solver()
ans = {"status": "Stopped"}
# pynq_thread = None
return json.dumps(ans)
@app.route("/status")
def status():
# global pynq_thread
res_mes = ""
if pynqrouter.solver_thread is None:
......@@ -121,3 +119,4 @@ if __name__ == "__main__":
if args["debug"]:
app.debug = True
app.run(host='0.0.0.0', port=args["port"], threaded=True)
DAS2018 ADC クライアント(リゾルバ)プログラム
===
DAS2018 アルゴリズムデザインコンテスト用クライアントプログラム
## Description
解答データをソルバから受信し,整形した結果をサーバへ返すプログラム.
## Requirements
- Python 3.5以上(くらい)
- Flask
## Usage
```
python3 main.py [--port XXXX] [--host XXXX]
```
### Options
<dl>
<dt>-H, --host</dt>
<dd>サーバホストのアドレス (デフォルト:192.168.5.1:5000)</dd>
<dt>-p, --port</dt>
<dd>使用するポート (デフォルト:5000)</dd>
</dl>
#!/usr/bin/env python3
"""
This script provides a PYNQ client.
This is intended to run on the client server (PYNQ).
"""
import argparse
import json
import os
import platform
import queue
import requests
import subprocess
import sys
import threading
import time
from flask import Flask, render_template, request, g
from urllib.parse import urlparse
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../solver')
import BoardStr
# import adc2018solver as pynqrouter
app = Flask(__name__)
args = {}
client_baseurl = ""
resolve_queue = None
def resolve():
"""
queueを受け取りそこに入ってきた答えを整形し,ホストに送信します.
"""
global args
global client_baseurl
global resolve_queue
while True:
if resolve_queue is None:
time.sleep(1)
continue
else:
data = resolve_queue.get()
if args['verbose']:
print("Processing queued data...")
print(data)
outpath = "./works/resolved.txt"
probpath = "./problems/{}".format(data['qname'])
tmppath = "./works/answer.txt"
with open(tmppath, "w") as fp:
fp.write(data['answer'])
# Resolver
cmd = "/home/pi/adc2017/pynq-router/resolver/solver --reroute --output {} {} {}".format(outpath, probpath, tmppath)
subprocess.call(cmd.strip().split(" "))
resolved = ""
with open(outpath, "r") as fp:
resolved = fp.read()
res = {
'answer': resolved,
'solved': True,
'solver': data['client'],
'resolver': client_baseurl,
'client': client_baseurl,
'cputime': data['cputime'],
'qname': data['qname'],
'req_id': data['req_id']
}
# 結果をホストに返す
r = requests.post("http://{}/post".format(args['host']), data=res)
if args['verbose']:
print("Done.")
print(res)
@app.route('/post', methods=["POST"])
def start():
# global pynq_thread
global args
global client_baseurl
global resolve_queue
if args["verbose"]:
print(request.form)
data = {
'client': request.form['client'],
'qname': request.form['qname'],
'answer': request.form['solution'],
'cputime': request.form['cputime'],
'req_id': request.form['req_id']
}
resolve_queue.put(data)
ans = {"status": "Queued"}
if args["verbose"]:
print(ans)
return json.dumps(ans)
@app.route('/stop')
def stop():
global resolve_queue
if resolve_queue.empty() is None:
ans = {"status": "Nothing queued"}
else:
# pynq_thread.stop()
while not resolve_queue.empty():
resolve_queue.get()
ans = {"status": "Stopped"}
return json.dumps(ans)
@app.route("/status")
def status():
res_mes = ""
if resolve_queue.empty():
res_mes = "Ready"
else:
res_mes = "Working"
res = {"status": res_mes}
return json.dumps(res)
@app.route("/")
def index():
return platform.node()
@app.before_request
def before_request():
global client_baseurl
_url = request.url
parse = urlparse(_url)
client_baseurl = parse.netloc
if __name__ == "__main__":
# Check if this script runs as "root" user
# if os.getuid() != 0:
# raise Exception("Must run as root")
# sys.exit(1)
parser = argparse.ArgumentParser(description="PYNQ client (for resolver).")
parser.add_argument("-p", "--port", action="store", type=int, default=5000, help="Port")
parser.add_argument("-H", "--host", action="store", type=str, default="192.168.5.1:5000", help="Host address")
parser.add_argument("--debug", action="store_true", default=False, help="Debug mode.")
parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Verbose.")
args = vars(parser.parse_args())
# Start resolver thread
resolve_queue = queue.Queue()
th = threading.Thread(target=resolve, args=())
th.setDaemon(True)
th.start()
if args["debug"]:
app.debug = True
app.run(host='0.0.0.0', port=args["port"], threaded=True)
DAS2017 ADC サーバプログラム
DAS218 ADC サーバプログラム
===
DAS2017 アルゴリズムデザインコンテスト用サーバプログラム
DAS2018 アルゴリズムデザインコンテスト用サーバプログラム
## Description
......@@ -32,12 +32,6 @@ python3 main.py [--question XXXX] [--port XXXX] [--clients XXXX]
<dt>-p, --port</dt>
<dd>サーバのポート (デフォルト:5000)</dd>
<dt>-l, --line-num-th</dt>
<dd>処理を分岐させるライン数の閾値</dd>
<dt>-t, --timeout</dt>
<dd>PYNQで処理させるタイムアウト(秒)</dd>
</dl>
## Comments
......
......@@ -5,6 +5,7 @@ This is intended to run on the host server (Raspberry Pi).
"""
import argparse
import datetime
import glob
import json
import os
......@@ -27,79 +28,143 @@ questions = None
clients = None
current_seed = 1
@app.before_request
def before_request():
def load_questions():
global app_args
global questions
global clients
if questions is None:
question_path = os.path.abspath(app_args["question"])
question_list = glob.glob("{}/NL_*.txt".format(question_path))
question_list.sort()
question_path = os.path.abspath(app_args["question"])
question_list = glob.glob("{}/NL_*.txt".format(question_path))
question_list.sort()
questions = OrderedDict()
for v in question_list:
# 問題の情報を読み込む
with open(v, "r") as fp:
_q_lines = fp.readlines()
board_size = ""
line_num = -1
for l in _q_lines:
if "SIZE" in l:
board_size = l.strip().split()[1]
if "LINE_NUM" in l:
line_num = int(l.strip().split()[1])
break
_name = os.path.basename(v)
questions[_name] = {
"path": v,
"status": "Not solved",
"answer": "",
"queue": Queue(),
"board_size": board_size,
"line_num": line_num,
"last_req": None,
"answers": [],
}
update_answer_list(_name)
# 既に回答されているものを読み込む
answer_path = os.path.abspath(app_args["out"])
answer_list = glob.glob("{}/T03_A*.txt".format(answer_path))
for v in answer_list:
_ans_name = os.path.basename(v)
m = re.search(r"T03_A([0-9A-Za-z]+)\.txt", _ans_name)
if m:
_name = "NL_Q{}.txt".format(m.group(1))
with open(v, "r") as fp:
_ans_dat = fp.read()
try:
questions[_name]["status"] = "Solved"
questions[_name]["answer"] = _ans_dat
except KeyError as e:
pass
questions = OrderedDict()
def update_answer_list(qname):
for v in question_list:
# 問題の情報を読み込む
with open(v, "r") as fp:
_q_lines = fp.readlines()
board_size = ""
line_num = -1
for l in _q_lines:
if "SIZE" in l:
board_size = l.strip().split()[1]
if "LINE_NUM" in l:
line_num = int(l.strip().split()[1])
break
_name = os.path.basename(v)
questions[_name] = {
"path": v,
"status": "Not solved",
"answer": {},
"queue": Queue(),
"board_size": board_size,
"line_num": line_num
}
# 既に回答されているものを読み込む
answer_path = os.path.abspath(app_args["out"])
answer_list = glob.glob("{}/T03_A*.txt".format(answer_path))
for v in answer_list:
_ans_name = os.path.basename(v)
m = re.search(r"T03_A([0-9A-Za-z]+)\.txt", _ans_name)
if m:
_name = "NL_Q{}.txt".format(m.group(1))
with open(v, "r") as fp:
_ans_dat = fp.read()
try:
questions[_name]["status"] = "Solved"
questions[_name]["answer"] = _ans_dat
except KeyError as e:
pass
global app_args
global questions
if clients is None:
questions[qname]['answers'] = []
with open(app_args["client"], "r") as fp:
_clients = fp.readlines()
_folder_name = os.path.splitext(qname)[0]
_answers_path = "{}/{}".format(app_args['out'], _folder_name)
if os.path.isdir(_answers_path):
answer_log_file = glob.glob("{}/*.json".format(_answers_path))
answer_log_file.sort()
answer_log_file.reverse()
for v2 in answer_log_file:
with open(v2, "r") as fp:
answer_log = json.load(fp)
questions[qname]['answers'].append(answer_log)
@app.before_request
def before_request():
global app_args
clients = [v.rstrip() for v in _clients]
g.local_mode = (request.remote_addr == "127.0.0.1")
@app.route("/post", methods=["POST"])
def post():
global questions
global app_args
_client = request.form["client"]
_qname = request.form["qname"]
_answer = request.form["answer"]
_cputime = request.form["cputime"]
_client = request.form["client"]
if "solver" in request.form:
_solver = request.form["solver"]
else:
_solver = _client
receive_time = datetime.datetime.now()
receive_time_str = receive_time.strftime("%Y%m%d%H%M%S")
dat = {
"req_id": request.form['req_id'],
"client": _client,
"solver": _solver,
"answer": _answer,
"cputime": request.form['cputime'],
"timestamp": receive_time.strftime("%Y/%m/%d %H:%M:%S")
}
# Create a temporary file to execute "nlcheck.py"
tmp_path = "{}/{}".format(app_args['out'], "tmp")
if not os.path.isdir(tmp_path):
os.makedirs(tmp_path)
tmp_file_name = "{}-{}.tmp".format(receive_time_str, _client.replace(":", "."))
tmp_file_path = "{}/{}".format(tmp_path, tmp_file_name)
with open(tmp_file_path, "w") as fp:
fp.write(_answer)
probpath = "{}/{}".format(app_args["question"], _qname)
# Format check
cmd = "/usr/bin/python /home/pi/adc2018/conmgr/adc2018/server/nlcheck.py --input {} --target {}".format(probpath, tmp_file_path)
print("`{}`".format(cmd))
p = subprocess.run(cmd.strip().split(" "), stdout=subprocess.PIPE)
nlcheck = p.stdout.decode().strip()
pattern = r"judge += +\[(.+?), ([0-9.]+)\]"
m = re.match(pattern, nlcheck)
if m and (m.group(1) == "True"):
dat["nlcheck"] = float(m.group(2))
else:
dat["nlcheck"] = -1
dat = {"client": _client, "answer": _answer, "cputime": _cputime}
save_path = "{}/{}".format(app_args['out'], os.path.splitext(_qname)[0])
if not os.path.isdir(save_path):
os.makedirs(save_path)
questions[_qname]["queue"].put(dat)
file_name = "{}-{}.json".format(receive_time_str, _client.replace(":", "."))
save_file_path = "{}/{}".format(save_path, file_name)
with open(save_file_path, "w") as fp:
json.dump(dat, fp, indent=4)
res = {"status": "OK"}
......@@ -129,121 +194,77 @@ def start():
qstr = "\n".join(_q_lines)
qnumber = _question_name.replace(".txt", "").replace("NL_Q", "")
probpath = "{}/{}".format(app_args["question"], _question_name)
tmppath = "{}/T03_A{}_tmp.txt".format(app_args["out"], qnumber)
infopath = "{}/T03_A{}_info.txt".format(app_args["out"], qnumber)
outpath = "{}/T03_A{}.txt".format(app_args["out"], qnumber)
res = {}
if line_num >= 0:
if line_num < app_args["line_num_th"]:
# LINE_NUMが閾値未満のとき,PYNQに問題を配信して問題を解かせる
res = solve_questions(_question_name, qstr)
# 一旦回答をテンポラリファイルに保存
with open(tmppath, "w") as fp:
fp.write(res["answer"]["answer"])
else:
# LINE_NUMが閾値以上のとき,PYNQでは解けないのでRaspberry Piに解かせる
# 文字数多くなるとコマンドラインで載りきらないからパイプで渡す
#boardstr = BoardStr.conv_boardstr(_q_lines, 'random', current_seed)
cmd = "/opt/python3.6/bin/python3.6 /home/pi/pynq-router/solver/gen_boardstr.py -t random -s {} {} | /home/pi/pynq-router/sw_huge/sim - {} {}".format(current_seed, probpath, current_seed, tmppath)
print("`{}`".format(cmd))
time_start = time.time()
subprocess.call(cmd.strip(), shell=True)
time_done = time.time()
elapsed = time_done - time_start
res["answer"] = {}
res["answer"]["client"] = "192.168.4.1"
res["answer"]["answer"] = "Solved on Raspberry Pi!"
res["answer"]["cputime"] = elapsed
res["status"] = "Solved on Raspberry Pi"
current_seed += 1
# CPU time
print("CPU_time:{}".format(res["answer"]["cputime"]))
with open(infopath, "w") as f:
f.write("CPU_time:{}\n".format(res["answer"]["cputime"]))
f.write("memory:551250\n")
# 回答をファイルに保存するとしたらここで処理する
# 整形ルーティング (再配線) する
#cmd = "/home/pi/pynq-router/resolver/solver --reroute --output {} {} {}".format(outpath, probpath, tmppath)
cmd = "/home/pi/adc2017/pynq-router/resolver/solver --reroute --output {} {} {}".format(outpath, probpath, tmppath)
print("`{}`".format(cmd))
subprocess.call(cmd.strip().split(" "))
# たまに整形ルーティングが失敗する
# そのときは tmp を答えファイルとしてコピーする
#if not os.path.exists(outpath) and os.path.exists(tmppath):
# cmd = "/bin/cp {} {}".format(tmppath, outpath)
# subprocess.call(cmd.strip().split(" "))
# 回答ファイルが正しく出力されないときは,正しく解けなかったとき
if not os.path.exists(outpath):
res["status"] = "DNF"
else:
# Format check
#cmd = "/usr/bin/python /home/pi/conmgr/adc2017/server/nlcheck.py --input {} --target {}".format(probpath, outpath)
cmd = "/usr/bin/python /home/pi/adc2018/conmgr/adc2018/server/nlcheck.py --input {} --target {}".format(probpath, outpath)
print("`{}`".format(cmd))
subprocess.call(cmd.strip().split(" "))
# LINE_NUMが閾値未満のとき,PYNQに問題を配信して問題を解かせる
res = solve_questions(_question_name, qstr)
# 最終結果だけを保存
questions[_question_name]["status"] = res["status"]
questions[_question_name]["answer"] = res["answer"]
return json.dumps(res)
def solve_questions(qname, qstr):
"""
このメソッドでは,問題データをソルバのクライアントに送りつける.
結果は/postに送られてくるので,結果の集計はそちらで行う.
"""
global clients
global questions
global current_seed
global app_args
def worker(host, qname, qstr, qseed, q):
def worker(host, qname, qstr, qseed, req_id, resolver):
_url = "http://{}/start".format(host)
data = {
"client": host,
"qname": qname,
"question": qstr,
"qseed": qseed,
"req_id": req_id,
"resolver": resolver
}
try:
r = requests.post(_url, data={"client": host, "qname": qname, "question": qstr, "qseed": qseed})
r = requests.post(_url, data=data)
client_res = json.loads(r.text)
q.put(client_res)
except Exception as e:
sys.stderr.write(str(e) + "\n")
threads = []
q = Queue()
for c in clients:
_th = threading.Thread(name=c, target=worker, args=(c, qname, qstr, current_seed, q))
# 時刻をリクエストIDとして設定
req_id = time.time()
questions[qname]['last_req'] = req_id
for c in clients['solver']:
# 問題はSolverに送る
client_addr = c[0]
idx_of_resolver = current_seed % len(clients['resolver'])
resolver = clients['resolver'][idx_of_resolver][0]
_th = threading.Thread(name=client_addr, target=worker, args=(client_addr, qname, qstr, current_seed, req_id, resolver))
_th.start()
threads.append(_th)
current_seed += 1
# PYNQが解き終わるまで待つ(ここでは最大10秒)
cnt = 0
while cnt < app_args["timeout"] and questions[qname]["queue"].qsize() < 1:
time.sleep(1)
cnt += 1
res = {"status": "Processed"}
res = {"status": "Done", "answers": [], "answer": ""}
return res
while not questions[qname]["queue"].empty():
_r = questions[qname]["queue"].get()
res["answers"].append(_r)
@app.route("/stop", methods=["POST"])
def stop():
_client = request.form["client"]
_url = _client + "/stop"
# res["answers"]に,回答を得られたものの結果が,返ってきた順に入る.
# 解の品質等を決めて最終的な回答を与える場合はここで処理する(今はとりあえず最初の答え)
# TODO: 答えが無い場合の処理
if len(res["answers"]) > 0:
res["answer"] = res["answers"][0]
else:
res["answer"] = { "client": "None", "answer": "" }
res["status"] = "DNF"
try:
r = requests.get(_url)
client_res = json.loads(r.text)["status"]
except Exception as e:
client_res = "Connection error"
sys.stderr.write(str(e) + "\n")
#print(res)
res = {"status": client_res}
return res
return json.dumps(res)
@app.route("/status", methods=["POST"])
def get_status():
......@@ -267,8 +288,9 @@ def get_clients():
res = OrderedDict()
for c in clients:
res[c] = "http://{}".format(c)
for c in clients['all']:
client_ip = c[0]
res[client_ip] = "http://{}".format(client_ip)
return json.dumps(res)
......@@ -288,45 +310,78 @@ def client_table():
global app_args
global clients
return render_template("part_client_table.html", clients=clients)
return render_template("part_client_table.html", clients=clients["all"], local_mode=g.local_mode)
@app.route("/get_question_status")
def question_status():
global app_args
global questions
global clients
qname = request.args.get("qname", "")
update_answer_list(qname)
qdata = questions[qname]
return render_template("part_question_status.html", qname=qname, qdata=qdata)
return render_template("part_question_status.html", qname=qname, qdata=qdata, solvers=clients["solver"])
@app.route("/")
def index():
global app_args
global questions
global clients
question_path = os.path.abspath(app_args["question"])
return render_template("index.html", questions=questions, question_path=question_path, clients=clients)
return render_template("index.html", questions=questions, question_path=question_path)
def main(args):
raise NotImprementedError()
def init_system():
global app_args
global questions
global clients
if questions is None:
load_questions()
if clients is None:
with open(app_args["client"], "r") as fp:
_clients = fp.readlines()
all_clients = [v.rstrip().split() for v in _clients]
solver = []
resolver = []
for v in all_clients:
if v[1].lower() == "solver":
solver.append(v)
elif v[1].lower() == "resolver":
resolver.append(v)
clients = {
"all": all_clients,
"solver": solver,
"resolver": resolver
}
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PYNQ control panel.")
parser.add_argument("-c", "--client", action="store", type=str, default=None, required=True, help="Client list.")
parser.add_argument("-q", "--question", action="store", type=str, default="./problems", help="Path to the question folder.")
parser.add_argument("-o", "--out", action="store", type=str, default="./answers", help="Path to the output folder.")
parser.add_argument("-l", "--line-num-th", action="store", type=int, default=128, help="Line number threshold.")
parser.add_argument("-t", "--timeout", action="store", type=int, default=300, help="Timeout.")
parser.add_argument("--debug", action="store_true", default=False, help="Debug mode.")
args = vars(parser.parse_args())
app_args = args
init_system()
if args["debug"]:
app.debug = True
app.run(host='0.0.0.0', threaded=True)
......@@ -43,12 +43,16 @@ body{
#client-control-pane{
height: 330px;
overflow: scroll;
overflow-y: scroll;
}
#client-control-pane table th,
#client-control-pane table td{
width: 50%;
#client-control-pane table th.large-cell,
#client-control-pane table td.large-cell{
width: 40%;
}
#client-control-pane table th.small-cell,
#client-control-pane table td.small-cell{
width: 20%;
}
#question-control-pane h3{
......
......@@ -63,7 +63,6 @@ var PynqManager = (function(){
}).done(function(res){
var answer = res;
$("#solving-question-status").text(answer["status"]);
$("#solved-result").text(answer["answer"]["answer"]);
$("#solved-client").text(answer["answer"]["client"]);
if (after !== null){
......@@ -75,7 +74,31 @@ var PynqManager = (function(){
_p.sendStop = function(){
console.log("Not implemented!");
for (var key in this.clients){
(function(_key, _client){
var statusObj = $(".client-status-row[data-cname='"+_key+"']").find(".client-status-value").eq(0)
$.ajax({
type: "POST",
url: "/stop",
dataType: "json",
data: {
"client": _client
}
}).done(function(res){
var answer = res["status"];
var message = "";
if (answer) {
message = answer;
}else{
message = "Illegal response: " + res;
}
statusObj.text(message);
}).fail(function(){
statusObj.text("Connection error");
});
})(key, this.clients[key]);
}
}
......@@ -102,13 +125,19 @@ $(function(){
$(".question-row").removeClass("q-selected");
$tr.addClass("q-selected");
var qname = $tr.data("qname");
show_question_status(qname);
// show_question_status(qname);
location.hash = "#" + qname;
return false;
});
var hash = location.hash.replace("#", "");
if(hash != ""){
$(".question-row[data-qname='" + hash + "']").addClass("q-selected");
}
});
}
var refresh_client_table = function(){
var show_client_table = function(){
$.ajax({
type: "GET",
dataType: "html",
......@@ -116,16 +145,7 @@ $(function(){
}).done(function(d){
$("#client-control-pane").html("");
$("#client-control-pane").html(d);
$.ajax({
type: "GET",
dataType: "json",
url: "/get_clients"
}).done(function(d){
pynqClients = d;
pm = PynqManager(pynqClients);
pm.getStatus();
});
pm.getStatus();
});
}
......@@ -143,15 +163,30 @@ $(function(){
var qname = $(this).data("qname");
pm.sendQuestion(qname, after=refresh_question_table);
});
$("#client-control-pane").find(".stop-button").eq(0).click(function(){
pm.sendStop();
});
});
}
$(window).on('hashchange', function(){
var hash = location.hash.replace("#", "");
if(hash == ""){
show_client_table();
}else{
show_question_status(hash);
}
}).trigger('hashchange');
refresh_question_table();
refresh_client_table();
$("#view-server-status-button").click(function(){
refresh_client_table();
return false;
$.ajax({
type: "GET",
dataType: "json",
url: "/get_clients"
}).done(function(d){
pynqClients = d;
pm = PynqManager(pynqClients);
});
});
......@@ -20,7 +20,7 @@
<div class="row">
<div class="col-5" id="question-control-pane">
<h3>問題一覧</h3>&nbsp;
<span><a href="#" id="view-server-status-button">クライアント状況</a></span>
<span><a href="/#" id="view-server-status-button">システム状況</a></span>
<div id="question-table-wrapper">
<p>Loading...</p>
</div>
......
<h3>クライアント状況</h3>
<h3>システム状況</h3>
<h4>動作モード</h4>
<p>
{% if local_mode %}
Normal Mode
{% else %}
Viewer Mode
{% endif %}
</p>
<h4>クライアント</h4>
<table class="table table-bordered" id="clients-table">
<tr>
<th>クライアント名</th>
<th>ステータス</th>
<th class="">Client</th>
<th class="">Role</th>
<th class="">Status</th>
</tr>
{% for c in clients %}
<tr class="client-status-row" data-cname="{{c}}">
<td class="client-status-name">{{c}}</td>
<tr class="client-status-row" data-cname="{{c[0]}}">
<td class="client-status-name">
{% if c|length > 3 %}
<img src="static/client-icon/{{c[3]}}" alt="{{c[2]}}" height="30" />&nbsp;
{% endif %}
{{c[0]}}
{% if c|length > 2 %}
&nbsp;({{c[2]}})
{% endif %}
</td>
<td class="">{{c[1]}}</td>
<td class="client-status-value"></td>
</tr>
{% endfor %}
......
<h3>問題 【{{qname}}】</h3>
<p>
<button class="btn btn-primary btn-lg start-button" type="button" data-qname="{{qname}}">Start</button>
</p>
<div class="row">
<div class="col-4">
<h3> 【{{qname}}】</h3>
<p>
<button class="btn btn-primary btn-lg start-button" type="button" data-qname="{{qname}}">Start</button>
<button class="btn btn-danger btn-lg stop-button" type="button" data-qname="all">Stop</button>
</p>
</div>
<div class="col-8">
<p>処理結果</p>
<table class="table table-bordered">
<tr>
<th>Client (Solver)</th>
<th>Status</th>
</tr>
{% for c in solvers %}
<tr>
<td>
{% if c|length > 3 %}
<img src="static/client-icon/{{c[3]}}" alt="{{c[2]}}" height="30" />&nbsp;
{% endif %}
{{c[0]}}
{% if c|length > 2 %}
&nbsp;({{c[2]}})
{% endif %}
</td>
<td></td>
</tr>
{% endfor %}
</table>
</div>
</div>
<div>
<h4>処理結果一覧</h4>
<table class="table table-bordered table-striped">
<tr>
<th>Timestamp</th>
<th>Client</th>
<th>Score</th>
</tr>
{% for v in qdata.answers %}
<tr>
<td>{{v.timestamp}}</td>
<td>{{v.solver}}</td>
<td>{{v.nlcheck}}</td>
</tr>
{% endfor %}
</table>
</div>
<p>状況:<span id="solving-question-status">{{qdata.status}}</span></p>
<h4>結果</h4>
<p>クライアント:<span id="solved-client">{{qdata.answer.client}}</span></p>
......
......@@ -78,6 +78,15 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
print(seed)
print('')
res = {
'client': option['client'],
'qname': option['name'],
'solution': '',
'cputime': -1.0,
'req_id': option['req_id'],
'solved': False
}
# LINE数を数えてコンフィグするbitstreamを分岐
line_num = boardstr.count('L')
if line_num < 127:
......@@ -89,7 +98,9 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
else:
solver_thread.stopped()
solver_thread = None
return {'solved': False, 'solution': '', 'elapsed': -1.0}
if "host" in option:
requests.post("http://{}/post".format(option['host']), data=res)
return res
# ボード文字列から X, Y, Z を読んでくる
size_x = (ord(boardstr[1]) - ord('0')) * 10 + (ord(boardstr[2]) - ord('0'))
......@@ -137,7 +148,9 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
if (solver_thread is not None) and (not solver_thread.is_running()):
solver_thread.stopped()
solver_thread = None
return { 'solved': False, 'solution': '', 'elapsed': -1.0 }
if "host" in option:
requests.post("http://{}/post".format(option['host']), data=res)
return res
# 完了の確認
print('Done!')
......@@ -154,11 +167,11 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
# 解けなかったらLEDを消す
mmio_led.write(0, 0)
sys.stderr.write('Cannot solve it!\n')
res = {'client': option['client'], 'qname': option['name'], 'answer': '', 'cputime': -1}
if "host" in option:
requests.post("http://{}/post".format(option['host']), data=res)
solver_thread = None
return { 'solved': False, 'solution': '', 'elapsed': -1.0 }
return res
print('Solved!')
# 解けたらLEDを全部つける
......@@ -185,13 +198,24 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
solution += str(boards[i]) # 普通に表示
solution += '\n'
res = {
'client': option['client'],
'qname': option['name'],
'solution': solution,
'cputime': elapsed,
'req_id': option['req_id'],
'solved': True
}
if "resolver" in option:
r = requests.post("http://{}/post".format(option['resolver']), data=res)
elif "host" in option:
r = requests.post("http://{}/post".format(option['host']), data=res)
if solver_thread is not None:
solver_thread.stopped()
res = {'client': option['client'], 'qname': option['name'], 'answer': solution, 'cputime': elapsed}
if "host" in option:
r = requests.post("http://{}/post".format(option['host']), data=res)
solver_thread = None
return { 'solved': True, 'solution': solution, 'elapsed': elapsed }
return res
def main():
parser = argparse.ArgumentParser(description="Solver with pynqrouter")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment