/*
 * Test the verse.compute_provider_regeneration() function
 */
BEGIN;

	/* Define the necessary constants using default values */
	SELECT sys.uoc_constant( 'game.resources.recovery' , '(test)' , 'Resources' , 0.01 );
	SELECT sys.uoc_constant( 'game.resources.recoveryDampening' , '(test)' , 'Resources' , 1.5 );
	
	/* Make sure the functions are not immutable during the tests */
	ALTER FUNCTION sys.get_constant( TEXT ) VOLATILE;
	ALTER FUNCTION verse.compute_provider_regeneration( DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ) VOLATILE;
	
	/****** TESTS BEGIN HERE ******/
	SELECT plan( 6 );


	SELECT diag_test_name( 'verse.compute_provider_regeneration() - no regeneration at maximal quantity' );
	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
	DECLARE
		rr	DOUBLE PRECISION;
	BEGIN
		rr := 0.05;
		WHILE rr < 1
		LOOP
			IF verse.compute_provider_regeneration( 100.0 , 100.0 , rr ) > 100.0
			THEN
				RETURN FALSE;
			END IF;
			rr := rr + 0.05;
		END LOOP;
		RETURN TRUE;
	END;
	$$ LANGUAGE PLPGSQL;
	SELECT ok( _run_tests() );
	DROP FUNCTION _run_tests( );


	SELECT diag_test_name( 'verse.compute_provider_regeneration() - regeneration >= 0' );
	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
	DECLARE
		qt	DOUBLE PRECISION;
		rr	DOUBLE PRECISION;
	BEGIN
		qt := 0;
		WHILE qt < 100.0
		LOOP
			rr := 0.05;
			WHILE rr < 1
			LOOP
				IF verse.compute_provider_regeneration( qt , 100.0 , rr ) <= qt
				THEN
					RETURN FALSE;
				END IF;
				rr := rr + 0.05;
			END LOOP;
			qt := qt + 5;
		END LOOP;
		RETURN TRUE;
	END;
	$$ LANGUAGE PLPGSQL;
	SELECT ok( _run_tests() );
	DROP FUNCTION _run_tests( );


	SELECT diag_test_name( 'verse.compute_provider_regeneration() - higher quantity => slower regeneration' );
	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
	DECLARE
		pdiff	DOUBLE PRECISION;
		diff	DOUBLE PRECISION;
		qt		DOUBLE PRECISION;
		rr		DOUBLE PRECISION;
	BEGIN
		rr := 0.05;
		WHILE rr < 1
		LOOP
			qt := 0;
			WHILE qt < 100.0
			LOOP
				diff := verse.compute_provider_regeneration( qt , 100.0 , rr ) - qt;
				IF qt <> 0 AND diff >= pdiff
				THEN
					RETURN FALSE;
				END IF;
				pdiff := diff;
				qt := qt + 5;
			END LOOP;
			rr := rr + 0.05;
		END LOOP;
		RETURN TRUE;
	END;
	$$ LANGUAGE PLPGSQL;
	SELECT ok( _run_tests() );
	DROP FUNCTION _run_tests( );


	SELECT diag_test_name( 'verse.compute_provider_regeneration() - higher recovery rate => faster regeneration' );
	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
	DECLARE
		pdiff	DOUBLE PRECISION;
		diff	DOUBLE PRECISION;
		qt		DOUBLE PRECISION;
		rr		DOUBLE PRECISION;
	BEGIN
		qt := 0;
		WHILE qt < 100.0
		LOOP
			rr := 0.05;
			WHILE rr < 1
			LOOP
				diff := verse.compute_provider_regeneration( qt , 100.0 , rr ) - qt;
				IF rr > 0.06 AND diff <= pdiff
				THEN
					RETURN FALSE;
				END IF;
				pdiff := diff;
				rr := rr + 0.05;
			END LOOP;
			qt := qt + 5;
		END LOOP;
		RETURN TRUE;
	END;
	$$ LANGUAGE PLPGSQL;
	SELECT ok( _run_tests() );
	DROP FUNCTION _run_tests( );


	SELECT diag_test_name( 'verse.compute_provider_regeneration() - effect of game.resources.recovery' );
	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
	DECLARE
		pdiff	DOUBLE PRECISION;
		diff	DOUBLE PRECISION;
		qt		DOUBLE PRECISION;
		rr		DOUBLE PRECISION;
	BEGIN
		qt := 0;
		WHILE qt < 100.0
		LOOP
			rr := 0.01;
			WHILE rr < 1
			LOOP
				UPDATE sys.constant_definitions
					SET c_value = rr
					WHERE name = 'game.resources.recovery';
				diff := verse.compute_provider_regeneration( qt , 100.0 , 0.5 ) - qt;
				IF rr > 0.011 AND diff <= pdiff
				THEN
					RETURN FALSE;
				END IF;
				pdiff := diff;
				rr := rr + 0.01;
			END LOOP;
			qt := qt + 5;
		END LOOP;
		RETURN TRUE;
	END;
	$$ LANGUAGE PLPGSQL;
	SELECT ok( _run_tests() );
	DROP FUNCTION _run_tests( );
	UPDATE sys.constant_definitions
		SET c_value = 0.01
		WHERE name = 'game.resources.recovery';



	SELECT diag_test_name( 'verse.compute_provider_regeneration() - effect of game.resources.recoveryDampening' );
	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
	DECLARE
		pdiff	DOUBLE PRECISION;
		diff	DOUBLE PRECISION;
		qt		DOUBLE PRECISION;
		rrd		DOUBLE PRECISION;
	BEGIN
		qt := 5;
		WHILE qt < 100.0
		LOOP
			rrd := 1;
			WHILE rrd < 3
			LOOP
				UPDATE sys.constant_definitions
					SET c_value = rrd
					WHERE name = 'game.resources.recoveryDampening';
				diff := verse.compute_provider_regeneration( qt , 100.0 , 0.5 ) - qt;
				IF rrd > 1.01 AND diff >= pdiff
				THEN
					RETURN FALSE;
				END IF;
				pdiff := diff;
				rrd := rrd + 0.25;
			END LOOP;
			qt := qt + 5;
		END LOOP;
		RETURN TRUE;
	END;
	$$ LANGUAGE PLPGSQL;
	SELECT ok( _run_tests() );
	DROP FUNCTION _run_tests( );
	UPDATE sys.constant_definitions
		SET c_value = 1.5
		WHERE name = 'game.resources.recoveryDampening';


	SELECT * FROM finish( );
ROLLBACK;