@@ -209,88 +209,212 @@ AttributionGame<schedulerId, usingBatch, inputEncryption>::
209
209
// know that it is the preferred touchpoint as well.
210
210
// Thus at the end we will get the fully reversed attribution match vector of
211
211
// conversions and touchpoints.
212
- if (FLAGS_use_new_output_format) {
213
- // ToDo: Implement logic for generating attribution output in new format.
214
- } else {
215
- for (auto conversion = conversions.rbegin ();
216
- conversion != conversions.rend ();
217
- ++conversion) {
218
- auto conv = *conversion;
212
+ for (auto conversion = conversions.rbegin (); conversion != conversions.rend ();
213
+ ++conversion) {
214
+ auto conv = *conversion;
215
+
216
+ if constexpr (usingBatch) {
217
+ OMNISCIENT_ONLY_XLOGF (
218
+ DBG,
219
+ " Computing attributions for conversions: {}" ,
220
+ common::vecToString (
221
+ conv.ts .openToParty (common::PUBLISHER).getValue ()));
222
+ } else {
223
+ OMNISCIENT_ONLY_XLOGF (
224
+ DBG,
225
+ " Computing attributions for conversion: {}" ,
226
+ conv.ts .openToParty (common::PUBLISHER).getValue ());
227
+ }
228
+
229
+ // store if conversion has already been attributed
230
+ SecBit<schedulerId, usingBatch> hasAttributedTouchpoint;
231
+ if constexpr (usingBatch) {
232
+ hasAttributedTouchpoint = SecBit<schedulerId, usingBatch>{
233
+ std::vector<bool >(batchSize, false ), common::PUBLISHER};
234
+ } else {
235
+ hasAttributedTouchpoint =
236
+ SecBit<schedulerId, usingBatch>{false , common::PUBLISHER};
237
+ }
238
+
239
+ CHECK_EQ (touchpoints.size (), thresholds.size ())
240
+ << " touchpoints and thresholds are not the same length." ;
241
+
242
+ for (size_t i = touchpoints.size (); i >= 1 ; --i) {
243
+ auto tp = touchpoints.at (i - 1 );
244
+ auto threshold = thresholds.at (i - 1 );
219
245
220
246
if constexpr (usingBatch) {
221
247
OMNISCIENT_ONLY_XLOGF (
222
248
DBG,
223
- " Computing attributions for conversions : {}" ,
249
+ " Checking touchpoints : {}" ,
224
250
common::vecToString (
225
- conv .ts .openToParty (common::PUBLISHER).getValue ()));
251
+ tp .ts .openToParty (common::PUBLISHER).getValue ()));
226
252
} else {
227
253
OMNISCIENT_ONLY_XLOGF (
228
254
DBG,
229
- " Computing attributions for conversion : {}" ,
230
- conv .ts .openToParty (common::PUBLISHER).getValue ());
255
+ " Checking touchpoint : {}" ,
256
+ tp .ts .openToParty (common::PUBLISHER).getValue ());
231
257
}
232
258
233
- // store if conversion has already been attributed
234
- SecBit<schedulerId, usingBatch> hasAttributedTouchpoint;
259
+ auto isTouchpointAttributable =
260
+ attributionRule.isAttributable (tp, conv, threshold);
261
+
262
+ auto isAttributed = isTouchpointAttributable & !hasAttributedTouchpoint;
263
+
264
+ hasAttributedTouchpoint = isAttributed | hasAttributedTouchpoint;
265
+
235
266
if constexpr (usingBatch) {
236
- hasAttributedTouchpoint = SecBit<schedulerId, usingBatch>{
237
- std::vector<bool >(batchSize, false ), common::PUBLISHER};
267
+ OMNISCIENT_ONLY_XLOGF (
268
+ DBG,
269
+ " isTouchpointAttributable={}, isAttributed={}, hasAttributedTouchpoint={}" ,
270
+ common::vecToString (
271
+ isTouchpointAttributable.extractBit ().getValue ()),
272
+ common::vecToString (isAttributed.extractBit ().getValue ()),
273
+ common::vecToString (
274
+ hasAttributedTouchpoint.extractBit ().getValue ()));
238
275
} else {
239
- hasAttributedTouchpoint =
240
- SecBit<schedulerId, usingBatch>{false , common::PUBLISHER};
276
+ OMNISCIENT_ONLY_XLOGF (
277
+ DBG,
278
+ " isTouchpointAttributable={}, isAttributed={}, hasAttributedTouchpoint={}" ,
279
+ isTouchpointAttributable.extractBit ().getValue (),
280
+ isAttributed.extractBit ().getValue (),
281
+ hasAttributedTouchpoint.extractBit ().getValue ());
241
282
}
242
283
243
- CHECK_EQ (touchpoints.size (), thresholds.size ())
244
- << " touchpoints and thresholds are not the same length." ;
245
-
246
- for (size_t i = touchpoints.size (); i >= 1 ; --i) {
247
- auto tp = touchpoints.at (i - 1 );
248
- auto threshold = thresholds.at (i - 1 );
249
-
250
- if constexpr (usingBatch) {
251
- OMNISCIENT_ONLY_XLOGF (
252
- DBG,
253
- " Checking touchpoints: {}" ,
254
- common::vecToString (
255
- tp.ts .openToParty (common::PUBLISHER).getValue ()));
256
- } else {
257
- OMNISCIENT_ONLY_XLOGF (
258
- DBG,
259
- " Checking touchpoint: {}" ,
260
- tp.ts .openToParty (common::PUBLISHER).getValue ());
261
- }
284
+ attributions.push_back (isAttributed);
285
+ }
286
+ }
287
+ std::reverse (attributions.begin (), attributions.end ());
288
+ return attributions;
289
+ }
262
290
263
- auto isTouchpointAttributable =
264
- attributionRule.isAttributable (tp, conv, threshold);
265
-
266
- auto isAttributed = isTouchpointAttributable & !hasAttributedTouchpoint;
267
-
268
- hasAttributedTouchpoint = isAttributed | hasAttributedTouchpoint;
269
-
270
- if constexpr (usingBatch) {
271
- OMNISCIENT_ONLY_XLOGF (
272
- DBG,
273
- " isTouchpointAttributable={}, isAttributed={}, hasAttributedTouchpoint={}" ,
274
- common::vecToString (
275
- isTouchpointAttributable.extractBit ().getValue ()),
276
- common::vecToString (isAttributed.extractBit ().getValue ()),
277
- common::vecToString (
278
- hasAttributedTouchpoint.extractBit ().getValue ()));
279
- } else {
280
- OMNISCIENT_ONLY_XLOGF (
281
- DBG,
282
- " isTouchpointAttributable={}, isAttributed={}, hasAttributedTouchpoint={}" ,
283
- isTouchpointAttributable.extractBit ().getValue (),
284
- isAttributed.extractBit ().getValue (),
285
- hasAttributedTouchpoint.extractBit ().getValue ());
286
- }
291
+ template <
292
+ int schedulerId,
293
+ bool usingBatch,
294
+ common::InputEncryption inputEncryption>
295
+ const std::vector<AttributionReformattedOutputFmt<schedulerId, usingBatch>>
296
+ AttributionGame<schedulerId, usingBatch, inputEncryption>::
297
+ computeAttributionsHelperV2 (
298
+ const std::vector<
299
+ PrivateTouchpoint<schedulerId, usingBatch, inputEncryption>>&
300
+ touchpoints,
301
+ const std::vector<
302
+ PrivateConversion<schedulerId, usingBatch, inputEncryption>>&
303
+ conversions,
304
+ const AttributionRule<schedulerId, usingBatch, inputEncryption>&
305
+ attributionRule,
306
+ const std::vector<std::vector<SecTimestamp<schedulerId, usingBatch>>>&
307
+ thresholds,
308
+ size_t batchSize) {
309
+ if constexpr (usingBatch) {
310
+ if (batchSize == 0 ) {
311
+ throw std::invalid_argument (
312
+ " Must provide positive batch size for batch execution!" );
313
+ }
314
+ }
315
+ std::vector<AttributionReformattedOutputFmt<schedulerId, usingBatch>>
316
+ attributionsOutput;
317
+ // We will be attributing on a sorted vector of touchpoints and conversions
318
+ // (based on timestamps).
319
+ // The preferred touchpoint for a conversion will be a valid attributable
320
+ // touchpoint with nearest timestamp to the conversion. In order to compute
321
+ // this efficiently, we will traverse backwards on both conversion and
322
+ // touchpoint vector. So that when we find a valid attributable touchpoint, we
323
+ // know that it is the preferred touchpoint as well.
324
+ // Thus at the end we will get the fully reversed attribution match vector of
325
+ // conversions and touchpoints.
326
+ for (auto conversion = conversions.rbegin (); conversion != conversions.rend ();
327
+ ++conversion) {
328
+ auto conv = *conversion;
329
+
330
+ if constexpr (usingBatch) {
331
+ OMNISCIENT_ONLY_XLOGF (
332
+ DBG,
333
+ " Computing attributions for conversions: {}" ,
334
+ common::vecToString (
335
+ conv.ts .openToParty (common::PUBLISHER).getValue ()));
336
+ } else {
337
+ OMNISCIENT_ONLY_XLOGF (
338
+ DBG,
339
+ " Computing attribution for conversion: {}" ,
340
+ conv.ts .openToParty (common::PUBLISHER).getValue ());
341
+ }
342
+
343
+ // store if conversion has already been attributed
344
+ SecBit<schedulerId, usingBatch> hasAttributedTouchpoint;
345
+ if constexpr (usingBatch) {
346
+ hasAttributedTouchpoint = SecBit<schedulerId, usingBatch>{
347
+ std::vector<bool >(batchSize, false ), common::PUBLISHER};
348
+ } else {
349
+ hasAttributedTouchpoint =
350
+ SecBit<schedulerId, usingBatch>{false , common::PUBLISHER};
351
+ }
352
+
353
+ CHECK_EQ (touchpoints.size (), thresholds.size ())
354
+ << " touchpoints and thresholds are not the same length." ;
355
+
356
+ SecAdId<schedulerId, usingBatch> attributedAdId;
357
+ uint64_t defaultAdId = 0 ;
358
+ if constexpr (usingBatch) {
359
+ // initialize the ad_id to be 0, is_attributed to be false:
360
+ attributedAdId = SecAdId<schedulerId, usingBatch>{
361
+ std::vector<uint64_t >(batchSize, defaultAdId), common::PUBLISHER};
362
+ } else {
363
+ attributedAdId =
364
+ SecAdId<schedulerId, usingBatch>(defaultAdId, common::PUBLISHER);
365
+ }
366
+ for (size_t i = touchpoints.size (); i >= 1 ; --i) {
367
+ auto tp = touchpoints.at (i - 1 );
368
+ auto threshold = thresholds.at (i - 1 );
287
369
288
- attributions.push_back (isAttributed);
370
+ if constexpr (usingBatch) {
371
+ OMNISCIENT_ONLY_XLOGF (
372
+ DBG,
373
+ " Checking touchpoints: {}" ,
374
+ common::vecToString (
375
+ tp.ts .openToParty (common::PUBLISHER).getValue ()));
376
+ } else {
377
+ OMNISCIENT_ONLY_XLOGF (
378
+ DBG,
379
+ " Checking touchpoint: {}" ,
380
+ tp.ts .openToParty (common::PUBLISHER).getValue ());
289
381
}
382
+
383
+ auto isTouchpointAttributable =
384
+ attributionRule.isAttributable (tp, conv, threshold);
385
+
386
+ auto isAttributed = isTouchpointAttributable & !hasAttributedTouchpoint;
387
+
388
+ hasAttributedTouchpoint = isAttributed | hasAttributedTouchpoint;
389
+
390
+ if constexpr (usingBatch) {
391
+ OMNISCIENT_ONLY_XLOGF (
392
+ DBG,
393
+ " isTouchpointAttributable={}, isAttributed={}, hasAttributedTouchpoint={}" ,
394
+ common::vecToString (
395
+ isTouchpointAttributable.extractBit ().getValue ()),
396
+ common::vecToString (isAttributed.extractBit ().getValue ()),
397
+ common::vecToString (
398
+ hasAttributedTouchpoint.extractBit ().getValue ()));
399
+ } else {
400
+ OMNISCIENT_ONLY_XLOGF (
401
+ DBG,
402
+ " isTouchpointAttributable={}, isAttributed={}, hasAttributedTouchpoint={}" ,
403
+ isTouchpointAttributable.extractBit ().getValue (),
404
+ isAttributed.extractBit ().getValue (),
405
+ hasAttributedTouchpoint.extractBit ().getValue ());
406
+ }
407
+
408
+ attributedAdId = attributedAdId.mux (isAttributed, tp.adId );
290
409
}
291
- std::reverse (attributions.begin (), attributions.end ());
410
+ attributionsOutput.push_back (
411
+ AttributionReformattedOutputFmt<schedulerId, usingBatch>{
412
+ .ad_id = attributedAdId,
413
+ .conv_value = conv.convValue ,
414
+ .is_attributed = hasAttributedTouchpoint});
292
415
}
293
- return attributions;
416
+ std::reverse (attributionsOutput.begin (), attributionsOutput.end ());
417
+ return attributionsOutput;
294
418
}
295
419
296
420
template <
0 commit comments