-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproctor.py
178 lines (170 loc) · 6.09 KB
/
proctor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import json
import requests
from xblock.core import XBlock
from xblock.fields import Scope, Integer
from xblock.fragment import Fragment
class ProctoringXBlock(XBlock):
"""
A custom XBlock for proctoring exams in Open edX.
"""
# XBlock fields
exam_id = Integer(help="The ID of the exam being proctored.", scope=Scope.user_state)
def start_proctoring(self, exam_id):
"""
Start the proctoring process for the specified exam ID.
"""
self.exam_id = exam_id
url = "http://proctoring.api/start_proctoring"
data = {"exam_id": exam_id}
headers = {"Content-Type": "application/json"}
response = requests.post(url, data=json.dumps(data), headers=headers)
response.raise_for_status()
def stop_proctoring(self):
"""
Stop the proctoring process for the current exam ID.
"""
if self.exam_id is not None:
url = "http://proctoring.api/stop_proctoring"
data = {"exam_id": self.exam_id}
headers = {"Content-Type": "application/json"}
response = requests.post(url, data=json.dumps(data), headers=headers)
response.raise_for_status()
def submit_exam(self):
"""
Submit the exam for the current exam ID.
"""
if self.exam_id is not None:
url = "http://proctoring.api/submit_exam"
data = {"exam_id": self.exam_id}
headers = {"Content-Type": "application/json"}
response = requests.post(url, data=json.dumps(data), headers=headers)
response.raise_for_status()
def studio_view(self, context=None):
"""
The primary view of the ProctoringXBlock for course staff.
"""
html = """
<div>
<label for="exam_id">Exam ID:</label>
<input type="number" id="exam_id" name="exam_id">
<button id="start_proctoring">Start Proctoring</button>
<button id="stop_proctoring">Stop Proctoring</button>
<button id="submit_exam">Submit Exam</button>
</div>
<script>
$(function() {
$("#start_proctoring").click(startProctoring);
$("#stop_proctoring").click(stopProctoring);
$("#submit_exam").click(submitExam);
});
function startProctoring() {
var exam_id = $("#exam_id").val();
$.ajax({
url: "start_proctoring",
type: "POST",
data: {exam_id: exam_id},
success: function(response) {
alert("Proctoring started for exam " + exam_id);
},
error: function(xhr, status, error) {
alert(xhr.responseText);
}
});
}
function stopProctoring() {
$.ajax({
url: "stop_proctoring",
type: "POST",
success: function(response) {
alert("Proctoring stopped");
},
error: function(xhr, status, error) {
alert(xhr.responseText);
}
});
}
function submitExam() {
$.ajax({
url: "submit_exam",
type: "POST",
success: function(response) {
alert("Exam submitted");
},
error: function(xhr, status, error) {
alert(xhr.responseText
}
});
}
</script>
"""
frag = Fragment(html)
frag.add_css("""
label {
display: inline-block;
width: 100px;
}
input {
width: 150px;
}
button {
margin-left: 10px;
}
""")
return frag
def student_view(self, context=None):
"""
The primary view of the ProctoringXBlock for students.
"""
html = """
<div>
<p>Proctoring is currently in progress for this exam.</p>
<p>Please complete the exam before the proctoring session ends.</p>
</div>
"""
frag = Fragment(html)
return frag
def submit_studio_form(self, data, suffix=''):
"""
Handle a form submission from the ProctoringXBlock studio view.
"""
if "exam_id" in data:
self.start_proctoring(data["exam_id"])
@XBlock.handler
def start_proctoring(self, request, suffix=''):
"""
Handle a request to start proctoring for an exam.
"""
if request.method == "POST":
exam_id = request.POST.get("exam_id")
if exam_id is not None:
self.start_proctoring(int(exam_id))
return HttpResponse(status=204)
return HttpResponseBadRequest()
@XBlock.handler
def stop_proctoring(self, request, suffix=''):
"""
Handle a request to stop proctoring for the current exam.
"""
if request.method == "POST":
self.stop_proctoring()
return HttpResponse(status=204)
return HttpResponseBadRequest()
@XBlock.handler
def submit_exam(self, request, suffix=''):
"""
Handle a request to submit the current exam.
"""
if request.method == "POST":
self.submit_exam()
return HttpResponse(status=204)
return HttpResponseBadRequest()
@staticmethod
def workbench_scenarios():
"""
Define the scenarios for the ProctoringXBlock in the workbench.
"""
return [
("ProctoringXBlock",
"""<proctoring/>
"""),
]