diff options
Diffstat (limited to 'Smarker')
| -rw-r--r-- | Smarker/assessments.py | 28 | ||||
| -rw-r--r-- | Smarker/database.py | 34 | ||||
| -rw-r--r-- | Smarker/reflect.py | 2 | ||||
| -rw-r--r-- | Smarker/requirements.txt | 1 | ||||
| -rw-r--r-- | Smarker/templates/tex.jinja2 | 15 | ||||
| -rw-r--r-- | Smarker/templates/text.jinja2 | bin | 28 -> 0 bytes | 
6 files changed, 73 insertions, 7 deletions
| diff --git a/Smarker/assessments.py b/Smarker/assessments.py index d5c8daf..a6c4df8 100644 --- a/Smarker/assessments.py +++ b/Smarker/assessments.py @@ -1,11 +1,29 @@  import misc_classes  import configparser  import jinja_helpers +import pycode_similar +import operator  import database  import argparse +import tempfile  import yaml  import os +def generate_plagarism_report(codes): +    for file_name, codes in codes.items(): +        with tempfile.TemporaryDirectory() as td: +            un_added_student_nos = {i[0] for i in codes.keys()} +            # print(un_added_student_nos) +            for k, v in sorted(codes.keys(), key=operator.itemgetter(0, 1), reverse=True): +                if k in un_added_student_nos: +                    with open(os.path.join(td, "%i.py" % k), "w") as f: +                        f.write(codes[(k, v)]) +                     +                    # print("Written %s at %s" % (k, v)) +                    un_added_student_nos.remove(k) +            input("%s..." % td) +            print(pycode_similar.detect(os.listdir(td))) +  if __name__ == "__main__":      config = configparser.ConfigParser()      config.read(os.path.join(os.path.split(__file__)[0], "smarker.conf")) @@ -47,6 +65,13 @@ if __name__ == "__main__":          help = "Add a student in the form e.g. 123456789,Eden,Attenborough,E.Attenborough@uea.ac.uk",          required = False      ) +    parser.add_argument( +        "-p", "--plagarism_report", +        action = misc_classes.EnvDefault, +        envvar = "plagarism_report", +        help = "Generate a plagarism report for the given assessment", +        required = False +    )      for option in config.options("mysql"):          parser.add_argument( @@ -91,6 +116,9 @@ if __name__ == "__main__":              print("Added student %s" % name) +        if args["plagarism_report"] is not None: +            generate_plagarism_report(db.get_submission_codes(args["plagarism_report"])) +          # print(db.get_assessment_yaml("CMP-4009B-2020-A2")) diff --git a/Smarker/database.py b/Smarker/database.py index 38af6a7..c1b1df0 100644 --- a/Smarker/database.py +++ b/Smarker/database.py @@ -111,6 +111,8 @@ class SmarkerDatabase:      def remove_assessment(self, name):          with self.__connection.cursor() as cursor: +            cursor.execute("DELETE FROM submitted_files WHERE submission_id IN (SELECT submission_id FROM submissions WHERE assessment_name = %s);", (name, )) +            cursor.execute("DELETE FROM submissions WHERE assessment_name = %s;", (name, ))              cursor.execute("DELETE FROM assessment_file WHERE assessment_name = %s;", (name, ))              cursor.execute("DELETE FROM assessment WHERE assessment_name = %s;", (name, ))          self.__connection.commit() @@ -153,3 +155,35 @@ class SmarkerDatabase:                      submission_id, file_name, file_contents                  ))          self.__connection.commit() + +    def get_submission_codes(self, assessment_name): +        out = {} +        with self.__connection.cursor() as cursor: +            cursor.execute("SELECT file_id, file_name FROM assessment_file WHERE assessment_name = %s;", (assessment_name, )) +            for file_id, file_name in cursor.fetchall(): +                out[file_name] = {} + +                cursor.execute(""" +                SELECT  +                    submitted_files.file_text,  +                    submissions.student_no,  +                    submissions.submission_dt  +                FROM submitted_files  +                INNER JOIN submissions  +                ON submissions.submission_id = submitted_files.submission_id  +                WHERE submitted_files.file_id = %s; +                """, (file_id, )) + +                for code, student_no, dt in cursor.fetchall(): +                    out[file_name][(int(student_no), dt)] = code +        return out + +    def get_most_recent_submission_report(self, assessment_name): +        with self.__connection.cursor() as cursor: +            cursor.execute("SELECT MAX(submission_id), student_no FROM submissions WHERE assessment_name = %s GROUP BY student_no;", (assessment_name, )) +            return [(int(i[0]), int(i[1]), yaml.safe_load(i[2])) for i in cursor.fetchall()] +                 + +if __name__ == "__main__": +    with SmarkerDatabase(host = "vps.eda.gay", user="root", passwd=input("Input password: "), db="Smarker", port=3307) as db: +        print(db.get_most_recent_submission_report("simple_assessment")) diff --git a/Smarker/reflect.py b/Smarker/reflect.py index 2a1f552..44d69de 100644 --- a/Smarker/reflect.py +++ b/Smarker/reflect.py @@ -376,7 +376,7 @@ def gen_reflection_report(client_code_path, assessment_struct, student_no, confi                                  lines = lines.replace("\r", "")                                  matches = {}                                  for regex_ in contents["regexes"]: -                                    matches[regex_] = re.findall(regex_, lines) +                                    matches[regex_] = re.findall(str(regex_), lines)                                  required_files_features["run"][j][cmd]["regexes"] = matches                                  required_files_features["run"][j][cmd]["full_output"] = lines diff --git a/Smarker/requirements.txt b/Smarker/requirements.txt index 944b77a..a8fef17 100644 --- a/Smarker/requirements.txt +++ b/Smarker/requirements.txt @@ -9,3 +9,4 @@ junit2html  pdfkit
  lxml
  pymysql
 +pycode_similar
 diff --git a/Smarker/templates/tex.jinja2 b/Smarker/templates/tex.jinja2 index eaa7db7..5985875 100644 --- a/Smarker/templates/tex.jinja2 +++ b/Smarker/templates/tex.jinja2 @@ -57,7 +57,7 @@ breaklines=true  \newcommand{\errortext}[1]{\textcolor{red}{\textbf{#1}}}
  \author{((( student_no )))}
 -\title{((( name ))) - Automatic marking report}
 +\title{((( tex_escape(name) ))) - Automatic marking report}
  \begin{document}
 @@ -70,16 +70,19 @@ breaklines=true  \begin{figure}[H]
      \centering
 -    \begin{forest}
 +    ((# \begin{forest}
          ((( recurse_class_tree_forest(class_tree)|indent(8, False) )))
 -    \end{forest}
 +    \end{forest} #))
 +    \begin{lstlisting}
 +((( recurse_class_tree_text(class_tree) )))
 +    \end{lstlisting}
      \caption{Class inheritance tree}
  \end{figure}
  \section{File Analysis}
  ((* set flat_files = flatten_struct(files) *))
  ((* for filename, files_contents in flat_files.items() *))
 -    \subsection{\texttt{((( filename )))}}
 +    \subsection{\texttt{((( tex_escape(filename) )))}}
      ((* if files_contents["present"] *))
          ((* if files_contents["has_exception"] *))
              \errortext{File cannot be run - has compile time exception.}
 @@ -87,9 +90,9 @@ breaklines=true              Please note that this file cannot be analysed or have tests preformed upon it-
              this can lead to the whole test suite failing if another module imports this.
 -            \textbf{Exception Type:} \texttt{((( files_contents["exception"]["type"] )))}
 +            \textbf{Exception Type:} \texttt{((( tex_escape(files_contents["exception"]["type"]) )))}
 -            \textbf{Exception String:} \texttt{((( files_contents["exception"]["str"] )))}
 +            \textbf{Exception String:} \texttt{((( tex_escape(files_contents["exception"]["str"]) )))}
              \textbf{Full Traceback:}
 diff --git a/Smarker/templates/text.jinja2 b/Smarker/templates/text.jinja2Binary files differ deleted file mode 100644 index eca6ebd..0000000 --- a/Smarker/templates/text.jinja2 +++ /dev/null | 
