We use cookies to enhance your experience on the site
CodeWorlds

PROJECT: Comprehensive Roman Empire Application

Ave, legate! Consul Caesar.js has entrusted you with the greatest challenge - creating a complete application for managing the Roman Empire. This will be a true test of all the skills you've acquired during your NestJS training!

Project Specification: Imperium Management System

Your application must be a complete Roman legion management system, handling:

1. User System and Authorization

  • Legionary registration and login with different ranks
  • JWT Authentication with refresh tokens
  • Role-based access control (RBAC)
  • Multi-factor authentication for consuls

2. Legion Management

  • Legions - different types, capacities, equipment
  • Soldiers - legionaries with skills and histories
  • Campaigns - tribute expeditions with route planning
  • Forts - operational bases with resources

3. Tribute System

  • Inventory management - chests, tributes, artifacts
  • Trading system - exchange between legions
  • Auction house - bidding on rare items
  • Value tracking - tracking value over time

4. Communication and Coordination

  • Real-time messaging - WebSocket communication
  • Legion announcements - announcements for legions
  • Battle coordination - coordination during battles
  • Weather alerts - weather notifications

5. Analytics and Reports

  • Performance dashboards - legion statistics
  • Tribute reports - profit analyses
  • Legion analytics - legion efficiency
  • Predictive insights - AI-driven predictions

Technical Structure

Core Modules

1// app.module.ts
2import { Module } from '@nestjs/common';
3import { ConfigModule } from '@nestjs/config';
4import { TypeOrmModule } from '@nestjs/typeorm';
5import { GraphQLModule } from '@nestjs/graphql';
6import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
7import { BullModule } from '@nestjs/bull';
8import { CacheModule } from '@nestjs/cache-manager';
9import { EventEmitterModule } from '@nestjs/event-emitter';
10
11// Custom modules
12import { AuthModule } from './auth/auth.module';
13import { LegionModule } from './legion/legion.module';
14import { LegionaryModule } from './legionary/legionary.module';
15import { TributeModule } from './tribute/tribute.module';
16import { CampaignModule } from './campaign/campaign.module';
17import { CommunicationModule } from './communication/communication.module';
18import { AnalyticsModule } from './analytics/analytics.module';
19import { WebsocketModule } from './websocket/websocket.module';
20
21// Configuration
22import { databaseConfig, redisConfig, appConfig } from './config';
23import { validationSchema } from './config/validation.schema';
24
25@Module({
26 imports: [
27 // Configuration
28 ConfigModule.forRoot({
29 isGlobal: true,
30 load: [databaseConfig, redisConfig, appConfig],
31 validationSchema,
32 }),
33
34 // Database
35 TypeOrmModule.forRootAsync({
36 useFactory: (configService: ConfigService) => configService.get('database'),
37 inject: [ConfigService],
38 }),
39
40 // GraphQL
41 GraphQLModule.forRoot<ApolloDriverConfig>({
42 driver: ApolloDriver,
43 autoSchemaFile: 'schema.gql',
44 subscriptions: {
45 'graphql-ws': true,
46 },
47 context: ({ req, connection }) =>
48 connection ? { req: connection.context } : { req },
49 }),
50
51 // Redis & Caching
52 BullModule.forRootAsync({
53 useFactory: (configService: ConfigService) => configService.get('redis'),
54 inject: [ConfigService],
55 }),
56
57 CacheModule.registerAsync({
58 useFactory: (configService: ConfigService) => ({
59 store: 'redis',
60 ...configService.get('redis'),
61 ttl: 300, // 5 minutes default
62 }),
63 inject: [ConfigService],
64 }),
65
66 // Event system
67 EventEmitterModule.forRoot(),
68
69 // Feature modules
70 AuthModule,
71 LegionModule,
72 LegionaryModule,
73 TributeModule,
74 CampaignModule,
75 CommunicationModule,
76 AnalyticsModule,
77 WebsocketModule,
78 ],
79 providers: [
80 // Global guards
81 {
82 provide: APP_GUARD,
83 useClass: JwtAuthGuard,
84 },
85 {
86 provide: APP_GUARD,
87 useClass: RolesGuard,
88 },
89 // Global interceptors
90 {
91 provide: APP_INTERCEPTOR,
92 useClass: LoggingInterceptor,
93 },
94 {
95 provide: APP_INTERCEPTOR,
96 useClass: TransformInterceptor,
97 },
98 // Global filters
99 {
100 provide: APP_FILTER,
101 useClass: AllExceptionsFilter,
102 },
103 ],
104})
105export class AppModule {}

Advanced Features Implementation

1// auth/strategies/jwt.strategy.ts
2@Injectable()
3export class JwtStrategy extends PassportStrategy(Strategy) {
4 constructor(
5 private configService: ConfigService,
6 private userService: UserService,
7 ) {
8 super({
9 jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
10 ignoreExpiration: false,
11 secretOrKey: configService.get<string>('jwt.secret'),
12 });
13 }
14
15 async validate(payload: any) {
16 const user = await this.userService.findById(payload.sub);
17 if (!user || !user.isActive) {
18 throw new UnauthorizedException('Legionary not found or inactive');
19 }
20 return user;
21 }
22}
23
24// websocket/legion-communication.gateway.ts
25@WebSocketGateway({
26 cors: {
27 origin: '*',
28 },
29})
30export class LegionCommunicationGateway
31 implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
32
33 @WebSocketServer()
34 server: Server;
35
36 private logger: Logger = new Logger('LegionCommunicationGateway');
37 private legionaryConnections = new Map<string, string>(); // socketId -> legionaryId
38
39 afterInit(server: Server) {
40 this.logger.log('Legion Communication Gateway initialized');
41 }
42
43 async handleConnection(client: Socket, ...args: any[]) {
44 try {
45 const token = client.handshake.auth.token;
46 const legionary = await this.authService.validateToken(token);
47
48 this.legionaryConnections.set(client.id, legionary.id);
49 client.join(\`cohort_\${legionary.cohortId}\`);
50 client.join(\`legion_\${legionary.legionId}\`);
51
52 this.server.to(\`cohort_\${legionary.cohortId}\`).emit('legionaryJoined', {
53 legionary: legionary.name,
54 message: \`\${legionary.name} joined the communication channel\`,
55 });
56
57 this.logger.log(\`Legionary \${legionary.name} connected to legion communication\`);
58 } catch (error) {
59 this.logger.error('Connection failed:', error);
60 client.disconnect();
61 }
62 }
63
64 handleDisconnect(client: Socket) {
65 const legionaryId = this.legionaryConnections.get(client.id);
66 if (legionaryId) {
67 this.legionaryConnections.delete(client.id);
68 this.logger.log(\`Legionary \${legionaryId} disconnected\`);
69 }
70 }
71
72 @SubscribeMessage('cohortMessage')
73 handleCohortMessage(client: Socket, payload: any) {
74 const legionaryId = this.legionaryConnections.get(client.id);
75 const legionary = this.userService.findById(legionaryId);
76
77 client.to(\`cohort_\${legionary.cohortId}\`).emit('cohortMessage', {
78 from: legionary.name,
79 message: payload.message,
80 timestamp: new Date(),
81 });
82 }
83
84 @SubscribeMessage('legionAnnouncement')
85 @UseGuards(WsJwtGuard, WsRolesGuard)
86 @Roles('CENTURION', 'CONSUL')
87 handleLegionAnnouncement(client: Socket, payload: any) {
88 const legionaryId = this.legionaryConnections.get(client.id);
89 const legionary = this.userService.findById(legionaryId);
90
91 this.server.to(\`legion_\${legionary.legionId}\`).emit('legionAnnouncement', {
92 from: legionary.name,
93 rank: legionary.rank,
94 message: payload.message,
95 priority: payload.priority || 'normal',
96 timestamp: new Date(),
97 });
98 }
99}
100
101// analytics/services/advanced-analytics.service.ts
102@Injectable()
103export class AdvancedAnalyticsService {
104 constructor(
105 private dataSource: DataSource,
106 @InjectQueue('analytics') private analyticsQueue: Queue,
107 ) {}
108
109 async generateLegionPerformanceReport(legionId: number, period: string) {
110 const job = await this.analyticsQueue.add('legion-performance', {
111 legionId,
112 period,
113 });
114
115 return { jobId: job.id };
116 }
117
118 async getPredictiveTributeInsights(legionId: number) {
119 // Machine learning predictions (TensorFlow.js example)
120 const historicalData = await this.getHistoricalTributeData(legionId);
121 const predictions = await this.mlPredict(historicalData);
122
123 return {
124 predictedTributeValue: predictions.value,
125 confidence: predictions.confidence,
126 recommendedActions: predictions.actions,
127 timeframe: '30 days',
128 };
129 }
130
131 private async mlPredict(data: any[]) {
132 // Simple ML model example
133 const values = data.map(d => d.value);
134 const trend = this.calculateTrend(values);
135 const seasonality = this.calculateSeasonality(data);
136
137 return {
138 value: trend.nextPrediction * seasonality.factor,
139 confidence: Math.min(trend.confidence * seasonality.confidence, 0.95),
140 actions: this.generateRecommendations(trend, seasonality),
141 };
142 }
143
144 @Cron('0 2 * * *') // Daily at 2:00 AM
145 async generateDailyReports() {
146 const legions = await this.getActiveLegions();
147
148 for (const legion of legions) {
149 await this.analyticsQueue.add('daily-report', {
150 legionId: legion.id,
151 date: new Date(),
152 });
153 }
154 }
155}
156
157// tribute/services/auction.service.ts
158@Injectable()
159export class AuctionService {
160 constructor(
161 private auctionRepository: AuctionRepository,
162 private eventEmitter: EventEmitter2,
163 @InjectQueue('auction') private auctionQueue: Queue,
164 ) {}
165
166 async createAuction(tributeId: number, sellerId: number, startingPrice: number, duration: number) {
167 const auction = await this.auctionRepository.create({
168 tributeId,
169 sellerId,
170 startingPrice,
171 currentPrice: startingPrice,
172 endTime: new Date(Date.now() + duration * 1000),
173 status: 'ACTIVE',
174 });
175
176 // Schedule auction end
177 await this.auctionQueue.add(
178 'end-auction',
179 { auctionId: auction.id },
180 { delay: duration * 1000 }
181 );
182
183 this.eventEmitter.emit('auction.created', auction);
184 return auction;
185 }
186
187 async placeBid(auctionId: number, bidderId: number, amount: number) {
188 const auction = await this.auctionRepository.findById(auctionId);
189
190 if (auction.status !== 'ACTIVE' || new Date() > auction.endTime) {
191 throw new BadRequestException('Auction is not active');
192 }
193
194 if (amount <= auction.currentPrice) {
195 throw new BadRequestException('Bid must be higher than current price');
196 }
197
198 // Anti-sniping: extend auction if bid in last 5 minutes
199 const timeLeft = auction.endTime.getTime() - Date.now();
200 if (timeLeft < 5 * 60 * 1000) {
201 auction.endTime = new Date(auction.endTime.getTime() + 5 * 60 * 1000);
202 }
203
204 auction.currentPrice = amount;
205 auction.currentBidderId = bidderId;
206
207 await this.auctionRepository.save(auction);
208
209 this.eventEmitter.emit('auction.bid', {
210 auctionId,
211 bidderId,
212 amount,
213 timeLeft: Math.max(0, timeLeft),
214 });
215
216 return auction;
217 }
218
219 @OnEvent('auction.end')
220 async handleAuctionEnd(auctionId: number) {
221 const auction = await this.auctionRepository.findById(auctionId);
222
223 if (auction.currentBidderId) {
224 await this.transferTribute(auction.tributeId, auction.currentBidderId);
225 await this.transferFunds(auction.currentBidderId, auction.sellerId, auction.currentPrice);
226
227 auction.status = 'COMPLETED';
228 auction.winnerId = auction.currentBidderId;
229 } else {
230 auction.status = 'NO_BIDS';
231 }
232
233 await this.auctionRepository.save(auction);
234 this.eventEmitter.emit('auction.completed', auction);
235 }
236}

Tasks to complete

Stage 1: Basic architecture (Week 1)

  1. Project setup - NestJS, TypeORM, Redis configuration
  2. Authentication system - JWT, refresh tokens, role-based access
  3. Base entities - User, Legion, Cohort, Tribute basics
  4. API endpoints - CRUD operations for basic entities
  5. Basic tests - unit tests for services

Stage 2: Business functionalities (Week 2)

  1. Campaign system - planning and executing campaigns
  2. Trading system - tribute exchange between legionaries
  3. Legion management - managing legions and skills
  4. Notification system - real-time notifications
  5. Advanced validation - complex business rules

Stage 3: Real-time and advanced (Week 3)

  1. WebSocket integration - real-time communication
  2. Auction system - tribute auctions
  3. Analytics dashboard - statistics and metrics
  4. Background jobs - async task processing
  5. Performance optimization - caching, indexes, optimizations

Stage 4: Production and advanced (Week 4)

  1. GraphQL implementation - alternative API
  2. Rate limiting - protection against spam
  3. Monitoring - health checks, metrics, alerting
  4. Deployment - Docker, CI/CD, environment management
  5. Advanced security - security headers, CORS, data encryption

Evaluation criteria

Functionality (25%)

  • All required features work correctly
  • Comprehensive authorization and permissions system
  • Real-time communication between users
  • Advanced business features (auctions, missions, trading)

Code quality (25%)

  • Readable architecture and project structure
  • Proper use of design patterns
  • Consistent code style and naming conventions
  • Proper error handling and validation

Performance and scalability (20%)

  • Database query optimization
  • Effective caching strategies
  • Background job processing
  • Rate limiting and resource management

Tests (15%)

  • Comprehensive unit tests (>80% coverage)
  • Integration tests for key flows
  • E2E tests for main functionalities
  • Performance tests

Documentation (15%)

  • API documentation (Swagger/OpenAPI)
  • README with setup and deployment instructions
  • Architecture documentation
  • Code comments where needed

Bonus Points

  • GraphQL subscriptions for real-time updates
  • Machine learning predictions for tribute values
  • Microservices architecture with message queues
  • Advanced monitoring with Prometheus/Grafana
  • Mobile app communicating with the API

Example API endpoints

1// Legion Management
2GET /api/legions # List legions
3POST /api/legions # Create legion
4GET /api/legions/:id # Legion details
5PUT /api/legions/:id # Update legion
6DELETE /api/legions/:id # Delete legion
7
8// Cohort Management
9GET /api/cohorts # List cohorts
10POST /api/cohorts # Add cohort
11GET /api/cohorts/:id # Cohort details
12PUT /api/cohorts/:id # Update cohort
13POST /api/cohorts/:id/assign-legionaries # Assign legionaries
14POST /api/cohorts/:id/campaigns # Create campaign
15
16// Tribute System
17GET /api/tributes # List tributes
18POST /api/tributes # Add tribute
19GET /api/tributes/:id # Tribute details
20PUT /api/tributes/:id/transfer # Transfer tribute
21POST /api/tributes/:id/auction # List for auction
22
23// Auctions
24GET /api/auctions # Active auctions
25POST /api/auctions/:id/bid # Place a bid
26GET /api/auctions/:id/history # Bidding history
27
28// Analytics
29GET /api/analytics/legion/:id # Legion statistics
30GET /api/analytics/tribute-trends # Tribute value trends
31GET /api/analytics/legion-performance # Legion performance
32
33// Real-time WebSocket events
34cohort:message # Messages in cohort
35legion:announcement # Legion announcements
36auction:bid # New auction bid
37campaign:update # Campaign update
38tribute:discovered # Tribute discovered

This is the greatest challenge in the service of the Roman Empire! Good luck, legate - the Empire is counting on you!

Go to CodeWorlds