diff --git a/src/Components/Core/Application/Ports/AvatarPort/AvatarPort.ts b/src/Components/Core/Application/Ports/AvatarPort/AvatarPort.ts index c171c9aea..cbfcce7d8 100644 --- a/src/Components/Core/Application/Ports/AvatarPort/AvatarPort.ts +++ b/src/Components/Core/Application/Ports/AvatarPort/AvatarPort.ts @@ -13,6 +13,15 @@ export default class AvatarPort return "AVATAR-PORT"; } + onAvatarConfigLoaded(avatarConfig: AvatarConfigTO): void { + this.mappedAdapters.forEach((adapters) => { + adapters.forEach((adapter) => { + if (adapter.onAvatarConfigLoaded) + adapter.onAvatarConfigLoaded(avatarConfig); + }); + }); + } + onAvatarConfigChanged( newAvatarConfig: AvatarConfigTO, avatarConfigDiff: Partial, diff --git a/src/Components/Core/Application/Ports/AvatarPort/IAvatarAdapter.ts b/src/Components/Core/Application/Ports/AvatarPort/IAvatarAdapter.ts index 2ce6ed5a6..72a66680a 100644 --- a/src/Components/Core/Application/Ports/AvatarPort/IAvatarAdapter.ts +++ b/src/Components/Core/Application/Ports/AvatarPort/IAvatarAdapter.ts @@ -1,6 +1,7 @@ import AvatarConfigTO from "../../DataTransferObjects/AvatarConfigTO"; export default interface IAvatarAdapter { + onAvatarConfigLoaded?(avatarConfig: AvatarConfigTO): void; onAvatarConfigChanged?( newAvatarConfig: AvatarConfigTO, avatarConfigDiff: Partial, diff --git a/src/Components/Core/Application/Ports/Interfaces/IAvatarPort.ts b/src/Components/Core/Application/Ports/Interfaces/IAvatarPort.ts index 521e1c61c..1806d93d6 100644 --- a/src/Components/Core/Application/Ports/Interfaces/IAvatarPort.ts +++ b/src/Components/Core/Application/Ports/Interfaces/IAvatarPort.ts @@ -3,6 +3,7 @@ import IAvatarAdapter from "../AvatarPort/IAvatarAdapter"; import { IAbstractPort } from "./IAbstractPort"; export default interface IAvatarPort extends IAbstractPort { + onAvatarConfigLoaded(avatarConfig: AvatarConfigTO): void; onAvatarConfigChanged( newAvatarConfig: AvatarConfigTO, avatarConfigDiff: Partial, diff --git a/src/Components/Core/Application/UseCases/LoadAvatar/ILoadAvatarUseCase.ts b/src/Components/Core/Application/UseCases/LoadAvatar/ILoadAvatarUseCase.ts deleted file mode 100644 index 708490890..000000000 --- a/src/Components/Core/Application/UseCases/LoadAvatar/ILoadAvatarUseCase.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { IAsyncUsecase } from "../../Abstract/IAsyncUsecase"; -export default interface ILoadAvatarUseCase extends IAsyncUsecase {} diff --git a/src/Components/Core/Application/UseCases/LoadAvatar/LoadAvatarUseCase.ts b/src/Components/Core/Application/UseCases/LoadAvatar/LoadAvatarUseCase.ts deleted file mode 100644 index 93c36c7a6..000000000 --- a/src/Components/Core/Application/UseCases/LoadAvatar/LoadAvatarUseCase.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { inject, injectable } from "inversify"; -import PORT_TYPES from "../../../DependencyInjection/Ports/PORT_TYPES"; -import type IAvatarPort from "../../Ports/Interfaces/IAvatarPort"; -import ILoadAvatarUseCase from "./ILoadAvatarUseCase"; -import CORE_TYPES from "~DependencyInjection/CoreTypes"; -import type ILoggerPort from "../../Ports/Interfaces/ILoggerPort"; -import { LogLevelTypes } from "src/Components/Core/Domain/Types/LogLevelTypes"; - -@injectable() -export default class LoadAvatarUseCase implements ILoadAvatarUseCase { - constructor( - @inject(CORE_TYPES.ILogger) private logger: ILoggerPort, - @inject(PORT_TYPES.IAvatarPort) private avatarPort: IAvatarPort - ) {} - - async executeAsync(): Promise { - // TODO: load avatar data from backend and pass it to the avatar port - // this.avatarPort.presentAvatar(); - - this.logger.log( - LogLevelTypes.TRACE, - "LoadAvatarUseCase: Loaded Avatar from Backend (NOT IMPLEMENTED)." - ); - return Promise.resolve(); - } -} diff --git a/src/Components/Core/Application/UseCases/LoadAvatarConfig/ILoadAvatarConfigUseCase.ts b/src/Components/Core/Application/UseCases/LoadAvatarConfig/ILoadAvatarConfigUseCase.ts new file mode 100644 index 000000000..2599627d1 --- /dev/null +++ b/src/Components/Core/Application/UseCases/LoadAvatarConfig/ILoadAvatarConfigUseCase.ts @@ -0,0 +1,3 @@ +import { IAsyncUsecase } from "../../Abstract/IAsyncUsecase"; +export default interface ILoadAvatarConfigUseCase + extends IAsyncUsecase {} diff --git a/src/Components/Core/Application/UseCases/LoadAvatarConfig/LoadAvatarConfigUseCase.ts b/src/Components/Core/Application/UseCases/LoadAvatarConfig/LoadAvatarConfigUseCase.ts new file mode 100644 index 000000000..d01c4ca20 --- /dev/null +++ b/src/Components/Core/Application/UseCases/LoadAvatarConfig/LoadAvatarConfigUseCase.ts @@ -0,0 +1,45 @@ +import { inject, injectable } from "inversify"; +import PORT_TYPES from "../../../DependencyInjection/Ports/PORT_TYPES"; +import type IAvatarPort from "../../Ports/Interfaces/IAvatarPort"; +import ILoadAvatarConfigUseCase from "./ILoadAvatarConfigUseCase"; +import CORE_TYPES from "~DependencyInjection/CoreTypes"; +import type ILoggerPort from "../../Ports/Interfaces/ILoggerPort"; +import { LogLevelTypes } from "../../../Domain/Types/LogLevelTypes"; +import type IEntityContainer from "../../../Domain/EntityContainer/IEntityContainer"; +import UserDataEntity from "../../../Domain/Entities/UserDataEntity"; +import type IBackendPort from "../../Ports/Interfaces/IBackendPort"; +import AvatarEntity from "src/Components/Core/Domain/Entities/AvatarEntity"; + +@injectable() +export default class LoadAvatarConfigUseCase + implements ILoadAvatarConfigUseCase +{ + constructor( + @inject(CORE_TYPES.ILogger) private logger: ILoggerPort, + @inject(PORT_TYPES.IAvatarPort) private avatarPort: IAvatarPort, + @inject(CORE_TYPES.IEntityContainer) + private entityContainer: IEntityContainer, + @inject(CORE_TYPES.IBackendAdapter) + private backend: IBackendPort, + ) {} + + async executeAsync(): Promise { + let userDataEntities = + this.entityContainer.getEntitiesOfType(UserDataEntity); + if (userDataEntities.length === 0) { + this.logger.log(LogLevelTypes.ERROR, "No user data entity found"); + return; + } else if (userDataEntities.length > 1) { + this.logger.log(LogLevelTypes.ERROR, "Multiple user data entities found"); + return; + } + + // TODO: actually load avatar config from backend + if (!userDataEntities[0].avatar) { + userDataEntities[0].avatar = new AvatarEntity(); + // let avatarConfig = await this.backend.loadAvatarConfigAsync(); + } + + this.avatarPort.onAvatarConfigLoaded(userDataEntities[0].avatar); + } +} diff --git a/src/Components/Core/DependencyInjection/UseCases/UseCaseDIConatiner.ts b/src/Components/Core/DependencyInjection/UseCases/UseCaseDIConatiner.ts index d584dae5b..d0d49c2c7 100644 --- a/src/Components/Core/DependencyInjection/UseCases/UseCaseDIConatiner.ts +++ b/src/Components/Core/DependencyInjection/UseCases/UseCaseDIConatiner.ts @@ -3,8 +3,8 @@ import CalculateLearningSpaceScoreUseCase from "../../Application/UseCases/Calcu import ICalculateLearningSpaceScoreUseCase from "../../Application/UseCases/CalculateLearningSpaceScore/ICalculateLearningSpaceScoreUseCase"; import ILoadLearningElementUseCase from "../../Application/UseCases/LoadLearningElement/ILoadLearningElementUseCase"; import LoadLearningElementUseCase from "../../Application/UseCases/LoadLearningElement/LoadLearningElementUseCase"; -import ILoadAvatarUseCase from "../../Application/UseCases/LoadAvatar/ILoadAvatarUseCase"; -import LoadAvatarUseCase from "../../Application/UseCases/LoadAvatar/LoadAvatarUseCase"; +import ILoadAvatarConfigUseCase from "../../Application/UseCases/LoadAvatarConfig/ILoadAvatarConfigUseCase"; +import LoadAvatarConfigUseCase from "../../Application/UseCases/LoadAvatarConfig/LoadAvatarConfigUseCase"; import ILoadLearningSpaceUseCase from "../../Application/UseCases/LoadLearningSpace/ILoadLearningSpaceUseCase"; import LoadLearningSpaceUseCase from "../../Application/UseCases/LoadLearningSpace/LoadLearningSpaceUseCase"; import ILoadLearningWorldUseCase from "../../Application/UseCases/LoadLearningWorld/ILoadLearningWorldUseCase"; @@ -94,8 +94,8 @@ const UseCaseDIContainer = new ContainerModule((bind) => { .to(SetWorldCompletionModalToShownUseCase) .inSingletonScope(); - bind(USECASE_TYPES.ILoadAvatarUseCase) - .to(LoadAvatarUseCase) + bind(USECASE_TYPES.ILoadAvatarUseCase) + .to(LoadAvatarConfigUseCase) .inSingletonScope(); bind(USECASE_TYPES.IScoreLearningElementUseCase) diff --git a/src/Components/Core/Presentation/Babylon/SceneManagement/Scenes/LearningSpaceSceneDefinition.ts b/src/Components/Core/Presentation/Babylon/SceneManagement/Scenes/LearningSpaceSceneDefinition.ts index fa644889c..da5976bfb 100644 --- a/src/Components/Core/Presentation/Babylon/SceneManagement/Scenes/LearningSpaceSceneDefinition.ts +++ b/src/Components/Core/Presentation/Babylon/SceneManagement/Scenes/LearningSpaceSceneDefinition.ts @@ -13,7 +13,6 @@ import BUILDER_TYPES from "~DependencyInjection/Builders/BUILDER_TYPES"; import bind from "bind-decorator"; import USECASE_TYPES from "~DependencyInjection/UseCases/USECASE_TYPES"; import type ILoadLearningSpaceUseCase from "src/Components/Core/Application/UseCases/LoadLearningSpace/ILoadLearningSpaceUseCase"; -import type ILoadAvatarUseCase from "src/Components/Core/Application/UseCases/LoadAvatar/ILoadAvatarUseCase"; import type IPresentationDirector from "../../../PresentationBuilder/IPresentationDirector"; import type IPresentationBuilder from "../../../PresentationBuilder/IPresentationBuilder"; import type INavigation from "../../Navigation/INavigation"; @@ -47,8 +46,6 @@ export default class LearningSpaceSceneDefinition private navigation: INavigation, @inject(USECASE_TYPES.ILoadLearningSpaceUseCase) private loadSpaceUseCase: ILoadLearningSpaceUseCase, - @inject(USECASE_TYPES.ILoadAvatarUseCase) - private loadAvatarUseCase: ILoadAvatarUseCase, @inject(BUILDER_TYPES.IAvatarCameraBuilder) private avatarCameraBuilder: IPresentationBuilder, @inject(USECASE_TYPES.IGetUserLocationUseCase) @@ -56,13 +53,13 @@ export default class LearningSpaceSceneDefinition @inject(BUILDER_TYPES.IAmbienceBuilder) private ambienceBuilder: IAmbienceBuilder, @inject(PORT_TYPES.ILearningWorldPort) - private learningWorldPort: ILearningWorldPort + private learningWorldPort: ILearningWorldPort, ) { super(); this.learningWorldPort.registerAdapter(this, LocationScope._global); } - protected override preTasks = [this.loadAvatarPreTask, this.loadSpacePreTask]; + protected override preTasks = [this.loadSpacePreTask]; protected override async initializeScene(): Promise { this.scene.clearColor = new Color4(0.66, 0.83, 0.98, 1); @@ -106,11 +103,6 @@ export default class LearningSpaceSceneDefinition this.navigation.reset(); } - @bind - private async loadAvatarPreTask(): Promise { - await this.loadAvatarUseCase.executeAsync(); - } - @bind private async loadSpacePreTask(): Promise { const userLocation = this.getUserLocationUseCase.execute(); diff --git a/src/Components/CoreTest/Presentation/Babylon/SceneManagment/Scenes/LearningSpaceSceneDefinition.test.ts b/src/Components/CoreTest/Presentation/Babylon/SceneManagment/Scenes/LearningSpaceSceneDefinition.test.ts index f775ec0fb..413305ca1 100644 --- a/src/Components/CoreTest/Presentation/Babylon/SceneManagment/Scenes/LearningSpaceSceneDefinition.test.ts +++ b/src/Components/CoreTest/Presentation/Babylon/SceneManagment/Scenes/LearningSpaceSceneDefinition.test.ts @@ -1,6 +1,5 @@ import { NullEngine, Scene } from "@babylonjs/core"; import { mock } from "jest-mock-extended"; -import ILoadAvatarUseCase from "../../../../../Core/Application/UseCases/LoadAvatar/ILoadAvatarUseCase"; import ILoadLearningSpaceUseCase from "../../../../../Core/Application/UseCases/LoadLearningSpace/ILoadLearningSpaceUseCase"; import BUILDER_TYPES from "../../../../../Core/DependencyInjection/Builders/BUILDER_TYPES"; import CoreDIContainer from "../../../../../Core/DependencyInjection/CoreDIContainer"; @@ -20,7 +19,6 @@ const presentationDirectorMock = mock(); const presentationBuilderMock = mock(); const navigationMock = mock(); const loadSpaceUseCaseMock = mock(); -const loadAvatarUseCaseMock = mock(); const getUserLocationUseCaseMock = mock(); const getUserLocationUseCaseReturnValue = { @@ -35,28 +33,25 @@ describe("LearningSpaceScene", () => { CoreDIContainer.snapshot(); CoreDIContainer.rebind(BUILDER_TYPES.IPresentationDirector).toConstantValue( - presentationDirectorMock + presentationDirectorMock, ); CoreDIContainer.rebind(BUILDER_TYPES.ILearningSpaceBuilder).toConstantValue( - presentationBuilderMock + presentationBuilderMock, ); CoreDIContainer.rebind(BUILDER_TYPES.IAvatarBuilder).toConstantValue( - presentationBuilderMock + presentationBuilderMock, ); CoreDIContainer.rebind(BUILDER_TYPES.IAvatarCameraBuilder).toConstantValue( - presentationBuilderMock + presentationBuilderMock, ); CoreDIContainer.rebind(CORE_TYPES.INavigation).toConstantValue( - navigationMock + navigationMock, ); CoreDIContainer.rebind( - USECASE_TYPES.ILoadLearningSpaceUseCase + USECASE_TYPES.ILoadLearningSpaceUseCase, ).toConstantValue(loadSpaceUseCaseMock); - CoreDIContainer.rebind(USECASE_TYPES.ILoadAvatarUseCase).toConstantValue( - loadAvatarUseCaseMock - ); CoreDIContainer.rebind( - USECASE_TYPES.IGetUserLocationUseCase + USECASE_TYPES.IGetUserLocationUseCase, ).toConstantValue(getUserLocationUseCaseMock); }); @@ -73,23 +68,23 @@ describe("LearningSpaceScene", () => { test("initializeScene doesn't throw", () => { systemUnderTest["scene"] = new Scene(new NullEngine()); presentationBuilderMock.getPresenter.mockReturnValue( - mock() + mock(), ); presentationBuilderMock.getViewModel.mockReturnValue( - new AvatarCameraViewModel() + new AvatarCameraViewModel(), ); getUserLocationUseCaseMock.execute.mockReturnValue( - getUserLocationUseCaseReturnValue + getUserLocationUseCaseReturnValue, ); expect( - async () => await systemUnderTest["initializeScene"]() + async () => await systemUnderTest["initializeScene"](), ).not.toThrow(); }); test("preTasks calls the LoadSpace use case", async () => { getUserLocationUseCaseMock.execute.mockReturnValue( - getUserLocationUseCaseReturnValue + getUserLocationUseCaseReturnValue, ); for (const task of systemUnderTest["preTasks"]) { @@ -99,18 +94,6 @@ describe("LearningSpaceScene", () => { expect(loadSpaceUseCaseMock.executeAsync).toHaveBeenCalledTimes(1); }); - test("preTasks contains call to loadAvatarUseCase", async () => { - getUserLocationUseCaseMock.execute.mockReturnValue( - getUserLocationUseCaseReturnValue - ); - - for (const task of systemUnderTest["preTasks"]) { - await task(); - } - - expect(loadAvatarUseCaseMock.executeAsync).toHaveBeenCalledTimes(1); - }); - test("onLearningSpaceLoaded sets the private member spaceData", () => { const spaceData = new LearningSpaceTO(); spaceData.template = LearningSpaceTemplateType.L;