Share JSXGraph: example "Exploring Functions (assessment)"

JSXGraph
Share JSXGraph: example "Exploring Functions (assessment)"
This website is a beta version. The official release will be in **2023**.

Exploring Functions (assessment)

This example can be used for assessment tasks with graphical input. The input variables have to be generated by the course system (e.g randomly). The output variables must be binded to the course system's answer method. If you change elements within the board, you will find the result below.

Question: Values of the Derivative of a Function

Mark the intervals in which the derivative of the function {f(x)} is positive, negative or 0.

First divide the domain of the function into intervals. To do this, drag the interval separators from the green box at the bottom right.

Then move the horizontal interval sliders down to red (negative derivative) or up to blue (positive derivative).

Result

[Change JSXGraph construction.]

Input

\([\{boundingbox_{xMin}\}, \) \(\{boundingbox_{yMax}\}, \) \(\{boundingbox_{xMax}\}, \) \(\{boundingbox_{yMin}\}, \) \(\{y_{bar}\}, \) \(\{intValue_1\}, \) \(\{intSeparator_1\}, \) \(\{intValue_2\}, \) \(\{intSeparator_2\}, ...,\) \(\{intSeparator_{N-1}\}, \)\(\{intVaule_N\}, \) \(\{f(x)\}]\)

\(\{intValue_i\}\in\{-1, 0, 1\}\)

Output

\([\{int_{begin}\}, \) \(\{intValue_1\}, \) \(\{intSeparator_1\}, \) \(\{intValue_2\}, \) \(\{intSeparator_2\}, ...,\) \(\{intSeparator_{M-1}\}, \) \(\{intValue_M\}, \) \(\{int_{end}\}]\)

\(M\) Number of Separators (outside the box)

<h4>Question: Values of the Derivative of a Function</h4>
Mark the intervals in which the derivative of the function {f(x)} is positive, negative or 0.
<p/>
First divide the domain of the function into intervals.
To do this, drag the interval separators from the green box at the bottom right.
<p/>
Then move the horizontal interval sliders down to red (negative derivative) or up to blue (positive derivative).
// Define the id of your board in BOARDID

// input data from LMS

let input = [
    -10, 10, 10, -10,           // boundingbox JSXGraph
    -8,                         // y coordinate (integer) of the interval bar
    0, 10,                      // interval value 1, separator 1
    0, 10,                      // interval value 2, separator 2
    0, 10,                      // interval value 3, separator 3
    0, 10,                      // interval value 4, separator 4
    0, 10,                      // interval value 5, separator 5
    0,                          // interval value 6,
    '0.1*x^3+0.25*x^2-0.5*x-1'  // function term
];

// visual adjustment necessary

let padding = 1;                // depends on xMax of boundingBox

// digits of results

let digits = 2;                 // digits

//

let xMin = input[0], xMax = input[2], yMax = input[1], yMin = input[3]; // JSXGraph boundingbox
let xStore = xMax - padding;    // position of the green box where the separators are "stored"
let yBar = input[4];            // interval bar

// JSXGraph board

const board = JXG.JSXGraph.initBoard(BOARDID, {
    boundingbox: [xMin, yMax, xMax, yMin],
    keepAspectRatio: true,
    axis: true,
    grid: false,
    defaultAxes: {x: {ticks: {label: {visible: false}}}, y: {ticks: {label: {visible: false}}}},
    showNavigation: false,
    showCopyright: false
});

// function graph

let f = board.create('functiongraph', [input[input.length - 1]], {
    strokeWidth: 2
});

// interval bar with green separator box

let A = board.create('point', [xMin, yBar], {
    fixed: true,
    visible: false
});
let B = board.create('point', [xStore, yBar], {
    fixed: true,
    visible: false
});
let s = board.create('segment', [A, B], {
    fixed: true,
    strokeWidth: 20,
    strokeColor: '#ffffff',
    highLight: false
});
let store = board.create('segment', [[xStore, yBar - padding / 2], [xStore, yBar + padding / 2]], {
    fixed: true,
    strokeWidth: 30,
    linecap: 'round',
    strokeColor: '#66cc33',
    highLight: false
});

//  separator handling

let G = [];
let P = [];
let coordsX = [];
let interval = [];
let sCount = (input.length - 7) / 2;

for (let i = 0; i < sCount; i++) {
    G[i] = board.create('glider', [input[6 + i * 2], 0, s], {
        name: '',
        face: '|',
        size: 10,
        strokeWidth: 3,
        strokeColor: '#000000',
        highlight: false,
        showInfoBox: false
    });
    G[i].on('drag', function (e) {
        sortSeparators();
    });
}

// all separators including begin and end separators

P.push(A);
for (let i = 0; i < G.length; i++)
    P.push(G[i]);
P.push(B);

// sort separators

let sortSeparators = function () {
    for (let i = 0; i < P.length; i++)
        coordsX[i] = P[i].X();
    coordsX.sort(function (a, b) {
        return a - b;
    });
    document.getElementById('outputID').innerHTML = output();
}

sortSeparators();

// create separators

for (let i = 0; i < P.length; i++) {
    let Pi = board.create('point', [() => {
        return coordsX[i];
    }, yBar], {visible: false});
    let Pi1 = board.create('point', [() => {
        return coordsX[i + 1];
    }, yBar], {visible: false});
    let l = board.create('segment', [Pi, Pi1], {strokeColor: '#cccccc', highlight: false, strokeWidth: 20});
    let n = board.create('segment', [[() => {
        return coordsX[i];
    }, xMin], [() => {
        return coordsX[i];
    }, xMax]], {
        strokeColor: '#999999', dash: 2, strokeWidth: 1, point1: {visible: false}, visible: () => {
            return (Math.abs(coordsX[i] - xStore) > 0.5 ? true : false);
        }
    });
    let m = board.create('segment', [[() => {
        return (Pi.X() + Pi1.X()) / 2;
    }, yBar - padding / 4], [() => {
        return (Pi.X() + Pi1.X()) / 2;
    }, yBar + padding / 4]], {name: '', visible: false});
    interval[i] = board.create('glider', [0, yBar + input[5 + i * 2] * padding, m], {
        name: '',
        face: '-',
        size: 6,
        strokeWidth: 3,
        strokeColor: '#000000',
        fillColor: '#000000',
        snapToGrid: true,
        highlight: false,
        snapToPoint: true,
        showInfoBox: false,
        visible: () => {
            return (l.L() > 1 ? true : false);
        }
    });
    let p = board.create('polygon', [[() => {
        return Pi.X();
    }, yMax], [() => {
        return (Pi1.X() == xStore ? xMax : Pi1.X());
    }, yMax], [() => {
        return (Pi1.X() == xStore ? xMax : Pi1.X());
    }, yMin], [() => {
        return Pi.X();
    }, yMin]], {
        highlight: false,
        strokeWidth: 20,
        vertices: {visible: false},
        borders: {visible: false},
        visible: () => {
            return (Pi.X() == xStore ? false : true);
        }
    });
    let t = board.create('text', [() => {
        return coordsX[i + 1];
    }, yBar - padding, () => {
        return ' ' + (i + 1) + ' ';
    }], {
        cssStyle: 'border: solid 2px black; padding: 2px 5px 2px 5px; background-color: #ffffff; margin: ' + (padding / 2) + 'px 0px 0px -10px; border-radius: 15px;',
        anchorX: 'left',
        anchorY: 'middle'
    });
    l.setAttribute({
        strokeColor: () => {
            return (interval[i].Y() != yBar ? (interval[i].Y() > yBar ? '#99ccff' : '#ffcccc') : '#cccccc');
        }
    });
    interval[i].setAttribute({
        strokeColor: () => {
            return (interval[i].Y() != yBar ? (interval[i].Y() > yBar ? '#0000ff' : '#ff0000') : '#666666');
        }
    });
    t.setAttribute({
        visible: () => {
            return (l.L() > 0.6 & (Math.abs(coordsX[i + 1] - xStore) > 1) ? true : false);
        }
    });
    p.setAttribute({
        fillColor: () => {
            return (interval[i].Y() != yBar ? (interval[i].Y() > yBar ? '#99ccff' : '#ffcccc') : '#ffffff');
        }
    });
    interval[i].on('drag', function (e) {
        sortSeparators();
    });
}

// output data for LMS, additional binding to LMS necessary

function output () {
    let out = [];
    let i = 0;
    while (coordsX[i] < xStore) {
        out.push(Math.round(coordsX[i] * Math.pow(10, digits)) / Math.pow(10, digits));
        try {
            let x = interval[i].Y() - yBar;
            if (x > 0)
                out.push(1);
            else if (x < 0)
                out.push(-1);
            else
                out.push(0);
        } catch (e) {
        }
        i++;
    }
    out.push(xMax);
    return out;
}
<h4>Result</h4>
[<span id="outputID">Change JSXGraph construction.</span>]

<h4>Input</h4>

\([\{boundingbox_{xMin}\}, \)
\(\{boundingbox_{yMax}\}, \)
\(\{boundingbox_{xMax}\}, \)
\(\{boundingbox_{yMin}\}, \)
\(\{y_{bar}\}, \)
\(\{intValue_1\}, \)
\(\{intSeparator_1\}, \)
\(\{intValue_2\}, \)
\(\{intSeparator_2\}, ...,\)
\(\{intSeparator_{N-1}\},
\)\(\{intVaule_N\}, \)
\(\{f(x)\}]\)
<p/><p/>

\(\{intValue_i\}\in\{-1, 0, 1\}\)

<h4>Output</h4>

\([\{int_{begin}\}, \)
\(\{intValue_1\}, \)
\(\{intSeparator_1\}, \)
\(\{intValue_2\}, \)
\(\{intSeparator_2\},
...,\)
\(\{intSeparator_{M-1}\}, \)
\(\{intValue_M\}, \)
\(\{int_{end}\}]\)
<p/><p/>
\(M\) Number of Separators (outside the box)