Skip to content

Commit

Permalink
Merge pull request #416 from Tangerine-Community/3742-add-score-count…
Browse files Browse the repository at this point in the history
…-and-percent

3742 add score count and percent
  • Loading branch information
esurface authored Jan 10, 2025
2 parents 925b808 + 7e462da commit fa42817
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 27 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# CHANGELOG

## v4.46.0

Section Scoring Updates:
- Add `<section_id>_percet` and `<section_id>_denominator` to the form item outputs.
- Prevent scoring of both tangy-timed, custom-scoring and regular scoring in the same section.

Rules:
- custom scoring always returns a percent
- users should only use one type of input per scoring section
- if there is a tangy-timed input, the score is the average of the percents of each grid. All other scores are ignored.

## v4.45.4

Fix missing function parens
Expand Down
60 changes: 59 additions & 1 deletion demo/tangy-scoring-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,65 @@ <h3>tangy-form scoring demo</h3>
<demo-snippet>
<template>
<tangy-form id="my-form" title="My Form">
<tangy-form-item title="Awuoro Yawa" scoring-section scoring-fields="fam_word1,fam_word2,cb1,cb2,text1,fruit_time,tangy-timed-grid" id="item1">
<tangy-form-item title="Scoring Inputs" scoring-section scoring-fields="fam_word1,fam_word2,text1,fruit_time" id="item1">
<tangy-radio-buttons name="fam_word1" question-number="" label="1. свет" hint-text=" [св'эт] закрытый слог, 2 согласные рядом" error-text="" warn-text="" class="" style="">
<option value="0">Неверно / нет ответа</option>
<option value="1">Верный</option>
</tangy-radio-buttons>
<tangy-radio-buttons name="fam_word2" question-number="" label="2. шар" hint-text="[шар] простой закрытый слог" error-text="" warn-text="" class="" style="">
<option value="0">Неверно / нет ответа</option>
<option value="1">Верный</option>
</tangy-radio-buttons>
<tangy-checkbox name="cb1">
Tangerines?
</tangy-checkbox>
<tangy-checkbox name="cb2">
Apples?
</tangy-checkbox>
<tangy-input name="text1" label="Number of people"></tangy-input>
<tangy-checkboxes
name="fruit_time"
label="What <b>time</b> do you take fruit?"
hint-text="This is <b>hint text</b>."
>
<option name="morning">Morning</option>
<option name="afternoon">Afternoon</option>
<option name="evening"><i>Evening</i></option>
</tangy-checkboxes>
</tangy-form-item>
<tangy-form-item title="Tangy-Timed Scoring" scoring-section scoring-fields="tangy-timed-grid" id="item2">
<tangy-timed required columns="3" name="tangy-timed-grid" auto-stop="2">
<option value="class1_term2-d">1</option><option value="class1_term2-1">Jumatatu,</option><option value="class1_term2-2">wezi</option><option value="class1_term2-3">walikuja</option><option value="class1_term2-4">kijijini.</option><option value="class1_term2-5">Watu</option><option value="class1_term2-6">wakapiga</option><option value="class1_term2-7">mayowe.</option><option value="class1_term2-8">“Tunataka</option><option value="class1_term2-9">dhahabu!”</option><option value="class1_term2-10">wezi</option><option value="class1_term2-11">wakasema.</option><option value="class1_term2-12">Watu</option><option value="class1_term2-13">walipatwa</option><option value="class1_term2-14">na</option><option value="class1_term2-15">wasiwasi.</option><option value="class1_term2-16">Watu</option><option value="class1_term2-17">wakasema,</option><option value="class1_term2-18">“Hatuna</option><option value="class1_term2-19">chochote</option><option value="class1_term2-20">cha</option><option value="class1_term2-21">thamani.”</option><option value="class1_term2-22">Polisi</option><option value="class1_term2-23">walifika</option><option value="class1_term2-24">hapo.</option><option value="class1_term2-25">Waliwashika</option><option value="class1_term2-26">wezi</option><option value="class1_term2-27">na</option><option value="class1_term2-28">kuwatia</option><option value="class1_term2-29">pingu.</option><option value="class1_term2-30">Wezi</option><option value="class1_term2-31">walipelekwa</option><option value="class1_term2-32">gerezani.</option>
</tangy-timed>
</tangy-form-item>
<tangy-form-item title="Custom Scoring Inputs" scoring-section scoring-fields="fam_word1,fam_word2,text1,fruit_time" id="item3" custom-scoring-logic="parseInt(
parseInt(getValue('fam_word1')) + parseInt(getValue('fam_word2') + parseInt(getValue('text1')) / 3 ) * 100">
<tangy-radio-buttons name="fam_word1" question-number="" label="1. свет" hint-text=" [св'эт] закрытый слог, 2 согласные рядом" error-text="" warn-text="" class="" style="">
<option value="0">Неверно / нет ответа</option>
<option value="1">Верный</option>
</tangy-radio-buttons>
<tangy-radio-buttons name="fam_word2" question-number="" label="2. шар" hint-text="[шар] простой закрытый слог" error-text="" warn-text="" class="" style="">
<option value="0">Неверно / нет ответа</option>
<option value="1">Верный</option>
</tangy-radio-buttons>
<tangy-checkbox name="cb1">
Tangerines?
</tangy-checkbox>
<tangy-checkbox name="cb2">
Apples?
</tangy-checkbox>
<tangy-input name="text1" label="Number of people"></tangy-input>
<tangy-checkboxes
name="fruit_time"
label="What <b>time</b> do you take fruit?"
hint-text="This is <b>hint text</b>."
>
<option name="morning">Morning</option>
<option name="afternoon">Afternoon</option>
<option name="evening"><i>Evening</i></option>
</tangy-checkboxes>
</tangy-form-item>
<tangy-form-item title="Mixed Inputs -- Only Scores Tangy-Timed" scoring-section scoring-fields="fam_word1,fam_word2,cb1,cb2,text1,fruit_time,tangy-timed-grid" id="item4">
<tangy-radio-buttons name="fam_word1" question-number="" label="1. свет" hint-text=" [св'эт] закрытый слог, 2 согласные рядом" error-text="" warn-text="" class="" style="">
<option value="0">Неверно / нет ответа</option>
<option value="1">Верный</option>
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "tangy-form",
"description": "A form element for lazy loaded multipage forms",
"version": "4.45.4",
"version": "4.46.0",
"main": "tangy-form.js",
"scripts": {
"start": "polymer serve",
Expand Down
79 changes: 55 additions & 24 deletions tangy-form-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -772,37 +772,58 @@ export class TangyFormItem extends PolymerElement {
this
.querySelectorAll('[name]')
.forEach(input => inputs.push(input.getModProps && window.useShrinker ? input.getModProps() : input.getProps()))

let score = 0
let percent = 0
let denominator = 0
let tangyTimedPercents = [];
this.inputs = inputs

if (this.querySelector('[name]')) {
const tangyFormItem = this.querySelector('[name]').parentElement
if(tangyFormItem.hasAttribute('scoring-section')) {
const selections = tangyFormItem.getAttribute('scoring-fields') || []
if(selections.length>0){
const selectionsArray = selections.split(',')
function findObjectByKey(array, key, value) {
for (let i = 0; i < array.length; i++) { if (array[i] == key) {return array[i];}
} return null;
}

this.inputs.forEach(input => {
const a = findObjectByKey(selectionsArray, input.name)
if (a != null){
let value;
if (input.tagName === 'TANGY-TIMED') {
//each grid present is scored as "number of correct items"/"number of total items" *100
const correct = numberOfCorrectItems(input);
const total = input.value.length
value = Math.round((correct/total) * 100).toString();
/*
* Per the documentation:
* - custom scoring always returns a percent
* - users are supposed to only have one type of input per scoring section
* - if there is a tangy-timed input, the score is the average of the percents of each grid. All other scores are ignored.
*/
if (tangyFormItem.hasAttribute('custom-scoring-logic') && tangyFormItem.getAttribute('custom-scoring-logic').trim().length > 0) {
score = this.customScore
percent = score
denominator = 100
} else {
const selections = tangyFormItem.getAttribute('scoring-fields') || []
if (selections.length > 0) {
const selectionsArray = selections.split(',')
function findObjectByKey(array, key, value) {
for (let i = 0; i < array.length; i++) { if (array[i] == key) {return array[i];}
} return null;
}
this.inputs.forEach(input => {
const a = findObjectByKey(selectionsArray, input.name)
if (a != null) {
let value;
if (input.tagName === 'TANGY-TIMED') {
//each grid present is scored as "number of correct items"/"number of total items" *100 aka a percent
const correct = numberOfCorrectItems(input);
const total = input.value.length
value = Math.round((correct/total) * 100).toString();
tangyTimedPercents.push(value);
} else {
value = getValue(input.name);
score += sumScore(value)
denominator += 1
}
}
})
if (tangyTimedPercents.length > 0) {
percent = Math.round(tangyTimedPercents.reduce((a, b) => parseInt(a) + parseInt(b)) / tangyTimedPercents.length)
score = percent
denominator = 100
} else {
value = getValue(input.name);
percent = Math.round((score/denominator) * 100)
}
score += sumScore(value)}
})
}
if(tangyFormItem.hasAttribute('custom-scoring-logic')&&tangyFormItem.getAttribute('custom-scoring-logic').trim().length>0){
score = this.customScore
}
}
function sumScore(value) {
let s = 0
Expand All @@ -818,6 +839,16 @@ export class TangyFormItem extends PolymerElement {
scoreEl.name = `${tangyFormItem.getAttribute('id')}_score`
scoreEl.value = score
this.inputs = [...inputs, scoreEl.getModProps && window.useShrinker ? scoreEl.getModProps() : scoreEl.getProps()]

const countEl = document.createElement('tangy-input')
countEl.name = `${tangyFormItem.getAttribute('id')}_score_denominator`
countEl.value = denominator
this.inputs = [...this.inputs, countEl.getModProps && window.useShrinker ? countEl.getModProps() : countEl.getProps()]

const percentEl = document.createElement('tangy-input')
percentEl.name = `${tangyFormItem.getAttribute('id')}_score_percent`
percentEl.value = percent
this.inputs = [...this.inputs, percentEl.getModProps && window.useShrinker ? percentEl.getModProps() : percentEl.getProps()]
}
}
if (window.devtools && window.devtools.open) {
Expand Down

0 comments on commit fa42817

Please sign in to comment.