163 lines
5.3 KiB
TypeScript
163 lines
5.3 KiB
TypeScript
import {
|
|
Controller, Get, Post, Body, Patch, Param, Query, UseGuards, Request
|
|
} from '@nestjs/common';
|
|
import {
|
|
ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiQuery, ApiParam
|
|
} from '@nestjs/swagger';
|
|
import { AIGuideService } from './ai-guide.service';
|
|
import { AIQueryDto } from './dto/ai-query.dto';
|
|
import { ARContentQueryDto } from './dto/ar-content-query.dto';
|
|
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
|
|
import { RolesGuard } from '../../common/guards/roles.guard';
|
|
import { Roles } from '../../common/decorators/roles.decorator';
|
|
import { AIGuideInteraction } from '../../entities/ai-guide-interaction.entity';
|
|
import { ARContent } from '../../entities/ar-content.entity';
|
|
|
|
@ApiTags('AI Guide')
|
|
@Controller('ai-guide')
|
|
@UseGuards(JwtAuthGuard)
|
|
@ApiBearerAuth('JWT-auth')
|
|
export class AIGuideController {
|
|
constructor(private readonly aiGuideService: AIGuideService) {}
|
|
|
|
@Post('query')
|
|
@ApiOperation({ summary: 'Ask AI guide a question' })
|
|
@ApiResponse({
|
|
status: 201,
|
|
description: 'AI response generated successfully',
|
|
schema: {
|
|
type: 'object',
|
|
properties: {
|
|
response: { type: 'string' },
|
|
suggestions: { type: 'array', items: { type: 'string' } },
|
|
arContent: { type: 'array' },
|
|
nearbyPlaces: { type: 'array' },
|
|
audioGuideUrl: { type: 'string' },
|
|
sessionId: { type: 'string' }
|
|
}
|
|
}
|
|
})
|
|
async queryAIGuide(@Body() queryDto: AIQueryDto, @Request() req) {
|
|
return this.aiGuideService.processAIQuery(queryDto, req.user.id);
|
|
}
|
|
|
|
@Post('ar-content/nearby')
|
|
@ApiOperation({ summary: 'Get nearby AR content' })
|
|
@ApiResponse({ status: 200, type: [ARContent] })
|
|
async getNearbyARContent(@Body() queryDto: ARContentQueryDto) {
|
|
return this.aiGuideService.getNearbyARContent(queryDto);
|
|
}
|
|
|
|
@Patch('ar-content/:id/view')
|
|
@ApiOperation({ summary: 'Increment AR content view count' })
|
|
@ApiParam({ name: 'id', type: 'string' })
|
|
async incrementARView(@Param('id') id: string) {
|
|
await this.aiGuideService.incrementARViewCount(id);
|
|
return { success: true, message: 'View count incremented' };
|
|
}
|
|
|
|
@Post('interactions/:id/rate')
|
|
@ApiOperation({ summary: 'Rate AI interaction' })
|
|
@ApiParam({ name: 'id', type: 'string' })
|
|
async rateInteraction(
|
|
@Param('id') id: string,
|
|
@Body() body: { rating: number },
|
|
@Request() req
|
|
) {
|
|
// TODO: Implement rating functionality
|
|
return { success: true, message: 'Rating saved' };
|
|
}
|
|
|
|
@Get('stats')
|
|
@UseGuards(RolesGuard)
|
|
@Roles('admin')
|
|
@ApiOperation({ summary: 'Get AI usage statistics (Admin only)' })
|
|
getAIUsageStats() {
|
|
return this.aiGuideService.getAIUsageStats();
|
|
}
|
|
|
|
// SMART RECOMMENDATIONS
|
|
@Get('recommendations/personalized')
|
|
@ApiOperation({ summary: 'Get personalized recommendations' })
|
|
@ApiQuery({ name: 'latitude', required: false, type: Number })
|
|
@ApiQuery({ name: 'longitude', required: false, type: Number })
|
|
@ApiQuery({ name: 'category', required: false, type: String })
|
|
async getPersonalizedRecommendations(
|
|
@Request() req,
|
|
@Query('latitude') latitude?: number,
|
|
@Query('longitude') longitude?: number,
|
|
@Query('category') category?: string,
|
|
) {
|
|
const queryDto: AIQueryDto = {
|
|
query: 'Show me personalized recommendations',
|
|
interactionType: 'recommendations' as any,
|
|
latitude,
|
|
longitude,
|
|
metadata: { category }
|
|
};
|
|
|
|
return this.aiGuideService.processAIQuery(queryDto, req.user.id);
|
|
}
|
|
|
|
// MONUMENT RECOGNITION
|
|
@Post('recognize-monument')
|
|
@ApiOperation({ summary: 'Recognize monument from image or location' })
|
|
async recognizeMonument(@Body() body: {
|
|
imageUrl?: string;
|
|
latitude?: number;
|
|
longitude?: number;
|
|
}, @Request() req) {
|
|
const queryDto: AIQueryDto = {
|
|
query: 'What is this monument?',
|
|
interactionType: 'monument-recognition' as any,
|
|
imageUrl: body.imageUrl,
|
|
latitude: body.latitude,
|
|
longitude: body.longitude,
|
|
};
|
|
|
|
return this.aiGuideService.processAIQuery(queryDto, req.user.id);
|
|
}
|
|
|
|
// AUDIO GUIDES
|
|
@Post('audio-guide')
|
|
@ApiOperation({ summary: 'Generate audio guide for location' })
|
|
async generateAudioGuide(@Body() body: {
|
|
placeId?: string;
|
|
latitude?: number;
|
|
longitude?: number;
|
|
language?: string;
|
|
}, @Request() req) {
|
|
const queryDto: AIQueryDto = {
|
|
query: 'Generate audio guide for this location',
|
|
interactionType: 'audio-guide' as any,
|
|
placeId: body.placeId,
|
|
latitude: body.latitude,
|
|
longitude: body.longitude,
|
|
language: body.language,
|
|
};
|
|
|
|
return this.aiGuideService.processAIQuery(queryDto, req.user.id);
|
|
}
|
|
|
|
// SMART DIRECTIONS
|
|
@Post('directions')
|
|
@ApiOperation({ summary: 'Get smart directions with points of interest' })
|
|
async getSmartDirections(@Body() body: {
|
|
destinationPlaceId?: string;
|
|
latitude?: number;
|
|
longitude?: number;
|
|
travelMode?: string;
|
|
}, @Request() req) {
|
|
const queryDto: AIQueryDto = {
|
|
query: `Get directions to ${body.destinationPlaceId || 'destination'}`,
|
|
interactionType: 'directions' as any,
|
|
placeId: body.destinationPlaceId,
|
|
latitude: body.latitude,
|
|
longitude: body.longitude,
|
|
metadata: { travelMode: body.travelMode || 'walking' }
|
|
};
|
|
|
|
return this.aiGuideService.processAIQuery(queryDto, req.user.id);
|
|
}
|
|
}
|