Skip to content

Commit 1260c9c

Browse files
feat: support multiple events
1 parent 26193b5 commit 1260c9c

File tree

3 files changed

+75
-30
lines changed

3 files changed

+75
-30
lines changed

src/events/questions.ts src/events/constants.ts

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
export const actions = ['flashlight', 'vote'];
2+
3+
export const events = [
4+
{
5+
name: 'aeg-beneficiary-concert',
6+
availableActions: ['flashlight'],
7+
},
8+
{
9+
name: 'pop-concert',
10+
availableActions: ['flashlight'],
11+
},
12+
{
13+
name: 'AEC-OC',
14+
availableActions: ['flashlight', 'vote'],
15+
},
16+
{
17+
name: 'AEC-CC',
18+
availableActions: ['flashlight', 'vote'],
19+
},
20+
];
21+
122
export const questions = [
223
{
324
question: 'What does CPU stand for?',

src/events/events.controller.ts

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
1-
import { Controller, Get, Query, Req, Res } from '@nestjs/common';
2-
import { Request, Response } from 'express';
1+
import { Controller, Get, Param, Query, Res } from '@nestjs/common';
2+
import { Response } from 'express';
3+
import { events } from './constants';
34
import { EventsService } from './events.service';
45

56
@Controller('events')
67
export class EventsController {
78
constructor(private readonly eventsService: EventsService) {}
89

9-
@Get('/subscribe')
10+
@Get('/:id/subscribe')
1011
poll(
11-
@Req() req: Request,
1212
@Res() res: Response,
13+
@Param('id') id: string,
1314
@Query('isInitialRequest') isInitialRequestParam: string,
1415
) {
16+
const event = events.find((e) => e.name === id);
17+
if (!event) return res.status(404).json({ message: 'Event not found' });
18+
1519
const isInitialRequest = isInitialRequestParam === 'true';
1620
if (isInitialRequest) {
17-
return res.json(this.eventsService.getCurrentAction());
21+
return res.json(this.eventsService.getCurrentAction(event.name));
1822
}
1923

20-
const client = (data: any) => res.json(data);
21-
this.eventsService.addClient(client);
22-
req.on('close', () => this.eventsService.removeClient(client));
24+
const cb = (data: any) => res.json(data);
25+
this.eventsService.addClient({ subscribedEvent: event.name, callback: cb });
2326
}
2427
}

src/events/events.service.ts

+43-22
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,70 @@
11
import { Injectable } from '@nestjs/common';
2+
import { events, questions } from './constants';
3+
4+
interface Client {
5+
subscribedEvent: string;
6+
callback: (data: any) => void;
7+
}
28

39
@Injectable()
410
export class EventsService {
5-
private clients: Array<(data: any) => void> = [];
6-
private data: any = { action: null };
11+
private clients: Client[] = [];
12+
private currentActions: Record<string, any> = events.reduce(
13+
(acc, event) => ({ ...acc, [event.name]: { action: null } }),
14+
{},
15+
);
716

817
constructor() {
9-
this.scheduleNewAction();
18+
events.forEach((event) => this.scheduleNewAction(event.name));
1019
}
1120

12-
addClient(client: (data: any) => void) {
21+
addClient(client: Client) {
1322
this.clients.push(client);
1423
}
1524

16-
removeClient(client: (data: any) => void) {
17-
this.clients = this.clients.filter((c) => c !== client);
18-
}
25+
notifyClients(event: string) {
26+
// Notify all clients subscribed to the event
27+
this.clients
28+
.filter((client) => client.subscribedEvent === event)
29+
.forEach((client) => client.callback(this.currentActions[event]));
1930

20-
notifyClients() {
21-
this.clients.forEach((c) => c(this.data));
22-
this.clients = [];
31+
// Remove clients subscribed to the event
32+
this.clients = this.clients.filter(
33+
(client) => client.subscribedEvent !== event,
34+
);
2335
}
2436

25-
scheduleNewAction() {
26-
const actions = ['flashlight', 'vote'];
27-
const selectedAction = actions[Math.floor(Math.random() * actions.length)];
28-
const delay = Math.floor(Math.random() * 15000) + 5000; // 5-20 seconds
37+
scheduleNewAction(event: string) {
38+
const availableActions = events.find(
39+
(e) => e.name === event,
40+
).availableActions;
41+
const selectedAction =
42+
availableActions[Math.floor(Math.random() * availableActions.length)];
43+
const delay = Math.floor(Math.random() * 15000) + 15000; // 15-30 seconds
2944

3045
setTimeout(() => {
31-
this.data = { action: selectedAction };
32-
this.notifyClients();
46+
if (selectedAction === 'flashlight') {
47+
this.currentActions[event] = { action: { type: 'flashlight' } };
48+
} else if (selectedAction === 'vote') {
49+
const question =
50+
questions[Math.floor(Math.random() * questions.length)];
51+
this.currentActions[event] = { action: { type: 'vote', ...question } };
52+
}
53+
54+
this.notifyClients(event);
3355

3456
setTimeout(
3557
() => {
36-
this.data = { action: null };
37-
this.notifyClients();
38-
this.scheduleNewAction();
58+
this.currentActions[event] = { action: null };
59+
this.notifyClients(event);
60+
this.scheduleNewAction(event);
3961
},
4062
selectedAction === 'flashlight' ? 5000 : 15000,
4163
);
4264
}, delay);
4365
}
4466

45-
getCurrentAction() {
46-
if (Object.keys(this.data).length > 0) return this.data;
47-
return { action: null };
67+
getCurrentAction(event: string) {
68+
return this.currentActions[event];
4869
}
4970
}

0 commit comments

Comments
 (0)