CTATProtractor - CMUCTAT/CTAT GitHub Wiki

CTATProtractor

This component shows a user a protractor with movable rays and supports a number of configuration options. A very basic CTATProtractor allows a user to move a single ray between 0 and 180 degrees.

Any number of movable rays can be added to the protractor, as well as two non-movable 'base' rays that are the primary basis for angle measures.

The protractor supports up to two sets of labels. One set runs along the inside of the protractor arc, and the other runs along the outside. Only the outside set is on by default. Either set can be configured to display degrees or radians.

Users click and drag on the interactive points to set the position of the rays on the protractor. Users can set custom tick mark intervals on the protractor, and can put it into 'snap' mode so that clicking and dragging is locked to the tick marks.

* Note: correct/incorrect/hint highlighting only currently works in Firefox. Necessary update for Chromium slated for version 89 (noted at version 87)

Code

User can move ray A around the protractor:

<div id="protractor" class="CTATProtractor"></div>

Running Example

CTATProtractor Example

Attributes and Settings

  • id: Required. The name of the component, must be a valid html id name.
  • class: Required. The class list, must include "CTATProtractor" and no other CTAT classes.
  • data-ctat-interactive-points: String of single-letter labels for interactive points. Default is "A". e.g. providing "ABC" as a parameter will create three interactive points/rays, labeled "A", "B", and "C".
  • data-ctat-base-points: String of single-letter labels for non-interactive base points. The first letter in the string will label the origin point of the protractor. Default is "OB" (producing a single base point/ray labelled "B", and an origin point labelled "O"). Maximum number of base rays is 2; e.g. supplying the parameter "ABCD" will result in an origin point "A", and two base rays "B" and "C", ignoring "D".
  • data-ctat-outer-labels: String of keywords to designate the type of, and direction of, labels on the outside of the protractor. Default is "counterclockwise degrees". Direction may be either "clockwise" or "counterclockwise", and type may be either "degrees" or "radians". Supplying a parameter value of "none" results in no labels.
  • data-ctat-inner-labels: String of keywords to designate the type of, and direction of, labels on the inside of the protractor. Default is "none". Direction may be either "clockwise" or "counterclockwise", and type may be either "degrees" or "radians". Supplying a parameter value of "none" results in no labels.
  • data-ctat-unit-of-measure: String to designate the type of measure unit generated by the protractor. Default is "degrees". Alternative values are "radians" (generates decimal values of radian measure) and "fraction" (generates a fraction string of the radian measure).*
  • data-ctat-precision: Number value to set the precision of radian measures; works in tandem with data-ctat-unit-of-measure (UoM).
    • If UoM is set to 'radians', this sets the number of decimal places for angles (e.g. parameter value of "4" will give 4 decimal places). Default for radians is 2 decimal places.
    • If UoM is set to 'fraction', this sets a fixed denominator and rounds to the closest whole numerator (e.g. parameter value of "4" will round all inputs to either 0, 1/4, 2/4, 3/4, or 4/4). Default for fractions is simplest denominator (e.g. 15 degree measure will generate "1/12", 11 degree measure will generate "11/180").
  • data-ctat-interval: Sets the angle tick mark & snap interval in degrees. Default is "15". Maximum is "90". Value must evenly divide 180, or else interval remains default.
  • data-ctat-snap: true or false. Default is false. If true, interactive points will snap to tick mark intervals while being moved.
  • data-ctat-drag-on-arc: true or false. Default is true. If true, interactive points will stay locked to the protractor arc while being moved.

* e.g. an angle of 15 degrees, equivalent to π/12 will generate a "radian" value of 0.262, or a "fraction" string of "1/12", where the π multiplier is implied.

*Under development:*

  • data-ctat-ctrl-radians: A list of ; deliminated ids of CTAT controller components that the user interacts with to change the labels that are visible between radian or degree. Default is "".
  • data-ctat-ctrl-interval: A list of ; deliminated ids of CTAT controller components that the user interacts with to change the value of the tickmark/snapping interval. Default is "".

Valid CTAT controller components include CTATButton, CTATImageButton, CTATTextInput, and CTATNumericStepper.

Action-Input

In addition to the common Actions listed in Often Used TPAs this component supports the following actions:

Action Input Notes
chooseAngle a string designating an angle selects an angle for the protractor to report, and puts it into "chosen" mode (see below). Name must be a valid angle in the current protractor (e.g. input of "ABC" requires an interactive point named "A", an origin point named "B", and another interactive point or base point named "C". After a valid angle is chosen using this Action, subsequent setAngle Actions will expect/report only the angle measure of the designated angle (e.g. instead of '"ABC":45', the ABC is assumed and input will only be '45')
setAngle a number or angle name/value string Moves an interactive point/ray to create the specified angle. Number inputs require protractor to be in "chosen" mode. Otherwise, strings should take the form "angle_name": angle_value - for example, "ABC": 123 will move point A to a position such that angle ABC is 123 degrees. *See section on Correctness Checking
lockPoints a string of interactive point names Locks the designated points at their current position (can no longer be moved by user). A blank value for the input will lock all interactive points in the protractor.
unlockPoints a string of interactive point names Unlocks the designated points at their current position (can again be moved by user). A blank value for the input will unlock all interactive points in the protractor.
hidePoints a string of interactive point names Hides the designated points at their current position (no longer visible/interactive). A blank value for the input will hide all interactive points in the protractor.
showPoints a string of interactive point names Shows currently hidden points (visible and can again be moved by user). A blank value for the input will show all currently hidden interactive points in the protractor.
fadeOutPoints a string of interactive point names Fades out the designated points at their current position (no longer visible/interactive). A blank value for the input will fade out all interactive points in the protractor.
fadeInPoints a string of interactive point names Fades in currently hidden points (visible and can again be moved by user). A blank value for the input will fade in all currently hidden interactive points in the protractor.
hideLabels "inner" or "outer" Hides the designated label set.
showLabels "inner" or "outer" Shows the designated label set.

* It may be easiest to think of the protractor as operating in one of two modes: "chosen" mode, where a specific angle has been chosen and the protractor is now only working with/reporting on the "chosen" angle; and "open" mode, where the protractor is working with/reporting all possible angles. Note that if there is only one angle in the protractor (e.g. only one base point and one interactive point), the protractor defaults to "chosen" mode.

For example, in the protractor below, there are two interactive points (A and E) and two base points (C and D), making a total of five possible angles in the protractor.

Example Protractor

Let's look at the case of moving point E 15 degrees to the left:

Moved Example Protractor

If we are operating in "open" mode, setAngle will report all possible angles created from that change:

"ABC":75, "ABD":105, "EBC":120, "EBD":60, "ABE":45

However, if we were to go into "chosen" mode by doing "chooseAngle" of input "ABC" first, setAngle will only report:

75

Or if we did a "chooseAngle" of input "ABE", setAngle will only report:

45

If the protractor is in "chosen" mode, setAngle TPAs require only an angle value, and will adjust the chosen angle according to that angle value input.

Styling

Here is a list of the default styles included in CTAT.css that govern various aspects of the look of the number line.

.CTATProtractor {
  min-height: 200px;
  min-width: 400px;
  max-width: 1000px;
  max-height: 500px;
  display: contents;
}

.CTATProtractor--container {
  height: auto;
  width: 100%;
  outline: 2px solid cornflowerblue;
  outline-offset: -2px;
}

.CTATProtractor--compass {
  stroke: rgb(131, 171, 245);
  stroke-width: 3px;
  fill: none;
}

.CTATProtractor--ticks {
  stroke: rgb(163, 118, 5);
  stroke-width: 4px;
}

.CTATProtractor--labels {
  text-anchor: middle;
  fill: rgb(47, 110, 182);
  font-size: 80%;
}

.CTATProtractor--label90 {
  font-weight: bold;
  font-size: 125%;
}

.CTATProtractor--label-origin {
  text-anchor: middle;
  font-style: italic;
  stroke: none;
  font-size: 125%;
  fill: blue;
}

.CTATProtractor--protrays {
  stroke: rgb(0, 204, 194);
  fill: rgb(0, 204, 194);
  stroke-width: 2;
}

.CTATProtractor--fgrays {
  stroke: blue;
  fill: blue;
  stroke-width: 2;
}

.CTATProtractor--labelray {
  text-anchor: middle;
  font-style: italic;
  stroke: none;
  font-size: 100%;
}

.CTATProtractor--select {
  cursor: grab;
  user-select: auto;
}

.CTATProtractor--correct {
  filter: drop-shadow(0 -1px 3px limegreen) drop-shadow(1px 0 3px limegreen)
    drop-shadow(0 1px 3px limegreen);
}
.CTATProtractor--incorrect {
  filter: drop-shadow(0 -1px 3px red) drop-shadow(1px 0 3px red)
    drop-shadow(0 1px 3px red);
}
.CTATProtractor--hint {
  filter: drop-shadow(0 -1px 3px yellow) drop-shadow(1px 0 3px yellow)
    drop-shadow(0 1px 3px yellow);
}

Correctness Checking

If the protractor is operating in "open" mode, special Javascript functions are required to successfully check whether student manipulations of the protractor match the desired input. These functions should be included in a JS file linked to the HTML file that specifies the interface. They will be called in the .BRD file for the problem:

The function below checks whether the student input falls within a certain range, allowing some tolerance for so students do not have to get the ray on the exact degree:

function checkProtractorInputRange(angleName, lower, upper, input) {
  inp = JSON.parse("{"+input+"}");
  inpAngle = Math.abs(inp[angleName]);

  return (inpAngle >= lower && inpAngle <= upper);
}

An example of a correctly configured student-input matcher for setting angle EBD to 120 degrees with a tolerance of 2 degrees in either direction is shown below:

Example Example Matcher Image

Based on these values, as long as the student moves ray E such that the measure of angle EBD is between 118 and 122 degrees, the tutor will accept it as correct, and it will then move ray E so that the angle EBA measures exactly 120 degrees.

Note that the matcher must be set to "boolean".

Also, please note that the JSON string for "Replace Student Input" MUST be surrounded by single quotes, but the JSON string for "Demonstrated Value - Input" must NOT have any quotes. This is necessary for hint highlighting and correctness highlighting to work.

If you do not want to replace student input with a precise value and want correctness highlighting to work properly, pass a null value for the angle (e.g. '"EBA": null').

Dynamically Accessing Angle Measures

If you would like to access the measures of specific angles that have been set for the protractor (e.g. for the purposes of hint/bug messages), you will need special Javascript functions in a problem file, similar to Correctness Checking:

window.onload = function () {
  protractor = this.CTATShellTools.findComponent('your_protractor_id_here')[0];
  console.log(protractor.reportAngle("some_valid_angle_name"));
}

function angleReturner(angleName) {
  reporting_angle = protractor.reportAngle(angleName);
  return reporting_angle;  
}

Calls to angleReturner() with a specified angle name will give you the current value of that angle on the protractor. (e.g. angleReturner("ABD") will give the current measurement of angle ABD).

Mass Production

Example for mass producing the labels, interactive points, base points, UoM, precision, drag-on-arc, interval, and snap for a CTATProtractor:

<div id="angles" class="CTATProtractor"
    data-ctat-inner-labels="%(innerlabels)%" 
    data-ctat-outer-labels="%(outerlabels)%"
    data-ctat-interactive-points="%(interactive_points)%"  
    data-ctat-base-points="%(base_points)%"
    data-ctat-unit-of-measure="%(uom)%"
    data-ctat-precision="%(precision)%"
    data-ctat-drag-on-arc="%(dragonarc)%"
    data-ctat-interval="%(interval)%" 
    data-ctat-snap="%(snap)%">
</div>
⚠️ **GitHub.com Fallback** ⚠️