Skip to content

Commit

Permalink
feat: support multiple events
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin-Frost committed May 19, 2024
1 parent 26193b5 commit 1260c9c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 30 deletions.
21 changes: 21 additions & 0 deletions src/events/questions.ts → src/events/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
export const actions = ['flashlight', 'vote'];

export const events = [
{
name: 'aeg-beneficiary-concert',
availableActions: ['flashlight'],
},
{
name: 'pop-concert',
availableActions: ['flashlight'],
},
{
name: 'AEC-OC',
availableActions: ['flashlight', 'vote'],
},
{
name: 'AEC-CC',
availableActions: ['flashlight', 'vote'],
},
];

export const questions = [
{
question: 'What does CPU stand for?',
Expand Down
19 changes: 11 additions & 8 deletions src/events/events.controller.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import { Controller, Get, Query, Req, Res } from '@nestjs/common';
import { Request, Response } from 'express';
import { Controller, Get, Param, Query, Res } from '@nestjs/common';
import { Response } from 'express';
import { events } from './constants';
import { EventsService } from './events.service';

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

@Get('/subscribe')
@Get('/:id/subscribe')
poll(
@Req() req: Request,
@Res() res: Response,
@Param('id') id: string,
@Query('isInitialRequest') isInitialRequestParam: string,
) {
const event = events.find((e) => e.name === id);
if (!event) return res.status(404).json({ message: 'Event not found' });

const isInitialRequest = isInitialRequestParam === 'true';
if (isInitialRequest) {
return res.json(this.eventsService.getCurrentAction());
return res.json(this.eventsService.getCurrentAction(event.name));
}

const client = (data: any) => res.json(data);
this.eventsService.addClient(client);
req.on('close', () => this.eventsService.removeClient(client));
const cb = (data: any) => res.json(data);
this.eventsService.addClient({ subscribedEvent: event.name, callback: cb });
}
}
65 changes: 43 additions & 22 deletions src/events/events.service.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,70 @@
import { Injectable } from '@nestjs/common';
import { events, questions } from './constants';

interface Client {
subscribedEvent: string;
callback: (data: any) => void;
}

@Injectable()
export class EventsService {
private clients: Array<(data: any) => void> = [];
private data: any = { action: null };
private clients: Client[] = [];
private currentActions: Record<string, any> = events.reduce(
(acc, event) => ({ ...acc, [event.name]: { action: null } }),
{},
);

constructor() {
this.scheduleNewAction();
events.forEach((event) => this.scheduleNewAction(event.name));
}

addClient(client: (data: any) => void) {
addClient(client: Client) {
this.clients.push(client);
}

removeClient(client: (data: any) => void) {
this.clients = this.clients.filter((c) => c !== client);
}
notifyClients(event: string) {
// Notify all clients subscribed to the event
this.clients
.filter((client) => client.subscribedEvent === event)
.forEach((client) => client.callback(this.currentActions[event]));

notifyClients() {
this.clients.forEach((c) => c(this.data));
this.clients = [];
// Remove clients subscribed to the event
this.clients = this.clients.filter(
(client) => client.subscribedEvent !== event,
);
}

scheduleNewAction() {
const actions = ['flashlight', 'vote'];
const selectedAction = actions[Math.floor(Math.random() * actions.length)];
const delay = Math.floor(Math.random() * 15000) + 5000; // 5-20 seconds
scheduleNewAction(event: string) {
const availableActions = events.find(
(e) => e.name === event,
).availableActions;
const selectedAction =
availableActions[Math.floor(Math.random() * availableActions.length)];
const delay = Math.floor(Math.random() * 15000) + 15000; // 15-30 seconds

setTimeout(() => {
this.data = { action: selectedAction };
this.notifyClients();
if (selectedAction === 'flashlight') {
this.currentActions[event] = { action: { type: 'flashlight' } };
} else if (selectedAction === 'vote') {
const question =
questions[Math.floor(Math.random() * questions.length)];
this.currentActions[event] = { action: { type: 'vote', ...question } };
}

this.notifyClients(event);

setTimeout(
() => {
this.data = { action: null };
this.notifyClients();
this.scheduleNewAction();
this.currentActions[event] = { action: null };
this.notifyClients(event);
this.scheduleNewAction(event);
},
selectedAction === 'flashlight' ? 5000 : 15000,
);
}, delay);
}

getCurrentAction() {
if (Object.keys(this.data).length > 0) return this.data;
return { action: null };
getCurrentAction(event: string) {
return this.currentActions[event];
}
}

0 comments on commit 1260c9c

Please sign in to comment.