first commit
This commit is contained in:
133
resemble/analyze.php
Normal file
133
resemble/analyze.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
require_once('../../../config.php');
|
||||
require_once('../lib.php');
|
||||
require_once("../../../lib/filelib.php");
|
||||
require_once('resemble_analyze_lib.php');
|
||||
|
||||
$id = required_param('id', PARAM_INT);
|
||||
$group = optional_param('group', 0, PARAM_INT);
|
||||
|
||||
$action = optional_param('action', 0, PARAM_CLEAN);
|
||||
$max = optional_param('max', 0, PARAM_INT);
|
||||
$lowest = optional_param('lowest', 0, PARAM_INT);
|
||||
|
||||
$params = array('id' => $id, 'group' => $group, 'action' => $action, 'max' => $max, 'lowest' => $lowest);
|
||||
$PAGE->set_url('/mod/programming/resemble/analyze.php', $params);
|
||||
|
||||
if (!$cm = get_coursemodule_from_id('programming', $id)) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
|
||||
if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
|
||||
print_error('coursemisconf');
|
||||
}
|
||||
|
||||
if (!$programming = $DB->get_record('programming', array('id' => $cm->instance))) {
|
||||
print_error('invalidprogrammingid', 'programming');
|
||||
}
|
||||
|
||||
require_login($course->id, true, $cm);
|
||||
|
||||
$context = context_module::instance($cm->id);
|
||||
require_capability('mod/programming:updateresemble', $context);
|
||||
|
||||
|
||||
/// Print the page header
|
||||
$PAGE->set_title($programming->name);
|
||||
$PAGE->set_heading(format_string($course->fullname));
|
||||
echo $OUTPUT->header();
|
||||
|
||||
/// Print tabs
|
||||
$renderer = $PAGE->get_renderer('mod_programming');
|
||||
$tabs = programming_navtab('resemble', 'resemble-analyze', $course, $programming, $cm);
|
||||
echo $renderer->render_navtab($tabs);
|
||||
|
||||
/// Print page content
|
||||
|
||||
if ($action) {
|
||||
if ($group != 0) {
|
||||
$users = get_group_users($group);
|
||||
} else {
|
||||
if ($usergrps = groups_get_all_groups($course->id, $USER->id)) {
|
||||
foreach ($usergrps as $ug) {
|
||||
$users = array_merge($users, get_group_users($ug->id));
|
||||
}
|
||||
} else {
|
||||
$users = False;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM {programming_submits} WHERE programmingid={$programming->id}";
|
||||
if (is_array($users)) {
|
||||
$sql .= ' AND userid IN (' . implode(',', array_keys($users)) . ')';
|
||||
}
|
||||
$sql .= ' ORDER BY timemodified DESC';
|
||||
$submits = $DB->get_records_sql($sql);
|
||||
|
||||
$users = array();
|
||||
$latestsubmits = array();
|
||||
if (is_array($submits)) {
|
||||
foreach ($submits as $submit) {
|
||||
if (in_array($submit->userid, $users))
|
||||
continue;
|
||||
$users[] = $submit->userid;
|
||||
$latestsubmits[] = $submit;
|
||||
}
|
||||
}
|
||||
$sql = 'SELECT * FROM {user} WHERE id IN (' . implode(',', $users) . ')';
|
||||
$users = $DB->get_records_sql($sql);
|
||||
|
||||
// create dir
|
||||
$dirname = $CFG->dataroot . '/temp';
|
||||
if (!file_exists($dirname)) {
|
||||
mkdir($dirname, 0777) or ( 'Failed to create dir');
|
||||
}
|
||||
$dirname .= '/programming';
|
||||
if (!file_exists($dirname)) {
|
||||
mkdir($dirname, 0777) or ( 'Failed to create dir');
|
||||
}
|
||||
$dirname .= '/' . $programming->id;
|
||||
if (file_exists($dirname)) {
|
||||
if (is_dir($dirname)) {
|
||||
fulldelete($dirname) or error('Failed to remove dir contents');
|
||||
//rmdir($dirname) or error('Failed to remove dir');
|
||||
} else {
|
||||
unlink($dirname) or error('Failed to delete file');
|
||||
}
|
||||
}
|
||||
mkdir($dirname, 0700) or error('Failed to create dir');
|
||||
|
||||
$files = array();
|
||||
// write files
|
||||
$exts = array('.txt', '.c', '.cxx', '.java', '.java', '.pas', '.py', '.cs');
|
||||
foreach ($latestsubmits as $submit) {
|
||||
$ext = $exts[$submit->language];
|
||||
$filename = "{$dirname}/{$submit->userid}-{$submit->id}{$ext}";
|
||||
$files[] = $filename;
|
||||
$f = fopen($filename, 'w');
|
||||
fwrite($f, $submit->code);
|
||||
fwrite($f, "\r\n");
|
||||
fclose($f);
|
||||
}
|
||||
//echo "dir is $dirname <br />";
|
||||
|
||||
$cwd = getcwd();
|
||||
chdir($dirname);
|
||||
$url = array();
|
||||
exec("perl $cwd/moss.pl -u {$CFG->programming_moss_userid} *", $url);
|
||||
print_r($url);
|
||||
$url = $url[count($url) - 1];
|
||||
echo "See result $url <br />";
|
||||
|
||||
// remove temp
|
||||
fulldelete($dirname);
|
||||
|
||||
parse_result($programming->id, $url, $max, $lowest);
|
||||
} else {
|
||||
include_once('resemble_analyze.tpl.php');
|
||||
}
|
||||
|
||||
/// Finish the page
|
||||
$OUTPUT->footer($course);
|
||||
?>
|
||||
74
resemble/compare.php
Normal file
74
resemble/compare.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
require_once('../../../config.php');
|
||||
require_once('../lib.php');
|
||||
|
||||
$id = required_param('id', PARAM_INT); // programming ID
|
||||
$rid = optional_param('rid', 0, PARAM_INT); // resemble id
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$perpage = optional_param('perpage', 0, PARAM_INT);
|
||||
|
||||
$params = array('id' => $id, 'rid' => $rid, 'page' => $page, 'perpage' => $perpage);
|
||||
$PAGE->set_url('/mod/programming/resemble/compare.php', $params);
|
||||
|
||||
if (! $cm = get_coursemodule_from_id('programming', $id)) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
|
||||
if (! $course = $DB->get_record('course', array('id' => $cm->course))) {
|
||||
print_error('coursemisconf');
|
||||
}
|
||||
|
||||
if (! $programming = $DB->get_record('programming', array('id' => $cm->instance))) {
|
||||
print_error('invalidprogrammingid', 'programming');
|
||||
}
|
||||
|
||||
require_login($course->id, true, $cm);
|
||||
|
||||
$context = context_module::instance($cm->id);
|
||||
|
||||
$resemble = $DB->get_record('programming_resemble', array('id' => $rid));
|
||||
$submit1 = $DB->get_record('programming_submits', array('id' => $resemble->submitid1));
|
||||
$submit2 = $DB->get_record('programming_submits', array('id' => $resemble->submitid2));
|
||||
if ($submit1->userid == $USER->id || $submit2->userid == $USER->id) {
|
||||
require_capability('mod/programming:viewresemble', $context);
|
||||
} else {
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
}
|
||||
|
||||
$user1 = $DB->get_record('user', array('id' => $submit1->userid));
|
||||
$user2 = $DB->get_record('user', array('id' => $submit2->userid));
|
||||
|
||||
|
||||
// Change matched lines into array, with an matched id as first element
|
||||
$lines1 = explode("\n", $submit1->code);
|
||||
$lines2 = explode("\n", $submit2->code);
|
||||
|
||||
$matches = explode(';', $resemble->matchedlines);
|
||||
$mid = 1;
|
||||
foreach($matches as $range) {
|
||||
list($range1, $range2) = explode(',', $range);
|
||||
|
||||
list($start, $end) = explode('-', $range1);
|
||||
while ($start <= $end) {
|
||||
if (array_key_exists($start, $lines1) &&
|
||||
!is_array($lines1[$start])) {
|
||||
$lines1[$start] = array($mid, $lines1[$start]);
|
||||
}
|
||||
$start++;
|
||||
}
|
||||
list($start, $end) = explode('-', $range2);
|
||||
while ($start <= $end) {
|
||||
if (array_key_exists($start, $lines2) &&
|
||||
!is_array($lines2[$start])) {
|
||||
$lines2[$start] = array($mid, $lines2[$start]);
|
||||
}
|
||||
$start++;
|
||||
}
|
||||
$mid++;
|
||||
}
|
||||
|
||||
|
||||
include_once('resemble_compare.tpl.php');
|
||||
|
||||
?>
|
||||
130
resemble/edit.php
Normal file
130
resemble/edit.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
require_once('../../../config.php');
|
||||
require_once('../lib.php');
|
||||
|
||||
$id = required_param('id', PARAM_INT);
|
||||
$action = optional_param('action', 'list', PARAM_CLEAN);
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$perpage = optional_param('perpage', 10, PARAM_INT);
|
||||
$format = optional_param('format', 'html', PARAM_CLEAN);
|
||||
$rids = optional_param_array('rids', array(), PARAM_INT);
|
||||
|
||||
$params = array('id' => $id, 'action' => $action, 'page' => $page, 'perpage' => $perpage, 'format' => $format);
|
||||
$PAGE->set_url('/mod/programming/resemble/edit.php', $params);
|
||||
|
||||
if (! $cm = get_coursemodule_from_id('programming', $id)) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
|
||||
if (! $course = $DB->get_record('course', array('id' => $cm->course))) {
|
||||
print_error('coursemisconf');
|
||||
}
|
||||
|
||||
if (! $programming = $DB->get_record('programming', array('id' => $cm->instance))) {
|
||||
print_error('invalidprogrammingid', 'programming');
|
||||
}
|
||||
|
||||
require_login($course->id, true, $cm);
|
||||
|
||||
$context = context_module::instance($cm->id);
|
||||
|
||||
$successurl = new moodle_url('/mod/programming/resemble/edit.php', array('id' => $cm->id, 'page' => $page, 'perpage' => $perpage));
|
||||
switch($action) {
|
||||
case 'list':
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
$offset = $page * $perpage;
|
||||
$sql = "SELECT re.*, ua.id as userid1, ub.id as userid2
|
||||
FROM {programming_resemble} AS re,
|
||||
{programming_submits} AS sa,
|
||||
{programming_submits} AS sb,
|
||||
{user} AS ua,
|
||||
{user} AS ub
|
||||
WHERE re.programmingid={$programming->id}
|
||||
AND re.flag>=0
|
||||
AND re.submitid1 = sa.id
|
||||
AND re.submitid2 = sb.id
|
||||
AND sa.userid = ua.id
|
||||
AND sb.userid = ub.id
|
||||
ORDER BY id
|
||||
LIMIT $offset, $perpage";
|
||||
$resemble = $DB->get_records_sql($sql);
|
||||
if (!is_array($resemble)) $resemble = array();
|
||||
$uids = array(); $sids = array();
|
||||
foreach($resemble as $r) {
|
||||
$uids[] = $r->userid1;
|
||||
$uids[] = $r->userid2;
|
||||
$sids[] = $r->submitid1;
|
||||
$sids[] = $r->submitid2;
|
||||
}
|
||||
if (!empty($uids)) {
|
||||
$users = $DB->get_records_select('user', 'id IN ('.implode($uids, ',').')');
|
||||
}
|
||||
if (!empty($sids)) {
|
||||
$submits = $DB->get_records_select('programming_submits', 'id IN ('.implode($sids, ',').')');
|
||||
}
|
||||
$totalcount = $DB->count_records_select('programming_resemble', 'programmingid='.$programming->id.' AND flag>=0');
|
||||
|
||||
/// Print page content
|
||||
if ($format == 'json') {
|
||||
require_once('../lib/JSON.php');
|
||||
$data = array(array_keys($resemble), array_values($resemble), array_keys($users), array_values($users));
|
||||
$json = new Services_JSON();
|
||||
echo $json->encode($data);
|
||||
} else {
|
||||
include_once('resemble_edit.tpl.php');
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'confirm':
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
$select = 'id in ('.join(',', $rids).')';
|
||||
$sql = $DB->set_field_select('programming_resemble', 'flag', PROGRAMMING_RESEMBLE_CONFIRMED, $select);
|
||||
redirect($successurl, get_string('resembleeditsucceeded', 'programming'), 2);
|
||||
break;
|
||||
|
||||
case 'warn':
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
$select = 'id in ('.join(',', $rids).')';
|
||||
$sql = $DB->set_field_select('programming_resemble', 'flag', PROGRAMMING_RESEMBLE_WARNED, $select);
|
||||
redirect($successurl, get_string('resembleeditsucceeded', 'programming'), 2);
|
||||
break;
|
||||
|
||||
case 'reset':
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
$select = 'id in ('.join(',', $rids).')';
|
||||
$sql = $DB->set_field_select('programming_resemble', 'flag', PROGRAMMING_RESEMBLE_NEW, $select);
|
||||
redirect($successurl, get_string('resembleeditsucceeded', 'programming'), 2);
|
||||
break;
|
||||
|
||||
case 'flag1':
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
$select = 'id in ('.join(',', $rids).')';
|
||||
$sql = $DB->set_field_select('programming_resemble', 'flag', PROGRAMMING_RESEMBLE_FLAG1, $select);
|
||||
redirect($successurl, get_string('resembleeditsucceeded', 'programming'), 2);
|
||||
break;
|
||||
|
||||
case 'flag2':
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
$select = 'id in ('.join(',', $rids).')';
|
||||
$sql = $DB->set_field_select('programming_resemble', 'flag', PROGRAMMING_RESEMBLE_FLAG2, $select);
|
||||
redirect($successurl, get_string('resembleeditsucceeded', 'programming'), 2);
|
||||
break;
|
||||
|
||||
case 'flag3':
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
$select = 'id in ('.join(',', $rids).')';
|
||||
$sql = $DB->set_field_select('programming_resemble', 'flag', PROGRAMMING_RESEMBLE_FLAG3, $select);
|
||||
redirect($successurl, get_string('resembleeditsucceeded', 'programming'), 2);
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
require_capability('mod/programming:editresemble', $context);
|
||||
$select = 'id in ('.join(',', $rids).')';
|
||||
$sql = $DB->set_field_select('programming_resemble', 'flag', PROGRAMMING_RESEMBLE_DELETED, $select);
|
||||
redirect($successurl, get_string('resembleeditsucceeded', 'programming'), 2);
|
||||
break;
|
||||
}
|
||||
|
||||
?>
|
||||
366
resemble/moss.pl
Normal file
366
resemble/moss.pl
Normal file
@@ -0,0 +1,366 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Please read all the comments down to the line that says "TOP".
|
||||
# These comments are divided into three sections:
|
||||
#
|
||||
# 1. usage instructions
|
||||
# 2. installation instructions
|
||||
# 3. standard copyright
|
||||
#
|
||||
# Feel free to share this script with other instructors of programming
|
||||
# classes, but please do not place the script in a publicly accessible
|
||||
# place. Comments, questions, and bug reports should be sent to
|
||||
# moss-request@cs.berkeley.edu.
|
||||
#
|
||||
# IMPORTANT: This script is known to work on Unix and on Windows using Cygwin.
|
||||
# It is not known to work on other ways of using Perl under Windows. If the
|
||||
# script does not work for you under Windows, you can try the email-based
|
||||
# version for Windows (available on the Moss home page).
|
||||
#
|
||||
|
||||
#
|
||||
# Section 1. Usage instructions
|
||||
#
|
||||
# moss [-l language] [-d] [-b basefile1] ... [-b basefilen] [-m #] [-c "string"] file1 file2 file3 ...
|
||||
#
|
||||
# The -l option specifies the source language of the tested programs.
|
||||
# Moss supports many different languages; see the variable "languages" below for the
|
||||
# full list.
|
||||
#
|
||||
# Example: Compare the lisp programs foo.lisp and bar.lisp:
|
||||
#
|
||||
# moss -l lisp foo.lisp bar.lisp
|
||||
#
|
||||
#
|
||||
# The -d option specifies that submissions are by directory, not by file.
|
||||
# That is, files in a directory are taken to be part of the same program,
|
||||
# and reported matches are organized accordingly by directory.
|
||||
#
|
||||
# Example: Compare the programs foo and bar, which consist of .c and .h
|
||||
# files in the directories foo and bar respectively.
|
||||
#
|
||||
# moss -d foo/*.c foo/*.h bar/*.c bar/*.h
|
||||
#
|
||||
# Example: Each program consists of the *.c and *.h files in a directory under
|
||||
# the directory "assignment1."
|
||||
#
|
||||
# moss -d assignment1/*/*.h assignment1/*/*.c
|
||||
#
|
||||
#
|
||||
# The -b option names a "base file". Moss normally reports all code
|
||||
# that matches in pairs of files. When a base file is supplied,
|
||||
# program code that also appears in the base file is not counted in matches.
|
||||
# A typical base file will include, for example, the instructor-supplied
|
||||
# code for an assignment. Multiple -b options are allowed. You should
|
||||
# use a base file if it is convenient; base files improve results, but
|
||||
# are not usually necessary for obtaining useful information.
|
||||
#
|
||||
# IMPORTANT: Unlike previous versions of moss, the -b option *always*
|
||||
# takes a single filename, even if the -d option is also used.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# Submit all of the C++ files in the current directory, using skeleton.cc
|
||||
# as the base file:
|
||||
#
|
||||
# moss -l cc -b skeleton.cc *.cc
|
||||
#
|
||||
# Submit all of the ML programs in directories asn1.96/* and asn1.97/*, where
|
||||
# asn1.97/instructor/example.ml and asn1.96/instructor/example.ml contain the base files.
|
||||
#
|
||||
# moss -l ml -b asn1.97/instructor/example.ml -b asn1.96/instructor/example.ml -d asn1.97/*/*.ml asn1.96/*/*.ml
|
||||
#
|
||||
# The -m option sets the maximum number of times a given passage may appear
|
||||
# before it is ignored. A passage of code that appears in many programs
|
||||
# is probably legitimate sharing and not the result of plagiarism. With -m N,
|
||||
# any passage appearing in more than N programs is treated as if it appeared in
|
||||
# a base file (i.e., it is never reported). Option -m can be used to control
|
||||
# moss' sensitivity. With -m 2, moss reports only passages that appear
|
||||
# in exactly two programs. If one expects many very similar solutions
|
||||
# (e.g., the short first assignments typical of introductory programming
|
||||
# courses) then using -m 3 or -m 4 is a good way to eliminate all but
|
||||
# truly unusual matches between programs while still being able to detect
|
||||
# 3-way or 4-way plagiarism. With -m 1000000 (or any very
|
||||
# large number), moss reports all matches, no matter how often they appear.
|
||||
# The -m setting is most useful for large assignments where one also a base file
|
||||
# expected to hold all legitimately shared code. The default for -m is 10.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# moss -l pascal -m 2 *.pascal
|
||||
# moss -l cc -m 1000000 -b mycode.cc asn1/*.cc
|
||||
#
|
||||
#
|
||||
# The -c option supplies a comment string that is attached to the generated
|
||||
# report. This option facilitates matching queries submitted with replies
|
||||
# received, especially when several queries are submitted at once.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# moss -l scheme -c "Scheme programs" *.sch
|
||||
#
|
||||
# The -n option determines the number of matching files to show in the results.
|
||||
# The default is 250.
|
||||
#
|
||||
# Example:
|
||||
# moss -c java -n 200 *.java
|
||||
# The -x option sends queries to the current experimental version of the server.
|
||||
# The experimental server has the most recent Moss features and is also usually
|
||||
# less stable (read: may have more bugs).
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# moss -x -l ml *.ml
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# Section 2. Installation instructions.
|
||||
#
|
||||
# You may need to change the very first line of this script
|
||||
# if perl is not in /usr/bin on your system. Just replace /usr/bin
|
||||
# with the pathname of the directory where perl resides.
|
||||
#
|
||||
|
||||
#
|
||||
# 3. Standard Copyright
|
||||
#
|
||||
#Copyright (c) 1997 The Regents of the University of California.
|
||||
#All rights reserved.
|
||||
#
|
||||
#Permission to use, copy, modify, and distribute this software for any
|
||||
#purpose, without fee, and without written agreement is hereby granted,
|
||||
#provided that the above copyright notice and the following two
|
||||
#paragraphs appear in all copies of this software.
|
||||
#
|
||||
#IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
||||
#DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
|
||||
#OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
|
||||
#CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
||||
#INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
#AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
#ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
|
||||
#PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
#
|
||||
#
|
||||
# STOP. It should not be necessary to change anything below this line
|
||||
# to use the script.
|
||||
#
|
||||
use IO::Socket;
|
||||
|
||||
#
|
||||
# As of the date this script was written, the following languages were supported. This script will work with
|
||||
# languages added later however. Check the moss website for the full list of supported languages.
|
||||
#
|
||||
@languages = ("c", "cc", "java", "ml", "pascal", "ada", "lisp", "scheme", "haskell", "fortran", "ascii", "vhdl", "perl", "matlab", "python", "mips", "prolog", "spice", "vb", "csharp", "modula2", "a8086", "javascript", "plsql");
|
||||
|
||||
$server = 'moss.stanford.edu';
|
||||
$port = '7690';
|
||||
$noreq = "Request not sent.";
|
||||
$usage = "usage: moss [-x] [-l language] [-d] [-b basefile1] ... [-b basefilen] [-m #] [-c \"string\"] file1 file2 file3 ...";
|
||||
|
||||
#
|
||||
# The userid is used to authenticate your queries to the server; don't change it!
|
||||
#
|
||||
$userid=123456789;
|
||||
|
||||
#
|
||||
# Process the command line options. This is done in a non-standard
|
||||
# way to allow multiple -b's.
|
||||
#
|
||||
$opt_l = "c"; # default language is c
|
||||
$opt_m = 10;
|
||||
$opt_d = 0;
|
||||
$opt_x = 0;
|
||||
$opt_c = "";
|
||||
$opt_n = 250;
|
||||
$bindex = 0; # this becomes non-zero if we have any base files
|
||||
|
||||
while (@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
|
||||
($first,$rest) = ($1,$2);
|
||||
|
||||
shift(@ARGV);
|
||||
if ($first eq "d") {
|
||||
$opt_d = 1;
|
||||
next;
|
||||
}
|
||||
if ($first eq "b") {
|
||||
if($rest eq '') {
|
||||
die "No argument for option -b.\n" unless @ARGV;
|
||||
$rest = shift(@ARGV);
|
||||
}
|
||||
$opt_b[$bindex++] = $rest;
|
||||
next;
|
||||
}
|
||||
if ($first eq "l") {
|
||||
if ($rest eq '') {
|
||||
die "No argument for option -l.\n" unless @ARGV;
|
||||
$rest = shift(@ARGV);
|
||||
}
|
||||
$opt_l = $rest;
|
||||
next;
|
||||
}
|
||||
if ($first eq "m") {
|
||||
if($rest eq '') {
|
||||
die "No argument for option -m.\n" unless @ARGV;
|
||||
$rest = shift(@ARGV);
|
||||
}
|
||||
$opt_m = $rest;
|
||||
next;
|
||||
}
|
||||
if ($first eq "c") {
|
||||
if($rest eq '') {
|
||||
die "No argument for option -c.\n" unless @ARGV;
|
||||
$rest = shift(@ARGV);
|
||||
}
|
||||
$opt_c = $rest;
|
||||
next;
|
||||
}
|
||||
if ($first eq "n") {
|
||||
if($rest eq '') {
|
||||
die "No argument for option -n.\n" unless @ARGV;
|
||||
$rest = shift(@ARGV);
|
||||
}
|
||||
$opt_n = $rest;
|
||||
next;
|
||||
}
|
||||
if ($first eq "x") {
|
||||
$opt_x = 1;
|
||||
next;
|
||||
}
|
||||
#
|
||||
# Override the name of the server. This is used for testing this script.
|
||||
#
|
||||
if ($first eq "s") {
|
||||
$server = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
#
|
||||
# Override the port. This is used for testing this script.
|
||||
#
|
||||
if ($first eq "p") {
|
||||
$port = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
#
|
||||
# Override the userid.
|
||||
#
|
||||
if ($first eq "u") {
|
||||
$userid = shift(@ARGV);
|
||||
next;
|
||||
}
|
||||
die "Unrecognized option -$first. $usage\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Check a bunch of things first to ensure that the
|
||||
# script will be able to run to completion.
|
||||
#
|
||||
|
||||
#
|
||||
# Make sure all the argument files exist and are readable.
|
||||
#
|
||||
print "Checking files . . . \n";
|
||||
$i = 0;
|
||||
while($i < $bindex)
|
||||
{
|
||||
die "Base file $opt_b[$i] does not exist. $noreq\n" unless -e "$opt_b[$i]";
|
||||
die "Base file $opt_b[$i] is not readable. $noreq\n" unless -r "$opt_b[$i]";
|
||||
die "Base file $opt_b is not a text file. $noreq\n" unless -T "$opt_b[$i]";
|
||||
$i++;
|
||||
}
|
||||
foreach $file (@ARGV)
|
||||
{
|
||||
die "File $file does not exist. $noreq\n" unless -e "$file";
|
||||
die "File $file is not readable. $noreq\n" unless -r "$file";
|
||||
die "File $file is not a text file. $noreq\n" unless -T "$file";
|
||||
}
|
||||
|
||||
if ("@ARGV" eq '') {
|
||||
die "No files submitted.\n $usage";
|
||||
}
|
||||
print "OK\n";
|
||||
|
||||
#
|
||||
# Now the real processing begins.
|
||||
#
|
||||
|
||||
|
||||
$sock = new IO::Socket::INET (
|
||||
PeerAddr => $server,
|
||||
PeerPort => $port,
|
||||
Proto => 'tcp',
|
||||
);
|
||||
die "Could not connect to server $server: $!\n" unless $sock;
|
||||
$sock->autoflush(1);
|
||||
|
||||
sub read_from_server {
|
||||
$msg = <$sock>;
|
||||
print $msg;
|
||||
}
|
||||
|
||||
sub upload_file {
|
||||
local ($file, $id, $lang) = @_;
|
||||
#
|
||||
# The stat function does not seem to give correct filesizes on windows, so
|
||||
# we compute the size here via brute force.
|
||||
#
|
||||
open(F,$file);
|
||||
$size = 0;
|
||||
while (<F>) {
|
||||
$size += length($_);
|
||||
}
|
||||
close(F);
|
||||
|
||||
print "Uploading $file ...";
|
||||
print $sock "file $id $lang $size $file\n";
|
||||
open(F,$file);
|
||||
while (<F>) {
|
||||
print $sock $_;
|
||||
}
|
||||
close(F);
|
||||
print "done.\n";
|
||||
}
|
||||
|
||||
|
||||
print $sock "moss $userid\n"; # authenticate user
|
||||
print $sock "directory $opt_d\n";
|
||||
print $sock "X $opt_x\n";
|
||||
print $sock "maxmatches $opt_m\n";
|
||||
print $sock "show $opt_n\n";
|
||||
|
||||
#
|
||||
# confirm that we have a supported languages
|
||||
#
|
||||
print $sock "language $opt_l\n";
|
||||
$msg = <$sock>;
|
||||
chop($msg);
|
||||
if ($msg eq "no") {
|
||||
print $sock "end\n";
|
||||
die "Unrecognized language $opt_l.";
|
||||
}
|
||||
|
||||
|
||||
# upload any base files
|
||||
$i = 0;
|
||||
while($i < $bindex) {
|
||||
&upload_file($opt_b[$i++],0,$opt_l);
|
||||
}
|
||||
|
||||
$setid = 1;
|
||||
foreach $file (@ARGV) {
|
||||
&upload_file($file,$setid++,$opt_l);
|
||||
}
|
||||
|
||||
print $sock "query 0 $opt_c\n";
|
||||
print "Query submitted. Waiting for the server's response.\n";
|
||||
&read_from_server();
|
||||
print $sock "end\n";
|
||||
close($sock);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
15
resemble/resemble_analyze.tpl.php
Normal file
15
resemble/resemble_analyze.tpl.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<br />
|
||||
<form id="resemble_analyze_form" action="resemble_analyze_cmd.php" target="cmd">
|
||||
<input type="hidden" name="id" value="<?php echo $cm->id ?>" />
|
||||
<input type="hidden" name="action" value="fetchresult" />
|
||||
<span>
|
||||
<label for="max">max</label>
|
||||
<input type="text" name="max" size="10" value="250"/>
|
||||
</span>
|
||||
<span>
|
||||
<label for="lowest">lowest</label>
|
||||
<input type="text" name="lowest" size="10" value="30"/>
|
||||
</span>
|
||||
<input id="begin_analyze" type="submit" value="begin" />
|
||||
</form>
|
||||
<iframe name="cmd" width="640" height="480"></iframe>
|
||||
127
resemble/resemble_analyze_cmd.php
Normal file
127
resemble/resemble_analyze_cmd.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
require_once('../../../config.php');
|
||||
require_once('../lib.php');
|
||||
require_once("../../../lib/filelib.php");
|
||||
require_once('resemble_analyze_lib.php');
|
||||
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
|
||||
$id = required_param('id', PARAM_INT);
|
||||
$group = optional_param('group', 0, PARAM_INT);
|
||||
|
||||
$max = optional_param('max', 0, PARAM_INT);
|
||||
$lowest = optional_param('lowest', 0, PARAM_INT);
|
||||
|
||||
if (!$cm = get_coursemodule_from_id('programming', $id)) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
|
||||
if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
|
||||
print_error('coursemisconf');
|
||||
}
|
||||
|
||||
if (!$programming = $DB->get_record('programming', array('id' => $cm->instance))) {
|
||||
print_error('invalidprogrammingid', 'programming');
|
||||
}
|
||||
|
||||
require_login($course->id, true, $cm);
|
||||
|
||||
$context = context_module::instance($cm->id);
|
||||
require_capability('mod/programming:updateresemble', $context);
|
||||
|
||||
/// Print page content
|
||||
if ($group != 0) {
|
||||
$users = get_group_users($group);
|
||||
} else {
|
||||
if ($usergrps = groups_get_all_groups($course->id, $USER->id)) {
|
||||
foreach ($usergrps as $ug) {
|
||||
$users = array_merge($users, get_group_users($ug->id));
|
||||
}
|
||||
} else {
|
||||
$users = False;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM {programming_submits} WHERE programmingid={$programming->id}";
|
||||
if (is_array($users)) {
|
||||
$sql .= ' AND userid IN (' . implode(',', array_keys($users)) . ')';
|
||||
}
|
||||
$sql .= ' ORDER BY timemodified DESC';
|
||||
$submits = $DB->get_records_sql($sql);
|
||||
|
||||
$users = array();
|
||||
$latestsubmits = array();
|
||||
if (is_array($submits)) {
|
||||
foreach ($submits as $submit) {
|
||||
if (in_array($submit->userid, $users))
|
||||
continue;
|
||||
$users[] = $submit->userid;
|
||||
$latestsubmits[] = $submit;
|
||||
}
|
||||
}
|
||||
$sql = 'SELECT * FROM {user} WHERE id IN (' . implode(',', $users) . ')';
|
||||
$users = $DB->get_records_sql($sql);
|
||||
|
||||
// create dir
|
||||
$dirname = $CFG->dataroot . '/temp';
|
||||
if (!file_exists($dirname)) {
|
||||
mkdir($dirname, 0777) or ( 'Failed to create dir');
|
||||
}
|
||||
$dirname .= '/programming';
|
||||
if (!file_exists($dirname)) {
|
||||
mkdir($dirname, 0777) or ( 'Failed to create dir');
|
||||
}
|
||||
$dirname .= '/' . $programming->id;
|
||||
if (file_exists($dirname)) {
|
||||
if (is_dir($dirname)) {
|
||||
fulldelete($dirname) or error('Failed to remove dir contents');
|
||||
//rmdir($dirname) or error('Failed to remove dir');
|
||||
} else {
|
||||
unlink($dirname) or error('Failed to delete file');
|
||||
}
|
||||
}
|
||||
mkdir($dirname, 0700) or error('Failed to create dir');
|
||||
|
||||
$files = array();
|
||||
// write files
|
||||
$exts = array('.txt', '.c', '.cxx', '.java', '.java', '.pas', '.py', '.cs');
|
||||
foreach ($latestsubmits as $submit) {
|
||||
$ext = $exts[$submit->language];
|
||||
$filename = "{$dirname}/{$submit->userid}-{$submit->id}{$ext}";
|
||||
$files[] = $filename;
|
||||
$f = fopen($filename, 'w');
|
||||
fwrite($f, $submit->code);
|
||||
fwrite($f, "\r\n");
|
||||
fclose($f);
|
||||
}
|
||||
// echo "dir is $dirname\n";
|
||||
|
||||
$cwd = getcwd();
|
||||
$cmd = "/usr/bin/perl $cwd/moss.pl -u {$CFG->programming_moss_userid} *";
|
||||
// echo "$cmd\n"; flush();
|
||||
|
||||
chdir($dirname);
|
||||
$ofile = popen($cmd, 'r');
|
||||
chdir($cwd);
|
||||
|
||||
$contents = '';
|
||||
if ($ofile) {
|
||||
while (!feof($ofile)) {
|
||||
$read = fread($ofile, 1024);
|
||||
$contents .= $read;
|
||||
echo $read;
|
||||
}
|
||||
pclose($ofile);
|
||||
}
|
||||
$lastline = substr($contents, strrpos($contents, "\n", -3));
|
||||
|
||||
preg_match('/(http:[\.\/a-z0-9]+)/', $lastline, $matches);
|
||||
$url = $matches[1];
|
||||
echo "Result: $url\n";
|
||||
|
||||
// remove temp
|
||||
fulldelete($dirname);
|
||||
|
||||
parse_result($programming->id, $url, $max, $lowest);
|
||||
?>
|
||||
118
resemble/resemble_analyze_lib.php
Normal file
118
resemble/resemble_analyze_lib.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
$moss_url = 'http://moss.stanford.edu/results';
|
||||
$curl = null;
|
||||
|
||||
function parse_index($programmingid, $index_file, $max, $lowest) {
|
||||
global $CFG, $DB;
|
||||
|
||||
$lines = fetch_by_curl($index_file);
|
||||
$s = 0;
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$m = array();
|
||||
switch ($s) {
|
||||
case 0:
|
||||
if (preg_match('/<TABLE>/', $line)) {
|
||||
$s = 1;
|
||||
$c = 0;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (preg_match('/^<TR><TD><A HREF="([^"]*)">(\d*)?-(\d*)\.\w* \((\d*)%\)<\/A>/', $line, $m)) {
|
||||
$resemble = new object;
|
||||
$resemble->programmingid = $programmingid;
|
||||
|
||||
$resemble->submitid1 = $m[3];
|
||||
$resemble->percent1 = $m[4];
|
||||
|
||||
$s = 2;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (preg_match('/<TD><A HREF="([^"]*)">(\d*)?-(\d*)\.\w* \((\d*)%\)<\/A>/', $line, $m)) {
|
||||
$resemble->submitid2 = $m[3];
|
||||
$resemble->percent2 = $m[4];
|
||||
$s = 3;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (preg_match('/<TD ALIGN=right>(\d+)/', $line, $m)) {
|
||||
$resemble->matchedcount = $m[1];
|
||||
if ($resemble->percent1 > $lowest or $resemble->percent2 > $lowest) {
|
||||
$resemble->matchedlines = parse_lines($index_file.'/match'.$c.'-top.html');
|
||||
if (!$DB->insert_record('programming_resemble', $resemble)) {
|
||||
printf("Failed to insert record.\n");
|
||||
}
|
||||
}
|
||||
$c ++;
|
||||
$s = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parse_lines($topfile) {
|
||||
$lines = fetch_by_curl($topfile);
|
||||
$s = 0;
|
||||
$c = 0;
|
||||
$result = '';
|
||||
|
||||
foreach($lines as $line) {
|
||||
$m = array();
|
||||
switch ($s) {
|
||||
case 0:
|
||||
if (preg_match('/^<TR><TD><A[^>]*>(\d+-\d+)<\/A>/', $line, $m)) {
|
||||
$s = 1;
|
||||
if ($result != '') $result .= ';';
|
||||
$result .= $m[1].',';
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (preg_match('/^<TD><A[^>]*>(\d+-\d+)<\/A>/', $line, $m)) {
|
||||
$s = 0;
|
||||
$result .= $m[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function parse_result($programmingid, $url, $max = 0, $lowest = 0) {
|
||||
global $CFG, $DB, $moss_url;
|
||||
global $curl;
|
||||
|
||||
// delete old moss result
|
||||
$DB->delete_records('programming_resemble', array('programmingid' => $programmingid));
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
|
||||
if (isset($CFG->proxyhost) && isset($CFG->proxyport) && ($CFG->proxyport > 0)) {
|
||||
curl_setopt($curl, CURLOPT_PROXY, $CFG->proxyhost);
|
||||
curl_setopt($curl, CURLOPT_PROXYPORT, $CFG->proxyport);
|
||||
if (isset($CFG->proxyuser) && isset($CFG->proxypass)) {
|
||||
curl_setopt($curl, CURLOPT_PROXYUSERPWD, $CFG->proxyuser.':'.$CFG->proxypass);
|
||||
}
|
||||
}
|
||||
|
||||
parse_index($programmingid, $url, $max, $lowest);
|
||||
|
||||
curl_close($curl);
|
||||
}
|
||||
|
||||
function fetch_by_curl($url) {
|
||||
global $CFG;
|
||||
global $curl;
|
||||
|
||||
echo "Fetching $url\n"; flush();
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
$ret = curl_exec($curl);
|
||||
|
||||
return explode("\n", $ret);
|
||||
}
|
||||
|
||||
?>
|
||||
90
resemble/resemble_compare.tpl.php
Normal file
90
resemble/resemble_compare.tpl.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/// Print the page header
|
||||
$PAGE->set_title($programming->name);
|
||||
$PAGE->set_heading(format_string($course->fullname));
|
||||
echo $OUTPUT->header();
|
||||
|
||||
/// Print tabs
|
||||
$renderer = $PAGE->get_renderer('mod_programming');
|
||||
$tabs = programming_navtab('resemble', 'resemble-compare', $course, $programming, $cm);
|
||||
echo $renderer->render_navtab($tabs);
|
||||
|
||||
/// Print page content
|
||||
?>
|
||||
|
||||
<table class="generaltable resemble-list">
|
||||
<tr>
|
||||
<td class="cell">
|
||||
<?php echo $OUTPUT->user_picture($user1, array('courseid' => $course->id)); ?>
|
||||
<a href="<?php echo $CFG->wwwroot; ?>/user/view.php?id=<?php echo $user1->id; ?>&course=<?php echo $course->id; ?>"><?php echo fullname($user1); ?></a>
|
||||
</td>
|
||||
<td class="cell"><?php echo userdate($submit1->timemodified); ?></td>
|
||||
<td class="cell">
|
||||
<?php echo $OUTPUT->user_picture($user2, array('courseid' => $course->id)); ?>
|
||||
<a href="<?php echo $CFG->wwwroot; ?>/user/view.php?id=<?php echo $user2->id; ?>&course=<?php echo $course->id; ?>"><?php echo fullname($user2); ?></a>
|
||||
</td>
|
||||
<td class="cell"><?php echo userdate($submit2->timemodified); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="resemble-compare-programs">
|
||||
<div id="submit1">
|
||||
<?php
|
||||
foreach ($lines1 as $line) {
|
||||
if (is_array($line)) {
|
||||
$mid = $line[0];
|
||||
$line = $line[1];
|
||||
echo '<span class="code match'.$mid.'">';
|
||||
} else {
|
||||
echo '<span class="code">';
|
||||
}
|
||||
$line = htmlspecialchars($line);
|
||||
$line = str_replace(array(' ', "\r"), array(' ', ''), $line);
|
||||
echo $line;
|
||||
echo '</span><br />'."\n";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div id="submit2">
|
||||
<?php
|
||||
foreach ($lines2 as $line) {
|
||||
if (is_array($line)) {
|
||||
$mid = $line[0];
|
||||
$line = $line[1];
|
||||
echo '<span class="code match'.$mid.'">';
|
||||
} else {
|
||||
echo '<span class="code">';
|
||||
}
|
||||
$line = htmlspecialchars($line);
|
||||
$line = str_replace(array(' ', "\r"), array(' ', ''), $line);
|
||||
echo $line;
|
||||
echo '</span><br />'."\n";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (has_capability('mod/programming:editresemble', $context)): ?>
|
||||
<form action="edit.php" method="post" id="resemble_editform">
|
||||
<input type="hidden" name="id" value="<?php echo $cm->id; ?>" />
|
||||
<input type="hidden" name="page" value="<?php echo $page; ?>" />
|
||||
<?php if (isset($perpage)): ?>
|
||||
<input type="hidden" name="perpage" value="<?php echo $perpage; ?>" />
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="action" value="" />
|
||||
<input type="hidden" name="rids[]" value="<?php echo $resemble->id; ?>" />
|
||||
|
||||
<div class="buttons">
|
||||
<input type="submit" name="highsimilitude" value="<?php echo get_string('highsimilitude', 'programming'); ?>" onclick="this.form.elements['action'].value = 'confirm'" />
|
||||
<input type="submit" name="mediumsimilitude" value="<?php echo get_string('mediumsimilitude', 'programming'); ?>" onclick="this.form.elements['action'].value = 'warn'"/>
|
||||
<input type="submit" name="lowsimilitude" value="<?php echo get_string('lowsimilitude', 'programming'); ?>" onclick="this.form.elements['action'].value = 'reset'"/>
|
||||
<input type="submit" name="delete" value="<?php echo get_string('delete'); ?>" onclick="this.form.elements['action'].value = 'delete'"/>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
/// Finish the page
|
||||
echo $OUTPUT->footer($course);
|
||||
?>
|
||||
113
resemble/resemble_edit.tpl.php
Normal file
113
resemble/resemble_edit.tpl.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/// Print the page header
|
||||
$PAGE->set_title($programming->name);
|
||||
$PAGE->set_heading(format_string($course->fullname));
|
||||
echo $OUTPUT->header();
|
||||
|
||||
/// Print tabs
|
||||
$renderer = $PAGE->get_renderer('mod_programming');
|
||||
$tabs = programming_navtab('resemble', 'resemble-edit', $course, $programming, $cm);
|
||||
echo $renderer->render_navtab($tabs);
|
||||
?>
|
||||
<?php
|
||||
if (is_array($resemble) && count($resemble)):
|
||||
$pagingbar = new paging_bar($totalcount, $page, $perpage, $PAGE->url, 'page');
|
||||
echo $OUTPUT->render($pagingbar);
|
||||
?>
|
||||
<form action="edit.php" method="post" id="resemble_editform">
|
||||
<input type="hidden" name="id" value="<?php echo $cm->id; ?>" />
|
||||
<input type="hidden" name="page" value="<?php echo $page; ?>" />
|
||||
<input type="hidden" name="perpage" value="<?php echo $perpage; ?>" />
|
||||
<input type="hidden" name="action" value="" />
|
||||
|
||||
<table class="generaltable resemble-list">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th><input type="checkbox" onchange="$('input[@type=checkbox]').attr('checked', this.checked);"/></th>
|
||||
<th colspan="4"><?php echo get_string('program1', 'programming'); ?></th>
|
||||
<th><?php echo get_string('percent1', 'programming'); ?></th>
|
||||
<th colspan="4"><?php echo get_string('program2', 'programming'); ?></th>
|
||||
<th><?php echo get_string('percent2', 'programming'); ?></th>
|
||||
<th><?php echo get_string('matchedlines', 'programming'); ?></th>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
foreach ($resemble as $r):
|
||||
switch($r->flag) {
|
||||
case PROGRAMMING_RESEMBLE_WARNED:
|
||||
$styleclass = $styleclass1 = $styleclass2 = 'warned cell';
|
||||
break;
|
||||
case PROGRAMMING_RESEMBLE_CONFIRMED:
|
||||
$styleclass = $styleclass1 = $styleclass2 = 'confirmed cell';
|
||||
break;
|
||||
case PROGRAMMING_RESEMBLE_FLAG1:
|
||||
$styleclass = 'confirmed cell';
|
||||
$styleclass1 = 'confirmed cell';
|
||||
$styleclass2 = 'cell';
|
||||
break;
|
||||
case PROGRAMMING_RESEMBLE_FLAG2:
|
||||
$styleclass = 'confirmed cell';
|
||||
$styleclass1 = 'cell';
|
||||
$styleclass2 = 'confirmed cell';
|
||||
break;
|
||||
case PROGRAMMING_RESEMBLE_FLAG3:
|
||||
$styleclass = $styleclass1 = $styleclass2 = 'flag3 cell';
|
||||
break;
|
||||
default:
|
||||
$styleclass = $styleclass1 = $styleclass2 = 'cell';
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td class="<?php echo $styleclass; ?>"><input type="checkbox" name="rids[]" value="<?php echo $r->id ?>" /></td>
|
||||
<td class="<?php echo $styleclass1; ?>">
|
||||
<?php echo $OUTPUT->user_picture($users[$r->userid1], array('courseid' => $course->id)); ?>
|
||||
</td>
|
||||
<td class="<?php echo $styleclass1; ?>">
|
||||
<?php echo $OUTPUT->action_link(new moodle_url('/user/view.php', array('id' => $r->userid1, 'course' => $course->id)), fullname($users[$r->userid1])); ?>
|
||||
</td>
|
||||
<td class="<?php echo $styleclass1 ?>">
|
||||
<?php echo $users[$r->userid1]->idnumber; ?>
|
||||
</td>
|
||||
<td class="<?php echo $styleclass1 ?>">
|
||||
<?php echo $OUTPUT->action_link(new moodle_url('/mod/programming/result.php', array('id' => $cm->id, 'submitid' => $r->submitid1)), $submits[$r->submitid1]->judgeresult); ?></a>
|
||||
</td>
|
||||
<td class="<?php echo $styleclass1; ?>"><?php echo $r->percent1; ?></td>
|
||||
<td class="<?php echo $styleclass2; ?>">
|
||||
<?php echo $OUTPUT->user_picture($users[$r->userid2], array('courseid' => $course->id)); ?>
|
||||
</td>
|
||||
<td class="<?php echo $styleclass2; ?>">
|
||||
<?php echo $OUTPUT->action_link(new moodle_url('/user/view.php', array('id' => $r->userid2, 'course' => $course->id)), fullname($users[$r->userid2])); ?>
|
||||
</td>
|
||||
<td class="<?php echo $styleclass2; ?>">
|
||||
<?php echo $users[$r->userid2]->idnumber; ?>
|
||||
</td>
|
||||
<td class="<?php echo $styleclass2; ?>">
|
||||
<?php echo $OUTPUT->action_link(new moodle_url('/mod/programming/result.php', array('id' => $cm->id, 'submitid' => $r->submitid2)), $submits[$r->submitid2]->judgeresult); ?></a>
|
||||
</td>
|
||||
<td class="<?php echo $styleclass2; ?>"><?php echo $r->percent2; ?></td>
|
||||
<td class="<?php echo $styleclass; ?>">
|
||||
<?php echo $OUTPUT->action_link(new moodle_url('/mod/programming/resemble/compare.php', array('id' => $cm->id, 'rid' => $r->id, 'page' => $page, 'perpage' => $perpage)), $r->matchedcount); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="buttons">
|
||||
<input type="submit" name="highsimilitude" value="<?php echo get_string('highsimilitude', 'programming'); ?>" onclick="this.form.elements['action'].value = 'confirm'" />
|
||||
<input type="submit" name="mediumsimilitude" value="<?php echo get_string('mediumsimilitude', 'programming'); ?>" onclick="this.form.elements['action'].value = 'warn'"/>
|
||||
<input type="submit" name="lowsimilitude" value="<?php echo get_string('lowsimilitude', 'programming'); ?>" onclick="this.form.elements['action'].value = 'reset'"/>
|
||||
<input type="submit" name="flag1" value="<?php echo get_string('flag1', 'programming'); ?>" onclick="this.form.elements['action'].value = 'flag1'"/>
|
||||
<input type="submit" name="flag2" value="<?php echo get_string('flag2', 'programming'); ?>" onclick="this.form.elements['action'].value = 'flag2'"/>
|
||||
<input type="submit" name="flag3" value="<?php echo get_string('flag3', 'programming'); ?>" onclick="this.form.elements['action'].value = 'flag3'"/>
|
||||
<input type="submit" name="delete" value="<?php echo get_string('delete'); ?>" onclick="this.form.elements['action'].value = 'delete'"/>
|
||||
</div>
|
||||
</form>
|
||||
<?php
|
||||
else:
|
||||
echo html_writer::tag('p', get_string('noresembleinfo', 'programming'));
|
||||
endif;
|
||||
|
||||
/// Finish the page
|
||||
echo $OUTPUT->footer($course);
|
||||
143
resemble/view.php
Normal file
143
resemble/view.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
require_once('../../../config.php');
|
||||
require_once('../lib.php');
|
||||
|
||||
$id = required_param('id', PARAM_INT); // programming ID
|
||||
$format = optional_param('format', 'html', PARAM_CLEAN);
|
||||
|
||||
$params = array('id' => $id, 'format' => $format);
|
||||
$PAGE->set_url('/mod/programming/resemble/view.php', $params);
|
||||
|
||||
if (! $cm = get_coursemodule_from_id('programming', $id)) {
|
||||
print_error('invalidcoursemodule');
|
||||
}
|
||||
|
||||
if (! $course = $DB->get_record('course', array('id' => $cm->course))) {
|
||||
print_error('coursemisconf');
|
||||
}
|
||||
|
||||
if (! $programming = $DB->get_record('programming', array('id' => $cm->instance))) {
|
||||
print_error('invalidprogrammingid', 'programming');
|
||||
}
|
||||
|
||||
require_login($course->id, true, $cm);
|
||||
|
||||
$context = context_module::instance($cm->id);
|
||||
|
||||
require_capability('mod/programming:viewresemble', $context);
|
||||
|
||||
$sql = "SELECT re.*, sa.userid AS userid1, sb.userid AS userid2
|
||||
FROM {programming_resemble} AS re,
|
||||
{programming_submits} AS sa,
|
||||
{programming_submits} AS sb
|
||||
WHERE re.programmingid={$programming->id}
|
||||
AND re.flag > 0
|
||||
AND sa.programmingid={$programming->id}
|
||||
AND sb.programmingid={$programming->id}
|
||||
AND re.submitid1 = sa.id
|
||||
AND re.submitid2 = sb.id
|
||||
AND (sa.userid = $USER->id OR sb.userid = $USER->id)
|
||||
ORDER BY re.id";
|
||||
$resemble = $DB->get_records_sql($sql);
|
||||
if (!is_array($resemble)) $resemble = array();
|
||||
|
||||
$uids = array();
|
||||
foreach($resemble as $r) {
|
||||
$uids[] = $r->userid1;
|
||||
$uids[] = $r->userid2;
|
||||
}
|
||||
if (!empty($uids)) {
|
||||
$users = $DB->get_records_select('user', 'id IN ('.implode($uids, ',').')');
|
||||
}
|
||||
|
||||
/// Print page content
|
||||
if ($format == 'json') {
|
||||
require_once('../lib/JSON.php');
|
||||
$data = array(array_keys($resemble), array_values($resemble), array_keys($users), array_values($users));
|
||||
$json = new Services_JSON();
|
||||
echo $json->encode($data);
|
||||
} else {
|
||||
|
||||
/// Print the page header
|
||||
$PAGE->set_title($programming->name);
|
||||
$PAGE->set_heading(format_string($course->fullname));
|
||||
echo $OUTPUT->header();
|
||||
|
||||
/// Print tabs
|
||||
$renderer = $PAGE->get_renderer('mod_programming');
|
||||
$tabs = programming_navtab('resemble', 'resemble-view', $course, $programming, $cm);
|
||||
echo $renderer->render_navtab($tabs);
|
||||
|
||||
if (is_array($resemble) && count($resemble)) {
|
||||
$mediumdegree = get_string('mediumsimilitude', 'programming');
|
||||
$highdegree = get_string('highsimilitude', 'programming');
|
||||
|
||||
echo $OUTPUT->box_start('resemble-list');
|
||||
|
||||
// resemble-list
|
||||
$table = new html_table();
|
||||
$table->head = array(
|
||||
get_string('similitudedegree', 'programming'),
|
||||
get_string('program1', 'programming'),
|
||||
get_string('percent1', 'programming'),
|
||||
get_string('program2', 'programming'),
|
||||
get_string('percent2', 'programming'),
|
||||
get_string('matchedlines', 'programming')
|
||||
);
|
||||
$table->data = array();
|
||||
|
||||
foreach ($resemble as $r) {
|
||||
switch($r->flag) {
|
||||
case PROGRAMMING_RESEMBLE_WARNED:
|
||||
$styleclass = $styleclass1 = $styleclass2 = 'warned';
|
||||
$degree = $mediumdegree;
|
||||
break;
|
||||
case PROGRAMMING_RESEMBLE_CONFIRMED:
|
||||
$styleclass = $styleclass1 = $styleclass2 = 'confirmed';
|
||||
$degree = $highdegree;
|
||||
break;
|
||||
case PROGRAMMING_RESEMBLE_FLAG1:
|
||||
$styleclass = 'confirmed';
|
||||
$styleclass1 = 'confirmed';
|
||||
$styleclass2 = '';
|
||||
$degree = $highdegree;
|
||||
break;
|
||||
case PROGRAMMING_RESEMBLE_FLAG2:
|
||||
$styleclass = 'confirmed';
|
||||
$styleclass1 = '';
|
||||
$styleclass2 = 'confirmed';
|
||||
$degree = $highdegree;
|
||||
break;
|
||||
case PROGRAMMING_RESEMBLE_FLAG3:
|
||||
$styleclass = $styleclass1 = $styleclass2 = 'flag3';
|
||||
$degree = $highdegree;
|
||||
break;
|
||||
default:
|
||||
$styleclass = '';
|
||||
}
|
||||
|
||||
$url1 = new moodle_url('/user/view.php', array('id' => $r->userid1, 'course' => $course->id));
|
||||
$fullname1 = fullname($users[$r->userid1]);
|
||||
$url2 = new moodle_url('/user/view.php', array('id' => $r->userid2, 'course' => $course->id));
|
||||
$fullname2 = fullname($users[$r->userid2]);
|
||||
$urlcmp = new moodle_url('/mod/programming/resemble/compare.php', array('id' => $cm->id, 'rid' => $r->id));
|
||||
$table->data[] = array(
|
||||
html_writer::tag('span', $degree, array('class' => $styleclass)),
|
||||
html_writer::tag('span', $OUTPUT->user_picture($users[$r->userid1]).$OUTPUT->action_link($url1, $fullname1, null, array('title' => $fullname1)), array('class' => $styleclass1)),
|
||||
html_writer::tag('span', $r->percent1, array('class' => $styleclass1)),
|
||||
html_writer::tag('span', $OUTPUT->user_picture($users[$r->userid2]).$OUTPUT->action_link($url2, $fullname2, null, array('title' => $fullname2)), array('class' => $styleclass2)),
|
||||
html_writer::tag('span', $r->percent2, array('class' => $styleclass2)),
|
||||
html_writer::tag('span', $OUTPUT->action_link($urlcmp, $r->matchedcount), array('class' => $styleclass)) );
|
||||
}
|
||||
|
||||
echo html_writer::table($table);
|
||||
echo $OUTPUT->box_end();
|
||||
|
||||
} else {
|
||||
echo html_writer::tag('p', get_string('noresembleinfo', 'programming'));
|
||||
}
|
||||
|
||||
/// Finish the page
|
||||
echo $OUTPUT->footer($course);
|
||||
}
|
||||
Reference in New Issue
Block a user