Skip to content

Breaking: Version 2 improvements (fixes #29)#30

Open
oliverfoster wants to merge 23 commits intomasterfrom
issue/29
Open

Breaking: Version 2 improvements (fixes #29)#30
oliverfoster wants to merge 23 commits intomasterfrom
issue/29

Conversation

@oliverfoster
Copy link
Copy Markdown
Member

@oliverfoster oliverfoster commented Jul 24, 2025

fixes #29

Fix

  • Reverted changes to broken intersection queries

Update

  • isAvailableInHierarchy to account for detached models
  • sets sorted by .order
  • removed the word raw throughout and changed for more accurate names, availableComponents etc
  • removed the word sub throughout, from subset, and changed for more accurate names, set, getSet.., etc
  • generally refactor code so that logic is more distinct and easier to read
  • split scoringset into interactionset, lifecycleset and scoringset
  • adaptmodelset extends interactionset,
  • lifecycleset extends interactionset
  • isolate the compatibility layer
  • automatically assign set ids
  • formalise State and Objective apis
  • formalise lifecycle phases and triggers for init, restore, start, reset, restart, visit, leave and update, fully integrating adapt-contrib-modifiers
  • add order for lifecycle elements so that adapt-contrib-banking, adapt-contrib-randomise and adapt-contrib-scoringAssessment can execute in order, ordering sets appropriately
  • separate utility functions into appropriate files
  • add jsdocs throughout

New

  • added multiple functions to account for detached models
  • added TotalSets to replace the set behaviour on the main Adapt.scoring API
  • document INTERSECTION_QUERY.md
  • document LIFECYCLE.md

Breaking

  • Almost every function has been renamed or moved

@cahirodoherty-learningpool
Copy link
Copy Markdown
Contributor

Conflicts need resolved on this

@joe-replin
Copy link
Copy Markdown

Moved to resolve conflicts and brought in the logging improvements from #26

Corrected wording for clarity in IntersectionSet section.
@oliverfoster
Copy link
Copy Markdown
Member Author

oliverfoster commented Mar 17, 2026

Joe's commits need reverting. The modifiers stuff has been included in the code already and doesn't need a secondary interface. That commit is a misunderstanding of the intent of version 2.
Update: terminology mixup. Joe has reused the word "modifiers" which is an older concept from Dan for a different design part. That name probably needs changing, the functions simplified and some more function comments adding.

a1fb354

…oved event trigger for 'scoring:reset' to `Lifecycle` for consistency.

Questionable whether a public method to update scoring is required. No longer used directly in scoring plugins as was the case with v1.
… `IntersectionSet` rather than `ScoringSet` as this is only required for intersection queries.
js/ScoringSet.js Outdated
* @param {Backbone.Model} model
* @returns {number}
*/
getMinScoreByModel(model) {
Copy link
Copy Markdown
Member Author

@oliverfoster oliverfoster Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these functions, and those added by Joe, aren't used anywhere other than the logging code, can we move them out of the main ScoringSet API and into a helpers file? Or fold them into the places that they're called from? I don't see a need for multiple small functions when a single larger one would work.

This is almost 10 new main API functions, just for printing logs.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will look into offloading the logic into another class, similar to how objectives are handled, but the different methods were setup to allow subclass extensibility, so we can easily override just the bits that differ between sets.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any use case for these beyond the logging stuff. Are you intending that the logging be overridden per set?

js/ScoringSet.js Outdated
return this.models.some(model => model.get('_isVisited'));
get isPartlyCorrect() {
if (!this.isSubmitted) return null;
return (this.correctness < this.maxCorrectness);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returns true if correctness is 0.

js/ScoringSet.js Outdated
return this.isStarted && !this.isComplete;
get isIncorrect() {
if (!this.isSubmitted) return null;
return (!this.correctness && this.maxCorrectness);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returns the maxCorrectness value if correctness equals 0.

@danielghost danielghost moved this from Needs Reviewing to Assigned in adapt_framework: The TODO Board Mar 20, 2026
js/Lifecycle.js Outdated
},
// restart calls set.onStart when any intersecting model or set is reset
async restart(set) {
await set.onStart?.();
Copy link
Copy Markdown
Contributor

@danielghost danielghost Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this call set.onRestart?.() instead to distinguish between a first attempt and a restart attempt? An alternative would be to have a flag akin to how wasRestored is used, but two different methods seems like a cleaner option. Is there a specific reason why this wouldn't work or cause problems?

See https://github.com/adaptlearning/adapt-contrib-scoring/pull/30/changes#r3024196814 for some context.

In cases where a set may require start and restart to be the same, onRestart called also call onStart within the set. Even in the current AssessmentSet.onStart`, some of these methods probably only need to happen after a reset.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any difference when I was rewriting everything. Just that reset/restart is usually exactly the same behaviour as start. Start is always the beginning of the lifecycle and reset, although seemingly at the end, is always the beginning of the lifecycle. I removed the on restart phase to clarify that it is effectively starting again. If you need to keep state between attempts then that state should be kept and managed on the set and not in the lifecycle stuff, where it's just confusing. Reset is not a finished or complete.

…ds in `ScoringSet` to query its models rather rather than the single parent model (which isn't always populated in a set). Fixed issues when evaluating correctness.
…rt attempt. Marked lifecycle callback hooks as protected methods, as calling these externally defeats the benefits of the LifecycleRenderer.
…ntrib-scoringAssessment#17. Resolved reset issues as the objective needs to wait until the set has been reset before updating the score and status - adjusted methods and logic accordingly so score and status can be handled separately by the sets lifecycle methods.
…class to keep this logic separate from the `ScoringSet`.
* Intentionally empty to prevent super Class event triggers
* @override
*/
onCompleted() {}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need AdaptModelSet to be firing the scoring event triggers? Anything listening to events such as 'scoring:set:complete' will be triggered every time one of these models is completed. Are we ever likely to use something like https://github.com/adaptlearning/adapt-contrib-scoringResults for these type of sets?

Leaving them in means we have a chatty scoring event system, which will probably not be utilised for these models. As these sets are only really needed to allow the queries and intersections to work, I would probably prevent them from firing the events to match v1, but happy to leave them in if it offers us more flexibility without compromising performance.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think leave to them in; it's a valid event to fire as a set is being completed.

_updateQueue(model) {
this._queuedChanges.push(model);
this._debouncedUpdate();
getSetById(id) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer exported. It can obviously be used via Adapt.scoring.getSetById, but should we make all of these types of methods utility functions that can be imported by plugins as required?

Currently we have a mixture of those that can only be referenced via Adapt.scoring and others which can be both imported individually or used via the scoring object. Do we need both, or just use imports?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They should be exported, yes.

Adapt.scoring references are easy to grab from the console. This can be handy for debugging.

/** @override */
onCompleted() {
if (this.isIntersectedSet) return;
Adapt.trigger('scoring:complete', Adapt.scoring);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use this as an argument rather than Adapt.scoring, to provide the correct context to listeners such as https://github.com/adaptlearning/adapt-contrib-core/blob/2c6ef07f8bfe5fe4dd317e4d0dad899cbd1f86e1/js/tracking.js#L93.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

async restore() {
const sets = getAllSets();
await this.renderer.render.restore(sets);
Adapt.trigger('scoring:restored', this.scoring);
Copy link
Copy Markdown
Contributor

@danielghost danielghost Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per https://github.com/adaptlearning/adapt-contrib-scoring/pull/30/changes#r3079115424, the event triggers on this file should include the TotalSets context unless we change the way the listeners currently work.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

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

Projects

Development

Successfully merging this pull request may close these issues.

Version 2

4 participants