LICENSE => 'AGPL_3',
SIGN => 1,
clean => {
- FILES => 'static/css/ static/js.js static/js.js.gz css/logos.css static/logos.png static/js.map static/js/'
- FILES => 'static/css/ static/js/'
++ FILES => 'static/css/ static/js/ css/logos.css static/logos.png'
},
BUILD_REQUIRES => {
qw/CSS::Minifier::XS 0
+ CSS::SpriteMaker 0
File::Slurp 0
- JavaScript::Minifier::XS 0
Test::MockTime 0
Test::More 0
Test::WWW::Mechanize::PSGI 0/,
display: none !important;
}
-td.user, td.owner {
+td.user, td.owner, .break-all {
word-break: break-all;
}
- ul.list-inline {
- display: inline-block;
+ #themes {
+ margin-left: 0;
+ }
+
+ #themes:before {
+ content: " Themes: ";
-}
+}
- (function(){
- 'use strict';
-
- $( document ).ready(function(){
- if(window.innerWidth >= 768)
- return;
- $('#title').before('<div class="text-center">Tap title to toggle menu</div>');
- $('nav').addClass('hidden');
- $('#title,#logo').on('click', function () {
- $('nav').toggleClass('hidden');
- });
- });
- })();
+ $(function(){
+ if(window.innerWidth >= 768)
+ return;
+ $('#title')[0].insertAdjacentHTML('beforebegin', '<div class="text-center">Tap title to toggle menu</div>');
+ $('nav')[0].classList.add('hidden');
- $('#title').on('click', () => $('nav')[0].classList.toggle('hidden'));
++ $('#title,#logo').on('click', () => $('nav')[0].classList.toggle('hidden'));
+ });
--- /dev/null
- (function(){
- 'use strict';
-
- $( document ).ready(function(){
- $('#sponsors').detach().appendTo($('#sidebar'));
- });
- })();
++$(() => $('#sidebar')[0].appendChild($('#sponsors')[0]));
- (function(){
- 'use strict';
+ const NAVS = {
+ home: /^\/$/,
+ pb: /^\/(?:pb|sol)\//,
+ ct: /^\/(?:ct|st|ed)\//,
+ log: /^\/log\//,
+ us: /^\/us\//,
+ account: /^\/account$/,
+ contribute: /^\/contribute$/,
++ about: /^\/about$/,
+ };
- var NAVS = {
- 'home': /^\/$/,
- 'pb': /^\/(?:pb|sol)\//,
- 'ct': /^\/(?:ct|st|ed)\//,
- 'log': /^\/log\//,
- 'us': /^\/us\//,
- 'account': /^\/account$/,
- 'contribute': /^\/contribute$/,
- 'about': /^\/about$/,
- };
-
- $( document ).ready(function(){
- var path = location.pathname;
- for (var nav in NAVS)
- if(path.match(NAVS[nav])) {
- $('#nav-' + nav).addClass('active');
- break;
- }
- });
- })();
+ $(function(){
+ let path = location.pathname;
+ for (let nav in NAVS)
+ if(path.match(NAVS[nav]))
+ $('#nav-' + nav)[0].classList.add('active');
+ });
- (function(){
- 'use strict';
- function set_style(name){
- $('link[rel~="stylesheet"]').prop('disabled', true);
- $('link[title="' + name + '"]').prop('disabled', false);
- localStorage.setItem("theme", name);
- $(document).ready(function() {
- if(name == 'slate' || name == 'cyborg')
- $('.logo').removeClass('logo-light');
- else
- $('.logo').addClass('logo-light');
- });
- }
-
- var selector;
-
- function add_themelink(theme, text) {
- var link = $('<a role="button">' + text + '</a>');
- link.appendTo(selector.find('ul')).wrap('<li>').on('click', function () { set_style(theme) });
- }
-
- $( document ).ready(function() {
- selector = $('<div>Themes: <ul class="list-inline"></ul></div>');
- add_themelink('cyborg', 'Black');
- add_themelink('slate', 'Grey');
- add_themelink('readable', 'White');
- $('#sidebar').prepend(selector);
+ function set_style(name){
+ $('link[rel~="stylesheet"]').each(e => e.disabled = true);
+ $('link[title="' + name + '"]')[0].disabled = false;
+ localStorage.setItem("theme", name);
++ $(function() {
++ if(name == 'slate' || name == 'cyborg')
++ $('.logo').each(e => e.classList.remove('logo-light'));
++ else
++ $('.logo').each(e => e.classList.add('logo-light'));
+ });
+ }
+
+ $(function() {
+ var theme_ul = '<ul class="list-inline" id="themes">' +
+ '<li><a role="button" data-theme="cyborg">Black</a>' +
+ '<li><a role="button" data-theme="slate">Grey</a>' +
+ '<li><a role="button" data-theme="readable">White</a></ul>';
+ var sidebar = $('#sidebar')[0];
+ sidebar.insertBefore(m(theme_ul), sidebar.firstChild);
+ $('#themes a').on('click', e => set_style(e.target.dataset.theme));
+ });
- var theme = localStorage.getItem("theme");
- if(theme) {
- if(theme == "cerulean" || theme == "cosmo")
- theme = "readable";
- set_style(theme);
- }
- })();
+ let theme = localStorage.getItem("theme");
+ if(theme) {
+ if(theme == "cerulean" || theme == "cosmo")
+ theme = "readable";
+ set_style(theme);
+ }
--- /dev/null
- (function(){
- 'use strict';
-
- $( document ).ready(function() {
- $('#webchat').prependTo('#sidebar');
- });
- })();
++$(() => $('#sidebar')[0].insertBefore($('#webchat')[0], $('#sidebar')[0].firstChild));
$tree->as_HTML(undef, undef, $optional_end_tags);
}
+my $logo = read_file 'mclogo.svg';
+$logo =~ y/\n//d;
+$logo =~ s/(\s+)/ /g;
+
sub process_skel {
my ($tree, %args) = @_;
+ $tree->fid('logo')->replace_with(HTML::Element::Library::super_literal $logo);
$tree->content_handler(
title => $args{title},
content => literal $args{meat});
if ($args{contest_stop}) {
$tree->fid('solution')->detach;
$tree->fid('solution_modal')->detach;
- my $score = $tree->fid('score');
- $score->attr('data-start' => $args{open_time});
- $score->attr('data-stop' => $args{contest_stop});
- $score->attr('data-value' => $args{value});
+ $tree->fid('score')->replace_content($args{value});
$tree->fid('countdown')->attr('data-stop' => $args{contest_stop});
} else {
$tree->fid('job_log')->edit_href(sub{$_ .= "&private=$args{private}"}) if $args{private};
$tree->fid('solution')->detach unless $args{solution};
$_->detach for $tree->fclass('rc'); # requires contest
- $tree->fid('solution_modal')->fclass('modal-body')->replace_content(literal $args{solution});
+ $tree->fid('solution_modal')->replace_content(literal $args{solution});
}
if ($args{cansubmit}) {
$tree->fid('nosubmit')->detach;
use warnings;
use CSS::Minifier::XS qw//;
- use JavaScript::Minifier::XS qw//;
+use CSS::SpriteMaker;
+ use Digest::SHA qw/sha256_base64/;
use IO::Compress::Gzip qw/gzip/;
- use File::Slurp qw/read_file write_file/;
+ use File::Slurp qw/read_file write_file edit_file_lines/;
mkdir 'static';
mkdir 'static/css';
+ mkdir 'static/js';
+sub make_sprite {
+ my $maker = Local::CSS::SpriteMaker->new(
+ css_class_prefix => 'logo-',
+ rc_override_classname => sub {
+ my ($name) = @_;
+ $name =~ s/-light/.logo-light/r;
+ }
+ );
+
+ $maker->make_sprite(
+ source_images => ['logos/'],
+ target_file => 'static/logos.png',
+ add_extra_padding => 10,
+ );
+
+ $maker->print_css(
+ filename => 'css/logos.css',
+ sprite_filename => '/static/logos.png',
+ );
+
+ system 'pngnq-s9', '-s1', 'static/logos.png';
+ system 'optipng', '-o7', '-zm1-9', 'static/logos-nq8.png';
+ rename 'static/logos-nq8.png', 'static/logos.png';
+}
+
sub gzip_file {
my ($file) = @_;
gzip $file => "$file.gz", -Level => 9, Minimal => 1;
}
sub make_js {
- if (-f 'compiler.jar') {
- system java => -jar => 'compiler.jar', qw,-O SIMPLE --create_source_map static/js.map --js_output_file static/js.js --language_in ECMASCRIPT5_STRICT --source_map_location_mapping js/|/static/js/,, <js/*>;
- my $js = read_file 'static/js.js';
- write_file 'static/js.js', '//# sourceMappingURL=/static/js.map', "\n", $js;
- system 'cp', '-rp', 'js', 'static/';
- } else {
- my $js;
- $js .= read_file $_ for <js/*.js>;
- write_file 'static/js.js', JavaScript::Minifier::XS::minify $js;
- }
- gzip_file 'static/js.js';
+ system java => -jar => 'compiler.jar', qw,-O SIMPLE --create_source_map static/js/js.map --js_output_file static/js/all.js --language_in ECMASCRIPT6_STRICT --language_out ECMASCRIPT5_STRICT --source_map_location_mapping js/|/static/js/,, <js/*>;
+ my $js = read_file 'static/js/all.js';
+ write_file 'static/js/all.js', '//# sourceMappingURL=/static/js/js.map', "\n", $js;
+ system 'cp', '-rp', 'js', 'static/';
+ gzip_file 'static/js/all.js';
}
+my $sprite_mtime = -M 'static/logos.png' // 0;
+for (<logos/*>) {
+ if (!$sprite_mtime || $sprite_mtime > -M) {
+ make_sprite;
+ last
+ }
+}
+
my $css_mtime = -M 'static/css/slate.css' // 0;
for (<css/*>, <css/themes/*>) {
if (!$css_mtime || $css_mtime > -M) {
}
}
-} 'tmpl/skel.en'
+ edit_file_lines {
+ my ($file) = m,(static.*\.(?:css|js)),;
+ return unless $file;
+ my $hash = sha256_base64 scalar read_file $file;
+ s/integrity=".*"/integrity="sha256-$hash="/;
++} 'tmpl/skel.en';
++
+package
+ Local::CSS::SpriteMaker;
+
+use parent qw/CSS::SpriteMaker/;
+
+sub _get_stylesheet_string {
+ my $self = shift;
+ my @ret = split "\n", $self->SUPER::_get_stylesheet_string(@_);
+ shift @ret;
+ @ret = sort @ret;
+ unshift @ret, <<EOF;
+a.logo {
+ background-image: url("/static/logos.png");
+ background-repeat: no-repeat;
+ display: inline-block;
+ vertical-align: middle;
+}
+EOF
+ join "\n", @ret;
+}
<dt>Owner</dt> <dd id="owner">owner</dd>
<dt>Level</dt> <dd id="level">Easy</dd>
<dt>Time limit (seconds)</dt> <dd smap="timeout">1</dd>
-<dt class="rc reqjs">Score</dt> <dd id="score" class="timer reqjs rc" data-start="..." data-stop="..." data-value="100">50</dd>
+<dt class="rc reqjs">Score</dt> <dd id="score" class="rc">50</dd>
<dt class="rc reqjs">Contest ends in</dt> <dd id="countdown" class="timer reqjs rc" data-stop="...">01:30</dd>
</dl>
<a href="/log/?problem=problem_id" id="job_log">Job log</a><br>
- <a href="/sol/problem_id" id="solution" data-toggle="modal" data-target="#solution_modal">Solution</a>
+ <a href="/sol/problem_id" id="solution">Solution</a>
<h1 static="no">Submit solution</h1>
<div class="form-group"><label for="prog">File:</label><input id="prog" name="prog" type="file"></div>
<div class="form-group"><label for="source_code">Source code:</label> <textarea class="form-control" id="source_code" name="source_code"></textarea></div>
<div class="form-group"><label for="prog_format">File format:</label><select id="prog_format" name="prog_format" class="form-control" required>
-<option value="C">C (gcc)</option>
-<option value="CPP" selected>C++ (g++)</option>
-<option value="GCCGO">Go (gccgo)</option>
-<option value="GOLANG">Go (gc)</option>
+<option value="C">C11 (gcc 4.7.2)</option>
+<option value="CPP" selected>C++11 (g++ 4.7.2)</option>
+<option value="GCCGO">Go (gccgo 4.7.2)</option>
+<option value="GOLANG">Go (gc 1.0.2)</option>
<option value="GOLFSCRIPT">Golfscript (golfscript.rb)</option>
-<option value="HASKELL">Haskell (ghc)</option>
-<option value="JAVA">Java (javac)</option>
-<option value="PASCAL">Pascal (fpc)</option>
-<option value="PERL">Perl (perl)</option>
-<option value="PYTHON">Python (python)</option>
-<option value="RUBY">Ruby (ruby)</option>
-<option value="SBCL">Common Lisp (sbcl)</option>
+<option value="HASKELL">Haskell (ghc 7.4.1)</option>
+<option value="JAVA">Java (openjdk 7u75)</option>
+<option value="PASCAL">Pascal (fpc 2.6.0)</option>
+<option value="PERL">Perl (perl 5.14.2)</option>
+<option value="PYTHON">Python (python 2.7.3)</option>
+<option value="RUBY">Ruby (ruby 2.2.1)</option>
+<option value="SBCL">Common Lisp (sbcl 1.0.57)</option>
</select></div>
<input type="submit" value="Submit job" class="btn btn-primary">
</div>
</div>
- <div class="modal fade" id="solution_modal" role="dialog" aria-hidden="true" tabindex="-1">
- <div class="modal-dialog modal-lg">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
- <h4 class="modal-title">Solution</h4>
- </div>
- <div class="modal-body"></div>
- </div>
- </div>
- </div>
+ <div class="backdrop"></div>
+ <div id="solution_modal" class="hidden modal"></div>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link href="/static/css/cyborg.css" title="cyborg" rel="stylesheet" integrity="x">
-<link href="/static/css/slate.css" title="slate" rel="alternate stylesheet" integrity="x">
+<link href="/static/favicon.png" rel="shortcut icon">
- <link href="/static/css/cyborg.css" title="cyborg" rel="alternate stylesheet">
- <link href="/static/css/slate.css" title="slate" rel="stylesheet">
- <link href="/static/css/readable.css" title="readable" rel="alternate stylesheet">
- <script src="/static/js.js" type="text/javascript" async defer></script>
++<link href="/static/css/cyborg.css" title="cyborg" rel="alternate stylesheet" integrity="x">
++<link href="/static/css/slate.css" title="slate" rel="stylesheet" integrity="x">
+ <link href="/static/css/readable.css" title="readable" rel="alternate stylesheet" integrity="x">
+ <script src="/static/js/all.js" type="text/javascript" async defer integrity="x"></script>
<body>
<div class="container-fluid">
<nav role="navigation">
<ul class="nav nav-pills nav-justified">
-<li id="nav-home"><a href="/">Gruntmaster 6000</a>
+<li id="nav-home"><a href="/">Home</a>
<li id="nav-pb"><a href="/pb/">Problems</a>
<li id="nav-ct"><a href="/ct/">Contests</a>
<li id="nav-log"><a href="/log/">Job log</a>
<li id="nav-us"><a href="/us/">Users</a>
<li id="nav-account" static="no"><a href="/account">Account</a>
+<li id="nav-about"><a href="/about">About / Help</a>
<li id="nav-contribute"><a href="/contribute">Contribute!</a>
</ul>
</nav>
+<div id="logo"></div>
<h1 id="title">TITLE</h1>
-<div id="static" class="alert alert-info" static="yes">This is a static version of Gruntmaster 6000.</div>
+<div id="static" class="alert alert-info" static="yes">This is a static version of MindCoding, useful when the <a class="alert-link" href="https://mindcoding.ro/">regular version</a> is overloaded.</div>
<div id="result"></div>
<main id="content">Content goes here</main>
+<div id="webchat"><a href="http://webchat.oftc.net/?channels=%23mindcoding" target="_blank">Webchat</a></div>
+
+<div id="sponsors">
+<h3>Official sponsors</h3>
+<a class="logo logo-emag" href="http://www.fundatiaemag.ro/"></a>
+<a class="logo logo-easyhost" href="http://ro.easyhost.com/"></a>
+<a class="logo logo-takeofflabs" href="http://www.takeofflabs.com/"></a>
+<a class="logo logo-bigstep" href="http://www.bigstep.com/"></a>
+<a class="logo logo-yardi" href="https://www.facebook.com/YardiRomania"></a>
+<a class="logo logo-bosch" href="http://www.bosch.com.ro/"></a>
+<a class="logo logo-endava" href="http://www.endava.com/"></a>
+</div>
+
<footer>
-Dilmom: Why don't you call your product the Gruntmaster 6000?<br>
-Dilbert: What kind of product do you see when you imagine a Gruntmaster 6000?<br>
-Dilmom: Well, it's a stripped-down version of the Gruntmaster 9000, of course. But it's software-upgradeable.
+<div class="row">
+<div class="col-md-6 column text-center">
+<a class="logo logo-hermes" href="http://www.societatea-hermes.ro"></a>
+</div>
+
+<div class="col-md-6 column text-center">
+<a class="logo logo-facebook" href="http://www.facebook.com/mindcodingcluj"></a>
+</div>
+</div>
+
+<h3>Partners</h3>
+<a href="https://www.facebook.com/spyhce?fref=ts" class="logo logo-spyhce"></a>
+<a href="https://www.facebook.com/telenav?fref=ts" class="logo logo-telenav"></a>
+<h3>Media Partners</h3>
+<a href="http://cs.ubbcluj.ro" class="logo logo-csf"></a>
+<a href="http://www.uniunea.ro" class="logo logo-usr"></a>
+<a href="http://www.coscj.ro" class="logo logo-cos"></a>
+<a href="http://www.cluj2015.ro/romana" class="logo logo-eyc"></a>
</footer>