|
|
|
|
|
shapeParams.forEach((d) => (d.startX = d.startX * 1.1)); |
|
|
|
|
|
const classifierBgPathTop = "M 420 150 H 0 V 0 H 420 V 150"; |
|
const classifierBgPathBottom = "M 420 300 H 0 V 0 H 420 V 300"; |
|
|
|
const toDropdownValueStringDict = { |
|
shape_name: "circles, triangles, or rectangles", |
|
pointiness: "pointy shapes or round shapes", |
|
size: "small shapes or big shapes", |
|
}; |
|
|
|
const toShortValueStringDict = { |
|
shape_name: "circles, triangles, or rectangles", |
|
pointiness: "pointy or round", |
|
size: "small or big", |
|
}; |
|
|
|
const toDropdownValueRoundingStringDict = { |
|
true: "with our best guess", |
|
false: 'as "other"', |
|
}; |
|
|
|
const toPropertyStringDict = { |
|
pointy: "pointy shapes", |
|
round: "round shapes", |
|
small: "small shapes", |
|
large: "big shapes", |
|
circle: "circles", |
|
triangle: "triangles", |
|
rect: "rectangles", |
|
}; |
|
|
|
function toOriginalString(inputString) { |
|
for (const [key, value] of Object.entries(toPropertyStringDict)) { |
|
if (inputString == value) { |
|
return key; |
|
} |
|
} |
|
} |
|
|
|
function toPropertyString(inputProperty, isRounding = true) { |
|
if (!isRounding && inputProperty.startsWith("rt_")) { |
|
return "others"; |
|
} |
|
return toPropertyStringDict[inputProperty.replace("rt_", "")]; |
|
} |
|
|
|
|
|
var allResults = {}; |
|
var summaries = {}; |
|
|
|
function toBool(inputString) { |
|
if (inputString == "true") { |
|
return true; |
|
} |
|
return false; |
|
} |
|
function updateResults() { |
|
allResults["default-classifier"] = calculateResults(); |
|
allResults["second-classifier"] = calculateResults( |
|
"shape_name", |
|
toBool( |
|
document.getElementById("second-classifier-select-rounding").value |
|
) |
|
); |
|
|
|
allResults["final-classifier"] = calculateResults( |
|
document.getElementById("final-classifier-select-category").value, |
|
toBool( |
|
document.getElementById("final-classifier-select-rounding").value |
|
) |
|
); |
|
|
|
allResults["conclusion"] = calculateResults( |
|
document.getElementById("conclusion-select-category").value, |
|
true |
|
); |
|
|
|
updateSummaries(); |
|
updateSecondInterfaceImages(); |
|
} |
|
|
|
|
|
|
|
|
|
function updateSummaries() { |
|
summaries["default-classifier"] = getPerformanceSummary("none"); |
|
summaries["second-classifier"] = getPerformanceSummary( |
|
"shape_name:" + |
|
document.getElementById("second-classifier-select-rounding").value |
|
); |
|
|
|
summaries["final-classifier"] = getPerformanceSummary( |
|
document.getElementById("final-classifier-select-category").value + |
|
":" + |
|
document.getElementById("final-classifier-select-rounding").value |
|
); |
|
|
|
summaries["conclusion"] = getPerformanceSummary( |
|
document.getElementById("conclusion-select-category").value + ":" + true |
|
); |
|
} |
|
|
|
|
|
|
|
function getPerformanceSummary(key) { |
|
allSummaries = { |
|
"shape_name:true": |
|
'<mark style="background-color: rgb(206, 234, 135);" class="well">well</mark> on circles, <mark style="background-color: rgb(244, 123, 74);" class="terribly">terribly</mark> on triangles, and <mark style="background-color: rgb(173, 220, 114);" class="best">best</mark> on rectangles', |
|
"shape_name:false": |
|
'<mark style="background-color: rgb(251, 163, 94);" class="poorly">poorly</mark> on circles, <mark style="background-color: rgb(155, 212, 108);" class="best">best</mark> on triangles and rectangles, and <mark style="background-color: rgb(252, 244, 171);" class="fine">fine</mark> on other shapes', |
|
"pointiness:true": |
|
'<mark style="background-color: rgb(184, 225, 119);" class="better">better</mark> on pointy shapes and <mark style="background-color: rgb(254, 206, 125);" class="worse">worse</mark> on round shapes', |
|
"pointiness:false": |
|
'<mark style="background-color: rgb(140, 205, 104);" class="best">best</mark> on pointy shapes, <mark style="background-color: rgb(243, 248, 171);" class="fine">fine</mark> on round shapes, and <mark style="background-color: rgb(253, 190, 111);" class="poorly">poorly</mark> on other shapes', |
|
"size:true": |
|
'<mark style="background-color: rgb(206, 234, 135);" class="better">better</mark> on small shapes, <mark style="background-color: rgb(254, 232, 154);" class="worse">worse</mark> on big shapes', |
|
"size:false": |
|
'<mark style="background-color: rgb(254, 215, 135);" class="poorly">poorly</mark> on small shapes, <mark style="background-color: rgb(165, 0, 38); color: #FFCCD8;" class="terribly">terribly</mark> on big shapes, and <mark style="background-color: rgb(110, 192, 99);" class="best">best</mark> on other shapes', |
|
"none:true": |
|
'<mark style="background-color: rgb(246, 248, 173);" class="fine">fine</mark> on all shapes', |
|
"none:false": |
|
'<mark style="background-color: rgb(246, 248, 173);" class="fine">fine</mark> on all shapes', |
|
none: '<mark style="background-color: rgb(246, 248, 173);" class="fine">fine</mark> on all shapes', |
|
}; |
|
|
|
return "The Is-Shaded Classifier performs " + allSummaries[key] + "."; |
|
} |
|
|
|
|
|
function updateSecondInterfaceImages() { |
|
d3.select(".second-interface").html(function () { |
|
if ( |
|
!document.getElementById("second-classifier-select-rounding").value |
|
) { |
|
return; |
|
} |
|
var imgPath = |
|
"img/interface_shape_name_" + |
|
document.getElementById("second-classifier-select-rounding").value; |
|
return ( |
|
'<img src="' + |
|
imgPath + |
|
'.png" alt="" class="interface-image" srcset="' + |
|
imgPath + |
|
'.svg"></img>' |
|
); |
|
}); |
|
} |
|
|
|
|
|
function calculateResults(property = "none", useGuess = false) { |
|
switch (property) { |
|
case "none": |
|
var nAccurate = shapeParams.filter( |
|
(shape) => shape.correctness == "correct" |
|
).length; |
|
var totalShapes = shapeParams.length; |
|
|
|
var results = [ |
|
{ |
|
object: "shape", |
|
n: totalShapes, |
|
"n correct": nAccurate, |
|
accuracy: (nAccurate / totalShapes).toFixed(3), |
|
rawCategoryName: "none", |
|
}, |
|
]; |
|
|
|
return results; |
|
case "pointiness": |
|
categories = ["pointy", "round"]; |
|
break; |
|
case "size": |
|
categories = ["small", "large"]; |
|
break; |
|
case "shape_name": |
|
categories = ["circle", "triangle", "rect"]; |
|
break; |
|
} |
|
|
|
var results = []; |
|
if (useGuess == true) { |
|
|
|
|
|
for (const category of categories) { |
|
|
|
var theseShapes = shapeParams.filter( |
|
(shape) => |
|
shape[property] == category || |
|
shape[property] == "rt_" + category |
|
); |
|
var nAccurate = theseShapes.filter( |
|
(shape) => shape.correctness == "correct" |
|
).length; |
|
var totalShapes = theseShapes.length; |
|
|
|
results.push({ |
|
object: toPropertyString(category), |
|
n: totalShapes, |
|
"n correct": nAccurate, |
|
accuracy: (nAccurate / totalShapes).toFixed(3), |
|
rawCategoryName: category, |
|
}); |
|
} |
|
} else { |
|
|
|
|
|
|
|
for (const category of categories) { |
|
var theseShapes = shapeParams.filter( |
|
(shape) => shape[property] == category |
|
); |
|
var nAccurate = theseShapes.filter( |
|
(shape) => shape.correctness == "correct" |
|
).length; |
|
var totalShapes = theseShapes.length; |
|
results.push({ |
|
object: toPropertyString(category), |
|
n: totalShapes, |
|
"n correct": nAccurate, |
|
accuracy: (nAccurate / totalShapes).toFixed(3), |
|
rawCategoryName: category, |
|
}); |
|
} |
|
|
|
|
|
var theseShapes = shapeParams.filter( |
|
(shape) => !categories.includes(shape[property]) |
|
); |
|
var nAccurate = theseShapes.filter( |
|
(shape) => shape.correctness == "correct" |
|
).length; |
|
var totalShapes = theseShapes.length; |
|
results.push({ |
|
object: "other shapes", |
|
n: totalShapes, |
|
"n correct": nAccurate, |
|
accuracy: (nAccurate / totalShapes).toFixed(3), |
|
rawCategoryName: "other", |
|
}); |
|
} |
|
|
|
return results; |
|
} |
|
|