Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DeleteNodeService } from '../../services/deleteNodeService';
import { CopyNodesService } from '../../services/copyNodesService';
import { DeleteTranslationsService } from '../../services/deleteTranslationsService';
import { CopyTranslationsService } from '../../services/copyTranslationsService';
import { ConstraintService } from '../../services/constraintService';

@Component({
selector: 'project-authoring-step',
Expand All @@ -24,6 +25,7 @@ export class ProjectAuthoringStepComponent {
constructor(
private copyNodesService: CopyNodesService,
private copyTranslationsService: CopyTranslationsService,
private constraintService: ConstraintService,
private dataService: TeacherDataService,
private deleteNodeService: DeleteNodeService,
private deleteTranslationsService: DeleteTranslationsService,
Expand Down Expand Up @@ -66,26 +68,19 @@ export class ProjectAuthoringStepComponent {
}

protected nodeHasConstraint(nodeId: string): boolean {
return this.projectService.nodeHasConstraint(nodeId);
return this.getNumberOfConstraintsOnNode(nodeId) > 0;
}

protected getNumberOfConstraintsOnNode(nodeId: string): number {
return this.projectService.getConstraintsOnNode(nodeId).length;
return this.projectService.getNode(nodeId).getConstraints().length;
}

protected nodeHasRubric(nodeId: string): boolean {
return this.projectService.nodeHasRubric(nodeId);
}

protected getConstraintDescriptions(nodeId: string): string {
let constraintDescriptions = '';
const constraints = this.projectService.getConstraintsOnNode(nodeId);
for (let c = 0; c < constraints.length; c++) {
let constraint = constraints[c];
let description = this.projectService.getConstraintDescription(constraint);
constraintDescriptions += c + 1 + ' - ' + description + '\n';
}
return constraintDescriptions;
return this.constraintService.getConstraintDescriptions(nodeId);
}

protected constraintIconClicked(nodeId: string): void {
Expand Down
4 changes: 4 additions & 0 deletions src/assets/wise5/common/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,8 @@ export class Node {
componentContent.connectedComponents.length !== 0
);
}

getConstraints(): any[] {
return this.constraints;
}
}
179 changes: 179 additions & 0 deletions src/assets/wise5/services/constraintService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,183 @@ export class ConstraintService {
hasActiveConstraints(): boolean {
return this.activeConstraints.length > 0;
}

getConstraintDescriptions(nodeId: string): string {
let constraintDescriptions = '';
const constraints = this.projectService.getNode(nodeId).getConstraints();
for (let c = 0; c < constraints.length; c++) {
const constraint = constraints[c];
const description = this.getConstraintDescription(constraint);
constraintDescriptions += c + 1 + ' - ' + description + '\n';
}
return constraintDescriptions;
}

/**
* Get the human readable description of the constraint.
* @param constraint The constraint object.
* @returns A human readable text string that describes the constraint.
* example
* 'All steps after this one will not be visitable until the student completes
* "3.7 Revise Your Bowls Explanation"'
*/
private getConstraintDescription(constraint: any): string {
let message = '';
for (const singleRemovalCriteria of constraint.removalCriteria) {
if (message != '') {
// this constraint has multiple removal criteria
if (constraint.removalConditional === 'any') {
message += ' or ';
} else if (constraint.removalConditional === 'all') {
message += ' and ';
}
}
message += this.getCriteriaMessage(singleRemovalCriteria);
}
return this.getActionMessage(constraint.action) + message;
}

/**
* Get the message that describes how to satisfy the criteria
* TODO: check if the criteria is satisfied
* @param criteria the criteria object that needs to be satisfied
* @returns the message to display to the student that describes how to
* satisfy the criteria
*/
getCriteriaMessage(criteria: any): string {
let message = '';
const name = criteria.name;
const params = criteria.params;

if (name === 'isCompleted') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
message += $localize`Complete <b>${nodeTitle}</b>`;
}
} else if (name === 'isVisited') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
message += $localize`Visit <b>${nodeTitle}</b>`;
}
} else if (name === 'isCorrect') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
message += $localize`Correctly answer <b>${nodeTitle}</b>`;
}
} else if (name === 'score') {
const nodeId = params.nodeId;
let nodeTitle = '';
let scoresString = '';

if (nodeId != null) {
nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
}

const scores = params.scores;
if (scores != null) {
scoresString = scores.join(', ');
}
message += $localize`Obtain a score of <b>${scoresString}</b> on <b>${nodeTitle}</b>`;
} else if (name === 'choiceChosen') {
const nodeId = params.nodeId;
const componentId = params.componentId;
const choiceIds = params.choiceIds;
let nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
let choices = this.projectService.getChoiceText(nodeId, componentId, choiceIds);
let choiceText = choices.join(', ');
message += $localize`You must choose "${choiceText}" on "${nodeTitle}"`;
} else if (name === 'usedXSubmits') {
const nodeId = params.nodeId;
let nodeTitle = '';

const requiredSubmitCount = params.requiredSubmitCount;

if (nodeId != null) {
nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
}

if (requiredSubmitCount == 1) {
message += $localize`Submit <b>${requiredSubmitCount}</b> time on <b>${nodeTitle}</b>`;
} else {
message += $localize`Submit <b>${requiredSubmitCount}</b> times on <b>${nodeTitle}</b>`;
}
} else if (name === 'branchPathTaken') {
const fromNodeId = params.fromNodeId;
const fromNodeTitle = this.projectService.getNodePositionAndTitle(fromNodeId);
const toNodeId = params.toNodeId;
const toNodeTitle = this.projectService.getNodePositionAndTitle(toNodeId);
message += $localize`Take the branch path from <b>${fromNodeTitle}</b> to <b>${toNodeTitle}</b>`;
} else if (name === 'wroteXNumberOfWords') {
const nodeId = params.nodeId;
if (nodeId != null) {
const requiredNumberOfWords = params.requiredNumberOfWords;
const nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
message += $localize`Write <b>${requiredNumberOfWords}</b> words on <b>${nodeTitle}</b>`;
}
} else if (name === 'isVisible') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
message += $localize`"${nodeTitle}" is visible`;
}
} else if (name === 'isVisitable') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
message += $localize`"${nodeTitle}" is visitable`;
}
} else if (name === 'addXNumberOfNotesOnThisStep') {
const nodeId = params.nodeId;
const requiredNumberOfNotes = params.requiredNumberOfNotes;
const nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
if (requiredNumberOfNotes == 1) {
message += $localize`Add <b>${requiredNumberOfNotes}</b> note on <b>${nodeTitle}</b>`;
} else {
message += $localize`Add <b>${requiredNumberOfNotes}</b> notes on <b>${nodeTitle}</b>`;
}
} else if (name === 'fillXNumberOfRows') {
const requiredNumberOfFilledRows = params.requiredNumberOfFilledRows;
const nodeId = params.nodeId;
const nodeTitle = this.projectService.getNodePositionAndTitle(nodeId);
if (requiredNumberOfFilledRows == 1) {
message += $localize`You must fill in <b>${requiredNumberOfFilledRows}</b> row in the <b>Table</b> on <b>${nodeTitle}</b>`;
} else {
message += $localize`You must fill in <b>${requiredNumberOfFilledRows}</b> rows in the <b>Table</b> on <b>${nodeTitle}</b>`;
}
} else if (name === 'teacherRemoval') {
message += $localize`Wait for your teacher to unlock the item`;
}
return message;
}

/**
* Get the constraint action as human readable text.
* @param action A constraint action.
* @return A human readable text string that describes the action
* example
* 'All steps after this one will not be visitable until '
*/
private getActionMessage(action: string): string {
if (action === 'makeAllNodesAfterThisNotVisitable') {
return $localize`All steps after this one will not be visitable until `;
}
if (action === 'makeAllNodesAfterThisNotVisible') {
return $localize`All steps after this one will not be visible until `;
}
if (action === 'makeAllOtherNodesNotVisitable') {
return $localize`All other steps will not be visitable until `;
}
if (action === 'makeAllOtherNodesNotVisible') {
return $localize`All other steps will not be visible until `;
}
if (action === 'makeThisNodeNotVisitable') {
return $localize`This step will not be visitable until `;
}
if (action === 'makeThisNodeNotVisible') {
return $localize`This step will not be visible until `;
}
}
}
123 changes: 1 addition & 122 deletions src/assets/wise5/services/projectService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1191,125 +1191,6 @@ export class ProjectService {
return null;
}

/**
* Get the message that describes how to satisfy the criteria
* TODO: check if the criteria is satisfied
* @param criteria the criteria object that needs to be satisfied
* @returns the message to display to the student that describes how to
* satisfy the criteria
*/
getCriteriaMessage(criteria: any): string {
let message = '';

if (criteria != null) {
const name = criteria.name;
const params = criteria.params;

if (name === 'isCompleted') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.getNodePositionAndTitle(nodeId);
message += $localize`Complete <b>${nodeTitle}</b>`;
}
} else if (name === 'isVisited') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.getNodePositionAndTitle(nodeId);
message += $localize`Visit <b>${nodeTitle}</b>`;
}
} else if (name === 'isCorrect') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.getNodePositionAndTitle(nodeId);
message += $localize`Correctly answer <b>${nodeTitle}</b>`;
}
} else if (name === 'score') {
const nodeId = params.nodeId;
let nodeTitle = '';
let scoresString = '';

if (nodeId != null) {
nodeTitle = this.getNodePositionAndTitle(nodeId);
}

const scores = params.scores;
if (scores != null) {
scoresString = scores.join(', ');
}
message += $localize`Obtain a score of <b>${scoresString}</b> on <b>${nodeTitle}</b>`;
} else if (name === 'choiceChosen') {
const nodeId = params.nodeId;
const componentId = params.componentId;
const choiceIds = params.choiceIds;
let nodeTitle = this.getNodePositionAndTitle(nodeId);
let choices = this.getChoiceText(nodeId, componentId, choiceIds);
let choiceText = choices.join(', ');
message += $localize`You must choose "${choiceText}" on "${nodeTitle}"`;
} else if (name === 'usedXSubmits') {
const nodeId = params.nodeId;
let nodeTitle = '';

const requiredSubmitCount = params.requiredSubmitCount;

if (nodeId != null) {
nodeTitle = this.getNodePositionAndTitle(nodeId);
}

if (requiredSubmitCount == 1) {
message += $localize`Submit <b>${requiredSubmitCount}</b> time on <b>${nodeTitle}</b>`;
} else {
message += $localize`Submit <b>${requiredSubmitCount}</b> times on <b>${nodeTitle}</b>`;
}
} else if (name === 'branchPathTaken') {
const fromNodeId = params.fromNodeId;
const fromNodeTitle = this.getNodePositionAndTitle(fromNodeId);
const toNodeId = params.toNodeId;
const toNodeTitle = this.getNodePositionAndTitle(toNodeId);
message += $localize`Take the branch path from <b>${fromNodeTitle}</b> to <b>${toNodeTitle}</b>`;
} else if (name === 'wroteXNumberOfWords') {
const nodeId = params.nodeId;
if (nodeId != null) {
const requiredNumberOfWords = params.requiredNumberOfWords;
const nodeTitle = this.getNodePositionAndTitle(nodeId);
message += $localize`Write <b>${requiredNumberOfWords}</b> words on <b>${nodeTitle}</b>`;
}
} else if (name === 'isVisible') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.getNodePositionAndTitle(nodeId);
message += $localize`"${nodeTitle}" is visible`;
}
} else if (name === 'isVisitable') {
const nodeId = params.nodeId;
if (nodeId != null) {
const nodeTitle = this.getNodePositionAndTitle(nodeId);
message += $localize`"${nodeTitle}" is visitable`;
}
} else if (name === 'addXNumberOfNotesOnThisStep') {
const nodeId = params.nodeId;
const requiredNumberOfNotes = params.requiredNumberOfNotes;
const nodeTitle = this.getNodePositionAndTitle(nodeId);
if (requiredNumberOfNotes == 1) {
message += $localize`Add <b>${requiredNumberOfNotes}</b> note on <b>${nodeTitle}</b>`;
} else {
message += $localize`Add <b>${requiredNumberOfNotes}</b> notes on <b>${nodeTitle}</b>`;
}
} else if (name === 'fillXNumberOfRows') {
const requiredNumberOfFilledRows = params.requiredNumberOfFilledRows;
const nodeId = params.nodeId;
const nodeTitle = this.getNodePositionAndTitle(nodeId);
if (requiredNumberOfFilledRows == 1) {
message += $localize`You must fill in <b>${requiredNumberOfFilledRows}</b> row in the <b>Table</b> on <b>${nodeTitle}</b>`;
} else {
message += $localize`You must fill in <b>${requiredNumberOfFilledRows}</b> rows in the <b>Table</b> on <b>${nodeTitle}</b>`;
}
} else if (name === 'teacherRemoval') {
message += $localize`Wait for your teacher to unlock the item`;
}
}
return message;
}

/**
* Get the choices of a Multiple Choice component.
* @param nodeId The node id.
Expand Down Expand Up @@ -1417,9 +1298,7 @@ export class ProjectService {
return componentService.componentHasWork(component);
}

calculateComponentIdToHasWork(
components: ComponentContent[]
): {
calculateComponentIdToHasWork(components: ComponentContent[]): {
[componentId: string]: boolean;
} {
const componentIdToHasWork: { [componentId: string]: boolean } = {};
Expand Down
Loading