infocyph/game-draw

Generates Item and Item count for winners.

Maintainers

Package info

github.com/infocyph/Game-Draw

pkg:composer/infocyph/game-draw

Statistics

Installs: 4 724

Dependents: 0

Suggesters: 0

Stars: 14

Open Issues: 1

3.1 2024-11-08 08:59 UTC

This package is auto-updated.

Last update: 2026-04-06 17:12:47 UTC


README

Unified draw engine with one request contract and one response contract for every draw method.

Requirements

  • PHP 8.4+
  • BCMath extension

Install

composer require infocyph/game-draw

Unified API

Use Infocyph\Draw\Draw as the only public draw entrypoint.

Request shape

[
    'method' => '...',      // required
    'items' => [...],       // required
    'candidates' => [...],  // required for grand + campaign.*
    'sourceFile' => '...',  // optional alternative for grand
    'options' => [...],     // optional
]

Response shape

[
    'method' => '...',
    'entries' => [
        [
            'itemId' => ?string,
            'candidateId' => ?string,
            'value' => mixed,
            'meta' => array
        ]
    ],
    'raw' => mixed,
    'meta' => [
        'mode' => 'single|multi',
        'requestedCount' => int,
        'returnedCount' => int
    ]
]

Single-pick and multi-pick methods both return entries[].

Supported methods

  • lucky
  • grand
  • probability
  • elimination
  • weightedElimination
  • roundRobin
  • cumulative
  • batched
  • timeBased
  • weightedBatch
  • sequential
  • rangeWeighted
  • campaign.run
  • campaign.batch
  • campaign.simulate

Examples

use Infocyph\Draw\Draw;

$draw = new Draw();

lucky

$result = $draw->execute([
    'method' => 'lucky',
    'items' => [
        ['item' => 'gift_a', 'chances' => 10, 'amounts' => [1]],
        ['item' => 'gift_b', 'chances' => 20, 'amounts' => [2]],
    ],
    'options' => ['count' => 2],
]);

grand

$result = $draw->execute([
    'method' => 'grand',
    'items' => ['gift_a' => 5, 'gift_b' => 2],
    'candidates' => ['u1', 'u2', 'u3', 'u4'],
    'options' => ['retryCount' => 50],
]);

probability

$result = $draw->execute([
    'method' => 'probability',
    'items' => [
        ['name' => 'item1', 'weight' => 0.2],
        ['name' => 'item2', 'weight' => 0.8],
    ],
    'options' => ['count' => 3],
]);

elimination

$result = $draw->execute([
    'method' => 'elimination',
    'items' => [
        ['name' => 'item1'],
        ['name' => 'item2'],
    ],
    'options' => ['count' => 2],
]);

weightedElimination

$result = $draw->execute([
    'method' => 'weightedElimination',
    'items' => [
        ['name' => 'item1', 'weight' => 10],
        ['name' => 'item2', 'weight' => 20],
    ],
    'options' => ['count' => 2],
]);

roundRobin

$result = $draw->execute([
    'method' => 'roundRobin',
    'items' => [
        ['name' => 'item1'],
        ['name' => 'item2'],
    ],
    'options' => ['count' => 3],
]);

cumulative

$result = $draw->execute([
    'method' => 'cumulative',
    'items' => [
        ['name' => 'item1'],
        ['name' => 'item2'],
    ],
    'options' => ['count' => 3],
]);

batched

$result = $draw->execute([
    'method' => 'batched',
    'items' => [
        ['name' => 'item1'],
        ['name' => 'item2'],
        ['name' => 'item3'],
    ],
    'options' => ['count' => 2, 'withReplacement' => false],
]);

timeBased

$result = $draw->execute([
    'method' => 'timeBased',
    'items' => [
        ['name' => 'item1', 'weight' => 10, 'time' => 'daily'],
        ['name' => 'item2', 'weight' => 20, 'time' => 'weekly'],
    ],
    'options' => ['count' => 2],
]);

weightedBatch

$result = $draw->execute([
    'method' => 'weightedBatch',
    'items' => [
        ['name' => 'item1', 'weight' => 10],
        ['name' => 'item2', 'weight' => 20],
    ],
    'options' => ['count' => 3],
]);

sequential

$result = $draw->execute([
    'method' => 'sequential',
    'items' => [
        ['name' => 'item1'],
        ['name' => 'item2'],
    ],
    'options' => ['count' => 3],
]);

rangeWeighted

$result = $draw->execute([
    'method' => 'rangeWeighted',
    'items' => [
        ['name' => 'item1', 'min' => 1, 'max' => 50, 'weight' => 10],
        ['name' => 'item2', 'min' => 5, 'max' => 25, 'weight' => 15],
    ],
    'options' => ['count' => 2],
]);

campaign.run

$result = $draw->execute([
    'method' => 'campaign.run',
    'items' => [
        'gold' => ['count' => 1, 'group' => 'premium'],
        'silver' => ['count' => 2, 'group' => 'basic'],
    ],
    'candidates' => ['u1', 'u2', 'u3', 'u4'],
    'options' => [
        'rules' => [
            'perUserCap' => 1,
            'perItemCap' => ['gold' => 1],
            'groupQuota' => ['premium' => 1, 'basic' => 2],
        ],
        'retryLimit' => 100,
        'withExplain' => true,
    ],
]);

campaign.batch

$result = $draw->execute([
    'method' => 'campaign.batch',
    'items' => ['bootstrap' => ['count' => 1]],
    'candidates' => ['u1', 'u2', 'u3', 'u4'],
    'options' => [
        'rules' => ['perUserCap' => 1],
        'phases' => [
            ['name' => 'phase_1', 'items' => ['item_a' => ['count' => 2]]],
            ['name' => 'phase_2', 'items' => ['item_b' => ['count' => 2]]],
        ],
        'retryLimit' => 100,
    ],
]);

campaign.simulate

$result = $draw->execute([
    'method' => 'campaign.simulate',
    'items' => ['gold' => ['count' => 1], 'silver' => ['count' => 2]],
    'candidates' => ['u1', 'u2', 'u3', 'u4'],
    'options' => ['iterations' => 1000, 'retryLimit' => 100],
]);