• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ProjektAdLer / 2D_3D_AdLer / #1121

03 Mar 2025 05:07PM UTC coverage: 96.631% (-0.2%) from 96.845%
#1121

push

lukaio3D
fixed broken tests for Builders in LearningWorldScorePanel and CompletionModal

2109 of 2445 branches covered (86.26%)

4904 of 5075 relevant lines covered (96.63%)

40.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.21
/src/Components/Core/Application/UseCases/ScoreLearningElement/ScoreLearningElementUseCase.ts
1
import { inject, injectable } from "inversify";
2
import { ComponentID } from "../../../Domain/Types/EntityTypes";
3
import CORE_TYPES from "../../../DependencyInjection/CoreTypes";
4
import USECASE_TYPES from "../../../DependencyInjection/UseCases/USECASE_TYPES";
5
import type IEntityContainer from "../../../Domain/EntityContainer/IEntityContainer";
6
import IScoreLearningElementUseCase from "./IScoreLearningElementUseCase";
7
import type IBackendPort from "../../Ports/Interfaces/IBackendPort";
8
import LearningElementEntity from "../../../Domain/Entities/LearningElementEntity";
9
import UserDataEntity from "../../../Domain/Entities/UserDataEntity";
10
import PORT_TYPES from "~DependencyInjection/Ports/PORT_TYPES";
11
import type ILearningWorldPort from "src/Components/Core/Application/Ports/Interfaces/ILearningWorldPort";
12
import type IGetUserLocationUseCase from "../GetUserLocation/IGetUserLocationUseCase";
13
import type { IInternalCalculateLearningWorldScoreUseCase } from "../CalculateLearningWorldScore/ICalculateLearningWorldScoreUseCase";
14
import type { IInternalCalculateLearningSpaceScoreUseCase } from "../CalculateLearningSpaceScore/ICalculateLearningSpaceScoreUseCase";
15
import type ILoggerPort from "../../Ports/Interfaces/ILoggerPort";
16
import { LogLevelTypes } from "src/Components/Core/Domain/Types/LogLevelTypes";
17
import type INotificationPort from "../../Ports/Interfaces/INotificationPort";
18
import i18next from "i18next";
19

20
@injectable()
21
export default class ScoreLearningElementUseCase
22
  implements IScoreLearningElementUseCase
23
{
24
  constructor(
25
    @inject(CORE_TYPES.ILogger)
26
    private logger: ILoggerPort,
27
    @inject(CORE_TYPES.IEntityContainer)
28
    private entityContainer: IEntityContainer,
29
    @inject(CORE_TYPES.IBackendAdapter)
30
    private backendAdapter: IBackendPort,
31
    @inject(USECASE_TYPES.ICalculateLearningWorldScoreUseCase)
32
    private calculateWorldScoreUseCase: IInternalCalculateLearningWorldScoreUseCase,
33
    @inject(USECASE_TYPES.ICalculateLearningSpaceScoreUseCase)
34
    private calculateSpaceScoreUseCase: IInternalCalculateLearningSpaceScoreUseCase,
35
    @inject(PORT_TYPES.ILearningWorldPort)
36
    private worldPort: ILearningWorldPort,
37
    @inject(USECASE_TYPES.IGetUserLocationUseCase)
38
    private getUserLocationUseCase: IGetUserLocationUseCase,
39
    @inject(PORT_TYPES.INotificationPort)
40
    private notificationPort: INotificationPort,
41
  ) {}
42

43
  async executeAsync(elementID: ComponentID): Promise<void> {
44
    // get user token
45
    const userEntity =
46
      this.entityContainer.getEntitiesOfType(UserDataEntity)[0];
8✔
47

48
    // get the current user location
49
    const userLocation = this.getUserLocationUseCase.execute();
8✔
50
    if (!userLocation.worldID || !userLocation.spaceID) {
8✔
51
      return this.rejectWithWarning(
1✔
52
        "User is not in a space! Trying to score elememt " + elementID,
53
      );
54
    }
55

56
    let backendSuccessful: boolean;
57
    // call backend
58
    try {
7✔
59
      backendSuccessful = await this.backendAdapter.scoreElement(
7✔
60
        userEntity.userToken,
61
        elementID,
62
        userLocation.worldID,
63
      );
64
    } catch (e) {
65
      return this.rejectWithWarning(
1✔
66
        "Backend call failed with error: " + e,
67
        elementID,
68
      );
69
    }
70

71
    const elements =
72
      this.entityContainer.filterEntitiesOfType<LearningElementEntity>(
6✔
73
        LearningElementEntity,
74
        (entity) =>
75
          entity.parentWorldID === userLocation.worldID &&
6!
76
          entity.id === elementID,
77
      );
78

79
    if (elements.length === 0)
6✔
80
      return this.rejectWithWarning("No matching element found!", elementID);
1✔
81
    else if (elements.length > 1)
5✔
82
      return this.rejectWithWarning(
1✔
83
        "More than one matching element found!",
84
        elementID,
85
      );
86

87
    if (!backendSuccessful && !elements[0].hasScored) {
4!
88
      this.notificationPort.onNotificationTriggered(
×
89
        LogLevelTypes.ERROR,
90
        `ScoreElementUseCase: scoreElement from backend returned: ${backendSuccessful} for learningelement ${elementID} in space ${userLocation.spaceID} of world ${userLocation.worldID}`,
91
        i18next.t("learningElementScoringFalse", { ns: "errorMessages" }),
92
      );
93
      return Promise.reject("error");
×
94
    }
95

96
    if (!elements[0].hasScored) {
4!
97
      elements[0].hasScored = true;
4✔
98

99
      try {
4✔
100
        const newWorldScore = this.calculateWorldScoreUseCase.internalExecute({
4✔
101
          worldID: userLocation.worldID,
102
        });
103
        this.worldPort.onLearningWorldScored(newWorldScore);
4✔
104
      } catch (e) {
105
        this.logger.log(
×
106
          LogLevelTypes.ERROR,
107
          `ScoreLearningElementUseCase: Error calculating new world score: ${e}`,
108
        );
109
      }
110

111
      try {
4✔
112
        const newSpaceScore = this.calculateSpaceScoreUseCase.internalExecute({
4✔
113
          worldID: userLocation.worldID,
114
          spaceID: userLocation.spaceID,
115
        });
116
        this.worldPort.onLearningSpaceScored(newSpaceScore);
4✔
117
      } catch (e) {
118
        this.logger.log(
×
119
          LogLevelTypes.ERROR,
120
          `ScoreLearningElementUseCase: Error calculating new space score: ${e}`,
121
        );
122
      }
123

124
      this.worldPort.onLearningElementScored(true, elementID);
4✔
125
    }
126
  }
127

128
  private rejectWithWarning(message: string, id?: ComponentID): Promise<void> {
129
    this.logger.log(
6✔
130
      LogLevelTypes.WARN,
131
      `ScoreLearningElementUseCase: ` +
132
        message +
133
        `${id ? " ElementID: " + id : ""}`,
6✔
134
    );
135
    return Promise.reject(message);
6✔
136
  }
137
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc