| Current Path : /home/seto/testhive.pm/includes/ |
| Current File : /home/seto/testhive.pm/includes/distribution.php |
<?php
// Shared distribution helpers
/**
* Pick one item from $items using the 'weight' key for weighted random selection.
* Falls back to uniform random if all weights are zero.
*/
function weighted_random(array $items): ?array {
if (empty($items)) return null;
$total = 0.0;
foreach ($items as $item) {
$total += (float)($item['weight'] ?? 1);
}
if ($total <= 0) {
return $items[array_rand($items)];
}
$rand = (mt_rand(0, PHP_INT_MAX - 1) / PHP_INT_MAX) * $total;
$cumulative = 0.0;
foreach ($items as $item) {
$cumulative += (float)($item['weight'] ?? 1);
if ($rand < $cumulative) return $item;
}
return end($items);
}
/**
* On-demand: try to assign a link to $pageId.
* Returns assignment array or null if page falls outside coverage.
*/
function assign_page_ondemand(int $pageId): ?array {
$campaigns = db()->query(
"SELECT id, target_url, weight, coverage_percent, rotation_days
FROM campaigns WHERE status='active'"
)->fetchAll();
if (empty($campaigns)) return null;
$campaign = weighted_random($campaigns);
if (!$campaign) return null;
// Coverage roll
if (mt_rand(0, 99) >= (float)$campaign['coverage_percent']) return null;
$links = db()->prepare("SELECT id, text, weight FROM links WHERE campaign_id=?");
$links->execute([$campaign['id']]);
$linkRows = $links->fetchAll();
if (empty($linkRows)) return null;
$link = weighted_random($linkRows);
if (!$link) return null;
$now = time();
$expiresAt = $now + max(1, (int)$campaign['rotation_days']) * 86400;
db()->prepare(
"INSERT OR REPLACE INTO page_assignments
(page_id, link_id, campaign_id, assigned_at, expires_at)
VALUES (?, ?, ?, ?, ?)"
)->execute([$pageId, $link['id'], $campaign['id'], $now, $expiresAt]);
return [
'link_id' => (int)$link['id'],
'campaign_id' => (int)$campaign['id'],
'link_text' => $link['text'],
'target_url' => $campaign['target_url'],
'expires_at' => $expiresAt,
];
}