Commit 839d7369 authored by Kento HASEGAWA's avatar Kento HASEGAWA

First commit

parents
### https://raw.github.com/github/gitignore/9d7ff09c7d38dce9ef03e7ea4dc908a622546757/Python.gitignore
# Project-specific files
/conf.json
/questions/*
!/questions/.gitkeep
/answers/*
!/answers/.gitkeep
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
### https://raw.github.com/github/gitignore/9d7ff09c7d38dce9ef03e7ea4dc908a622546757/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
This diff is collapsed.
# ADC2019
Ensemble solver system for the algorithm design content in DA symposium 2019
## Environments
実際のソルバで使用している環境.
+ デバイス
- Raspberry Pi 3 B+
+ ソフトウェア
- Python >= 3.5 (通信プログラム)
* Flask
* gevent
* gevent-websocket
## Our previous works
+ [adc2018-system](https://www.togawa.cs.waseda.ac.jp/gitlab/adc2018/adc2018-system)
* [pynq-router](https://github.com/kotarot/pynq-router)
* [nl-solver](https://github.com/kotarot/nl-solver)
## License
This software is released under GPL v3 License, see [LICENSE](LICENSE).
#!python3
# ADC2019 system module
import json
from roles import Host, Solver
config = None
role = None
def init(args):
if ('config' in args) and (args['config'] is not None):
load_config(args['config'])
def load_config(path):
global config
global role
with open(path, 'r') as fp:
config = json.load(fp)
if 'role' in config:
set_role(config['role'], config)
def set_role(role_name, config_data):
global role
if role_name == 'host':
role = Host(config_data)
elif role_name == 'solver':
role = Solver(config_data)
def call_api(method, cmd, params):
if role is not None:
return role.call_api(method, cmd, params)
else:
if cmd == 'role':
if method == 'POST':
set_role(params['role'], params)
return {'role': role.type}
else:
return {'role': 'Undefined'}
else:
return None
#!python3
import argparse
from flask import abort, Flask, g, jsonify, render_template, request
from gevent import pywsgi, monkey
from geventwebsocket.handler import WebSocketHandler
from queue import Queue
import adc2019system
webui = Flask(__name__)
@webui.route('/')
def webui_index():
# return adc2019system.role.role
return render_template('index.html')
@webui.route('/template/questions')
def webui_template_questions():
if (adc2019system.role is not None) and (adc2019system.role.type == 'host'):
questions = adc2019system.role.get_questions()
return render_template('part_questions.html', questions=questions)
else:
return abort(404)
@webui.route('/template/question/<name>')
def webui_template_question_status(name=None):
if name is None:
return abort(404)
if (adc2019system.role is not None) and (adc2019system.role.type == 'host'):
questions = adc2019system.role.get_questions()
return render_template('part_question_status.html', questions=questions)
else:
return abort(404)
@webui.route('/api/<path:cmd>', methods=['GET', 'POST'])
def webui_api(cmd=None):
if cmd is None:
return jsonify({'version': 'v1.0', 'app': 'adc2019system'})
if request.method == 'POST':
if request.headers['Content-Type'] != 'application/json':
return abort(400)
else:
params = request.json
else:
params = None
res = adc2019system.call_api(request.method, cmd, params)
if res is None:
return abort(404)
else:
return jsonify(res)
@webui.route('/ws')
def webui_ws():
pass
def init_system(args):
adc2019system.init(args)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='ADC2019 System')
parser.add_argument('-p', '--port', default=5000, type=int, action='store', help='Web UI and API port')
parser.add_argument('-c', '--config', default=None, type=str, action='store', help='Config file')
parser.add_argument('--debug', default=False, action='store_true', help='Debug mode')
args = vars(parser.parse_args())
init_system(args)
if args["debug"]:
webui.debug = True
webui.threaded = True
# webui.run(host='0.0.0.0', threaded=True)
server = pywsgi.WSGIServer(("", args['port']), webui, handler_class=WebSocketHandler)
server.serve_forever()
from .host import Host
from .solver import Solver
import glob
import json
import requests
from utils import Question
class Host(object):
def __init__(self, config):
self.type = 'host'
self.config = config
self.questions = []
self._load_questions(config['question_path'])
self.worker = dict()
self.setup_workers()
def __repr__(self):
return "Host"
def _load_questions(self, path):
questions_path = glob.glob(path)
questions_path = sorted(questions_path)
for v in questions_path:
question = Question(v)
self.questions.append(question)
def setup_workers(self):
for v in self.config['worker']:
worker_name = v['name']
self.worker[worker_name] = Worker(v)
def get_questions(self):
return self.questions
def call_api(self, method, cmd, params):
if cmd == 'role':
return {'role': self.type}
else:
return None
class Worker(object):
def __init__(self, params):
self.address = params['address']
self.name = params['name']
self.role = None
self.set_role(params['role'])
def post(self, path, data):
response = requests.post(
f'http://{self.address}/api/{path}',
json.dumps(data),
headers={'Content-Type': 'application/json'})
return response
def set_role(self, role):
r = self.post('role', {'role': role})
class RoleBase(object):
def __init__(self, config):
self.type = ''
def __repr__(self):
return ''
\ No newline at end of file
class Solver(object):
def __init__(self, config):
self.type = 'solver'
def __repr__(self):
return "Solver"
def call_api(self, method, cmd, params):
if cmd == 'role':
return {'role': self.type}
else:
return None
html, body{
font-size: 11px;
overflow: hidden;
}
body{
padding-top: 10px;
}
/* scrollbar settings */
::-webkit-scrollbar{
width: 20px;
border: 1px solid rgba(0, 0, 50, .2);
}
::-webkit-scrollbar-thumb{
background-color: rgba(0, 0, 50, .5);
}
#question-table-wrapper{
height: calc(100vh - 50px);
overflow-y: scroll;
overflow-x: hidden;
}
#question-table-wrapper th.large-cell,
#question-table-wrapper td.large-cell{
width: 24%;
}
#question-table-wrapper th.small-cell,
#question-table-wrapper td.small-cell{
width: 14%;
}
#question-table-wrapper tr.question-row,
#question-table-wrapper tr.question-row td{
cursor: pointer;
}
#question-table-wrapper tr.question-row.q-selected{
background-color: rgba(200, 100, 100, .3);
}
#question-table-wrapper tr.question-row:hover{
background-color: rgba(200, 100, 100, .15);
}
#client-control-pane{
height: calc(100vh - 20px);
overflow-y: scroll;
}
#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{
display: inline-block;
}
#client-control-pane tr.answer-detail-row,
#client-control-pane tr.answer-detail-row td{
cursor: pointer;
}
#client-control-pane tr.answer-detail-row:hover{
background-color: rgba(200, 100, 100, .15);
}
#client-control-pane tr.answer-detail-row.submit-answer{
background-color: rgba(100, 200, 100, .3);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<title>ADC2019 Solver System</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/theme_1562552953227.css">
<link rel="stylesheet" href="/static/css/adc2019.css">
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.bundle.min.js"></script>
<script src="/static/js/d3.min.js"></script>
<script src="/static/js/adc2019.js"></script>
<style>
.axis path {
display: none;
}
.axis line {
stroke-opacity: 0.3;
shape-rendering: crispEdges;
}
input[type="range"] {
right: 0;
top: 0;
position: absolute;
}
svg,
#chart-container {
width: 100%;
height: 100vh;
display: block;
}
#content-left h3{
display: inline-block;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="content-wrapper" class="container-fluid">
<div id="content-row" class="row">
<div class="col-4" id="content-left">
<h3>問題一覧</h3>&nbsp;
<span><a href="/#" id="view-server-status-button">システム状況</a></span>
<div id="question-list-container">
<p>Loading...</p>
</div>
</div>
<div class="col-8" id="content-right">
<div id="status-container">
</div>
</div>
</div>
</div>
</div>
</body>
</html>
<div class="row">
<div class="col-4">
<h3> 【{{qname}}】</h3>
{#% # if localmode %#}
<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>
<p>
<button class="btn btn-info btn-lg save-button" type="button" data-qname="{{qname}}">Save</button>
<button class="btn btn-success btn-lg submit-button" type="button" data-qname="{{qname}}">Up</button>
</p>
{#% else %#}
<!-- [View Only] -->
{#% endif %#}
</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>{{qdata.solver[c[0]]}}</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 k, v in qdata.answers.items() %#}
{#% if (qdata.best_json == k) and (v.answer != "") %#}
<tr class="answer-detail-row submit-answer" data-json="{#{k}#}" data-qname="{#{qname}#}">
{#% else %#}
<tr class="answer-detail-row" data-json="{#{k}#}" data-qname="{#{qname}#}">
{#% endif %#}
<td>{#{v.timestamp}#}</td>
<td>{#{v.solver}#}</td>
<td>
{#% if v.nlcheck == -1 %#}
Not solved
{#% else %#}
{#{v.nlcheck}#}
{#% endif %#}
</td>
</tr>
{#% endfor %#} -->
</table>
</div>
<table class="table table-bordered table-hover" id="question-table">
<thead>
<tr>
<th class="large-cell">File Name</th>
<th class="large-cell">Size</th>
<th class="small-cell">#Blocks</th>
<th class="large-cell">Status</th>
</tr>
</thead>
<tbody>
{% for v in questions %}
<tr class="question-row" data-qname="{{v.name}}">
<td class="large-cell">{{v.name}}</td>
<td class="large-cell">{{v.size_str}}</td>
<td class="small-cell">{{v.block_num}}</td>
<td class="large-cell">{{v.status}}</td>
</tr>
{% endfor %}
</tbody>
</table>
from .data import Question
import os
class Question(object):
def __init__(self, path):
self.path = path
self.name = ''
self.size = (0, 0)
self.block_num = 0
self.status = 'Ready'
self._load_question(path)
@property
def size_str(self):
return f'{self.size[0]}X{self.size[1]}'
def _load_question(self, path):
with open(path, 'r') as fp:
q_lines = fp.readlines()
board_size = [0, 0]
block_num = 0
for _l in q_lines:
if "SIZE" in _l:
board_size_str = _l.strip().split()[1]
board_size = [int(v) for v in board_size_str.split('X')]
if 'BLOCK_NUM' in _l:
block_num = int(_l.strip().split()[1])
name = os.path.splitext(os.path.basename(path))[0]
self.size = board_size
self.block_num = block_num
self.name = name
self.status = 'Ready'
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