From ca07207d515ecdc8466bb5dc4203bbcfab1a04b1 Mon Sep 17 00:00:00 2001
From: prathamesh
Date: Sun, 12 Jan 2020 12:25:28 +0530
Subject: evaluator for r- Initial

---
 yaksh/models.py           |  1 +
 yaksh/r_code_evaluator.py | 96 +++++++++++++++++++++++++++++++++++++++++++++++
 yaksh/settings.py         |  4 ++
 3 files changed, 101 insertions(+)
 create mode 100644 yaksh/r_code_evaluator.py

diff --git a/yaksh/models.py b/yaksh/models.py
index 6881b4f..6edb9ea 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -46,6 +46,7 @@ languages = (
         ("cpp", "C++ Language"),
         ("java", "Java Language"),
         ("scilab", "Scilab"),
+        ("r", "R"),
     )
 
 question_types = (
diff --git a/yaksh/r_code_evaluator.py b/yaksh/r_code_evaluator.py
new file mode 100644
index 0000000..ca4c94a
--- /dev/null
+++ b/yaksh/r_code_evaluator.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+from __future__ import unicode_literals
+import os
+import subprocess
+import re
+
+# Local imports
+from .base_evaluator import BaseEvaluator
+from .file_utils import copy_files, delete_files
+
+
+class RCodeEvaluator(BaseEvaluator):
+    """Tests the R code obtained from Code Server"""
+    def __init__(self, metadata, test_case_data):
+        self.files = []
+        self.submit_code_path = ""
+        self.test_code_path = ""
+        # Set metadata values
+        self.user_answer = metadata.get('user_answer')
+        self.file_paths = metadata.get('file_paths')
+        self.partial_grading = metadata.get('partial_grading')
+
+        # Set test case data values
+        self.test_case = test_case_data.get('test_case')
+        self.weight = test_case_data.get('weight')
+
+    def teardown(self):
+        # Delete the created file.
+        if os.path.exists(self.submit_code_path):
+            os.remove(self.submit_code_path)
+        if os.path.exists(self.test_code_path):
+            os.remove(self.test_code_path)
+        if self.files:
+            delete_files(self.files)
+
+    def check_code(self):
+        self.submit_code_path = self.create_submit_code_file('function.r')
+        self.test_code_path = self.create_submit_code_file('main.r')
+        if self.file_paths:
+            self.files = copy_files(self.file_paths)
+        clean_ref_path = self.test_code_path
+        self.user_answer, terminate_commands = \
+            self._remove_r_quit(self.user_answer.lstrip())
+
+        success = False
+        mark_fraction = 0.0
+        self.write_to_submit_code_file(self.submit_code_path, self.user_answer)
+        self.write_to_submit_code_file(self.test_code_path, self.test_case)
+        # Throw message if there are commmands that terminates scilab
+        add_err = ""
+        if terminate_commands:
+            add_err = "Please do not use quit() in your\
+                        code.\n Otherwise your code will not be evaluated\
+                        correctly.\n"
+
+        cmd = 'Rscript main.r'
+        ret = self._run_command(cmd, shell=True, stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE
+                                )
+        proc, stdout, stderr = ret
+
+        if stderr is '':
+            # Clean output
+            stdout = self._strip_output(stdout)
+            if proc.returncode == 31:
+                success, err = True, None
+                mark_fraction = 1.0 if self.partial_grading else 0.0
+            else:
+                err = add_err + stdout
+        else:
+            err = add_err + stderr
+
+        return success, err, mark_fraction
+
+    def _remove_r_quit(self, string):
+        """
+            Removes quit from the R code
+        """
+        new_string = ""
+        terminate_commands = False
+        for line in string.splitlines():
+            new_line = re.sub(r"quit.*$", "", line)
+            if line != new_line:
+                terminate_commands = True
+            new_string = new_string + '\n' + new_line
+        return new_string, terminate_commands
+
+    def _strip_output(self, out):
+        """
+            Cleans whitespace from the output
+        """
+        strip_out = "Message"
+        for l in out.split('\n'):
+            if l.strip():
+                strip_out = strip_out+"\n"+l.strip()
+        return strip_out + out
diff --git a/yaksh/settings.py b/yaksh/settings.py
index 9e9597d..7b42298 100644
--- a/yaksh/settings.py
+++ b/yaksh/settings.py
@@ -55,4 +55,8 @@ code_evaluators = {
         "standardtestcase": "yaksh.scilab_code_evaluator.ScilabCodeEvaluator",
         "hooktestcase": "yaksh.hook_evaluator.HookEvaluator"
         },
+    "r": {
+        "standardtestcase": "yaksh.r_code_evaluator.RCodeEvaluator",
+        "hooktestcase": "yaksh.hook_evaluator.HookEvaluator"
+        },
 }
-- 
cgit