Updates as per Team meeting 28 Aug 2025

This commit is contained in:
Peter Edmond 2025-05-28 19:53:00 +01:00
parent 9d6c761d15
commit 88853e955c
9 changed files with 581 additions and 185 deletions

View File

@ -1,7 +1,8 @@
function drawBar(id) {
function drawBar(id,data) {
//console.log(id);
const svg = d3.select(`${id}`); const svg = d3.select(`${id}`);
const backgroundwidth = +svg.attr("width"); const backgroundwidth = +svg.attr("width");
const backgroundradius = 10; const backgroundradius = 10;
@ -23,8 +24,9 @@ svg.append("rect")
// .attr("stroke-width", 2); // .attr("stroke-width", 2);
//const data = {
const data = { /*
data = {
"-3": 0, "-3": 0,
"-2": 1, "-2": 1,
"-1": 3, "-1": 3,
@ -33,6 +35,9 @@ const data = {
"2": 0, "2": 0,
"3": 10 "3": 10
}; };
*/
//console.log(data);
const dataArray = Object.entries(data).map(([key, count]) => ({ const dataArray = Object.entries(data).map(([key, count]) => ({
key: +key, key: +key,
@ -72,10 +77,6 @@ svg.append("g")
.selectAll("text") .selectAll("text")
.style("visibility", "hidden"); // This hides the labels .style("visibility", "hidden"); // This hides the labels
// Y Axis // Y Axis
//svg.append("g") //svg.append("g")
// .attr("transform", `translate(${margin.left},0)`) // .attr("transform", `translate(${margin.left},0)`)
@ -110,15 +111,14 @@ svg.selectAll(".label")
const format = d3.format(".2f"); const format = d3.format(".2f");
const totalCount = d3.sum(dataArray, d => d.count); const totalCount = d3.sum(dataArray, d => d.count);
const weightedSum = d3.sum(dataArray, d => d.key * d.count); const weightedSum = d3.sum(dataArray, d => d.key * d.count);
const average = totalCount > 0 ? format(weightedSum / totalCount) : 0; average = totalCount > 0 ? weightedSum / totalCount : 0;
const xLinear = d3.scaleLinear() const xLinear = d3.scaleLinear()
.domain([-3, 3]) .domain([-3, 3])
.range([margin.left + x.bandwidth() / 2, width - margin.right - x.bandwidth() / 2]); .range([margin.left + x.bandwidth() / 2, width - margin.right - x.bandwidth() / 2]);
const avgX = xLinear(average);
// const avgX = xLinear(average); //const avgX = xLinear(-0.50); // Temporary for testing
const avgX = xLinear(2.7); // Temporary for testing
svg.append("line") svg.append("line")
.attr("x1", avgX) .attr("x1", avgX)
@ -127,7 +127,7 @@ svg.append("line")
.attr("y2", y(d3.max(dataArray, d => d.count)) - 20) .attr("y2", y(d3.max(dataArray, d => d.count)) - 20)
.attr("stroke", "#e40074") // From brand guidelines .attr("stroke", "#e40074") // From brand guidelines
.attr("stroke-width", 4) .attr("stroke-width", 4)
.attr("stroke-dasharray", "6,2"); .attr("stroke-dasharray", "10,4");
/* /*
svg.append("text") svg.append("text")
@ -140,6 +140,7 @@ svg.append("text")
*/ */
// Title beneath the graph // Title beneath the graph
/*
svg.append("text") svg.append("text")
.attr("x", width / 2) .attr("x", width / 2)
.attr("y", height - 10) // Just below the x-axis .attr("y", height - 10) // Just below the x-axis
@ -147,13 +148,14 @@ svg.append("text")
.attr("font-size", "14px") .attr("font-size", "14px")
.attr("fill", "black") .attr("fill", "black")
.text("Demo bar graph"); .text("Demo bar graph");
*/
// Add infor to right of bar chart // Add info to right of bar chart
// Oblong settings // Oblong settings
const boxx = 620; const boxx = 610;
const boxy = 60; const boxy = 60;
const boxwidth = 150; const boxwidth = 170;
const boxheight = 80; const boxheight = 80;
const cornerRadius = 10; const cornerRadius = 10;
@ -185,9 +187,40 @@ svg.append("text")
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("dominant-baseline", "middle") .attr("dominant-baseline", "middle")
.attr("font-size", "20px") .attr("font-size", "20px")
.attr("font-weight", "900") // 400 is normal, 700 is bold, 900 is extra-bold .attr("font-weight", "400") // 400 is normal, 700 is bold, 900 is extra-bold
.attr("font-family", "sans-serif") .attr("font-family", "sans-serif")
.text("Average : 1.69"); .text("Average: ")
.append(function() {
return document.createElementNS("http://www.w3.org/2000/svg", "tspan");
})
.text(average.toFixed(1))
.attr("class", "average")
.attr("fill", "#e40074")
.attr("font-weight", "900");
// .text("Average : "+average.toFixed(2));
// Get the score gap:
let maxKey = null;
let minKey = null;
for (const [key, value] of Object.entries(data)) {
if (value > 0) {
const numKey = Number(key);
//console.log(numkey);
if (maxKey === null || numKey > maxKey) {
maxKey = numKey;
}
if (minKey === null || numKey < minKey) {
minKey = numKey;
}
}
}
scoregap = maxKey - minKey+1;
// Add text to the bottom half // Add text to the bottom half
svg.append("text") svg.append("text")
@ -196,8 +229,58 @@ svg.append("text")
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("dominant-baseline", "middle") .attr("dominant-baseline", "middle")
.attr("font-size", "20px") .attr("font-size", "20px")
.attr("font-weight", "900") // 400 is normal, 700 is bold, 900 is extra-bold .attr("font-weight", "400") // 400 is normal, 700 is bold, 900 is extra-bold
.attr("font-family", "sans-serif") .attr("font-family", "sans-serif")
.text("Score Gap : 6"); .text("Score gap: ")
.append(function() {
return document.createElementNS("http://www.w3.org/2000/svg", "tspan");
})
.text(scoregap)
.attr("font-weight", "900");
// .text("Score Gap : "+scoregap);
return average; //Needed for the next layer up in the analysis
} }
function doBarData(id,qid) {
return fetch('get_qid_counts.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({ qid })
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not OK');
}
return response.json();
})
.then(data => {
if (data.error) {
throw new Error(data.error);
}
// console.log(data);
// console.log(data[0][Object.keys(data[0])[0]]);
/* */
bardata = {
"-3": data[0][Object.keys(data[0])[0]],
"-2": data[1][Object.keys(data[1])[0]],
"-1": data[2][Object.keys(data[2])[0]],
"0": data[3][Object.keys(data[3])[0]],
"1": data[4][Object.keys(data[4])[0]],
"2": data[5][Object.keys(data[5])[0]],
"3": data[6][Object.keys(data[6])[0]],
};
//console.log(bardata);
drawBar(id,bardata);
// return data; // Should be an array like [{ value: -3, count: 2 }, ..., { value: 3, count: 5 }]
});
}

View File

@ -155,7 +155,7 @@ svg.append("text")
.attr("fill", "black") // 🎨 customize color .attr("fill", "black") // 🎨 customize color
.attr("font-size", bigfont) .attr("font-size", bigfont)
.attr("font-weight", "bold") .attr("font-weight", "bold")
.attr("font-family", "Courier New, monospace") .attr("font-family", 'sans-serif, Consolas, "Lucida Console", Menlo, "DejaVu Sans Mono", monospace')
.text(`${mean}`); .text(`${mean}`);
// Add axis labels // Add axis labels

View File

@ -133,7 +133,7 @@ const midY = (bottomLeft[1] + bottomRight[1]) / 2;
if (!svg.classed("no-text")){ if (!svg.classed("no-text")){
svg.append("text") svg.append("text")
.attr("x", midX) .attr("x", midX)
.attr("y", midY + 30) // Adjust for correct height (moved to bottom) .attr("y", midY + 25) // Adjust for correct height (moved to bottom)
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("fill", textcolour) // My Colour .attr("fill", textcolour) // My Colour
.attr("font-size", "22px") .attr("font-size", "22px")
@ -142,20 +142,20 @@ svg.append("text")
} }
// And now a central number // And now a central number
let bigy = midY-45; let bigy = midY + 70;
let bigfont = "36px"; let bigfont = "36px";
if (svg.classed("big-number")){ if (svg.classed("big-number")){
bigy = midY-85; bigy = midY + 120;
bigfont = "70px"; bigfont = "70px";
} }
svg.append("text") svg.append("text")
.attr("x", midX) .attr("x", midX)
.attr("y", midY + 70) .attr("y", bigy)
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("fill", "black") // 🎨 customize color .attr("fill", "black") // 🎨 customize color
.attr("font-size", bigfont) .attr("font-size", bigfont)
.attr("font-weight", "bold") .attr("font-weight", "bold")
.attr("font-family", "Courier New, monospace") .attr("font-family", 'sans-serif, Consolas, "Lucida Console", Menlo, "DejaVu Sans Mono", monospace')
.text(`${mean}`); .text(`${mean}`);
} }

View File

@ -7,7 +7,7 @@ $dataCentre = $config['data_centre'];
$surveyId = $_POST['survey_id'] ?? null; $surveyId = $_POST['survey_id'] ?? null;
if (!$surveyId) { if (!$surveyId) {
$surveyId="SV_bD838sNKZEmi6Tc"; // *****FIXME***** JUST FOR DEVELOPMENT $surveyId="SV_cwKjMqAqGxImjMG"; // *****FIXME***** JUST FOR DEVELOPMENT
//die("No survey ID provided."); //die("No survey ID provided.");
} }
@ -93,6 +93,10 @@ curl_close($ch);
// Decode the response // Decode the response
$data = json_decode($response, true); $data = json_decode($response, true);
//For testing only
echo $response;
//Save surveyId //Save surveyId
//insertSurveyIfNotExists($identifier, $description); // The identifier is actually the surveyId, and the description isn't included at this point. //insertSurveyIfNotExists($identifier, $description); // The identifier is actually the surveyId, and the description isn't included at this point.
$surveyIndex = getOrCreateSurvey($surveyId, ""); $surveyIndex = getOrCreateSurvey($surveyId, "");

View File

@ -7,7 +7,8 @@ $dataCenter = $config['data_centre'];
// Get the survey ID from POST // Get the survey ID from POST
$surveyId = $_POST['survey_id'] ?? null; $surveyId = $_POST['survey_id'] ?? null;
if (!$surveyId) { if (!$surveyId) {
$surveyId="SV_cAstEvm4ZrPaqGi"; //$surveyId="SV_cAstEvm4ZrPaqGi";
$surveyId="SV_cwKjMqAqGxImjMG";
#die("No survey ID provided."); #die("No survey ID provided.");
} }

View File

@ -40,6 +40,19 @@ $surveys = $result['result']['elements'] ?? [];
<body> <body>
<h1>Select a Survey</h1> <h1>Select a Survey</h1>
<p>This tool has been created by Peter Edmond working for <a href="https://www.telospartners.com/">Telos Partners</a> as part of the OPL Data Analysis Project. Whilst it *SHOULD* behave as expected, it has been know for lightning to strike, computers to explode, and pigs to fly (allegedly, if thrown out of an aircraft?). There may be other interesting side effects? If this software does something unexpected, then it should be addressed to Telos Partners <a href="https://www.chiark.greenend.org.uk/~sgtatham/bugs.html">AFTER READING AND UNDERSTANDING how to report bugs effectively</a>.
</p>
<p>In order to be able to access the survey data, you must use this form to export the data from <a href="https://telospartners.eu.qualtrics.com/login">Qualtrics</a>. This is done via an API key. Normally the survey will be immediately visible by name in the drop down, however under certain circumstances this might not work, such as if it has the same name as another survey, or the survey has not been shared with the account that is associated with the API.
</p>
<p>The ability to check whether a surveyId is accessible for exporting can be checked directly via the surveyId. The form allowing direct entry of the surveyID lso carries out a full export of the data associated with the requested surveyId (provided that surveyId data can be accessed). The template survey is surveyId SV_cwKjMqAqGxImjMG if you wish to test a value. The surveyId is of the form SV_************** and can be found by looking at the survey web page path when looking at the survey in the Qualtrics interface.
</p>
<p>NOTE - Once you have pressed submit, your browser will appear to freeze. This is because there is LOADS of work going on in the background to authenticate, identify all the answers that have been provided to this survey, and download them. Once the available answer sets have been downloaded, you will get a messy page showing the surveyId, the total number of COMPLETED AND SUBMITTED response sets (responseId). Once the page with the Response IDs has appeared, then the data has been fully exported, and is <a href="./reportTemplate.html">available for analysis.</a></p>
<p>The export process OVER-WRITES any previous results for a particular survey. This means that that if data is deleted in the Qualtrics interface, then that data set will be lost. Additionally, by importing the data, and additional completed surveys will be added to the data set and be available for analysis. Carrying out the import process effectively aims to sychronise the data for analysis with that from the Qualtrics survey software.</p>
<?php if (empty($surveys)): ?> <?php if (empty($surveys)): ?>
<p>No surveys found or an error occurred.</p><br><br><hr><br> <p>No surveys found or an error occurred.</p><br><br><hr><br>
@ -61,6 +74,13 @@ $surveys = $result['result']['elements'] ?? [];
<br><br> <br><br>
<input type="submit" value="Submit"> <input type="submit" value="Submit">
</form> </form>
<br>
<form method="POST" action="getData.php">
<label for="survey_id">.....OR enter a surveyId to download data and produce reports:</label>
<input name="survey_id" id="survey_id">
<br><br>
<input type="submit" value="Submit">
</form>
<?php endif; ?> <?php endif; ?>
</body> </body>
</html> </html>

View File

@ -1,13 +1,19 @@
<?php <?php
header('Content-Type: application/json'); header('Content-Type: application/json');
if (php_sapi_name() === 'cli') {
echo "Running from command line.\n";
$qid="QID2_7";
} else {
//echo "Running from browser.\n";
// Basic input validation and sanitization // Basic input validation and sanitization
if (!isset($_POST['qid']) || empty($_POST['qid'])) { if (!isset($_POST['qid']) || empty($_POST['qid'])) {
echo json_encode(['error' => 'Missing QID parameter']); echo json_encode(['error' => 'Missing QID parameter']);
exit; exit;
} }
$qid = $_POST['qid']; $qid = $_POST['qid'];
}
// Database connection (adjust credentials accordingly) // Database connection (adjust credentials accordingly)
// //
@ -54,7 +60,8 @@ try {
// Return as JSON array of objects [{value: -3, count: 5}, ...] // Return as JSON array of objects [{value: -3, count: 5}, ...]
$response = []; $response = [];
foreach ($counts as $value => $count) { foreach ($counts as $value => $count) {
$response[] = ['value' => $value, 'count' => $count]; //$response[] = ['value' => $value, 'count' => $count];
$response[] = ['"'.strval($value).'"' => $count];
} }
echo json_encode($response); echo json_encode($response);
@ -65,3 +72,12 @@ try {
} }

View File

@ -69,39 +69,154 @@ function RAGGED(average){
//Great EO Leaders //Great EO Leaders
average = doBarData('#svg2_1','QID35_7'); average = doBarData('#svg2_1','QID36_7');
//makeSvgRightClickable('svg1_1'); //makeSvgRightClickable('svg1_1');
doBarData('#svg2_2','QID35_2'); doBarData('#svg2_2','QID36_2');
//makeSvgRightClickable('svg1_2'); //makeSvgRightClickable('svg1_2');
doBarData('#svg2_3','QID35_8'); doBarData('#svg2_3','QID36_8');
//makeSvgRightClickable('svg1_3'); //makeSvgRightClickable('svg1_3');
doBarData('#svg2_4','QID35_7'); doBarData('#svg2_4','QID36_9');
//makeSvgRightClickable('svg1_4'); //makeSvgRightClickable('svg1_4');
//doBarData('#svg2_5','QID35_10');
//makeSvgRightClickable('svg1_5');
//Great EO Governance //Great EO Governance
average = doBarData('#svg3_1','QID35_7'); average = doBarData('#svg3_1','QID37_7');
//makeSvgRightClickable('svg1_1'); //makeSvgRightClickable('svg1_1');
doBarData('#svg3_2','QID35_2'); doBarData('#svg3_2','QID37_2');
//makeSvgRightClickable('svg1_2'); //makeSvgRightClickable('svg1_2');
doBarData('#svg3_3','QID35_8'); doBarData('#svg3_3','QID37_8');
//makeSvgRightClickable('svg1_3'); //makeSvgRightClickable('svg1_3');
doBarData('#svg3_4','QID35_7'); doBarData('#svg3_4','QID37_20');
//makeSvgRightClickable('svg1_4'); //makeSvgRightClickable('svg1_4');
doBarData('#svg3_5','QID35_10'); doBarData('#svg3_5','QID37_21');
//makeSvgRightClickable('svg1_5'); //makeSvgRightClickable('svg1_5');
doBarData('#svg3_6','QID35_10'); doBarData('#svg3_6','QID37_22');
//makeSvgRightClickable('svg1_5'); //makeSvgRightClickable('svg1_5');
//EO APPROACH
//Great EO Culture
average = doBarData('#svg4_1','QID2_7');
//makeSvgRightClickable('svg1_1');
doBarData('#svg4_2','QID2_2');
//makeSvgRightClickable('svg1_2');
doBarData('#svg4_3','QID2_8');
//makeSvgRightClickable('svg1_3');
doBarData('#svg4_4','QID2_9');
//makeSvgRightClickable('svg1_4');
//Great EO Engagement
average = doBarData('#svg5_1','QID33_7');
//makeSvgRightClickable('svg1_1');
doBarData('#svg5_2','QID33_2');
//makeSvgRightClickable('svg1_2');
doBarData('#svg5_3','QID33_8');
//makeSvgRightClickable('svg1_3');
doBarData('#svg5_4','QID33_9');
//makeSvgRightClickable('svg1_4');
//Great EO Stewardship
average = doBarData('#svg6_1','QID34_7');
//makeSvgRightClickable('svg1_1');
doBarData('#svg6_2','QID34_2');
//makeSvgRightClickable('svg1_2');
doBarData('#svg6_3','QID34_8');
//makeSvgRightClickable('svg1_3');
doBarData('#svg6_4','QID34_17');
//makeSvgRightClickable('svg1_4');
//EO ACTIONS
//Great EO Strategy
average = doBarData('#svg7_1','QID40_7');
//makeSvgRightClickable('svg1_1');
doBarData('#svg7_2','QID40_2');
//makeSvgRightClickable('svg1_2');
doBarData('#svg7_3','QID40_8');
//makeSvgRightClickable('svg1_3');
doBarData('#svg7_4','QID40_9');
//makeSvgRightClickable('svg1_4');
//Great EO Innovation
average = doBarData('#svg8_1','QID41_7');
//makeSvgRightClickable('svg1_1');
doBarData('#svg8_2','QID41_2');
//makeSvgRightClickable('svg1_2');
doBarData('#svg8_3','QID41_19');
//makeSvgRightClickable('svg1_3');
doBarData('#svg8_4','QID41_20');
//makeSvgRightClickable('svg1_4');
doBarData('#svg8_5','QID41_21');
//makeSvgRightClickable('svg1_5');
//Great EO Advantage
average = doBarData('#svg9_1','QID42_7');
//makeSvgRightClickable('svg1_1');
doBarData('#svg9_2','QID42_2');
//makeSvgRightClickable('svg1_2');
doBarData('#svg9_3','QID42_8');
//makeSvgRightClickable('svg1_3');
//EO RESULTS
//Great EO Measurement
average = doBarData('#svg10_1','QID44_21');
//makeSvgRightClickable('svg1_1');
doBarData('#svg10_2','QID44_7');
//makeSvgRightClickable('svg1_2');
doBarData('#svg10_3','QID44_2');
//makeSvgRightClickable('svg1_3');
doBarData('#svg10_4','QID44_8');
//makeSvgRightClickable('svg1_4');
//Great EO Evaluation
average = doBarData('#svg11_1','QID45_24');
//makeSvgRightClickable('svg1_1');
doBarData('#svg11_2','QID45_25');
//makeSvgRightClickable('svg1_2');
doBarData('#svg11_3','QID45_26');
//makeSvgRightClickable('svg1_3');
doBarData('#svg11_4','QID45_29');
//makeSvgRightClickable('svg1_4');
//Great EO Impact
average = doBarData('#svg12_1','QID46_27');
//makeSvgRightClickable('svg1_1');
doBarData('#svg12_2','QID46_28');
//makeSvgRightClickable('svg1_2');
doBarData('#svg12_3','QID46_29');
//makeSvgRightClickable('svg1_3');
doBarData('#svg12_4','QID46_30');
//makeSvgRightClickable('svg1_4');
doBarData('#svg12_5','QID46_31');
//makeSvgRightClickable('svg1_5');
doBarData('#svg12_6','QID46_32');
//makeSvgRightClickable('svg1_5');
doBarData('#svg12_7','QID46_33');
//makeSvgRightClickable('svg1_3');
doBarData('#svg12_8','QID46_34');
//makeSvgRightClickable('svg1_4');
doBarData('#svg12_9','QID46_36');
//makeSvgRightClickable('svg1_5');
doBarData('#svg12_10','QID46_37');
//makeSvgRightClickable('svg1_5');
// Make sure that evreything is loaded! // Make sure that evreything is loaded!
setTimeout(() => { setTimeout(() => {
console.log("Waited 2 seconds"); console.log("Waited 8 seconds");
// We now have access to all of the averages, so can calculate the basic triangle. // We now have access to all of the averages, so can calculate the basic triangle.
//EO ROLES
let svg1_avg = (getAverage("svg1_")+3)/7; let svg1_avg = (getAverage("svg1_")+3)/7;
let svg2_avg = (getAverage("svg2_")+3)/7; let svg2_avg = (getAverage("svg2_")+3)/7;
let svg3_avg = (getAverage("svg3_")+3)/7; let svg3_avg = (getAverage("svg3_")+3)/7;
@ -109,7 +224,6 @@ function RAGGED(average){
console.log(svg1_avg,svg2_avg,svg3_avg, roles_avg); console.log(svg1_avg,svg2_avg,svg3_avg, roles_avg);
doLittleWhiteTriangle('svg_roles'); doLittleWhiteTriangle('svg_roles');
//drawtriangle('#svg_roles','Roles','#008845',[0.25,0.5,0.75],'', { x: 0, y: 100 },roles_avg.toFixed(1)); //drawtriangle('#svg_roles','Roles','#008845',[0.25,0.5,0.75],'', { x: 0, y: 100 },roles_avg.toFixed(1));
drawtriangle('#svg_roles','Roles','#008845',[svg1_avg,svg2_avg,svg3_avg],'', { x: 0, y: 100 },roles_avg.toFixed(1)); drawtriangle('#svg_roles','Roles','#008845',[svg1_avg,svg2_avg,svg3_avg],'', { x: 0, y: 100 },roles_avg.toFixed(1));
@ -124,25 +238,108 @@ function RAGGED(average){
//makeSvgRightClickable('svg_roles_test'); //makeSvgRightClickable('svg_roles_test');
}, 500);
//EO APPROACH //EO APPROACH
let svg4_avg = (getAverage("svg4_")+3)/7;
let svg5_avg = (getAverage("svg5_")+3)/7;
let svg6_avg = (getAverage("svg6_")+3)/7;
let approach_avg = (7*(svg4_avg+svg5_avg+svg6_avg)/3)-3; // this converts the scales lengths to the correct value
console.log(svg4_avg,svg5_avg,svg6_avg,approach_avg);
doLittleWhiteTriangle('svg_approach');
//drawtriangle('#svg_approach','Approach','#008845',[0.25,0.5,0.75],'', { x: 0, y: 100 },average_avg.toFixed(1));
drawtriangle('#svg_approach','Approach','#ed4c0c',[svg4_avg,svg5_avg,svg6_avg],'', { x: 0, y: 100 },approach_avg.toFixed(1));
//makeSvgRightClickable('svg_approach');
doLittleWhiteTriangle('svg_approach_RAG');
drawtriangle('#svg_approach_RAG','Approach','#ed4c0c',[svg4_avg,svg5_avg,svg6_avg],RAGGED(approach_avg), { x: 0, y: 100 },approach_avg.toFixed(1));
//makeSvgRightClickable('svg_approach_RAG');
//doLittleWhiteTriangle('svg_approach_test');
//drawtriangle('#svg_approach_test','Approach','#ed4c0c',[0.95,0.95,0.95],RAGGED(approach_avg), { x: 0, y: 100 },approach_avg.toFixed(1));
//makeSvgRightClickable('svg_approach_test');
//EO ACTIONS
let svg7_avg = (getAverage("svg7_")+3)/7;
let svg8_avg = (getAverage("svg8_")+3)/7;
let svg9_avg = (getAverage("svg9_")+3)/7;
let actions_avg = (7*(svg7_avg+svg8_avg+svg9_avg)/3)-3; // this converts the scales lengths to the correct value
console.log(svg7_avg,svg8_avg,svg9_avg,actions_avg);
doLittleWhiteTriangle('svg_actions');
//drawtriangle('#svg_actions','Actions','#b2c8c4',[0.25,0.5,0.75],'', { x: 0, y: 100 },actions_avg.toFixed(1));
drawtriangle('#svg_actions','Actions','#b2c8c4',[svg7_avg,svg8_avg,svg9_avg],'', { x: 0, y: 100 },actions_avg.toFixed(1));
//makeSvgRightClickable('svg_actions');
doLittleWhiteTriangle('svg_actions_RAG');
drawtriangle('#svg_actions_RAG','Actions','#b2c8c4',[svg7_avg,svg8_avg,svg9_avg],RAGGED(actions_avg), { x: 0, y: 100 },actions_avg.toFixed(1));
//makeSvgRightClickable('svg_actions_RAG');
//doLittleWhiteTriangle('svg_actions_test');
//drawtriangle('#svg_actions_test','Actions','#b2c8c4',[0.95,0.95,0.95],RAGGED(actions_avg), { x: 0, y: 100 },actions_avg.toFixed(1));
//makeSvgRightClickable('svg_actions_test');
//EO IMPACT
let svg10_avg = (getAverage("svg10_")+3)/7;
let svg11_avg = (getAverage("svg11_")+3)/7;
let svg12_avg = (getAverage("svg12_")+3)/7;
let results_avg = (7*(svg10_avg+svg11_avg+svg12_avg)/3)-3; // this converts the scales lengths to the correct value
console.log(svg10_avg,svg11_avg,svg12_avg,results_avg);
doLittleWhiteTriangle('svg_results');
//drawtriangle('#svg_results','Results','#74469',[0.25,0.5,0.75],'', { x: 0, y: 100 },impact_avg.toFixed(1));
drawtriangleinverted('#svg_results','Results','#74469c',[svg10_avg,svg11_avg,svg12_avg],'', { x: 0, y: 0 },results_avg.toFixed(1));
//makeSvgRightClickable('svg_results');
doLittleWhiteTriangle('svg_results_RAG');
drawtriangleinverted('#svg_results_RAG','Results','#74469c',[svg10_avg,svg11_avg,svg12_avg],RAGGED(results_avg), { x: 0, y: 0 },results_avg.toFixed(1));
//makeSvgRightClickable('svg_results_RAG');
doLittleWhiteTriangle('svg_results_test');
drawtriangleinverted('#svg_results_test','Results','#74469c',[0.95,0.95,0.95],RAGGED(results_avg), { x: 0, y: 0 },results_avg.toFixed(1));
//makeSvgRightClickable('svg_results_test');
//drawBar('#svg1_1','QID34_7'); doBigWhiteTriangle('svg_pyramid');
//makeSvgRightClickable('svg1_1'); drawtriangle('#svg_pyramid','Roles','#008845',[svg1_avg,svg2_avg,svg3_avg],'', { x: 0, y: 350 },roles_avg.toFixed(1));
drawtriangle('#svg_pyramid','Actions','#b2c8c4',[svg4_avg,svg5_avg,svg6_avg],'',{ x: 370, y: 350 },actions_avg.toFixed(1));
drawtriangle('#svg_pyramid','Approach','#ed4c0c',[svg7_avg,svg8_avg,svg9_avg],'',{ x: 185, y: 30 },approach_avg.toFixed(1));
drawtriangleinverted('#svg_pyramid','Results','#74469c',[svg10_avg,svg11_avg,svg12_avg],'',{ x: 185, y: 243},results_avg.toFixed(1));
makeSvgRightClickable('svg_pyramid');
//drawBar('#svg1_2');
//makeSvgRightClickable('svg1_2');
//drawBar('#svg1_3');
//makeSvgRightClickable('svg1_3');
//drawBar('#svg1_4'); doBigWhiteTriangle('svg_pyramid_RAG');
//makeSvgRightClickable('svg1_4'); drawtriangle('#svg_pyramid_RAG','Roles','#008845',[svg1_avg,svg2_avg,svg3_avg],RAGGED(roles_avg), { x: 0, y: 350 },roles_avg.toFixed(1));
drawtriangle('#svg_pyramid_RAG','Actions','#b2c8c4',[svg4_avg,svg5_avg,svg6_avg],RAGGED(actions_avg),{ x: 370, y: 350 },actions_avg.toFixed(1));
drawtriangle('#svg_pyramid_RAG','Approach','#ed4c0c',[svg7_avg,svg8_avg,svg9_avg],RAGGED(approach_avg),{ x: 185, y: 30 },approach_avg.toFixed(1));
drawtriangleinverted('#svg_pyramid_RAG','Results','#74469c',[svg10_avg,svg11_avg,svg12_avg],RAGGED(results_avg),{ x: 185, y: 243},results_avg.toFixed(1));
makeSvgRightClickable('svg_pyramid_RAG');
doBigWhiteTriangle('svg_pyramid_RAG_test');
drawtriangle('#svg_pyramid_RAG_test','Roles','#008845',[0.9,0.9,0.9],RAGGED(roles_avg), { x: 0, y: 350 },roles_avg.toFixed(1));
drawtriangle('#svg_pyramid_RAG_test','Actions','#b2c8c4',[0.9,0.9,0.9],RAGGED(actions_avg),{ x: 370, y: 350 },actions_avg.toFixed(1));
drawtriangle('#svg_pyramid_RAG_test','Approach','#ed4c0c',[0.9,0.9,0.9],RAGGED(approach_avg),{ x: 185, y: 30 },approach_avg.toFixed(1));
drawtriangleinverted('#svg_pyramid_RAG_test','Results','#74469c',[0.9,0.9,0.9],RAGGED(results_avg),{ x: 185, y: 243},results_avg.toFixed(1));
makeSvgRightClickable('svg_pyramid_RAG_test');
doBigWhiteTriangle('svg_pyramid_RAG_test2');
drawtriangle('#svg_pyramid_RAG_test2','Roles','#008845',[0.95,0.95,0.95],RAGGED(roles_avg), { x: 0, y: 350 },roles_avg.toFixed(1));
drawtriangle('#svg_pyramid_RAG_test2','Actions','#b2c8c4',[0.95,0.95,0.95],RAGGED(actions_avg),{ x: 370, y: 350 },actions_avg.toFixed(1));
drawtriangle('#svg_pyramid_RAG_test2','Approach','#ed4c0c',[0.95,0.95,0.95],RAGGED(approach_avg),{ x: 185, y: 30 },approach_avg.toFixed(1));
drawtriangleinverted('#svg_pyramid_RAG_test2','Results','#74469c',[0.95,0.95,0.95],RAGGED(results_avg),{ x: 185, y: 243},results_avg.toFixed(1));
makeSvgRightClickable('svg_pyramid_RAG_test2');
}, 800);
//drawBar('#svg1_5');
//makeSvgRightClickable('svg1_5');
} }

View File

@ -57,7 +57,7 @@ function doLittleWhiteTriangle(id){
/*
function inlineStyles(svgElement) { function inlineStyles(svgElement) {
const allElements = svgElement.querySelectorAll('*'); const allElements = svgElement.querySelectorAll('*');
const computedStyles = window.getComputedStyle(svgElement); const computedStyles = window.getComputedStyle(svgElement);
@ -78,9 +78,46 @@ function inlineStyles(svgElement) {
}); });
} }
*/
function inlineStyles(svgElement) {
const allElements = svgElement.querySelectorAll('*');
allElements.forEach(el => {
const computed = window.getComputedStyle(el);
const style = [];
for (let i = 0; i < computed.length; i++) {
const key = computed[i];
let value = computed.getPropertyValue(key);
// Replace currentColor with resolved color
if (value === 'currentcolor') {
value = computed.color;
}
style.push(`${key}:${value};`);
}
el.setAttribute('style', style.join(' '));
});
// Also inline root <svg>
const svgComputed = window.getComputedStyle(svgElement);
let rootStyle = '';
for (let i = 0; i < svgComputed.length; i++) {
const key = svgComputed[i];
let value = svgComputed.getPropertyValue(key);
if (value === 'currentcolor') {
value = svgComputed.color;
}
rootStyle += `${key}:${value};`;
}
svgElement.setAttribute('style', rootStyle);
}
/*
function makeSvgRightClickable(id) { function makeSvgRightClickable(id) {
const svg = document.getElementById(id); const svg = document.getElementById(id);
inlineStyles(svg); inlineStyles(svg);
@ -101,10 +138,48 @@ function makeSvgRightClickable(id) {
img.alt = "Right-click to save SVG image"; img.alt = "Right-click to save SVG image";
// Replace or insert after SVG // Replace or insert after SVG
svg.style.display = "none"; // hide original //svg.style.display = "none"; // hide original
svg.parentNode.insertBefore(img, svg.nextSibling); svg.parentNode.insertBefore(img, svg.nextSibling);
} }
// Call the function after D3 has drawn the SVG // Call the function after D3 has drawn the SVG
//makeSvgRightClickable("id"); //makeSvgRightClickable("id");
*/
function makeSvgRightClickable(id) {
const svg = document.getElementById(id);
inlineStyles(svg);
// Set namespace
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
// Ensure width and height are set
if (!svg.hasAttribute("width")) svg.setAttribute("width", svg.getBoundingClientRect().width);
if (!svg.hasAttribute("height")) svg.setAttribute("height", svg.getBoundingClientRect().height);
// Serialize
const svgData = new XMLSerializer().serializeToString(svg);
const svgBlob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
const url = URL.createObjectURL(svgBlob);
// Create image element
const img = document.createElement("img");
img.src = url;
img.width = svg.getAttribute("width");
img.height = svg.getAttribute("height");
img.alt = "Right-click to save SVG image";
if (svg.classList.contains("pyramid")) {
img.classList.add("pyramid");
}
if (svg.classList.contains("triangle")) {
img.classList.add("triangle");
}
svg.style.display = "none";
svg.parentNode.insertBefore(img, svg.nextSibling);
}