Research update
* Implemented new research update. Old research system no longer updates. * Fixed a major bug in the constants registrar * Added game.research.vacation constant (determines the rate of research when players are in vacation mode)
This commit is contained in:
parent
a14601df37
commit
c7949e41cc
11 changed files with 414 additions and 85 deletions
|
@ -53,7 +53,7 @@ public class ConstantsRegistrarBean
|
||||||
true ) );
|
true ) );
|
||||||
cDesc = "Initial universe size (offset relative to the centre).";
|
cDesc = "Initial universe size (offset relative to the centre).";
|
||||||
defs.add( new ConstantDefinition( "game.universe.initialSize" , "Universe" , cDesc , 1.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( "game.universe.initialSize" , "Universe" , cDesc , 1.0 , 1.0 , true ) );
|
||||||
|
|
||||||
// Natural resources
|
// Natural resources
|
||||||
cDesc = "Global recovery rate multiplier for natural resources. This should be kept close to 0.";
|
cDesc = "Global recovery rate multiplier for natural resources. This should be kept close to 0.";
|
||||||
defs.add( new ConstantDefinition( "game.resources.recovery" , "Natural resources" , cDesc , 0.01 , 0.00001 ,
|
defs.add( new ConstantDefinition( "game.resources.recovery" , "Natural resources" , cDesc , 0.01 , 0.00001 ,
|
||||||
|
@ -125,12 +125,12 @@ public class ConstantsRegistrarBean
|
||||||
defs.add( new ConstantDefinition( wcNames[ 6 ] , cat , cDesc , 0.50 , 0.01 , true ) );
|
defs.add( new ConstantDefinition( wcNames[ 6 ] , cat , cDesc , 0.50 , 0.01 , true ) );
|
||||||
cDesc = "Proportion of queue investments that is recovered when flushing the queue.";
|
cDesc = "Proportion of queue investments that is recovered when flushing the queue.";
|
||||||
defs.add( new ConstantDefinition( wcNames[ 7 ] , cat , cDesc , 0.1 , 0.01 , 1.0 ) );
|
defs.add( new ConstantDefinition( wcNames[ 7 ] , cat , cDesc , 0.1 , 0.01 , 1.0 ) );
|
||||||
|
|
||||||
// Research
|
// Research
|
||||||
String[] rcNames = {
|
String[] rcNames = {
|
||||||
"basePoints" , "visibility.points" , "visibility.ratio" , "weightBase"
|
"basePoints" , "visibility.points" , "visibility.ratio" , "weightBase" , "vacation"
|
||||||
};
|
};
|
||||||
for ( int i = 0 ; i < wcNames.length ; i++ ) {
|
for ( int i = 0 ; i < rcNames.length ; i++ ) {
|
||||||
rcNames[ i ] = "game.research." + rcNames[ i ];
|
rcNames[ i ] = "game.research." + rcNames[ i ];
|
||||||
}
|
}
|
||||||
cat = "Research & technologies";
|
cat = "Research & technologies";
|
||||||
|
@ -144,6 +144,8 @@ public class ConstantsRegistrarBean
|
||||||
+ "to compute the actual weight when determining how research points are distributed between "
|
+ "to compute the actual weight when determining how research points are distributed between "
|
||||||
+ "an empire's in-progress research.";
|
+ "an empire's in-progress research.";
|
||||||
defs.add( new ConstantDefinition( rcNames[ 3 ] , cat , cDesc , 10.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( rcNames[ 3 ] , cat , cDesc , 10.0 , 1.0 , true ) );
|
||||||
|
cDesc = "Research points multiplier used when the player is on vacation.";
|
||||||
|
defs.add( new ConstantDefinition( rcNames[ 4 ] , cat , cDesc , 0.1 , 0.01 , 0.99 ) );
|
||||||
|
|
||||||
// Vacation mode
|
// Vacation mode
|
||||||
cDesc = "Initial vacation credits.";
|
cDesc = "Initial vacation credits.";
|
||||||
|
@ -188,7 +190,7 @@ public class ConstantsRegistrarBean
|
||||||
// Ticker
|
// Ticker
|
||||||
cDesc = "Interval between ticks with the highest frequency, in milliseconds.";
|
cDesc = "Interval between ticks with the highest frequency, in milliseconds.";
|
||||||
defs.add( new ConstantDefinition( "ticker.interval" , "Ticker" , cDesc , 5000.0 , 1000.0 , true ) );
|
defs.add( new ConstantDefinition( "ticker.interval" , "Ticker" , cDesc , 5000.0 , 1000.0 , true ) );
|
||||||
|
|
||||||
// Accounts
|
// Accounts
|
||||||
cDesc = "Minimal interval between address change requests (seconds)";
|
cDesc = "Minimal interval between address change requests (seconds)";
|
||||||
defs.add( new ConstantDefinition( "accounts.acrDelay" , "Accounts" , cDesc , 14400.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.acrDelay" , "Accounts" , cDesc , 14400.0 , 1.0 , true ) );
|
||||||
|
@ -202,25 +204,32 @@ public class ConstantsRegistrarBean
|
||||||
defs.add( new ConstantDefinition( "accounts.banDelay" , "Accounts" , cDesc , 178000.0 , 3600.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.banDelay" , "Accounts" , cDesc , 178000.0 , 3600.0 , true ) );
|
||||||
cDesc = "Delay before a ban request expires (seconds)";
|
cDesc = "Delay before a ban request expires (seconds)";
|
||||||
defs.add( new ConstantDefinition( "accounts.banExpiration" , "Accounts" , cDesc , oneWeek , 3600.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.banExpiration" , "Accounts" , cDesc , oneWeek , 3600.0 , true ) );
|
||||||
|
|
||||||
// Accounts - warnings
|
// Accounts - warnings
|
||||||
cDesc = "Amount of warnings that triggers an automatic ban request.";
|
cDesc = "Amount of warnings that triggers an automatic ban request.";
|
||||||
defs.add( new ConstantDefinition( "accounts.warnings.autoBan" , "Accounts - Warnings" , cDesc , 3.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.warnings.autoBan" , "Accounts - Warnings" , cDesc , 3.0 , 1.0 ,
|
||||||
|
true ) );
|
||||||
cDesc = "Period after a warning is received during which additional warnings will be ignored (seconds).";
|
cDesc = "Period after a warning is received during which additional warnings will be ignored (seconds).";
|
||||||
defs.add( new ConstantDefinition( "accounts.warnings.grace" , "Accounts - Warnings" , cDesc , 7200.0 , 60.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.warnings.grace" , "Accounts - Warnings" , cDesc , 7200.0 , 60.0 ,
|
||||||
|
true ) );
|
||||||
cDesc = "Time after which warnings are decreased (expressed in units as defined by a.w.expiration.units).";
|
cDesc = "Time after which warnings are decreased (expressed in units as defined by a.w.expiration.units).";
|
||||||
defs.add( new ConstantDefinition( "accounts.warnings.expiration" , "Accounts - Warnings" , cDesc , 60.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.warnings.expiration" , "Accounts - Warnings" , cDesc , 60.0 , 1.0 ,
|
||||||
|
true ) );
|
||||||
cDesc = "Units used to express warning expiration time (seconds).";
|
cDesc = "Units used to express warning expiration time (seconds).";
|
||||||
defs.add( new ConstantDefinition( "accounts.warnings.expiration.units" , "Accounts - Warnings" , cDesc , 86400.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.warnings.expiration.units" , "Accounts - Warnings" , cDesc ,
|
||||||
|
86400.0 , 1.0 , true ) );
|
||||||
|
|
||||||
// Account inactivity
|
// Account inactivity
|
||||||
cDesc = "Time units (seconds)";
|
cDesc = "Time units (seconds)";
|
||||||
defs.add( new ConstantDefinition( "accounts.inactivity.units" , "Accounts - Inactivity" , cDesc , oneWeek , 3600.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.inactivity.units" , "Accounts - Inactivity" , cDesc , oneWeek ,
|
||||||
|
3600.0 , true ) );
|
||||||
cDesc = "Time after which the inactivity warning e-mail is to be sent, expressed using units defined by a.i.units.";
|
cDesc = "Time after which the inactivity warning e-mail is to be sent, expressed using units defined by a.i.units.";
|
||||||
defs.add( new ConstantDefinition( "accounts.inactivity.warningMail" , "Accounts - Inactivity" , cDesc , 3.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.inactivity.warningMail" , "Accounts - Inactivity" , cDesc , 3.0 ,
|
||||||
|
1.0 , true ) );
|
||||||
cDesc = "Time between the inactivity warning e-mail and actual account deletion, expressed using units defined by a.i.units.";
|
cDesc = "Time between the inactivity warning e-mail and actual account deletion, expressed using units defined by a.i.units.";
|
||||||
defs.add( new ConstantDefinition( "accounts.inactivity.deletion" , "Accounts - Inactivity" , cDesc , 1.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( "accounts.inactivity.deletion" , "Accounts - Inactivity" , cDesc , 1.0 , 1.0 ,
|
||||||
|
true ) );
|
||||||
|
|
||||||
// Bug reports
|
// Bug reports
|
||||||
cDesc = "Amount of credits granted for low priority bug reports.";
|
cDesc = "Amount of credits granted for low priority bug reports.";
|
||||||
defs.add( new ConstantDefinition( "bugtracker.lowCredits" , "Bug tracking system" , cDesc , 1.0 , 1.0 , true ) );
|
defs.add( new ConstantDefinition( "bugtracker.lowCredits" , "Bug tracking system" , cDesc , 1.0 , 1.0 , true ) );
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
* _empire The empire's identifier
|
* _empire The empire's identifier
|
||||||
* _technology The string identifier for the technology to implement
|
* _technology The string identifier for the technology to implement
|
||||||
*/
|
*/
|
||||||
DROP FUNCTION emp.technology_implement( INT , TEXT );
|
DROP FUNCTION IF EXISTS emp.technology_implement( INT , TEXT );
|
||||||
CREATE FUNCTION emp.technology_implement( _empire INT , _technology TEXT )
|
CREATE FUNCTION emp.technology_implement( _empire INT , _technology TEXT )
|
||||||
RETURNS BOOLEAN
|
RETURNS BOOLEAN
|
||||||
LANGUAGE PLPGSQL
|
LANGUAGE PLPGSQL
|
||||||
|
@ -291,6 +291,56 @@ GRANT EXECUTE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute an empire's total research points
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* Obtain an empire's total research points by adding the happiness-adjusted
|
||||||
|
* value for each planet, then applying the global modifier for vacation mode
|
||||||
|
* if necessary.
|
||||||
|
*
|
||||||
|
* FIXME: time factor is hard-coded
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* _empire The empire's identifier
|
||||||
|
* _on_vacation TRUE if the player is on vacation, FALSE otherwise
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* ? The amount of research points.
|
||||||
|
*/
|
||||||
|
DROP FUNCTION IF EXISTS emp.research_get_points( INT , BOOLEAN );
|
||||||
|
CREATE FUNCTION emp.research_get_points( _empire INT , _on_vacation BOOLEAN )
|
||||||
|
RETURNS DOUBLE PRECISION
|
||||||
|
LANGUAGE SQL
|
||||||
|
STRICT STABLE
|
||||||
|
SECURITY INVOKER
|
||||||
|
AS $research_get_points$
|
||||||
|
|
||||||
|
SELECT SUM( verse.adjust_production(
|
||||||
|
_planet.population * sys.get_constant( 'game.research.basePoints' ) ,
|
||||||
|
_happiness.current / _planet.population
|
||||||
|
) ) * ( CASE
|
||||||
|
WHEN $2 THEN
|
||||||
|
sys.get_constant( 'game.research.vacation' )
|
||||||
|
ELSE
|
||||||
|
1.0
|
||||||
|
END )::DOUBLE PRECISION
|
||||||
|
FROM emp.planets _emp_planet
|
||||||
|
INNER JOIN verse.planets _planet
|
||||||
|
ON _emp_planet.planet_id = _planet.name_id
|
||||||
|
INNER JOIN verse.planet_happiness _happiness
|
||||||
|
USING ( planet_id )
|
||||||
|
WHERE _emp_planet.empire_id = $1;
|
||||||
|
|
||||||
|
$research_get_points$;
|
||||||
|
|
||||||
|
REVOKE EXECUTE
|
||||||
|
ON FUNCTION emp.research_get_points( INT , BOOLEAN )
|
||||||
|
FROM PUBLIC;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Technology visibility view
|
* Technology visibility view
|
||||||
|
|
|
@ -3,90 +3,188 @@
|
||||||
--
|
--
|
||||||
-- Game updates - empire research
|
-- Game updates - empire research
|
||||||
--
|
--
|
||||||
-- Copyright(C) 2004-2010, DeepClone Development
|
-- Copyright(C) 2004-2012, DeepClone Development
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION sys.process_empire_research_updates( c_tick BIGINT )
|
/*
|
||||||
|
* Empire update data
|
||||||
|
* -------------------
|
||||||
|
*
|
||||||
|
* This type can be used to return empires along with their "on vacation"
|
||||||
|
* status.
|
||||||
|
*
|
||||||
|
* FIXME: it should probably be somewhere else, but for now this is the only
|
||||||
|
* file that uses it.
|
||||||
|
*/
|
||||||
|
DROP TYPE IF EXISTS sys.empire_update_type CASCADE;
|
||||||
|
CREATE TYPE sys.empire_update_type AS (
|
||||||
|
/* The empire's identifier */
|
||||||
|
empire_id INT ,
|
||||||
|
|
||||||
|
/* TRUE if the player is on vacation, FALSE otherwise */
|
||||||
|
on_vacation BOOLEAN
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lock records and list empires which require a research update
|
||||||
|
* --------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This function will lock all records needed for a research update, and
|
||||||
|
* return the list of empires to be updated. These empires, in addition to
|
||||||
|
* being marked for update, must possess planets and have in-progress
|
||||||
|
* research.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* _tick The identifier of the current update cycle
|
||||||
|
*
|
||||||
|
* Returns a set of:
|
||||||
|
* empire_id The empire's identifier
|
||||||
|
* on_vacation TRUE if the player is on vacation, FALSE otherwise
|
||||||
|
*/
|
||||||
|
DROP FUNCTION IF EXISTS sys.gu_research_get_empires( BIGINT ) CASCADE;
|
||||||
|
CREATE FUNCTION sys.gu_research_get_empires( _tick BIGINT )
|
||||||
|
RETURNS SETOF sys.empire_update_type
|
||||||
|
LANGUAGE SQL
|
||||||
|
STRICT VOLATILE
|
||||||
|
SECURITY INVOKER
|
||||||
|
AS $gu_research_get_empires$
|
||||||
|
|
||||||
|
SELECT DISTINCT * FROM (
|
||||||
|
SELECT _empire.name_id AS empire_id ,
|
||||||
|
( _vacation.status IS NOT NULL AND
|
||||||
|
_vacation.status = 'PROCESSED' ) AS on_vacation
|
||||||
|
FROM sys.updates _upd_sys
|
||||||
|
INNER JOIN emp.empires_updates _emp_update
|
||||||
|
USING ( updtgt_id , updtype_id , update_id )
|
||||||
|
INNER JOIN emp.empires _empire
|
||||||
|
USING ( name_id )
|
||||||
|
INNER JOIN emp.technologies_v2 _emp_tech
|
||||||
|
ON _emp_tech.empire_id = _empire.name_id
|
||||||
|
INNER JOIN defs.technologies _tech
|
||||||
|
USING ( technology_name_id )
|
||||||
|
INNER JOIN emp.planets _emp_planet
|
||||||
|
USING ( empire_id )
|
||||||
|
INNER JOIN verse.planets _planet
|
||||||
|
ON _emp_planet.planet_id = _planet.name_id
|
||||||
|
INNER JOIN verse.planet_happiness _happiness
|
||||||
|
USING ( planet_id )
|
||||||
|
INNER JOIN naming.empire_names _emp_name
|
||||||
|
ON _emp_name.id = _empire.name_id
|
||||||
|
INNER JOIN users.credentials _user
|
||||||
|
ON _user.address_id = _emp_name.owner_id
|
||||||
|
LEFT OUTER JOIN users.vacations _vacation
|
||||||
|
ON _vacation.account_id = _emp_name.owner_id
|
||||||
|
WHERE _upd_sys.update_last = $1
|
||||||
|
AND _upd_sys.update_state = 'PROCESSING'
|
||||||
|
AND _emp_tech.emptech_state = 'RESEARCH'
|
||||||
|
FOR UPDATE OF _upd_sys , _emp_update , _emp_tech
|
||||||
|
FOR SHARE OF _empire , _tech , _emp_planet , _planet ,
|
||||||
|
_happiness , _emp_name , _user
|
||||||
|
) _sub;
|
||||||
|
|
||||||
|
$gu_research_get_empires$;
|
||||||
|
|
||||||
|
REVOKE EXECUTE
|
||||||
|
ON FUNCTION sys.gu_research_get_empires( BIGINT )
|
||||||
|
FROM PUBLIC;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update research for a single empire
|
||||||
|
* ------------------------------------
|
||||||
|
*
|
||||||
|
* This stored procedure updates research points for all in-progress research
|
||||||
|
* of a single empire.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* _empire_id The empire's identifier
|
||||||
|
* _on_vacation TRUE if the player is on vacation, FALSE otherwise
|
||||||
|
*/
|
||||||
|
DROP FUNCTION IF EXISTS sys.gu_research_update_empire( INT , BOOLEAN ) CASCADE;
|
||||||
|
CREATE FUNCTION sys.gu_research_update_empire( _empire INT , _on_vacation BOOLEAN )
|
||||||
RETURNS VOID
|
RETURNS VOID
|
||||||
|
LANGUAGE PLPGSQL
|
||||||
STRICT VOLATILE
|
STRICT VOLATILE
|
||||||
SECURITY INVOKER
|
SECURITY INVOKER
|
||||||
AS $$
|
AS $gu_research_update_empire$
|
||||||
|
|
||||||
DECLARE
|
DECLARE
|
||||||
rec RECORD;
|
_points DOUBLE PRECISION;
|
||||||
r_points REAL;
|
_record RECORD;
|
||||||
tu_rec RECORD;
|
|
||||||
BEGIN
|
BEGIN
|
||||||
-- Lock empires for update and planets for share
|
|
||||||
PERFORM e.name_id
|
|
||||||
FROM sys.updates _upd_sys
|
|
||||||
INNER JOIN emp.empires_updates eu
|
|
||||||
USING ( updtgt_id , updtype_id , update_id )
|
|
||||||
INNER JOIN emp.empires e USING ( 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 _upd_sys.update_last = c_tick
|
|
||||||
AND _upd_sys.update_state = 'PROCESSING'
|
|
||||||
FOR UPDATE OF e
|
|
||||||
FOR SHARE OF ep , p;
|
|
||||||
|
|
||||||
-- Process empires
|
_points := emp.research_get_points( _empire , _on_vacation );
|
||||||
FOR rec IN SELECT e.name_id AS id , ( v.status = 'PROCESSED' ) AS on_vacation ,
|
FOR _record IN
|
||||||
sum( p.population ) AS population
|
SELECT _emp_tech.technology_name_id , _emp_tech.emptech_points , _emp_tech.emptech_priority ,
|
||||||
FROM sys.updates _upd_sys
|
_points * _weights.emptech_weight / ( _totals.emptech_total_weight * 1440 ) AS emptech_new_points ,
|
||||||
INNER JOIN emp.empires_updates eu
|
_def.technology_points::DOUBLE PRECISION AS technology_points
|
||||||
USING ( updtgt_id , updtype_id , update_id )
|
FROM emp.technologies_v2 _emp_tech
|
||||||
INNER JOIN emp.empires e USING ( name_id )
|
INNER JOIN emp.research_weights_view _weights
|
||||||
INNER JOIN emp.planets ep ON ep.empire_id = e.name_id
|
USING ( empire_id , technology_name_id )
|
||||||
INNER JOIN verse.planets p ON p.name_id = ep.planet_id
|
INNER JOIN emp.research_total_weights_view _totals
|
||||||
INNER JOIN naming.empire_names en ON en.id = e.name_id
|
USING ( empire_id )
|
||||||
LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id
|
INNER JOIN defs.technologies _def
|
||||||
WHERE _upd_sys.update_last = c_tick
|
USING ( technology_name_id )
|
||||||
AND _upd_sys.update_state = 'PROCESSING'
|
WHERE _emp_tech.empire_id = _empire
|
||||||
GROUP BY e.name_id , v.status
|
AND _emp_tech.emptech_state = 'RESEARCH'
|
||||||
LOOP
|
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
|
IF _record.emptech_points + _record.emptech_new_points >= _record.technology_points THEN
|
||||||
r_points := rec.population * sys.get_constant( 'game.work.rpPerPopUnit' ) / 1440.0;
|
UPDATE emp.technologies_v2
|
||||||
IF rec.on_vacation
|
SET emptech_state = 'PENDING' ,
|
||||||
THEN
|
emptech_points = NULL ,
|
||||||
r_points := r_points / sys.get_constant( 'vacation.researchDivider' );
|
emptech_priority = NULL
|
||||||
|
WHERE technology_name_id = _record.technology_name_id
|
||||||
|
AND empire_id = _empire;
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
UPDATE emp.technologies_v2
|
||||||
|
SET emptech_points = emptech_points + _record.emptech_new_points
|
||||||
|
WHERE technology_name_id = _record.technology_name_id
|
||||||
|
AND empire_id = _empire;
|
||||||
END IF;
|
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 LOOP;
|
||||||
|
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE plpgsql;
|
$gu_research_update_empire$;
|
||||||
|
|
||||||
|
REVOKE EXECUTE
|
||||||
|
ON FUNCTION sys.gu_research_update_empire( INT , BOOLEAN )
|
||||||
|
FROM PUBLIC;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process a batch of empire research updates
|
||||||
|
* -------------------------------------------
|
||||||
|
*
|
||||||
|
* Update all empires in the batch which have both in-progress research and
|
||||||
|
* planets.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* _tick The identifier of the current update cycle
|
||||||
|
*/
|
||||||
|
DROP FUNCTION IF EXISTS sys.process_empire_research_updates( BIGINT ) CASCADE;
|
||||||
|
CREATE FUNCTION sys.process_empire_research_updates( _tick BIGINT )
|
||||||
|
RETURNS VOID
|
||||||
|
LANGUAGE SQL
|
||||||
|
STRICT VOLATILE
|
||||||
|
SECURITY INVOKER
|
||||||
|
AS $process_empire_research_updates$
|
||||||
|
|
||||||
|
SELECT sys.gu_research_update_empire( empire_id , on_vacation )
|
||||||
|
FROM sys.gu_research_get_empires( $1::BIGINT );
|
||||||
|
|
||||||
|
$process_empire_research_updates$;
|
||||||
|
|
||||||
|
REVOKE EXECUTE
|
||||||
|
ON FUNCTION sys.process_empire_research_updates( BIGINT )
|
||||||
|
FROM PUBLIC;
|
||||||
|
|
||||||
|
|
||||||
SELECT sys.register_update_type( 'Empires' , 'EmpireResearch' ,
|
SELECT sys.register_update_type( 'Empires' , 'EmpireResearch' ,
|
||||||
'Empire research points are being attributed to technologies.' ,
|
'Empire research points are being attributed to technologies.' ,
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Test the sys.gu_research_get_empires() function
|
||||||
|
*/
|
||||||
|
BEGIN;
|
||||||
|
\i utils/common-setup/setup-gu-research-get-empires-test.sql
|
||||||
|
|
||||||
|
SELECT plan( 2 );
|
||||||
|
|
||||||
|
SELECT diag_test_name( 'gu_research_get_empires() - Selected empires and vacation state' );
|
||||||
|
SELECT set_eq( $$
|
||||||
|
SELECT * FROM sys.gu_research_get_empires( 0::BIGINT );
|
||||||
|
$$ , $$ VALUES (
|
||||||
|
_get_emp_name( 'emp4') , FALSE
|
||||||
|
) , (
|
||||||
|
_get_emp_name( 'emp5') , TRUE
|
||||||
|
) $$ );
|
||||||
|
|
||||||
|
SELECT diag_test_name( 'gu_research_get_empires() - No results with "bad" update identifier' );
|
||||||
|
SELECT is_empty( $$
|
||||||
|
SELECT * FROM sys.gu_research_get_empires( 12::BIGINT );
|
||||||
|
$$ );
|
||||||
|
|
||||||
|
SELECT * FROM finish( );
|
||||||
|
ROLLBACK;
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* Test privileges on sys.gu_research_get_empires()
|
||||||
|
*/
|
||||||
|
BEGIN;
|
||||||
|
SELECT plan( 1 );
|
||||||
|
|
||||||
|
SELECT diag_test_name( 'sys.gu_research_get_empires() - Privileges' );
|
||||||
|
SELECT throws_ok( 'SELECT sys.gu_research_get_empires( 0::BIGINT )' , 42501 );
|
||||||
|
|
||||||
|
SELECT * FROM finish( );
|
||||||
|
ROLLBACK;
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Common setup for research update locking and empire selection
|
||||||
|
* --------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Empires are selected when:
|
||||||
|
* - they are part of the current update batch,
|
||||||
|
* - they possess planets,
|
||||||
|
* - they have in-progress research entries.
|
||||||
|
* All related data is locked: the update entries, empire, empire technology
|
||||||
|
* records, technology definitions, planets (including ownership records and
|
||||||
|
* happiness records), as well as the empire's name and associated account.
|
||||||
|
*/
|
||||||
|
|
||||||
|
-- Make sure the only update type left is EmpireResearch
|
||||||
|
DELETE FROM sys.update_types
|
||||||
|
WHERE updtype_name <> 'EmpireResearch';
|
||||||
|
|
||||||
|
\i utils/strings.sql
|
||||||
|
\i utils/resources.sql
|
||||||
|
\i utils/accounts.sql
|
||||||
|
\i utils/naming.sql
|
||||||
|
\i utils/universe.sql
|
||||||
|
|
||||||
|
-- Create some technology definitions, dropping constraints on unused columns
|
||||||
|
ALTER TABLE defs.technologies
|
||||||
|
ALTER technology_description_id DROP NOT NULL ,
|
||||||
|
ALTER technology_discovery_id DROP NOT NULL ,
|
||||||
|
ALTER technology_category_id DROP NOT NULL ,
|
||||||
|
ALTER technology_price DROP NOT NULL;
|
||||||
|
SELECT _create_test_strings( 3 , 'tech' );
|
||||||
|
INSERT INTO defs.technologies ( technology_name_id , technology_points )
|
||||||
|
SELECT id , 100.0 FROM defs.strings
|
||||||
|
WHERE name LIKE 'tech%';
|
||||||
|
|
||||||
|
-- Create the empire names and planets
|
||||||
|
SELECT _create_emp_names( 6 , 'emp' );
|
||||||
|
SELECT _create_raw_planets( 4 , 'planet' );
|
||||||
|
INSERT INTO verse.planet_happiness( planet_id , target , current )
|
||||||
|
SELECT id , 0.75 , 1500
|
||||||
|
FROM naming.map_names
|
||||||
|
WHERE name LIKE 'planet%';
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empire 1 has no planets and no in-progress research. It will not be
|
||||||
|
* selected or locked.
|
||||||
|
*/
|
||||||
|
INSERT INTO emp.empires( name_id , cash )
|
||||||
|
VALUES( _get_emp_name( 'emp1' ) , 100.0 );
|
||||||
|
INSERT INTO emp.technologies_v2 (
|
||||||
|
empire_id , technology_name_id ,
|
||||||
|
emptech_state , emptech_points , emptech_priority )
|
||||||
|
SELECT _get_emp_name( 'emp1' ) , technology_name_id , 'KNOWN' , NULL , NULL
|
||||||
|
FROM defs.technologies;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empire 2 has planets, but no in-progress research. It will not be
|
||||||
|
* selected.
|
||||||
|
*/
|
||||||
|
INSERT INTO emp.empires( name_id , cash )
|
||||||
|
VALUES( _get_emp_name( 'emp2' ) , 100.0 );
|
||||||
|
INSERT INTO emp.technologies_v2 (
|
||||||
|
empire_id , technology_name_id ,
|
||||||
|
emptech_state , emptech_points , emptech_priority )
|
||||||
|
SELECT _get_emp_name( 'emp2' ) , technology_name_id , 'KNOWN' , NULL , NULL
|
||||||
|
FROM defs.technologies;
|
||||||
|
INSERT INTO emp.planets( empire_id , planet_id )
|
||||||
|
VALUES( _get_emp_name( 'emp2' ) , _get_map_name( 'planet1' ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empire 3 has in-progress research, but no planets. It will not be selected.
|
||||||
|
*/
|
||||||
|
INSERT INTO emp.empires( name_id , cash )
|
||||||
|
VALUES( _get_emp_name( 'emp3' ) , 100.0 );
|
||||||
|
INSERT INTO emp.technologies_v2 ( empire_id , technology_name_id )
|
||||||
|
SELECT _get_emp_name( 'emp3' ) , technology_name_id
|
||||||
|
FROM defs.technologies;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empire 4 has in-progress research and planets. It has no vacation mode
|
||||||
|
* record. It will be selected.
|
||||||
|
*/
|
||||||
|
INSERT INTO emp.empires( name_id , cash )
|
||||||
|
VALUES( _get_emp_name( 'emp4' ) , 100.0 );
|
||||||
|
INSERT INTO emp.technologies_v2 ( empire_id , technology_name_id )
|
||||||
|
SELECT _get_emp_name( 'emp4' ) , technology_name_id
|
||||||
|
FROM defs.technologies;
|
||||||
|
INSERT INTO emp.planets( empire_id , planet_id )
|
||||||
|
VALUES( _get_emp_name( 'emp4' ) , _get_map_name( 'planet2' ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empire 5 has in-progress research, planets and a vacation mode record.
|
||||||
|
* It will be selected.
|
||||||
|
*
|
||||||
|
* Note: we need to add an entry to users.active_accounts for vacation mode
|
||||||
|
* records to work.
|
||||||
|
*/
|
||||||
|
INSERT INTO emp.empires( name_id , cash )
|
||||||
|
VALUES( _get_emp_name( 'emp5' ) , 100.0 );
|
||||||
|
INSERT INTO emp.technologies_v2 ( empire_id , technology_name_id )
|
||||||
|
SELECT _get_emp_name( 'emp5' ) , technology_name_id
|
||||||
|
FROM defs.technologies;
|
||||||
|
INSERT INTO emp.planets( empire_id , planet_id )
|
||||||
|
VALUES( _get_emp_name( 'emp5' ) , _get_map_name( 'planet3' ) );
|
||||||
|
INSERT INTO users.active_accounts( credentials_id ,vacation_credits )
|
||||||
|
SELECT id , 12
|
||||||
|
FROM users.addresses
|
||||||
|
WHERE address = 'emp5@example.org';
|
||||||
|
INSERT INTO users.vacations ( account_id , since , status )
|
||||||
|
SELECT id , NOW() , 'PROCESSED'
|
||||||
|
FROM users.addresses
|
||||||
|
WHERE address = 'emp5@example.org';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Empire 6 is similar to empire 4, but will not be marked for update in the
|
||||||
|
* current batch.
|
||||||
|
*/
|
||||||
|
INSERT INTO emp.empires( name_id , cash )
|
||||||
|
VALUES( _get_emp_name( 'emp6' ) , 100.0 );
|
||||||
|
INSERT INTO emp.technologies_v2 ( empire_id , technology_name_id )
|
||||||
|
SELECT _get_emp_name( 'emp6' ) , technology_name_id
|
||||||
|
FROM defs.technologies;
|
||||||
|
INSERT INTO emp.planets( empire_id , planet_id )
|
||||||
|
VALUES( _get_emp_name( 'emp6' ) , _get_map_name( 'planet4' ) );
|
||||||
|
|
||||||
|
|
||||||
|
/* Speaking of current batch - set it up */
|
||||||
|
UPDATE sys.updates su
|
||||||
|
SET update_state = 'PROCESSING' , update_last = 0
|
||||||
|
FROM emp.empires_updates eu
|
||||||
|
WHERE eu.update_id = su.update_id
|
||||||
|
AND eu.name_id <> _get_emp_name( 'emp6' );
|
||||||
|
UPDATE sys.updates su
|
||||||
|
SET update_state = 'PROCESSED' , update_last = 0
|
||||||
|
FROM emp.empires_updates eu
|
||||||
|
WHERE eu.update_id = su.update_id
|
||||||
|
AND eu.name_id = _get_emp_name( 'emp6' );
|
Reference in a new issue