Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
adc2018-system
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
adc2018
adc2018-system
Commits
89ba9abd
Commit
89ba9abd
authored
Aug 12, 2018
by
Kento HASEGAWA
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make it possible to save all the answers sent from clients (#9)
parent
4cffa912
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
129 additions
and
87 deletions
+129
-87
.gitignore
.gitignore
+2
-0
main.py
comm/server/main.py
+84
-81
pynq-manager.css
comm/server/static/css/pynq-manager.css
+1
-1
pynq-manager.js
comm/server/static/js/pynq-manager.js
+0
-1
part_question_status.html
comm/server/templates/part_question_status.html
+42
-4
No files found.
.gitignore
View file @
89ba9abd
...
...
@@ -3,6 +3,8 @@
.DS_Store
*.txt
*.tmp
*.json
# Object files
*.o
...
...
comm/server/main.py
View file @
89ba9abd
...
...
@@ -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,6 +28,25 @@ questions = None
clients
=
None
current_seed
=
1
def
update_answer_list
(
qname
):
global
app_args
global
questions
questions
[
qname
][
'answers'
]
=
[]
_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
...
...
@@ -57,12 +77,15 @@ def before_request():
questions
[
_name
]
=
{
"path"
:
v
,
"status"
:
"Not solved"
,
"answer"
:
{}
,
"answer"
:
""
,
"queue"
:
Queue
(),
"board_size"
:
board_size
,
"line_num"
:
line_num
"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
))
...
...
@@ -91,15 +114,55 @@ def before_request():
def
post
():
global
questions
global
app_args
_client
=
request
.
form
[
"client"
]
_qname
=
request
.
form
[
"qname"
]
_answer
=
request
.
form
[
"answer"
]
_cputime
=
request
.
form
[
"cputime"
]
dat
=
{
"client"
:
_client
,
"answer"
:
_answer
,
"cputime"
:
_cputime
}
receive_time
=
datetime
.
datetime
.
now
()
receive_time_str
=
receive_time
.
strftime
(
"
%
Y
%
m
%
d
%
H
%
M
%
S"
)
dat
=
{
"client"
:
_client
,
"answer"
:
_answer
,
"cputime"
:
_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
)
print
(
nlcheck
,
m
)
if
m
and
(
m
.
group
(
1
)
==
"True"
):
dat
[
"nlcheck"
]
=
float
(
m
.
group
(
2
))
else
:
dat
[
"nlcheck"
]
=
-
1
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"
}
...
...
@@ -132,116 +195,54 @@ def start():
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
"
)
# 回答をファイルに保存するとしたらここで処理する
# LINE_NUMが閾値未満のとき,PYNQに問題を配信して問題を解かせる
res
=
solve_questions
(
_question_name
,
qstr
)
# 整形ルーティング (再配線) する
#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
(
" "
))
# 最終結果だけを保存
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
,
request_time
):
_url
=
"http://{}/start"
.
format
(
host
)
try
:
r
=
requests
.
post
(
_url
,
data
=
{
"client"
:
host
,
"qname"
:
qname
,
"question"
:
qstr
,
"qseed"
:
qseed
})
r
=
requests
.
post
(
_url
,
data
=
{
"client"
:
host
,
"qname"
:
qname
,
"question"
:
qstr
,
"qseed"
:
qseed
,
"request_time"
:
request_time
})
client_res
=
json
.
loads
(
r
.
text
)
q
.
put
(
client_res
)
except
Exception
as
e
:
sys
.
stderr
.
write
(
str
(
e
)
+
"
\n
"
)
threads
=
[]
q
=
Queue
()
request_time
=
time
.
time
()
for
c
in
clients
:
_th
=
threading
.
Thread
(
name
=
c
,
target
=
worker
,
args
=
(
c
,
qname
,
qstr
,
current_seed
,
q
))
_th
=
threading
.
Thread
(
name
=
c
,
target
=
worker
,
args
=
(
c
,
qname
,
qstr
,
current_seed
,
request_time
))
_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"
:
"Done"
,
"answers"
:
[],
"answer"
:
""
}
while
not
questions
[
qname
][
"queue"
]
.
empty
():
_r
=
questions
[
qname
][
"queue"
]
.
get
()
res
[
"answers"
]
.
append
(
_r
)
# res["answers"]に,回答を得られたものの結果が,返ってきた順に入る.
# 解の品質等を決めて最終的な回答を与える場合はここで処理する(今はとりあえず最初の答え)
# TODO: 答えが無い場合の処理
if
len
(
res
[
"answers"
])
>
0
:
res
[
"answer"
]
=
res
[
"answers"
][
0
]
else
:
res
[
"answer"
]
=
{
"client"
:
"None"
,
"answer"
:
""
}
res
[
"status"
]
=
"DNF"
#print(res)
res
=
{
"status"
:
"Processed"
}
return
res
...
...
@@ -295,11 +296,14 @@ 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
,
clients
=
clients
)
@
app
.
route
(
"/"
)
def
index
():
...
...
@@ -321,7 +325,6 @@ if __name__ == "__main__":
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
())
...
...
comm/server/static/css/pynq-manager.css
View file @
89ba9abd
...
...
@@ -43,7 +43,7 @@ body{
#client-control-pane
{
height
:
330px
;
overflow
:
scroll
;
overflow
-y
:
scroll
;
}
#client-control-pane
table
th
,
...
...
comm/server/static/js/pynq-manager.js
View file @
89ba9abd
...
...
@@ -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
){
...
...
comm/server/templates/part_question_status.html
View file @
89ba9abd
<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-6"
>
<h3>
問題 【{{qname}}】
</h3>
<p>
<button
class=
"btn btn-primary btn-lg start-button"
type=
"button"
data-qname=
"{{qname}}"
>
Start
</button>
</p>
</div>
<div
class=
"col-6"
>
<p>
処理結果
</p>
<table
class=
"table table-bordered"
>
<tr>
<th>
クライアント
</th>
<th>
Status
</th>
</tr>
{% for c in clients %}
<tr>
<td>
{{c}}
</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.client}}
</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>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment