Skip to content

Commit

Permalink
feat: init prop stats handling; improvements for prop viewing
Browse files Browse the repository at this point in the history
  • Loading branch information
fearandesire committed Oct 28, 2024
1 parent c37060e commit fee72ae
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 23 deletions.
54 changes: 35 additions & 19 deletions src/commands/props/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export class UserCommand extends Subcommand {
}

public async viewActive(interaction: Subcommand.ChatInputCommandInteraction) {
await interaction.deferReply();
return this.viewActiveProps(interaction);
}

Expand Down Expand Up @@ -352,6 +353,7 @@ export class UserCommand extends Subcommand {
props,
'Active Props',
'Displaying props with active predictions',
{ isViewingActiveProps: true },
);
} catch (error) {
this.container.logger.error(error);
Expand Down Expand Up @@ -475,33 +477,44 @@ export class UserCommand extends Subcommand {
props: Prop[],
title: string,
description: string,
forPlayer = false,
options?: PropEmbedOptions,
) {
try {
if (props.length === 0) {
return interaction.editReply({
content: 'No props were found matching the search criteria.',
});
}
let embed: EmbedBuilder;
if (!options?.isViewingActiveProps) {
const firstProp = props[0];
const date = new DateManager().toDiscordUnix(firstProp.commence_time);
const eventId = firstProp.event_id;
embed = new EmbedBuilder()
.setTitle(`${title}`)
.setDescription(
`${description}\n\n**Event Information**\n🆔 **Event ID:** \`${eventId}\`\n🗓️ **Date:** ${date}\n${firstProp.home_team} vs ${firstProp.away_team}`,
)
.setColor('#0099ff')
.setTimestamp();

const firstProp = props[0];
const date = new DateManager().toDiscordUnix(firstProp.commence_time);
const eventId = firstProp.event_id;
const embed = new EmbedBuilder()
.setTitle(`${title}`)
.setDescription(
`${description}\n\n**Event Information**\n🆔 **Event ID:** \`${eventId}\`\n🗓️ **Date:** ${date}\n${firstProp.home_team} vs ${firstProp.away_team}`,
)
.setColor('#0099ff')
.setTimestamp();

const formattedProps = this.formatPropsForEmbed(props, {
displayingForPlayer: forPlayer,
});
for (const field of formattedProps) {
embed.addFields(field);
const formattedProps = this.formatPropsForEmbed(props);
for (const field of formattedProps) {
embed.addFields(field);
}
}
if (options?.isViewingActiveProps) {
embed = new EmbedBuilder()
.setTitle(title)
.setDescription(description)
.setColor('#0099ff')
.setTimestamp();

const formattedProps = this.formatPropsForEmbed(props);
for (const field of formattedProps) {
embed.addFields(field);
}
}

if (props.length > 25) {
embed.setFooter({
text: `Showing 25 out of ${props.length} props. More props are available, but cannot be displayed in this embed.`,
Expand All @@ -518,7 +531,6 @@ export class UserCommand extends Subcommand {

private formatPropsForEmbed(
props: Prop[],
options: { displayingForPlayer: boolean },
): { name: string; value: string }[] {
return props.slice(0, 25).map((prop) => {
let pointDisplay = '';
Expand Down Expand Up @@ -615,3 +627,7 @@ export class UserCommand extends Subcommand {
}
}
}

interface PropEmbedOptions {
isViewingActiveProps?: boolean;
}
13 changes: 12 additions & 1 deletion src/utils/api/Khronos/guild/guild-wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { GuildsApi, type Guild } from '@kh-openapi';
import {
GuildsApi,
type GetGuildsBySportAndConfigTypeRequest,
type Guild,
} from '@kh-openapi';
import { type IKH_API_CONFIG, KH_API_CONFIG } from '../KhronosInstances.js';
import type { Channel } from 'discord.js';
import { DiscordConfigEnums } from '../../common/interfaces/kh-pluto/kh-pluto.interface.js';
Expand Down Expand Up @@ -53,4 +57,11 @@ export default class GuildWrapper {
}
return logChannel;
}

async getGuildsForSportWithConfig(
params: GetGuildsBySportAndConfigTypeRequest,
): Promise<Guild[]> {
const guilds = await this.guildsApi.getGuildsBySportAndConfigType(params);
return guilds;
}
}
4 changes: 4 additions & 0 deletions src/utils/api/Khronos/props/propsApiWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,8 @@ export default class PropsApiWrapper {
async getPropsByPlayer(params: FindPropsByDescriptionRequest) {
return await this.propsApi.findPropsByDescription(params);
}

async getStatsProps() {
// Add none
}
}
41 changes: 40 additions & 1 deletion src/utils/api/common/interfaces/schemas/prop.schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import { z } from 'zod';
import {
nullable,
number,
object,
record,
string,
union,
z,
type infer,
} from 'zod';
import { BettingMarketSchema } from './betting-market.schema.js';

/**
Expand Down Expand Up @@ -75,3 +84,33 @@ export const PropOptionsSchema = z.object({
* Type definition for prop options.
*/
export type PropOptions = z.infer<typeof PropOptionsSchema>;

export const PredictionPercentageStatsSchema = z.object({
prop_id: z.string(),

home_team: z.string(),

away_team: z.string(),

total_predictions: z.number(),

percentages: z.record(z.number()),

betting_on: z.union([z.string(), z.number()]),

betting_on_label: z.string(),

description: z.string().nullable(),
});

export type PredictionPercentageStats = z.infer<
typeof PredictionPercentageStatsSchema
>;

export const PredictionStatsNotificationsArraySchema = z.array(
PredictionPercentageStatsSchema,
);

export type PredictionStatsNotificationsArray = z.infer<
typeof PredictionStatsNotificationsArraySchema
>;
31 changes: 29 additions & 2 deletions src/utils/api/controllers/props.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {
PredictionStatsNotificationsArraySchema,
PropArraySchema,
PropOptionsSchema,
type PredictionStatsNotificationsArray,
} from '../common/interfaces/index.js';
import {
GuildChannelArraySchema,
Expand All @@ -16,7 +18,7 @@ export class PropsController {
this.propsService = new PropsService();
}

validateRequestBody(body: RequestBody): ValidatedData | null {
validateReqPropEmbedBody(body: RequestBody): ValidatedData | null {
const propsResult = PropArraySchema.safeParse(body.props);
const guildChannelsResult = GuildChannelArraySchema.safeParse(
body.guildChannels,
Expand All @@ -43,7 +45,7 @@ export class PropsController {
async processDaily(
body: RequestBody,
): Promise<{ success: boolean; message: string }> {
const validatedData = this.validateRequestBody(body);
const validatedData = this.validateReqPropEmbedBody(body);

if (!validatedData) {
return { success: false, message: 'Invalid request body' };
Expand All @@ -64,4 +66,29 @@ export class PropsController {
message: 'Props processed and embeds created successfully',
};
}

validatePredictionStatsBody(
body: RequestBody,
): PredictionStatsNotificationsArray | null {
const result = PredictionStatsNotificationsArraySchema.safeParse(body);

if (!result.success) {
return null;
}

return result.data;
}

/**
* @summary Iterate through receiving data - create an embed for each record and display the stats of each prop.
* @description This method is used to post stats of the props that have just recently started. It will go through the incoming data which will have the stats already aggregated.
* Each object in the array will be the data included to make the embed.
*/
async processPostStart(body: RequestBody) {
const validatedData = this.validatePredictionStatsBody(body);

if (!validatedData) {
return { success: false, message: 'Invalid request body' };
}
}
}
6 changes: 6 additions & 0 deletions src/utils/api/routes/props/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ PropsRouter.post('/props/daily', async (ctx) => {
}
});

PropsRouter.post('/props/stats/post-start', async (ctx) => {
const result = await propsController.processPostStart(
ctx.request.body as RequestBody,
);
});

export default PropsRouter;

0 comments on commit fee72ae

Please sign in to comment.