Commit b98bed42 authored by Konstantin Schulz's avatar Konstantin Schulz

fixed a bug where the frequency analysis data for matching exercises would be deleted

parent abc6d52e
Pipeline #15736 passed with stages
in 2 minutes and 45 seconds
x=$(git tag --points-at HEAD)
echo "export const version = '${x}';" > mc_frontend/src/version.ts
python ./mc_frontend/update_version.py
docker-compose build
docker-compose down
docker-compose up -d
......@@ -30,6 +30,7 @@ class Config(object):
-1] == "mcserver" else MC_SERVER_DIRECTORY
IS_DOCKER = os.environ.get("IS_THIS_A_DOCKER_CONTAINER", False)
MC_FRONTEND_DIRECTORY = os.path.join(Path(MC_SERVER_DIRECTORY).parent.parent, "mc_frontend")
MC_FRONTEND_SRC_DIRECTORY = os.path.join(MC_FRONTEND_DIRECTORY, "src")
ASSETS_DIRECTORY = os.path.join(MC_SERVER_APP_DIRECTORY, "assets")
FILES_DIRECTORY = os.path.join(MC_SERVER_APP_DIRECTORY, "files")
TMP_DIRECTORY = os.path.join(FILES_DIRECTORY, "tmp")
......@@ -97,7 +98,7 @@ class Config(object):
FLASK_MIGRATE = "migrate"
GRAPHANNIS_DEPENDENCY_LINK = "dep"
GRAPHANNIS_LOG_PATH = os.path.join(os.getcwd(), "graphannis.log")
H5P_DIRECTORY = "/home/mc/h5p" if IS_DOCKER else os.path.join(MC_FRONTEND_DIRECTORY, "src", "assets", "h5p")
H5P_DIRECTORY = "/home/mc/h5p" if IS_DOCKER else os.path.join(MC_FRONTEND_SRC_DIRECTORY, "assets", "h5p")
# Windows: use 127.0.0.1 as host IP fallback
HOST_IP_FALLBACK = "0.0.0.0"
HOST_IP_CSM = DOCKER_SERVICE_NAME_CSM if IS_DOCKER else HOST_IP_FALLBACK
......
......@@ -40,7 +40,7 @@ jmespath==0.9.5
jsonschema==3.2.0
kiwisolver==1.2.0
LinkHeader==0.4.3
lxml==4.5.0
lxml==4.6.2
Mako==1.1.2
MarkupSafe==1.1.1
matplotlib==3.2.1
......
......@@ -23,7 +23,6 @@ from typing import Dict, List, Tuple, Type, Any
from conllu import TokenList
from flask import Flask
from gensim.models import Word2Vec
from graphannis.graph import GraphUpdate
from lxml import etree
from networkx import MultiDiGraph, Graph
from requests import HTTPError
......@@ -38,15 +37,16 @@ from mcserver.app import create_app, db, start_updater, full_init
from mcserver.app.api.exerciseAPI import map_exercise_data_to_database
from mcserver.app.models import ResourceType, FileType, ExerciseType, ExerciseData, \
NodeMC, LinkMC, GraphData, Phenomenon, CustomCorpus, AnnisResponse, Solution, DownloadableFile, Language, \
VocabularyCorpus, TextComplexityMeasure, CitationLevel, FrequencyItem, TextComplexity, Dependency, PartOfSpeech, \
Choice, XapiStatement, ExerciseMC, CorpusMC, make_solution_element_from_salt_id, Sentence, ReferenceableText
from mcserver.app.services import AnnotationService, CorpusService, FileService, CustomCorpusService, DatabaseService, \
XMLservice, TextService, FrequencyService, ExerciseService
VocabularyCorpus, TextComplexityMeasure, CitationLevel, FrequencyItem, TextComplexity, Dependency, \
PartOfSpeech, Choice, XapiStatement, ExerciseMC, CorpusMC, make_solution_element_from_salt_id, Sentence, \
ReferenceableText
from mcserver.app.services import AnnotationService, CorpusService, FileService, CustomCorpusService, \
DatabaseService, XMLservice, TextService, FrequencyService, ExerciseService
from mcserver.config import TestingConfig, Config
from mcserver.models_auto import Corpus, Exercise, UpdateInfo, LearningResult
from mocks import Mocks, MockResponse, MockW2V, MockQuery, TestHelper
from openapi.openapi_server.models import VocabularyForm, VocabularyMC, TextComplexityForm, ExerciseForm, KwicForm, \
VectorNetworkForm, MatchingExercise, ExerciseTypePath, H5PForm
from openapi.openapi_server.models import VocabularyForm, VocabularyMC, TextComplexityForm, ExerciseForm, \
KwicForm, VectorNetworkForm, MatchingExercise, ExerciseTypePath, H5PForm
class McTestCase(unittest.TestCase):
......
......@@ -5,7 +5,7 @@
"homepage": "https://ionicframework.com/",
"scripts": {
"ng": "ng",
"start": "ng serve --port 8100",
"start": "python update_version.py && ng serve --port 8100",
"build": "ng build",
"test-ci": "ng test --code-coverage --watch=false",
"test-cov": "ng test --code-coverage --watch=true",
......
......@@ -8,7 +8,7 @@
</div>
</ion-buttons>
<ion-spinner *ngIf="helperService.openRequests.length"></ion-spinner>
<ion-title *ngIf="helperService.applicationState | async as state">{{ state.currentSetup.currentAuthor?.name }}</ion-title>
<ion-title *ngIf="helperService.applicationState | async as state">{{ state.mostRecentSetup.currentAuthor?.name }}</ion-title>
<ion-buttons slot="end">
<ion-menu-button autoHide="false">
<ion-icon name="menu"></ion-icon>
......@@ -20,7 +20,7 @@
<ion-content class="ion-padding">
<ion-list *ngIf="helperService.applicationState | async as state">
<ion-item *ngFor="let corpus of state.currentSetup.currentAuthor?.corpora">
<ion-item *ngFor="let corpus of state.mostRecentSetup.currentAuthor?.corpora">
<button (click)="showPossibleReferences(corpus)">
<span>{{corpus.title}}</span>
</button>
......
......@@ -95,7 +95,7 @@ export class AuthorPage implements OnInit {
showCorpora(author: Author): void {
this.corpusService.currentAuthor = author;
this.helperService.applicationState.pipe(take(1)).subscribe((as: ApplicationState) => {
as.currentSetup.currentAuthor = author;
as.mostRecentSetup.currentAuthor = author;
this.helperService.saveApplicationState(as).then();
this.helperService.goToPage(this.navCtrl, configMC.pageUrlAuthorDetail).then();
});
......
import {fakeAsync, flushMicrotasks, TestBed} from '@angular/core/testing';
import {TestBed} from '@angular/core/testing';
import {CorpusService} from './corpus.service';
import {IonicStorageModule} from '@ionic/storage';
......@@ -19,10 +19,9 @@ import {CorpusMC} from './models/corpusMC';
import {Author} from './models/author';
import {take} from 'rxjs/operators';
import {TextRange} from './models/textRange';
import Spy = jasmine.Spy;
import {AnnisResponse, NodeMC} from '../../openapi';
import {Phenomenon} from '../../openapi';
import {AnnisResponse, NodeMC, Phenomenon} from '../../openapi';
import {ReplaySubject, Subscription} from 'rxjs';
import Spy = jasmine.Spy;
describe('CorpusService', () => {
let httpClient: HttpClient;
......@@ -51,7 +50,9 @@ describe('CorpusService', () => {
it('should adjust translations', (done) => {
spyOn(corpusService.helperService, 'makeGetRequest').and.returnValue(Promise.resolve(MockMC.apiResponseFrequencyAnalysisGet));
spyOn(corpusService, 'getSortedQueryValues').and.returnValue([PartOfSpeechValue.adjective.toString()]);
spyOn(corpusService, 'getSortedQueryValues').and.callFake((query: QueryMC, queryIndex: number) => {
query.availableValues = [PartOfSpeechValue.adjective];
});
corpusService.helperService.applicationState.next(
corpusService.helperService.deepCopy(MockMC.applicationState) as ApplicationState);
corpusService.exercise.type = ExerciseType.matching;
......@@ -79,22 +80,16 @@ describe('CorpusService', () => {
stateSpy.and.returnValue(state.pipe(take(1)));
corpusService.annisResponse = undefined;
corpusService.checkAnnisResponse().then(() => {
}, () => {
}, async () => {
expect(corpusService.annisResponse).toBeFalsy();
state = new ReplaySubject<ApplicationState>();
state.next(corpusService.helperService.deepCopy(MockMC.applicationState) as ApplicationState);
stateSpy.and.returnValue(state.pipe(take(1)));
corpusService.checkAnnisResponse().then(() => {
expect(corpusService.annisResponse).toBeTruthy();
corpusService.checkAnnisResponse().then(() => {
expect(corpusService.annisResponse).toBeTruthy();
done();
}, () => {
console.log('FOURTH CHECK FAILED');
});
}, () => {
console.log('THIRD CHECK FAILED');
});
await corpusService.checkAnnisResponse();
expect(corpusService.annisResponse).toBeTruthy();
await corpusService.checkAnnisResponse();
expect(corpusService.annisResponse).toBeTruthy();
done();
});
});
});
......@@ -193,13 +188,13 @@ describe('CorpusService', () => {
it('should get sorted query values', () => {
corpusService.exercise.type = ExerciseType.cloze;
const query: QueryMC = new QueryMC({phenomenon: Phenomenon.Upostag});
let result: string[] = corpusService.getSortedQueryValues(query, 0);
expect(result.length).toBe(0);
corpusService.getSortedQueryValues(query, 0);
expect(query.availableValues.length).toBe(0);
const pmc: PhenomenonMapContent = corpusService.phenomenonMap[query.phenomenon];
pmc.specificValues = {a: 0, b: 1, c: 2};
pmc.translationValues = {a: 'a', b: 'c', c: 'b'};
result = corpusService.getSortedQueryValues(query, 0);
expect(result.length).toBe(3);
corpusService.getSortedQueryValues(query, 0);
expect(query.availableValues.length).toBe(3);
corpusService.exercise.type = ExerciseType.matching;
corpusService.annisResponse = {
frequency_analysis: [{
......@@ -213,14 +208,14 @@ describe('CorpusService', () => {
phenomena: [Phenomenon.Upostag, Phenomenon.Upostag]
}]
};
result = corpusService.getSortedQueryValues(query, 1);
expect(result.length).toBe(3);
corpusService.getSortedQueryValues(query, 1);
expect(query.availableValues.length).toBe(3);
corpusService.annisResponse.frequency_analysis.forEach(fi => fi.phenomena = [Phenomenon.Upostag]);
corpusService.annisResponse.frequency_analysis[0].values[0] = 'a';
corpusService.annisResponse.frequency_analysis[1].values[0] = 'b';
corpusService.annisResponse.frequency_analysis[2].values[0] = 'c';
result = corpusService.getSortedQueryValues(query, 0);
expect(result.length).toBe(3);
corpusService.getSortedQueryValues(query, 0);
expect(query.availableValues.length).toBe(3);
});
it('should get text', (done) => {
......@@ -267,33 +262,38 @@ describe('CorpusService', () => {
});
});
it('should initialize the current corpus', fakeAsync(() => {
corpusService.helperService.applicationState.next(new ApplicationState());
it('should initialize the current corpus', ((done) => {
corpusService.helperService.applicationState.next(new ApplicationState({mostRecentSetup: new TextData()}));
let corpus: CorpusMC = {source_urn: ''};
const subscriptions: Subscription[] = [];
function initCorpus(): void {
subscriptions.forEach((sub: Subscription, idx: number, subList: Subscription[]) => {
sub.unsubscribe();
delete subList[idx];
});
corpusService.initCurrentCorpus().then(() => {
subscriptions.push(corpusService.currentCorpus.subscribe((cc: CorpusMC) => {
corpus = cc;
}));
function initCorpus(): Promise<void> {
return new Promise<void>(resolve => {
subscriptions.forEach((sub: Subscription, idx: number, subList: Subscription[]) => {
sub.unsubscribe();
delete subList[idx];
});
corpusService.initCurrentCorpus().then(() => {
subscriptions.push(corpusService.currentCorpus.subscribe((cc: CorpusMC) => {
corpus = cc;
return resolve();
}));
});
});
flushMicrotasks();
}
initCorpus();
// first subscription will not resolve because the current corpus is null
initCorpus().then();
expect(corpus.source_urn).toBeFalsy();
corpusService.helperService.applicationState.next(
corpusService.helperService.deepCopy(MockMC.applicationState) as ApplicationState);
initCorpus();
expect(corpus.source_urn).toBeTruthy();
corpus = undefined;
initCorpus();
expect(corpus).toBeTruthy();
initCorpus().then(async () => {
expect(corpus.source_urn).toBeTruthy();
corpus = undefined;
await initCorpus();
expect(corpus).toBeTruthy();
done();
});
}));
it('should load corpora from local storage', (done) => {
......@@ -417,14 +417,14 @@ describe('CorpusService', () => {
it('should update the base word', () => {
const adjustSpy: Spy = spyOn(corpusService, 'adjustQueryValue');
const queryValuesSpy: Spy = spyOn(corpusService, 'getSortedQueryValues').and.returnValue([]);
const queryValuesSpy: Spy = spyOn(corpusService, 'getSortedQueryValues');
corpusService.annisResponse = {
frequency_analysis: corpusService.helperService.deepCopy(MockMC.apiResponseFrequencyAnalysisGet)
};
corpusService.annisResponse.frequency_analysis[0].phenomena.push(Phenomenon.Feats);
corpusService.exercise.type = ExerciseType.matching;
corpusService.exercise.queryItems.push(new QueryMC());
corpusService.updateBaseWord(new QueryMC(), 0);
corpusService.exercise.queryItems.push(new QueryMC({selectedValues: []}));
corpusService.updateBaseWord(corpusService.exercise.queryItems.slice(-1)[0], 0);
expect(adjustSpy).toHaveBeenCalledTimes(1);
expect(queryValuesSpy).toHaveBeenCalledTimes(1);
expect(corpusService.exercise.queryItems[1].phenomenon).toBe(Phenomenon.Feats);
......
......@@ -25,7 +25,6 @@ import {PhenomenonMap, PhenomenonMapContent} from 'src/app/models/phenomenonMap'
import {ReplaySubject} from 'rxjs';
import {ApplicationState} from './models/applicationState';
import {take} from 'rxjs/operators';
import {TextData} from './models/textData';
import {Storage} from '@ionic/storage';
import {UpdateInfo} from './models/updateInfo';
import configMC from '../configMC';
......@@ -58,8 +57,9 @@ export class CorpusService {
type: ExerciseType.cloze,
typeTranslation: '',
queryItems: [new QueryMC({
availableValues: [],
phenomenon: Phenomenon.Upostag,
values: [PartOfSpeechValue.adjective],
selectedValues: [PartOfSpeechValue.adjective],
})],
feedback: new Feedback({general: '', incorrect: '', partiallyCorrect: '', correct: ''}),
instructionsTranslation: ''
......@@ -75,6 +75,7 @@ export class CorpusService {
lemma: new PhenomenonMapContent({translationObject: null}),
upostag: new PhenomenonMapContent({translationObject: PartOfSpeechTranslation})
});
public previewAnnisResponse: AnnisResponse;
public searchRegexMissingString: string;
public shareLinkCopiedString: string;
public textTooLongString: string;
......@@ -89,8 +90,9 @@ export class CorpusService {
}
adjustQueryValue(query: QueryMC, queryIndex: number): void {
this.getSortedQueryValues(query, queryIndex);
// when the phenomenon changes, choose the first value from the translated list as the default
query.values = [this.getSortedQueryValues(query, queryIndex)[0]];
query.selectedValues = query.availableValues.slice(0, 1);
this.updateBaseWord(query, queryIndex);
}
......@@ -103,8 +105,8 @@ export class CorpusService {
value => this.exercise.instructionsTranslation = value);
}
if (this.exercise.type === ExerciseType.matching) {
this.exercise.queryItems = [new QueryMC({phenomenon: Phenomenon.Upostag, values: []}),
new QueryMC({phenomenon: Phenomenon.Upostag, values: []})];
this.exercise.queryItems = [new QueryMC({phenomenon: Phenomenon.Upostag, selectedValues: []}),
new QueryMC({phenomenon: Phenomenon.Upostag, selectedValues: []})];
this.getFrequencyAnalysis().then(() => {
this.adjustQueryValue(this.exercise.queryItems[0], 0);
this.adjustQueryValue(this.exercise.queryItems[1], 1);
......@@ -119,10 +121,11 @@ export class CorpusService {
checkAnnisResponse(): Promise<void> {
return new Promise((resolve, reject) => {
if (this.annisResponse) {
if (this.annisResponse && this.previewAnnisResponse) {
return resolve();
}
this.helperService.applicationState.pipe(take(1)).subscribe((state: ApplicationState) => {
this.previewAnnisResponse = state.previewAnnisResponse;
this.annisResponse = state.mostRecentSetup.annisResponse;
this.currentAuthor = state.mostRecentSetup.currentAuthor;
this.currentUrn = state.mostRecentSetup.currentUrn;
......@@ -215,7 +218,7 @@ export class CorpusService {
getFrequencyAnalysis(): Promise<void> {
return new Promise((resolve, reject) => {
if (this.annisResponse.frequency_analysis.length) {
if (this.annisResponse.frequency_analysis && this.annisResponse.frequency_analysis.length) {
return resolve();
} else {
const url: string = configMC.backendBaseUrl + configMC.backendApiFrequencyPath;
......@@ -234,30 +237,36 @@ export class CorpusService {
});
}
getSortedQueryValues(query: QueryMC, queryIndex: number): string[] {
getSortedQueryValues(query: QueryMC, queryIndex: number): void {
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 => x.values[0] === this.exercise.queryItems[0].selectedValues[0] &&
x.phenomena[1] === query.phenomenon);
return Array.from(new Set<string>(relevantFIs.map(x => x.values[1]))).sort((a, b) => {
return pmc.translationValues[a] < pmc.translationValues[b] ? -1 : 1;
});
query.availableValues = Array.from(new Set<string>(relevantFIs.map(x => x.values[1])))
.sort((a, b) => {
return pmc.translationValues[a] < pmc.translationValues[b] ? -1 : 1;
});
return;
} else {
const relevantFIs: FrequencyItem[] = this.annisResponse.frequency_analysis.filter(
x => x.phenomena[0] === query.phenomenon);
return Array.from(new Set<string>(relevantFIs.map(x => x.values[0]))).sort((a, b) => {
return pmc.translationValues[a] < pmc.translationValues[b] ? -1 : 1;
});
query.availableValues = Array.from(new Set<string>(relevantFIs.map(x => x.values[0])))
.sort((a, b) => {
return pmc.translationValues[a] < pmc.translationValues[b] ? -1 : 1;
});
return;
}
}
if (!pmc.specificValues) {
return [];
query.availableValues = [];
return;
}
return Object.keys(pmc.specificValues).sort((a, b) => {
query.availableValues = Object.keys(pmc.specificValues).sort((a, b) => {
return pmc.translationValues[a] < pmc.translationValues[b] ? -1 : 1;
});
return;
}
getText(saveToCache: boolean = true): Promise<void> {
......@@ -332,8 +341,8 @@ export class CorpusService {
this.currentCorpus = new ReplaySubject<CorpusMC>(1);
if (!this.currentCorpusCache) {
this.helperService.applicationState.pipe(take(1)).subscribe((state: ApplicationState) => {
const textData: TextData = state.currentSetup ? state.currentSetup : state.mostRecentSetup;
this.currentCorpusCache = textData ? textData.currentCorpus : null;
this.currentCorpusCache = state.mostRecentSetup.currentCorpus ?
state.mostRecentSetup.currentCorpus : null;
if (this.currentCorpusCache) {
this.currentCorpus.next(this.currentCorpusCache);
}
......@@ -349,7 +358,7 @@ export class CorpusService {
initCurrentTextRange(): void {
this.currentTextRange = new ReplaySubject<TextRange>(1);
this.helperService.applicationState.pipe(take(1)).subscribe((state: ApplicationState) => {
this.currentTextRangeCache = state.currentSetup.currentTextRange;
this.currentTextRangeCache = state.mostRecentSetup.currentTextRange;
this.currentTextRange.next(this.currentTextRangeCache);
});
}
......@@ -422,7 +431,6 @@ export class CorpusService {
this.annisResponse = ar;
if (saveToCache) {
this.helperService.applicationState.pipe(take(1)).subscribe((as: ApplicationState) => {
as.currentSetup.annisResponse = null;
as.mostRecentSetup = {
annisResponse: ar,
currentUrn: this.currentUrn,
......@@ -430,10 +438,7 @@ export class CorpusService {
currentCorpus: this.currentCorpusCache,
currentTextRange: this.currentTextRangeCache
};
this.helperService.saveApplicationState(as).then(() => {
as.currentSetup.currentUrn = this.currentUrn;
as.currentSetup.annisResponse = ar;
});
this.helperService.saveApplicationState(as).then();
});
}
}
......@@ -530,7 +535,7 @@ export class CorpusService {
this.currentCorpus.next(this.currentCorpusCache);
this.setCurrentTextRange(-1, null, new TextRange({start: ['', '', ''], end: ['', '', '']}));
this.helperService.applicationState.pipe(take(1)).subscribe((state: ApplicationState) => {
state.currentSetup.currentCorpus = corpus;
state.mostRecentSetup.currentCorpus = corpus;
this.helperService.applicationState.next(state);
});
}
......@@ -556,9 +561,10 @@ export class CorpusService {
return;
}
if (!queryIndex && this.exercise.type === ExerciseType.matching) {
if (!this.getSortedQueryValues(this.exercise.queryItems[1], 1).length) {
this.getSortedQueryValues(this.exercise.queryItems[1], 1);
if (!query.selectedValues.length) {
const fi: FrequencyItem = this.annisResponse.frequency_analysis.find(
x => x.values[0] === this.exercise.queryItems[0].values[0]);
x => x.values[0] === this.exercise.queryItems[0].selectedValues[0]);
this.exercise.queryItems[1].phenomenon = fi.phenomena[1];
}
this.adjustQueryValue(this.exercise.queryItems[1], 1);
......
......@@ -65,9 +65,9 @@
*ngIf="corpusService.exercise.type === ExerciseType.matching; else notMatching">
<label>
<h2 class="label">{{ 'QUERY_VALUE' | translate }}</h2>
<select [(ngModel)]="query.values[0]" name="queryValue"
<select [(ngModel)]="query.selectedValues[0]" name="queryValue"
(change)="corpusService.updateBaseWord(query, i)">
<option *ngFor="let key of corpusService.getSortedQueryValues(query, i)"
<option *ngFor="let key of query.availableValues"
[value]=key>{{ getDisplayValue(query, key, i) }}
</option>
</select>
......@@ -76,9 +76,9 @@
<ng-template #notMatching>
<label>
<h2 class="label">{{ 'QUERY_VALUE' | translate }}</h2>
<select [(ngModel)]="query.values" name="queryValue" multiple
size="{{Math.min(corpusService.getSortedQueryValues(query, i).length, 20)}}">
<option *ngFor="let key of corpusService.getSortedQueryValues(query, i)"
<select [(ngModel)]="query.selectedValues" name="queryValue" multiple
size="{{Math.min(query.availableValues.length, 20)}}">
<option *ngFor="let key of query.availableValues"
[value]=key>{{ getDisplayValue(query, key, i) }}
</option>
</select>
......
......@@ -70,7 +70,7 @@ describe('ExerciseParametersPage', () => {
configMC.maxTextLength = 0;
exerciseParametersPage.corpusService.exercise.queryItems[0].phenomenon = Phenomenon.Lemma;
exerciseParametersPage.corpusService.exercise.type = ExerciseType.matching;
exerciseParametersPage.corpusService.exercise.queryItems.push(new QueryMC({values: []}));
exerciseParametersPage.corpusService.exercise.queryItems.push(new QueryMC({selectedValues: []}));
exerciseParametersPage.generateExercise().then(() => {
}, () => {
expect(h5pSpy).toHaveBeenCalledTimes(1);
......
......@@ -54,8 +54,9 @@ export class ExerciseParametersPage implements OnInit {
if (0 < configMC.maxTextLength && configMC.maxTextLength < this.corpusService.currentText.length) {
this.helperService.showToast(this.toastCtrl, this.corpusService.textTooLongString).then();
return reject();
} else if ((phenomenon === Phenomenon.Lemma && !this.corpusService.exercise.queryItems[0].values) ||
this.corpusService.exercise.type === ExerciseType.matching && !this.corpusService.exercise.queryItems[1].values[0]) {
} else if ((phenomenon === Phenomenon.Lemma && !this.corpusService.exercise.queryItems[0].selectedValues) ||
this.corpusService.exercise.type === ExerciseType.matching &&
!this.corpusService.exercise.queryItems[1].selectedValues[0]) {
this.helperService.showToast(this.toastCtrl, this.corpusService.emptyQueryValueString).then();
return reject();
} else {
......@@ -74,7 +75,7 @@ export class ExerciseParametersPage implements OnInit {
if (this.corpusService.exercise.type === ExerciseType.matching) {
if (queryIndex) {
const relevantFI: FrequencyItem = this.corpusService.annisResponse.frequency_analysis.find(
x => x.values[0] === this.corpusService.exercise.queryItems[0].values[0] && x.values[1] === key);
x => x.values[0] === this.corpusService.exercise.queryItems[0].selectedValues[0] && x.values[1] === key);
count = relevantFI.count;
} else {
const relevantFIs: FrequencyItem[] = this.corpusService.annisResponse.frequency_analysis.filter(
......@@ -90,7 +91,7 @@ export class ExerciseParametersPage implements OnInit {
getExerciseData(): Promise<void> {
return new Promise<void>(resolve => {
const searchValues: string[] = this.corpusService.exercise.queryItems.map(
query => query.phenomenon + '=' + query.values.join('|'));
query => query.phenomenon + '=' + query.selectedValues.join('|'));
let instructions: string = this.corpusService.exercise.instructionsTranslation;
if (this.corpusService.exercise.type === ExerciseType.kwic) {
this.getKwicExercise(JSON.stringify(searchValues)).then();
......@@ -98,7 +99,7 @@ export class ExerciseParametersPage implements OnInit {
} else if (this.corpusService.exercise.type === ExerciseType.markWords) {
const phenomenon: Phenomenon = this.corpusService.exercise.queryItems[0].phenomenon;
const pmc: PhenomenonMapContent = this.corpusService.phenomenonMap[phenomenon];
const values: string[] = this.corpusService.exercise.queryItems[0].values as string[];
const values: string[] = this.corpusService.exercise.queryItems[0].selectedValues as string[];
instructions += ` [${values.map(x => pmc.translationValues[x]).join(', ')}]`;
}
this.corpusService.currentCorpus.pipe(take(1)).subscribe((cc: CorpusMC) => {
......@@ -135,14 +136,12 @@ export class ExerciseParametersPage implements OnInit {
formData.append(key, ef[key]);
});
this.helperService.makePostRequest(this.http, this.toastCtrl, url, formData).then((ar: AnnisResponse) => {
// save the old frequency analysis in case we want to change the exercise parameters at a later time
ar.frequency_analysis = this.corpusService.annisResponse.frequency_analysis;
this.helperService.applicationState.pipe(take(1)).subscribe((as: ApplicationState) => {
as.mostRecentSetup.annisResponse = ar;
as.previewAnnisResponse = this.corpusService.previewAnnisResponse = ar;
this.helperService.saveApplicationState(as).then();
this.corpusService.annisResponse.exercise_id = ar.exercise_id;
this.corpusService.annisResponse.uri = ar.uri;
this.corpusService.annisResponse.solutions = ar.solutions;
// this.corpusService.annisResponse.exercise_id = ar.exercise_id;
// this.corpusService.annisResponse.uri = ar.uri;
// this.corpusService.annisResponse.solutions = ar.solutions;
this.helperService.goToPage(this.navCtrl, configMC.pageUrlPreview).then();
return resolve();
});
......
......@@ -89,13 +89,13 @@ describe('ExerciseService', () => {
expect(postSpy).toHaveBeenCalledTimes(0);
exerciseService.currentExerciseParams = {};
const downloadSpy: Spy = spyOn(exerciseService, 'downloadBlobAsFile');
exerciseService.corpusService.annisResponse = {exercise_id: ''};
exerciseService.corpusService.previewAnnisResponse = {exercise_id: ''};
exerciseService.corpusService.exercise.type = ExerciseType.markWords;
exerciseService.currentExerciseParams = {language: LanguageShortcut.English};
exerciseService.downloadH5Pexercise().then(() => {
expect(downloadSpy).toHaveBeenCalledTimes(1);
exerciseService.corpusService.currentSolutions =
exerciseService.corpusService.annisResponse.solutions = [{
exerciseService.corpusService.previewAnnisResponse.solutions = [{
target: {
token_id: 1,
sentence_id: 1
......@@ -167,7 +167,7 @@ describe('ExerciseService', () => {
it('should get solution indices', () => {