-- LegacyWorlds Beta 6
-- PostgreSQL database scripts
--
-- Game updates - population growth and happiness
--
-- Copyright(C) 2004-2010, DeepClone Development
-- --------------------------------------------------------


CREATE OR REPLACE FUNCTION sys.process_planet_population_updates( c_tick BIGINT )
		RETURNS VOID
		STRICT VOLATILE
		SECURITY INVOKER
	AS $$
DECLARE
	rec		RECORD;
	rel_ch	REAL;
	abs_ch	REAL;
	g_fact	REAL;
	gf_inc	REAL;
	n_happ	REAL;
	t_happ	REAL;
	temp	REAL;
	growth	REAL;
	workers	REAL;
	str_thr	REAL;
BEGIN
	-- Get constants
	rel_ch := sys.get_constant( 'game.happiness.relativeChange' );
	abs_ch := sys.get_constant( 'game.happiness.maxAbsoluteChange' );
	g_fact := sys.get_constant( 'game.growthFactor' );
	gf_inc := sys.get_constant( 'game.growthFactor.rCentre' );
	str_thr := sys.get_constant( 'game.happiness.strike' );

	-- Process planets
	FOR rec IN SELECT p.name_id AS id , p.population AS pop ,
					ph.target AS target , ph.current AS happy_pop ,
					( ph.current / p.population )::REAL AS current
				FROM sys.updates su
					INNER JOIN verse.planets_updates vu
						USING ( update_id , updtype_id , updtgt_id )
					INNER JOIN verse.planets p
						USING ( name_id )
					INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
				FOR UPDATE OF p, ph
	LOOP
		IF round( rec.target / rel_ch ) = round( rec.current / rel_ch ) THEN
			-- Happiness does not change
			n_happ := rec.current;
		ELSE
			-- Compute new happiness
			temp := rec.pop * rel_ch;
			IF temp > abs_ch THEN
				temp := abs_ch;
			ELSEIF temp < 1 THEN
				temp := 1;
			END IF;

			IF rec.target < rec.current THEN
				temp := - temp;
			END IF;

			n_happ := ( rec.happy_pop + temp ) / rec.pop;
		END IF;
		
		-- Compute population growth
		temp := verse.adjust_production( verse.get_raw_production( rec.id , 'POP' ) , n_happ );
		growth := ( g_fact + temp * gf_inc ) * n_happ / 1440.0;

		-- Get workers
		SELECT INTO workers SUM( b.amount * d.workers )
			FROM verse.planet_buildings b
				INNER JOIN tech.buildings d
					ON d.buildable_id = b.building_id
			WHERE b.planet_id = rec.id;
		IF workers IS NULL THEN
			workers := 0;
		END IF;

		-- Compute new target happiness
		t_happ := verse.compute_happiness( rec.pop + growth , workers ,
			verse.adjust_production( verse.get_raw_production( rec.id , 'DEF' ) , n_happ ) ,
			emp.get_size( rec.id )
		);
		
		-- Update planet and happiness records
		UPDATE verse.planet_happiness
			SET current = ( rec.pop + growth ) * n_happ , target = t_happ
			WHERE planet_id = rec.id;
		UPDATE verse.planets
			SET population = rec.pop + growth
			WHERE name_id = rec.id;

		-- Send strike begin/end messages
		IF n_happ < str_thr AND rec.current >= str_thr
		THEN
			PERFORM events.strike_event( rec.id , TRUE );
		ELSEIF n_happ >= str_thr AND rec.current < str_thr
		THEN
			PERFORM events.strike_event( rec.id , FALSE );
		END IF;
	END LOOP;
END;
$$ LANGUAGE plpgsql;

SELECT sys.register_update_type( 'Planets' , 'PlanetPopulation' ,
		'Planet populations are being updated.' ,
		'process_planet_population_updates'
	);