rendered paste bodyIndex: evaluator/settings.py
===================================================================
--- evaluator/settings.py (revision 0)
+++ evaluator/settings.py (revision 0)
@@ -0,0 +1,13 @@
+# '%' is not allowed in the compilation string.
+# Format Strings:
+# %i --- Input File Name
+# %o --- Ouput File Name
+# %u --- User Name (who submitted the code)
+# %q --- Question Name
+
+
+C_COMPILE_STR = 'gcc -lm \'%i\' -o \'%o\''
+CPP_COMPILE_STR = 'g++ -lm \%i\' -o \'%o\''
+JAVA_COMPILE_STR = 'javac \'%i\''
+
+WORK_DIR = 'evaluator/work_files'
Index: evaluator/main.py
===================================================================
--- evaluator/main.py (revision 0)
+++ evaluator/main.py (revision 0)
@@ -0,0 +1,193 @@
+import sys
+import os
+import time
+import commands
+import threading
+import subprocess
+import tempfile
+import time
+try:
+ from settings import *
+ from server.models import Attempt, ToBeEvaluated, BeingEvaluated
+except ImportError:
+ C_COMPILE_STR = 'gcc -lm \'%i\' -o \'%o\''
+ CPP_COMPILE_STR = 'g++ -lm \%i\' -o \'%o\''
+ JAVA_COMPILE_STR = 'javac \'%i\''
+ WORK_DIR = 'evaluator/work_files'
+
+
+class EvaluatorError (Exception):
+ def __init__ (self, error, value=''):
+ self.value = value
+ self.error = error
+
+ def __str__ (self):
+ return repr (self.value)
+
+
+class Evaluator ():
+ def __str__ (self):
+ raise NotImplementedError ('Must be Overridden')
+
+ def compile (self, code_file, input_file):
+ raise NotImplementedError ('Must be Overridden')
+
+ def run (self, exec_file):
+ raise NotImplementedError ('Must be Overridden')
+
+ def save_file (self, file_path, contents):
+ try:
+ if not os.path.exists (WORK_DIR):
+ os.mkdir (WORK_DIR)
+
+ path_cont = []
+ path_split = lambda (x): x != '' and \
+ path_split(os.path.split(x)[0]) or \
+ path_cont.append (os.path.basename(x))
+ path_cont = path_cont[1:-1]
+ path = WORKDIR
+ for cont in path_cont:
+ path = os.path.join (path, cont)
+ if not os.path.exists (path):
+ os.mkdir (path)
+
+ open_file = open (os.path.join (WORK_DIR, file_path), 'w')
+ open_file.write (contents)
+ open_file.close()
+ except OSError, IOError:
+ raise
+ return file_name
+
+ def check (self, attempt, output):
+ raise NotImplementedError ('Must be Overridden')
+
+ def evaluate (self, attempt):
+ # Save the File
+ save_loc = os.path.join (attemp.user.username, attempt.user.filename)
+ code_file = self.save_file (save_loc, attempt.code)
+
+ # Compile the File
+ exec_file = self.compile (code_file, attempt.question.test_input)
+
+ # Execute the file for preset input
+ output = self.run (exec_file)
+
+ # Match the output to expected output
+ return self.check (attempt, output)
+
+
+class C_Evaluator (Evaluator):
+ num_out = 0
+ status = 0
+ output = ''
+ def __init__ (self):
+ threading.Thread.__init__ (self)
+ self.compile_cmd = C_COMPILE_STR
+
+
+ def __str__ (self):
+ return 'C Evaluator'
+
+ def compile (self, code_file):
+ output_file = code_file # Change this value to change output file name
+ # replace the code with the object file
+ cmd = self.compile_cmd.replace ('%i',code_file).replace('%o',output_file)
+
+ (status, output) = commands.getstatusoutput (cmd)
+ if status != 0:
+ raise EvaluatorError ('Compiler Error', output)
+ else:
+ return output_file
+
+ def run (self, exec_file, input_file):
+ output_file = tempfile.NameTemporaryFile ()
+ kws = {}
+ cmd = exec_file + ' < ' + input_file + ' > ' + output_file.name
+ start_time = time.time()
+ p = subproces.Popen (cmd, **kws)
+ # (status, output) = commands.getstatusoutput (exec_file + ' < ' \
+ # + input_file)
+ while True:
+ if time.time() - start_time >= 5:
+ raise EvalutorError ('Time Limit Expired')
+ elif p.poll() != None:
+ break
+ time.sleep (0.5)
+ if p.returncode != 0:
+ raise EvaluatorError ('Run-Time Error')
+ else:
+ return output
+
+
+class CPP_Evaluator (Evaluator):
+ def __str__ (self):
+ return 'C++ Evaluator'
+ def evaluate (self, attempt):
+ pass
+
+class Java_Evaluator (Evaluator):
+ def __str__ (self):
+ return 'Java Evaluator'
+ def evaluate (self, attempt):
+ pass
+
+class PythonEvaluator (Evaluator):
+ def __str__ (self):
+ return 'Python Evaluator'
+ def evaluate (self, attempt):
+ pass
+
+class Client (thread.Threading):
+ """ The Evaluator will evaluate and update the status """
+ evaluators = {'c':C_Evaluator, 'c++':CPP_Evaluator,
+ 'java':Java_Evaluator, 'python':Python_Evaluator}
+
+ def __init__ (self):
+ pass
+
+ def queue_not_empty (self):
+ """ Checks if the ToBeEvaluated queue is empty or not """
+ if ToBeEvaluated.objects.count > 0:
+ return True
+ return False
+
+ def dequeue_attempts (self):
+ """ Returns an attempt from the ToBeEvaluated queue based on priority
+ algorithms or return None if queue is empty """
+ try:
+ attempt = ToBeEvaluated.objects.all()[0]
+ to_be_eval = BeingEvaluated(attempt=attempt.attempt)
+ attempt.delete()
+ return to_be_eval
+ except IndexError:
+ return None
+
+ def get_attempt (self):
+ """ Keep polling the ToBeEvaluated queue until an attempt to be
+ evaluated is obtained """
+ while True:
+ if (self.queue_not_empty()):
+ return self.dequeue_attempts()
+ time.sleep (1)
+
+ def evaluate (self, attempt):
+ """ Evaluate the attempt and return the ruling :-) """
+ lang = attempt.language.lang.lower()
+ # first list special case languages whose names cannot be used for
+ # function names in python
+ try:
+ evaluator = self.evaluators[lang](attempt)
+ except KeyError:
+ raise NotImplementedError ('Language '+lang+' not supported')
+ result = evaluator.evaluate()
+
+ def run (self):
+ print 'Evaluator Started'
+ while True:
+ attempt = self.get_attempt ()
+ if attempt == None:
+ continue
+ # evalute the attempt
+ return_value = self.evaluate (attempt.attempt)
+ attempt.delete ()
+ return return_value
Index: server/models.py
===================================================================
--- server/models.py (revision 13)
+++ server/models.py (working copy)
@@ -7,6 +7,7 @@
# TODO: Change this to self.name and have special method for activation key
def __str__(self):
return self.user.get_full_name()
+
score = models.PositiveIntegerField(default=0)
activation_key = models.CharField(maxlength=40)
key_expires = models.DateTimeField()
@@ -17,6 +18,7 @@
""" Contains the question content and path to evaluators and test cases """
def __str__(self):
return self.name
+
name = models.CharField(maxlength=32)
text = models.TextField()
test_input = models.FileField(upload_to = 'hidden/evaluators/testCases')
@@ -28,13 +30,15 @@
class Language(models.Model):
def __str__(self):
return self.compiler
- compiler = models.CharField(maxlength=32)
+
+ lang = models.CharField(maxlength=32)
class Admin: pass
class Attempt(models.Model):
""" Contains Attempt Information """
def __str__(self):
- return self.user.user.username + ' :' + self.question.name
+ return self.user.user.username + ' :' + self.question.name
+
user = models.ForeignKey(UserProfile)
question = models.ForeignKey(Question)
result = models.BooleanField()
@@ -43,5 +47,8 @@
time_of_submit = models.DateTimeField(auto_now_add=True)
class Admin: pass
-class Pending(models.Model):
+class ToBeEvaluated(models.Model):
attempt = models.ForeignKey(Attempt)
+
+class BeingEvaluated (models.Model):
+ attempt = models.ForeignKey (Attempt)
Index: settings.py
===================================================================
--- settings.py (revision 13)
+++ settings.py (working copy)
@@ -86,5 +86,9 @@
CONTEST_NAME = 'Hackzor'
# replace with the email of your own contest
CONTEST_EMAIL = 'hackzor@googlegroups.com'
+
# replace with the url of your own contest
CONTEST_URL = '192.168.1.2'
+
+# Supported Languages for the code submission
+SUPPORTED_LANGS = ['C','C++','Java','Python','Ruby']
Index: ChangeLog
===================================================================
--- ChangeLog (revision 13)
+++ ChangeLog (working copy)
@@ -6,6 +6,8 @@
* settings.py (CONTEST_NAME, CONTEST_EMAIL): Added generic support
for Contest Name and Email ID
+ (SUPPORTED_LANGS): Added SUPPORTED_LANGS, which should be used to
+ populate the language field in code submission
2006-10-16 Ravi Shankar <ravehanker@gmail.com>
* urls.py(urlpatterns): Added default home page