{"version":3,"file":"app-a6e9ab50.f584a1446b2fc034d810.bundle.js","mappings":"AAGA","sources":["webpack://lernplattform-admin-frontend/../common/aurelia-components/pin-code/pin-code.html","webpack://lernplattform-admin-frontend/../common/aurelia-components/placeable-dialog/placeable-dialog.html","webpack://lernplattform-admin-frontend/../common/aurelia-components/points-donut-chart/points-donut-chart.html","webpack://lernplattform-admin-frontend/../common/aurelia-components/points-explanation/points-explanation.html","webpack://lernplattform-admin-frontend/../common/aurelia-components/pin-code/index.ts","webpack://lernplattform-admin-frontend/../common/aurelia-components/pin-code/pin-code.ts","webpack://lernplattform-admin-frontend/../common/aurelia-components/placeable-dialog/index.ts","webpack://lernplattform-admin-frontend/../common/aurelia-components/placeable-dialog/placeable-dialog.ts","webpack://lernplattform-admin-frontend/../common/aurelia-components/points-donut-chart/index.ts","webpack://lernplattform-admin-frontend/../common/aurelia-components/points-donut-chart/points-donut-chart.ts","webpack://lernplattform-admin-frontend/../common/aurelia-components/points-explanation/index.ts","webpack://lernplattform-admin-frontend/../common/aurelia-components/points-explanation/points-explanation.ts"],"sourcesContent":["// Module\nvar code = \"<template> <div class=\\\"pin-code\\\"> <input class=\\\"pin-code__pin-input\\\" type=\\\"text\\\" ref=\\\"pinInputElement\\\" t=\\\"[aria-label]frp.inputLabel\\\" keyup.delegate=\\\"pinChanged($event)\\\"> <div class=\\\"pin-code__pin-boxes-wrapper\\\"> <div class=\\\"pin-code__pin-box-triplet\\\"> <div repeat.for=\\\"i of 3\\\" class=\\\"pin-code__pin-character-box ${ i === currentPosition ? 'pin-code__pin-character-box--active' : '' } ${ error ? 'pin-code__pin-character-box--error' : '' }\\\" click.delegate=\\\"focusInputAtIndex($event, $index)\\\"> <span class=\\\"pin-code__pin-character\\\">${pinCode.charAt($index)}</span> </div> </div> <div class=\\\"pin-code__pin-dash\\\"></div> <div class=\\\"pin-code__pin-box-triplet\\\"> <div repeat.for=\\\"i of 3\\\" class=\\\"pin-code__pin-character-box ${ i + 3 === currentPosition ? 'pin-code__pin-character-box--active' : '' } ${ error ? 'pin-code__pin-character-box--error' : '' }\\\" click.delegate=\\\"focusInputAtIndex($event, $index + 3)\\\"> <span class=\\\"pin-code__pin-character\\\">${pinCode.charAt($index + 3)}</span> </div> </div> </div> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template class=\\\"placeable-dialog ${ visible ? 'placeable-dialog--visible' : '' }\\\" style.to-view=\\\"{\\n            '--placeable-dialog-left': positionLeft,\\n            '--placeable-dialog-top': positionTop\\n          }\\\"> <div ref=\\\"contentWrapperElement\\\" class=\\\"placeable-dialog__content\\\" tabindex=\\\"${ visible ? '0' : '-1' }\\\" role=\\\"alertdialog\\\" aria-modal=\\\"true\\\"> <div class=\\\"placeable-dialog__scrollbox\\\"> <rich-text text.to-view=\\\"text\\\" mode=\\\"content\\\"></rich-text> </div> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template class=\\\"points-donut-chart\\\"> <canvas class=\\\"points-donut-chart__chart\\\" height.to-view=\\\"chartCanvasSize\\\" width.to-view=\\\"chartCanvasSize\\\" ref=\\\"chartCanvasElement\\\"></canvas> <div class=\\\"points-donut-chart__total\\\"> <h3 class=\\\"points-donut-chart__total-points\\\">${totalPoints}</h3> <p class=\\\"points-donut-chart__total-description\\\" t=\\\"common.points-donut-chart.pointsTotal\\\"></p> </div> </template>\";\n// Exports\nexport default code;","// Module\nvar code = \"<template class=\\\"points-explanation lp-site-content-small\\\"> <h3 class=\\\"points-explanation__title\\\" t=\\\"common.points-explanation.title\\\"></h3> <p class=\\\"points-explanation__description-text\\\" t.to-view=\\\"generalDescriptionTk\\\"></p> <div class=\\\"points-explanation__image-wrapper\\\"> <img class=\\\"points-explanation__image\\\" src.to-view=\\\"course.moduleCoverLearningUrl ? course.moduleCoverLearningUrl : images.learn\\\"> </div> <h5 class=\\\"points-explanation__description-title\\\" t=\\\"common.points-explanation.learnTitle\\\"></h5> <p class=\\\"points-explanation__description-text\\\" t=\\\"common.points-explanation.learnDescription\\\" t-params.to-view=\\\"{ maxPoints: COURSE_TOTAL_LEARN_POINTS }\\\"></p> <div class=\\\"points-explanation__image-wrapper points-explanation__image-wrapper--train\\\"> <img class=\\\"points-explanation__image\\\" src.to-view=\\\"course.moduleCoverTrainingUrl ? course.moduleCoverTrainingUrl : images.train\\\"> </div> <h5 class=\\\"points-explanation__description-title\\\" t=\\\"common.points-explanation.trainTitle\\\"></h5> <p class=\\\"points-explanation__description-text\\\" t=\\\"common.points-explanation.trainDescription\\\" t-params.to-view=\\\"trainDescriptionParams\\\"></p> <div class=\\\"points-explanation__image-wrapper points-explanation__image-wrapper--testexam\\\"> <img class=\\\"points-explanation__image\\\" src.to-view=\\\"course.moduleCoverTestexamUrl ? course.moduleCoverTestexamUrl : images.testexam\\\"> </div> <h5 class=\\\"points-explanation__description-title\\\" t=\\\"common.points-explanation.testExamTitle\\\"></h5> <p class=\\\"points-explanation__description-text\\\" t=\\\"common.points-explanation.testExamDescription\\\" t-params.to-view=\\\"{ defaultPoints: DEFAULT_POINTS_PER_QUESTION }\\\"></p> <template if.to-view=\\\"showGames\\\"> <div class=\\\"points-explanation__image-wrapper points-explanation__image-wrapper--games\\\"> <img class=\\\"points-explanation__image\\\" src.to-view=\\\"images.games\\\"> </div> <h5 class=\\\"points-explanation__description-title\\\" t=\\\"common.points-explanation.gamesTitle\\\"></h5> <p class=\\\"points-explanation__description-text\\\" t=\\\"common.points-explanation.gamesDescription\\\" t-params.to-view=\\\"{ defaultPoints: DEFAULT_POINTS_PER_QUESTION }\\\"></p> </template> <p class=\\\"points-explanation__description-text points-explanation__description-text--solitary\\\" t=\\\"common.points-explanation.additionalDescription\\\"></p> <p class=\\\"points-explanation__description-text points-explanation__description-text--solitary\\\" t=\\\"common.points-explanation.finalDescription\\\"></p> </template>\";\n// Exports\nexport default code;","import { PLATFORM, FrameworkConfiguration } from 'aurelia-framework';\n\nexport function configure(config: FrameworkConfiguration): void {\n  config.globalResources(PLATFORM.moduleName('common/aurelia-components/pin-code/pin-code'));\n}\n","import { PLATFORM, autoinject, bindable, useView } from 'aurelia-framework';\nimport { DomUtils } from 'common/utils/DomUtils';\nimport { assertNotNullOrUndefined } from 'common/utils/assert';\n\nconst DEFAULT_ALLOWED_CHARACTERS = 'BCDFGHJKLMNPQRSTVWXYZ23456789';\n\n/**\n * @event {PinCodeChangedEvent} pin-code-changed\n * \n * Provide allowedCharacters like this: 'BCDFGHJKLMNPQRSTVWXYZ23456789'.\n * The pin code will autogenerate and add lowercase versions for all \n * letters in the allowedCharacters string.\n */\n@useView(PLATFORM.moduleName('./pin-code.html'))\n@autoinject()\nexport class PinCode {\n  @bindable() allowedCharacters: string = DEFAULT_ALLOWED_CHARACTERS;\n  @bindable() addLowercaseLetters = true; \n  @bindable() error = false;\n  // script would be able to handle a variety of lengths as a bindable, \n  // but html/style would need some adjustments.\n  private desiredPinCodeLength = 6;\n  private ensuredAllowedCharacters = '';\n\n  private domElement: HTMLElement;\n  private pinInputElement: HTMLInputElement | null = null;\n  private validatePinCodeRegex: RegExp | null = null;\n  private currentPosition = 0;\n  private pinCode = '';\n  \n  constructor(\n    element: Element,\n  ) {\n    this.domElement = element as HTMLElement;\n  }\n\n  // expose focus and update input\n  public focusInput(): void {\n    this.updateInputElement();\n  }\n\n  private attached(): void {\n    this.ensureLowercaseLetters();\n    // add spaces to allowed characters for handling empty pin code characters\n    this.validatePinCodeRegex = new RegExp(`^[${this.ensuredAllowedCharacters} ]*$`);\n    this.updateInputElement();\n  }\n\n  private pinChanged(event: KeyboardEvent): void {\n    assertNotNullOrUndefined(this.pinInputElement, 'Input element must be available for pin login!');\n    let newPinCandidate = this.pinInputElement?.value.toUpperCase();\n    let characterDeleted = false;\n\n    // first handle arrow keys or other keys that don't change the pin code\n    if(this.pinCode === newPinCandidate) {\n      switch(event.key) {\n        case 'ArrowLeft':\n          this.currentPosition = Math.max(this.currentPosition - 1, 0);\n          break;\n        case 'ArrowRight':\n          this.currentPosition = Math.min(this.currentPosition + 1, this.desiredPinCodeLength - 1);\n          break;\n      }\n      this.updateInputElement();\n      return;\n    }\n\n    // remove \"-\" in case a code was copy pasted\n    newPinCandidate = newPinCandidate.replace(/-/g, '');\n\n    // reject forbidden characters\n    if(!this.validatePinCodeRegex?.test(newPinCandidate)) {\n      this.updateInputElement();\n      return;\n    }\n\n    // manipulating existing characters ...\n    if(this.currentPosition < this.pinCode.length) {\n      if(newPinCandidate.length > this.pinCode.length) {\n        // only replace next character in case of adding one character only,\n        // copy pasting more code just shifts existing code to the right\n        if(newPinCandidate.length === this.pinCode.length + 1) {\n          this.pinCode = `${newPinCandidate.slice(0, this.currentPosition + 1)}${newPinCandidate\n            .slice(this.currentPosition + 2, newPinCandidate.length)}`;\n        } else {\n          this.pinCode = newPinCandidate;\n        }\n      } else {\n        // deleted a character > replace it with a space\n        this.pinCode = `${this.pinCode.slice(0, this.currentPosition)} ${this.pinCode.slice(this.currentPosition + 1, this.pinCode.length)}`;\n        characterDeleted = true;\n      }\n    } else {\n      this.pinCode = newPinCandidate;\n    }\n    \n    // cap pinCode and set new position\n    if(this.pinCode.length > this.desiredPinCodeLength) {\n      this.pinCode = this.pinCode.slice(0, this.desiredPinCodeLength);\n      this.currentPosition = this.desiredPinCodeLength - 1;\n    }\n    if(!characterDeleted && this.currentPosition < this.desiredPinCodeLength - 1) {\n      this.currentPosition += 1;\n    }\n\n    this.updateInputElement();\n    this.firePinChangedEvent(); \n  }\n\n  public focusInputAtIndex(event: MouseEvent, newDesiredIndex: number): void {      \n    event.stopPropagation();\n\n    // selecting a pin code element to the right of the already filled out code\n    // automatically selects the first free character box\n    this.currentPosition = newDesiredIndex > this.pinCode.length\n      ? this.pinCode.length\n      : newDesiredIndex;\n\n    this.updateInputElement();\n  }\n\n  private updateInputElement(): void {\n    assertNotNullOrUndefined(this.pinInputElement, 'Input element must be available for pin login!');\n    this.pinInputElement.value = this.pinCode;\n    this.pinInputElement.focus();\n    this.pinInputElement.setSelectionRange(this.currentPosition, this.currentPosition);\n  }\n\n  private firePinChangedEvent(): void {\n    const cleanedPinCode = this.pinCode.replace(/ /g, '');\n    DomUtils.fireEvent<PinCodeChangedEvent['detail']>(this.domElement, {\n      detail: {\n        pinCode: cleanedPinCode,\n        actionEnabled: cleanedPinCode.length === this.desiredPinCodeLength,\n      },\n      name: 'pin-code-changed',\n    });\n  }\n\n  private ensureLowercaseLetters(): void {\n    if(this.allowedCharacters.length === 0) {\n      this.allowedCharacters = DEFAULT_ALLOWED_CHARACTERS;\n    }\n\n    if(!this.addLowercaseLetters) {\n      this.ensuredAllowedCharacters = this.allowedCharacters;\n      return;\n    }\n\n    let modifiedString = '';\n    for(const character of this.allowedCharacters) {\n      modifiedString += character;\n      if(character >= 'A' && character <= 'Z') {\n        modifiedString += character.toLowerCase();\n      }\n    }\n    this.ensuredAllowedCharacters = modifiedString;\n  }\n}\n\n\n/**\n * pinCode ... currently entered pin code\n * actionEnabled ... pinCode has desired length and consists only of allowed characters\n */\ninterface IPinCodeChangedEventDetail {\n  pinCode: string;\n  actionEnabled: boolean;\n}\n\nexport type PinCodeChangedEvent = CustomEvent<IPinCodeChangedEventDetail>;","import { PLATFORM, FrameworkConfiguration } from 'aurelia-framework';\n\nexport function configure(config: FrameworkConfiguration): void {\n  config.globalResources(PLATFORM.moduleName('common/aurelia-components/placeable-dialog/placeable-dialog'));\n}\n","import { PLATFORM, TaskQueue, autoinject, bindable, useView } from 'aurelia-framework';\nimport { FocusTrap } from 'common/aurelia-classes/FocusTrap';\nimport { SubscriptionManager, SubscriptionManagerService } from 'common/aurelia-services/SubscriptionManagerService';\nimport { KeyboardKey } from 'common/enum/keyboard.key.enum';\nimport { DomUtils } from 'common/utils/DomUtils';\n\n/**\n * @event {PlaceableDialogCloseEvent} close\n */\n@useView(PLATFORM.moduleName('./placeable-dialog.html'))\n@autoinject()\nexport class PlaceableDialog {\n  @bindable() public anchorElement: HTMLElement | null = null;\n  @bindable() public wrapperElement: HTMLElement | null = null;\n  @bindable() public text: string = '';\n  @bindable() public btnText: string = '';\n  @bindable() public visible: boolean = false;\n\n  private positionLeft: string = '0';\n  private positionTop: string = '0';\n\n  private domElement: HTMLElement;\n  private contentWrapperElement: HTMLElement | null = null;\n  private subscriptionManager: SubscriptionManager;\n  private focusTrap: FocusTrap | null = null;\n\n  constructor(\n    element: Element,\n    private subscriptionManagerService: SubscriptionManagerService,\n    private taskQueue: TaskQueue,\n  ) {\n    this.domElement = element as HTMLElement;\n    this.subscriptionManager = subscriptionManagerService.createSubscriptionManager();\n  }\n\n  protected attached(): void {\n    this.updateSubscriptions();\n  }\n\n  protected detached(): void {\n    this.subscriptionManager.disposeSubscriptions();\n    this.getOrCreateFocusTrap()?.destroy();\n  }\n\n  private updatePosition(): void {\n    if(!this.wrapperElement || !this.anchorElement || !this.contentWrapperElement) return;\n    const wrapperRect = this.wrapperElement.getBoundingClientRect();\n    const anchorRect = this.anchorElement.getBoundingClientRect();\n    const dialogRect = this.contentWrapperElement.getBoundingClientRect();\n    const SPACING = 15;\n\n    let topPosition = anchorRect.bottom + SPACING;\n    let leftPosition = anchorRect.left + anchorRect.width / 2 - dialogRect.width / 2;\n\n    const hasEnoughSpaceAtTop = anchorRect.top - SPACING - dialogRect.height > wrapperRect.top;\n    const hasEnoughSpaceAtBottom = topPosition + dialogRect.height < wrapperRect.bottom;\n    const hasEnoughSpaceAtRight = leftPosition + dialogRect.width < wrapperRect.right;\n    const hasEnoughSpaceAtLeft = leftPosition > wrapperRect.left;\n\n    if(!hasEnoughSpaceAtBottom) {\n      topPosition = anchorRect.top - dialogRect.height - SPACING;\n    }\n\n    if(!hasEnoughSpaceAtRight) {\n      const spaceNeeded = leftPosition + dialogRect.width + SPACING - wrapperRect.right;\n      leftPosition = leftPosition - spaceNeeded;\n\n      if(leftPosition + dialogRect.width + SPACING > anchorRect.left) {\n        leftPosition = anchorRect.left - SPACING - dialogRect.width;\n      }\n    }\n\n    if(!hasEnoughSpaceAtLeft) {\n      const spaceNeededLeft = leftPosition - SPACING - wrapperRect.left;\n      leftPosition = leftPosition - spaceNeededLeft;\n\n      if(leftPosition - SPACING < anchorRect.right) {\n        leftPosition = anchorRect.right + SPACING;\n      }\n    }\n\n    if(!hasEnoughSpaceAtBottom && !hasEnoughSpaceAtTop) {\n      topPosition = (wrapperRect.top + (wrapperRect.height / 2)) - (dialogRect.height / 2);\n\n      if(leftPosition > wrapperRect.left && anchorRect.right + SPACING + dialogRect.width < wrapperRect.right) {\n        leftPosition = anchorRect.right + SPACING;\n      } else if(anchorRect.left - SPACING - dialogRect.width > wrapperRect.left) {\n        leftPosition = anchorRect.left - SPACING - dialogRect.width;\n      }\n    }\n\n    this.positionTop = `${Math.round(topPosition)}px`;\n    this.positionLeft = `${Math.round(leftPosition)}px`;\n  }\n\n  private anchorElementChanged(): void {\n    this.updateSubscriptions();\n  }\n\n  private visibleChanged(): void {\n    this.updateSubscriptions();\n    if(this.visible) {\n      this.getOrCreateFocusTrap()?.setup();\n    } else {\n      this.getOrCreateFocusTrap()?.destroy();\n    }\n  }\n\n  private updateSubscriptions(): void {\n    this.subscriptionManager.disposeSubscriptions();\n    this.subscriptionManager.subscribeToElementResize(this.domElement, () => this.updatePosition());\n\n    if(this.visible) this.taskQueue.queueTask(() => {\n      if(this.domElement.isConnected && this.contentWrapperElement) {\n        this.subscriptionManager.subscribeToKeyboardEvent(window, KeyboardKey.Escape, () => {\n          this.fireCloseEvent();\n        });\n        this.subscriptionManager.subscribeToClickOutside(this.contentWrapperElement, () => {\n          this.fireCloseEvent();\n        });\n      }\n    });\n  }\n\n  private fireCloseEvent(): void {\n    DomUtils.fireEvent<PlaceableDialogCloseEvent['detail']>(this.domElement, {\n      bubbles: true,\n      name: 'close',\n    });\n  }\n\n  private getOrCreateFocusTrap(): FocusTrap | null {\n    if(this.contentWrapperElement && !this.focusTrap) {\n      this.focusTrap = new FocusTrap(this.contentWrapperElement, this.subscriptionManagerService);\n    }\n    return this.focusTrap;\n  }\n}\n\nexport type PlaceableDialogCloseEvent = CustomEvent<never>;\n","import { PLATFORM, FrameworkConfiguration } from 'aurelia-framework';\n\nexport function configure(config: FrameworkConfiguration): void {\n  config.globalResources(PLATFORM.moduleName('common/aurelia-components/points-donut-chart/points-donut-chart'));\n}\n","import { bindable, autoinject, PLATFORM, useView } from 'aurelia-framework';\nimport { ICoursePointsGroupedDto } from 'common/dto/course/points/course.points.interface';\nimport { Chart } from 'chart.js';\nimport { assertNotNullOrUndefined } from 'common/utils/assert';\nimport { StringUtils } from 'common/utils/StringUtils';\nimport { SiteThemer, ThemeColorType } from 'common/aurelia-classes/SiteThemer';\n\n@useView(PLATFORM.moduleName('./points-donut-chart.html'))\n@autoinject()\nexport class PointsDonutChart {\n  @bindable() public pointsGroup: ICoursePointsGroupedDto | null = null;\n  private totalPoints = '0';\n  private chartCanvasElement: HTMLCanvasElement | null = null;\n  private chartCanvasSize = 190;\n  private chart: Chart | null = null;\n\n  private isAttached = false;\n\n  constructor(private siteThemer: SiteThemer) { }\n\n  protected attached(): void {\n    this.isAttached = true;\n  }\n\n  protected detached(): void {\n    this.isAttached = false;\n    this.chart?.destroy();\n  }\n\n  private pointsGroupChanged(): void {\n    if(this.pointsGroup && this.isAttached) {\n      this.totalPoints = StringUtils.formatNumberGrouped(this.getTotalPoints());\n      this.drawChart();\n    }\n  }\n\n  private drawChart(): void {\n    this.chart?.destroy();\n    assertNotNullOrUndefined(this.chartCanvasElement, 'chartCanvasElement cannot be null or undefined');\n\n    this.chart = new Chart(this.chartCanvasElement, {\n      data: {\n        datasets: [\n          {\n            data: this.prepareData(),\n            backgroundColor: this.generateGradients(),\n          },\n        ],\n      },\n      type: 'doughnut',\n      options: {\n        layout: {\n          padding: {\n            top: -10,\n          },\n        },\n        aspectRatio: 1,\n        responsive: false,\n        cutoutPercentage: 75,\n        tooltips: {\n          enabled: false,\n        },\n        elements: {\n          arc: {\n            borderWidth: 0,\n          },\n        },\n        hover: {\n          mode: undefined,\n        },\n      },\n    });\n\n  }\n\n  private prepareData(): number[] {\n    if(!this.pointsGroup || !this.getTotalPoints()) return [100];\n\n    return [\n      this.pointsGroup.learning,\n      this.pointsGroup.training,\n      this.pointsGroup.testexam,\n      this.pointsGroup.activityStreak + this.pointsGroup.duel + this.pointsGroup.lecture,\n    ];\n  }\n\n  private generateGradients(): CanvasGradient[] | string {\n    if(!this.pointsGroup || !this.getTotalPoints()) {\n      return this.siteThemer.getColor(ThemeColorType.PrimaryTransparent);\n    }\n\n    const ctx = this.chartCanvasElement?.getContext('2d');\n    const colors: CanvasGradient[] = [];\n    if(ctx) {\n      const gradientTwo = ctx.createLinearGradient(0, 0, 0, this.chartCanvasSize);\n      const gradientThree = ctx.createLinearGradient(0, 0, 0, this.chartCanvasSize);\n      const gradientFour = ctx.createLinearGradient(0, 0, 0, this.chartCanvasSize);\n      const gradientOne = ctx.createLinearGradient(0, 0, 0, this.chartCanvasSize);\n      gradientOne.addColorStop(0, this.siteThemer.getColor(ThemeColorType.Primary));\n      gradientOne.addColorStop(1, this.siteThemer.getColor(ThemeColorType.PrimaryGradient));\n      colors.push(gradientOne);\n\n      gradientTwo.addColorStop(0, this.siteThemer.getColor(ThemeColorType.Secondary1));\n      gradientTwo.addColorStop(1, this.siteThemer.getColor(ThemeColorType.Secondary1Gradient));\n      colors.push(gradientTwo);\n\n      gradientThree.addColorStop(0, this.siteThemer.getColor(ThemeColorType.Testexam));\n      gradientThree.addColorStop(1, this.siteThemer.getColor(ThemeColorType.TestexamGradient));\n      colors.push(gradientThree);\n\n      gradientFour.addColorStop(0, this.siteThemer.getColor(ThemeColorType.Secondary3));\n      gradientFour.addColorStop(1, this.siteThemer.getColor(ThemeColorType.Secondary3Gradient));\n      colors.push(gradientFour);\n    }\n    return colors;\n  }\n\n  private getTotalPoints(): number {\n    if(!this.pointsGroup) return 0;\n    return Object.values(this.pointsGroup).reduce((acc, val) => acc + val, 0);\n  }\n}\n","import { PLATFORM, FrameworkConfiguration } from 'aurelia-framework';\n\nexport function configure(config: FrameworkConfiguration): void {\n  config.globalResources(PLATFORM.moduleName('common/aurelia-components/points-explanation/points-explanation'));\n}\n","import { autoinject, bindable, computedFrom, PLATFORM, useView } from 'aurelia-framework';\nimport { imageNameToString } from 'common/aurelia-components/images';\nimport { COURSE_TOTAL_LEARN_POINTS } from 'common/constants/course.constants';\nimport {\n  ANSWER_COUNT_REQUIRED_FOR_COMPLETION,\n  DEFAULT_POINTS_PER_QUESTION,\n} from 'common/constants/quiz.constants';\nimport { ICourseContentDto } from 'common/dto/course/content/course.interface';\nimport { MathUtils } from 'common/utils/MathUtils';\nimport { TrainUtils } from 'common/utils/TrainUtils';\n\n@autoinject()\n@useView(PLATFORM.moduleName('./points-explanation.html'))\nexport class PointsExplanation {\n  @bindable() public trainingQuestionsTotal = 0;\n  @bindable() public course: ICourseContentDto | null = null;\n  @bindable() public showGames = true;\n\n  private DEFAULT_POINTS_PER_QUESTION = DEFAULT_POINTS_PER_QUESTION;\n  private COURSE_TOTAL_LEARN_POINTS = COURSE_TOTAL_LEARN_POINTS;\n  private ANSWER_COUNT_REQUIRED_FOR_COMPLETION = ANSWER_COUNT_REQUIRED_FOR_COMPLETION;\n  private images = {\n    learn: imageNameToString.LearningCropped,\n    train: imageNameToString.TrainCropped,\n    testexam: imageNameToString.TestexamCropped,\n    games: imageNameToString.GamesCropped,\n  };\n\n  @computedFrom('showGames')\n  private get generalDescriptionTk(): string {\n    return `common.points-explanation.${this.showGames ? 'generalDescriptionGamesEnabled' : 'generalDescription'}`;\n  }\n\n  @computedFrom('trainingQuestionsTotal')\n  private get trainDescriptionParams(): Record<string, unknown> {\n    return {\n      defaultPoints: DEFAULT_POINTS_PER_QUESTION,\n      questionsTotal: this.trainingQuestionsTotal,\n      completionAnswerCount: ANSWER_COUNT_REQUIRED_FOR_COMPLETION,\n      pointsTotal: MathUtils.roundToDigit(TrainUtils.getTrainingMaxPoints(this.trainingQuestionsTotal), 4),\n    };\n  }\n}\n"],"names":[],"sourceRoot":""}