Commit e7a02e9a authored by Kento HASEGAWA's avatar Kento HASEGAWA
Browse files

Add support for saving the best solution

parent 105e3566
Loading
Loading
Loading
Loading
+13 −0
Changes for roles/host.py: 13 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -89,6 +89,16 @@ class Host(object):
        else:
            return {'status': 'error'}
    
    def save_solution(self, problem_key):

        problem = self.get_problem(problem_key)

        if problem is not None:
            problem.save_best_solution()
            return {'status': 'saved'}
        else:
            return {'status': 'failed'}
    
    def get_request_status(self, request_id):
        if request_id in self.request:
            return self.request[request_id].get_status()
@@ -122,6 +132,9 @@ class Host(object):
        elif cmd == 'problem/solution':
            self.store_solution(params)
            return {'status': 'received'}
        elif cmd == 'problem/save':
            problem_key = params['problem']
            return self.save_solution(problem_key)
        elif cmd == 'request/status':
            request_id = float(params['request_id'])
            return self.get_request_status(request_id)
+4 −4
Changes for static/css/adc2019.css: 4 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -60,16 +60,16 @@ body{
    display: inline-block;
}

#client-control-pane tr.solution-detail-row, 
#client-control-pane tr.solution-detail-row td{
#solution-list-container tr.solution-detail-row, 
#solution-list-container tr.solution-detail-row td{
    cursor: pointer;
}

#client-control-pane tr.solution-detail-row:hover{
#solution-list-container tr.solution-detail-row:hover{
    background-color: rgba(200, 100, 100, .15);
}

#client-control-pane tr.solution-detail-row.submit-answer{
#solution-list-container tr.solution-detail-row.submit-solution{
    background-color: rgba(100, 200, 100, .3);
}

+21 −0
Changes for static/js/adc2019.js: 21 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@ class StatusView {
                _this.start_solver();
            });
            
            _this.container.find('.save-button').click(()=>{
                _this.save_solution();
            });

            _this.container.find('.solution-detail-row td').click((e) => {
                var solution_id = $(e.target).parent("tr").data("solution-id");
                var problem_name = $(e.target).parent("tr").data("problem");
@@ -84,6 +88,23 @@ class StatusView {
        });
    }
    
    // 保存
    save_solution(){
        var _this = this;
        
        $.ajax({
            type: "POST",
            dataType: "json",
            url: "/api/problem/save",
            data: JSON.stringify({
                "problem": _this.problem_key
            }),
            contentType: 'application/json'
        }).done((d) => {
            _this.show_problem();
        });
    }

    get_request_status(request_id, timeout){
        var _this = this;
        $.ajax({
+4 −4
Changes for templates/part_problem_status.html: 4 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -22,11 +22,11 @@
        </thead>
        <tbody>
            {% for k, v in problem.get_solutions().items() %}
            {#% if (qdata.best_json == k) and (v.answer != "") %#}
            <!-- <tr class="answer-detail-row submit-answer" data-json="{#{k}#}" data-qname="{#{qname}#}"> -->
            {#% else %#}
            {% if k == problem.best_solution %}
            <tr class="solution-detail-row submit-solution" data-solution-id="{{k}}" data-problem="{{problem.name}}">
            {% else %}
            <tr class="solution-detail-row" data-solution-id="{{k}}" data-problem="{{problem.name}}">
            {#% endif %#}
            {% endif %}
                <td>{{v.timestamp_str}}</td>
                <td>{{v.worker}}</td>
                <td>
+84 −19
Changes for utils/data.py: 84 added lines, 19 removed lines.
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ class Problem(object):
        self.status = 'Ready'
        self.solutions = dict()
        self.solution_path = solution_path
        self.best_solution = None

        self._load_problem(problem_path)
    
@@ -106,6 +107,33 @@ class Problem(object):
        # Save solution
        solution.save(self.solution_path)
    
    def save_best_solution(self):

        best_score = None
        for k, v in self.solutions.items():
            if v.is_valid_solution():
                _score = v.score
                if (best_score is None) or (_score < best_score[1]):
                    best_score = (k, _score)

        if best_score is not None:

            solution_name = self.name
            outpath = f'{self.solution_path}/submit'

            if not os.path.exists(outpath):
                os.mkdir(outpath)
            
            best_solution_key = best_score[0]

            with open(f'{outpath}/{solution_name}.txt', 'w') as fp:
                fp.write(self.solutions[best_solution_key].solution)

            with open(f'{outpath}/{solution_name}.json', 'w') as fp:
                json.dump(self.solutions[best_solution_key].get_dict(), fp, indent=4)
            
            self.best_solution = best_solution_key

    def get_solutions(self):
        return self.solutions
    
@@ -124,25 +152,20 @@ class Solution(object):
        self.worker = data['worker']
        self.elapsed_time = data['elapsed_time']
        self.solution = data['solution']
        self.status = data['status']
        self.size = (None, None)
        self.map = None
        self.block = dict()

        self.timestamp = time.time()
        self._id = str(uuid.uuid4())

    def get_id(self):
        return self._id
        self._parse_solution()

    def get_dict(self):
        return {
            'id': self._id,
            'timestamp': self.timestamp,
            'request_id': self.request_id,
            'worker': self.worker,
            'elapsed_time': self.elapsed_time,
            'problem': self.problem,
            'solution': self.solution
        }
    def _parse_solution(self):

    def get_d3json(self):
        if self.status != 'done':
            return

        board_size = [0, 0]
        block_num = 0
@@ -155,9 +178,11 @@ class Solution(object):
        bmap = list()
        bposition = dict()

        state = 0

        while li < len(_lines):
            _l = _lines[li].strip()
            if 'SIZE' in _l:
            if (state == 0) and ('SIZE' in _l):
                board_size_str = _l.strip().split()[1]
                board_solution_size = [int(v) for v in board_size_str.split('X')]
                bw = board_solution_size[0]
@@ -166,7 +191,8 @@ class Solution(object):
                    li += 1
                    _l = _lines[li].strip()
                    bmap.append([int(v.strip()) for v in _l.split(',')])
            if 'BLOCK' in _l:
                state = 1
            if (state == 1) and ('BLOCK' in _l):
                p = r'BLOCK#([0-9]+) +@\(([0-9]+), *([0-9]+)\)'
                m = re.match(p, _l.strip())
                bi = int(m.group(1))
@@ -177,14 +203,53 @@ class Solution(object):
                    'x': bx,
                    'y': by,
                }
                state = 2

            li += 1

            self.size = (bw, bh)
            self.map = bmap
            self.block = bposition

    @property
    def score(self):
        if (len(self.size) == 2) and (self.size[0] is not None) and (self.size[1] is not None):
            return self.size[0] * self.size[1]
        else:
            return None

    def is_valid_solution(self):
        return self.status == 'done'

    def get_id(self):
        return self._id
    
    def get_dict(self):
        return {
            'w': bw,
            'h': bh,
            'map': bmap,
            'block': bposition
            'id': self._id,
            'timestamp': self.timestamp,
            'request_id': self.request_id,
            'worker': self.worker,
            'elapsed_time': self.elapsed_time,
            'problem': self.problem,
            'solution': self.solution
        }
    
    def get_d3json(self):

        if self.state == 'done':
            return {
                'w': self.size[0],
                'h': self.size[1],
                'map': self.map,
                'block': self.block
            }
        else:
            return {
                'w': 0,
                'h': 0,
                'map': [[]],
                'block': dict()
            }
    
    def save(self, basedir):