Skip to content

ambco-iscte/jask

Repository files navigation

Jask

A Library for Generating Questions about Learners' Code in Java

ACM ITiCSE '22 - Check out Jask's original paper!

ICPEC 2025 - Check out a small study using Jask!

Jask is a library for generating Questions about Learners' Code (QLCs) targeting Java code. Jask aims to reframe previous work on QLCs as a library which can be integrated into existing educational programming environments to promote program comprehension. Jask provides question templates which can be applied to snippets of Java code to generate concrete questions targeting that code.

InstallationWhat is Jask?Question TypesExamples



⚙️ Installation

Important

Jask requires Strudel.

Jask is an experimental library, and as such is not yet available in build automation tools (Gradle, etc.)

To use Jask in your project, first build its .jar file using Gradle's build task. The .jar file is generated under the project root in /build/libs. This file should be copied to your own project's libs folder, and then added as a dependency in your build automation tool of choice. For example (in Kotlin Gradle):

dependencies {
    implementation(files("libs/jask-0.5.5.jar"))
}

The file name can change depending on the version of Jask, and should be changed in your dependency specification accordingly.


🤔 Question Types

Structural -- pt.iscte.jask.templates.structural

Structural QLCs target structural/static aspects of code.

Dynamic -- pt.iscte.jask.templates.dynamic

Dynamic QLCs target dynamic aspects of the code's execution.

Quality -- pt.iscte.jask.templates.quality

Quality QLCs target anti-patterns and code refactor opportunities. The aim of these QLCs is to provide students with an an opportunity to reflect about how the quality of their code could be improved.

Errors -- pt.iscte.jask.errors

Error QLCs target compiler and runtime errors. The aim of these QLCs is to provide students with an opportunity to reflect critically about their code's errors.


👉 Examples

Structural QLC

val src = """
    class Test {
        static double average(int a, int b) {
            double n = 2.0;
            return (a + b) / n;
        }           
    }
"""

val qlc = HowManyVariables().generate(src)
println(qlc)
How many variables (not including parameters) does the function [average] have?
--------------------------------------
static double average(int a, int b) {
    double n = 2.0;
    return (a + b) / n;
}    
--------------------------------------
[ ] 2
[ ] 3
[x] 1
[ ] 4

Dynamic QLC

val src = """
    class Test {
        static double abs(double n) {
            if (n < 0)
                return -n;
            else
                return n;
        }
    }
""".trimIndent()

val qlc = WhichReturnExecuted().generate(src, ProcedureCall(
    id = "abs",
    arguments = listOf(-2.0)
))
Which return statement (line) executed when calling [abs(-2.0)]?
------------------------------
static double abs(double n) {
    if (n < 0)
        return -n;
    else
        return n;
}
------------------------------
[x] Line 3
[ ] Line 5

Runtime Error QLC

val src = """
    class ArrayUtils {
        static int sum(int[] a) {
            int s = 0;
            for (int i = 0; i <= a.length; i++)
                s += a[i];
            return s;
        }
    }
""".trimIndent()

val (result, qlcs) = QLCVirtualMachine(src).execute("sum", listOf(1, 2, 3, 4, 5))

qlcs.forEach { 
    println(it) 
}
The function call [sum([1, 2, 3, 4, 5])] threw an ArrayIndexOutOfBounds 
exception at line 4: the index [5] is invalid for the array [a].
------------------------------------------
static int sum(int[] a) {
    int s = 0;
    for (int i = 0; i <= a.length; i++) {
        s = s + a[i];
    }
    return s;
}
------------------------------------------

Which is the length of the array [a]?
[ ] 4
[ ] 0
[ ] 6
[x] 5

Which is the last valid index of the array [a]?
[ ] 3
[ ] 5
[x] 4
[ ] 0

Which variable is being used to access the array [a]?
[ ] s
[x] i
[ ] a
[ ] None of the above.

Which is the sequence of values taken by the variable [i] 
when calling [sum([1, 2, 3, 4, 5])]?
[x] 0, 1, 2, 3, 4, 5
[ ] 1, 2, 3, 4, 5
[ ] 1, 3, 6, 10, 15
[ ] 0, 1, 2, 3, 4

🔠 Translating Jask

Jask provides a localisation module which allows developers to translate the content of questions into any language. The localisation module relies on language files present in the resources folder.

Each language files contains a set of key-value pairs corresponding to the different localisabe elements in Jask. In the translations %s is used to denote a value that will be filled in (automatically!) by Jask when using that translation.

If you want to add a new language and make it available in Jask, feel free to make a pull request with your own language files! You can add these to the initblock of the initialisation module. Otherwise, a language can be loaded from any folder (containing the .properties files) located in the project's resources folder using Localisation.loadLanguageFromResource("name of language folder").


📝 Publications Using Jask


© Credit

About

A Library for Generating Questions about Learners' Code in Java

Topics

Resources

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •  

Languages