BachelorarbeitUmfrage/src/app/components/test-suite/assessments/spatial-stability-assessment/spatial-stability-assessmen...

175 lines
4.9 KiB
TypeScript

import {
Component,
AfterViewInit,
OnDestroy,
ViewChild,
ElementRef,
CUSTOM_ELEMENTS_SCHEMA,
ChangeDetectorRef,
EventEmitter,
Output,
inject
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MetricsTrackerService } from '../../../../services/metrics-tracker.service';
import '../../../../../assets/scripts/model-viewer';
@Component({
selector: 'app-spatial-stability-assessment',
standalone: true,
imports: [CommonModule, FormsModule],
templateUrl: './spatial-stability-assessment.component.html',
styleUrls: ['./spatial-stability-assessment.component.css'],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class SpatialStabilityAssessmentComponent implements AfterViewInit, OnDestroy { // <-- Implement OnDestroy
@ViewChild('modelViewer') modelViewerRef!: ElementRef<any>;
@Output() testComplete = new EventEmitter<void>();
@Output() redoTest = new EventEmitter<number>();
private metricsService = inject(MetricsTrackerService);
public verticalOffset = 0;
public currentPhase = 0; // 0: waiting, 1: adjust, 2: lock, 3: countdown, 4: complete
public remainingTime = 20;
public progressPercentage = 0;
private initialArAnchor: { x: number, y: number, z: number } | null = null;
private lockedPosition: { verticalOffset: number, anchor: string } | null = null;
private countdownInterval: any = null;
protected isModelPlaced = false;
constructor(private cdr: ChangeDetectorRef) {
this.logInteraction = this.logInteraction.bind(this);
}
ngAfterViewInit() {
const modelViewer = this.modelViewerRef.nativeElement;
this.metricsService.startDeviceOrientationTracking();
this.metricsService.startArTracking(modelViewer);
modelViewer.addEventListener('ar-status', (event: any) => {
if (event.detail.status === 'session-started' && !this.isModelPlaced) {
setTimeout(() => this.getInitialAnchor(), 1000);
}
});
}
public logInteraction(event: Event) {
this.metricsService.logInteraction(event);
}
private async getInitialAnchor() {
const modelViewer = this.modelViewerRef.nativeElement;
const anchorString = modelViewer.getAnchor();
if (!anchorString.includes('not placed')) {
const coords = anchorString.split(' ').map(parseFloat);
this.initialArAnchor = { x: coords[0], y: coords[1], z: coords[2] };
this.isModelPlaced = true;
this.currentPhase = 1;
this.cdr.detectChanges();
} else {
setTimeout(() => this.getInitialAnchor(), 500);
}
}
onSliderInput() {
if (this.initialArAnchor && this.currentPhase === 1) {
const newY = this.initialArAnchor.y + this.verticalOffset;
const anchor = `${this.initialArAnchor.x} ${newY} ${this.initialArAnchor.z}`;
this.modelViewerRef.nativeElement.setAttribute('ar-anchor', anchor);
}
}
lockPosition() {
this.lockedPosition = {
verticalOffset: this.verticalOffset,
anchor: this.modelViewerRef.nativeElement.getAttribute('ar-anchor')
};
this.currentPhase = 2;
}
adjustMore() {
this.currentPhase = 1;
}
startCountdown() {
this.currentPhase = 3;
this.remainingTime = 20;
this.progressPercentage = 0;
this.countdownInterval = setInterval(() => {
this.remainingTime--;
this.progressPercentage = ((20 - this.remainingTime) / 20) * 100;
if (this.remainingTime <= 0) {
this.completeTest(true);
}
this.cdr.detectChanges();
}, 1000);
}
cancelTest() {
if (this.countdownInterval) {
clearInterval(this.countdownInterval);
this.countdownInterval = null;
}
this.currentPhase = 2;
this.metricsService.logInteraction(new CustomEvent('test-cancelled', { detail: { phase: 'countdown' }}));
}
private completeTest(wasCompleted: boolean) {
if (this.countdownInterval) {
clearInterval(this.countdownInterval);
this.countdownInterval = null;
}
const finalResults = {
testCompletedSuccessfully: wasCompleted,
initialAnchor: this.initialArAnchor,
lockedPosition: this.lockedPosition,
};
this.metricsService.logInteraction(new CustomEvent('test-results', {
detail: {
testName: 'SpatialStability',
results: finalResults
}
}));
if (wasCompleted) {
this.currentPhase = 4;
}
if(wasCompleted) {
this.testComplete.emit();
}
}
restartTest() {
this.currentPhase = 1;
this.remainingTime = 20;
this.progressPercentage = 0;
this.lockedPosition = null;
if (this.countdownInterval) {
clearInterval(this.countdownInterval);
this.countdownInterval = null;
}
this.metricsService.resetMetrics();
}
finishAssessment() {
this.testComplete.emit();
}
ngOnDestroy() {
if (this.countdownInterval) {
clearInterval(this.countdownInterval);
}
this.metricsService.cleanup();
}
}