diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/MiningSettingsDAOBean.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/MiningSettingsDAOBean.java new file mode 100644 index 0000000..57047b9 --- /dev/null +++ b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/MiningSettingsDAOBean.java @@ -0,0 +1,83 @@ +package com.deepclone.lw.beans.game.resources; + + +import java.sql.Types; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; + +import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO; +import com.deepclone.lw.utils.StoredProc; + + + +/** + * Data access component for mining settings + * + *

+ * This component implements the methods which allow mining settings to be updated by calling the + * appropriate stored procedures. + * + * @author E. Benoît + */ +class MiningSettingsDAOBean + implements MiningSettingsDAO +{ + /** emp.mset_update_start(INT) stored procedure */ + private StoredProc pStartEmpireUpdate; + + /** emp.mset_update_set(TEXT,INT) stored procedure */ + private StoredProc pSetMiningPriority; + + /** emp.mset_update_apply() stored procedure */ + private StoredProc pApplyUpdate; + + + /** + * Dependency injector that sets the data source + * + * @param dataSource + * the data source + */ + @Autowired( required = true ) + public void setDataSource( DataSource dataSource ) + { + this.pStartEmpireUpdate = new StoredProc( dataSource , "emp" , "mset_update_start" ); + this.pStartEmpireUpdate.addParameter( "_empire" , Types.INTEGER ); + this.pStartEmpireUpdate.addOutput( "_success" , Types.BOOLEAN ); + + this.pSetMiningPriority = new StoredProc( dataSource , "emp" , "mset_update_set" ); + this.pSetMiningPriority.addParameter( "_resource" , Types.VARCHAR ); + this.pSetMiningPriority.addParameter( "_priority" , Types.INTEGER ); + this.pSetMiningPriority.addOutput( "_success" , Types.BOOLEAN ); + + this.pApplyUpdate = new StoredProc( dataSource , "emp" , "mset_update_apply" ); + this.pApplyUpdate.addOutput( "_success" , Types.BOOLEAN ); + } + + + /* Documented in interface */ + @Override + public boolean startUpdate( int empireId ) + { + return (Boolean) this.pStartEmpireUpdate.execute( empireId ).get( "_success" ); + } + + + /* Documented in interface */ + @Override + public boolean setNewPriority( String resource , int priority ) + { + return (Boolean) this.pSetMiningPriority.execute( resource , priority ).get( "_success" ); + } + + + /* Documented in interface */ + @Override + public boolean applyUpdate( ) + { + return (Boolean) this.pApplyUpdate.execute( ).get( "_success" ); + } + +} diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesControllerBean.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesControllerBean.java new file mode 100644 index 0000000..a2b8040 --- /dev/null +++ b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesControllerBean.java @@ -0,0 +1,68 @@ +package com.deepclone.lw.beans.game.resources; + + +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO; +import com.deepclone.lw.interfaces.game.resources.ResourcesController; + + + +/** + * Resources controller component + * + *

+ * This component implements all game actions that affect resources or resource-related information, + * such as mining priorities. + * + * @author E. Benoît + */ +@Transactional +class ResourcesControllerBean + implements ResourcesController +{ + + /** The mining settings access interface */ + private MiningSettingsDAO settings; + + + /** + * Dependency injector that sets the mining settings access interface + * + * @param settings + * the mining settings access interface + */ + @Autowired( required = true ) + public void setMiningSettingsDAO( MiningSettingsDAO settings ) + { + this.settings = settings; + } + + + /** + * Update an empire's mining settings + * + *

+ * Start a mining settings update for the specified empire, then set each resource-specific + * priority, then apply the update. Exit whenever something goes wrong. + */ + @Override + public void updateEmpireSettings( int empireId , Map< String , Integer > settings ) + { + if ( !this.settings.startUpdate( empireId ) ) { + return; + } + + for ( Map.Entry< String , Integer > entry : settings.entrySet( ) ) { + if ( ! this.settings.setNewPriority( entry.getKey( ) , entry.getValue( ) ) ) { + return; + } + } + + this.settings.applyUpdate( ); + } + +} diff --git a/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources.xml b/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources.xml index 2c36ed9..12debf7 100644 --- a/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources.xml +++ b/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources.xml @@ -3,6 +3,8 @@ xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> + + diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/UpdateEmpireMiningSettingsCommandDelegateBean.java b/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/UpdateEmpireMiningSettingsCommandDelegateBean.java new file mode 100644 index 0000000..ea0b021 --- /dev/null +++ b/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/UpdateEmpireMiningSettingsCommandDelegateBean.java @@ -0,0 +1,74 @@ +package com.deepclone.lw.beans.user.player.game; + + +import org.springframework.beans.factory.annotation.Autowired; + +import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate; +import com.deepclone.lw.beans.user.abst.SessionCommandHandler; +import com.deepclone.lw.beans.user.player.GameSubTypeBean; +import com.deepclone.lw.cmd.player.UpdateEmpireMiningSettingsCommand; +import com.deepclone.lw.interfaces.game.resources.ResourcesController; +import com.deepclone.lw.interfaces.session.ServerSession; +import com.deepclone.lw.session.Command; +import com.deepclone.lw.session.CommandResponse; +import com.deepclone.lw.session.NullResponse; + + + +/** + * Command handler for empire mining settings updates + * + * @author E. Benoît + */ +class UpdateEmpireMiningSettingsCommandDelegateBean + implements AutowiredCommandDelegate +{ + + /** The resources controller */ + private ResourcesController resourcesController; + + + /** + * Dependency injector that sets the resources controller + * + * @param resourcesController + * the resources controller + */ + @Autowired( required = true ) + public void setResourcesController( ResourcesController resourcesController ) + { + this.resourcesController = resourcesController; + } + + + /** This class handles {@link UpdateEmpireMiningSettingsCommand} instances */ + @Override + public Class< ? extends Command > getType( ) + { + return UpdateEmpireMiningSettingsCommand.class; + } + + + /** This class is enabled for the {@link GameSubTypeBean} session type */ + @Override + public Class< ? extends SessionCommandHandler > getCommandHandler( ) + { + return GameSubTypeBean.class; + } + + + /** + * If the account is not in vacation mode, update mining settings. Always return a + * {@link NullResponse}. + */ + @Override + public CommandResponse execute( ServerSession session , Command command ) + { + if ( !session.get( "vacation" , Boolean.class ) ) { + int empireId = session.get( "empireId" , Integer.class ); + this.resourcesController.updateEmpireSettings( empireId , + ( (UpdateEmpireMiningSettingsCommand) command ).getSettings( ) ); + } + return new NullResponse( ); + } +} diff --git a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/player.xml b/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/player.xml index 37a91ea..203a345 100644 --- a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/player.xml +++ b/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/player.xml @@ -45,6 +45,7 @@ + diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/045-empire-mining.sql b/legacyworlds-server-data/db-structure/parts/040-functions/045-empire-mining.sql index 9c4545f..d8b4f04 100644 --- a/legacyworlds-server-data/db-structure/parts/040-functions/045-empire-mining.sql +++ b/legacyworlds-server-data/db-structure/parts/040-functions/045-empire-mining.sql @@ -29,15 +29,17 @@ BEGIN CREATE TEMPORARY TABLE mset_update( empire_id INT , - resource_name_id INT , + resource_name TEXT , empmset_weight INT ) ON COMMIT DROP; INSERT INTO mset_update - SELECT _mset.empire_id , _mset.resource_name_id , 2 + SELECT _mset.empire_id , _str.name , 2 FROM emp.empires _empire INNER JOIN emp.mining_settings _mset ON _empire.name_id = _mset.empire_id + INNER JOIN defs.strings _str + ON _str.id = _mset.resource_name_id WHERE _empire.name_id = _empire_id FOR SHARE OF _empire FOR UPDATE OF _mset; @@ -81,7 +83,7 @@ BEGIN CREATE TEMPORARY TABLE mset_update( empire_id INT , planet_id INT , - resource_name_id INT , + resource_name TEXT , empmset_weight INT ) ON COMMIT DROP; @@ -106,8 +108,10 @@ BEGIN FOR UPDATE; INSERT INTO mset_update - SELECT _empire_id , _planet_id , resource_name_id , 2 + SELECT _empire_id , _planet_id , _str.name , 2 FROM verse.resource_providers + INNER JOIN defs.strings _str + ON _str.id = resource_name_id WHERE planet_id = _planet_id; RETURN TRUE; @@ -131,14 +135,14 @@ GRANT EXECUTE * must be called after emp.mset_update_start() has initialised the table. * * Parameters: - * _resource_id The resource's identifier + * _resource The resource's text identifier * _weight The setting's new value * * Returns: * ? True if the resource exists, false otherwise. */ -DROP FUNCTION IF EXISTS emp.mset_update_set( INT , INT ); -CREATE FUNCTION emp.mset_update_set( _resource_id INT , _weight INT ) +DROP FUNCTION IF EXISTS emp.mset_update_set( TEXT , INT ); +CREATE FUNCTION emp.mset_update_set( _resource TEXT , _weight INT ) RETURNS BOOLEAN STRICT VOLATILE SECURITY DEFINER @@ -147,7 +151,7 @@ BEGIN UPDATE mset_update SET empmset_weight = _weight - WHERE resource_name_id = _resource_id; + WHERE resource_name = _resource; RETURN FOUND; END; @@ -155,10 +159,10 @@ $mset_update_set$ LANGUAGE PLPGSQL; REVOKE EXECUTE - ON FUNCTION emp.mset_update_set( INT , INT ) + ON FUNCTION emp.mset_update_set( TEXT , INT ) FROM PUBLIC; GRANT EXECUTE - ON FUNCTION emp.mset_update_set( INT , INT ) + ON FUNCTION emp.mset_update_set( TEXT , INT ) TO :dbuser; @@ -201,8 +205,10 @@ BEGIN empire_id , planet_id , resource_name_id , emppmset_weight ) SELECT empire_id , planet_id , - resource_name_id , empmset_weight - FROM mset_update; + _str.id , empmset_weight + FROM mset_update + INNER JOIN defs.strings _str + ON _str.name = resource_name; EXCEPTION @@ -211,8 +217,10 @@ BEGIN UPDATE emp.mining_settings _settings SET empmset_weight = _update.empmset_weight FROM mset_update _update + INNER JOIN defs.strings _str + ON _str.name = _update.resource_name WHERE _update.empire_id = _settings.empire_id - AND _update.resource_name_id = _settings.resource_name_id; + AND _str.id = _settings.resource_name_id; END; RETURN TRUE; diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/010-mset-update-start.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/010-mset-update-start.sql index b73c7bc..8584f82 100644 --- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/010-mset-update-start.sql +++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/010-mset-update-start.sql @@ -23,7 +23,7 @@ BEGIN; SELECT ok( NOT emp.mset_update_start( _get_bad_emp_name( ) ) ); SELECT diag_test_name( 'emp.mset_update_start( INT ) - Temporary table exists despite bad empire identifier' ); SELECT has_table( 'mset_update' ); - DROP TABLE mset_update; + DROP TABLE IF EXISTS mset_update; SELECT diag_test_name( 'emp.mset_update_start( INT ) - Return value on valid empire identifier' ); diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/015-mset-update-start-planet.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/015-mset-update-start-planet.sql index 816508a..31536c8 100644 --- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/015-mset-update-start-planet.sql +++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/015-mset-update-start-planet.sql @@ -28,31 +28,31 @@ BEGIN; SELECT ok( NOT emp.mset_update_start( _get_bad_emp_name( ) , _get_map_name( 'testPlanet1' ) ) ); SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite bad empire identifier' ); SELECT has_table( 'mset_update' ); - DROP TABLE mset_update; + DROP TABLE IF EXISTS mset_update; SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on bad planet identifier' ); SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_bad_map_name( ) ) ); SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite bad planet identifier' ); SELECT has_table( 'mset_update' ); - DROP TABLE mset_update; + DROP TABLE IF EXISTS mset_update; SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on unowned planet identifier' ); SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet2' ) ) ); SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite unowned planet identifier' ); SELECT has_table( 'mset_update' ); - DROP TABLE mset_update; + DROP TABLE IF EXISTS mset_update; SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on unowned planet identifier' ); SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet2' ) ) ); SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite unowned planet identifier' ); SELECT has_table( 'mset_update' ); - DROP TABLE mset_update; + DROP TABLE IF EXISTS mset_update; SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on planet with no resource providers' ); SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet3' ) ) ); SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite planet with no resource providers' ); SELECT has_table( 'mset_update' ); - DROP TABLE mset_update; + DROP TABLE IF EXISTS mset_update; SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on valid identifiers' ); diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/020-mset-update-set.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/020-mset-update-set.sql index 7515bfb..5009bb6 100644 --- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/020-mset-update-set.sql +++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/020-mset-update-set.sql @@ -4,34 +4,34 @@ BEGIN; CREATE TEMPORARY TABLE mset_update( empire_id INT , - resource_name_id INT , + resource_name TEXT , empmset_weight INT ) ON COMMIT DROP; - INSERT INTO mset_update VALUES ( 1 , 1 , 0 ) , ( 1 , 2 , 0 ); + INSERT INTO mset_update VALUES ( 1 , 'a' , 0 ) , ( 1 , 'b' , 0 ); /***** TESTS BEGIN HERE *****/ SELECT plan( 7 ); SELECT diag_test_name( 'emp.mset_update_set( ) - Valid update' ); - SELECT ok( emp.mset_update_set( 1 , 1 ) ); + SELECT ok( emp.mset_update_set( 'a' , 1 ) ); SELECT diag_test_name( 'emp.mset_update_set( ) - Valid update results (1/2)' ); - SELECT is( empmset_weight , 1 ) FROM mset_update WHERE resource_name_id = 1; + SELECT is( empmset_weight , 1 ) FROM mset_update WHERE resource_name = 'a'; SELECT diag_test_name( 'emp.mset_update_set( ) - Valid update results (2/2)' ); - SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name_id = 2; + SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name = 'b'; DELETE FROM mset_update; - INSERT INTO mset_update VALUES ( 1 , 1 , 0 ) , ( 1 , 2 , 0 ); + INSERT INTO mset_update VALUES ( 1 , 'a' , 0 ) , ( 1 , 'b' , 0 ); SELECT diag_test_name( 'emp.mset_update_set( ) - Update on unknown resource' ); - SELECT ok( NOT emp.mset_update_set( 12 , 1 ) ); + SELECT ok( NOT emp.mset_update_set( 'c' , 1 ) ); SELECT diag_test_name( 'emp.mset_update_set( ) - Unknown resource update results (1/2)' ); - SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name_id = 1; + SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name = 'a'; SELECT diag_test_name( 'emp.mset_update_set( ) - Unknown resource update results (2/2)' ); - SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name_id = 2; + SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name = 'b'; DELETE FROM mset_update; - INSERT INTO mset_update VALUES ( 1 , 1 , 0 ) , ( 1 , 2 , 0 ); + INSERT INTO mset_update VALUES ( 1 , 'a' , 0 ) , ( 1 , 'b' , 0 ); SELECT diag_test_name( 'emp.mset_update_set( ) - Update with invalid weight' ); - SELECT ok( emp.mset_update_set( 1 , -1 ) ); + SELECT ok( emp.mset_update_set( 'a' , -1 ) ); SELECT * FROM finish( ); ROLLBACK; \ No newline at end of file diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/030-mset-update-apply.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/030-mset-update-apply.sql index 14c8d6d..d9088fa 100644 --- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/030-mset-update-apply.sql +++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-mining/030-mset-update-apply.sql @@ -2,6 +2,11 @@ * Test the emp.mset_update_apply() function */ BEGIN; + /* + * Create a pair of strings + */ + INSERT INTO defs.strings (name) VALUES ( 'a' ) , ( 'b' ); + /* * Remove foreign keys from the empire mining settings table, insert some * data into it. @@ -10,15 +15,17 @@ BEGIN; DROP CONSTRAINT fk_empmset_empire , DROP CONSTRAINT fk_empmset_resource; INSERT INTO emp.mining_settings ( empire_id , resource_name_id ) - VALUES ( 1 , 1 ) , ( 1 , 2 ); + SELECT 1 , id + FROM defs.strings + WHERE name IN ( 'a' , 'b' ); /* Create the temporary table */ CREATE TEMPORARY TABLE mset_update( empire_id INT , - resource_name_id INT , + resource_name TEXT , empmset_weight INT ) ON COMMIT DROP; - INSERT INTO mset_update VALUES ( 1 , 1 , 0 ) , ( 1 , 2 , 4 ); + INSERT INTO mset_update VALUES ( 1 , 'a' , 0 ) , ( 1 , 'b' , 4 ); /***** TESTS BEGIN HERE *****/ SELECT plan( 8 ); @@ -27,23 +34,31 @@ BEGIN; SELECT ok( emp.mset_update_apply( ) ); SELECT diag_test_name( 'emp.mset_update_apply() - Empire update results' ); SELECT set_eq( - $$ SELECT resource_name_id , empmset_weight FROM emp.mining_settings $$ , - $$ VALUES ( 1 , 0 ) , ( 2 , 4 ) $$ + $$ SELECT name , empmset_weight + FROM emp.mining_settings + INNER JOIN defs.strings + ON resource_name_id = id $$ , + $$ VALUES ( 'a' , 0 ) , ( 'b' , 4 ) $$ ); /* Reset temporary table and settings */ DELETE FROM mset_update; DELETE FROM emp.mining_settings; INSERT INTO emp.mining_settings ( empire_id , resource_name_id ) - VALUES ( 1 , 1 ) , ( 1 , 2 ); + SELECT 1 , id + FROM defs.strings + WHERE name IN ( 'a' , 'b' ); - INSERT INTO mset_update VALUES ( 1 , 1 , -1 ) , ( 1 , 2 , 4 ); + INSERT INTO mset_update VALUES ( 1 , 'a' , -1 ) , ( 1 , 'b' , 4 ); SELECT diag_test_name( 'emp.mset_update_apply() - Applying invalid empire update' ); SELECT ok( NOT emp.mset_update_apply( ) ); SELECT diag_test_name( 'emp.mset_update_apply() - Invalid empire update results' ); SELECT set_eq( - $$ SELECT resource_name_id , empmset_weight FROM emp.mining_settings $$ , - $$ VALUES ( 1 , 2 ) , ( 2 , 2 ) $$ + $$ SELECT name , empmset_weight + FROM emp.mining_settings + INNER JOIN defs.strings + ON resource_name_id = id $$ , + $$ VALUES ( 'a' , 2 ) , ( 'b' , 2 ) $$ ); @@ -55,38 +70,48 @@ BEGIN; DROP CONSTRAINT fk_emppmset_empire , DROP CONSTRAINT fk_emppmset_resource; INSERT INTO emp.planet_mining_settings ( empire_id , planet_id , resource_name_id ) - VALUES ( 1 , 1 , 1 ) , ( 1 , 1 , 2 ); + SELECT 1 , 1 , id + FROM defs.strings + WHERE name IN ( 'a' , 'b' ); DROP TABLE mset_update; CREATE TEMPORARY TABLE mset_update( empire_id INT , planet_id INT , - resource_name_id INT , + resource_name TEXT , empmset_weight INT ) ON COMMIT DROP; - INSERT INTO mset_update VALUES ( 1 , 1 , 1 , 0 ) , ( 1 , 1 , 2 , 4 ); + INSERT INTO mset_update VALUES ( 1 , 1 , 'a' , 0 ) , ( 1 , 1 , 'b' , 4 ); SELECT diag_test_name( 'emp.mset_update_apply() - Applying valid planet update' ); SELECT ok( emp.mset_update_apply( ) ); SELECT diag_test_name( 'emp.mset_update_apply() - Planet update results' ); SELECT set_eq( - $$ SELECT resource_name_id , emppmset_weight FROM emp.planet_mining_settings $$ , - $$ VALUES ( 1 , 0 ) , ( 2 , 4 ) $$ + $$ SELECT name , emppmset_weight + FROM emp.planet_mining_settings + INNER JOIN defs.strings + ON resource_name_id = id $$ , + $$ VALUES ( 'a' , 0 ) , ( 'b' , 4 ) $$ ); /* Reset temporary table and settings */ DELETE FROM mset_update; DELETE FROM emp.planet_mining_settings; INSERT INTO emp.planet_mining_settings ( empire_id , planet_id , resource_name_id ) - VALUES ( 1 , 1 , 1 ) , ( 1 , 1 , 2 ); + SELECT 1 , 1 , id + FROM defs.strings + WHERE name IN ( 'a' , 'b' ); - INSERT INTO mset_update VALUES ( 1 , 1 , 1 , -1 ) , ( 1 , 1 , 2 , 4 ); + INSERT INTO mset_update VALUES ( 1 , 1 , 'a' , -1 ) , ( 1 , 1 , 'b' , 4 ); SELECT diag_test_name( 'emp.mset_update_apply() - Applying invalid planet update' ); SELECT ok( NOT emp.mset_update_apply( ) ); SELECT diag_test_name( 'emp.mset_update_apply() - Invalid planet update results' ); SELECT set_eq( - $$ SELECT resource_name_id , emppmset_weight FROM emp.planet_mining_settings $$ , - $$ VALUES ( 1 , 2 ) , ( 2 , 2 ) $$ + $$ SELECT name , emppmset_weight + FROM emp.planet_mining_settings + INNER JOIN defs.strings + ON resource_name_id = id $$ , + $$ VALUES ( 'a' , 2 ) , ( 'b' , 2 ) $$ ); SELECT * FROM finish( ); diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-mining/020-mset-update-set.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-mining/020-mset-update-set.sql index cc37514..633ccae 100644 --- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-mining/020-mset-update-set.sql +++ b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-mining/020-mset-update-set.sql @@ -7,7 +7,7 @@ BEGIN; SELECT diag_test_name( 'emp.mset_update_set() - Privileges' ); SELECT lives_ok( $$ - SELECT emp.mset_update_set( 1 , -1 ) + SELECT emp.mset_update_set( 'a' , -1 ) $$ ); SELECT * FROM finish( ); diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/MiningSettingsDAO.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/MiningSettingsDAO.java new file mode 100644 index 0000000..c19656e --- /dev/null +++ b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/MiningSettingsDAO.java @@ -0,0 +1,60 @@ +package com.deepclone.lw.interfaces.game.resources; + + +/** + * Data access object for mining settings + * + *

+ * This interface provides methods which call stored procedures that control mining settings for + * both empires and planets. + * + * @author E. Benoît + */ +public interface MiningSettingsDAO +{ + + /** + * Start an empire settings update + * + *

+ * Start an empire settings update by calling the emp.mset_update_start(INT) stored + * procedure. + * + * @param empireId + * the identifier of the empire whose settings will be updated + * + * @return true on success, false on failure + */ + public boolean startUpdate( int empireId ); + + + /** + * Set the new extraction priority of a resource + * + *

+ * Call the emp.mset_update_set(TEXT,INT) stored procedure to set the new + * extraction priority for some type of resources. An mining settings update (empire- or + * planet-wide) must have been initiated before this method is called. + * + * @param resource + * the identifier of the resource + * @param priority + * the new extraction priority for the resource + * + * @return true on success, false if the resource did not exist. + */ + public boolean setNewPriority( String resource , int priority ); + + + /** + * Apply the current settings update + * + *

+ * This method applies a previously initiated mining settings update by calling the + * emp.mset_update_apply() stored procedure. + * + * @return true on success, false if one of the priorities was + * invalid. + */ + public boolean applyUpdate( ); +} diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesController.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesController.java new file mode 100644 index 0000000..2444da7 --- /dev/null +++ b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesController.java @@ -0,0 +1,30 @@ +package com.deepclone.lw.interfaces.game.resources; + + +import java.util.Map; + + + +/** + * Resources control interface + * + *

+ * This interface corresponds to the component which controls resources from the game's point of + * view. It contains methods that update mining settings. + * + * @author E. Benoît + */ +public interface ResourcesController +{ + + /** + * Update an empire's mining settings + * + * @param empireId + * the empire's identifier + * @param settings + * the new settings + */ + public void updateEmpireSettings( int empireId , Map< String , Integer > settings ); + +} diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/MockMiningSettingsDAO.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/MockMiningSettingsDAO.java new file mode 100644 index 0000000..0b46dce --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/MockMiningSettingsDAO.java @@ -0,0 +1,121 @@ +package com.deepclone.lw.beans.game.resources; + + +import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO; + + + +/** + * Mock mining settings DAO which can be used to simulate failures and trace which methods were + * called. + * + * @author E. Benoît + * + */ +public class MockMiningSettingsDAO + implements MiningSettingsDAO +{ + /** The empire identifier with which {@link #startUpdate(int)} was called */ + private Integer updateEmpire = null; + + /** The amount of calls to {@link #setNewPriority(String, int)} */ + private int callsToSet = 0; + + /** Whether {@link #applyUpdate()} was called */ + private boolean applyCalled = false; + + /** Whether {@link #startUpdate(int)} will succeed or fail */ + private boolean startUpdateSucceeds = true; + + /** Whether applyUpdate will succeed */ + private boolean applyUpdateSucceeds = true; + + /** + * Amount of calls to {@link #setNewPriority(String, int)} that will succeed, or + * null if they will all succeed. + */ + private Integer maxSetCalls = null; + + + /** @return the empire identifier to update */ + public Integer getUpdateEmpire( ) + { + return this.updateEmpire; + } + + + /** @return the amount of calls to {@link #setNewPriority(String, int)} */ + public int getCallsToSet( ) + { + return this.callsToSet; + } + + + /** @return true if {@link #applyUpdate()} was called */ + public boolean wasApplyCalled( ) + { + return this.applyCalled; + } + + + /** + * Determine whether calls to {@link #startUpdate(int)} will succeed + * + * @param startUpdateSucceeds + * true if the call is to succeed, false if it is to fail + */ + public void setStartUpdateSucceeds( boolean startUpdateSucceeds ) + { + this.startUpdateSucceeds = startUpdateSucceeds; + } + + + /** + * Determine whether calls to {@link #applyUpdate()} will succeed + * + * @param applyUpdateSucceeds + * true if the call is to succeed, false if it is to fail + */ + public void setApplyUpdateSucceeds( boolean applyUpdateSucceeds ) + { + this.applyUpdateSucceeds = applyUpdateSucceeds; + } + + + /** + * Set the amount of calls to {@link #setNewPriority(String, int)} that will succeed + * + * @param maxSetCalls + * the amount of calls that will succeed, or null if the method must + * always succeed + */ + public void setMaxSetCalls( Integer maxSetCalls ) + { + this.maxSetCalls = maxSetCalls; + } + + + @Override + public boolean startUpdate( int empireId ) + { + this.updateEmpire = empireId; + return this.startUpdateSucceeds; + } + + + @Override + public boolean setNewPriority( String resource , int priority ) + { + this.callsToSet++; + return ( this.maxSetCalls == null || this.maxSetCalls > this.callsToSet - 1 ); + } + + + @Override + public boolean applyUpdate( ) + { + this.applyCalled = true; + return this.applyUpdateSucceeds; + } + +} diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestResourcesControllerBean.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestResourcesControllerBean.java new file mode 100644 index 0000000..b836ab9 --- /dev/null +++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestResourcesControllerBean.java @@ -0,0 +1,121 @@ +package com.deepclone.lw.beans.game.resources; + + +import static org.junit.Assert.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO; + + + +/** + * Tests for {@link ResourcesControllerBean} + * + * @author E. Benoît + * + */ +public class TestResourcesControllerBean +{ + + /** Empire identifier used in the tests */ + private static final Integer EMPIRE_ID = 42; + + /** Mining settings used in the tests */ + private static final Map< String , Integer > MINING_SETTINGS; + + /** + * Initialise the mining settings map + */ + static { + HashMap< String , Integer > tempMap = new HashMap< String , Integer >( ); + tempMap.put( "test 1" , 1 ); + tempMap.put( "test 2" , 2 ); + tempMap.put( "test 3" , 3 ); + tempMap.put( "test 4" , 4 ); + MINING_SETTINGS = Collections.unmodifiableMap( tempMap ); + } + + /** The mock database access object */ + private MockMiningSettingsDAO miningSettingsDAO; + + /** The instance to test on */ + private ResourcesControllerBean ctrl; + + + /** + * Create the resource controller that will be used in the tests and its various (usually fake) + * dependencies + */ + @Before + public void setUp( ) + { + this.miningSettingsDAO = new MockMiningSettingsDAO( ); + this.ctrl = new ResourcesControllerBean( ); + this.ctrl.setMiningSettingsDAO( this.miningSettingsDAO ); + } + + + /** + * When calling {@link MiningSettingsDAO#startUpdate(int)} fails, the empire settings update is + * interrupted. + */ + @Test + public void testEmpireStartUpdateFails( ) + { + this.miningSettingsDAO.setStartUpdateSucceeds( false ); + this.ctrl.updateEmpireSettings( EMPIRE_ID , MINING_SETTINGS ); + assertEquals( EMPIRE_ID , this.miningSettingsDAO.getUpdateEmpire( ) ); + assertEquals( 0 , this.miningSettingsDAO.getCallsToSet( ) ); + assertFalse( this.miningSettingsDAO.wasApplyCalled( ) ); + } + + + /** + * When calling {@link MiningSettingsDAO#startUpdate(int)} succeeds but one of the calls to + * {@link MiningSettingsDAO#setNewPriority(String, int)} fails, the update is interrupted. + */ + @Test + public void testSetMiningPriorityFails( ) + { + this.miningSettingsDAO.setMaxSetCalls( 2 ); + this.ctrl.updateEmpireSettings( EMPIRE_ID , MINING_SETTINGS ); + assertEquals( EMPIRE_ID , this.miningSettingsDAO.getUpdateEmpire( ) ); + assertEquals( 3 , this.miningSettingsDAO.getCallsToSet( ) ); + assertFalse( this.miningSettingsDAO.wasApplyCalled( ) ); + } + + + /** + * If both {@link MiningSettingsDAO#startUpdate(int)} and + * {@link MiningSettingsDAO#setNewPriority(String, int)} succeed, + * {@link MiningSettingsDAO#applyUpdate()} is called. + */ + @Test + public void testSettingsSuccess( ) + { + this.ctrl.updateEmpireSettings( EMPIRE_ID , MINING_SETTINGS ); + assertEquals( EMPIRE_ID , this.miningSettingsDAO.getUpdateEmpire( ) ); + assertEquals( 4 , this.miningSettingsDAO.getCallsToSet( ) ); + assertTrue( this.miningSettingsDAO.wasApplyCalled( ) ); + } + + + /** + * A failure of {@link MiningSettingsDAO#applyUpdate()} has no influence on the call. + */ + @Test + public void testSettingsApplyFail( ) + { + this.miningSettingsDAO.setApplyUpdateSucceeds( false ); + this.ctrl.updateEmpireSettings( EMPIRE_ID , MINING_SETTINGS ); + assertEquals( EMPIRE_ID , this.miningSettingsDAO.getUpdateEmpire( ) ); + assertEquals( 4 , this.miningSettingsDAO.getCallsToSet( ) ); + assertTrue( this.miningSettingsDAO.wasApplyCalled( ) ); + } +} diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/UpdateEmpireMiningSettingsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/UpdateEmpireMiningSettingsCommand.java new file mode 100644 index 0000000..757417d --- /dev/null +++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/UpdateEmpireMiningSettingsCommand.java @@ -0,0 +1,50 @@ +package com.deepclone.lw.cmd.player; + + +import java.util.Map; + +import com.deepclone.lw.session.Command; + + + +/** + * Command that updates empire mining settings + * + * @author E. Benoît + */ +public class UpdateEmpireMiningSettingsCommand + extends Command +{ + + /** + * Serialisation version identifier + * + *

+ */ + private static final long serialVersionUID = 1L; + + /** The new empire mining settings */ + private final Map< String , Integer > settings; + + + /** + * Initialise the command using mining settings + * + * @param settings + * a map that associates resource identifiers to priorities + */ + public UpdateEmpireMiningSettingsCommand( Map< String , Integer > settings ) + { + this.settings = settings; + } + + + /** @return the mining settings to apply */ + public Map< String , Integer > getSettings( ) + { + return this.settings; + } + +} diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java b/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java index 1cc1607..0f15268 100644 --- a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java +++ b/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java @@ -85,6 +85,19 @@ public class PlayerSession } + /** + * Send an {@link UpdateEmpireMiningSettingsCommand} to the server + * + * @param miningSettings + * the mining settings + */ + public void updateEmpireMiningSettings( Map< String , Integer > miningSettings ) + throws SessionException , SessionServerException , SessionMaintenanceException + { + this.execute( new UpdateEmpireMiningSettingsCommand( miningSettings ) ); + } + + /* Planet list */ public ListPlanetsResponse listPlanets( ) diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl index 639de56..28d1686 100644 --- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl +++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl @@ -63,60 +63,8 @@ <@tab id="economy" title="Economy"> - - <@listview> - <@lv_line headers=true> - <@lv_column width=30>  - <@lv_column width="x">Resource - <@lv_column width=100 centered=true><@over_time "Income" /> - <@lv_column width=100 centered=true><@over_time "Upkeep" /> - <@lv_column width=100 centered=true>Reserves - <@lv_column width=100 centered=true>Mining priority - - - <#list ov.economy as resource> - - <#if previousCategory?has_content && !resource.category?has_content - || resource.category?has_content && !previousCategory?has_content - || resource.category?has_content && previousCategory?has_content - && resource.category != previousCategory> - <@lv_line> - <#if resource.category?has_content> - ${resource.category?xhtml} - <#else> -
- - - <#local previousCategory=resource.category> - - - <@lv_line> - <@lv_column>  - <@lv_column>${resource.title?xhtml} -
${resource.description?xhtml}
- - <@lv_column centered=true>${resource.income?string(",##0")} - <@lv_column centered=true>${resource.upkeep?string(",##0")} - <@lv_column centered=true>${resource.stockpiled?string(",##0")} - <@lv_column centered=true> - <#if resource.miningPriority?has_content> - <#switch resource.miningPriority> - <#case 0>lowest<#break> - <#case 1>low<#break> - <#case 2>normal<#break> - <#case 3>high<#break> - <#case 4>highest<#break> - - <#else> - N/A - - - - - - - - + <#include "overview/resources.ftl" /> + <@overviewResources /> <@tab id="research" title="Research"> diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview/resources.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview/resources.ftl new file mode 100644 index 0000000..7206f92 --- /dev/null +++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview/resources.ftl @@ -0,0 +1,64 @@ +<#macro overviewResources> +
<@listview> + <@lv_line headers=true> + <@lv_column width=30>  + <@lv_column width="x">Resource + <@lv_column width=100 centered=true><@over_time "Income" /> + <@lv_column width=100 centered=true><@over_time "Upkeep" /> + <@lv_column width=100 centered=true>Reserves + <@lv_column width=100 centered=true>Mining priority + + + <#list ov.economy as resource> + + <#if previousCategory?has_content && !resource.category?has_content + || resource.category?has_content && !previousCategory?has_content + || resource.category?has_content && previousCategory?has_content + && resource.category != previousCategory> + <@lv_line> + <#if resource.category?has_content> + ${resource.category?xhtml} + <#else> +
+ + + <#local previousCategory=resource.category> + + + <@lv_line> + <@lv_column>  + <@lv_column>${resource.title?xhtml} +
${resource.description?xhtml}
+ + <@lv_column centered=true>${resource.income?string(",##0")} + <@lv_column centered=true>${resource.upkeep?string(",##0")} + <@lv_column centered=true>${resource.stockpiled?string(",##0")} + <@lv_column centered=true> + <#if resource.miningPriority?has_content> + + <#else> + N/A + + + + + + + <@lv_line headers=true> + <@lv_column width="x" colspan=6>  + + <@lv_line> + <@lv_column colspan=4>  + <@lv_column right=true colspan=2> + + + + +
+ \ No newline at end of file diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl index 5bf71e8..01aa309 100644 --- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl +++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl @@ -63,60 +63,8 @@ <@tab id="economy" title="Économie"> - - <@listview> - <@lv_line headers=true> - <@lv_column width=30>  - <@lv_column width="x">Ressource - <@lv_column width=100 centered=true><@over_time "Bénéfice" /> - <@lv_column width=100 centered=true><@over_time title="Charges" feminin=true pluriel=true /> - <@lv_column width=100 centered=true>Réserves - <@lv_column width=100 centered=true>Priorité d'extraction - - - <#list ov.economy as resource> - - <#if previousCategory?has_content && !resource.category?has_content - || resource.category?has_content && !previousCategory?has_content - || resource.category?has_content && previousCategory?has_content - && resource.category != previousCategory> - <@lv_line> - <#if resource.category?has_content> - ${resource.category?xhtml} - <#else> -
- - - <#local previousCategory=resource.category> - - - <@lv_line> - <@lv_column>  - <@lv_column>${resource.title?xhtml} -
${resource.description?xhtml}
- - <@lv_column centered=true>${resource.income?string(",##0")} - <@lv_column centered=true>${resource.upkeep?string(",##0")} - <@lv_column centered=true>${resource.stockpiled?string(",##0")} - <@lv_column centered=true> - <#if resource.miningPriority?has_content> - <#switch resource.miningPriority> - <#case 0>très basse<#break> - <#case 1>basse<#break> - <#case 2>normale<#break> - <#case 3>haute<#break> - <#case 4>très haute<#break> - - <#else> - N/A - - - - - - - - + <#include "overview/resources.ftl" /> + <@overviewResources /> <@tab id="research" title="Recherche"> diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview/resources.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview/resources.ftl new file mode 100644 index 0000000..fd0a77f --- /dev/null +++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview/resources.ftl @@ -0,0 +1,64 @@ +<#macro overviewResources> +
<@listview> + <@lv_line headers=true> + <@lv_column width=30>  + <@lv_column width="x">Ressource + <@lv_column width=100 centered=true><@over_time "Bénéfice" /> + <@lv_column width=100 centered=true><@over_time title="Charges" feminin=true pluriel=true /> + <@lv_column width=100 centered=true>Réserves + <@lv_column width=100 centered=true>Priorité d'extraction + + + <#list ov.economy as resource> + + <#if previousCategory?has_content && !resource.category?has_content + || resource.category?has_content && !previousCategory?has_content + || resource.category?has_content && previousCategory?has_content + && resource.category != previousCategory> + <@lv_line> + <#if resource.category?has_content> + ${resource.category?xhtml} + <#else> +
+ + + <#local previousCategory=resource.category> + + + <@lv_line> + <@lv_column>  + <@lv_column>${resource.title?xhtml} +
${resource.description?xhtml}
+ + <@lv_column centered=true>${resource.income?string(",##0")} + <@lv_column centered=true>${resource.upkeep?string(",##0")} + <@lv_column centered=true>${resource.stockpiled?string(",##0")} + <@lv_column centered=true> + <#if resource.miningPriority?has_content> + + <#else> + N/A + + + + + + + <@lv_line headers=true> + <@lv_column width="x" colspan=6>  + + <@lv_line> + <@lv_column colspan=4>  + <@lv_column right=true colspan=2> + + + + +
+ \ No newline at end of file diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl index 3e196b7..10b04f9 100644 --- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl +++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl @@ -10,15 +10,15 @@ <#macro lv_column width=0 centered=false right=false colspan=0> <#if width?is_string> - colspan="${colspan}"> + colspan="${colspan}"> <#nested> <#elseif width gt 0> - colspan="${colspan}"> + colspan="${colspan}"> <#nested> <#else> - colspan="${colspan}"> + colspan="${colspan}"> <#nested> diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java b/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java index ffbbf46..ecc8c1f 100644 --- a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java +++ b/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java @@ -1,6 +1,10 @@ package com.deepclone.lw.web.main.game; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; @@ -20,6 +24,15 @@ import com.deepclone.lw.web.csess.PlayerSession; +/** + * Overview page controller + * + *

+ * This page controller implements the "Overview" page, as well as the commands it supports + * (implement technology, update empire mining settings). + * + * @author E. Benoît + */ @Controller @SessionRequirement( value = true , redirectTo = "player-session" , subType = "game" ) @SessionAttributes( "language" ) @@ -27,6 +40,29 @@ public class OverviewPage extends PageControllerBase { + /** + * Main overview display + * + *

+ * This method is mapped to the overview page's URL. It will fetch the empire overview from the + * server and display the appropriate page. + * + * @param request + * the HTTP request + * @param language + * the language from the session + * @param model + * the model + * + * @return the overview page rendering order + * + * @throws SessionException + * if some error occurs on the server + * @throws SessionServerException + * if the server is unreachable + * @throws SessionMaintenanceException + * if the game is under maintenance + */ @RequestMapping( "/overview" ) public String overview( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model ) throws SessionException , SessionServerException , SessionMaintenanceException @@ -36,6 +72,30 @@ public class OverviewPage } + /** + * "Implement technology" command + * + *

+ * This method is mapped to the technology implementation command URL. + * + * @param request + * the HTTP request + * @param language + * the language from the session + * @param model + * the model + * @param tech + * the technology identifier + * + * @return the overview page rendering order + * + * @throws SessionException + * if some error occurs on the server + * @throws SessionServerException + * if the server is unreachable + * @throws SessionMaintenanceException + * if the game is under maintenance + */ @RequestMapping( value = "/implement-{tech}.action" , method = RequestMethod.POST ) public String implement( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model , @PathVariable String tech ) @@ -52,4 +112,67 @@ public class OverviewPage return this.render( model , "game" , language , "overview" , pSession.implementTechnology( techId ) ); } + + @RequestMapping( value = "/update-mining-settings.action" , method = RequestMethod.POST ) + public String updateMiningSettings( HttpServletRequest request , @ModelAttribute( "language" ) String language , + Model model ) + throws SessionException , SessionServerException , SessionMaintenanceException + { + Map< String , Integer > miningSettings = this.getMiningSettings( request ); + if ( miningSettings != null ) { + this.getSession( PlayerSession.class , request ).updateEmpireMiningSettings( miningSettings ); + } + return this.redirect( "overview#economy" ); + } + + + /** + * Extract mining priorities from the HTTP request + * + *

+ * Look for all submitted fields that begin with "ems-" then try to extract their values into a + * map that associates resource identifiers to priorities. + * + * @param request + * the HTTP request + * + * @return the map containing the submitted mining settings, or null if one of the + * values was incorrect. + */ + private Map< String , Integer > getMiningSettings( HttpServletRequest request ) + { + Map< String , Object > input = this.getInput( request ); + Map< String , Integer > miningSettings = new HashMap< String , Integer >( ); + for ( Entry< String , Object > entry : input.entrySet( ) ) { + // Ignore items which are not mining settings + String name = entry.getKey( ); + if ( !name.startsWith( "ems-" ) ) { + continue; + } + name = name.substring( 4 ); + + // Get values + if ( ! ( entry.getValue( ) instanceof String[] ) ) { + continue; + } + String[] values = (String[]) entry.getValue( ); + if ( values.length < 1 ) { + continue; + } + + // Pre-validate them + int value; + try { + value = Integer.parseInt( values[ 0 ] ); + } catch ( NumberFormatException e ) { + value = -1; + } + if ( value < 0 || value > 4 ) { + return null; + } + + miningSettings.put( name , value ); + } + return miningSettings; + } } diff --git a/legacyworlds/dev-tools/run-database-tests.sh b/legacyworlds/dev-tools/run-database-tests.sh new file mode 100755 index 0000000..cfaf812 --- /dev/null +++ b/legacyworlds/dev-tools/run-database-tests.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +[ -z "$3" ] && { + echo "Syntax: $0 test-database admin-user test-user [misc]" >&2 + echo + echo "Where misc is:" + echo " --no-create don't create the DB" + echo " --run-name name run tests matching '*name*'" + echo + exit 1 +} + +test_db="$1" +admin_user="$2" +test_user="$3" + +create_db=1 +run_name="" +while ! [ -z "$4" ]; do + if [ "x$4" = "x--no-create" ]; then + create_db=0 + elif [ "x$4" = "x--run-name" ]; then + shift + run_name="$4" + fi + + shift +done + +scriptdir="`dirname $0`" +tempdir="`mktemp -d`" +cp -Rap $scriptdir/../../legacyworlds-server-data/db-structure/* $tempdir/ +cat > $tempdir/db-config.txt <