Are you sure this is worth the effort, Ilyin? Why not just have a separate version of the question for each language you're offering to the student? I agree it's not very elegant but it's way easier than all the alternatives.
However, since you ask ...
By the "state" of the drop-down language menu (an HTML select element) I meant whatever value is currently selected. Getting that state value into the question requires a script within the question text, which would need to (say) insert a line at the start of the student answer, preferably in a language-specific comment, such as
// LANGUAGE = C
or
# LANGUAGE = Python
I managed to get a script like that going in preview mode but getting it working in a general would be much harder and I really don't think it's an idea worth pursuing. Far better to tell students to insert a line like that themselves at the start of their program.
I've added a section to the documentation explaining how to add new languages by scripting in Python. See http://coderunner.org.nz/mod/book/view.php?id=193&chapterid=749
You can extend the idea explained in that section of the documentation to implement a multi-language questions. For example, here's a per-test template to run a submission in either Python or C depending on the comment line at the start of the submitted program:
""" The template for a question type that accept either C or Python answers, requiring
that the first line of the program is a # or // comment for Python or C respectively.
"""
import subprocess
student_answer = """{{ STUDENT_ANSWER | e('py') }}"""
if student_answer.startswith('#'):
language = 'python'
filename = 'prog.py'
elif student_answer.startswith('//'):
language = 'c'
filename = 'prog.c'
else:
raise Exception("Illegal submission. Program must start with a comment.")
# Write the student code to a file
with open(filename, "w") as src:
print(student_answer, file=src)
# Compile if it's C
if language == 'c':
cflags = "-std=c99 -Wall -Werror"
return_code = subprocess.call("gcc {0} -o prog prog.c".format(cflags).split())
if return_code != 0:
raise Exception("** Compilation failed. Testing aborted **")
exec_command = ["./prog"]
else: # Python doesn't need a compile phase
exec_command = ["python3", "./prog.py"]
# Now run the code. Since this is a per-test template,
# stdin is already set up for the stdin text specified in the test case,
# so we can run the compiled program directly.
try:
output = subprocess.check_output(exec_command, universal_newlines=True)
print(output)
except subprocess.CalledProcessError as e:
if e.returncode > 0:
# Ignore non-zero positive return codes
if e.output:
print(e.output)
else:
# But negative return codes are signals - abort
if e.output:
print(e.output, file=sys.stderr)
if e.returncode < 0:
print("Task failed with signal", -e.returncode, file=sys.stderr)
print("** Further testing aborted **", file=sys.stderr)
Please realise though that that's just a prototype that's had minimal testing. It will undoubtedly need refining. I've never actually used multilingual questions myself.
Richard