ColdCore/templates/challenges/challenges.html

178 lines
6.8 KiB
HTML

{% extends "base.html" %}
{% block title %}Challenges{% endblock %}
{% block head %}
{% endblock %}
{% block content %}
<section>
<div class="row">
<div class="col s12">
<div class="card purple darken-1">
<div class="card-content white-text">
Due to way more users than expected, the platform and some problems may not be stable. Please report all errors encountered in a ticket or on IRC, and be patient :).
</div>
</div>
</div>
</div>
</section>
<div class="row">
<div class="col s6">
<div class="left">
<select onchange="filterCategories(this);">
<option value="*">Show all</option>
{% for category in categories %}
<option>{{ category }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="col s6">
<span class="right"><a class="btn" href="#" id="toggleState">Collapse all challenges</a></span>
</div>
</div>
{% for stage in stages %}
<hr />
{% if stage.description %}
<p>{{stage.description}}</p>
{% endif %}
<span class="left"><h4>{{ stage.name }}</h4></span>
<span class="right"><a class="stage-collapse" data-collapse="{{ stage.alias }}" href="#">Toggle</a></span>
<div class="clearfix"></div>
<ul class="collapsible popout" data-collapsible="expandable">
{% for challenge in challenges[stage.id] %}
<li class="challenge" data-category="{{ challenge.category }}" data-stage="{{stage.alias}}">
<div id="header-{{ challenge.alias }}" data-challenge="{{ challenge.alias }}" class="collapsible-header">
<div class="status-dot green circle tooltipped" data-position="right" data-tooltip="This challenge is Online"></div>
<div class="challenge-text truncate">{{ challenge.name }}</div>
<span class="right">
<span>{{ challenge.author }}</span>
<b>&middot;</b>
<span id="solves-{{ challenge.alias }}">{{ solves[challenge.id] }}</span> {% if solves[challenge.id] == 1 %}solve{% else %}solves{% endif %}
<b>&middot;</b>
{{ challenge.category }}
<b>&middot;</b>
{{ challenge.points }} pt
{% if challenge in solved %}
<i id="check-{{ challenge.alias }}" class="material-icons green-text right check-icon">done</i>
{% else %}
<div class="check-pad"></div>
{% endif %}
</span>
</div>
<div class="collapsible-body">
<p>{{ challenge.description | safe }}
{% if challenge in solved %}
<br /><br /><strong>Your team has solved this challenge!</strong><br />
<a href="{{ url_for('.show_solves', challenge_id=challenge.alias) }}">View solves</a>
</p>
{% else %}
<br /><br />
<a href="{{ url_for('.show_solves', challenge_id=challenge.alias) }}">View solves</a>
</p>
<form class="flag-form" action="{{ url_for('.submit', challenge_id=challenge.alias) }}" data-challenge="{{ challenge.alias }}" method="POST">
<div class="row no-bot">
<div class="col s12 m10">
<div class="input-field">
<input required id="flag-{{ challenge.alias }}" name="flag" type="text" />
<label for="flag-{{ challenge.alias }}">Flag</label>
</div>
</div>
<div class="col s12 m2">
<button class="btn waves-effect waves-light flag-submit" type="submit">Submit</button>
</div>
<input name="_csrf_token" type="hidden" value="{{ csrf_token() }}" />
</div>
</form><br />
{% endif %}
</li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}
{% block postscript %}
<script>
$(function() {
$("select").material_select();
});
</script>
{% if config.apisubmit %}
<script>
var challenges_open = JSON.parse(localStorage.getItem("challenges-open")) || {{ first_stage | tojson }};
Object.keys(challenges_open).forEach(function(el){
$(".collapsible-header#header-" + el).addClass("active");
});
$(".collapsible-header").on("click", function(){
var chall = $(this).data('challenge');
if(challenges_open.hasOwnProperty(chall)) {
delete challenges_open[chall];
} else {
challenges_open[chall] = true;
}
localStorage.setItem("challenges-open", JSON.stringify(challenges_open));
});
var state = $(".collapsible-header.active").length == 0;
function updateButton(){
if(state){
$("#toggleState").html("Expand all challenges");
} else {
$("#toggleState").html("Collapse all challenges");
}
}
updateButton(state);
function toggle() {
if(state) {
$(".collapsible-header").each(function(i, x){ $(x).hasClass("active") || $(x).click(); });
} else {
$(".collapsible-header").each(function(i, x){ $(x).hasClass("active") && $(x).click(); });
}
state = !state;
updateButton(state);
}
function filterCategories(t) {
var v = t.options[t.selectedIndex].value;
if(v == "*")
$(".challenge").show();
else {
$(".challenge[data-category=" + v + "]").show();
$(".challenge[data-category!=" + v + "]").hide();
}
}
$("#toggleState").on("click", function(e){
e.preventDefault();
toggle();
});
$(".stage-collapse").on("click", function(e){
e.preventDefault();
var stage = $(this).data('collapse');
var header_selector = ".challenge[data-stage=" + stage + "] .collapsible-header";
var state = $(header_selector + ".active").length != 0;
if(state)
$(header_selector).each(function(i, x){ $(x).hasClass("active") && $(x).click(); });
else
$(header_selector).each(function(i, x){ $(x).hasClass("active") || $(x).click(); });
});
$("form").submit(function(e) {
var id = $(this).data("challenge");
var flag = $("#flag-" + id).val();
console.log(id);
console.log(flag);
api.makeCall("/submit/" + id + ".json", {flag: flag, _csrf_token: "{{ csrf_token() }}"}, function(data) {
if(data.code) {
Materialize.toast(data.message, 4000);
}
else {
Materialize.toast("Flag accepted!", 4000);
$("#check-" + id).show();
$("#header-" + id).click();
$("#solves-" + id).html(data.solves);
}
});
return false;
});
</script>
{% endif %}
{% endblock %}