/
githubmirror
/
oppia
Обзор
Документация
Войти
/
githubmirror
/
oppia
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
extensions/interactions/MultipleChoiceInput/directives/oppia-interactive-multiple-choice-input.component.ts
160 строк
6 KB
tanmaygoyal2007
Fix part of #23496 : Apply strict type checks to group 15 and 16 files (#26342)
27 июн 2026, 01:01
Не верифицирован
27 июн 2026, 01:01
f74507d
Код
Авторство
О чём код?
// Copyright 2014 The Oppia Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * @fileoverview Component for the MultipleChoiceInput interaction. * * IMPORTANT NOTE: The naming convention for customization args that are passed * into the component is: the name of the parameter, followed by 'With', * followed by the name of the arg. */ import {Component, HostListener, Input, OnInit} from '@angular/core'; import {RecordedVoiceovers} from 'domain/exploration/recorded-voiceovers.model'; import {StateCard} from 'domain/state_card/state-card.model'; import {MultipleChoiceInputCustomizationArgs} from 'interactions/customization-args-defs'; import {InteractionAttributesExtractorService} from 'interactions/interaction-attributes-extractor.service'; import {CurrentInteractionService} from 'pages/exploration-player-page/services/current-interaction.service'; import {PlayerTranscriptService} from 'pages/exploration-player-page/services/player-transcript.service'; import {MultipleChoiceInputRulesService} from './multiple-choice-input-rules.service'; import { MultipleChoiceInputOrderedChoicesService, ChoiceWithIndex, } from './multiple-choice-input-ordered-choices-service'; import '../static/multiple_choice_input.css'; @Component({ selector: 'oppia-interactive-multiple-choice-input', templateUrl: './multiple-choice-input-interaction.component.html', }) export class InteractiveMultipleChoiceInputComponent implements OnInit { COMPONENT_NAME_RULE_INPUT!: string; @Input() choicesWithValue!: string; @Input() showChoicesInShuffledOrderWithValue!: string; choices!: ChoiceWithIndex[]; answer: number | null = null; displayedCard!: StateCard; errorMessageI18nKey: string = ''; recordedVoiceovers!: RecordedVoiceovers; constructor( private currentInteractionService: CurrentInteractionService, private interactionAttributesExtractorService: InteractionAttributesExtractorService, private multipleChoiceInputRulesService: MultipleChoiceInputRulesService, private playerTranscriptService: PlayerTranscriptService, private multipleChoiceInputOrderedChoicesService: MultipleChoiceInputOrderedChoicesService ) {} private getAttrs() { return { choicesWithValue: this.choicesWithValue, showChoicesInShuffledOrderWithValue: this.showChoicesInShuffledOrderWithValue, }; } private validate(): boolean { return this.answer !== null; } private shuffleChoices(choices: ChoiceWithIndex[]): void { for ( var currentIndex = choices.length - 1; currentIndex >= 0; currentIndex-- ) { var temporaryValue = null; var randomIndex = null; randomIndex = Math.floor(Math.random() * (currentIndex + 1)); temporaryValue = choices[currentIndex]; choices[currentIndex] = choices[randomIndex]; choices[randomIndex] = temporaryValue; } } private getOrderedChoices(): ChoiceWithIndex[] { if (this.playerTranscriptService.getNumSubmitsForLastCard() > 0) { return this.multipleChoiceInputOrderedChoicesService.get(); } const {showChoicesInShuffledOrder, choices} = this.interactionAttributesExtractorService.getValuesFromAttributes( 'MultipleChoiceInput', this.getAttrs() ) as MultipleChoiceInputCustomizationArgs; const choicesWithIndex = choices.value.map((value, originalIndex) => ({ originalIndex, choice: value, })); if (showChoicesInShuffledOrder.value) { this.shuffleChoices(choicesWithIndex); } else { choicesWithIndex.sort((c1, c2) => c1.originalIndex - c2.originalIndex); } this.multipleChoiceInputOrderedChoicesService.store(choicesWithIndex); return choicesWithIndex; } ngOnInit(): void { this.choices = this.getOrderedChoices(); this.answer = null; this.currentInteractionService.registerCurrentInteraction( () => this.submitAnswer(), () => this.validate() ); } selectAnswer(event: MouseEvent, answer: string | null): void { event.preventDefault(); if (answer === null) { return; } this.errorMessageI18nKey = ''; // Deselect previously selected option. var selectedElement = document.querySelector( 'button.multiple-choice-option.selected' ); if (selectedElement) { selectedElement.classList.remove('selected'); } // Selected current option. (event.currentTarget as HTMLDivElement).classList.add('selected'); this.answer = parseInt(answer, 10); this.currentInteractionService.updateCurrentAnswer(this.answer); } @HostListener('document:keydown.enter', ['$event']) handleEnterKey(event: KeyboardEvent): void { event.preventDefault(); this.submitAnswer(); } submitAnswer(): void { if (this.answer === null) { if (this.currentInteractionService.showNoResponseError()) { this.errorMessageI18nKey = 'I18N_INTERACTIONS_ITEM_SELECTION_NO_RESPONSE'; } return; } this.currentInteractionService.onSubmit( this.answer, this.multipleChoiceInputRulesService ); } }