Commit 476e4ef5 authored by Konstantin Schulz's avatar Konstantin Schulz
Browse files

added the matching exercise type

parent 6d789b0c
......@@ -33,6 +33,7 @@
"DEPENDENCY_ROOT": "Wurzel",
"DEPENDENCY_SUBJECT": "Subjekt",
"DEPENDENCY_VOCATIVE": "Vokativ",
"DEPENDENT_WORD": "Abhängiges Wort",
"EMAIL": "E-Mail",
"END": "Ende",
"EXERCISE_DOWNLOAD_NEXT_STEPS": "Nächste Schritte:",
......@@ -53,13 +54,16 @@
"FILE_TYPE_DOCX": "DOCX",
"FILE_TYPE_PDF": "PDF",
"FILE_TYPE_XML": "XML",
"GIVEN": "Gegeben",
"HEAD_WORD": "Basiswort",
"HELP": "Hilfe",
"INSTRUCTION_CHOOSE_FORMAT_AND_IMPORT": "Wähle als Dateiformat das 'Moodle-XML-Format'. Lade anschließend die soeben heruntergeladene XML-Datei hoch und klicke auf 'Import'.",
"INSTRUCTION_COGWHEEL_MORE": "Klicke auf das Zahnrad-Symbol oben rechts, dann auf 'Mehr'.",
"INSTRUCTION_GO_TO_QUESTION_BANK": "Klicke auf 'Fragensammlung', dann auf 'Import'.",
"INSTRUCTION_LOGIN_MOODLE": "Lade die Übung mit einem Klick auf 'XML' herunter. Nun logge dich in Moodle ein und betrete den Kurs, der die Übung enthalten soll.",
"INSTRUCTIONS": "Anweisungen",
"INSTRUCTIONS_FILL_THE_GAP": "Ordne die Wörter aus dem Pool den richtigen Lücken zu!",
"INSTRUCTIONS_CLOZE": "Ordne die Wörter aus dem Pool den richtigen Lücken zu!",
"INSTRUCTIONS_MATCHING": "Ordne die zusammengehörigen Elemente einander zu!",
"INVALID_TEXT_RANGE": "Ungültige Textauswahl",
"MACHINA_CALLIDA_BACKEND": "Machina Callida Backend",
"MACHINA_CALLIDA_FRONTEND": "Machina Callida Frontend",
......@@ -89,5 +93,6 @@
"START": "Anfang",
"TEST": "Test",
"TEXT_TOO_LONG": "Text zu lang, max. Wortzahl: ",
"WANTED": "Gesucht",
"WELCOME": "Willkommen!"
}
\ No newline at end of file
......@@ -33,6 +33,7 @@
"DEPENDENCY_ROOT": "Root",
"DEPENDENCY_SUBJECT": "Subject",
"DEPENDENCY_VOCATIVE": "Vocative",
"DEPENDENT_WORD": "Base word",
"EMAIL": "E-Mail",
"END": "End",
"EXERCISE_DOWNLOAD_NEXT_STEPS": "Next steps:",
......@@ -53,13 +54,16 @@
"FILE_TYPE_DOCX": "DOCX",
"FILE_TYPE_PDF": "PDF",
"FILE_TYPE_XML": "XML",
"GIVEN": "Given",
"HEAD_WORD": "Head word",
"HELP": "Help",
"INSTRUCTION_CHOOSE_FORMAT_AND_IMPORT": "Choose 'Moodle XML format' as file format. Now upload the XML file that you just downloaded, then click on 'Import'.",
"INSTRUCTION_COGWHEEL_MORE": "Click on the cogwheel in the upper right corner, then on 'More'.",
"INSTRUCTION_GO_TO_QUESTION_BANK": "Click on 'Question bank', then on 'Import'.",
"INSTRUCTION_LOGIN_MOODLE": "Download the exercise by clicking on 'XML'. Now log into Moodle and enter the course that is going to contain the exercise.",
"INSTRUCTIONS": "Instructions",
"INSTRUCTIONS_FILL_THE_GAP": "Assign the words from the pool to the correct gaps!",
"INSTRUCTIONS_CLOZE": "Assign the words from the pool to the correct gaps!",
"INSTRUCTIONS_MATCHING": "Assign the matching elements to each other!",
"INVALID_TEXT_RANGE": "Invalid text range",
"MACHINA_CALLIDA_BACKEND": "Machina Callida Backend",
"MACHINA_CALLIDA_FRONTEND": "Machina Callida Frontend",
......@@ -89,5 +93,6 @@
"START": "Start",
"TEST": "Test",
"TEXT_TOO_LONG": "Text too long, max. word count: ",
"WANTED": "Wanted",
"WELCOME": "Welcome!"
}
\ No newline at end of file
import {Graph} from "./graph";
import {Solution} from "./solution";
export class AnnisResponse {
public graph: Graph;
public solution: { [targetNodeId: string]: string };
public solutions: Solution[];
public uri: string;
constructor(init?: Partial<AnnisResponse>) {
......
......@@ -12,6 +12,11 @@ export enum ExerciseTypeTranslation {
matching = <any>"EXERCISE_TYPE_MATCHING",
}
export enum InstructionsTranslation {
cloze = <any>"INSTRUCTIONS_CLOZE",
matching = <any>"INSTRUCTIONS_MATCHING",
}
export enum MoodleExerciseType {
cloze = <any>"ddwtos",
matching = <any>"matching",
......
import {ExerciseType, ExerciseTypeTranslation} from "./enum";
import {ExerciseType} from "./enum";
import {QueryMC} from "./queryMC";
import {Feedback} from "./feedback";
export class Exercise {
public type: ExerciseType;
public typeTranslation: ExerciseTypeTranslation;
public query: QueryMC;
public typeTranslation: string;
public queryItems: QueryMC[];
public feedback: Feedback;
constructor(init?:Partial<Exercise>) {
public instructionsTranslation: string;
constructor(init?: Partial<Exercise>) {
Object.assign(this, init);
}
}
......
import {SolutionElement} from "./solutionElement";
export class Solution {
public target: SolutionElement;
public value: SolutionElement;
constructor(init?: Partial<Solution>) {
Object.assign(this, init);
}
}
\ No newline at end of file
export class SolutionElement {
public sentence_id: number;
public token_id: number;
public content: string;
public salt_id: string;
constructor(init?: Partial<SolutionElement>) {
Object.assign(this, init);
}
}
\ No newline at end of file
......@@ -141,6 +141,7 @@ export class CorpusDetailPage {
}
let newUrnBase: string = this.corpusProvider.currentCorpus.source_urn + ":";
this.corpusProvider.currentUrn = newUrnBase + this.corpusProvider.currentLastUrnPart;
this.corpusProvider.currentText = "";
this.navCtrl.push(ShowTextPage).then();
}
}
......
......@@ -6,6 +6,7 @@ import {ExerciseProvider} from "../../providers/exercise/exercise";
import {TranslateService} from "@ngx-translate/core";
import {FeedbackPage} from "../feedback/feedback";
import {CorpusProvider} from "../../providers/corpus/corpus";
import {ExerciseType, ExerciseTypeTranslation} from "../../models/enum";
@Component({
selector: 'page-home',
......@@ -28,11 +29,7 @@ export class HomePage {
}
async test() {
let a = "";
let b = !!a;
let c = new Date().getTime();
let d = new Date(c);
let f = d.getTime() - c;
let a = ExerciseTypeTranslation["cloze"];
let g = 0;
}
}
......@@ -21,18 +21,50 @@
<ion-content padding>
<div *ngIf="exerciseProvider.annisResponse; else loading">
<h1>{{ 'INSTRUCTIONS' | translate }}</h1>
<h4>{{ ExerciseTypeTranslation[this.exerciseProvider.exercise.type] | translate }}: {{
instructionsFillTheGapString }}</h4>
<div *ngFor="let solution of exerciseProvider.annisResponse?.solution | dictToIterable">{{solution}}&#32;</div>
<h4>{{ ExerciseTypeTranslation[exerciseProvider.exercise.type] | translate }}: {{
exerciseProvider.exercise.instructionsTranslation }}</h4>
<div *ngIf="exerciseProvider.exercise.type === ExerciseType.cloze; else matching">
<div *ngFor="let solution of solutionsShuffled">
{{solution.target.content}}&#32;
</div>
<br>
<br>
<!-- Do not use non-breaking whitespaces (&nbsp;). If you do, some browsers will start breaking lines on a character basis (after a resize occurred), which results in single words being cut into pieces at the end of a line. Use &#32; instead. -->
<div *ngFor="let node of exerciseProvider.annisResponse?.graph.nodes">{{node.annis_tok}}&#32;</div>
</div>
<ng-template #matching>
<ion-grid>
<ion-row>
<ion-col>
<h5>{{ "GIVEN" | translate }}</h5>
</ion-col>
<ion-col>
<h5>{{ "WANTED" | translate }}</h5>
</ion-col>
</ion-row>
<ion-row *ngFor="let solution of solutionsShuffled">
<ion-col>{{solution.target.content}}</ion-col>
<ion-col>{{solution.value.content}}</ion-col>
<!--<ion-grid>-->
<!--<ion-row *ngFor="let value of solutionsShuffled[key]">-->
<!--<ion-col>{{ getNodeById(key).annis_tok }}</ion-col>-->
<!--<ion-col>{{ getNodeById(value).annis_tok }}</ion-col>-->
<!--</ion-row>-->
<!--</ion-grid>-->
</ion-row>
</ion-grid>
</ng-template>
<br>
<br>
<!-- Do not use non-breaking whitespaces (&nbsp;). If you do, some browsers will start breaking lines on a character basis (after a resize occurred), which results in single words being cut into pieces at the end of a line. Use &#32; instead. -->
<div *ngFor="let node of exerciseProvider.annisResponse?.graph.nodes">{{node.annis_tok}}&#32;</div>
<br>
<br>
<button ion-button block (click)="downloadExercise(FileType[FileType.pdf])">{{ 'FILE_TYPE_PDF' | translate }}</button>
<button ion-button block (click)="downloadExercise(FileType[FileType.xml])">{{ 'FILE_TYPE_XML' | translate }}</button>
<button ion-button block (click)="downloadExercise(FileType[FileType.docx])">{{ 'FILE_TYPE_DOCX' | translate }}</button>
<button ion-button block (click)="downloadExercise(FileType[FileType.pdf])">
{{ 'FILE_TYPE_PDF' | translate }}
</button>
<button ion-button block (click)="downloadExercise(FileType[FileType.xml])">
{{ 'FILE_TYPE_XML' | translate }}
</button>
<button ion-button block (click)="downloadExercise(FileType[FileType.docx])">
{{ 'FILE_TYPE_DOCX' | translate }}
</button>
<br>
<br>
<h4>{{ 'EXERCISE_DOWNLOAD_NEXT_STEPS' | translate }}</h4>
......
......@@ -5,9 +5,11 @@ import {AnnisResponse} from "../../models/annisResponse";
import {ExerciseProvider} from "../../providers/exercise/exercise";
import {TranslateService} from "@ngx-translate/core";
import {CorpusProvider} from "../../providers/corpus/corpus";
import {ExerciseTypeTranslation, FileType, MoodleExerciseType} from "../../models/enum";
import {ExerciseType, ExerciseTypeTranslation, FileType, MoodleExerciseType} from "../../models/enum";
import {FeedbackPage} from "../feedback/feedback";
import {HelperProvider} from "../../providers/helper/helper";
import {SolutionElement} from "../../models/solutionElement";
import {Solution} from "../../models/solution";
/**
* Generated class for the PreviewPage page.
......@@ -22,51 +24,43 @@ import {HelperProvider} from "../../providers/helper/helper";
templateUrl: 'preview.html',
})
export class PreviewPage {
public instructionsFillTheGapString: string;
FileType = FileType;
FeedBackPage = FeedbackPage;
ExerciseTypeTranslation = ExerciseTypeTranslation;
public ExerciseType = ExerciseType;
public FileType = FileType;
public FeedBackPage = FeedbackPage;
public ExerciseTypeTranslation = ExerciseTypeTranslation;
public ObjectKeys = Object.keys;
public solutionsShuffled: Solution[];
constructor(public navCtrl: NavController, public navParams: NavParams,
public http: HttpClient,
public exerciseProvider: ExerciseProvider,
public translateService: TranslateService,
public corpusProvider: CorpusProvider) {
this.translateService.get("INSTRUCTIONS_FILL_THE_GAP").subscribe((value) => {
this.instructionsFillTheGapString = value;
});
this.solutionsShuffled = [];
if (!this.exerciseProvider.annisResponse) {
this.getExerciseData();
}
}
private getExerciseData() {
this.translateService.get(this.exerciseProvider.exercise.typeTranslation.toString()).subscribe((ett: string) => {
let formData = new FormData();
let search_value: string = this.exerciseProvider.exercise.query.phenomenon + "=" + this.exerciseProvider.exercise.query.value;
// TODO: change the corpus title to something meaningful, e.g. concatenate user ID and wanted exercise title
formData.append("title", this.exerciseProvider.createGuid());
formData.append("text", this.corpusProvider.currentText);
formData.append("type", MoodleExerciseType[this.exerciseProvider.exercise.type]);
formData.append("type_translation", ett);
formData.append("search_value", search_value);
formData.append("instructions", this.instructionsFillTheGapString);
formData.append("correct_feedback", this.exerciseProvider.exercise.feedback.correct);
formData.append("partially_correct_feedback", this.exerciseProvider.exercise.feedback.partiallyCorrect);
formData.append("incorrect_feedback", this.exerciseProvider.exercise.feedback.incorrect);
formData.append("general_feedback", this.exerciseProvider.exercise.feedback.general);
let url = HelperProvider.config["backendBaseUrl"] + HelperProvider.config["backendApiExercisePath"];
this.http.post(url, formData).subscribe((ar: AnnisResponse) => {
let maxGapLength = Math.max.apply(Math, Object.keys(ar.solution).map(key => ar.solution[key].length));
ar.graph.nodes.forEach((node) => {
if (node.annis_tok.startsWith("[[")) {
node.annis_tok = "_".repeat(maxGapLength)
}
});
this.exerciseProvider.annisResponse = ar;
}, (error) => {
console.log(error);
});
let formData = new FormData();
let search_values: string[] = this.exerciseProvider.exercise.queryItems.map(query => query.phenomenon + "=" + query.value);
// TODO: change the corpus title to something meaningful, e.g. concatenate user ID and wanted exercise title
formData.append("title", this.exerciseProvider.createGuid());
formData.append("text", this.corpusProvider.currentText);
formData.append("type", MoodleExerciseType[this.exerciseProvider.exercise.type]);
formData.append("type_translation", this.exerciseProvider.exercise.typeTranslation);
formData.append("search_values", JSON.stringify(search_values));
formData.append("instructions", this.exerciseProvider.exercise.instructionsTranslation);
formData.append("correct_feedback", this.exerciseProvider.exercise.feedback.correct);
formData.append("partially_correct_feedback", this.exerciseProvider.exercise.feedback.partiallyCorrect);
formData.append("incorrect_feedback", this.exerciseProvider.exercise.feedback.incorrect);
formData.append("general_feedback", this.exerciseProvider.exercise.feedback.general);
let url = HelperProvider.config["backendBaseUrl"] + HelperProvider.config["backendApiExercisePath"];
this.http.post(url, formData).subscribe((ar: AnnisResponse) => {
this.processAnnisResponse(ar);
}, (error) => {
console.log(error);
});
}
......@@ -77,4 +71,29 @@ export class PreviewPage {
let url = HelperProvider.config["backendBaseUrl"] + HelperProvider.config["backendApiFilePath"];
window.open(url + "/" + fileId + fileTypeString, "_blank");
}
private processAnnisResponse(ar: AnnisResponse) {
if (this.exerciseProvider.exercise.type === ExerciseType.cloze) {
let maxGapLength: number = Math.max.apply(Math, ar.solutions.map(x => x.target.content.length));
Array.from(new Set(ar.solutions.map(value => value.target.salt_id))).forEach((value) => {
ar.graph.nodes.forEach((node) => {
if (node.id === value) {
node.annis_tok = "_".repeat(maxGapLength)
}
});
});
}
let targets: SolutionElement[] = ar.solutions.map(x => x.target).sort(() => {
// TODO: for really random shuffling, implement the Fisher-Yates Shuffle algorithm
return 0.5 - Math.random();
});
targets.forEach((value: SolutionElement, index: number, array: SolutionElement[]) => {
this.solutionsShuffled.push(new Solution({target: value, value: ar.solutions[index].value}));
});
this.exerciseProvider.annisResponse = ar;
}
getNodeById(id: string) {
return this.exerciseProvider.annisResponse.graph.nodes.find(x => x.id === id);
}
}
......@@ -24,74 +24,69 @@
<div *ngIf="corpusProvider.currentText.length > 0; else loading">
<p>{{corpusProvider.currentText}}</p>
<h2>{{ 'EXERCISE_GENERATE' | translate }}</h2>
<ion-list>
<ion-item>
<ion-label>
{{ 'EXERCISE_TYPE' | translate }}
</ion-label>
<ion-select [(ngModel)]="exerciseProvider.exercise.type" name="exerciseType"
(ionChange)="adjustTypeTranslation()">
<ion-option *ngFor="let key of ObjectKeys(ExerciseType)" [value]=key>{{ ExerciseTypeTranslation[key]
| translate }}
</ion-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>
{{ 'QUERY_PHENOMENON' | translate }}
</ion-label>
<ion-select [(ngModel)]="exerciseProvider.exercise.query.phenomenon" name="queryPhenomenon"
(ionChange)="adjustQueryValue()">
<ion-option *ngFor="let phenomenon of ObjectKeys(Phenomenon)" [value]=phenomenon>{{
PhenomenonTranslation[phenomenon] | translate }}
</ion-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>
{{ 'QUERY_VALUE' | translate }}
</ion-label>
<ion-select *ngIf="exerciseProvider.exercise.query.phenomenon !== Phenomenon.lemma; else lemma"
[(ngModel)]="exerciseProvider.exercise.query.value" name="queryValue">
<ion-option
*ngFor="let key of getSortedQueryValues()" [value]=key>{{
exerciseProvider.phenomenonMap[exerciseProvider.exercise.query.phenomenon][0][key] }}
</ion-option>
</ion-select>
</ion-item>
<br>
<ion-list>
<ion-title>{{ 'EXERCISE_FEEDBACK' | translate }}</ion-title>
<ion-item>
<ion-label>{{ 'EXERCISE_FEEDBACK_GENERAL' | translate }}</ion-label>
<ion-textarea [(ngModel)]="exerciseProvider.exercise.feedback.general"
name="feedbackGeneral"></ion-textarea>
</ion-item>
<ion-item>
<ion-label>{{ 'EXERCISE_FEEDBACK_CORRECT' | translate }}</ion-label>
<ion-textarea [(ngModel)]="exerciseProvider.exercise.feedback.correct"
name="feedbackCorrect"></ion-textarea>
</ion-item>
<ion-item>
<ion-label>{{ 'EXERCISE_FEEDBACK_PARTIALLY_CORRECT' | translate }}</ion-label>
<ion-textarea [(ngModel)]="exerciseProvider.exercise.feedback.partiallyCorrect"
name="feedbackPartiallyCorrect"></ion-textarea>
</ion-item>
<ion-item>
<ion-label>{{ 'EXERCISE_FEEDBACK_INCORRECT' | translate }}</ion-label>
<ion-textarea [(ngModel)]="exerciseProvider.exercise.feedback.incorrect"
name="feedbackIncorrect"></ion-textarea>
</ion-item>
</ion-list>
</ion-list>
<ion-grid>
<ion-row>
<ion-col>
<ion-label>
{{ 'EXERCISE_TYPE' | translate }}
</ion-label>
<ion-select [(ngModel)]="exerciseProvider.exercise.type" name="exerciseType"
(ionChange)="adjustTranslations()">
<ion-option *ngFor="let key of ObjectKeys(ExerciseType)" [value]=ExerciseType[key]>{{
ExerciseTypeTranslation[key]
| translate }}
</ion-option>
</ion-select>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-label>
{{ 'INSTRUCTIONS' | translate }}
</ion-label>
<ion-input [(ngModel)]="exerciseProvider.exercise.instructionsTranslation"
name="instructionsTranslation"></ion-input>
</ion-col>
</ion-row>
<ion-row *ngIf="exerciseProvider.exercise.type === ExerciseType.matching">
<ion-col><h3>{{ 'HEAD_WORD' | translate }}</h3></ion-col>
<ion-col><h3>{{ 'DEPENDENT_WORD' | translate }}</h3></ion-col>
</ion-row>
<ion-row>
<ion-col *ngFor="let query of exerciseProvider.exercise.queryItems">
<ion-grid>
<ion-row>
<ion-col>
<ion-label>{{ 'QUERY_PHENOMENON' | translate }}</ion-label>
<ion-select [(ngModel)]="query.phenomenon" name="queryPhenomenon"
(ionChange)="adjustQueryValue(query)">
<ion-option *ngFor="let phenomenon of ObjectKeys(Phenomenon)" [value]=phenomenon>{{
PhenomenonTranslation[phenomenon] | translate }}
</ion-option>
</ion-select>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<ion-label>{{ 'QUERY_VALUE' | translate }}</ion-label>
<ion-select *ngIf="query.phenomenon !== Phenomenon.lemma; else lemma"
[(ngModel)]="query.value" name="queryValue">
<ion-option *ngFor="let key of getSortedQueryValues(query)" [value]=key>{{
exerciseProvider.phenomenonMap[query.phenomenon][0][key] }}
</ion-option>
</ion-select>
<ng-template #lemma>
<ion-input [(ngModel)]="query.value" placeholder="Lemma"></ion-input>
</ng-template>
</ion-col>
</ion-row>
</ion-grid>
</ion-col>
</ion-row>
</ion-grid>
<button ion-button (click)="generateExercise()">{{ 'PREVIEW' | translate }}</button>
</div>
<ng-template #loading>
<ion-spinner></ion-spinner>
</ng-template>
<ng-template #lemma>
<div item-end style="width: 100px">
<ion-input [(ngModel)]="exerciseProvider.exercise.query.value" placeholder="Lemma"></ion-input>
</div>
</ng-template>
</ion-content>
......@@ -2,7 +2,7 @@ import {Component} from '@angular/core';
import {IonicPage, NavController, NavParams, ToastController} from 'ionic-angular';
import {CorpusProvider} from "../../providers/corpus/corpus";
import {
ExerciseType, ExerciseTypeTranslation,
ExerciseType, ExerciseTypeTranslation, InstructionsTranslation, PartOfSpeechValue,
Phenomenon,
PhenomenonTranslation
} from "../../models/enum";
......@@ -11,6 +11,7 @@ import {PreviewPage} from "../preview/preview";
import {TranslateService} from "@ngx-translate/core";
import {FeedbackPage} from "../feedback/feedback";
import {HelperProvider} from "../../providers/helper/helper";
import {QueryMC} from "../../models/queryMC";
/**
* Generated class for the ShowTextPage page.
......@@ -58,7 +59,7 @@ export class ShowTextPage {
});
toast.present().then();
}
else if (this.exerciseProvider.exercise.query.phenomenon === Phenomenon.lemma && !this.exerciseProvider.exercise.query.value) {
else if (this.exerciseProvider.exercise.queryItems[0].phenomenon === Phenomenon.lemma && !this.exerciseProvider.exercise.queryItems[0].value) {
let toast = this.toastCtrl.create({
message: this.emptyQueryValueString,
duration: 3000,
......@@ -72,25 +73,35 @@ export class ShowTextPage {
}
}
getSortedQueryValues() {
let targetObject: object = this.exerciseProvider.phenomenonMap[this.exerciseProvider.exercise.query.phenomenon][0];
getSortedQueryValues(query: QueryMC) {
let targetObject: object = this.exerciseProvider.phenomenonMap[query.phenomenon][0];
return Object.keys(targetObject).sort((a, b) => {
return a === b ? 0 : (targetObject[a] < targetObject[b] ? -1 : 1);
});
}
adjustQueryValue() {
if (this.exerciseProvider.exercise.query.phenomenon === Phenomenon.lemma) {
this.exerciseProvider.exercise.query.value = "";
adjustQueryValue(query: QueryMC) {
if (query.phenomenon === Phenomenon.lemma) {
query.value = "";
}
else {
let availableValues = Object.keys(this.exerciseProvider.phenomenonMap[this.exerciseProvider.exercise.query.phenomenon][0]);
let availableValues = Object.keys(this.exerciseProvider.phenomenonMap[query.phenomenon][0]);
// when the phenomenon changes, choose a (almost) random value as the default
this.exerciseProvider.exercise.query.value = availableValues[Object.keys(availableValues)[0]];
query.value = availableValues[Object.keys(availableValues)[0]];
}
}
adjustTypeTranslation() {
this.exerciseProvider.exercise.typeTranslation = ExerciseTypeTranslation[ExerciseTypeTranslation[this.exerciseProvider.exercise.type]];
adjustTranslations() {
this.translateService.get(ExerciseTypeTranslation[this.exerciseProvider.exercise.type]).subscribe(value => this.exerciseProvider.exercise.typeTranslation = value);
this.translateService.get(InstructionsTranslation[this.exerciseProvider.exercise.type]).subscribe(value => this.exerciseProvider.exercise.instructionsTranslation = value);
if (this.exerciseProvider.exercise.type === ExerciseType.matching) {
this.exerciseProvider.exercise.queryItems.push(new QueryMC({
phenomenon: Phenomenon.partOfSpeech,
value: PartOfSpeechValue.adjective,
}));
}
else if (this.exerciseProvider.exercise.queryItems.length > 1) {
this.exerciseProvider.exercise.queryItems.splice(1, 1);
}
}
}
import {Pipe, PipeTransform} from '@angular/core';
/**
* Generated class for the DictToIterablePipe pipe.
*
* See https://angular.io/api/core/Pipe for more info on Angular Pipes.
*/
@Pipe({
name: 'dictToIterable',
})
export class DictToIterablePipe implements PipeTransform {
/**
* Takes a value and makes it lowercase.
*/
transform(value: object, ...args) {
if (!value) {
return [];
}
return Object.keys(value).map(key => value[key]);
}
}
import { NgModule } from '@angular/core';
import { DictToIterablePipe } from './dict-to-iterable/dict-to-iterable';
@NgModule({
declarations: [DictToIterablePipe],
declarations: [],
imports: [],
exports: [DictToIterablePipe]
exports: []
})
export class PipesModule {}
......@@ -3,7 +3,7 @@ import {Injectable} from '@angular/core';
import {