// Trading Room State — decision-making with time constraints
//
// Included globally from index.php (right after $pos0 is read) so any
// part of the page - not just content/tradingroom.php - can read
// $info_mode / $media_mode / $live / $draft / $pos0 / etc. Guarded so an
// extra include (e.g. content/tradingroom.php including it explicitly for
// documentation) is a cheap no-op.
if (defined('TRADINGROOM_STATE_LOADED')) {
return;
}
define('TRADINGROOM_STATE_LOADED', true);
$stateCacheFile = CACHE . 'tradingroom.state';
// --- Gather inputs ---
$live = get_YoutubeLive()['live'] == 'true';
$ctrader = (bool)$pos0;
$active_positions = $ctrader && strpos($pos0, 'Active Positions') !== false;
$rcounts = null;
if ($live) {
$rcounts = @unserialize(@file_get_contents(URI."tmp/restream_stats"));
}
$viewers = is_array($rcounts) && isset($rcounts['stats']['viewers']) ? intval($rcounts['stats']['viewers']) : 0;
$destinations = is_array($rcounts) && isset($rcounts['stats']['destinations']) ? $rcounts['stats']['destinations'] : 0;
// Ensure wp_draft cache exists before Tradelog_draft_content.php tries to read it.
// That file only reads the cache; Tradelog_draft_status.php is the one that writes it
// (normally triggered by the footer's 1px updateSiteCounts.php image). Without this,
// the first tradingroom load after the cache is cleared sees no draft even when one exists.
$_wpDraftCache = CACHE.'wp_draft';
if (!file_exists($_wpDraftCache) || filemtime($_wpDraftCache) < (time() - 20)) {
include(URI.'lib/3rd/wordpress/Tradelog_draft_status.php');
}
// Only consider there's a draft if Tradelog_draft_content.php actually loaded content
$_REQUEST['part'] = 'time';
ob_start();
include(URI.'lib/3rd/wordpress/Tradelog_draft_content.php');
$wpdate = intval(ob_get_clean());
$draft = $wpdate > 0;
// --- Compute desired (immediate) state ---
$desired = [];
if ($live) $desired['media_mode'] = 'live';
elseif ($draft && $active_positions) $desired['media_mode'] = 'capture';
else $desired['media_mode'] = 'cam';
if ($draft) $desired['info_mode'] = 'session';
elseif ($ctrader) $desired['info_mode'] = 'ctrader';
elseif ($live) $desired['info_mode'] = 'livestream';
else $desired['info_mode'] = 'idle';
$desired['show_chart'] = !$live && !$draft;
$desired['show_draft'] = $draft;
// --- Time constraints (seconds) before transitioning to the resting/default state ---
// The delay only applies when idling out (e.g. screenshot→cam, session→idle).
// Returning to an active state (e.g. trade reopens) is always immediate.
$delays = [
'media_mode' => 900, // 15 min — keep screenshot after positions close
'info_mode' => 0, // immediate — draft/ctrader data may no longer be valid
'show_chart' => 0, // immediate
'show_draft' => 0, // immediate
];
$resting = [
'media_mode' => 'cam',
'info_mode' => 'idle',
'show_chart' => false,
'show_draft' => false,
];
// --- Read saved state ---
$saved = [];
if (file_exists($stateCacheFile)) {
$saved = @unserialize(@file_get_contents($stateCacheFile));
if (!is_array($saved)) $saved = [];
}
$now = time();
$state = [];
foreach ($desired as $key => $newValue) {
$oldValue = isset($saved[$key]['value']) ? $saved[$key]['value'] : null;
$since = isset($saved[$key]['since']) ? $saved[$key]['since'] : $now;
if ($newValue !== $oldValue) {
// Only delay when heading TO the resting value, and (for media_mode)
// only coming FROM 'capture' - the 5min grace period is for keeping
// the trade screenshot up after positions close, not for keeping a
// dead 'live' embed around after the stream ends.
$fromCapture = $key !== 'media_mode' || $oldValue === 'capture';
if ($oldValue !== null && $newValue === $resting[$key] && $fromCapture && ($now - $since) < $delays[$key]) {
$state[$key] = ['value' => $oldValue, 'since' => $since];
} else {
$state[$key] = ['value' => $newValue, 'since' => $now];
}
} else {
$state[$key] = ['value' => $newValue, 'since' => $now];
}
}
@file_put_contents($stateCacheFile, serialize($state), LOCK_EX);
// --- Export layout variables ---
$media_mode = $state['media_mode']['value'];
$info_mode = $state['info_mode']['value'];
$show_chart = $state['show_chart']['value'];
$show_draft = $state['show_draft']['value'];
// --- Purge LiteSpeed's /blog page cache when the header status badge
// would change ($live or $info_mode flipped) - otherwise it can keep
// showing a stale "Active Position"/Trading Room button on cached /blog
// pages for up to litespeed.conf.cache-ttl_pub (1800s). $pos0's live text
// isn't tracked here - that changes often while already showing the badge
// and isn't worth a purge on its own.
$badgeCacheFile = CACHE . 'tradingroom.badge';
$badgeNow = ['live' => $live, 'info_mode' => $info_mode];
$badgeSaved = @unserialize(@file_get_contents($badgeCacheFile));
if ($badgeSaved !== $badgeNow) {
@file_put_contents($badgeCacheFile, serialize($badgeNow), LOCK_EX);
if (is_array($badgeSaved)) {
@file_get_contents(ULOCAL.'lib/3rd/wordpress/lscache-purge.php');
}
}
- Trading Room
-
Fx News
- Signals
-
Money
-
Insights
-
Apps
// Trading Room State — decision-making with time constraints
//
// Included globally from index.php (right after $pos0 is read) so any
// part of the page - not just content/tradingroom.php - can read
// $info_mode / $media_mode / $live / $draft / $pos0 / etc. Guarded so an
// extra include (e.g. content/tradingroom.php including it explicitly for
// documentation) is a cheap no-op.
if (defined('TRADINGROOM_STATE_LOADED')) {
return;
}
define('TRADINGROOM_STATE_LOADED', true);
$stateCacheFile = CACHE . 'tradingroom.state';
// --- Gather inputs ---
$live = get_YoutubeLive()['live'] == 'true';
$ctrader = (bool)$pos0;
$active_positions = $ctrader && strpos($pos0, 'Active Positions') !== false;
$rcounts = null;
if ($live) {
$rcounts = @unserialize(@file_get_contents(URI."tmp/restream_stats"));
}
$viewers = is_array($rcounts) && isset($rcounts['stats']['viewers']) ? intval($rcounts['stats']['viewers']) : 0;
$destinations = is_array($rcounts) && isset($rcounts['stats']['destinations']) ? $rcounts['stats']['destinations'] : 0;
// Ensure wp_draft cache exists before Tradelog_draft_content.php tries to read it.
// That file only reads the cache; Tradelog_draft_status.php is the one that writes it
// (normally triggered by the footer's 1px updateSiteCounts.php image). Without this,
// the first tradingroom load after the cache is cleared sees no draft even when one exists.
$_wpDraftCache = CACHE.'wp_draft';
if (!file_exists($_wpDraftCache) || filemtime($_wpDraftCache) < (time() - 20)) {
include(URI.'lib/3rd/wordpress/Tradelog_draft_status.php');
}
// Only consider there's a draft if Tradelog_draft_content.php actually loaded content
$_REQUEST['part'] = 'time';
ob_start();
include(URI.'lib/3rd/wordpress/Tradelog_draft_content.php');
$wpdate = intval(ob_get_clean());
$draft = $wpdate > 0;
// --- Compute desired (immediate) state ---
$desired = [];
if ($live) $desired['media_mode'] = 'live';
elseif ($draft && $active_positions) $desired['media_mode'] = 'capture';
else $desired['media_mode'] = 'cam';
if ($draft) $desired['info_mode'] = 'session';
elseif ($ctrader) $desired['info_mode'] = 'ctrader';
elseif ($live) $desired['info_mode'] = 'livestream';
else $desired['info_mode'] = 'idle';
$desired['show_chart'] = !$live && !$draft;
$desired['show_draft'] = $draft;
// --- Time constraints (seconds) before transitioning to the resting/default state ---
// The delay only applies when idling out (e.g. screenshot→cam, session→idle).
// Returning to an active state (e.g. trade reopens) is always immediate.
$delays = [
'media_mode' => 900, // 15 min — keep screenshot after positions close
'info_mode' => 0, // immediate — draft/ctrader data may no longer be valid
'show_chart' => 0, // immediate
'show_draft' => 0, // immediate
];
$resting = [
'media_mode' => 'cam',
'info_mode' => 'idle',
'show_chart' => false,
'show_draft' => false,
];
// --- Read saved state ---
$saved = [];
if (file_exists($stateCacheFile)) {
$saved = @unserialize(@file_get_contents($stateCacheFile));
if (!is_array($saved)) $saved = [];
}
$now = time();
$state = [];
foreach ($desired as $key => $newValue) {
$oldValue = isset($saved[$key]['value']) ? $saved[$key]['value'] : null;
$since = isset($saved[$key]['since']) ? $saved[$key]['since'] : $now;
if ($newValue !== $oldValue) {
// Only delay when heading TO the resting value, and (for media_mode)
// only coming FROM 'capture' - the 5min grace period is for keeping
// the trade screenshot up after positions close, not for keeping a
// dead 'live' embed around after the stream ends.
$fromCapture = $key !== 'media_mode' || $oldValue === 'capture';
if ($oldValue !== null && $newValue === $resting[$key] && $fromCapture && ($now - $since) < $delays[$key]) {
$state[$key] = ['value' => $oldValue, 'since' => $since];
} else {
$state[$key] = ['value' => $newValue, 'since' => $now];
}
} else {
$state[$key] = ['value' => $newValue, 'since' => $now];
}
}
@file_put_contents($stateCacheFile, serialize($state), LOCK_EX);
// --- Export layout variables ---
$media_mode = $state['media_mode']['value'];
$info_mode = $state['info_mode']['value'];
$show_chart = $state['show_chart']['value'];
$show_draft = $state['show_draft']['value'];
// --- Purge LiteSpeed's /blog page cache when the header status badge
// would change ($live or $info_mode flipped) - otherwise it can keep
// showing a stale "Active Position"/Trading Room button on cached /blog
// pages for up to litespeed.conf.cache-ttl_pub (1800s). $pos0's live text
// isn't tracked here - that changes often while already showing the badge
// and isn't worth a purge on its own.
$badgeCacheFile = CACHE . 'tradingroom.badge';
$badgeNow = ['live' => $live, 'info_mode' => $info_mode];
$badgeSaved = @unserialize(@file_get_contents($badgeCacheFile));
if ($badgeSaved !== $badgeNow) {
@file_put_contents($badgeCacheFile, serialize($badgeNow), LOCK_EX);
if (is_array($badgeSaved)) {
@file_get_contents(ULOCAL.'lib/3rd/wordpress/lscache-purge.php');
}
}