Skip to content

Add a multiple choice match list macro. - #1541

Open
drgrice1 wants to merge 1 commit into
openwebwork:developfrom
drgrice1:match-list-macro
Open

drgrice1 wants to merge 1 commit into
openwebwork:developfrom
drgrice1:match-list-macro

Conversation

@drgrice1

@drgrice1 drgrice1 commented Sep 20, 2026 •

Copy link
Copy Markdown
Member

The parserMatchList.pl macro is intended to replace the PGchoicemacros.pl match list (obtained via new_match_list). This is the only thing left from the PGchoicemacros.pl that has not yet been replaced with a modern MathObject equivalent.

The MatchList object derives from a Value::List and is an ans_array type answer. So it is inserted into PGML with the [_]*{...} syntax, and if a custom checker is desired the list_checker is needed.

This macro is similar in nature to the parserPopUp.pl and parserCheckboxList.pl macros in many ways, and actually uses the parserPopUp.pl DropDown object internally. As with the objects from those macros, this MatchList object can be used as a part answer in a MultiAnswer or RadioMultiAnswer.

The tutorial/sample-problems/Misc/Matching.pg has been replaced with the tutorial/sample-problems/Misc/MatchList.pg problem. The tutorial/sample-problems/Misc/MatchingAlt.pg has also been removed, since that approach is better accomplished with the parserMatchList.pl macro.

There are unit tests for the macro in t/macros/parserMatchList.t.

Note that the PTX output will need verification (and probably modification). Claude added something for that, but I don't know what it is correct.

Here are some problems that demonstrate some other uses of the macro that are different than the sample problem:
MatchList.zip

Edit:

Added options:

  • verticalAlign: vertical alignment of the entire match list (top, middle, or bottom)
  • questionVerticalAlign: alignment of the question contents inside the div that contains it
  • choiceVerticalAlign: alignment of the choice contents inside the div that contains it

Added method:

  • answer: Call $ml->answer($i) to get the textual answer for question $i.

@drgrice1

Copy link
Copy Markdown
Member Author

The attached example problems include problems that use a MatchList in a MultiAnswer and RadioMultiAnswer, and the examples have custom checkers. I wanted to point out that the default MultiAnswer and RadioMultiAnswer checkers do work. The examples just demonstrate how you would do things in a custom checker.

@pstaabp

pstaabp commented Sep 24, 2026

Copy link
Copy Markdown
Member

Overall, this works well. I've been testing this by rewriting some problems. I have a few comments:

  1. Should we add this to the parserMultipleChoice.pl macro?
  2. I haven't come across an example where I've wanted this, but I wonder if we want a layout option with the questions/answers above each other? This may be helpful when either the questions or answers are long. I notice that problems react well when the screen is narrow, so this may not be needed.
  3. I've been also writing solutions that access the solution. It would be nice to have access to the string answer to the $i th question. I got around this by defining the question/answer array refs, then accessing them with the originalIndex method, but a answer($i) would be nice.

@drgrice1

Copy link
Copy Markdown
Member Author
  1. Should we add this to the parserMultipleChoice.pl macro?

I suppose. I will leave that up to @Alex-Jordan. To be honest, I don't know why that macro file exists, and I don't think it is a good idea to even have. I missed when that was added.

  1. I haven't come across an example where I've wanted this, but I wonder if we want a layout option with the questions/answers above each other? This may be helpful when either the questions or answers are long. I notice that problems react well when the screen is narrow, so this may not be needed.

Generally, the responsive layout that is used will work for all scenarios. But we can add other layout options if needed. I will leave that for another pull request though.

  1. I've been also writing solutions that access the solution. It would be nice to have access to the string answer to the $i th question. I got around this by defining the question/answer array refs, then accessing them with the originalIndex method, but a answer($i) would be nice.

You state the last sentence as a workaround, but that is the intended way to do that. You have the list of answers, and you have the originalIndex method to get the answer displayed in position $i from the original list. For direct access to the choice string displayed at index $i you could also use $ml->choices->[$i]. That does exactly what your proposed answer($i) call would do.

@Alex-Jordan

Copy link
Copy Markdown
Contributor

I will think about better PTX output here. Off the top of my head, a sidebyside, with two p, each having an ol. The labeling (ABC/123) etc needs to respect the labeling that the problem author gave.

parserMultipleChoice.pl was meant as a convenience macro, for people who find it hard to remember the names of our macro files (even though this name isn't any better). It also helps in a tiny way if you decide you want to switch a radio buttons problem to dropdown, in that you can just change the code and not change the macro library. But it's not a big deal. If it continues to exist, then it should include this new one.

I'm trying this with an old image matching exercise. Could there be options for vertical alignment? Just playing with CSS, I can get:

Screenshot 2026-09-24 at 11 24 21 AM

To look this way instead:

Screenshot 2026-09-24 at 11 25 37 AM

Also, when the answer options are tall lists like this, I think it could be better to have the question part top-aligned, like this:

Screenshot 2026-09-24 at 11 28 42 AM

@drgrice1
drgrice1 force-pushed the match-list-macro branch 5 times, most recently from b4e86b2 to 29f9d61 Compare September 24, 2026 21:10
@drgrice1

drgrice1 commented Sep 24, 2026 •

Copy link
Copy Markdown
Member Author

I added several options and another method. See my edited initial comment.

@Alex-Jordan: With the new options you can achieve the alignment you requested. Set verticalAlign => 'top' to get the questions and choices top aligned instead of vertically centered. Set choiceVerticalAlign => 'top' to get the label top aligned with the choice text (or image).

Note that using images as choices in this macro (just as for using them for the parserRadioButtons.pl or parserCheckboxList.pl) is not well supported at this point. GD images might work alright, but you shouldn't be using those. Images created with plots.pl do not work so well. With all of the macros issue #1542 causes a problem. With the parserRadioButtons.pl and parserCheckboxList.pl macros there is also an issue with putting divs inside a label. I have a branch that adds an optional layout for those macros that would make it valid for an image (it uses a flex layout and puts the div image outside of the label), but it doesn't fix issue #1542.

I added this macro to those that are loaded by the parserMultipleChoice.pl macro. The problem that I have with that macro is that it is encouraging inefficiently loading macros that aren't used. With the need to get problems to render with less overhead for the server, that is not good.

@drgrice1
drgrice1 force-pushed the match-list-macro branch 4 times, most recently from f51c112 to 2853785 Compare September 28, 2026 11:40
The `parserMatchList.pl` macro is intended to replace the
`PGchoicemacros.pl` match list (obtained via `new_match_list`).
This is the only thing left from the PGchoicemacros.pl that has not yet
been replaced with a modern MathObject equivalent.

The `MatchList` object derives from a `Value::List` and is an
`ans_array` type answer.  So it is inserted into PGML with the
`[_]*{...}` syntax, and if a custom checker is desired the
`list_checker` is needed.

This macro is similar in nature to the `parserPopUp.pl` and
`parserCheckboxList.pl` macros in many ways, and actually uses the
`parserPopUp.pl` `DropDown` object internally. As with the objects from
those macros, this `MatchList` object can be used as a part answer in a
`MultiAnswer` or `RadioMultiAnswer`.

The `tutorial/sample-problems/Misc/Matching.pg` has been replaced with
the `tutorial/sample-problems/Misc/MatchList.pg` problem.  The
`tutorial/sample-problems/Misc/MatchingAlt.pg` has also been removed,
since that approach is better accomplished with the `parserMatchList.pl`
macro.

There are unit tests for the macro in `t/macros/parserMatchList.t`.

Note that the `PTX` output will need verification (and probably
modification).  Claude added something for that, but I don't know what
it is correct.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@pstaabp

pstaabp commented Sep 28, 2026

Copy link
Copy Markdown
Member

I'm not getting the questions and choices to align top/bottom. It seems like lines 580 and 594 is where the css class is set, but that is on the individual items. Shouldn't the align be on the containing div? (line 568)

@drgrice1

Copy link
Copy Markdown
Member Author

@pstaabp: Are you trying to align the questions and choices, or are you trying to align the content of the questions or choices? The lines of code that you are referring to are for the alignment of question or choice content, not for alignment of the questions and choices. The alignment of questions and choices is set with the verticalAlign option, and that IS done on line 568 of the code (which is the containing div).

@pstaabp

pstaabp commented Sep 28, 2026

Copy link
Copy Markdown
Member

I think I misunderstood what those did. I was thinking the questionVerticalAlign and choiceVerticalAlign individually aligned the questions and choices, not aligning within the div?

@drgrice1

Copy link
Copy Markdown
Member Author

Yes, the verticalAlign option affects both questions and choices and applies to the container. The questionVerticalAlign and choiceVerticalAlign options affect the alignment of the contents of individual questions or choices. These options were created to address the two different alignment cases that @Alex-Jordan noted. First, he asked that the label be top aligned for an image (for that use the choiceVerticalAlign option). Second, he asked that when the list of answer choices is tall that the questions and answers be top aligned (for that use the verticalAlign option).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants