From f3ba4ba750a698ebcbe11c146267f4984112c77f Mon Sep 17 00:00:00 2001 From: Kento HASEGAWA Date: Mon, 26 Aug 2019 23:16:12 +0900 Subject: [PATCH] Add support for adc2019 official tools --- .gitmodules | 3 ++ Makefile | 2 + adc2019 | 1 + roles/host.py | 57 +++++++++++++---------------- static/js/adc2019.js | 29 +++++++++++++-- templates/part_solution_status.html | 1 + utils/adcclilib.py | 19 +++++----- utils/data.py | 29 ++++++++++++++- 8 files changed, 95 insertions(+), 46 deletions(-) create mode 160000 adc2019 diff --git a/.gitmodules b/.gitmodules index 228ba88..f779b88 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/Makefile b/Makefile index 3030952..2fbe953 100644 --- a/Makefile +++ b/Makefile @@ -2,3 +2,5 @@ .PHONY: clean clean: rm -rf ./solutions/* + rm -rf ./solvers/hsgw/P*.txt + rm -rf ./solvers/kwmr/A*.txt diff --git a/adc2019 b/adc2019 new file mode 160000 index 0000000..a408465 --- /dev/null +++ b/adc2019 @@ -0,0 +1 @@ +Subproject commit a40846560bf682e7a6165ae50216c7bb49dccd26 diff --git a/roles/host.py b/roles/host.py index 0cad37d..80ab427 100644 --- a/roles/host.py +++ b/roles/host.py @@ -7,6 +7,7 @@ import requests from utils import Problem, GroupPart import utils.adcclilib as adccli +# import adc2019.client.adcclient class Host(object): @@ -212,47 +213,41 @@ class Host(object): solution_id = params['solution'] return self.get_viewer_data(problem_key, solution_id) elif cmd == 'adccli/login': - with open('path-to-adccli-login', 'r') as fp: - d = json.load(fp) - r = adccli.login(d['url'], d['username'], d['password']) - res = {'message': r} - return json.dumps(res) + r = adccli.login(self.config['adccli']['url'], self.config['adccli']['username'], self.config['adccli']['password']) + return {'status': r} elif cmd == 'adccli/logout': r = adccli.logout() - res = {'message': r} - return json.dumps(res) + return {'status': r} elif cmd == 'adccli/whoami': - with open('path-to-adccli-login', 'r') as fp: - d = json.load(fp) r = adccli.whoami() - res = {'message': r, 'status': r == d['username']} - return json.dumps(res) + return {'message': r, 'status': r == self.config['adccli']} elif cmd == 'adccli/download-problem': out_abspath = os.path.abspath(self.config['problem_path']) r = adccli.get_q_all(out_abspath) self._load_problems(self.config['problem_path']) - res = {'message': r} - return json.dumps(res) + return {'status': r} elif cmd == 'adccli/upload-solution': - qname = params['problem'] - if not "best_json" in questions[qname]: - res = {'message': "Required to 'save' before submission"} + problem_key = params['problem'] + problem = self.problems[problem_key] + if problem.best_solution_key is None: + res = {'status': "Required to 'save' before submission"} else: - out_path = "{}/{}".format(self.config['solution_path'], "submit") - # qnumber = qname.replace("NL_Q", "").replace(".txt", "") - # ans_file_path = "{}/T01_A{}.txt".format(out_path, qnumber) - # ans_file_abspath = os.path.abspath(ans_file_path) - - # r = adccli.put_a(qnumber, ans_file_abspath) - # mes = r + "\n" - - # json_name = questions[qname]['best_json'] - # data = questions[qname]['answers'][json_name] - # r = adccli.put_a_info(qnumber, data['cputime'], "0", "Test") - # mes += r - mes = '' - res = {'message': mes} - return json.dumps(res) + solution_path = f"{self.config['solution_path']}/{problem_key}/submit/{problem_key}.txt" + qnumber = problem_key.replace("NL_Q", "").replace(".txt", "") + + solution_abspath = os.path.abspath(solution_path) + + r = adccli.put_a(qnumber, solution_abspath) + mes = r + "\n" + + best_solution_key = problem.best_solution_key + best_solution = problem.get_solution(best_solution_key) + cputime = f'{best_solution.elapsed_time:.3f}' + info_mes = f'Solver: {best_solution.worker}, RID: {best_solution.request_id}' + r = adccli.put_a_info(qnumber, cputime, "0", info_mes) + mes += r + res = {'status': mes} + return res else: return None diff --git a/static/js/adc2019.js b/static/js/adc2019.js index bdd1a45..6f24286 100644 --- a/static/js/adc2019.js +++ b/static/js/adc2019.js @@ -41,6 +41,10 @@ class StatusView { _this.fire('refresh'); }); + _this.container.find('.submit-button').click(()=>{ + _this.save_solution(); + }); + _this.container.find('#chk-solver-all').prop('checked', false); _this.container.find('#chk-solver-all').on('change', (e) => { @@ -144,6 +148,23 @@ 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); + }); + } update_status_view(){ var _this = this; @@ -227,18 +248,18 @@ 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']) diff --git a/templates/part_solution_status.html b/templates/part_solution_status.html index 517c6c4..fe7824d 100644 --- a/templates/part_solution_status.html +++ b/templates/part_solution_status.html @@ -20,6 +20,7 @@ {% else %} {{v.status}} {% endif %} + {{v.nlcheck}} {% endfor %} diff --git a/utils/adcclilib.py b/utils/adcclilib.py index fb03db3..de332ab 100644 --- a/utils/adcclilib.py +++ b/utils/adcclilib.py @@ -1,20 +1,21 @@ -#!/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() + # p = subprocess.run(exec_cmd, stdout=subprocess.PIPE, shell=True) + # res = p.stdout.decode().strip() + res = '' print(res) 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(): @@ -35,7 +36,7 @@ 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) diff --git a/utils/data.py b/utils/data.py index c6a606f..460a9b3 100644 --- a/utils/data.py +++ b/utils/data.py @@ -5,6 +5,7 @@ import math import os import queue import re +import subprocess import time import uuid @@ -353,9 +354,27 @@ class Problem(object): print(f'I: Put a solution: {solution_id}') self.solutions[solution_id] = solution + if solution.status == 'done': + problem_path = self.path + solution_path = f'{self.solution_path}/{self.name}/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']) @@ -424,6 +443,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 @@ -516,7 +540,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): -- 2.22.0