#!/usr/bin/perl -w

# market_update.pl
# (c) CWZ, LLC

# Update the in-game Crypto market

use strict;
use lib '.';
use CWZ;

Exec: {
	# Calculate the SUM of all units in the game market and base the delta_fluc on volume movers
	# ..reset delta_fluc, move previous unit_ref into unit_prev, sum up current unit_vol, and decay unit_ref with a
	# half-life towards current unit_vol (so the delta_fluc carries on for several minutes)
	qDb_do("UPDATE Crypto_Game cg SET delta_fluc = 0, unit_prev = unit_ref,
												 unit_vol = (SELECT IFNULL(SUM(units), 0) FROM Player_Crypto WHERE cd = cg.cd),
												 unit_ref = unit_ref + (unit_vol - unit_prev) / 2");
	qDb_do("UPDATE Crypto_Game SET unit_ref = unit_vol WHERE ABS(unit_vol - unit_ref) < 10");			# Obsolete when live
	qDb_do("UPDATE Crypto_Game SET delta_fluc = LEAST((unit_vol - unit_ref) / unit_ref * delta_base, delta_base)
					WHERE delta_base > 0 AND unit_ref != 0");
	qDb_do("UPDATE Crypto_Game SET delta_fluc = GREATEST((unit_ref - unit_vol) / unit_ref * delta_base, delta_base)
					WHERE delta_base < 0 AND unit_ref != 0");

	# Create a chance for the market to fluctuate randomly on top of volume fluctuation
	# ..RNG fluctuation can vary only up to +/- 10% of the delta_base
	qDb_do("UPDATE Crypto_Game SET delta_fluc = delta_fluc + rand() * (delta_base * 0.2) - (delta_base * 0.1)
					WHERE delta_base <> 0 AND RAND() < 0.1");

	# Do the update
	qDb_do("UPDATE Crypto_Game SET price_now = price_now + price_now * (delta_base + delta_fluc)");

	# Make sure we didn't bump up against max/min limits
	# ..if we have, continually temper delta_base until next drug story time
	qDb_do("UPDATE Crypto_Game SET delta_base = delta_base * 0.5
				WHERE (price_now > price_max AND delta_base > 0) OR (price_now < price_min AND delta_base < 0)");

	# Update the calculated market field in Player table to reflect new market prices
	qDb_do("UPDATE Player p
	SET p.market = (
	    SELECT COALESCE(
	        SUM(
	            IFNULL(pc.units, 0) * IFNULL(cl.price_now, 0)
	            + IFNULL(pc.units, 0) * IFNULL(cg.price_now, 0)
	        ),
	        0
	    )
	    FROM Player_Crypto pc
	    LEFT JOIN Crypto_Game cg ON pc.cd = cg.cd
	    LEFT JOIN Crypto_Live cl ON pc.cd = cl.cd
	    WHERE pc.pid = p.pid)");
}
