corpus.service.ts 23.5 KB
Newer Older
1
/* tslint:disable:no-string-literal object-literal-shorthand */
Konstantin Schulz's avatar
Konstantin Schulz committed
2
import {Injectable} from '@angular/core';
3 4 5
import {CorpusMC} from 'src/app/models/corpusMC';
import {Author} from 'src/app/models/author';
import {TextRange} from 'src/app/models/textRange';
6
import {HttpClient, HttpErrorResponse, HttpParams} from '@angular/common/http';
7 8 9
import {TranslateService} from '@ngx-translate/core';
import {ToastController} from '@ionic/angular';
import {HelperService} from 'src/app/helper.service';
10
import {AnnisResponse} from 'src/app/models/annisResponse';
11 12 13 14
import {
    CaseTranslations,
    CaseValue,
    DependencyTranslation,
15 16 17
    DependencyValue,
    ExerciseType,
    ExerciseTypeTranslation,
18
    InstructionsTranslation,
19 20 21
    PartOfSpeechTranslation,
    PartOfSpeechValue,
    Phenomenon
22 23 24 25 26 27
} from 'src/app/models/enum';
import {NodeMC} from 'src/app/models/nodeMC';
import {LinkMC} from 'src/app/models/linkMC';
import {QueryMC} from 'src/app/models/queryMC';
import {Exercise} from 'src/app/models/exercise';
import {Feedback} from 'src/app/models/feedback';
28 29
import {PhenomenonMap, PhenomenonMapContent} from 'src/app/models/phenomenonMap';
import {FrequencyItem} from 'src/app/models/frequencyItem';
30 31 32 33
import {BehaviorSubject, ReplaySubject} from 'rxjs';
import {ApplicationState} from './models/applicationState';
import {take} from 'rxjs/operators';
import {TextData} from './models/textData';
Konstantin Schulz's avatar
Konstantin Schulz committed
34

35 36 37 38
@Injectable({
    providedIn: 'root'
})
export class CorpusService {
39
    public annisResponse: AnnisResponse;
Konstantin Schulz's avatar
Konstantin Schulz committed
40 41
    public availableCorpora: CorpusMC[];
    public availableAuthors: Author[];
42
    public baseUrn: string;
43
    public citationsUnavailableString: string;
44
    public corporaUnavailableString: string;
Konstantin Schulz's avatar
Konstantin Schulz committed
45
    public currentAuthor: Author;
46 47
    public currentCorpus: ReplaySubject<CorpusMC>;
    private currentCorpusCache: CorpusMC;
48
    public currentText = '';
49 50
    public currentTextRange: ReplaySubject<TextRange>;
    private currentTextRangeCache: TextRange = new TextRange({start: ['', '', ''], end: ['', '', '']});
51 52 53 54 55 56 57 58 59 60 61
    public currentUrn: string;
    public exercise: Exercise = new Exercise({
        type: ExerciseType.cloze,
        typeTranslation: '',
        queryItems: [new QueryMC({
            phenomenon: Phenomenon.partOfSpeech,
            values: [PartOfSpeechValue.adjective],
        })],
        feedback: new Feedback({general: '', incorrect: '', partiallyCorrect: '', correct: ''}),
        instructionsTranslation: ''
    });
62
    public invalidTextRangeString: string;
63
    public isMostRecentSetupLoaded = false;
64
    public isTextRangeCorrect = false;
65 66 67 68 69 70
    public phenomenonMap: PhenomenonMap = new PhenomenonMap({
        case: new PhenomenonMapContent({translationObject: CaseTranslations}),
        dependency: new PhenomenonMapContent({translationObject: DependencyTranslation}),
        lemma: new PhenomenonMapContent({translationObject: null}),
        partOfSpeech: new PhenomenonMapContent({translationObject: PartOfSpeechTranslation})
    });
71
    public shareLinkCopiedString: string;
Konstantin Schulz's avatar
Konstantin Schulz committed
72

Konstantin Schulz's avatar
Konstantin Schulz committed
73
    constructor(public translate: TranslateService,
74
                public http: HttpClient,
75 76 77
                public toastCtrl: ToastController,
                public helperService: HelperService,
    ) {
78
        this.isMostRecentSetupLoaded = false;
79 80 81
        this.helperService.initApplicationState();
        this.initCurrentCorpus();
        this.initCurrentTextRange();
82
        HelperService.waitForConfig().then(() => {
83
            this.checkForUpdates().finally(() => {
84 85
                this.checkAnnisResponse().then(() => {
                    this.restoreLastCorpus().then(() => {
86
                        this.isMostRecentSetupLoaded = true;
87 88
                    });
                }, () => {
89
                    this.isMostRecentSetupLoaded = true;
90
                });
91
            });
92 93 94
        });
        this.initPhenomenonMap();
        this.getTranslations();
95 96 97
        this.translate.onLangChange.subscribe(() => {
            this.getTranslations();
        });
98 99
    }

100 101 102 103
    adjustQueryValue(query: QueryMC, queryIndex: number) {
        // when the phenomenon changes, choose the first value from the translated list as the default
        query.values = [this.getSortedQueryValues(query, queryIndex)[0]];
        this.updateBaseWord(query, queryIndex);
Konstantin Schulz's avatar
Konstantin Schulz committed
104 105
    }

Konstantin Schulz's avatar
Konstantin Schulz committed
106 107 108 109 110 111 112 113
    adjustTranslations() {
        this.translate.get(ExerciseTypeTranslation[this.exercise.type]).subscribe(
            value => this.exercise.typeTranslation = value);
        if ([ExerciseType.cloze, ExerciseType.matching, ExerciseType.markWords].indexOf(this.exercise.type) > -1) {
            this.translate.get(InstructionsTranslation[this.exercise.type]).subscribe(
                value => this.exercise.instructionsTranslation = value);
        }
        if (this.exercise.type === ExerciseType.matching) {
114 115 116 117 118 119 120
            this.exercise.queryItems = [new QueryMC({phenomenon: Phenomenon.partOfSpeech, values: []}),
                new QueryMC({phenomenon: Phenomenon.partOfSpeech, values: []})];
            this.getFrequencyAnalysis().then(() => {
                this.adjustQueryValue(this.exercise.queryItems[0], 0);
                this.adjustQueryValue(this.exercise.queryItems[1], 1);
                return;
            });
Konstantin Schulz's avatar
Konstantin Schulz committed
121 122 123
        } else if (this.exercise.queryItems.length > 1) {
            this.exercise.queryItems.splice(1, 1);
        }
124
        this.adjustQueryValue(this.exercise.queryItems[0], 0);
Konstantin Schulz's avatar
Konstantin Schulz committed
125 126
    }

127
    checkAnnisResponse() {
128
        return new Promise((outerResolve, outerReject) => {
129
            if (this.annisResponse) {
130
                return outerResolve();
131
            }
132 133 134 135 136 137 138 139 140 141
            HelperService.applicationState.pipe(take(1)).subscribe((state: ApplicationState) => {
                if (state.mostRecentSetup) {
                    this.annisResponse = state.mostRecentSetup.annisResponse;
                    this.currentAuthor = state.mostRecentSetup.currentAuthor;
                    this.currentUrn = state.mostRecentSetup.currentUrn;
                    this.currentCorpusCache = state.mostRecentSetup.currentCorpus;
                    return outerResolve();
                } else {
                    return outerReject();
                }
142 143
            }, () => {
                return outerReject();
144 145 146 147
            });
        });
    }

148 149 150 151 152 153 154 155 156 157
    checkForUpdates(): Promise<void> {
        return new Promise((resolve, reject) => {
            // check local storage for necessary updates
            const updateInfoJSON: object = JSON.parse(window.localStorage.getItem(HelperService.config['localStorageKeyUpdateInfo']));
            this.getCorpora(updateInfoJSON ? new Date(updateInfoJSON['corpora'].lastAccessTime).getTime() : 0).then(() => {
                return resolve();
            }, () => {
                return reject();
            });
        });
Konstantin Schulz's avatar
Konstantin Schulz committed
158 159
    }

160 161
    getCorpora(lastUpdateTimeMS: number = 0): Promise<void> {
        return new Promise((resolve, reject) => {
162 163
            this.availableCorpora = [];
            this.availableAuthors = [];
164
            // get corpora from REST API
165
            const url = HelperService.config['backendBaseUrl'] + HelperService.config['backendApiCorporaPath'];
166 167
            const params: HttpParams = new HttpParams().set('last_update_time', lastUpdateTimeMS.toString());
            HelperService.makeGetRequest(this.http, this.toastCtrl, url, params).then((data: object) => {
168
                if (data) {
169 170 171 172
                    const corpusList: CorpusMC[] = data['corpora'] as CorpusMC[];
                    window.localStorage.setItem(HelperService.config['localStorageKeyCorpora'], JSON.stringify(corpusList));
                    const updateInfo: object = {corpora: {lastAccessTime: new Date().getTime()}};
                    window.localStorage.setItem(HelperService.config['localStorageKeyUpdateInfo'], JSON.stringify(updateInfo));
173
                    this.processCorpora(corpusList);
174
                    return resolve();
175
                } else {
176
                    this.loadCorporaFromLocalStorage();
177
                    return resolve();
178
                }
179
            }, async (error: HttpErrorResponse) => {
180
                this.loadCorporaFromLocalStorage();
181
                const toast = await this.toastCtrl.create({
182 183 184 185 186
                    message: this.corporaUnavailableString,
                    duration: 3000,
                    position: 'top'
                });
                toast.present().then();
187
                return reject(error);
188
            });
189
        });
190 191
    }

192 193 194 195 196 197 198 199 200 201
    getCTStextPassage(urn: string): Promise<AnnisResponse> {
        return new Promise(((resolve, reject) => {
            const url = HelperService.config['backendBaseUrl'] + HelperService.config['backendApiRawtextPath'];
            const params: HttpParams = new HttpParams().set('urn', urn);
            HelperService.makeGetRequest(this.http, this.toastCtrl, url, params).then((ar: AnnisResponse) => {
                return resolve(ar);
            }, (error: HttpErrorResponse) => {
                return reject(error);
            });
        }));
202 203
    }

204 205 206 207 208 209 210 211 212 213
    getCTSvalidReff(urn: string): Promise<string[]> {
        return new Promise((resolve, reject) => {
            const fullUrl: string = HelperService.config['backendBaseUrl'] + HelperService.config['backendApiValidReffPath'];
            const params: HttpParams = new HttpParams().set('urn', urn);
            HelperService.makeGetRequest(this.http, this.toastCtrl, fullUrl, params).then((reff: string[]) => {
                resolve(reff);
            }, (error: HttpErrorResponse) => {
                reject(error);
            });
        });
214 215
    }

216 217 218 219 220
    getFrequencyAnalysis() {
        return new Promise((resolve, reject) => {
            if (this.annisResponse.frequency_analysis.length) {
                return resolve();
            } else {
221 222 223
                const url: string = HelperService.config['backendBaseUrl'] + HelperService.config['backendApiFrequencyPath'];
                const params: HttpParams = new HttpParams().set('urn', this.currentUrn);
                HelperService.makeGetRequest(this.http, this.toastCtrl, url, params).then((fis: FrequencyItem[]) => {
224 225
                    HelperService.isLoading = false;
                    this.annisResponse.frequency_analysis = fis;
226 227 228 229
                    HelperService.applicationState.pipe(take(1)).subscribe((as: ApplicationState) => {
                        as.mostRecentSetup.annisResponse = this.annisResponse;
                        this.helperService.saveApplicationState(as).then();
                    });
230
                    return resolve();
231
                }, () => {
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
                    return reject();
                });
            }
        });
    }

    getSortedQueryValues(query: QueryMC, queryIndex: number): string[] {
        const pmc: PhenomenonMapContent = this.phenomenonMap[query.phenomenon];
        if (this.exercise.type === ExerciseType.matching) {
            if (queryIndex) {
                const relevantFIs: FrequencyItem[] = this.annisResponse.frequency_analysis.filter(
                    x => x.values[0] === this.exercise.queryItems[0].values[0] &&
                        x.phenomena[1] === query.phenomenon.toString());
                return Array.from(new Set<string>(relevantFIs.map(x => x.values[1]))).sort((a, b) => {
                    return a === b ? 0 : (pmc.translationValues[a] < pmc.translationValues[b] ? -1 : 1);
                });
            } else {
                const relevantFIs: FrequencyItem[] = this.annisResponse.frequency_analysis.filter(
                    x => x.phenomena[0] === query.phenomenon.toString());
                return Array.from(new Set<string>(relevantFIs.map(x => x.values[0]))).sort((a, b) => {
                    return a === b ? 0 : (pmc.translationValues[a] < pmc.translationValues[b] ? -1 : 1);
                });
            }
        }
        if (!pmc.specificValues) {
            return [];
        }
        return Object.keys(pmc.specificValues).sort((a, b) => {
            return a === b ? 0 : (pmc.translationValues[a] < pmc.translationValues[b] ? -1 : 1);
Konstantin Schulz's avatar
Konstantin Schulz committed
261 262 263
        });
    }

264
    getText(saveToCache: boolean = true): Promise<void> {
265 266 267
        return new Promise((resolve, reject) => {
            this.currentText = '';
            if (HelperService.isVocabularyCheck) {
268
                return resolve();
269
            } else {
270
                this.getCTStextPassage(this.currentUrn).then((ar: AnnisResponse) => {
271
                    this.processAnnisResponse(ar, saveToCache);
272
                    return resolve();
273
                }, async (error: HttpErrorResponse) => {
274
                    return reject(error);
275 276 277 278 279 280
                });
            }
        });
    }

    getTranslations() {
281
        this.translate.get('ERROR_CORPORA_UNAVAILABLE').subscribe(value => this.corporaUnavailableString = value);
282 283 284 285 286 287 288 289 290 291
        this.translate.get('EXERCISE_FEEDBACK_CORRECT_DEFAULT').subscribe(value => this.exercise.feedback.correct = value);
        this.translate.get('EXERCISE_FEEDBACK_INCORRECT_DEFAULT').subscribe(value => this.exercise.feedback.incorrect = value);
        this.translate.get('EXERCISE_FEEDBACK_PARTIALLY_CORRECT_DEFAULT').subscribe((value) => {
            this.exercise.feedback.partiallyCorrect = value;
        });
        this.translate.get('EXERCISE_FEEDBACK_GENERAL_DEFAULT').subscribe(value => this.exercise.feedback.general = value);
        this.translate.get(ExerciseTypeTranslation[ExerciseType.cloze]).subscribe(value => this.exercise.typeTranslation = value);
        this.translate.get(InstructionsTranslation[ExerciseType.cloze]).subscribe((value) => {
            this.exercise.instructionsTranslation = value;
        });
292 293
        this.translate.get('INVALID_TEXT_RANGE').subscribe(value => this.invalidTextRangeString = value);
        this.translate.get('ERROR_CITATIONS_UNAVAILABLE').subscribe(value => this.citationsUnavailableString = value);
294
        this.translate.get('LINK_COPIED').subscribe(value => this.shareLinkCopiedString = value);
295 296
    }

297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
    initCurrentCorpus(): void {
        this.currentCorpus = new ReplaySubject<CorpusMC>(1);
        if (!this.currentCorpusCache) {
            HelperService.applicationState.subscribe((as: ApplicationState) => {
                const textData: TextData = as.currentSetup ? as.currentSetup : as.mostRecentSetup;
                this.currentCorpusCache = textData ? textData.currentCorpus : null;
                this.currentCorpus.next(this.currentCorpusCache);
            });
        } else {
            this.currentCorpus.next(this.currentCorpusCache);
        }
    }

    initCurrentTextRange(): void {
        this.currentTextRange = new ReplaySubject<TextRange>(1);
        HelperService.applicationState.pipe(take(1)).subscribe((state: ApplicationState) => {
            this.currentTextRangeCache = state.currentSetup.currentTextRange;
            this.currentTextRange.next(this.currentTextRangeCache);
        });
    }

318 319
    initPhenomenonMap() {
        // map the different phenomena to their respective Enum for processing and display/translation
Konstantin Schulz's avatar
Konstantin Schulz committed
320 321
        Object.keys(Phenomenon).forEach((key) => {
            if (key !== Phenomenon[Phenomenon.lemma]) {
322 323 324
                const pmc: PhenomenonMapContent = this.phenomenonMap[key];
                pmc.translationValues = {};
                const translationObject: object = pmc.translationObject;
Konstantin Schulz's avatar
Konstantin Schulz committed
325 326
                Object.keys(translationObject).forEach((k: string) => {
                    if (k !== k.toUpperCase()) {
327
                        this.translate.get(translationObject[k]).subscribe(v => pmc.translationValues[k] = v);
Konstantin Schulz's avatar
Konstantin Schulz committed
328 329 330 331
                    }
                });
            }
        });
332 333
    }

334
    isTreebank(corpus: CorpusMC) {
335
        return corpus.source_urn.includes('proiel');
336 337
    }

338
    public loadCorporaFromLocalStorage() {
339 340 341
        const storedCorporaJSONstring: string = window.localStorage.getItem(HelperService.config['localStorageKeyCorpora']);
        if (storedCorporaJSONstring) {
            const corpusList: CorpusMC[] = JSON.parse(storedCorporaJSONstring) as CorpusMC[];
342 343 344 345
            this.processCorpora(corpusList);
        }
    }

346
    processAnnisResponse(ar: AnnisResponse, saveToCache: boolean = true) {
347 348 349
        Object.keys(this.phenomenonMap).forEach((key: string) => {
            const pmc: PhenomenonMapContent = this.phenomenonMap[key];
            pmc.specificValues = {};
350
        });
351 352
        this.phenomenonMap.lemma.translationValues = {};
        this.processNodes(ar);
353
        const pointingLinks: LinkMC[] = ar.links.filter(x => x.annis_component_type === 'Pointing');
354 355 356
        pointingLinks.forEach((link: LinkMC) => {
            const dep: DependencyValue = HelperService.dependencyMap[link.udep_deprel];
            if (dep) {
357 358
                const existingValue = this.phenomenonMap.dependency.specificValues[dep];
                this.phenomenonMap.dependency.specificValues[dep] = (existingValue ? existingValue : 0) + 1;
359 360 361
            }
        });
        // need to add root dependencies manually because they are tricky to handle
362
        const nodeIds: string[] = ar.nodes.map(x => x.id);
363 364
        const nodesWithDependencySet: Set<string> = new Set<string>(pointingLinks.map(x => x.target));
        const rootNodeIds: string[] = nodeIds.filter(x => !nodesWithDependencySet.has(x));
365 366
        this.phenomenonMap.dependency.specificValues[DependencyValue.root] = rootNodeIds.length;
        this.adjustQueryValue(this.exercise.queryItems[0], 0);
Konstantin Schulz's avatar
Konstantin Schulz committed
367
        // remove whitespace before punctuation
368
        this.currentText = ar.nodes.map(x => x.annis_tok).join(' ').replace(/[ ]([.,\/#!$%\^&\*;:{}=\-_`~()])/g, (x: string) => {
Konstantin Schulz's avatar
Konstantin Schulz committed
369 370
            return x.trim();
        });
371 372
        this.annisResponse = ar;
        if (saveToCache) {
373 374 375 376 377
            HelperService.applicationState.pipe(take(1)).subscribe((as: ApplicationState) => {
                as.currentSetup.currentUrn = this.currentUrn;
                as.currentSetup.annisResponse = ar;
                this.helperService.saveApplicationState(as).then();
            });
378
        }
379 380
    }

381
    processCorpora(corpusList: CorpusMC[]) {
382 383
        this.availableCorpora = [];
        this.availableAuthors = [];
384
        corpusList.forEach((corpus: CorpusMC) => {
385
            corpus.citations = {};
386
            this.availableCorpora.push(corpus);
387
            if (this.isTreebank(corpus)) {
388
                corpus.author += ' (PROIEL)';
389
            }
390
            const existingAuthor: Author = this.availableAuthors.find(author => author.name === corpus.author);
391 392
            if (existingAuthor) {
                existingAuthor.corpora.push(corpus);
393
            } else {
394 395 396 397 398 399 400 401 402
                this.availableAuthors.push(new Author({
                    name: corpus.author,
                    corpora: [corpus]
                }));
            }
        });
        this.availableAuthors.sort((author1, author2) => {
            if (author1.name < author2.name) {
                return -1;
403
            } else if (author1.name > author2.name) {
404 405 406 407 408 409 410
                return 1;
            }
            return 0;
        });
        this.availableAuthors.forEach((author) => {
            author.corpora.sort((corpus1, corpus2) => {
                if (corpus1.title < corpus2.title) {
Konstantin Schulz's avatar
Konstantin Schulz committed
411
                    return -1;
412
                } else if (corpus1.title > corpus2.title) {
Konstantin Schulz's avatar
Konstantin Schulz committed
413 414 415 416 417 418
                    return 1;
                }
                return 0;
            });
        });
    }
419

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
    processNodes(ar: AnnisResponse) {
        ar.nodes.forEach((node: NodeMC) => {
            let existingValue = this.phenomenonMap.lemma.specificValues[node.udep_lemma];
            this.phenomenonMap.lemma.specificValues[node.udep_lemma] = (existingValue ? existingValue : 0) + 1;
            this.phenomenonMap.lemma.translationValues[node.udep_lemma] = node.udep_lemma;
            if (node.udep_feats) {
                const featsParts: string[] = node.udep_feats.split('|');
                const casePart: string = featsParts.find(x => x.toLowerCase().includes(Phenomenon[Phenomenon.case]));
                if (casePart) {
                    const caseAbbreviation: string = casePart.split('=')[1];
                    const caseValue: CaseValue = HelperService.caseMap[caseAbbreviation];
                    existingValue = this.phenomenonMap.case.specificValues[caseValue];
                    this.phenomenonMap.case.specificValues[caseValue] = (existingValue ? existingValue : 0) + 1;
                }
            }
            const pos: PartOfSpeechValue = HelperService.partOfSpeechMap[node.udep_upostag];
            existingValue = this.phenomenonMap.partOfSpeech.specificValues[pos];
            this.phenomenonMap.partOfSpeech.specificValues[pos] = (existingValue ? existingValue : 0) + 1;
        });
    }

441
    restoreLastCorpus() {
442
        return new Promise((resolve, reject) => {
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
            HelperService.applicationState.pipe(take(1)).subscribe((state: ApplicationState) => {
                this.annisResponse = state.mostRecentSetup.annisResponse;
                this.currentUrn = state.mostRecentSetup.currentUrn;
                this.currentCorpusCache = state.mostRecentSetup.currentCorpus;
                this.currentTextRangeCache = state.mostRecentSetup.currentTextRange;
                this.isTextRangeCorrect = true;
                if (this.annisResponse && this.annisResponse.nodes.length) {
                    this.processAnnisResponse(this.annisResponse, false);
                    return resolve();
                } else if (this.currentText) {
                    // check if the data is already present
                    return resolve();
                } else {
                    const saveToCache: boolean = !state.mostRecentSetup.annisResponse || !state.mostRecentSetup.annisResponse.nodes.length;
                    this.getText(saveToCache).then(() => {
                        return resolve();
                    }, () => {
                        return reject();
                    });
                }
463 464
            });
        });
465
    }
466

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
    saveNewCorpus(corpus: CorpusMC): void {
        this.currentCorpusCache = corpus;
        this.currentCorpus.next(this.currentCorpusCache);
        this.setCurrentTextRange(-1, null, new TextRange({start: ['', '', ''], end: ['', '', '']}));
        HelperService.applicationState.pipe(take(1)).subscribe((state: ApplicationState) => {
            state.currentSetup.currentCorpus = corpus;
            HelperService.applicationState.next(state);
        });
    }

    setCurrentTextRange(inputId: number = -1, newValue: string = null, tr: TextRange = null): void {
        if (tr) {
            this.currentTextRangeCache = tr;
        } else if (inputId >= 0) {
            const isStart: boolean = inputId < 4;
            const targetInputId = `input${inputId}`;
            if (newValue === null) {
                newValue = document.querySelector<HTMLInputElement>(`#${targetInputId}`).value;
            }
            const trIdx: number = inputId - (isStart ? 1 : 4);
            const relevantTextRangePart: string[] = isStart ? this.currentTextRangeCache.start : this.currentTextRangeCache.end;
            relevantTextRangePart[trIdx] = newValue;
        }
        this.currentTextRange.next(this.currentTextRangeCache);
    }

493
    updateBaseWord(query: QueryMC, queryIndex: number) {
494
        if (!this.annisResponse || !this.annisResponse.frequency_analysis || !this.annisResponse.frequency_analysis.length) {
495 496 497 498 499 500 501 502 503 504 505 506
            return;
        }
        if (!queryIndex && this.exercise.type === ExerciseType.matching) {
            if (!this.getSortedQueryValues(this.exercise.queryItems[1], 1).length) {
                const fi: FrequencyItem = this.annisResponse.frequency_analysis.find(
                    x => x.values[0] === this.exercise.queryItems[0].values[0]);
                this.exercise.queryItems[1].phenomenon = Phenomenon[fi.phenomena[1]];
            }
            this.adjustQueryValue(this.exercise.queryItems[1], 1);
        }
    }

Konstantin Schulz's avatar
Konstantin Schulz committed
507
}