-- LegacyWorlds Beta 6
-- PostgreSQL database scripts
--
-- Game updates - empire research
--
-- Copyright(C) 2004-2010, DeepClone Development
-- --------------------------------------------------------


CREATE OR REPLACE FUNCTION sys.process_empire_research_updates( c_tick BIGINT )
		RETURNS VOID
		STRICT VOLATILE
		SECURITY INVOKER
	AS $$
DECLARE
	rec			RECORD;
	r_points	REAL;
	tu_rec		RECORD;
BEGIN
	-- Lock empires for update and planets for share
	PERFORM e.name_id FROM sys.updates su
			INNER JOIN emp.updates eu ON eu.update_id = su.id
			INNER JOIN emp.empires e ON eu.empire_id = e.name_id
			INNER JOIN emp.planets ep ON ep.empire_id = e.name_id
			INNER JOIN verse.planets p ON p.name_id = ep.planet_id
		WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
			AND su.gu_type = 'EMPIRE_RESEARCH'
		FOR UPDATE OF e
		FOR SHARE OF ep , p;

	-- Process empires
	FOR rec IN SELECT e.name_id AS id , ( v.status = 'PROCESSED' ) AS on_vacation ,
						sum( p.population ) AS population
					FROM sys.updates su
						INNER JOIN emp.updates eu ON eu.update_id = su.id
						INNER JOIN emp.empires e ON eu.empire_id = e.name_id
						INNER JOIN emp.planets ep ON ep.empire_id = e.name_id
						INNER JOIN verse.planets p ON p.name_id = ep.planet_id
						INNER JOIN naming.empire_names en ON en.id = e.name_id
						LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id
					WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
						AND su.gu_type = 'EMPIRE_RESEARCH'
					GROUP BY e.name_id , v.status
	LOOP
		-- Insert any missing tech line
		INSERT INTO emp.technologies ( empire_id , line_id )
			SELECT rec.id , l.name_id
				FROM tech.lines l
					LEFT OUTER JOIN emp.technologies t
						ON t.line_id = l.name_id AND t.empire_id = rec.id
				WHERE t.empire_id IS NULL;

		-- Compute research output
		r_points := rec.population * sys.get_constant( 'game.work.rpPerPopUnit' ) / 1440.0;
		IF rec.on_vacation
		THEN
			r_points := r_points / sys.get_constant( 'vacation.researchDivider' );
		END IF;

		-- Update technologies where:
		-- 1) the level actually exists and
		-- 2) accumulated points haven't reach the level's
		FOR tu_rec IN SELECT t.line_id AS line_id , t.accumulated AS accumulated ,
							l.points AS points , ( l.points - t.accumulated ) AS diff ,
							l.id AS level_id
						FROM emp.technologies t
							INNER JOIN tech.levels l ON l.line_id = t.line_id
								AND l.level = t.level AND t.accumulated < l.points
						WHERE t.empire_id = rec.id
						FOR UPDATE OF t
		LOOP
			UPDATE emp.technologies t SET accumulated = ( CASE
						WHEN tu_rec.diff <= r_points THEN tu_rec.points
						ELSE tu_rec.accumulated + r_points
					END )
				WHERE t.line_id = tu_rec.line_id AND t.empire_id = rec.id;

			-- Send message
			IF tu_rec.diff <= r_points
			THEN
				PERFORM events.tech_ready_event( rec.id , tu_rec.level_id );
			END IF;
		END LOOP;
	END LOOP;
END;
$$ LANGUAGE plpgsql;