All pastes #215530 Raw Edit

Casanova

public text v1 · immutable
#215530 ·published 2006-10-22 17:52 UTC
rendered paste body
Index: 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