Created
May 18, 2019 05:20
-
-
Save lhchavez/49c48c7363ce497edbdbf40d575727f8 to your computer and use it in GitHub Desktop.
omegaUp falso
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import argparse | |
import cgi | |
import http.server | |
import itertools | |
import json | |
import os | |
import socketserver | |
import time | |
import urllib.parse | |
_SUBMISSIONS = 'submissions' | |
_CONTESTS = [ | |
{ | |
"alias": | |
"OMI2019DIA1", | |
"title": | |
"OMI 2019 - Día 1", | |
"problems": [ | |
{ | |
"alias": "OMI-2019-Resistencia", | |
"title": "Resistencia", | |
"languages": ["cat"], | |
}, | |
{ | |
"alias": "OMI-2019-Sumas", | |
"title": "La Loza de los Ravangers", | |
"languages": ["cpp11", "c"], | |
}, | |
{ | |
"alias": "OMI-2019-Spider-Man", | |
"title": "El amigable Hombre Araña", | |
"languages": ["cpp11", "c"], | |
}, | |
], | |
}, | |
{ | |
"alias": | |
"OMIP2019DIA1", | |
"title": | |
"OMIP 2019 - Día 1", | |
"problems": [ | |
{ | |
"alias": "OMIPS-2019-Comprimiendo", | |
"title": "Comprimiendo", | |
"languages": ["kp", "kj"], | |
}, | |
{ | |
"alias": "OMIPS-2019-Pistas", | |
"title": "Pistas", | |
"languages": ["kp", "kj"], | |
}, | |
{ | |
"alias": "OMIPS-2019-Guantelete", | |
"title": "El Guantelete del Infinito", | |
"languages": ["kp", "kj"], | |
}, | |
], | |
}, | |
{ | |
"alias": | |
"OMIS2019DIA1", | |
"title": | |
"OMIS 2019 - Día 1", | |
"problems": [ | |
{ | |
"alias": "OMIPS-2019-Comprimiendo", | |
"title": "Comprimiendo", | |
"languages": ["kp", "kj"], | |
}, | |
{ | |
"alias": "OMIPS-2019-Patron", | |
"title": "Repitiendo el Patrón", | |
"languages": ["kp", "kj"], | |
}, | |
{ | |
"alias": "OMIPS-2019-Guantelete", | |
"title": "El Guantelete del Infinito", | |
"languages": ["kp", "kj"], | |
}, | |
], | |
}, | |
] | |
_PROBLEMS = dict( | |
itertools.chain.from_iterable([(problem['alias'], problem['languages']) | |
for problem in contest['problems']] | |
for contest in _CONTESTS)) | |
_CONTENTS = '''<!DOCTYPE html> | |
<html> | |
<head> | |
<title>omegaUp falso</title> | |
<style> | |
body { | |
font-family: sans-serif; | |
} | |
</style> | |
<script type="text/json" id="contest-payload">%s</script> | |
</head> | |
<body> | |
<h1>omegaUp falso</h1> | |
%s | |
<form method="POST" action="/"> | |
<label>Concurso <select name="contest"><option value="">Elige tu concurso</option></select></label><br> | |
<label>Problema <select name="problem"></select></label><br> | |
<label>Lenguaje <select name="language"></select></label><br> | |
<textarea name="source" cols="80" rows="50"></textarea><br> | |
<button type="submit" disabled>Enviar</button> | |
</form> | |
<script type="text/javascript"> | |
const payload = JSON.parse(document.getElementById('contest-payload').innerText); | |
const contestSelect = document.querySelector('select[name="contest"]'); | |
const problemSelect = document.querySelector('select[name="problem"]'); | |
const languageSelect = document.querySelector('select[name="language"]'); | |
const sourceTextarea = document.querySelector('textarea'); | |
const submitButton = document.querySelector('button'); | |
const languageMapping = new Map([ | |
['cpp11', 'C++'], | |
['c', 'C'], | |
['cat', 'Sólo salida'], | |
['kp', 'Karel (Pascal)'], | |
['kj', 'Karel (Java)'], | |
]); | |
contestSelect.addEventListener('change', (ev) => { | |
while (problemSelect.firstChild) { | |
problemSelect.removeChild(problemSelect.firstChild); | |
} | |
for (let contest of payload) { | |
if (ev.target.value != contest.alias) continue; | |
for (let problem of contest.problems) { | |
const problemOption = document.createElement('option'); | |
problemOption.value = problem.alias; | |
problemOption.appendChild(document.createTextNode(problem.title)); | |
problemSelect.appendChild(problemOption); | |
} | |
problemSelect.dispatchEvent(new Event('change')); | |
} | |
}); | |
problemSelect.addEventListener('change', (ev) => { | |
while (languageSelect.firstChild) { | |
languageSelect.removeChild(languageSelect.firstChild); | |
} | |
for (let contest of payload) { | |
if (contestSelect.value != contest.alias) continue; | |
for (let problem of contest.problems) { | |
if (ev.target.value != problem.alias) continue; | |
for (let language of problem.languages) { | |
const languageOption = document.createElement('option'); | |
languageOption.value = language; | |
languageOption.appendChild(document.createTextNode(languageMapping.get(language))); | |
languageSelect.appendChild(languageOption); | |
} | |
} | |
} | |
}); | |
for (let contest of payload) { | |
const contestOption = document.createElement('option'); | |
contestOption.value = contest.alias; | |
contestOption.appendChild(document.createTextNode(contest.title)); | |
contestSelect.appendChild(contestOption); | |
} | |
function onContentUpdate() { | |
submitButton.disabled = sourceTextarea.value == '' || problemSelect.value == ''; | |
} | |
contestSelect.addEventListener('change', onContentUpdate); | |
problemSelect.addEventListener('change', onContentUpdate); | |
sourceTextarea.addEventListener('change', onContentUpdate); | |
</script> | |
</body> | |
</html> | |
''' | |
class Handler(http.server.BaseHTTPRequestHandler): | |
def do_GET(self): | |
if self.path != '/': | |
self.send_response(404) | |
return | |
self.send_response(200) | |
self.send_header('Content-Type', 'text/html; charset=utf-8') | |
self.send_header('Connection', 'close') | |
self.end_headers() | |
self.wfile.write( | |
(_CONTENTS % (json.dumps(_CONTESTS), '')).encode('utf-8')) | |
def do_POST(self): | |
if self.path != '/': | |
self.send_response(404) | |
return | |
ctype, pdict = cgi.parse_header(self.headers.get('content-type')) | |
if ctype != 'application/x-www-form-urlencoded': | |
self.log_error('bad content-type: %s', ctype) | |
self.send_response(400) | |
return | |
length = int(self.headers.get('content-length')) | |
postvars = dict((key.decode('utf-8'), value.decode('utf-8')) | |
for key, value in urllib.parse.parse_qsl( | |
self.rfile.read(length), encoding='utf-8')) | |
if not postvars.get('problem', ''): | |
self.log_error('missing problem in request: %s', postvars) | |
self.send_response(400) | |
return | |
if not postvars.get('language', ''): | |
self.log_error('missing language in request: %s', postvars) | |
self.send_response(400) | |
return | |
if not postvars.get('source', ''): | |
self.log_error('missing source in request: %s', postvars) | |
self.send_response(400) | |
return | |
if postvars['problem'] not in _PROBLEMS: | |
self.log_error('unknown problem: %s', postvars['problem']) | |
self.send_response(400) | |
return | |
if postvars['language'] not in _PROBLEMS[postvars['problem']]: | |
self.log_error('unsupported language %s for problem: %s', | |
postvars['language'], postvars['problem']) | |
self.send_response(400) | |
return | |
path = os.path.join( | |
_SUBMISSIONS, | |
'%s_%d_%s.%s' % (self.address_string(), int(time.time()), | |
postvars['problem'], postvars['language'])) | |
self.log_message('Writing submission to %s', path) | |
with open(path, 'x') as f: | |
f.write(postvars['source']) | |
self.send_response(200) | |
self.send_header('Content-Type', 'text/html; charset=utf-8') | |
self.send_header('Connection', 'close') | |
self.end_headers() | |
self.wfile.write( | |
(_CONTENTS % | |
(json.dumps(_CONTESTS), | |
'<h2>Problema enviado exitosamente!</h2>')).encode('utf-8')) | |
def _main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--port', type=int, default=80) | |
args = parser.parse_args() | |
os.makedirs(_SUBMISSIONS, exist_ok=True) | |
socketserver.TCPServer.allow_reuse_address = True | |
with socketserver.TCPServer(("", args.port), Handler) as httpd: | |
print("serving at port", args.port) | |
httpd.serve_forever() | |
if __name__ == '__main__': | |
_main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment