Open sangwinc opened 7 years ago
We probably need to add in a positive integer option (between 2 and 36 to respect Maxima's restrictions) in here https://github.com/maths/moodle-qtype_stack/blob/master/stack/options.class.php#L30 Then we can carry that contextual information around and use that option elsewhere.
In particular, the number base would probably need to be an additional argument to the casstrting constructor, so that we can fine-tune any regex patterns looking for missing stars. Currently the problem with base 16, for example is that 1A gets rejected as 1*A just about anywhere by this code: https://github.com/maths/moodle-qtype_stack/blob/master/stack/cas/casstring.class.php#L991
There are currently about 394 "new stack_cas_casstring" commands, so this will be a major change.
Some complexities of the use cases that need to be borne in mind for these features:
Convert the following denary number: {# (obase:10,denum) #} to binary and hexdecimal
however, this is very hit and miss - the scope of the setting change is poorly defined.
1) Indeed, setting the base for the whole question using a single question level option would be rather odd and excessive. Why not just have the base as an input specific option? The inputs would naturally then convert whatever is given to the common base of the question (let that always be as it as been base 10) and whine about cases where someone tries to input "2" instead of "10" to an input requiring binary values.
2, 3) Personally I do not believe it would make sense to set the base we operate in, we should instead tune input and output when needed, let the tool do its thing in whatever base it wishes and it does it in binary anyway, thus we could simply use all the traditional tools just like we used before. If the question author needs to input values in binary instead of base-10 they can just wrap those special cases in suitable wrapper functions. Output again requires tools like the sig-figs outputs...
4) For students or for authors?
Naturally, I know nothing of the original need that brought bases to STACK but I believe bases are just part of the IO layer and should stay there. Any actions requiring acting on binary representation on i.e. "bit twiddling" should stay behind the curtain and can be done there with slightly more complex steps maybe requiring line by line changes of ibase
. obase
should happen inside dispsf
style wrappers.
Naturally, I understand that Chris may wish to switch the whole question to same base to deal with the caching of CAS-sessions in somewhat sensible way and if so that will need to be rethought... If I understand correctly any inline changes to ibase/obase
are opaque to the caching and cause havoc there.
This should cover most of the output issues (including padding) but for input the inputs need to be aware and validate bases.
Chris,
I do believe that CAS session caching is indeed a problem, but I think that is only a problem if you allow obase
to be tuned in the cached context. In-line (in keyval that is) ibase
is not a problem for caching as long as the obase
stays the same and we move ibase
to be the last item in the cache. it (ibase
) needs to be passed on to the next context but may not be present when parsing the native obase
(base-10) values when reading the cache in.
Also if we are to mix multiple bases inside the question logic we will need something a bit simpler than dealing with ibase
, consider and play with maxima with the following situation:
ibase:3;
ibase:10;
ibase
within the question authoring context.Sorry about constant comments, but I for some reason dislike ibase
so much that I can't stop. Try this:
ibase:16;
deadbeef + 1;
And you should see that Maxima parser can't deal with numbers it can't distinguish from variables. In addition ibase
cannot be applied on a statement by statement basis as it works on the wrong phase of the parser. Basically, it just does not work for bases over 10 and even then only if you only have one base and don't want to switch bases.
What I would suggest is that instead of ibase
we would have a function that is given a string and a base and it parses that with some eval-string function (probably at lisp level or in a suitable block) i.e. inbase(16,"deadbeef") + 1 = 3735928560
naturally the function would safely fail if it sees any parenthesis in the string or security related variable-names. Key benefit here being that we can go around the Maxima parser issue and we can keep the authoring logic in a single base
0deadbeef + 1
does work but can you assume the students to know that.
Thank you Matti, As ever your comments are very helpful here. It is good to have these discussions before I start to change things....
More things to note, although in base 36 the number 1751504350 (that is in base 10) might be a problem for our validation we should be secure as conversion from that number to the symbol would require obase
trickery combined with holes plugged in the previous security scare (good that we caught that as I have a feeling that the people playing with these bases might be the people that would have had the minds to use that hole). However, whatever validation the Different Radix Input field would have it can't apply the same validation we currently use as higher bases may contain our forbidden keywords in the values.
To keep the input fields validation manageable we should probably decide that it only allows atomic values to be imputed newer any expressions or structures. (i.e. my earlier comment about parenthesis) We should also decide which radii we support as once we pass the alphabets things get difficult and require more robust validation. Probably people will also require Base64 but with that we will need to start validating paddings and as it uses different logic with its symbols it will need to be handled separately. (Base64 is probably best handled with the string input field, although direct validation would not be present then)
While I do not currently see a way to abuse ibase/obase
to bypass our security validation I have a bad feeling and do believe that we should not use those directly to manage input of values nor output.
Thanks Matti,
I also have a "bad feeling" about ibase/obase. I think we need a more careful approach to number bases here...
Chris
I am reasonably ok with the idea of qualifying base-10+ numbers with a prefixing zero, in the same way as stack implements it. I can always add a note to the question to clarify that. For wider use, you will find that programming courses et al will want a variety of possible prefixing and suffixing standards that relate to specific programming languages, e.g. 0xDEADBEEF in C++ and Java. I have tried using stackintfmt in a question to see if I can get leading zero output. It works in the question text, but unlike obase, it does not work in the model answers. Has someone else got a working solution for this? I am asking the student to convert a base 10 number to a binary number.
How often do you expect to ask students to give a non-decimal answer that isn't just a single number?
As to teachers answers with stackintfmt
I guess that just does not work and waits for suitable functions like the ones used when dealing with units or significant figures.
Not just one number type of an answer, that I would consider would be something answering questions where you need to present an expression where a variable unknown mask is present in the response maybe deadbeef | MASK
although in that case how would we even know if the MASK
is a variable and not just another number? But in any case if we can just say that we do not need more than one atomic number this should be easy if not things get complex fast.
How often do you expect to ask students to give a non-decimal answer that isn't just a single number?
There are cases for showing working out which might involve multiple numbers, but that could be handled various ways.
Just to say I have started coding a solution to this. I will report back when I have gotten a little further. I am aiming for an inert function (like displaydp) that will also affect the input base, number of input digits, model answer and 'typed as'. I am going to include a parameter in the function to control the number parsing for base-11+ so that you can opt either for start-a-number-with-a-zero or letters-always-count-as-numbers.
Thanks for picking this up. If you put your code into a branch (e.g. iss317) I'm happy to look at it. Don't hesitate to email off list if you need help, or we can Skype.
Just to let you know I'm working on a new "numerical" input type. Adding in a option "base(n)" to check that only digits 0,..,(n-1) and possibly "." appear in the student's expression would be a natural place for validation I think.
Has your code addressed validation yet?
I am struggling with input just now. I am also trying to get a debugging environment installed so I can follow where the php code is going - I thought I saw a how to somewhere but now can't find it. Yes I think the numerical type is an excellent idea. It needs signs too and a minimum figures before and after point check.My code handles various prefixes and suffices too plain, C,Basic, Maxima and subscript suffix - these should be include for maximum usefulness.
On 10 December 2017 17:09:47 GMT+00:00, Chris Sangwin notifications@github.com wrote:
Just to let you know I'm working on a new "numerical" input type. Adding in a option "base(n)" to check that only digits 0,..,(n-1) and possibly "." appear in the student's expression would be a natural place for validation I think.
Has your code addressed validation yet?
-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/maths/moodle-qtype_stack/issues/317#issuecomment-350562835
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
P.S. having two brainstorms on unrelated fronts:
On 10 December 2017 17:09:47 GMT+00:00, Chris Sangwin notifications@github.com wrote:
Just to let you know I'm working on a new "numerical" input type. Adding in a option "base(n)" to check that only digits 0,..,(n-1) and possibly "." appear in the student's expression would be a natural place for validation I think.
Has your code addressed validation yet?
-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/maths/moodle-qtype_stack/issues/317#issuecomment-350562835
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
PPS. I have pushed a WIP progress commit to my repo so you can 'steal' some of my functions: e.g.: https://github.com/sgparry/moodle-qtype_stack/blob/iss317/stack/maxima/basen.lisp https://github.com/sgparry/moodle-qtype_stack/commit/ba5e1d47ef200601ff26f9d2cd24b7e6dfd73752 There are significant additions to a number of lisp and files. Hope that helps.
About P.S. 1) Working JVM may not be that simple thing to ask for but once you ask for that the step to full on MaximaPool is not that big. MaximaPool would happily run ABCL processes and bundling the Tomcat alongside ABCL Maxima and MaximaPool would be a trivial next step.
2) Yes please! Only thing where that old printing markers and parsing style processing we have works well is the timeout handling where one can get some values parsed from the output stream, but as we do not really have any use for those values... Oh how I would like to able to copy the cache tables contents to JSON columns in my database and do queries directly on it..
I'm sorry you are struggling with validation. The complexity of this has grown over the years, and I think the whole inputs folder is probably due to be refactored.
I agree wholeheartedly, that our own distro of Maxima would be great. We could then know what people were using, and check new version of Maxima work before they are in the wild! A cut-down version might be faster, and have fewer libraries we don't want. Etc... It has been on my mind for a while. If you have suggestions of a mechanism this would be great.
On 2. the connection with Maxima is very old indeed. It was necessarily some of the first code I wrote! While it has served us well for years I'm not "fond" of it. I'm sure a more professional API with Maxima would be very sensible. This is also probably due to be re-factored.
Just having the "API" push a JSON string to some singular function on the Maxima side would be nice and that function would then output a JSON structure that could be parsed for key/varname based errors/values. The important thing would be that we would only cache the JSON so that there would be no need to parse the other output the process gives. Maybe even output just the values at the end of the evaluation so that we could stop that iterate in the reverse order to fetch the last value loop from spinning around.
One problem is that currently there exists no map type objects in Maxima (that I know of) to represent named properties in JSON and without such certain things are a bit difficult, but not impossible. Without such an object it is quite difficult to build a generic JSON parser inside Maxima, one has to go back to LISP to do that (and luckily it has already been done). Although we do not really need maps nor even parsers as we can simply use lists of strings to push stuff in and construct the response JSON as a string any way we want. We might also want to write the JSON from Maxima to a file (like plots) to avoid potential issues related to line lengths...
The bigger problem is that most of STACK-Maxima code assumes direct output and tends to just print out errors/feedback directly, which would be a problem if we want to collect those details into a structured output i.e. how do we collect the values of these print calls in algebraic_equivalence... Plenty of things need to be fixed to actually use errors and errcatch to push those kinds of an details to the correct places.
Has anybody used Stack with the Maxima windows build since prehistory? As far as I can see stack is utterly non-functional with 5.39.0.
Not for a while.
All our servers are Debian based. I used to develop on Windows (e.g. home and laptop machines) but this year I switched to virtual box for development.
How important is a Windows build?
Chris
I have it working (no gnuplot just now) - but only after arm twisting. Could not get the non-optimised working at all but got the optimised working by manually optimising and setting the config to "Unix optimised". I will post another issue and fix it properly at some point soon.
Thanks, I appreciate you making the effort here. My laptop is soaked in coffee (and with the very helpful university support people, sans hard drive for data recovery) and if I get this back I'll have a Windows machine again to test on! I will help sort this out. I can't remember ever using the optimised version on Windows because I only ever used it for demo/dev. Are you planning to use this in anger? Chris
I have the problem that my school laptop is Redmond only. I use Linux at home when I can. I have added a Windows Optimised option to my local code-base which helps, but the kicker seems to be that recent Maxima builds use a more intelligent batch file to start from - so copying the batch to moodledata and running it no longer works. I am not too sure of what we need to redirect and why. Gnuplot does not work at all yet. I have enough to develop with for now, but I do feel in the longer term we need to support twindows only victims too. The maxima windows build seems to have progressed a fair bit recently.
Finally getting back to this after nearly a year :-(
Good to hear from you again. We are making good, if slow, progress. Help would be much appreciated. I'd like to get this all working, but I'd like to keep the install process as simple as possible. Since we last communicated we've started active work on an "API" (see api_v4 branch). So that is yet another install scenario we'd like to support. This will also help with the Maxima pool as well.
I am probably being pretty dense, but I cannot see anything explaining what the purpose / rationale of the API is. Can you point me at some docs or a discussion thread? Thanks. I will try to help where I can but I have to be wary of getting too deep into install enhancements; I got #331 going as what was supposed to be a no-brainer quick contribution that helped me when I was working to get #317 done, but ended up stuck so deeply in it I never got #317 complete, and that feature is mission critical for me. I have barely scratched the boolean / digital logic yet either, which I need.
Ahh this... Some things have happened since this was last discussed the primary thing being that a parser for Maxima commands is coming "soon" to the validation phase of casstrings. Essentially, it will modify many things and might make it possible to deal with the 1A => 1*A
bit more selectively we could even push the base as a parameter to the parsing so that in base 11 this would happen [1A,1B] => [1A, 1*B]
. More importantly the parsing logic could be used to rewrite values before they reach Maxima i.e. we could turn whatever is inputted to base-10 integers outside Maxima thus avoiding having to deal with ibase
. So that might be an option, but currently the parser does not identify non base-10 numbers so some work would need to be done, but should not be difficult to validate that the numbers are in the wanted base outside Maxima conversion of large numbers might however be a bit cumbersome.
Numbers would still need to start with numerical digits, so prefixing with zero if the first "digit" is not a number is pretty much required from the side of the Maxima parser.
The code that I have already written but not pushed yet copes with a variety of input prefixes including non-numeric. It also handles suffix format using underscore. It has to do all this because in Comp Sci and programming courses base 2 8 and 16 formats vary enormously depending on the target language students are taught, including 'bare' hex which is the troublesome one. IIRC in my modifications the teacher wraps the numbers in answer with a function call to dictate the expected input base and format and the pre-parser in STACK uses regexps to wrap the numbers in the user's input with quotes and reserved maxima function calls in a similar fashion to how strings and sigfigs are handled. The actual conversions are done within the functions using Maxima own functions once the prefix/suffix have been adjusted to Maxima norm. It works mostly - error handling was still flakey. I also needed some small mods to input matrices so I can use them for working out - I was still working on those.
On 8 November 2018 07:09:07 GMT+00:00, Matti Harjula notifications@github.com wrote:
Ahh this... Some things have happened since this was last discussed the primary thing being that a parser for Maxima commands is coming "soon" to the validation phase of casstrings. Essentially, it will modify many things and might make it possible to deal with the
1A => 1*A
bit more selectively we could even push the base as a parameter to the parsing so that in base 11 this would happen[1A,1B] => [1A, 1*B]
. More importantly the parsing logic could be used to rewrite values before they reach Maxima i.e. we could turn whatever is inputted to base-10 integers outside Maxima thus avoiding having to deal withibase
. So that might be an option, but currently the parser does not identify non base-10 numbers so some work would need to be done, but should not be difficult to validate that the numbers are in the wanted base outside Maxima conversion of large numbers might however be a bit cumbersome.Numbers would still need to start with numerical digits, so prefixing with zero if the first "digit" is not a number is pretty much required from the side of the Maxima parser.
-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/maths/moodle-qtype_stack/issues/317#issuecomment-436894717
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
Looking forward to seeing how you have done that, but based on what I can grok from that it would probably fit nicely into the new system as a new parsing-rule basically something that happens before the input goes to a real parser and validation. Those parsing rules essentially describe the old insert stars logic but could do something entirely different like rewrite number formats.
The new system is coming but unfortunately we have had some issues in finding time to finish it, basically, error messages have changed, unit tests are broken and we would need to test how many existing questions break due to it.
With a lot of sticky tape and chewing gum, as usual with Moodle PHP code. I have to merge latest master and trying and shake out any resulting bugs but as soon as I have done that I will push the code I have so you can take a peek.
On 8 November 2018 07:54:31 GMT+00:00, Matti Harjula notifications@github.com wrote:
Looking forward to seeing how you have done that, but based on what I can grok from that it would probably fit nicely into the new system as a new parsing-rule basically something that happens before the input goes to a real parser and validation. Those parsing rules essentially describe the old insert stars logic but could do something entirely different like rewrite number formats.
The new system is coming but unfortunately we have had some issues in finding time to finish it, basically, error messages have changed, unit tests are broken and we would need to test how many existing questions break due to it.
-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/maths/moodle-qtype_stack/issues/317#issuecomment-436904292
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
Thank you for all the commits related to number base support. I confess I'm away on holiday this week (walking in the mountains) without a dev machine to hand. I will pick this up when I'm back on Tuesday... Chris
Thank you very much indeed. I've started to review the code, and done a preliminary code tidy here: https://github.com/maths/moodle-qtype_stack/tree/sgparry-iss317
I'm going to run the unit tests over night, but I'd really like some examples of more tests for the number base work, and some documentation. Are you willing to carry on and help with this?
I am happy to help with the documentation - it might take me a week or two before I can spare the time but it's not a biggie. Test writing is something I have a bit of a blind spot for - IIRC I wrote some unit tests for the basic functions, but not much more than that. I may need some help with the higher level tests.
On 21 April 2019 18:02:05 BST, Chris Sangwin notifications@github.com wrote:
Thank you very much indeed. I've started to review the code, and done a preliminary code tidy here: https://github.com/maths/moodle-qtype_stack/tree/sgparry-iss317
I'm going to run the unit tests over night, but I'd really like some examples of more tests for the number base work, and some documentation. Are you willing to carry on and help with this?
-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/maths/moodle-qtype_stack/issues/317#issuecomment-485266904
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
Thanks,
I've run the tests over night. (It takes ages on my home dev machine....) The only new error is in the new tests/basenoptions_test.php
1) stack_basen_options_test::test Error: Undefined class constant 'BASENMODE_CHOICE'
/var/www/moodle36/question/type/stack/tests/basenoptions_test.php:36 /var/www/moodle36/lib/phpunit/classes/advanced_testcase.php:80
So, your changes break nothing existing. Thanks! I'm keen to make sure we have plenty of tests, and docs, before we merge into master (otherwise there is a risk this never gets done!). I'm very happy to help with this. Once we have a couple of examples in place I'm sure you can add lots more very easily. Tim gave me a lot of help with PHP unit, and it isn't easy to get started, so I'll do the same if you are willing to help.
I've been writing my first "basen" question. It all looks very useful!
Of course, I'm also trying to break it. This screen shot shows an issue we need to address.
I hope these are some useful stubs and pointers to places for docs and some tests. https://github.com/maths/moodle-qtype_stack/commit/f26df298fb620f09b0596d8657d7795fc80ac453
Thank you so much for adding in the Maxima rtest files. I don't think we need to put too much duplication of all this into the PHP code.
Yes - I think that testvissue was a last minute issue I fixed - might be worth double checking if you have the latest push... if you have I might have overlooked the change when pushing.
On 22 April 2019 08:33:59 BST, Chris Sangwin notifications@github.com wrote:
I've been writing my first "basen" question. It all looks very useful!
Of course, I'm also trying to break it. This screen shot shows an issue we need to address.
-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/maths/moodle-qtype_stack/issues/317#issuecomment-485351573
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
It's a tricky one this - I am not even sure what should happen in this case. Obviously it needs to reject the input, which it does, but who knows what should actually sppear in the "interpreted as" or the hint. You cannot just assume 2 should be treated as an incorrect part of the number - in Base N any letter is also a potential digit in another base.
On 22 April 2019 08:33:59 BST, Chris Sangwin notifications@github.com wrote:
I've been writing my first "basen" question. It all looks very useful!
Of course, I'm also trying to break it. This screen shot shows an issue we need to address.
-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/maths/moodle-qtype_stack/issues/317#issuecomment-485351573
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
Could we just assume that the base and the format used is defined input by input basis and in that screenshot case the base being defined as 2 the existence of 2 in any integer token would be considered invalid, with suitable warning message? As 2 could not exist anywhere else than maybe something likeatan2()
which is something the insert stars logic already knows of in the iss324 branch things should be safe. Well the greedy mode will be a different issue...
In the suffix mode naturally the rules would be defined token by token basis.
I've started from https://github.com/sgparry/moodle-qtype_stack/commit/7db2bc9b9b7d9fb4b5545f70ffad6a51be60b38b which is your latest commit, so I think you may have overlooked the change in BASENMODE_CHOICE.
Currently all this is in the "algebraic" input type rather than the "numerical". This means we can have, e.g. polynomials with coefficients written in base n (I tried your code Stephen, and my modest tests with these objects work, which I think is a testament to your design here!). Do we need such things? I don't know, but they make perfect mathematical sense and someone must have thought about them....
I have two proposals.
(1) Default: we reject as "invalid" any wrong digits with a very helpful error message such as "The digit x should not appear in a base n number".
(2) In the numerical input type, where we assume there is only a number, we have an option to accept wrong digits as "valid", so they can later be marked as incorrect. This will allow a teacher to test if a student knows which digits to use as part of the assessment (rather than validity).
This is exactly why we need the validity/correctness split in the design!
I'm suggesting (2) is only on the numerical input type to avoid deciding if 10A is "two times A" (in base 2) or something in base >10.... In the numerical input type we know it is a number, so A can't be a variable.
The latest one from Chris brings the inputs into play, while the way you currently define the format and base through the teachers answer does work it might be prettier (both in code complexity and usage sense) if they were directly options of inputs. Although then we need an expansion of the inputs and logic for input options to be CAS statements as static options could not provide CAS based tuning like your teachers answer way does.
In any case Chris, do think carefully whether you want to do this before the iss324 branch parser is in play. It will change pretty much everything related to this and provide tools that suit to this quite well.
Polynomials with coefficients is truly one of the better examples of this in use and will make a sensible testcase.
The use of fixed input options is problematic as it then requires the same piece of information to be duplicated in at least two places and does not allow the format to adapt to the question if needed. Being to specify through the teacher answer is consistent with other similar cases such as displaydp.
On 23 April 2019 10:13:46 BST, Matti Harjula notifications@github.com wrote:
The latest one from Chris brings the inputs into play, while the way you currently define the format and base through the teachers answer does work it might be prettier (both in code complexity and usage sense) if they were directly options of inputs. Although then we need an expansion of the inputs and logic for input options to be CAS statements as static options could not provide CAS based tuning like your teachers answer way does.
In any case Chris, do think carefully whether you want to do this before the iss324 branch parser is in play. It will change pretty much everything related to this and provide tools that suit to this quite well.
Polynomials with coefficients is truly one of the better examples of this in use and will make a sensible testcase.
-- You are receiving this because you commented. Reply to this email directly or view it on GitHub: https://github.com/maths/moodle-qtype_stack/issues/317#issuecomment-485719412
-- Sent from my Android device with K-9 Mail. Please excuse my brevity.
Indeed fixed options are a problem for this but it would be nice if we had a way of having options that can have CAS statements and those statements can reference the question variables thus "duplicating" via reference. But I guess full redefinition of the input subsystem is not going to happen soon, I do however have a vision for it which would include rethinking the options and more importantly the validation and initialisation logic. Chris can expect to see that vision soon enough in the form of a wall of text...
Maxima has good support for number bases through the "ibase" and "obase" command. So, we get an awful lot for free here. However, we need support for the base at the very top level in an "option" at the stack options level. This will ensure that all sessions use the same number base, including those sessions which implement the answer tests.
Adding in another question level option adds complexity and is non-reversible.
The recent commit b124349e8c3023f9b4ca63649f8c2aae64de04c7 ensures that ibase and obase don't always break things, but a lot more is needed here.