import { Component, Output, EventEmitter, OnInit, OnDestroy } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ArLoggerService } from '../../../../services/ar-logger.service'; @Component({ selector: 'app-first-input-assessment', standalone: true, imports: [CommonModule], templateUrl: './first-input-assessment.component.html', styleUrls: ['./first-input-assessment.component.css'] }) export class FirstInputAssessmentComponent implements OnInit, OnDestroy { @Output() testComplete = new EventEmitter(); @Output() redoTest = new EventEmitter(); showManualComplete = false; showRedoButton = false; firstInputDetected = false; sessionStartTime: number = 0; xrSession: any = null; constructor(private logger: ArLoggerService) {} ngOnInit(): void { this.logger.updateStatus('Assessment 1 initialized - Ready to begin first input detection'); setTimeout(() => { this.showManualComplete = true; this.showRedoButton = true; }, 30000); this.initializeWebXRTracking(); } ngOnDestroy(): void { this.exitWebXRSession(); } private initializeWebXRTracking(): void { const modelViewer = document.getElementById('first-input-model') as any; if (modelViewer) { modelViewer.addEventListener('ar-status', (event: any) => { if (event.detail.status === 'session-started') { this.xrSession = modelViewer.model?.webXRCamera?.session; this.sessionStartTime = performance.now(); this.firstInputDetected = false; console.log('WebXR session started for first input test'); this.logger.updateStatus('WebXR active - Waiting for first input'); this.setupFirstInputTracking(); } }); } } private setupFirstInputTracking(): void { if (!this.xrSession) return; const onXRFrame = (time: number, frame: any) => { if (!this.xrSession || this.firstInputDetected) return; const inputSources = this.xrSession.inputSources; for (let inputSource of inputSources) { if (inputSource.gamepad) { inputSource.gamepad.buttons.forEach((button: any, index: number) => { if (button.pressed && !this.firstInputDetected) { this.handleFirstInput('button', { buttonIndex: index, inputSource: inputSource.handedness }); return; } }); inputSource.gamepad.axes.forEach((axis: any, index: number) => { if (Math.abs(axis) > 0.1 && !this.firstInputDetected) { this.handleFirstInput('axis', { axisIndex: index, value: axis, inputSource: inputSource.handedness }); return; } }); } } if (this.xrSession && !this.firstInputDetected) { this.xrSession.requestAnimationFrame(onXRFrame); } }; this.xrSession.requestAnimationFrame(onXRFrame); } private handleFirstInput(inputType: string, inputData: any): void { if (this.firstInputDetected) return; this.firstInputDetected = true; const endTime = performance.now(); const sessionDuration = endTime - this.sessionStartTime; const testData = { duration: sessionDuration, firstInputType: inputType, firstInputData: inputData, sessionDuration: sessionDuration, completedSuccessfully: true }; this.logger.markTestComplete('firstInputTest'); console.log('First input detected:', inputType, inputData); this.logger.updateStatus(`First input detected: ${inputType} - Auto completing test`); setTimeout(() => { this.exitWebXRSession(); this.completeTest(); }, 2000); } manualCompleteFirstTest(): void { if (!this.firstInputDetected) { this.logger.markTestComplete('firstInputTest'); } this.completeTest(); } private completeTest(): void { this.showManualComplete = true; this.showRedoButton = true; this.testComplete.emit(); } onRedoTest(): void { this.firstInputDetected = false; this.showManualComplete = false; this.showRedoButton = false; this.exitWebXRSession(); this.redoTest.emit(); } private exitWebXRSession(): void { if (this.xrSession) { this.xrSession.end().then(() => { console.log('WebXR session ended'); this.xrSession = null; }).catch((err: any) => { console.error('Error ending WebXR session:', err); }); } } }