Counting correct answers to questions

What I’m trying to do

A score that shows how many questions of a quiz or test I got right. With the total number of questions and the number of correct answers. I’d like to add the following buttons:

Correct: increases both the total number of questions answered and the number of correct answers. (example: 7/10 → 8/11)
Wrong: only increases the total number of questions answered. (example: 7/10 → 7/11)

Things I have tried

At the moment, I’m using the progress bar itself (example: ). But there isn’t a mechanism for buttons like the ones mentioned above, and I don’t know how to implement that.

It would be great to have your help with this. Thanks in advance.

What type of progress bar are you using ?
I think there is a possibility of something like that with a combination of advanced-uri plugin and buttons, or with dataviewjs and metadata menu plugin, or with the buttons plugin.

1 Like

I’m using the default progress bar from the HTML language that comes embed with Obsidian (class: progress). Ex: <progress value=2 max=3></progress>

You can try this dataviewjs code:

```dataviewjs
let current = dv.current();
let currentFile = app.vault.getAbstractFileByPath(current.file.path);
let test = parseInt(dv.current().test);
let max = parseInt(dv.current().max);
const button = dv.el('button', 'Correct'); button.onclick = () => { app.fileManager.processFrontMatter(currentFile, (frontmatter) => { frontmatter["test"] = test + 1}); app.fileManager.processFrontMatter(currentFile, (frontmatter) => { frontmatter["max"] = max + 1})}; 
const button2 = dv.el('button', 'Wrong'); button2.onclick = () => { app.fileManager.processFrontMatter(currentFile, (frontmatter) => { frontmatter["max"] = max + 1 })}; 
 dv.el('progress', " ",{ attr: { value: test, max: max } }); dv.span(" " + dv.current().test + " / " + dv.current().max);
 dv.paragraph("")
 dv.span(button); dv.span(button2);
```

This code relies on properties (here test and max, but you can change the name and the properties) to display a progress bar, and displays buttons that allow you to increment either both properties if correct, or max alone if wrong.

1 Like

Thank you, you saved me. It works well.

I would join the two changes to the frontmatter into one call of app.fileManager.processFrontMatter(), so you don’t have two independent file write operations to the same file.

And the code also demands for the properties to be present when you start the show… There is also a small feature, that if you spam click either button, it might lag a little (or demand another click (or reload) after a little delay) to get the correct number.

Accounting for all of this, and joining the handling into one function, we end up with another way of doing this which look like this:

```dataviewjs
const TOTAL_KEY = "total"
const CORRECT_KEY = "correct"

async function handleButton(currentFile, deltaCorrect ) {
  await app.fileManager.processFrontMatter(currentFile, (fm) => {
    // Verify that our properties actually exists, and create if not
    if ( !(TOTAL_KEY in fm)  ) fm[TOTAL_KEY] = 0
    if ( !(CORRECT_KEY in fm) ) fm[CORRECT_KEY] = 0

    // Increase total number, and add the delta to the other
    fm[TOTAL_KEY] += 1
    fm[CORRECT_KEY] += deltaCorrect
  })
}

const current = dv.current()
const currentFile = app.vault.getAbstractFileByPath(current.file.path)

const countCorrect = dv.el('button', 'Correct')
countCorrect.onclick = () => { handleButton(currentFile, 1) }

const countWrong = dv.el('button', 'Wrong')
countWrong.onclick = () => { handleButton(currentFile, 0) }

let test = parseInt(dv.current()[CORRECT_KEY] ?? 0)
let max = parseInt(dv.current()[TOTAL_KEY] ?? 0)
 
dv.el('progress', " ",{ attr: { value: test, max: max } })
dv.span(" " + test + " / " + max)

dv.paragraph("")

dv.span(countCorrect); dv.span(countWrong)
```

Here it’s also easier to change to whatever key/property names you want to use, as they’re declared as constant at the start. And we give them a start of 0, so it looks nice even with undefined properties.

There are simply too many ways to do stuff when coding, so this is not say that @Anwen’s solution is wrong in any way, it’s just a different variant with slightly more error handling along the way.

4 Likes

It was really a great improvement. Is there any way to make the Correct button green and the Wrong button red? I can only change both at once by making the following change in the CSS snippet:

.block-language-dataviewjs button {
background-color: #008000;
}

You mean something like this?

const countCorrect = dv.el('button', 'Correct', { attr: { style:"background-color: green;" }})

You could also add a class the same way, if you want to do many style changes… :smiley:

1 Like

That’s right. Thanks a lot for the help.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.