import _ from "lodash"; import { CampaignData, CampaignModel } from "../models/CampaignModel"; import { ChoiceRequest, HeaderBiddingType } from "../models"; import { FeatureConfigService } from "../services/FeatureConfig.service"; import { Device } from "../models/device.model"; export type DeviceOS = "ios" | "android" | "unknown"; export type EnvironmentType = "web" | "in-app" | "unknown"; export type RequestSource = { deviceOS: DeviceOS; environmentType: EnvironmentType; }; const operatingSystemMapping: { [k: string]: DeviceOS } = { IOS: "ios", IPHONE: "ios", IPAD: "ios", "APPLE IOS": "ios", IPADOS: "ios", ANDROID: "android", "FIRE OS": "android", FIREOS: "android", }; export function decodeRequestSource(encoded: string): RequestSource { const envStr = encoded[0]; const osStr = encoded[1]; let env: EnvironmentType; switch (envStr) { case "w": env = "web"; break; case "i": env = "in-app"; break; default: env = "unknown"; } let os: DeviceOS; switch (osStr) { case "a": os = "android"; break; case "i": os = "ios"; break; default: os = "unknown"; } return { environmentType: env, deviceOS: os }; } export function encodeRequestSource(requestSource: RequestSource): string { return requestSource.environmentType[0] + requestSource.deviceOS[0]; } export function getRequestSource(request: ChoiceRequest): RequestSource { return { environmentType: request.environment_type, deviceOS: getDeviceOS(request.device), }; } export const getEnvironmentTypeFromSourceType = ( sourceType: string | undefined ): EnvironmentType => { if (sourceType === "WEBMOBILE") { return "web"; } else { return "in-app"; } }; export const getHeaderBiddingTypeFromRequest = ( requestHeaderBiddingType: string | undefined ): HeaderBiddingType | undefined => { switch (requestHeaderBiddingType) { case "MAX": return HeaderBiddingType.MAX; case "Prebid": return HeaderBiddingType.PreBidJS; case "TAM": return HeaderBiddingType.AmazonTAM; default: return undefined; } }; export const isWeb = (request: ChoiceRequest): boolean => { return request.environment_type === "web"; }; export const getDeviceOS = (device?: Device): DeviceOS => { if (device?.os) { return operatingSystemMapping[device.os.toUpperCase()]; } return "unknown"; }; export const initCampaigns = async (request: ChoiceRequest, campaignModel: CampaignModel) => { const campaignData = await campaignModel.findByMultipleId(request.campaigns.map((c) => c.id)); _.forEach(campaignData, (v, k) => { if (v == null) { throw new Error(`Campaign ${k} missing in request`); } }); request.campaignData = campaignData as Record; const fallbackCampaigns = FeatureConfigService.getInstance().getParameterValueAsStringList( request, "ms-choices.fallback-campaign-ids", ",", [] ); fallbackCampaigns.forEach((cId) => request.groupedCampaignIds.fallback.add(cId)); request.campaigns.forEach((c) => { const data = request.campaignData[c.id]; c.id = `${c.id}`; c.metadata ??= {}; c.metadataTmp ??= {}; c.stepsPassedStatus ??= {}; if (request.groupedCampaignIds.fallback.has(c.id)) { return; } if (campaignModel.isMarketplace(data)) { request.groupedCampaignIds.marketplace.add(c.id); } else if (campaignModel.isProgrammatic(data)) { request.groupedCampaignIds.programmatic.add(c.id); } else { request.groupedCampaignIds.managed.add(c.id); } }); }; export const DEFAULT_LABELS = ["inventory_source", "environment_type", "device_os"]; export const initPromLabels = async (request: ChoiceRequest) => { const paramInfo = FeatureConfigService.getInstance().getParameterInfo( request, "ms-filter.exp-remove-prog", "0" ); request.allMetricsLabels = { inventory_source: request.inventory_source, environment_type: request.environment_type, device_os: getDeviceOS(request.device), }; request.globalRequestLabels = { has_managed: (request.groupedCampaignIds.managed.size > 0).toString(), has_prog: (request.groupedCampaignIds.programmatic.size > 0).toString(), has_mkp: (request.groupedCampaignIds.marketplace.size > 0).toString(), has_fb: (request.groupedCampaignIds.fallback.size > 0).toString(), fixed_price: "false", private_auction: "false", open_auction: "false", test_pop: paramInfo?.popIndex ?? -1, tmax: getTMaxBucket(request.tMax), header_bidding_type: request.headerBiddingType ?? "unknown", is_gdpr_applied: request.user?.is_gdpr_applied === undefined ? "unknown" : request.user.is_gdpr_applied.toString(), }; }; const getTMaxBucket = (tMax: number | undefined): number => { switch (true) { case tMax === undefined: return -1; case tMax! >= 200 && tMax! < 300: return 200; case tMax! >= 300 && tMax! < 400: return 300; default: return 400; } }; export const hasCampaign = (request: ChoiceRequest): boolean => { return request.campaigns.length > 0; };