Commit f944ecfb authored by Konstantin Schulz's avatar Konstantin Schulz
Browse files

test module now has new improvements in: timer, navigation, better rounding...

test module now has new improvements in: timer, navigation, better rounding for evaluation percentage
parent b15716c8
......@@ -14,6 +14,7 @@ export class HelperService {
public static currentPopover: any;
public static generalErrorAlertMessage: string;
public static isLoading = false;
public static isDevMode = ['localhost'].indexOf(window.location.hostname) > -1; // set this to "false" for simulated production mode
public static isVocabularyCheck = false;
public static mostRecentSetup: ApplicationState = null;
......
......@@ -16,7 +16,6 @@ export class HomePage {
HelperService = HelperService;
public corpusUpdateCompletedString: string;
public isCorpusUpdateInProgress = false;
public isProductionEnv = ['localhost'].indexOf(window.location.hostname) > -1;
constructor(public navCtrl: NavController,
public http: HttpClient,
......
......@@ -15,18 +15,29 @@
<ion-content padding>
<ion-grid>
<!-- Comment out the *ngIf condition for easy navigation during development -->
<ion-row *ngIf="currentState !== TestModuleState.inProgress">
<!-- for easy navigation during development -->
<ion-row *ngIf="HelperService.isDevMode; else production">
<ion-col>
<ion-label>{{ 'TEST_MODULE_GO_TO_EXERCISE' | translate}}</ion-label>
<ion-select [(ngModel)]="selectedExerciseIndex" name="selectedExerciseIndex"
(ionChange)="showNextExercise(+selectedExerciseIndex - 1, true)">
<ion-select-option *ngFor="let number of Array.from(Array(getExerciseCount()).keys())">
{{number + 1}}
</ion-select-option>
<ion-label>{{ 'TEST_MODULE_GO_TO_EXERCISE' | translate}}:</ion-label>
<ion-select [(ngModel)]="currentExerciseIndex" name="currentExerciseIndex"
(ngModelChange)="showNextExercise(currentExerciseIndex)">
<ion-select-option *ngFor="let number of Array.from(Array(getExerciseCount()).keys())"
[value]="number">{{ number + 1 }}</ion-select-option>
</ion-select>
</ion-col>
</ion-row>
<ng-template #production>
<ion-row *ngIf="currentState !== TestModuleState.inProgress || HelperService.isDevMode">
<ion-col>
<ion-label>{{ 'TEST_MODULE_GO_TO_EXERCISE' | translate}}:</ion-label>
<ion-select [(ngModel)]="currentExerciseIndex" name="currentExerciseIndex"
(ngModelChange)="showNextExercise(currentExerciseIndex, true)">
<ion-select-option *ngFor="let number of Array.from(Array(getExerciseCount()).keys())"
[value]="number">{{ number + 1 }}</ion-select-option>
</ion-select>
</ion-col>
</ion-row>
</ng-template>
<ion-row *ngIf="currentState == TestModuleState.inProgress">
<ion-col>
<ion-label>{{ 'TEST_MODULE_PROGRESS_PART' | translate }} {{getCurrentExercisePartIndex() + 1}}</ion-label>
......@@ -67,7 +78,7 @@
</ion-row>
<ion-row>
<ion-col><b>{{ 'UNIT_TEST_TITLE' | translate }}</b><br>
{{ 'UNIT_TEST_TEXT' | translate }}
{{ 'UNIT_TEST_TEXT' | translate }}
</ion-col>
<ion-col>
<br>5 min
......@@ -87,9 +98,11 @@
{{ 'UNIT_DATA_SECURITY' | translate}}
</ion-col>
</ion-row>
<ion-row style="text-align:right;">
<ion-row class="button-continue">
<ion-col>
<ion-button (click)="showNextExercise(1)">{{ 'START_TEST' | translate}}</ion-button>
<ion-button (click)="continue()">
{{ 'START_TEST' | translate}}
</ion-button>
</ion-col>
</ion-row>
</div>
......@@ -102,6 +115,12 @@
<div class="h5p-container"></div>
</ion-col>
</ion-row>
<ion-row
*ngIf="currentState == TestModuleState.showSolutions && !getCurrentExerciseName().startsWith(nonH5Pstring)">
<ion-button (click)="continue()">
{{ 'BUTTON_CONTINUE' | translate}}
</ion-button>
</ion-row>
<!-- step 6: show results -->
<div *ngIf="currentState == TestModuleState.showResults">
<ion-row>
......@@ -109,37 +128,42 @@
<ion-card>
<ion-item>
<ion-icon name="stats" slot="start"></ion-icon>
<ion-label position="stacked"><h2>{{ 'RESULT' | translate }} {{ 'UNIT_DIAGNOSIS_TITLE' | translate}}</h2></ion-label>
<ion-label position="stacked">
<h2>{{ 'RESULT' | translate }} {{ 'UNIT_DIAGNOSIS_TITLE' | translate}}</h2></ion-label>
<br>
{{results[0][0]}} {{ 'OF' | translate}} {{results[0][1]}}
{{results[0][0]}} {{ 'OF' | translate}} {{results[0][1]}}
{{ 'UNIT_EVALUATION_TASKS' | translate}}
</ion-item>
<ion-item>
<ion-icon name="book" slot="start"></ion-icon>
<ion-label position="stacked"><h2>{{ 'RESULT' | translate }} {{ 'UNIT_APPLICATION_TITLE' | translate}}</h2></ion-label>
{{results[1][0]}} {{ 'OF' | translate}} {{results[1][1]}}
<ion-label position="stacked">
<h2>{{ 'RESULT' | translate }} {{ 'UNIT_APPLICATION_TITLE' | translate}}</h2>
</ion-label>
{{results[1][0]}} {{ 'OF' | translate}} {{results[1][1]}}
{{ 'UNIT_EVALUATION_TASKS' | translate}}
</ion-item>
<ion-item>
<ion-icon name="walk" slot="start"></ion-icon>
<ion-label position="stacked"><h2>{{ 'RESULT' | translate }} {{ 'UNIT_EXERCISE_TITLE' | translate}}</h2></ion-label>
<ion-label position="stacked">
<h2>{{ 'RESULT' | translate }} {{ 'UNIT_EXERCISE_TITLE' | translate}}</h2></ion-label>
<div *ngIf="testType == TestType.cloze; else list">
{{results[2][0]}} {{ 'OF' | translate}} {{results[2][1]}}
{{ 'UNIT_EVALUATION_GAPS' | translate }}
{{results[2][0]}} {{ 'OF' | translate}} {{results[2][1]}}
{{ 'UNIT_EVALUATION_GAPS' | translate }}
</div>
<ng-template #list>
{{results[2][0]}} {{ 'OF' | translate}} {{results[2][1]}}
{{results[2][0]}} {{ 'OF' | translate}} {{results[2][1]}}
{{ 'UNIT_EVALUATION_WORDS' |translate }}
{{knownCount[0]}}
{{knownCount[0]}}
</ng-template>
</ion-item>
<ion-item>
<ion-icon name="pulse" slot="start"></ion-icon>
<ion-label position="stacked"><h2>{{ 'RESULT' | translate }} {{ 'UNIT_TEST_TITLE' | translate}}</h2></ion-label>
{{results[3][0]}} {{ 'OF' | translate}} {{results[3][1]}}
<ion-label position="stacked">
<h2>{{ 'RESULT' | translate }} {{ 'UNIT_TEST_TITLE' | translate}}</h2></ion-label>
{{results[3][0]}} {{ 'OF' | translate}} {{results[3][1]}}
{{ 'UNIT_EVALUATION_TASKS' | translate}}<br>
{{ 'UNIT_EVALUATION_CHANGE' | translate}}
{{ ((results[0][0] - results[3][0]) / (results[0][0] > 0 ? results[0][0] : 1)) * -100 }}
{{ 'UNIT_EVALUATION_CHANGE' | translate}}
{{ (((results[0][0] - results[3][0]) / (results[0][0] > 0 ? results[0][0] : 1)) * -100).toFixed(2) }}
%
</ion-item>
</ion-card>
......
.button-continue {
text-align: right;
}
ion-grid {
text-align: left;
}
......
......@@ -38,9 +38,8 @@ export class TestPage implements OnDestroy, OnInit {
durationSeconds: 0,
exercises: ["nonH5P_1"]
}), new ExercisePart({
// TODO: FILL BLANKS 7 JSON FILE IS NOT CORRECT (EN/DE)
startIndex: 0,
durationSeconds: 300,
startIndex: 0,
durationSeconds: 300,
exercises: ["fill_blanks_1", "multi_choice_1", "multi_choice_2",
"multi_choice_3", "multi_choice_4", "multi_choice_5", "multi_choice_6",
"multi_choice_7", "multi_choice_8", "fill_blanks_2", "fill_blanks_3",
......@@ -53,8 +52,8 @@ export class TestPage implements OnDestroy, OnInit {
durationSeconds: 600,
exercises: ["multi_choice_19", "multi_choice_20", "multi_choice_21", "multi_choice_22", "multi_choice_23"]
}), new ExercisePart({
startIndex: 0,
durationSeconds: 900,
startIndex: 0,
durationSeconds: 900,
exercises: ["drag_text_1", "drag_text_2", "drag_text_3",
"drag_text_4", "drag_text_5"]
}), new ExercisePart({
......@@ -75,7 +74,7 @@ export class TestPage implements OnDestroy, OnInit {
"voc_list_71", "voc_list_72", "voc_list_73", "voc_list_74", "voc_list_75", "voc_list_76",
"voc_list_77", "voc_list_78", "voc_list_79", "voc_list_80", "voc_list_81", "voc_list_82",
"voc_list_83", "voc_list_84", "voc_list_85", "voc_list_86"]
// voc_list_14 = voc_list_7 (et) --> 14 deleted
// voc_list_14 = voc_list_7 (et) --> 14 deleted
}), new ExercisePart({
startIndex: 0, durationSeconds: 300, exercises: ["fill_blanks_1", "multi_choice_1", "multi_choice_2",
"multi_choice_3", "multi_choice_4", "multi_choice_5", "multi_choice_6",
......@@ -99,7 +98,6 @@ export class TestPage implements OnDestroy, OnInit {
public nonH5Pstring: string = "nonH5P";
public progressBarValue: number;
public results: [number, number][];
public selectedExerciseIndex: string;
public testType: TestType;
public timer: any;
public timerIDstring: string = "#timer";
......@@ -150,6 +148,11 @@ export class TestPage implements OnDestroy, OnInit {
this.currentState = TestModuleState.showResults;
}
continue() {
this.currentExerciseIndex = this.currentExerciseIndex + 1;
this.showNextExercise(this.currentExerciseIndex, this.currentState == TestModuleState.showSolutions);
}
async exit(ev: any = null) {
HelperService.currentPopover = await this.popoverController.create({
component: ConfirmCancelPage,
......@@ -225,16 +228,16 @@ export class TestPage implements OnDestroy, OnInit {
}
ngOnDestroy() {
clearInterval(this.timer);
this.removeTimer(false);
H5P.externalDispatcher.off('xAPI');
H5P.externalDispatcher.off('domChanged');
document.querySelector(this.h5pRowIDstring).classList.add(this.hideClassString);
}
ngOnInit(): void {
this.randomizeTestType();
this.results = [];
// this.currentExerciseIndex = 0;
this.showNextExercise(0);
this.currentExerciseIndex = 0;
this.adjustStartIndices();
this.vocService.currentTestResults = {};
this.currentState = TestModuleState.inProgress;
......@@ -265,6 +268,9 @@ export class TestPage implements OnDestroy, OnInit {
setH5PeventHandlers() {
H5P.externalDispatcher.on('xAPI', (event: XAPIevent) => {
if (this.currentState != TestModuleState.inProgress) {
return;
}
// results are only available when a task has been completed/answered, not in the "attempted" or "interacted" stages
if (event.data.statement.verb.id === HelperService.config["xAPIverbIDanswered"] && event.data.statement.result) {
this.vocService.currentTestResults[this.currentExerciseIndex] = event.data.statement;
......@@ -276,7 +282,7 @@ export class TestPage implements OnDestroy, OnInit {
}
}
if (!this.didTimeRunOut) {
this.showNextExercise(this.currentExerciseIndex + 1);
this.continue();
}
}
});
......@@ -296,16 +302,14 @@ export class TestPage implements OnDestroy, OnInit {
showNextExercise(newIndex: number, review: boolean = false) {
if (!review) {
const metaIndex: number = this.currentExerciseParts.map(x => x.startIndex).indexOf(newIndex);
if (metaIndex > -1) {
if (this.currentExerciseParts[metaIndex].durationSeconds > 0) {
this.removeTimer(false);
this.initTimer(this.currentExerciseParts[metaIndex].durationSeconds);
} else if (newIndex == this.currentExerciseParts[this.currentExerciseParts.length - 1].startIndex) {
this.removeTimer(true);
}
if (metaIndex > -1 && this.currentExerciseParts[metaIndex].durationSeconds > 0) {
this.removeTimer(false);
this.initTimer(this.currentExerciseParts[metaIndex].durationSeconds);
}
}
this.currentExerciseIndex = newIndex;
if (newIndex == this.currentExerciseParts[this.currentExerciseParts.length - 1].startIndex) {
this.removeTimer(true);
}
const currentExercisePart: ExercisePart = this.currentExerciseParts[this.getCurrentExercisePartIndex()];
const maxProgress: number = currentExercisePart.exercises.length;
this.progressBarValue = (newIndex - currentExercisePart.startIndex) / maxProgress;
......@@ -313,8 +317,6 @@ export class TestPage implements OnDestroy, OnInit {
const currentExerciseName = this.getCurrentExerciseName();
if (currentExerciseName.startsWith(this.nonH5Pstring)) {
document.querySelector(this.h5pRowIDstring).classList.add(this.hideClassString);
// uncomment this (and comment out the following line) for easier navigation during development
// if (newIndex == this.currentExerciseParts[this.currentExerciseParts.length - 1].startIndex) {
if (!review && newIndex == this.currentExerciseParts[this.currentExerciseParts.length - 1].startIndex) {
this.analyzeResults();
H5P.externalDispatcher.off('xAPI');
......@@ -357,7 +359,6 @@ export class TestPage implements OnDestroy, OnInit {
triggerSolutionsEventHandler() {
const iframe: HTMLIFrameElement = document.querySelector(this.h5pIframeString);
if (iframe) {
// h5p-answer
if (this.vocService.currentTestResults[this.currentExerciseIndex]) {
const oldActivity: Activity = <Activity>this.vocService.currentTestResults[this.currentExerciseIndex].object;
const oldResponse: string = this.vocService.currentTestResults[this.currentExerciseIndex].result.response;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment