From 41625177915abdb2d9ca9151ca0d97806e871dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Santanch=C3=A8?= Date: Thu, 7 Dec 2023 13:30:39 -0300 Subject: [PATCH 1/2] feat (heart): simulator improvements --- .../player/js/heart/lively-talk-oid-custom.js | 101 +++++++++++++----- 1 file changed, 73 insertions(+), 28 deletions(-) diff --git a/src/adonisjs/public/player/js/heart/lively-talk-oid-custom.js b/src/adonisjs/public/player/js/heart/lively-talk-oid-custom.js index 104e7639..4223b6bd 100644 --- a/src/adonisjs/public/player/js/heart/lively-talk-oid-custom.js +++ b/src/adonisjs/public/player/js/heart/lively-talk-oid-custom.js @@ -12,36 +12,36 @@ Oid.customize('foid:lively-talk', { }`, process: function(oid, parameters) { if (parameters) { - if (parameters.value == 'simular') { + if (parameters.value == 'simular' || parameters.value == 'voltar') { let erro = 0 let existe = '✔'//existe um coração - oid.smExiste = 'O coração existe! Verifique se há erro em algum outro lugar.' + oid.smExiste = 'O coração existe! Verifique se há erro em algum outro lugar.\n ' let instrucoes = '✔'// não há blocos soltas - oid.sminstrucoes = 'Não existem instruções soltas! Verifique se há erro em algum outro lugar.' + oid.sminstrucoes = 'Não existem instruções soltas! Verifique se há erro em algum outro lugar.\n ' let ciclo = '✔' //existe 5 ciclos - oid.smciclo = 'A quantidade de ciclos do meu coração está correta! Verifique se há erro em algum outro lugar.' + oid.smciclo = 'A quantidade de ciclos do meu coração está correta! Verifique se há erro em algum outro lugar.\n ' let vazio = '✔' //bloco roxo escuro não tem campos vazios - oid.smvazio = 'Nenhum campo esta vazio! Verifique se há erro em algum outro lugar.' + oid.smvazio = 'Nenhum campo esta vazio! Verifique se há erro em algum outro lugar.\n ' let textoEle = '✔' //associação entre texto e imagem atv. eletrica - oid.smtextoEle = 'Associação entre texto e imagem correta no bloco da atividade elétrica.' + oid.smtextoEle = 'Associação entre texto e imagem correta no bloco da atividade elétrica.\n ' let textoMec = '✔' //associação entre texto e imagem atv. mec - oid.smtextoMec = 'Associação entre texto e imagem correta no bloco da atividade mecânica.' + oid.smtextoMec = 'Associação entre texto e imagem correta no bloco da atividade mecânica.\n ' let ordemEletrica = '✔' //ordem das atv. eletrica - oid.smordemEle = 'Ordem dos blocos está corretas. Verifique se há erro em algum outro lugar.' + oid.smordemEle = 'Ordem da atividade elétrica está corretas. Verifique se há erro em algum outro lugar.\n ' let ordemMec = '✔' //ordem das atv. mec - oid.smordemMec = 'Ordem das atividades mecânica correta.' + oid.smordemMec = 'Ordem das atividades mecânica correta.\n ' let ordemOnda = '✔' //ordem das ondas - oid.smordemOnda = 'Ordem das ondas do ECG correta.' + oid.smordemOnda = 'Ordem das ondas do ECG correta.\n ' let ordem = '✔' //ordem de todos os blocos - oid.smordem = 'Ordem dos blocos estão corretos.' + oid.smordem = 'Ordem dos blocos estão corretos! Verifique se há erro em algum outro lugar.\n ' let asEleMec = '✔' //associacao das atv. eletrica com atv mec - oid.smasEleMEc = 'Associação da atividades elétrica e da atividade mecânica corretas.' + oid.smasEleMEc = 'Associação da atividades elétrica e da atividade mecânica corretas.\n ' let asMecOnda = '✔' //associacao das atv. mec com onda - oid.smasMecOnda = 'Associação das ondas ECG e da atividade mecânica corretas.' + oid.smasMecOnda = 'Associação das ondas ECG e da atividade mecânica corretas.\n ' let asEleOnda = '✔' //associacao das atv eletrica com ondas - oid.smasEleOnda = 'Associação da atividades elétrica e das ondas ECG corretas.' + oid.smasEleOnda = 'Associação da atividades elétrica e das ondas ECG corretas.\n ' let associacao = '✔' //associacao de qualquer bloco - oid.smassociacao = 'Associação entre blocos está correta.' + oid.smassociacao = 'Associação entre blocos está correta! Verifique se há erro em algum outro lugar.\n ' oid.txt = '' //oid.txt = '
AnáliseStatus
' oid.know = '' @@ -50,14 +50,14 @@ Oid.customize('foid:lively-talk', { if (oid.statements == null || oid.statements.length == 0){ //oid.handleSend('display', {value: '-> Nada a ser processado'}) existe = '❌' - oid.smExiste = 'Vá em componetes e escolha um bloco para começar!' + oid.smExiste = 'Vá em componetes e escolha um bloco para começar! \n ' erro++ } else { if (oid.statements.length > 1 || !Array.isArray(oid.statements[0])){ //oid.handleSend('display', {value: '-> Ainda há instruções soltas, não posso processar'}) instrucoes = '❌' - oid.sminstrucoes = 'Algum bloco está sozinho. Utilize bloco roxo escuro para fazer a conecção dos blocos!' + oid.sminstrucoes = 'Algum bloco está sozinho. Utilize bloco roxo escuro para fazer a conecção dos blocos! \n ' erro++ } else{ @@ -66,13 +66,13 @@ Oid.customize('foid:lively-talk', { if (vstm.length < 5){ //feedback += '-> Estão faltando ciclos no meu pobre coração\n' ciclo = '❌' - oid.smciclo = 'Ops, estão faltando ciclos no meu coração!' + oid.smciclo = 'Ops, estão faltando ciclos no meu coração! \n ' erro++ } else if (vstm.length > 5){ //feedback += '-> Há muitos ciclos no meu coração, ele está fora de controle\n' ciclo = '❌' - oid.smciclo = 'Ops, tem muitos ciclos no meu coração!' + oid.smciclo = 'Ops, tem muitos ciclos no meu coração!\n ' erro++ } let empty = false @@ -83,7 +83,7 @@ Oid.customize('foid:lively-talk', { if (empty) { //feedback += '-> Há uma ou mais instruções incompletas\n' vazio = '❌' - oid.smvazio = 'Está faltando algo! A associação entre o ECG, a atvidade elétrica e a atividade mecânica não está completa! ' + oid.smvazio = 'Está faltando algo! A associação entre o ECG, a atividade elétrica e a atividade mecânica não está completa! \n ' erro++ } // analisando consistencia entre texto e imagem de cada célula @@ -98,7 +98,7 @@ Oid.customize('foid:lively-talk', { if (pEle > 0) { //feedback += -> O texto que você escolheu em uma das imagens em algum dos blocos não descreve adequadamente a atividade ilustrada. (detalhes em Saiba mais)\n textoEle = '❌' - oid.smtextoEle = `Associação entre textos e imagens inconsistente em ${pEle} blocos na atividade elétrica.` + oid.smtextoEle = `Associação entre textos e imagens inconsistente em ${pEle} blocos na atividade elétrica. \n ` //oid.know += -> Associação entre textos e imagens inconsistente em ${pEle} blocos na atividade elétrica\n erro++ } @@ -114,7 +114,7 @@ Oid.customize('foid:lively-talk', { //feedback += -> O texto que você escolheu em uma das imagens em algum dos blocos não descreve adequadamente a atividade ilustrada. (detalhes em Saiba mais)\n //oid.know += -> Associação entre textos e imagens inconsistente em ${pMec} blocos na atividade mecânica\n textoMec = '❌' - oid.smtextoMec = `Associação entre textos e imagens inconsistente em ${pMec} blocos na atividade mecânica.` + oid.smtextoMec = `Associação entre textos e imagens inconsistente em ${pMec} blocos na atividade mecânica.\n ` erro++ } @@ -133,7 +133,7 @@ Oid.customize('foid:lively-talk', { //feedback += -> Alguma coisa está fora de ordem. (detalhes em Saiba mais)\n //oid.know += -> Revise a ordem em que o pulso elétrico segue. Do jeito que está, o impulso não segue uma sequência contínua.\n ordemEletrica = '❌' - oid.smordemEle = 'Ordem da atividade elétrico incorreta.\n' + oid.smordemEle = 'Ordem da atividade elétrica incorreta. \n' erro++ } // analisando a ordem das Ondas ECG @@ -148,7 +148,7 @@ Oid.customize('foid:lively-talk', { //feedback += -> Alguma coisa está fora de ordem. (detalhes em Saiba mais)\n //oid.know += -> Revise a ordem da onda do ECG. Do jeito que está a onda não segue uma sequência contínua.\n ordemOnda = '❌' - oid.smordemOnda = 'Ordem da onda do ECG incorreta.\n' + oid.smordemOnda = 'Ordem da onda do ECG incorreta. \n' erro++ } // analisando a ordem da atividade mecanica @@ -162,7 +162,7 @@ Oid.customize('foid:lively-talk', { //feedback += -> Alguma coisa está fora de ordem. (detalhes em Saiba mais)\n //oid.know += -> Revise a ordem da atividade mecânica. Do jeito que está, o movimento não permite bombear sangue na sequência correta.\n ordemMec = '❌' - oid.smordemMec = 'Ordem da atividade mecânica incorreta.\n' + oid.smordemMec = 'Ordem da atividade mecânica incorreta. \n' erro++ } if(iMec || iEle || iOnda){ @@ -194,19 +194,19 @@ Oid.customize('foid:lively-talk', { } if (incompatOndaEle){ //oid.know += -> Uma ou mais atividades elétricas não geram às ondas do ECG que foram associadas.\n - oid.asEleOnda = 'Uma ou mais atividades elétricas não geram às ondas do ECG.\n' + oid.asEleOnda = 'Uma ou mais atividades elétricas não geram às ondas do ECG. \n' asEleOnda = '❌' erro++ } if (incompatEleMec){ //oid.know += -> Uma ou mais atividades elétricas não disparam às atividades mecânicas que foram associadas.\n - oid.asEleMec = 'Uma ou mais atividades elétricas não disparam às atividades mecânicas.\n' + oid.asEleMec = 'Uma ou mais atividades elétricas não disparam às atividades mecânicas. \n' asEleMec = '❌' erro++ } if (incompatOndaMec){ //oid.know += -> Uma ou mais ondas do ECG não corresponde às atividades mecânicas associadas.\n - oid.asMecOnda = 'Uma ou mais ondas do ECG não corresponde às atividades mecânicas associadas.\n' + oid.asMecOnda = 'Uma ou mais ondas do ECG não corresponde às atividades mecânicas associadas. \n' asMecOnda = '❌' erro++ } @@ -272,6 +272,51 @@ Oid.customize('foid:lively-talk', { else if (parameters.value == 'associacao-incorreta') { oid.handleSend('display', {value: oid.smassociacao}) + }else if (parameters.value == 'smsem-coracao') { + oid.handleSend('display', + {value: 'No menu de componentes você verá 4 blocos clique em um para começar.'}) + }else if (parameters.value == 'ins') { + oid.handleSend('display', + {value: 'Encaixe os blocos soltos dentro de um bloco roxo escuro para fazer as associações.\n'}) + } + else if (parameters.value == 'fc') { + oid.handleSend('display', + {value: 'Meu coração esta incompleto, coloque mais blocos.\n'}) + } + else if (parameters.value == 'mc') { + oid.handleSend('display', + {value: 'Estou sobrecarregando! Tire alguns blocos.\n'}) + } + else if (parameters.value == 'v') { + oid.handleSend('display', + {value: 'Associação incompleta. Não deixe campos vazios no bloco roxo escuro.\n'}) + } + else if (parameters.value == 'te') { + oid.handleSend('display', + {value: 'Revise o texto das atividades elétricas.\n'}) + }else if (parameters.value == 'tm') { + oid.handleSend('display', + {value: 'Revise o texto das atividades mecânica.\n'}) + }else if (parameters.value == 'oe') { + oid.handleSend('display', + {value: 'O impulso elétrico não segue o caminho esperado, revise a ordem.\n'}) + } + else if (parameters.value == 'oo') { + oid.handleSend('display', + {value: 'A onda não segue o caminho esperado, revise a ordem.\n'}) + }else if (parameters.value == 'om') { + oid.handleSend('display', + {value: 'O movimento do coração não pode bombear o sangue, revise a ordem.\n'}) + }else if (parameters.value == 'aeo') { + oid.handleSend('display', + {value: 'Alguma onda do ECG e a atividade elétrica associada não está compativel, tente outra combinação.\n'}) + } + else if (parameters.value == 'aem') { + oid.handleSend('display', + {value: 'Alguma atividade mecânica não combina com atividade elétrica escolhida, tente outra combinação.\n'}) + }else if (parameters.value == 'aom') { + oid.handleSend('display', + {value: 'Alguma onda do ECG representa outro movimento mecânico do coração, reveja.\n'}) } else if (parameters.value.length == 0) oid.statements = null From fc222163d8eb9f33d4248869c06316cefb266a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Santanch=C3=A8?= Date: Sat, 16 Dec 2023 16:08:57 -0300 Subject: [PATCH 2/2] feat (annotation): new clustering metric --- .../public/editor/annotate/js/annotator.js | 6 +- .../public/editor/annotate/js/metrics.js | 52 ++++++ .../public/editor/annotate/metrics/index.html | 1 + .../public/editor/annotate/metrics/metrics.js | 148 ++++++++++++++---- .../cases/play/schemas/heart-robot-kolb.csv | 1 + .../public/report/js/report-annotations.js | 9 +- 6 files changed, 186 insertions(+), 31 deletions(-) create mode 100644 src/adonisjs/public/report/category/cases/play/schemas/heart-robot-kolb.csv diff --git a/src/adonisjs/public/editor/annotate/js/annotator.js b/src/adonisjs/public/editor/annotate/js/annotator.js index dffa3361..9c121757 100644 --- a/src/adonisjs/public/editor/annotate/js/annotator.js +++ b/src/adonisjs/public/editor/annotate/js/annotator.js @@ -539,6 +539,9 @@ class Annotator { o2html += '' } const ctcategories = Object.keys(catIndex).length + + const clustering = Math.round(AnnotationMetrics.i._clusteringFreeRecall(catOrder)*100) / 100 + if (isAnnotations) { document.querySelector('#memory-scores').innerHTML = `` diff --git a/src/adonisjs/public/editor/annotate/js/metrics.js b/src/adonisjs/public/editor/annotate/js/metrics.js index fe451dd3..6c7e69bd 100644 --- a/src/adonisjs/public/editor/annotate/js/metrics.js +++ b/src/adonisjs/public/editor/annotate/js/metrics.js @@ -60,6 +60,58 @@ class AnnotationMetrics { score: subs } } + + /* + * Category clustering calculator for free recall + * https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3665324/ + */ + _clusteringFreeRecall (categoriesOrder) { + const n = categoriesOrder.length // number of recalled items + + // sort by text position (second element) + const sortedL = categoriesOrder.sort((a, b) => a[1] - b[1]) + + const nc = {} // number of recalled items in each recalled category + let r = 0 // number of category repetition + for (let i = 0; i < sortedL.length; i++) { + const cat = sortedL[i][0] + if (!nc[cat]) + nc[cat] = 1 + else + nc[cat]++ + let nextPos = i + 1 + while (nextPos < sortedL.length && sortedL[nextPos][1] === sortedL[i][1]) + nextPos++ + if (nextPos < sortedL.length) { + let sp = nextPos + while (sp < sortedL.length && sortedL[sp][1] === sortedL[nextPos][1]) { + if (cat == sortedL[sp][0]) { + r++ + break + } + sp++ + } + } + } + + const c = Object.keys(nc).length // number of recalled categories + const max = n - c // maximum possible number of category repetitions + + let er = 0 // expected number of category repetitions + for (const cat in nc) + er += nc[cat] * nc[cat] + er = er / n - 1 + + const rr = r / (n - 1) // ratio of repetition + + const mrr = r / max // modified ratio of repetition + + const ds = r - er // deviation score + + const arc = (r - er) / (max - er) // adjusted ratio of clustering + + return arc + } } (function () { diff --git a/src/adonisjs/public/editor/annotate/metrics/index.html b/src/adonisjs/public/editor/annotate/metrics/index.html index c33b35e5..dfc93750 100644 --- a/src/adonisjs/public/editor/annotate/metrics/index.html +++ b/src/adonisjs/public/editor/annotate/metrics/index.html @@ -1,6 +1,7 @@ + diff --git a/src/adonisjs/public/editor/annotate/metrics/metrics.js b/src/adonisjs/public/editor/annotate/metrics/metrics.js index ae19295e..71f1e5b7 100644 --- a/src/adonisjs/public/editor/annotate/metrics/metrics.js +++ b/src/adonisjs/public/editor/annotate/metrics/metrics.js @@ -1,7 +1,7 @@ function sortSubstitutionCount(numbersList) { const sortedL = numbersList.slice().sort((a, b) => a - b) - console.log(numbersList) - console.log(sortedL) + present(numbersList) + present(sortedL) let subs = 0 for (let i = 0; i < numbersList.length; i++) { if (numbersList[i] !== sortedL[i]) { @@ -11,18 +11,18 @@ function sortSubstitutionCount(numbersList) { return Math.ceil(subs/2) } -// console.log(sortSubstitutionCount([1, 1, 1, 2, 3, 3, 4])) -// console.log(sortSubstitutionCount([1, 1, 1, 3, 2, 3, 4])) -// console.log(sortSubstitutionCount([1, 1, 1, 3, 3, 2, 4])) -// console.log(sortSubstitutionCount([1, 1, 1, 4, 3, 2, 3])) -// console.log(sortSubstitutionCount([1, 4, 1, 3, 3, 2, 1])) -// console.log(sortSubstitutionCount([4, 3, 3, 2, 1, 1, 1])) +// present(sortSubstitutionCount([1, 1, 1, 2, 3, 3, 4])) +// present(sortSubstitutionCount([1, 1, 1, 3, 2, 3, 4])) +// present(sortSubstitutionCount([1, 1, 1, 3, 3, 2, 4])) +// present(sortSubstitutionCount([1, 1, 1, 4, 3, 2, 3])) +// present(sortSubstitutionCount([1, 4, 1, 3, 3, 2, 1])) +// present(sortSubstitutionCount([4, 3, 3, 2, 1, 1, 1])) function selfOrderCount(categoriesOrder) { // sort by text position (second element) const sortedL = categoriesOrder.sort((a, b) => a[1] - b[1]) - console.log('Sorted by position') - console.log(sortedL) + present('Sorted by position') + present(sortedL) // group by category (first element) // group = [category, position, count] @@ -46,13 +46,13 @@ function selfOrderCount(categoriesOrder) { prev = i } } - console.log('Grouped by category') - console.log(JSON.parse(JSON.stringify(grouped))) + present('Grouped by category') + present(JSON.parse(JSON.stringify(grouped))) // sort groups by position (second element) const sortedG = grouped.sort((a, b) => a[1] - b[1]) - console.log('Group sorted by position') - console.log(JSON.parse(JSON.stringify(sortedG))) + present('Group sorted by position') + present(JSON.parse(JSON.stringify(sortedG))) // count order change to group together categories let subs = 0 @@ -75,21 +75,113 @@ function selfOrderCount(categoriesOrder) { } } } - console.log('Final group after ordering') - console.log(sortedG) + present('Final group after ordering') + present(sortedG) return subs } -console.log(selfOrderCount( - [[1, 10], [2, 20], [1, 20], [2, 30]])) -console.log(selfOrderCount( - [[1, 10], [2, 20], [1, 25], [2, 30]])) -console.log(selfOrderCount( - [[1, 10], [2, 20], [1, 20], [3, 20], [1, 30], [2, 30], [3, 30]])) -console.log(selfOrderCount( - [[2, 71], [2, 96], [3, 98], [2, 100], [5, 120], [5, 130], [5, 135], [3, 140], [5, 180]])) -console.log(selfOrderCount( - [[5, 135], [2, 100], [2, 71], [2, 96], [5, 130], [3, 98], [5, 180], [5, 120], [3, 140]])) -console.log(selfOrderCount( - [[2, 71], [2, 96], [3, 98], [2, 98], [5, 98], [5, 130], [5, 135], [3, 140], [5, 180]])) \ No newline at end of file +// present(selfOrderCount( +// [[1, 10], [2, 20], [1, 20], [2, 30]])) +// present(selfOrderCount( +// [[1, 10], [2, 20], [1, 25], [2, 30]])) +// present(selfOrderCount( +// [[1, 10], [2, 20], [1, 20], [3, 20], [1, 30], [2, 30], [3, 30]])) +// present(selfOrderCount( +// [[2, 71], [2, 96], [3, 98], [2, 100], [5, 120], [5, 130], [5, 135], [3, 140], [5, 180]])) +// present(selfOrderCount( +// [[5, 135], [2, 100], [2, 71], [2, 96], [5, 130], [3, 98], [5, 180], [5, 120], [3, 140]])) +// present(selfOrderCount( +// [[2, 71], [2, 96], [3, 98], [2, 98], [5, 98], [5, 130], [5, 135], [3, 140], [5, 180]])) + +/* + * Category clustering calculator for free recall + * https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3665324/ + * tested here and traferred to /editor/annotate/js/metrics.js +*/ +function clusteringFreeRecall(categoriesOrder, console) { + + const n = categoriesOrder.length // number of recalled items + + // sort by text position (second element) + const sortedL = categoriesOrder.sort((a, b) => a[1] - b[1]) + + const nc = {} // number of recalled items in each recalled category + let r = 0 // number of category repetition + for (let i = 0; i < sortedL.length; i++) { + const cat = sortedL[i][0] + if (!nc[cat]) + nc[cat] = 1 + else + nc[cat]++ + let nextPos = i + 1 + while (nextPos < sortedL.length && sortedL[nextPos][1] === sortedL[i][1]) + nextPos++ + if (nextPos < sortedL.length) { + let sp = nextPos + while (sp < sortedL.length && sortedL[sp][1] === sortedL[nextPos][1]) { + if (cat == sortedL[sp][0]) { + r++ + break + } + sp++ + } + } + } + + const c = Object.keys(nc).length // number of recalled categories + const max = n - c // maximum possible number of category repetitions + + let er = 0 // expected number of category repetitions + for (const cat in nc) + er += nc[cat] * nc[cat] + er = er / n - 1 + + const rr = r / (n - 1) // ratio of repetition + + const mrr = r / max // modified ratio of repetition + + const ds = r - er // deviation score + + const arc = (r - er) / (max - er) // adjusted ratio of clustering + + if (console) { + present('\n\n=== Clustering Free Recall ===') + present(JSON.stringify(categoriesOrder)) + present('--- n = ' + n) + present('--- sorted by position') + present(JSON.stringify(sortedL)) + present('--- c = ' + c) + present('--- ni') + present(nc) + present('--- r = ' + r) + present('--- max = ' + max) + present('--- E(r) = ' + Math.round(er * 100) / 100) + present('--- RR = ' + Math.round(rr * 100) / 100) + present('--- MRR = ' + Math.round(mrr * 100) / 100) + present('--- DS = ' + Math.round(ds * 100) / 100) + present('--- ARC = ' + Math.round(arc * 100) / 100) + } + + return arc +} + +function present (output) { + document.querySelector('#console').value += output + '\n' +} + +present(clusteringFreeRecall( + [[2, 1], [4, 2], [4, 3], [3, 4], [2, 5], [3, 6], [1, 7], [4, 8], [4, 9]], true +)) +present(clusteringFreeRecall( + [[3, 1], [4, 2], [4, 3], [3, 4], [1, 5], [1, 6], [3, 7], [1, 8], [1, 9], [2, 10], [2, 11], [2, 12], [4, 13], [4, 14], [3, 15]], true +)) +present(clusteringFreeRecall( + [[2, 1], [2, 2], [3, 3], [1, 4], [1, 5], [1, 6], [1, 7], [2, 8], [3, 9], [3, 10], [2, 11], [1, 12], [4, 13], [4, 14], [4, 15], [4, 16], [2, 17], [2, 18], [3, 19], [1, 20]], true +)) +present(clusteringFreeRecall( + [[5, 135], [2, 100], [2, 71], [2, 96], [5, 130], [3, 98], [5, 180], [5, 120], [3, 140]], true)) +present(clusteringFreeRecall( + [[2, 71], [2, 96], [3, 98], [2, 98], [5, 98], [5, 130], [5, 135], [3, 140], [5, 180]], true)) +present(clusteringFreeRecall( + [[2, 71], [2, 96], [3, 98], [2, 98], [5, 98], [7,98], [5, 130], [5, 135], [3, 140], [5, 180]], true)) \ No newline at end of file diff --git a/src/adonisjs/public/report/category/cases/play/schemas/heart-robot-kolb.csv b/src/adonisjs/public/report/category/cases/play/schemas/heart-robot-kolb.csv new file mode 100644 index 00000000..da9f4889 --- /dev/null +++ b/src/adonisjs/public/report/category/cases/play/schemas/heart-robot-kolb.csv @@ -0,0 +1 @@ +Kolb1.kb1,Kolb2.kb2,Kolb3.kb3,Kolb4.kb4,Kolb5.kb5,Kolb6.kb6,Kolb7.kb7,Kolb8.kb8,Kolb9.kb9,Kolb10.kb10,Kolb11.kb11,Kolb12.kb12 \ No newline at end of file diff --git a/src/adonisjs/public/report/js/report-annotations.js b/src/adonisjs/public/report/js/report-annotations.js index e0716aff..f798548d 100644 --- a/src/adonisjs/public/report/js/report-annotations.js +++ b/src/adonisjs/public/report/js/report-annotations.js @@ -111,6 +111,8 @@ class ReportManager { } const selfOrder = AnnotationMetrics.i._selfOrderCount(catOrder) + const clustering = AnnotationMetrics.i._clusteringFreeRecall(catOrder) + let o1csv = '' let sep = '' for (const g of selfOrder.groups) { @@ -133,7 +135,10 @@ class ReportManager { const ctcategories = Object.keys(catIndex).length - return `${ctcategories},${ctright},${ctinfright},${ctideas},${ctrightencap},${ctinfrightencap},${ctwrong},${ctwrongencap},${ctcategories * ctideas},${(ctideas == 0) ? 0 : ctright / ctideas},${(ctideas == 0) ? 0 : ctinfright / ctideas},${(ctideas == 0) ? 0 : (ctrightencap + ctwrongencap) / ctideas},${selfOrder.score},${(ctideas == 0) ? 0 : selfOrder.score / ctideas}${countCat},"${o1csv}","${o2csv}"` + return `${ctcategories},${ctright},${ctinfright},${ctideas},${ctrightencap},${ctinfrightencap},${ctwrong},${ctwrongencap},` + + `${ctcategories * ctideas},${(ctideas == 0) ? 0 : ctright / ctideas},${(ctideas == 0) ? 0 : ctinfright / ctideas},` + + `${(ctideas == 0) ? 0 : (ctrightencap + ctwrongencap) / ctideas},${selfOrder.score},` + + `${(ctideas == 0) ? 0 : selfOrder.score / ctideas},${clustering}${countCat},"${o1csv}","${o2csv}"` } async _download () { @@ -146,7 +151,7 @@ class ReportManager { '"used categories","right","right (inferred)","total ideas","right encapsulated",' + '"right encapsulated (inferred)","wrong","wrong encapsulated","coverage score",' + '"accuracy score","accuracy score (inferred)","encapsulated score","self order score",' + - '"normalized self order score"' + '"normalized self order score","clustering in free recall"' for (const m in ReportManager.catList) table += ',"' + ReportManager.catList[m] + '"'
Erro
' + catList[g[0]-1] + '' + g[2] + '