From 8a5816b2d78b314f58afeb49c2ea92df834c3654 Mon Sep 17 00:00:00 2001 From: Ruben Bimberg <ruben.bimberg@mni.thm.de> Date: Mon, 27 Sep 2021 16:33:01 +0200 Subject: [PATCH] Implement sliders for weighting of keywords [Ticket: #665] --- .../TopicCloudAdminData.ts | 126 ++++++++++++++---- .../topic-cloud-administration.component.html | 44 +++++- .../topic-cloud-administration.component.scss | 16 +++ .../topic-cloud-administration.component.ts | 44 +++++- .../shared/tag-cloud/tag-cloud.component.ts | 1 + .../services/util/tag-cloud-data.service.ts | 43 ++---- .../util/topic-cloud-admin.service.ts | 8 +- src/assets/i18n/creator/de.json | 23 +++- src/assets/i18n/creator/en.json | 23 +++- src/assets/i18n/participant/de.json | 23 +++- src/assets/i18n/participant/en.json | 23 +++- 11 files changed, 303 insertions(+), 71 deletions(-) diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts b/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts index 42b959a8f..e0cc85d7b 100644 --- a/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts +++ b/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts @@ -1,5 +1,26 @@ import { ProfanityFilter } from '../../../../models/room'; +export interface TopicCloudAdminDataScoring { + score: number; +} + +export enum TopicCloudAdminDataScoringKey { + countComments = 'countComments', + countUsers = 'countUsers', + countSelectedByQuestioner = 'countSelectedByQuestioner', + countKeywordByModerator = 'countKeywordByModerator', + countKeywordByCreator = 'countKeywordByCreator', + countCommentsAnswered = 'countCommentsAnswered', + summedUpvotes = 'summedUpvotes', + summedDownvotes = 'summedDownvotes', + summedVotes = 'summedVotes', + cappedSummedVotes = 'cappedSummedVotes' +} + +export type TopicCloudAdminDataScoringObject = { + [key in TopicCloudAdminDataScoringKey]: TopicCloudAdminDataScoring; +}; + export interface TopicCloudAdminData { blacklist: string[]; wantedLabels: { @@ -15,8 +36,65 @@ export interface TopicCloudAdminData { minUpvotes: number; startDate: string; endDate: string; + scorings: TopicCloudAdminDataScoringObject; } +export const ensureDefaultScorings = (data: TopicCloudAdminData) => { + if (!data.scorings) { + data.scorings = {} as TopicCloudAdminDataScoringObject; + } + for (const option of Object.keys(TopicCloudAdminDataScoringKey)) { + if (data.scorings[option]) { + continue; + } + switch (option) { + case TopicCloudAdminDataScoringKey.cappedSummedVotes: + data.scorings[option] = { + score: 0.1 + }; + break; + case TopicCloudAdminDataScoringKey.countUsers: + data.scorings[option] = { + score: 0.5 + }; + break; + case TopicCloudAdminDataScoringKey.countCommentsAnswered: + case TopicCloudAdminDataScoringKey.countKeywordByCreator: + case TopicCloudAdminDataScoringKey.countKeywordByModerator: + case TopicCloudAdminDataScoringKey.countSelectedByQuestioner: + data.scorings[option] = { + score: 1 + }; + break; + default: + data.scorings[option] = { + score: 0 + }; + break; + } + } +}; + +export type TopicCloudAdminDataScoringPreset = { + [key in TopicCloudAdminDataScoringKey]: { + min: number; + max: number; + }; +}; + +export const keywordsScoringMinMax: TopicCloudAdminDataScoringPreset = { + countComments: { min: -5, max: 5 }, + countUsers: { min: -5, max: 5 }, + countSelectedByQuestioner: { min: -5, max: 5 }, + countKeywordByModerator: { min: -5, max: 5 }, + countKeywordByCreator: { min: -5, max: 5 }, + countCommentsAnswered: { min: -5, max: 5 }, + summedUpvotes: { min: -5, max: 5 }, + summedDownvotes: { min: -5, max: 5 }, + summedVotes: { min: -5, max: 5 }, + cappedSummedVotes: { min: -5, max: 5 } +}; + export enum KeywordOrFulltext { keyword, fulltext, @@ -40,33 +118,33 @@ export class Labels { } const deLabels: Label[] = [ - {tag: 'sb', label: 'Subjekt', enabledByDefault: true}, - {tag: 'op', label: 'Präpositionalobjekt', enabledByDefault: true}, - {tag: 'og', label: 'Genitivobjekt', enabledByDefault: true}, - {tag: 'da', label: 'Dativobjekt', enabledByDefault: true}, - {tag: 'oa', label: 'Akkusativobjekt', enabledByDefault: true}, - {tag: 'ROOT', label: 'Satzkernelement', enabledByDefault: true}, - {tag: 'pd', label: 'Prädikat', enabledByDefault: false}, - {tag: 'ag', label: 'Genitivattribut', enabledByDefault: false}, - {tag: 'app', label: 'Apposition', enabledByDefault: false}, - {tag: 'nk', label: 'Nomen Kernelement', enabledByDefault: false}, - {tag: 'mo', label: 'Modifikator', enabledByDefault: false}, - {tag: 'cj', label: 'Konjunktor', enabledByDefault: false}, - {tag: 'par', label: 'Klammerzusatz', enabledByDefault: false} + { tag: 'sb', label: 'Subjekt', enabledByDefault: true }, + { tag: 'op', label: 'Präpositionalobjekt', enabledByDefault: true }, + { tag: 'og', label: 'Genitivobjekt', enabledByDefault: true }, + { tag: 'da', label: 'Dativobjekt', enabledByDefault: true }, + { tag: 'oa', label: 'Akkusativobjekt', enabledByDefault: true }, + { tag: 'ROOT', label: 'Satzkernelement', enabledByDefault: true }, + { tag: 'pd', label: 'Prädikat', enabledByDefault: false }, + { tag: 'ag', label: 'Genitivattribut', enabledByDefault: false }, + { tag: 'app', label: 'Apposition', enabledByDefault: false }, + { tag: 'nk', label: 'Nomen Kernelement', enabledByDefault: false }, + { tag: 'mo', label: 'Modifikator', enabledByDefault: false }, + { tag: 'cj', label: 'Konjunktor', enabledByDefault: false }, + { tag: 'par', label: 'Klammerzusatz', enabledByDefault: false } ]; const enLabels: Label[] = [ - {tag: 'nsubj', label: 'Nominal subject', enabledByDefault: true}, - {tag: 'pobj', label: 'Object of preposition', enabledByDefault: true}, - {tag: 'dobj', label: 'Direct object', enabledByDefault: true}, - {tag: 'compound', label: 'Compound', enabledByDefault: true}, - {tag: 'nsubjpass', label: 'Passive nominal subject', enabledByDefault: true}, - {tag: 'ROOT', label: 'Sentence kernel element', enabledByDefault: true}, - {tag: 'nummod', label: 'Numeric modifier', enabledByDefault: false}, - {tag: 'amod', label: 'Adjectival modifier', enabledByDefault: false}, - {tag: 'npadvmod', label: 'Noun phrase as adverbial modifier', enabledByDefault: false}, - {tag: 'conj', label: 'Conjunct', enabledByDefault: false}, - {tag: 'intj', label: 'Interjection', enabledByDefault: false} + { tag: 'nsubj', label: 'Nominal subject', enabledByDefault: true }, + { tag: 'pobj', label: 'Object of preposition', enabledByDefault: true }, + { tag: 'dobj', label: 'Direct object', enabledByDefault: true }, + { tag: 'compound', label: 'Compound', enabledByDefault: true }, + { tag: 'nsubjpass', label: 'Passive nominal subject', enabledByDefault: true }, + { tag: 'ROOT', label: 'Sentence kernel element', enabledByDefault: true }, + { tag: 'nummod', label: 'Numeric modifier', enabledByDefault: false }, + { tag: 'amod', label: 'Adjectival modifier', enabledByDefault: false }, + { tag: 'npadvmod', label: 'Noun phrase as adverbial modifier', enabledByDefault: false }, + { tag: 'conj', label: 'Conjunct', enabledByDefault: false }, + { tag: 'intj', label: 'Interjection', enabledByDefault: false } ]; export const spacyLabels = new Labels(deLabels, enLabels); diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html index 222f911ca..bc7cb8d65 100644 --- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html +++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html @@ -28,11 +28,43 @@ </mat-radio-group> </mat-card> - <mat-card style="background: none; margin-bottom: 10px;"> - <mat-slide-toggle [(ngModel)]="considerVotes"> - {{'topic-cloud-dialog.consider-votes' | translate}} - </mat-slide-toggle> - </mat-card> + <mat-accordion> + <mat-expansion-panel class="color-background margin-top margin-bottom keyword-scoring"> + <mat-expansion-panel-header class="color-background"> + <mat-panel-title> + {{'topic-cloud-dialog.keyword-scoring-header' | translate}} + <mat-icon class="help-explanation" + matTooltip="{{'topic-cloud-dialog.keyword-scoring-header-info' | translate}}">help + </mat-icon> + </mat-panel-title> + </mat-expansion-panel-header> + <ng-container *ngFor="let option of scoringOptions"> + <ars-row fxLayout="row"> + <label + id="keyword-scoring-{{option}}">{{'topic-cloud-dialog.keyword-scoring-' + option | translate}}</label> + <mat-icon class="help-explanation" + matTooltip="{{'topic-cloud-dialog.keyword-scoring-' + option + '-info' | translate}}">help + </mat-icon> + <ars-fill></ars-fill> + <label>{{scorings[option].score}}</label> + </ars-row> + <mat-slider + [min]="scoringMinMax[option].min" + [max]="scoringMinMax[option].max" + [(ngModel)]="scorings[option].score" + [step]="0.1" + [thumbLabel]="true" + aria-labelledby="keyword-scoring-{{option}}"> + </mat-slider> + </ng-container> + <button mat-button class="themeRequirementInput reset" + [disabled]="isDefaultScoring()" + (click)="setDefaultScoring()"> + {{'topic-cloud-dialog.topic-requirement-reset' | translate}} + </button> + </mat-expansion-panel> + </mat-accordion> + <div *ngIf="isCreatorOrMod"> <mat-card style="background: none; margin-bottom: 10px;"> <mat-slide-toggle (change)="showMessage('words-will-be-overwritten', $event.checked)" @@ -339,7 +371,7 @@ <p [ngClass]="{'animation-blink': searchMode}" matTooltip="{{'topic-cloud-dialog.keyword-counter' | translate}}"> {{searchMode ? filteredKeywords.length : - selectedTabIndex === 0 ? keywords.size : blacklistKeywords.length}}</p> + selectedTabIndex === 0 ? keywords.size : blacklistKeywords.length}}</p> </div> <div class="margin-left vertical-center"> <button [ngClass]="{'animation-blink': sortMode!=='alphabetic'}" mat-icon-button [matMenuTriggerFor]="sortMenu"> diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss index d2d701694..1887a1260 100644 --- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss +++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss @@ -186,3 +186,19 @@ mat-dialog-content { color: var(--on-secondary); } } + +.keyword-scoring { + width: 100%; + + mat-slider { + width: 100%; + } +} + +.help-explanation { + width: 1.2em; + height: 1.2em; + line-height: 1.2em; + font-size: 1.2em; + margin: auto 0 auto 0.25em; +} diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts index a21c7bce9..4744be85b 100644 --- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts +++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts @@ -7,7 +7,13 @@ import { TranslateService } from '@ngx-translate/core'; import { LanguageService } from '../../../../services/util/language.service'; import { TopicCloudAdminService } from '../../../../services/util/topic-cloud-admin.service'; import { ProfanityFilterService } from '../../../../services/util/profanity-filter.service'; -import { TopicCloudAdminData, Labels, spacyLabels, KeywordOrFulltext } from './TopicCloudAdminData'; +import { + TopicCloudAdminData, + Labels, + spacyLabels, + KeywordOrFulltext, + TopicCloudAdminDataScoringObject, TopicCloudAdminDataScoringKey, keywordsScoringMinMax, ensureDefaultScorings +} from './TopicCloudAdminData'; import { User } from '../../../../models/user'; import { Comment } from '../../../../models/comment'; import { CommentService } from '../../../../services/http/comment.service'; @@ -60,8 +66,12 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { startDate: string; endDate: string; selectedTabIndex = 0; + scorings: TopicCloudAdminDataScoringObject; + scoringOptions = Object.keys(TopicCloudAdminDataScoringKey); + scoringMinMax = keywordsScoringMinMax; keywords: Map<string, Keyword> = new Map<string, Keyword>(); + defaultScorings: TopicCloudAdminDataScoringObject; private topicCloudAdminData: TopicCloudAdminData; private profanityFilter: boolean; private censorPartialWordsCheck: boolean; @@ -84,6 +94,9 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { this.langService.langEmitter.subscribe(lang => { this.translateService.use(lang); }); + const emptyData = {} as TopicCloudAdminData; + ensureDefaultScorings(emptyData); + this.defaultScorings = emptyData.scorings; } ngOnInit(): void { @@ -194,14 +207,14 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { /** * Returns a lambda which closes the dialog on call. */ - buildCloseDialogActionCallback(): () => void { + buildCloseDialogActionCallback(): () => void { return () => this.ngOnDestroy(); } /** * Returns a lambda which executes the dialog dedicated action on call. */ - buildSaveActionCallback(): () => void { + buildSaveActionCallback(): () => void { return () => this.save(); } @@ -313,7 +326,8 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { minQuestions: minQuestionsVerified, minUpvotes: minUpvotesVerified, startDate: this.startDate.length ? this.startDate : null, - endDate: this.endDate.length ? this.endDate : null + endDate: this.endDate.length ? this.endDate : null, + scorings: this.scorings }; this.topicCloudAdminService.setAdminData(this.topicCloudAdminData, true, this.data.user.role); } @@ -340,6 +354,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { this.minUpvotes = String(this.topicCloudAdminData.minUpvotes); this.startDate = this.topicCloudAdminData.startDate || ''; this.endDate = this.topicCloudAdminData.endDate || ''; + this.scorings = this.topicCloudAdminData.scorings; } } @@ -480,7 +495,7 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { if (this.selectedTabIndex === 0) { const entries = [...this.keywords.entries()]; this.filteredKeywords = entries.filter(([_, keyword]) => - keyword.keyword.toLowerCase().includes(this.searchedKeyword.toLowerCase()) + keyword.keyword.toLowerCase().includes(this.searchedKeyword.toLowerCase()) ).map(e => e[1]); } else { this.filteredKeywords = this.blacklistKeywords.filter(keyword => @@ -595,6 +610,25 @@ export class TopicCloudAdministrationComponent implements OnInit, OnDestroy { return ''; } } + + isDefaultScoring(): boolean { + for (const key of Object.keys(this.defaultScorings)) { + const subObject = this.defaultScorings[key]; + const refSubObject = this.scorings[key]; + for (const subKey in subObject) { + if (subObject[subKey] !== refSubObject[subKey]) { + return false; + } + } + } + return true; + } + + setDefaultScoring() { + for (const key of Object.keys(this.defaultScorings)) { + this.scorings[key] = { ...this.defaultScorings[key] }; + } + } } interface Keyword { diff --git a/src/app/components/shared/tag-cloud/tag-cloud.component.ts b/src/app/components/shared/tag-cloud/tag-cloud.component.ts index 400f2c315..9515eec1b 100644 --- a/src/app/components/shared/tag-cloud/tag-cloud.component.ts +++ b/src/app/components/shared/tag-cloud/tag-cloud.component.ts @@ -392,6 +392,7 @@ export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit { admin.minUpvotes = data.admin.minUpvotes; admin.startDate = data.admin.startDate; admin.endDate = data.admin.endDate; + admin.scorings = data.admin.scorings; data.admin = undefined; this.topicCloudAdmin.setAdminData(admin, false, this.userRole); if (this.deviceInfo.isCurrentlyMobile) { diff --git a/src/app/services/util/tag-cloud-data.service.ts b/src/app/services/util/tag-cloud-data.service.ts index ccfb10d96..f4ddb4012 100644 --- a/src/app/services/util/tag-cloud-data.service.ts +++ b/src/app/services/util/tag-cloud-data.service.ts @@ -74,7 +74,6 @@ export class TagCloudDataService { private _metaDataBus: BehaviorSubject<TagCloudMetaData>; private _commentSubscription = null; private _roomId = null; - private _calcWeightType = TagCloudCalcWeightType.byLength; private _lastFetchedData: TagCloudData = null; private _lastFetchedComments: Comment[] = null; private _lastMetaData: TagCloudMetaData = null; @@ -249,17 +248,6 @@ export class TagCloudDataService { return this._dataBus.value; } - set weightCalcType(type: TagCloudCalcWeightType) { - if (type !== this._calcWeightType) { - this._calcWeightType = type; - this.rebuildTagData(); - } - } - - get weightCalcType(): TagCloudCalcWeightType { - return this._calcWeightType; - } - get demoActive(): boolean { return this._isDemoActive; } @@ -329,7 +317,6 @@ export class TagCloudDataService { private onReceiveAdminData(data: TopicCloudAdminData, update = false) { this._adminData = data; - this._calcWeightType = this._adminData.considerVotes ? TagCloudCalcWeightType.byLengthAndVotes : TagCloudCalcWeightType.byLength; if (update) { this.rebuildTagData(); } @@ -353,21 +340,17 @@ export class TagCloudDataService { } private calculateWeight(tagData: TagCloudDataTagEntry): number { - const value = Math.max(tagData.cachedVoteCount, 0); - const additional = (tagData.distinctUsers.size - 1) * 0.5 + - tagData.commentsByModerators + - tagData.commentsByCreator + - tagData.generatedByQuestionerCount + - tagData.taggedCommentsCount + - tagData.answeredCommentsCount; - switch (this._calcWeightType) { - case TagCloudCalcWeightType.byVotes: - return value + additional; - case TagCloudCalcWeightType.byLengthAndVotes: - return value / 10.0 + tagData.comments.length + additional; - default: - return tagData.comments.length + additional; - } + const scorings = this._adminData.scorings; + return tagData.comments.length * scorings.countComments.score + + tagData.distinctUsers.size * scorings.countUsers.score + + tagData.generatedByQuestionerCount * scorings.countSelectedByQuestioner.score + + tagData.commentsByModerators * scorings.countKeywordByModerator.score + + tagData.commentsByCreator * scorings.countKeywordByCreator.score + + tagData.answeredCommentsCount * scorings.countCommentsAnswered.score + + tagData.cachedUpVotes * scorings.summedUpvotes.score + + tagData.cachedDownVotes * scorings.summedDownvotes.score + + tagData.cachedVoteCount * scorings.summedVotes.score + + Math.max(tagData.cachedVoteCount, 0) * scorings.cappedSummedVotes.score; } private rebuildTagData() { @@ -383,8 +366,8 @@ export class TagCloudDataService { let maxWeight = null; for (const value of data.values()) { value.weight = this.calculateWeight(value); - minWeight = Math.min(value.weight, minWeight || value.weight); - maxWeight = Math.max(value.weight, maxWeight || value.weight); + minWeight = Math.min(value.weight, minWeight === null ? value.weight : minWeight); + maxWeight = Math.max(value.weight, maxWeight === null ? value.weight : maxWeight); } //calculate weight counts and adjusted weights const same = minWeight === maxWeight; diff --git a/src/app/services/util/topic-cloud-admin.service.ts b/src/app/services/util/topic-cloud-admin.service.ts index eea4ab450..9875cef1a 100644 --- a/src/app/services/util/topic-cloud-admin.service.ts +++ b/src/app/services/util/topic-cloud-admin.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@angular/core'; import { + ensureDefaultScorings, KeywordOrFulltext, spacyLabels, TopicCloudAdminData @@ -47,7 +48,8 @@ export class TopicCloudAdminService { minQuestions: admin.minQuestions, minUpvotes: admin.minUpvotes, startDate: admin.startDate, - endDate: admin.endDate + endDate: admin.endDate, + scorings: admin.scorings }; room.tagCloudSettings = JSON.stringify(settings); } @@ -120,9 +122,11 @@ export class TopicCloudAdminService { minQuestions: 1, minUpvotes: 0, startDate: null, - endDate: null + endDate: null, + scorings: null }; } + ensureDefaultScorings(data); return data; } diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json index e0e01240d..8478bd9d4 100644 --- a/src/assets/i18n/creator/de.json +++ b/src/assets/i18n/creator/de.json @@ -416,7 +416,28 @@ "question-count-plural": "Fragen", "edit-keyword-tip": "Neues Thema", "no-keywords-note": "Es gibt keine Themen.", - "consider-votes": "Bewertungen der Fragen berücksichtigen", + "keyword-scoring-header": "Bewertung der Stichwörter", + "keyword-scoring-header-info": "Einstellbare Multiplikatoren für die Gewichtung der Schlüsselwörter", + "keyword-scoring-countComments": "Anzahl Kommentare", + "keyword-scoring-countComments-info": "Anzahl der Kommentare, aus denen die Schlüsselwörter extrahiert wurden", + "keyword-scoring-countUsers": "Anzahl Fragensteller*innen", + "keyword-scoring-countUsers-info": "Anzahl exklusiver Fragensteller*innen, die dieses Schlüsselwort verwendet haben", + "keyword-scoring-countSelectedByQuestioner": "Anzahl verifiziert", + "keyword-scoring-countSelectedByQuestioner-info": "Anzahl der Verifizierungen eines Schlüsselworts durch einen Fragesteller*in", + "keyword-scoring-countKeywordByModerator": "Anzahl Schlüsselwörter von Moderatoren", + "keyword-scoring-countKeywordByModerator-info": "Anzahl der Verwendungen dieses Schlüsselworts durch Moderatoren", + "keyword-scoring-countKeywordByCreator": "Anzahl Schlüsselwörter vom Ersteller", + "keyword-scoring-countKeywordByCreator-info": "Anzahl der Verwendungen dieses Schlüsselworts durch den Ersteller", + "keyword-scoring-countCommentsAnswered": "Anzahl beantwortete Kommentare", + "keyword-scoring-countCommentsAnswered-info": "Anzahl der Kommentare, die dieses Stichwort enthalten und beantwortet wurden", + "keyword-scoring-summedUpvotes": "Anzahl aller Upvotes", + "keyword-scoring-summedUpvotes-info": "Anzahl aller Upvotes, die auf den Kommentaren mit diesem Schlüsselwort gemacht worden sind", + "keyword-scoring-summedDownvotes": "Anzahl aller Downvotes", + "keyword-scoring-summedDownvotes-info": "Anzahl aller Downvotes, die auf den Kommentaren mit diesem Schlüsselwort gemacht worden sind", + "keyword-scoring-summedVotes": "Summe aller Votes", + "keyword-scoring-summedVotes-info": "Summe aus den Up- und Downvotes, die auf den Kommentaren mit diesem Schlüsselwort gemacht worden sind", + "keyword-scoring-cappedSummedVotes": "Summe aller Votes (>= 0)", + "keyword-scoring-cappedSummedVotes-info": "(Siehe Summe aller Votes). Die Summe kann nicht unter null fallen und wird minimal 0", "profanity": "Vulgäre Wörter mit »***« überschreiben", "hide-blacklist-words": "Themen aus der Blacklist verbergen", "sort-alpha": "Alphabetisch", diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json index bdd01c3c6..3c0a39839 100644 --- a/src/assets/i18n/creator/en.json +++ b/src/assets/i18n/creator/en.json @@ -426,7 +426,28 @@ "question-count-plural": "Questions", "edit-keyword-tip": "New topic", "no-keywords-note": "There are no topics.", - "consider-votes": "Consider Votes", + "keyword-scoring-header": "Keyword weighting", + "keyword-scoring-header-info": "Adjustable multipliers for the weighting of keywords", + "keyword-scoring-countComments": "Number of comments", + "keyword-scoring-countComments-info": "Number of comments from which the keywords have been extracted", + "keyword-scoring-countUsers": "Number of questioners", + "keyword-scoring-countUsers-info": "Number of exclusive questioners who used this keyword", + "keyword-scoring-countSelectedByQuestioner": "Number verified", + "keyword-scoring-countSelectedByQuestioner-info": "Number of times a keyword has been verified by a questioner", + "keyword-scoring-countKeywordByModerator": "Number of keywords from moderators", + "keyword-scoring-countKeywordByModerator-info": "Number of times this keyword has been used by moderators", + "keyword-scoring-countKeywordByCreator": "Number of keywords from creator", + "keyword-scoring-countKeywordByCreator-info": "Number of times this keyword has been used by the creator", + "keyword-scoring-countCommentsAnswered": "Number of answered comments", + "keyword-scoring-countCommentsAnswered-info": "Number of comments that have this keyword and have been answered", + "keyword-scoring-summedUpvotes": "Number of all upvotes", + "keyword-scoring-summedUpvotes-info": "Number of all upvotes made on the comments with this keyword", + "keyword-scoring-summedDownvotes": "Number of all downvotes", + "keyword-scoring-summedDownvotes-info": "Number of all downvotes made on the comments with this keyword", + "keyword-scoring-summedVotes": "Sum of all votes", + "keyword-scoring-summedVotes-info": "Sum of the upvotes and downvotes made on the comments with this keyword", + "keyword-scoring-cappedSummedVotes": "Sum of all votes (>= 0)", + "keyword-scoring-cappedSummedVotes-info": "(See the sum of all votes). The sum cannot fall below zero and becomes a minimum of 0", "profanity": "Censor profanity", "hide-blacklist-words": "Hide blacklist keywords", "sort-alpha": "Alphabetically", diff --git a/src/assets/i18n/participant/de.json b/src/assets/i18n/participant/de.json index 2dd52369f..e9e12de31 100644 --- a/src/assets/i18n/participant/de.json +++ b/src/assets/i18n/participant/de.json @@ -321,7 +321,28 @@ "question-count-plural": "Fragen", "edit-keyword-tip": "Neues Thema", "no-keywords-note": "Es gibt keine Themen.", - "consider-votes": "Bewertungen der Fragen berücksichtigen", + "keyword-scoring-header": "Bewertung der Stichwörter", + "keyword-scoring-header-info": "Einstellbare Multiplikatoren für die Gewichtung der Schlüsselwörter", + "keyword-scoring-countComments": "Anzahl Kommentare", + "keyword-scoring-countComments-info": "Anzahl der Kommentare, aus denen die Schlüsselwörter extrahiert wurden", + "keyword-scoring-countUsers": "Anzahl Fragensteller*innen", + "keyword-scoring-countUsers-info": "Anzahl exklusiver Fragensteller*innen, die dieses Schlüsselwort verwendet haben", + "keyword-scoring-countSelectedByQuestioner": "Anzahl verifiziert", + "keyword-scoring-countSelectedByQuestioner-info": "Anzahl der Verifizierungen eines Schlüsselworts durch einen Fragesteller*in", + "keyword-scoring-countKeywordByModerator": "Anzahl Schlüsselwörter von Moderatoren", + "keyword-scoring-countKeywordByModerator-info": "Anzahl der Verwendungen dieses Schlüsselworts durch Moderatoren", + "keyword-scoring-countKeywordByCreator": "Anzahl Schlüsselwörter vom Ersteller", + "keyword-scoring-countKeywordByCreator-info": "Anzahl der Verwendungen dieses Schlüsselworts durch den Ersteller", + "keyword-scoring-countCommentsAnswered": "Anzahl beantwortete Kommentare", + "keyword-scoring-countCommentsAnswered-info": "Anzahl der Kommentare, die dieses Stichwort enthalten und beantwortet wurden", + "keyword-scoring-summedUpvotes": "Anzahl aller Upvotes", + "keyword-scoring-summedUpvotes-info": "Anzahl aller Upvotes, die auf den Kommentaren mit diesem Schlüsselwort gemacht worden sind", + "keyword-scoring-summedDownvotes": "Anzahl aller Downvotes", + "keyword-scoring-summedDownvotes-info": "Anzahl aller Downvotes, die auf den Kommentaren mit diesem Schlüsselwort gemacht worden sind", + "keyword-scoring-summedVotes": "Summe aller Votes", + "keyword-scoring-summedVotes-info": "Summe aus den Up- und Downvotes, die auf den Kommentaren mit diesem Schlüsselwort gemacht worden sind", + "keyword-scoring-cappedSummedVotes": "Summe aller Votes (>= 0)", + "keyword-scoring-cappedSummedVotes-info": "(Siehe Summe aller Votes). Die Summe kann nicht unter null fallen und wird minimal 0", "profanity": "Vulgäre Wörter mit »***« überschreiben", "hide-blacklist-words": "Themen aus der Blacklist verbergen", "sort-alpha": "Alphabetisch", diff --git a/src/assets/i18n/participant/en.json b/src/assets/i18n/participant/en.json index 7ae49a217..a3fbef81d 100644 --- a/src/assets/i18n/participant/en.json +++ b/src/assets/i18n/participant/en.json @@ -327,7 +327,28 @@ "question-count-plural": "Questions", "edit-keyword-tip": "New topic", "no-keywords-note": "There are no topics.", - "consider-votes": "Consider Votes", + "keyword-scoring-header": "Keyword weighting", + "keyword-scoring-header-info": "Adjustable multipliers for the weighting of keywords", + "keyword-scoring-countComments": "Number of comments", + "keyword-scoring-countComments-info": "Number of comments from which the keywords have been extracted", + "keyword-scoring-countUsers": "Number of questioners", + "keyword-scoring-countUsers-info": "Number of exclusive questioners who used this keyword", + "keyword-scoring-countSelectedByQuestioner": "Number verified", + "keyword-scoring-countSelectedByQuestioner-info": "Number of times a keyword has been verified by a questioner", + "keyword-scoring-countKeywordByModerator": "Number of keywords from moderators", + "keyword-scoring-countKeywordByModerator-info": "Number of times this keyword has been used by moderators", + "keyword-scoring-countKeywordByCreator": "Number of keywords from creator", + "keyword-scoring-countKeywordByCreator-info": "Number of times this keyword has been used by the creator", + "keyword-scoring-countCommentsAnswered": "Number of answered comments", + "keyword-scoring-countCommentsAnswered-info": "Number of comments that have this keyword and have been answered", + "keyword-scoring-summedUpvotes": "Number of all upvotes", + "keyword-scoring-summedUpvotes-info": "Number of all upvotes made on the comments with this keyword", + "keyword-scoring-summedDownvotes": "Number of all downvotes", + "keyword-scoring-summedDownvotes-info": "Number of all downvotes made on the comments with this keyword", + "keyword-scoring-summedVotes": "Sum of all votes", + "keyword-scoring-summedVotes-info": "Sum of the upvotes and downvotes made on the comments with this keyword", + "keyword-scoring-cappedSummedVotes": "Sum of all votes (>= 0)", + "keyword-scoring-cappedSummedVotes-info": "(See the sum of all votes). The sum cannot fall below zero and becomes a minimum of 0", "profanity": "Censor profanity", "hide-blacklist-words": "Hide blacklist keywords", "sort-alpha": "Alphabetically", -- GitLab