Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
adc2019-system
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
adc2019
adc2019-system
Commits
79827d1a
Commit
79827d1a
authored
Aug 21, 2019
by
Kento HASEGAWA
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support for the problem viewer and dragging blocks in viewers
parent
fb0ef6af
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
184 additions
and
197 deletions
+184
-197
main.py
main.py
+3
-3
host.py
roles/host.py
+8
-7
adc2019-viewer.js
static/js/adc2019-viewer.js
+171
-186
adc2019.js
static/js/adc2019.js
+1
-1
part_problem_status.html
templates/part_problem_status.html
+1
-0
viewer.html
templates/viewer.html
+0
-0
No files found.
main.py
View file @
79827d1a
...
...
@@ -16,9 +16,9 @@ def webui_index():
# return adc2019system.role.role
return
render_template
(
'index.html'
)
@
webui
.
route
(
'/view
/solution
'
)
def
webui_view
_solution
():
return
render_template
(
'view
-solution
.html'
)
@
webui
.
route
(
'/view
er
'
)
def
webui_view
er
():
return
render_template
(
'view
er
.html'
)
@
webui
.
route
(
'/part/problems'
)
def
webui_part_problems
():
...
...
roles/host.py
View file @
79827d1a
...
...
@@ -106,16 +106,17 @@ class Host(object):
else
:
return
{
'status'
:
'unknown request'
}
def
get_
solution_for_viewer
(
self
,
problem_key
,
solution_id
):
def
get_
viewer_data
(
self
,
problem_key
,
solution_id
):
problem
=
self
.
get_problem
(
problem_key
)
if
problem
is
None
:
return
None
problem_data
=
problem
.
get_d3json
()
solution
=
problem
.
get_solution
(
solution_id
)
if
solution
is
None
:
return
None
solution_data
=
solution
.
get_d3json
()
if
solution_id
is
None
:
solution_data
=
None
else
:
solution
=
problem
.
get_solution
(
solution_id
)
solution_data
=
solution
.
get_d3json
()
return
{
'problem'
:
problem_data
,
...
...
@@ -146,10 +147,10 @@ class Host(object):
elif
cmd
==
'stop'
:
self
.
worker_manager
.
request_stop
()
return
{}
elif
cmd
==
'view
/solution
'
:
elif
cmd
==
'view'
:
problem_key
=
params
[
'problem'
]
solution_id
=
params
[
'solution'
]
return
self
.
get_
solution_for_viewer
(
problem_key
,
solution_id
)
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
)
...
...
static/js/adc2019-viewer.js
View file @
79827d1a
...
...
@@ -103,31 +103,33 @@ class ADC2019BoardViewer {
let
cubeResolution
=
this
.
cubeResolution
;
// Draw outer box
let
_width
=
data
[
'solution'
][
'w'
]
*
this
.
cubeResolution
;
let
_height
=
data
[
'solution'
][
'h'
]
*
this
.
cubeResolution
;
this
.
view
.
append
(
"g"
)
.
attr
(
"class"
,
"x axis"
)
.
selectAll
(
"line"
)
.
data
([
0
,
_width
])
.
enter
().
append
(
"line"
)
.
attr
(
"x1"
,
function
(
d
)
{
return
d
;
})
.
attr
(
"y1"
,
0
)
.
attr
(
"x2"
,
function
(
d
)
{
return
d
;
})
.
attr
(
"y2"
,
_height
)
.
attr
(
"stroke"
,
"#d00"
)
.
attr
(
"stroke-width"
,
2
);
this
.
view
.
append
(
"g"
)
.
attr
(
"class"
,
"y axis"
)
.
selectAll
(
"line"
)
.
data
([
0
,
_height
])
.
enter
().
append
(
"line"
)
.
attr
(
"x1"
,
0
)
.
attr
(
"y1"
,
function
(
d
)
{
return
d
;
})
.
attr
(
"x2"
,
_width
)
.
attr
(
"y2"
,
function
(
d
)
{
return
d
;
})
.
attr
(
"stroke"
,
"#d00"
)
.
attr
(
"stroke-width"
,
2
);
if
((
'solution'
in
data
)
&&
(
data
[
'solution'
]
!=
null
)){
let
_width
=
data
[
'solution'
][
'w'
]
*
this
.
cubeResolution
;
let
_height
=
data
[
'solution'
][
'h'
]
*
this
.
cubeResolution
;
this
.
view
.
append
(
"g"
)
.
attr
(
"class"
,
"x axis"
)
.
selectAll
(
"line"
)
.
data
([
0
,
_width
])
.
enter
().
append
(
"line"
)
.
attr
(
"x1"
,
function
(
d
)
{
return
d
;
})
.
attr
(
"y1"
,
0
)
.
attr
(
"x2"
,
function
(
d
)
{
return
d
;
})
.
attr
(
"y2"
,
_height
)
.
attr
(
"stroke"
,
"#d00"
)
.
attr
(
"stroke-width"
,
2
);
this
.
view
.
append
(
"g"
)
.
attr
(
"class"
,
"y axis"
)
.
selectAll
(
"line"
)
.
data
([
0
,
_height
])
.
enter
().
append
(
"line"
)
.
attr
(
"x1"
,
0
)
.
attr
(
"y1"
,
function
(
d
)
{
return
d
;
})
.
attr
(
"x2"
,
_width
)
.
attr
(
"y2"
,
function
(
d
)
{
return
d
;
})
.
attr
(
"stroke"
,
"#d00"
)
.
attr
(
"stroke-width"
,
2
);
}
let
colors
=
d3
.
schemeCategory10
...
...
@@ -138,11 +140,18 @@ class ADC2019BoardViewer {
// Create data
var
blocks
=
data
[
'problem'
][
'block'
];
var
block_nums
=
Object
.
keys
(
blocks
).
length
;
var
block_row
=
Math
.
ceil
(
Math
.
sqrt
(
block_nums
));
var
block_idx
=
0
;
for
(
var
bi
in
blocks
){
let
bw
=
blocks
[
bi
][
'w'
];
let
bh
=
blocks
[
bi
][
'h'
];
let
bx
=
data
[
'solution'
][
'block'
][
bi
][
'x'
];
let
by
=
data
[
'solution'
][
'block'
][
bi
][
'y'
];
var
bx
=
(
block_idx
%
block_row
)
*
3
;
var
by
=
(
Math
.
floor
(
block_idx
/
block_row
))
*
3
;
if
((
'solution'
in
data
)
&&
(
data
[
'solution'
]
!=
null
)){
bx
=
data
[
'solution'
][
'block'
][
bi
][
'x'
];
by
=
data
[
'solution'
][
'block'
][
bi
][
'y'
];
}
blocks
[
bi
][
'cellpos'
]
=
Array
();
for
(
var
_h
=
0
;
_h
<
bh
;
_h
++
){
...
...
@@ -161,6 +170,34 @@ class ADC2019BoardViewer {
blocks
[
bi
][
'x'
]
=
bx
;
blocks
[
bi
][
'y'
]
=
by
;
block_idx
++
;
}
function
snapToGrid
(
p
,
r
)
{
return
Math
.
round
(
p
/
r
)
*
r
;
}
var
__view
=
this
.
view
;
function
dragged
(
d
)
{
var
el
=
d3
.
select
(
this
);
var
_x
=
parseInt
(
el
.
attr
(
'data-x'
),
10
)
+
d3
.
event
.
x
;
var
_y
=
parseInt
(
el
.
attr
(
'data-y'
),
10
)
+
d3
.
event
.
y
;
el
.
attr
(
"transform"
,
(
d
)
=>
{
return
'translate('
+
snapToGrid
(
_x
,
cubeResolution
)
+
','
+
snapToGrid
(
_y
,
cubeResolution
)
+
')'
})
}
function
dragended
(
d
)
{
var
el
=
d3
.
select
(
this
).
classed
(
"dragging"
,
false
);
var
_x
=
parseInt
(
el
.
attr
(
'data-x'
),
10
)
+
d3
.
event
.
x
;
var
_y
=
parseInt
(
el
.
attr
(
'data-y'
),
10
)
+
d3
.
event
.
y
;
d3
.
select
(
this
)
.
attr
(
'data-x'
,
snapToGrid
(
_x
,
cubeResolution
))
.
attr
(
'data-y'
,
snapToGrid
(
_y
,
cubeResolution
));
}
function
dragstarted
(
d
)
{
var
el
=
d3
.
select
(
this
);
el
.
raise
().
classed
(
"dragging"
,
true
);
}
var
itemContainer
=
this
.
view
.
selectAll
(
"g.itemContainer"
)
...
...
@@ -168,15 +205,19 @@ class ADC2019BoardViewer {
.
enter
()
.
append
(
'g'
)
.
attr
(
'class'
,
'itemContainer'
)
.
attr
(
"transform"
,
(
d
)
=>
'translate('
+
d
.
x
+
','
+
d
.
y
+
')'
)
.
attr
(
"transform"
,
(
d
)
=>
'translate('
+
0
+
','
+
0
+
')'
)
.
attr
(
'data-x'
,
(
d
)
=>
d
.
x
)
.
attr
(
'data-y'
,
(
d
)
=>
d
.
y
);
.
attr
(
'data-y'
,
(
d
)
=>
d
.
y
)
.
call
(
d3
.
drag
()
.
on
(
"start"
,
dragstarted
)
.
on
(
"drag"
,
dragged
)
.
on
(
"end"
,
dragended
));
var
cellContainer
=
itemContainer
.
append
(
'g'
)
.
attr
(
'class'
,
'cellContainer'
)
.
attr
(
'data-color'
,
(
d
,
i
)
=>
colors
[
i
%
colors
.
length
])
.
attr
(
'x'
,
0
)
.
attr
(
'y'
,
0
)
.
attr
(
'y'
,
0
)
;
cellContainer
.
selectAll
(
'g'
)
.
data
((
d
)
=>
d
.
cellpos
)
...
...
@@ -191,165 +232,100 @@ class ADC2019BoardViewer {
return
d3
.
select
(
nodes
[
i
].
parentNode
).
attr
(
'data-color'
);
});
cellContainer
.
selectAll
(
'g'
)
.
data
((
d
)
=>
d
.
cellpos
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'x'
,
(
d
)
=>
d
[
0
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'y'
,
(
d
)
=>
d
[
1
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'width'
,
this
.
cubeResolution
)
.
attr
(
'height'
,
this
.
cubeResolution
)
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'fill'
,
'white'
)
.
attr
(
'font-size'
,
'20px'
)
.
attr
(
'cursor'
,
'move'
);
// .text((d) => d[2]);
let
sw
=
data
[
'solution'
][
'w'
];
let
sh
=
data
[
'solution'
][
'h'
];
var
lines
=
Object
();
for
(
var
_h
=
0
;
_h
<
sh
;
_h
++
){
for
(
var
_w
=
0
;
_w
<
sw
;
_w
++
){
let
line_index
=
data
[
'solution'
][
'map'
][
_h
][
_w
];
if
(
line_index
==
0
){
continue
;
}
if
((
'solution'
in
data
)
&&
(
data
[
'solution'
]
!=
null
)){
cellContainer
.
selectAll
(
'g'
)
.
data
((
d
)
=>
d
.
cellpos
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'x'
,
(
d
)
=>
d
[
0
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'y'
,
(
d
)
=>
d
[
1
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'width'
,
this
.
cubeResolution
)
.
attr
(
'height'
,
this
.
cubeResolution
)
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'fill'
,
'white'
)
.
attr
(
'font-size'
,
'20px'
)
.
attr
(
'cursor'
,
'move'
);
}
else
{
cellContainer
.
selectAll
(
'g'
)
.
data
((
d
)
=>
d
.
cellpos
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'x'
,
(
d
)
=>
d
[
0
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'y'
,
(
d
)
=>
d
[
1
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'width'
,
this
.
cubeResolution
)
.
attr
(
'height'
,
this
.
cubeResolution
)
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'fill'
,
'white'
)
.
attr
(
'font-size'
,
'20px'
)
.
attr
(
'cursor'
,
'move'
)
.
text
((
d
)
=>
d
[
2
]);
}
if
(
!
lines
.
hasOwnProperty
(
line_index
)){
lines
[
line_index
]
=
Array
();
}
lines
[
line_index
].
push
([
_w
,
_h
,
line_index
]);
if
((
_w
+
1
<
sw
)
&&
(
data
[
'solution'
][
'map'
][
_h
][
_w
+
1
]
==
line_index
)){
lines
[
line_index
].
push
([
_w
+
0.5
,
_h
,
''
]);
}
if
((
_h
+
1
<
sh
)
&&
(
data
[
'solution'
][
'map'
][
_h
+
1
][
_w
]
==
line_index
)){
lines
[
line_index
].
push
([
_w
,
_h
+
0.5
,
''
]);
if
((
'solution'
in
data
)
&&
(
data
[
'solution'
]
!=
null
)){
// Draw lines
let
sw
=
data
[
'solution'
][
'w'
];
let
sh
=
data
[
'solution'
][
'h'
];
var
lines
=
Object
();
for
(
var
_h
=
0
;
_h
<
sh
;
_h
++
){
for
(
var
_w
=
0
;
_w
<
sw
;
_w
++
){
let
line_index
=
data
[
'solution'
][
'map'
][
_h
][
_w
];
if
(
line_index
==
0
){
continue
;
}
if
(
!
lines
.
hasOwnProperty
(
line_index
)){
lines
[
line_index
]
=
Array
();
}
lines
[
line_index
].
push
([
_w
,
_h
,
line_index
]);
if
((
_w
+
1
<
sw
)
&&
(
data
[
'solution'
][
'map'
][
_h
][
_w
+
1
]
==
line_index
)){
lines
[
line_index
].
push
([
_w
+
0.5
,
_h
,
''
]);
}
if
((
_h
+
1
<
sh
)
&&
(
data
[
'solution'
][
'map'
][
_h
+
1
][
_w
]
==
line_index
)){
lines
[
line_index
].
push
([
_w
,
_h
+
0.5
,
''
]);
}
}
}
let
lineColors
=
d3
.
schemePastel2
var
lineItemContainer
=
this
.
view
.
selectAll
(
"g.lineItemContainer"
)
.
data
(
Object
.
values
(
lines
))
.
enter
()
.
append
(
'g'
)
.
attr
(
'class'
,
'lineItemContainer'
);
var
lineContainer
=
lineItemContainer
.
append
(
'g'
)
.
attr
(
'class'
,
'lineContainer'
)
.
attr
(
'data-color'
,
(
d
,
i
)
=>
lineColors
[
i
%
lineColors
.
length
]);
lineContainer
.
selectAll
(
'g'
)
.
data
((
d
)
=>
d
)
.
enter
()
.
append
(
'rect'
)
.
attr
(
'x'
,
(
d
)
=>
(
d
[
0
]
+
0.25
)
*
this
.
cubeResolution
)
.
attr
(
'y'
,
(
d
)
=>
(
d
[
1
]
+
0.25
)
*
this
.
cubeResolution
)
.
attr
(
'width'
,
(
this
.
cubeResolution
*
0.5
))
.
attr
(
'height'
,
(
this
.
cubeResolution
*
0.5
))
.
attr
(
'fill'
,
(
d
,
i
,
nodes
)
=>
{
return
d3
.
select
(
nodes
[
i
].
parentNode
).
attr
(
'data-color'
);
});
lineContainer
.
selectAll
(
'g'
)
.
data
((
d
)
=>
d
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'x'
,
(
d
)
=>
d
[
0
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'y'
,
(
d
)
=>
d
[
1
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'width'
,
(
this
.
cubeResolution
*
0.5
))
.
attr
(
'height'
,
(
this
.
cubeResolution
*
0.5
))
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'fill'
,
'black'
)
.
attr
(
'font-size'
,
'16px'
)
.
text
((
d
)
=>
d
[
2
]);
}
let
lineColors
=
d3
.
schemePastel2
var
lineItemContainer
=
this
.
view
.
selectAll
(
"g.lineItemContainer"
)
.
data
(
Object
.
values
(
lines
))
.
enter
()
.
append
(
'g'
)
.
attr
(
'class'
,
'lineItemContainer'
);
var
lineContainer
=
lineItemContainer
.
append
(
'g'
)
.
attr
(
'class'
,
'lineContainer'
)
.
attr
(
'data-color'
,
(
d
,
i
)
=>
lineColors
[
i
%
lineColors
.
length
]);
lineContainer
.
selectAll
(
'g'
)
.
data
((
d
)
=>
d
)
.
enter
()
.
append
(
'rect'
)
.
attr
(
'x'
,
(
d
)
=>
(
d
[
0
]
+
0.25
)
*
this
.
cubeResolution
)
.
attr
(
'y'
,
(
d
)
=>
(
d
[
1
]
+
0.25
)
*
this
.
cubeResolution
)
.
attr
(
'width'
,
(
this
.
cubeResolution
*
0.5
))
.
attr
(
'height'
,
(
this
.
cubeResolution
*
0.5
))
.
attr
(
'fill'
,
(
d
,
i
,
nodes
)
=>
{
return
d3
.
select
(
nodes
[
i
].
parentNode
).
attr
(
'data-color'
);
});
lineContainer
.
selectAll
(
'g'
)
.
data
((
d
)
=>
d
)
.
enter
()
.
append
(
'text'
)
.
attr
(
'x'
,
(
d
)
=>
d
[
0
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'y'
,
(
d
)
=>
d
[
1
]
*
this
.
cubeResolution
+
0.5
*
this
.
cubeResolution
)
.
attr
(
'width'
,
(
this
.
cubeResolution
*
0.5
))
.
attr
(
'height'
,
(
this
.
cubeResolution
*
0.5
))
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'fill'
,
'black'
)
.
attr
(
'font-size'
,
'16px'
)
.
text
((
d
)
=>
d
[
2
]);
}
// _draw_blocks(blocks){
// let cubeResolution = this.cubeResolution;
// function snapToGrid(p, r) {
// return Math.round(p / r) * r;
// }
// function dragged(d) {
// var el = d3.select(this);
// var _x = parseInt(el.attr('data-x'), 10) + d3.event.x;
// var _y = parseInt(el.attr('data-y'), 10) + d3.event.y;
// el.attr("transform", (d) => {
// return 'translate(' + snapToGrid(_x, cubeResolution) + ',' + snapToGrid(_y, cubeResolution) + ')'
// })
// }
// function dragended(d) {
// var el = d3.select(this).classed("dragging", false);
// var _x = parseInt(el.attr('data-x'), 10) + d3.event.x;
// var _y = parseInt(el.attr('data-y'), 10) + d3.event.y;
// d3.select(this)
// .attr('data-x', snapToGrid(_x, cubeResolution))
// .attr('data-y', snapToGrid(_y, cubeResolution));
// }
// function dragstarted(d) {
// var el = d3.select(this);
// el.raise().classed("dragging", true);
// }
// let colors = d3.schemeCategory10
// // Reference
// // Grid: https://bl.ocks.org/ngminhtrung/7c5721a1504f3e29a36da9ddd9e5039b
// // Snap: https://bl.ocks.org/evanjmg/ea3e59e67b4256c8831d3fc80f71294b
// // Nested data structure: https://codeday.me/jp/qa/20190428/720184.html
// var itemContainer = this.view.selectAll("g.itemContainer")
// .data(blocks)
// .enter()
// .append('g')
// .attr('class', 'itemContainer')
// .attr("transform", (d) => 'translate(' + d.x + ',' + d.y + ')')
// .attr('data-x', (d) => d.x)
// .attr('data-y', (d) => d.y)
// .call(d3.drag()
// .on("start", dragstarted)
// .on("drag", dragged)
// .on("end", dragended));
// var cellContainer = itemContainer.append('g')
// .attr('class', 'cellContainer')
// .attr('data-color', (d, i) => colors[i])
// .attr('x', 0)
// .attr('y', 0)
// cellContainer.selectAll('g')
// .data((d) => d.cells)
// .enter()
// .append('rect')
// .attr('x', (d) => d[0] * this.cubeResolution)
// .attr('y', (d) => d[1] * this.cubeResolution)
// .attr('width', this.cubeResolution)
// .attr('height', this.cubeResolution)
// .attr('cursor', 'move')
// .attr('fill', (d, i, nodes) => {
// return d3.select(nodes[i].parentNode).attr('data-color');
// });
// cellContainer.selectAll('g')
// .data((d) => d.cells)
// .enter()
// .append('text')
// .attr('x', (d) => d[0] * this.cubeResolution + 0.5 * this.cubeResolution)
// .attr('y', (d) => d[1] * this.cubeResolution + 0.5 * this.cubeResolution)
// .attr('width', this.cubeResolution)
// .attr('height', this.cubeResolution)
// .attr('text-anchor', 'middle')
// .attr('fill', 'white')
// .attr('font-size', '20px')
// .attr('cursor', 'move')
// .text((d) => d[2]);
// }
}
$
(
function
(){
...
...
@@ -359,17 +335,26 @@ $(function(){
hash
=
location
.
hash
.
replace
(
"#"
,
""
);
params
=
hash
.
split
(
'/'
);
problem_name
=
params
[
0
];
if
(
params
.
length
>
1
){
solution_id
=
params
[
1
];
}
else
{
solution_id
=
null
;
}
$
.
ajax
({
type
:
"POST"
,
dataType
:
"json"
,
url
:
"/api/view
/solution
"
,
url
:
"/api/view"
,
data
:
JSON
.
stringify
({
"problem"
:
p
arams
[
0
]
,
"solution"
:
params
[
1
]
"problem"
:
p
roblem_name
,
"solution"
:
solution_id
}),
contentType
:
'application/json'
}).
done
((
d
)
=>
{
board
.
draw
(
d
);
}).
fail
((
d
)
=>
{
console
.
log
(
d
);
});
});
...
...
static/js/adc2019.js
View file @
79827d1a
...
...
@@ -38,7 +38,7 @@ class StatusView {
_this
.
container
.
find
(
'.solution-detail-row.valid-solution td'
).
click
((
e
)
=>
{
var
solution_id
=
$
(
e
.
target
).
parent
(
"tr"
).
data
(
"solution-id"
);
var
problem_name
=
$
(
e
.
target
).
parent
(
"tr"
).
data
(
"problem"
);
var
viewer_url
=
"/view
/solution
#"
+
problem_name
+
"/"
+
solution_id
;
var
viewer_url
=
"/view
er
#"
+
problem_name
+
"/"
+
solution_id
;
window
.
open
(
viewer_url
,
"_blank"
);
});
...
...
templates/part_problem_status.html
View file @
79827d1a
<div>
<h4
class=
'inline-heading'
id=
'problem-status-title'
>
{{problem.name}}
</h4>
<a
href=
"/viewer#{{problem.name}}"
target=
"_blank"
>
Viewer
</a>
{#% # if localmode %#}
<button
class=
"btn btn-primary btn-lg start-button"
type=
"button"
data-qname=
"{{problem.name}}"
>
Start
</button>
<!-- <button class="btn btn-danger btn-lg stop-button" type="button" data-qname="all">Stop</button> -->
...
...
templates/view
-solution
.html
→
templates/view
er
.html
View file @
79827d1a
File moved
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