Usage Scenarios#
Scenario 1: Flash Giveaway (Unique Winners)#
Use grand when each user should win at most once.
<?php
use Infocyph\Draw\Draw;
$draw = new Draw();
$result = $draw->execute([
'method' => 'grand',
'items' => ['gift_card' => 10, 'vip_pass' => 2],
'candidates' => $userIds,
]);
Check fulfillment:
<?php
if ($result['meta']['fulfilled'] === false) {
// inspect partialReason + unfilledCount
}
Scenario 1b: Grand Draw from CSV Source#
When candidates come from a file instead of an in-memory list:
<?php
$result = $draw->execute([
'method' => 'grand',
'items' => ['gift_card' => 5],
'sourceFile' => '/path/to/users.csv',
]);
CSV notes:
first column is treated as user ID
duplicates are deduplicated
no header auto-skip
Scenario 2: Weighted Reward Amounts#
Use lucky with weighted amount maps for controlled payout distributions.
<?php
$result = $draw->execute([
'method' => 'lucky',
'items' => [
[
'item' => 'coins',
'chances' => 100,
'amountMode' => 'weighted',
'amounts' => ['10' => 0.65, '50' => 0.25, '100' => 0.10],
],
],
'options' => ['count' => 100],
]);
Scenario 3: Rotation Without Repeats#
Use weightedElimination for weighted picks that remove selected items.
<?php
$result = $draw->execute([
'method' => 'weightedElimination',
'items' => [
['name' => 'tier_a', 'weight' => 5],
['name' => 'tier_b', 'weight' => 3],
['name' => 'tier_c', 'weight' => 2],
],
'options' => ['count' => 3],
]);
Scenario 4: Rule-Aware Campaign with Explainability#
Use campaign.run with withExplain for why/why-not traces.
<?php
use Infocyph\Draw\State\MemoryCachePool;
$result = $draw->execute([
'method' => 'campaign.run',
'items' => [
'gold' => ['count' => 1, 'weight' => 3, 'group' => 'premium'],
'silver' => ['count' => 3, 'weight' => 1, 'group' => 'basic'],
],
'candidates' => $userIds,
'options' => [
'cachePool' => new MemoryCachePool(),
'rules' => [
'perUserCap' => 1,
'groupQuota' => ['premium' => 1, 'basic' => 3],
],
'withExplain' => true,
],
]);
Inspect explain payload:
<?php
$explainByItem = $result['raw']['explain'] ?? [];
$goldExplain = $explainByItem['gold'] ?? [];
// each element includes status, slot, rejectedSummary, and attempts
Scenario 5: Multi-Phase Campaign#
Use campaign.batch when campaigns unfold in stages.
<?php
$result = $draw->execute([
'method' => 'campaign.batch',
'candidates' => $userIds,
'options' => [
'rules' => ['perUserCap' => 1],
'phases' => [
[
'name' => 'launch',
'items' => ['starter' => ['count' => 100, 'weight' => 2]],
],
[
'name' => 'retention',
'items' => ['booster' => ['count' => 50, 'weight' => 1]],
],
],
],
]);
Note:
phases share the same cachePool for a single batch request by default,
so rule counters can carry across phases.
Scenario 6: Reproducible Simulation Run#
Use campaign.simulate with seed for deterministic repeated analysis.
<?php
$result = $draw->execute([
'method' => 'campaign.simulate',
'items' => [
'gold' => ['count' => 1, 'weight' => 2],
'silver' => ['count' => 2, 'weight' => 1],
],
'candidates' => $userIds,
'options' => [
'iterations' => 5000,
'seed' => 42,
],
]);
Scenario 7: Auditable Production Execution#
Capture and verify campaign audits.
<?php
use Infocyph\Draw\Audit\AuditTrail;
$audit = $result['raw']['audit'];
$verified = AuditTrail::verify(
$audit,
$auditConfiguration,
$result['raw']['winners'],
$seedFingerprint,
$sharedSecret,
);