Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MathQuill replaces AnSwEr input fields #920

Closed
wants to merge 3 commits into from

Conversation

drdrew42
Copy link
Sponsor Member

This is only a rudimentary implementation of the MathQuill live-renderer. All AnSwEr000# blanks are greedily supplanted by a live-rendering input field. (limited to the first 9 answer blanks for now)

The immediate rendering of expressions is quite impressive, and I think I've managed to ensure that prior answers are rendered accurately (albeit with some additional parenthesis) when the page is reloaded. Additionally, MathQuill automatically resizes the entry box as its contents grow...

caveat: Answers that expect string responses (single-letter MC responses are fine) will not work with this feature. For example, "hello" is interpreted as h * e * l * l * o.

@mgage
Copy link
Sponsor Member

mgage commented Jan 22, 2019

This appears to have been based off of master. It needs to be rebased to descend from develop.

I believe that is why there are a number of conflicted files in the PR above.

It's possible there maybe changes in master that should be made in develop as well. (Mostly replacing hosted2 with demo in urls).

@Alex-Jordan
Copy link
Contributor

I happen to be testing an Edfinity course for basic algebra this term, and Edfinity already uses MathQuill. We've hit a problem that may or may not be relevant for this WeBWorK feature. It stems from this MathQuill bug. The symptom is that in my course, when students are required to practice set-builder notation like {x|x>0}, students have no way to enter that. You start typing, and the first { makes a ghosted } suggested at the end of the expression. When you type the |, that counts as a delimiter partner for the {, and the ghost } clears away. So you keep typing and get to the }, but this causes MathQuill to insert a { back at the beginning. So you have {{x|x>0}. You can't delete one of the { without also deleting either the | or the }, and the student is stuck unable to submit a correct answer.

When testing this feature, this is something to look at. Of course it would be MathQuill's problem to solve.

Let's assume they solve that problem. I would want to disable this feature if it is going to turn text answers into math. Like no solution into $no solution$. UNLESS there could be a way to give a data attribute to the answer blank acknowledging that some text (non-math) input is expected, and based on that, MathQuill would turn itself off. Is there any hope of answer blanks knowing whether or not they expect some text in the correct answer?

@drdrew42
Copy link
Sponsor Member Author

I'm also curious how Edfinity has implemented the translation to pure-text math, as the MathField.text() method in MQ produces horrible output for \sin and \cos, though it's fine for \sqrt... This makes it difficult to push the math that's been entered over to WW to be evaluated.

I've got a very basic LaTeX to text parser adapted from some found-code, making things a little better, but not close to being robust. Basic latex is now converted into properly parse-able text for webwork to evaluate - at the expense of additional parens, which are re-rendered when the page is reloaded on "submit answer". This leads to potential cascades of parenthesis, which I'm trying to resolve on load, instead of prior to submission.

@heiderich
Copy link
Member

It looks cool. However, without having looked at the details, I would be surprised if, without modification, MathQuill could deal properly with all possible syntax of PG, in particular having in mind the flexibility the contexts and the configurable parser of PG allows. Therefore I also think that it would be helpful if MathQuill could be enables and disables on a per problem basis.

@taniwallach
Copy link
Member

The ideas sounds really cool, but the issues of short phrase answers and other settings where MathQuill does not behave well (such as the ones @Alex-Jordan mentioned) certainly means that finer level control of when MQ should manage a given answer blank is probably necessary in the long-term.

Optimally, it seems that there will need to be some mechanism for PG to either white-list which answer blanks should be handled by MathQuill or to black-list which ones should not, possibly by setting something in the HTML class attributes of the input elements, or by embedding some data for the JavaScript code to process before modifying the answer blanks.

In the short term, it may be simple to provide a mechanism to disable MQ for an entire problem, without the fine tuning for specific answer blanks.

@taniwallach
Copy link
Member

Some issues to consider:

However, Desmos must somehow be parsing the functions back into something which defined the function to be graphed in some reasonable way, so is probably a good solution to this issue.

@Alex-Jordan
Copy link
Contributor

For what its worth, I would argue against anything in a .pg file that gets into managing MathQuill. I have a similar sentiment towards hints and the $showhints variable. A .pg file should be readily shared via the OPL, and some of these decisions (showing hints, not showing them) differ when the problem is used by instructor A at school B for Course C compared to instructor X at school Y in course Z. For example with MQ, the implementation I've seen in Edfinity wants to auto-complete delimiters. At some very low levels I sometimes teach at, auto-completion defeats the purpose of the exercise. So you could have a low-level problem where one instructor wants that feature and another does not, hence my position that these things should not be coded into .pg problems.

Instead I see them as either

  1. course configuration issues
  2. attributes of a problem as it is incorporated into a set, like the point value, attempts value, or SMA threshold of a problem.

MathObjects can store all kinds of properties. Suppose that one property of a MathObject was a control board of sorts for what kinds of translations MQ is allowed to do. And that when you use $mo->ans_rule, it passed an attribute to the input field (with HTML output) that communicated that control board.

Viewing the issue as in arena 1 above, the Context() could set defaults for this control board for each class of MO. And these could be overridden with the local macros folder or course.conf or a combination of both. A String could ignore MQ altogether. A Formula in FormulaWithUnits could turn "sin" into s\,\mathrm{in} instead of \sin, for instance.

Viewing the issue as in arena 2 above would make the Set Details page messy, so I'd steer away from that. Unless it was just a very simple boolean switch "turn on/off MQ for this problem" field.

But I'll repeat my thesis that I think it would be unfortunate for problems to hard-code any MQ configuration. My PreTeXt training has me conscious of the different hats we wear. Here, there is the PG problem author and then there is the instructor managing their course. I'd argue that MQ configuration should be under control of the latter, not the former.

@dpvc
Copy link
Member

dpvc commented Jan 23, 2019

I've always been concerned about formatted editing in light of the fact that the problem Context can change the meaning of how the expressions are interpreted, and that information is not available in the browser. The editing assumes that the standard rules apply, and while that is true in the vast majority of problems, it is certainly not be the case in all of them.

There needs to be a mechanism for dealing with these problems, and I don't think it should fall on the professor to have to determine which are the ones that applies to. So while I agree with most of what Alex says above, I disagree with the suggestion that the problem file should not be able to control the availability of formatted editing. I think this has to be part of what the problem files do. Alex seems to be moving in that direction by suggesting that MathObject can help control that, and I agree with that. Using the context to send hints to MQ about the editing might be possible, but would take some work.

It sounds like MathQuil is producing LaTeX output, and that needs to be converted into WeBWorK's student input format. That seems like a fragile approach. No doubt MQ is storing some sort of parse tree internally, and that could be converted into the proper format directly rather than round-tripping through LaTeX.

Personally, I've never been a big fan of the visually-formatted math editor, but something that might be useful is a popup formatted version of the text string the student is entering. Something that hovers near the answer as the student types it and displays the formatted version (using MathJax, for instance). Didn't Geoff already do something like that?

@heiderich
Copy link
Member

There needs to be a mechanism for dealing with these problems, and I don't think it should fall on the professor to have to determine which are the ones that applies to. So while I agree with most of what Alex says above, I disagree with the suggestion that the problem file should not be able to control the availability of formatted editing. I think this has to be part of what the problem files do. Alex seems to be moving in that direction by suggesting that MathObject can help control that, and I agree with that. Using the context to send hints to MQ about the editing might be possible, but would take some work.

I agree with that.

Personally, I've never been a big fan of the visually-formatted math editor, but something that might be useful is a popup formatted version of the text string the student is entering. Something that hovers near the answer as the student types it and displays the formatted version (using MathJax, for instance). Didn't Geoff already do something like that?

This might be a safer approach. Even if something goes wrong with the preview, students would still be able to enter answers correctly. I remember having seen something like this in STACK.

@taniwallach
Copy link
Member

@drdrew42 - notwithstanding all the worries and potential pitfalls, I do think that MathQuill managed input could be a very helpful tool for many use cases. Please don't take these comments as more than a discussion of what needs to be overcome to make your vision into a reality, nor as a reason not to start testing things long before all the long-term solutions are found.

@Alex-Jordan wrote:

For what its worth, I would argue against anything in a .pg file that gets into managing MathQuill.
...
MathObjects can store all kinds of properties. ...
Viewing the issue as in arena 1 above, the Context() could set defaults for this control board for each class of MO. And these could be overridden with the local macros folder or course.conf or a combination of both. A String could ignore MQ altogether. A Formula in FormulaWithUnits could turn "sin" into s\,\mathrm{in} instead of \sin, for instance.
Viewing the issue as in arena 2 above would make the Set Details page messy, so I'd steer away from that. Unless it was just a very simple boolean switch "turn on/off MQ for this problem" field.

But I'll repeat my thesis that I think it would be unfortunate for problems to hard-code any MQ configuration. My PreTeXt training has me conscious of the different hats we wear. Here, there is the PG problem author and then there is the instructor managing their course. I'd argue that MQ configuration should be under control of the latter, not the former.

Alex - I hear what you are saying. However, I think @dpvc and @heiderich are right that the problem files need to be able to avoid MQ hijacking their input elements.

One of the criticisms most often raised against MathNet (the legacy system we are replacing) is the difficulty some students have in typing complex answers (ex. in some more complicated chain rule questions) and MathNet only allowed input with properly balanced parenthesis and would give some visual indications about improper balancing of parentheses. I suspect that some of our courses would be happy to let students use Wiris/MathType or MathQuill to help them visualize while they were typing or even give them a palette . Personally, I think that there is much to be said for students learning to type linear math notations on their own.

As such, I certainly understand the interest in some frameworks using answer input which have nice automatic rendering.

Florian @heiderich, Davide @dpvc and I are just making the point that pg is used for a broad enough class of problems (essays, string answers, non-standard math contexts) that some of them are likely not to want MQ to take control and mess up their input, so that turning MQ "hijacking" on/off only at the course level is not likely to be sufficient. It seems that In a course which has some content where MQ is desired and other content where it is not, some mechanism is needed to control when MQ should "hijack" an answer input element.

To this end, it is clear to me that the problem PG code should be able to very strongly suggest that MQ not interfere with some/all answer elements.

Supposing that any other technical issues with MQ "text()" output and compatibility with what WW needs as the answer syntax can be solved, the question is then what sort of control mechanisms are suitable.

Certainly, when MathObjects are used, sensible defaults, like disabling MQ for "strings" are possible via the MathObjects default settings, once MathObjects is extended to support the control of MQ hijacking of answer elements. However, not all older questions use MathObjects, and such older questions would also need to easily disable MQ for "strings."

In any case, a teacher who wishes to override the MO defaults (if MO provides a manner to adjust them) or override any settings hard-coded into a pg file can always make a locally modified version of the pg file to adjust the settings to their needs.

About the "problem level" disabling of MQ - the only thing needed would be some sort of boolean on/off setting. Whether such a setting is hard-coded into the pg file (and pushed directly into the HTML output) or set inside the set definition settings can be determined later. If it were in the set definition settings, maybe a pg problem (possibly via the library browser based on some setting from the problem tags) should be able to pass a "strong recommendation" to disable MQ for itself in some manner, to avoid the teachers needing to determine on their own when that should be done. (The direct disable in PG is almost certainly easier to implement.)

On the theme of getting valid answer strings out of MQ, as @dpvc noted, it is probably more feasible to extend MQ's functionality to create "WW input format" to to parse the LaTeX result. The problem is that the MQ team is focused on their needs, and WW has different needs. I'm not sure if someone has the time, interest, and inclination to work on adding "WW output" to MQ in the near future. (It seems to me that the commercial Wiris/MathType editor is probably a more practical short term option - as the company made the effort to produce output strings for WW as part of the code that they contributed to the WW codebase to interface with their product.)

BTW There is something which does try to offer a live preview: https://github.com/spirography/webwork-helper listed as "A chrome extension that adds several useful features to WeBWorK" though I have no idea of how well it works, and I assume it does not behave well on answers which need special syntax rather then simple function/expression syntax.

@Alex-Jordan
Copy link
Contributor

OK, I clarify my thesis:

Hard coding of display options (say for MathQuill live rendering) directly into a pg file should be possible, but not the first approach. In particular, when such things can be stashed into a context file, it would be good practice to do so.

A solution where the Context() settings and individual MathObject properties control the display parameters would be great. At that point, when someone gets the point of writing a problem, and they find themselves customizing the MathQuill parameters in the .pg file (say by setting context flags or the properties of an individual Math Object), I would ask them to think hard about whether it would be better to write a context.pl file to capture whatever the essence of the topic is that is calling for a deviation from the default.

Otherwise, in practice, the pg author makes a working problem, and then duplicates their setup code over and over into other problems. And if these choices conflict with another instructor's notation or curricular concerns, they either choose to not use these problems, or they have many files to manually edit into copies of essentially the same question. (And this just gets worse when one of these problems is put up as an example for new pg authors.) But contrast this with just making a single locally modified context file.

Something that hovers near the answer as the student types it and displays the formatted version (using MathJax, for instance). Didn't Geoff already do something like that?

Yes, that's the MathView editor. I like it, and we mostly do use it here. It does have its problems, including overlap with what we foresee being some trouble from MathQuill. There is a issue (#638) discussing some of these issues.

Please don't take these comments as more than a discussion of what needs to be overcome to make your vision into a reality, nor as a reason not to start testing things long before all the long-term solutions are found.

Absolutely. I took "this is only a rudimentary implementation" as an invitation to review what experience with similar things in the past has revealed. Either MathQuill- or WIRIS/MathType-based live rendering would be a highly desirable feature to many. Speaking of...

Wiris/MathType

What is the status with WeBWorK's WIRIS editor? It has one, I think with lots of options turned off. Is anyone using it in practice?

@drdrew42
Copy link
Sponsor Member Author

I took "this is only a rudimentary implementation" as an invitation to review what experience with similar things in the past has revealed.

Exactly. I had only come across mathquill at a conference last week, where @mgage jokingly said, "have it to me by Monday" and so I did. Though it was immediately clear that there were going to be exactly the kinds of issues we're discussing here - and I certainly appreciate hearing everyone's insights.

I agree with @Alex-Jordan that having the context somehow pass information about the type of answer it's expecting into the DOM is a preferable solution. For example, when rendering a PG file, and we come to the creation of an field, would it be possible to pass a class attribute that is determined from the answer object? In other words, at the point when webwork is generating fields, can webwork already determine the expected object for that field? If this is possible, then the mqeditor.js could check which AnSwEr#s are acceptable to replace by looking at the class attribute for each input field.

Regarding the preparation of a mathquill object for submission to webwork - I think it would not be too onerous to customize a mathquill method that generates a webwork-friendly string from their internal parsing tree. In building a customized mathquill, we can also stop the pipe from being a paired object, etc. I'm interested in pursuing this approach - which I think could address ~95% of the concerns around a feature of this type. The major exception I foresee is the handling of string input, which may be addressable from the page-rendering side via Context and MO properties.

What other major/minor issues might I be overlooking?

@mgage
Copy link
Sponsor Member

mgage commented Jan 25, 2019 via email

@drdrew42
Copy link
Sponsor Member Author

After slogging through the source code, I have solved some of the core issues with the .text() method - I can now get fundamental math functions (sine, cosine, log, etc.) to be delivered properly in plaintext from MathQuill to WeBWorK.

I've also found that by using \text followed by a space, one can enter an arbitrary string which is parsed and delivered as such. My next steps will be to restructure " as a paired delimiter to duplicate this effect. While typing " to begin a string may be a minor inconvenience, I believe this would go a long way towards resolving one of our fundamental conflicts.

Also, to-do: test out the removal of \pipe from the paired brackets category, in order to support set-builder notation as requested.

Comments and suggestions welcome.

@dpvc
Copy link
Member

dpvc commented Jan 30, 2019

Sorry for the late response, but there is an issue with this proposal

when MathObjects are used, sensible defaults, like disabling MQ for "strings" are possible via the MathObjects default settings

Most of the time strings are used, it is for something like "give the limit or type 'DNE' if it doesn't exist). That means that the answer blank, even when it is expecting a string, needs to be able to format expressions, because that is one of the types of answer that the student should be expecting to enter. If you turn off formatting for string answers, that will give away the fact that the answer is a string and not a number in this case.

So I think there has to be a means for MathQuill to handle (some predefined) strings. These can be obtained from the context, but simply disabling MathQuill for string input will be a problem.

@Alex-Jordan
Copy link
Contributor

I've also found that by using \text followed by a space, one can enter an arbitrary string which is parsed and delivered as such.

Just a note to be aware of. \text behaves differently for tex pdf output than for MathJax. In MathJax, (almost) no macros are expanded. So while \text{\ldots\%} will print …% in a latex pdf, it will print \ldots\% in MathJax output. That is just one example. The exceptions are that \$, \{, and \} are expanded in MathJax.

I don't know if this affects anything here, but I thought it worth mentioning.

@drdrew42
Copy link
Sponsor Member Author

In this case, the purposes for \text would be enabling arbitrary string input; and returning the space bar's ability to create white space. The .text() method returns the contents of a text-box completely as expected - allowing WeBWorK to receive the arbitrary string, exactly as typed. (Default behavior with the .text() method is to pass back a double-quoted string for text-box content, but that can be easily eliminated.)

As far as I can tell, regarding mathquill's behavior in text-mode, absolutely nothing is expanded (so nothing needs escaping either) until you type a $, which re-enables math-mode. So I guess you wouldn't be able to include a $ in your raw string without some further modifications.

@dpvc
Copy link
Member

dpvc commented Jan 30, 2019

@Alex-Jordan, I wrote an extension that allows more expansion within \text{}, in case that helps. it is not in core MathJax yet, but can be made into an extension that can be loaded.

@drdrew42, \text{} is probably not what you want to use, as we have had issues with that in the past when people's strings include TeX special characters. For example \text{a < b} will produce a ¡ b as the output in actual TeX, and \text{a_b} will produce an error about missing dollar signs (since _ can only be used in math mode). So unless you are escaping the TeX specials, \text{} is probably not the right way to go. Instead, you probably want to use \verb with a character as delimiter that is not used in the string.

@drdrew42
Copy link
Sponsor Member Author

@dpvc except that for MathQuill, \text is not a literal command in the TeX sense. LaTeX output is even disabled (I think?) for text-blocks. In essence, the \text command executes a fundamental shift in expected input for the mathField, which is only shifted back when a $ is entered. I had no difficulty entering a < b and have exactly that string passed back by the .text() method.

MathQuill is not a LaTeX parser in the usual sense - it's parsing in real-time, rather than parsing a fixed input string (unless you're using it to parse a fixed field in an HTML). Once text-mode is activated, it truly ignores everything, backslashes, other command strings that MQ normally intercepts, absolutely everything - except the dollar-sign.

@drdrew42
Copy link
Sponsor Member Author

drdrew42 commented Jan 31, 2019

MathQuill after typing \text a < b:
screen shot 2019-01-30 at 7 45 59 pm
This is a SS of a live MathQuill with the top result being .latex(), the third is .text(), and the last two are filtered through a couple of post-processing scripts (that obviously are not prepared for \text)...

@dpvc
Copy link
Member

dpvc commented Jan 31, 2019

Your example shows the LaTeX version to be \text{a < b}, which will work in MathJax because it is not real LaTeX (and apparently in MathQuill's output as well), but if you used that in WeBWorK for hardcopy output, it would not display properly. But nothing from this will be used in hardcopy, so I guess that is OK.

@mgage
Copy link
Sponsor Member

mgage commented Feb 1, 2019

@dpvc -- could you look at these latest commits from dev-mathquill ? The last one changes 150 files. It seems to me that it might have been based off master somewhere, but I haven't been able to figure it out.

@mgage mgage mentioned this pull request Feb 1, 2019
@mgage
Copy link
Sponsor Member

mgage commented Feb 1, 2019

@dpvc Davide. I may have figured this out. I cherry picked the relevant commit from Andrew's work and then reconciled a few files. This seems cleaner. See PR #921

@dpvc
Copy link
Member

dpvc commented Feb 1, 2019

@mgage, merging develop into a branch that originated from master is not the solution to the issue. You do have to move the commits onto a new branch that originates from develop and remove the old branch; there is no way to remediate the original branch.

The new develop-based branch can have the commits cherry-picked, as you have done, or (in some cases) rebased from the original branch. In this case, since there were only two commits on the branch, it is easy to cherry-pick them. But rebasing could also have worked. Something like

git rebase --onto new-branch 84cf8e6 3963ae6

where 84cf8e6 is the commit just before the first one you want to move (in this case, the branch point from the master branch) and 3963ae6 is the last commit you want to move (in this case, the one just before he served in develop). If there are conflicts along the way, the rebase will stop to let you resolve them, and commit the fixes, then you can continue the rebase (if I recall correctly).

In any case, your branch is good, and should supersede this one.

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.

None yet

6 participants