Skip to content

FITB schema items #2980

Description

@rbeezer

For reaction from @dbrianwalton. If you provide an organized response (keep numbering, etc) I can probably have Claude read it with good effect. Thanks.

Activity

  1. rbeezer commented on Jun 26, 2026

    @rbeezer
    CollaboratorAuthor

    I'm bringing the RELAX-NG schema (schema/pretext.xml) up to date with the dynamic fill-in (FITB) exercises as authored in the sample article, and I'd like your guidance on the intended model before encoding it.

    What already validates. The evaluation → evaluate → test → numcmp/strcmp/jscmp/mathcmp style is already in the schema, and the sample's fill-ins using it validate cleanly. (I also fixed an orphaned FillIn pattern — the dev @mode/@answer/@ansobj/@name/@width extension had never been wired to the inline fillin; inline interactive blanks now validate.)

    What the schema does not yet model (used in the sample's "Dynamic Exercises"):

    • <setup> (with @seed): computed-value definitions — <formula><eval obj="…"/></formula>, <variable name="…">…</variable>, and an older <var><condition string="…"|number="…"><feedback/></condition></var>.
    • <eval obj="…"/>: inline references to setup objects, appearing inside <p>, <m>, <md>, <formula>, <variable>.
    • <evaluation> computed style: directly holds eval/formula/variable/feedback (rather than evaluate+).

    Questions:

    1. Is the setup/eval/formula/variable computed style the current, canonical authoring? Does it coexist with evaluate/test, or supersede it?
    2. What is the full content model of <setup> — which children/attributes (formula, variable, var, condition, randomization, …)?
    3. Where should <eval obj=> be allowed inline — any math/text (m/md/p), or scoped to dynamic-exercise contexts? (This has the broadest reach into core content models, so I want the scope right.)
    4. In the computed style, what exactly does <evaluation> contain (eval/formula/variable/feedback)?
    5. Is the old-style <var>/<condition> deprecated — should the sample drop it — or should the schema keep admitting it for backward compatibility?
    6. Are de-object/de-number/de-evaluate/de-random/de-expression authored forms, or only compiled (assembly-time) forms? (The schema should validate authored source, not compiled output.)

    Once these are settled, the schema changes are mechanical — happy to draft the RELAX-NG once the model is confirmed.

    Claude Opus 4.8, acting as a coding assistant for Rob Beezer

  2. dbrianwalton commented on Jul 15, 2026

    @dbrianwalton
    Contributor

    Answers to questions to the best of my knowledge. I did have Claude help me look for side cases that I hadn't thought to include and believe it is all present.

    1. The older <var><condition>...<feedback/></condition></var> only persists because of old RST coded books. Those really are replaced by the evaluation -> evaluate -> test/feedback model. That is, the RST definition of FITB questions used setup to define evaluation conditions and feedback and did not actually setup anything randomized about the question. The current approach uses the <setup> block to setup the problem and the <evaluation> block to define evaluation of answers.

    2. Here is the potential structure of <setup>. * setup
      - attribute seed (text) is optional, but a warning is generated if missing because any actual randomization would be unpredictable without the seed provided — there are other non-randomizing aspects of setup that may also occur.
      - children elements:
      -- de-object (these are defined sequentially and can refer to earlier named objects)
      -- setupScript (optional, raw JS executed after the objects in de-object* are defined)
      -- postRenderScript (optional, raw JS that is in a callback function called after the exercise HTML is injected into the page)

      • de-object (child of setup)
        • attribute name (text), required
        • attribute context (text: "number" or "formula" are only options right now)
        • child element (must be only one): de-random (create random number), de-number (any other number), de-expression (formula or expression), de-evaluate (evaluated version of a formula)
      • de-random (child of de-object)
        • attribute distribution (text: "discrete" is the only supported version currently but can be expanded in future for others)
        • attributes min and max (values should be numbers)
        • attribute by (value should be number) — optional, using default of 1 if not provided
        • attribute nonzero (values: "yes" or omitted, implying false)
        • there should be no children.
      • de-number (child of de-object, intended to be for de-object[@context="number"])
        • should contain text that parses to a formula that represents a constant number (no free variables)
      • de-expression (child of de-object, intended to be for de-object[@context="formula"])
        • attribute reduce (text: "yes" or omitted, implying false)
        • attribute mode (text: "formula" (default if missing) or "substitution" or "derivative")
        • children depend on value of @mode.
          -- de-expression[not(@mode) or @mode="formula"] should have text child that will be parsed as a formula
          -- de-expression[@mode="substitution"] should have children: <formula/><variable/>
          -- de-expression[@mode="derivative"] should have children: <formula/><variable/>
      • de-evaluate (child of de-object, intended to create context="number",)
        • attribute reduce (text: "yes" or omitted, implying false) — used to simplify numerical values.
        • children are the pair <formula/><variable/>
      • formula (child of de-expression[@mode="substitution"] or de-expression[@mode="derivative"] or de-evaluate)
        • single child chosen from de-expression | de-evaluate | eval (de-random and de-number are technically possible but have not practical reason to use them unless you want a randomized value or formula not previously defined and don't intend to save it). The purpose of this is that we are going to reference some other formula (usually pre-defined) in order to create a new derived formula.
      • variable (child of de-expression[@mode="substitution"] or de-expression[@mode="derivative"] or de-evaluate)
        • attribute name (text)
        • when child of de-expression[@mode="derivative"] there are no children elements parsed; when child of de-expression[@mode="substitution"] or de-evaluate, there will be a child or plain text content as follows:
          -- eval | de-number | de-expression — a future enhancement should probably add de-evaluate as an option since no reason to exclude that option, but not currently allowed.
          -- plain text is currently parsed raw but that is probably an error to allow this as it will only work if the text represents a valid javascript expression. (Do NOT include this in the valid schema)
      • eval (child of variable, but can also appear outside of — see answer to Q3)
        • attribute obj (text representing the stored name of an object)

    Note: the potential children of de-object can also be created inside of mathcmp tests in the evaluation block. This makes it possible to create formulas and values based on the users submitted response. I doubt anything specifically blocks de-random, but an author really shouldn't do that.

    1. <eval obj="..."> as an object that will display for FITB questions can technically appear anywhere within statement, solution, and feedback (inside evaluation/evaluate/test). If it appears inside math-mode, it is meant to use the TeX representation of the object. Otherwise it will be a raw toString representation.

    2. The <evaluation> block has one or more evaluate children elements. I think you already have this.

      • evaluate[@all="yes"] provides a test for correctness for ALL fillin elements. This is optional and only applies if there are multiple answer blanks.
      • evaluate elements will have an optional feedback element and a test element from numcmp | strcmp | jscmp | mathcmp | logic. Only a single numcmp or strcmp should be present, but multiple entries of jscmp, mathcmp, and logic use an implied "AND" logic that all must return true to be a match.
      • test elements have an optional correct="yes" attribute, and there should only be one of these, which is used to determine if a submitted response is correct. If this is missing, the provided answer or answer object is compared by default.
      • mathcmp is maybe the only item that might require additional comment.
        • If mathcmp[@use-answer="yes"] then there are no children (submitted compared to provided answer)
        • If mathcmp[@obj], then there are no children (submitted compared to named object)
        • If mathcmp has one child, then submitted is compared to the child object
        • If mathcmp has two children, then the two children define objects and they are compared with each other.
        • Possible children are any of the de-object children defining structures: de-number, de-expression, de-evaluate, and eval, using the same schema restrictions as noted during setup.
    3. This feels above my pay-grade. I think that we should say it is deprecated and drop the example moving forward and not provide new authors with the existing examples. I don't think there is a cost to retaining the supporting code.

    4. They are all authored forms.

  3. rbeezer commented on Jul 15, 2026

    @rbeezer
    CollaboratorAuthor

    Implemented in #3041 — the development schema now carries the full model described above, and the sample article's dynamic exercises validate against it. A few refinements surfaced during the encoding, numbered for easy reply:

    1. de-number/@reduce. The sample article uses it (<de-number reduce="yes">y0/base_yint</de-number> for the object A), but the description above lists @reduce only on de-expression and de-evaluate. The schema currently admits it on de-number, with a comment noting the discrepancy. Intended, or should the sample compute that differently?
    2. feedback placement. Answer 4 describes an optional feedback on evaluate, but all observed usage (sample article included) places feedback inside test, after the comparisons. The schema currently admits both positions. Which is canonical — or are both supported deliberately?
    3. formula children. Encoded as de-expression | de-evaluate | eval only, excluding the "technically possible but no practical reason" de-random/de-number. Confirm that tightening is welcome.
    4. de-object/@context. Encoded as required (the description doesn't mark it optional, and the sample always supplies it). Confirm.
    5. Sample drift, fixed at the source: three de-expression elements carried a stray @context (it belongs on de-object), and one variable held a bare-text value (0), now wrapped as <de-number>0</de-number> per the "do NOT include plain text" ruling.

    The old-style var/condition form is not modeled, per answer 5 and the schema's deprecated-means-absent policy; retiring the sample's legacy examples will be addressed separately.

    Claude Fable 5, acting as a coding assistant for Rob Beezer

  4. dbrianwalton commented on Jul 16, 2026

    @dbrianwalton
    Contributor
    1. Add @reduce to be available for de-number. I will add the XSL to account for it. I think it should be present.
    2. The XSL does not care about ordering. It should not matter.
    3. Tightening is acceptable. No need for the others.
    4. Confirmed.
    5. This was actually a misremembering on my part in the last response. I remember now what the purpose of the bare-text was — it was not about the PreTeXt XSL but about the underlying javascript library for the math expressions. Evaluation of variables can be either de-object elements or pure javascript numerical values. So the bare-text 0 would have been acceptable. However, allowing bare javascript increases the likelihood of creating broken JSON, so this is another XSL that I will want to modify — allow bare-text but it will be interpreted as an implicit <de-number>. (Can the schema allow bare-text? The original sample would work fine, but I will want to consider this an error needing to be fixed)
  5. dbrianwalton commented on Jul 16, 2026

    @dbrianwalton
    Contributor

    I realized I need to add a clarification to the schema. When there exists evaluation/evaluate[@all="yes"], there can only be one child test element and it implicitly is interpreted as correct. Having more than one test child would create an issue. I will add this to my list of clean-up items to resolve.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions