Commit 6f0a8af2 authored by Kento HASEGAWA's avatar Kento HASEGAWA

Use hash to show each question status and support for client icons (#8)

parent b6497913
...@@ -19,3 +19,7 @@ solver ...@@ -19,3 +19,7 @@ solver
# Python files # Python files
*.pyc *.pyc
__pycache__/ __pycache__/
# client-icons
client-icon/
...@@ -28,6 +28,59 @@ questions = None ...@@ -28,6 +28,59 @@ questions = None
clients = None clients = None
current_seed = 1 current_seed = 1
def load_questions():
global app_args
global questions
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,
"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
def update_answer_list(qname): def update_answer_list(qname):
global app_args global app_args
...@@ -50,65 +103,8 @@ def update_answer_list(qname): ...@@ -50,65 +103,8 @@ def update_answer_list(qname):
@app.before_request @app.before_request
def before_request(): def before_request():
global app_args 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()
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,
"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
if clients is None:
with open(app_args["client"], "r") as fp:
_clients = fp.readlines()
clients = [v.rstrip() for v in _clients] g.local_mode = (request.remote_addr == "127.0.0.1")
@app.route("/post", methods=["POST"]) @app.route("/post", methods=["POST"])
def post(): def post():
...@@ -237,7 +233,8 @@ def solve_questions(qname, qstr): ...@@ -237,7 +233,8 @@ def solve_questions(qname, qstr):
request_time = time.time() request_time = time.time()
for c in clients: for c in clients:
_th = threading.Thread(name=c, target=worker, args=(c, qname, qstr, current_seed, request_time)) client_addr = c[0]
_th = threading.Thread(name=client_addr, target=worker, args=(client_addr, qname, qstr, current_seed, request_time))
_th.start() _th.start()
threads.append(_th) threads.append(_th)
current_seed += 1 current_seed += 1
...@@ -269,7 +266,8 @@ def get_clients(): ...@@ -269,7 +266,8 @@ def get_clients():
res = OrderedDict() res = OrderedDict()
for c in clients: for c in clients:
res[c] = "http://{}".format(c) client_ip = c[0]
res[client_ip] = "http://{}".format(client_ip)
return json.dumps(res) return json.dumps(res)
...@@ -289,7 +287,7 @@ def client_table(): ...@@ -289,7 +287,7 @@ def client_table():
global app_args global app_args
global clients global clients
return render_template("part_client_table.html", clients=clients) return render_template("part_client_table.html", clients=clients, local_mode=g.local_mode)
@app.route("/get_question_status") @app.route("/get_question_status")
def question_status(): def question_status():
...@@ -314,22 +312,42 @@ def index(): ...@@ -314,22 +312,42 @@ def index():
question_path = os.path.abspath(app_args["question"]) question_path = os.path.abspath(app_args["question"])
print(g.local_mode)
return render_template("index.html", questions=questions, question_path=question_path, clients=clients) return render_template("index.html", questions=questions, question_path=question_path, clients=clients)
def main(args): def main(args):
raise NotImprementedError() 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()
clients = [v.rstrip().split() for v in _clients]
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PYNQ control panel.") 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("-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("-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("-o", "--out", action="store", type=str, default="./answers", help="Path to the output folder.")
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.") parser.add_argument("--debug", action="store_true", default=False, help="Debug mode.")
args = vars(parser.parse_args()) args = vars(parser.parse_args())
app_args = args app_args = args
init_system()
if args["debug"]: if args["debug"]:
app.debug = True app.debug = True
app.run(host='0.0.0.0', threaded=True) app.run(host='0.0.0.0', threaded=True)
...@@ -46,9 +46,13 @@ body{ ...@@ -46,9 +46,13 @@ body{
overflow-y: scroll; overflow-y: scroll;
} }
#client-control-pane table th, #client-control-pane table th.large-cell,
#client-control-pane table td{ #client-control-pane table td.large-cell{
width: 50%; width: 40%;
}
#client-control-pane table th.small-cell,
#client-control-pane table td.small-cell{
width: 20%;
} }
#question-control-pane h3{ #question-control-pane h3{
......
...@@ -101,13 +101,19 @@ $(function(){ ...@@ -101,13 +101,19 @@ $(function(){
$(".question-row").removeClass("q-selected"); $(".question-row").removeClass("q-selected");
$tr.addClass("q-selected"); $tr.addClass("q-selected");
var qname = $tr.data("qname"); var qname = $tr.data("qname");
show_question_status(qname); // show_question_status(qname);
location.hash = "#" + qname;
return false; 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({ $.ajax({
type: "GET", type: "GET",
dataType: "html", dataType: "html",
...@@ -145,12 +151,15 @@ $(function(){ ...@@ -145,12 +151,15 @@ $(function(){
}); });
} }
refresh_question_table(); $(window).on('hashchange', function(){
refresh_client_table(); var hash = location.hash.replace("#", "");
if(hash == ""){
show_client_table();
}else{
show_question_status(hash);
}
}).trigger('hashchange');
$("#view-server-status-button").click(function(){ refresh_question_table();
refresh_client_table();
return false;
});
}); });
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<div class="row"> <div class="row">
<div class="col-5" id="question-control-pane"> <div class="col-5" id="question-control-pane">
<h3>問題一覧</h3>&nbsp; <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"> <div id="question-table-wrapper">
<p>Loading...</p> <p>Loading...</p>
</div> </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"> <table class="table table-bordered" id="clients-table">
<tr> <tr>
<th>クライアント名</th> <th class="">Client</th>
<th>ステータス</th> <th class="">Role</th>
<th class="">Status</th>
</tr> </tr>
{% for c in clients %} {% for c in clients %}
<tr class="client-status-row" data-cname="{{c}}"> <tr class="client-status-row" data-cname="{{c[0]}}">
<td class="client-status-name">{{c}}</td> <td class="client-status-name">
{% if c|length > 3 %}
&nbsp;<img src="static/client-icon/{{c[3]}}" alt="{{c[2]}}" height="30" />
{% endif %}
{{c[0]}}
{% if c|length > 2 %}
&nbsp;({{c[2]}})
{% endif %}
</td>
<td class="">{{c[1]}}</td>
<td class="client-status-value"></td> <td class="client-status-value"></td>
</tr> </tr>
{% endfor %} {% endfor %}
......
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