Empire mining settings

* Modified mining settings stored procedures to use text identifiers
instead of numeric identifiers

* Added DAO for mining settings and controller for resource operations

* Added UpdateEmpireMiningSettingsCommand and associated command
delegate. The command always returns NullResponse.

* Overview page templates split into multiple files for clarity, added
priority update form to the empire economy view and associated web
server handler
This commit is contained in:
Emmanuel BENOîT 2012-02-05 10:10:43 +01:00
parent 92dd01ffce
commit d38576a5cf
24 changed files with 1024 additions and 160 deletions

View file

@ -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
*
* <p>
* This component implements the methods which allow mining settings to be updated by calling the
* appropriate stored procedures.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class MiningSettingsDAOBean
implements MiningSettingsDAO
{
/** <code>emp.mset_update_start(INT)</code> stored procedure */
private StoredProc pStartEmpireUpdate;
/** <code>emp.mset_update_set(TEXT,INT)</code> stored procedure */
private StoredProc pSetMiningPriority;
/** <code>emp.mset_update_apply()</code> 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" );
}
}

View file

@ -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
*
* <p>
* This component implements all game actions that affect resources or resource-related information,
* such as mining priorities.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@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
*
* <p>
* 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( );
}
}

View file

@ -3,6 +3,8 @@
xsi:schemaLocation=" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="miningSettingsDAO" class="com.deepclone.lw.beans.game.resources.MiningSettingsDAOBean" />
<bean id="resourcesController" class="com.deepclone.lw.beans.game.resources.ResourcesControllerBean" />
<bean id="resourcesInformationDAO" class="com.deepclone.lw.beans.game.resources.ResourcesInformationDAOBean" /> <bean id="resourcesInformationDAO" class="com.deepclone.lw.beans.game.resources.ResourcesInformationDAOBean" />
</beans> </beans>

View file

@ -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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
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( );
}
}

View file

@ -45,6 +45,7 @@
<!-- Game: empire --> <!-- Game: empire -->
<bean class="com.deepclone.lw.beans.user.player.game.OverviewCommandDelegateBean" /> <bean class="com.deepclone.lw.beans.user.player.game.OverviewCommandDelegateBean" />
<bean class="com.deepclone.lw.beans.user.player.game.ImplementTechCommandDelegateBean" /> <bean class="com.deepclone.lw.beans.user.player.game.ImplementTechCommandDelegateBean" />
<bean class="com.deepclone.lw.beans.user.player.game.UpdateEmpireMiningSettingsCommandDelegateBean" />
<bean class="com.deepclone.lw.beans.user.player.game.GetNewPlanetCommandDelegateBean" /> <bean class="com.deepclone.lw.beans.user.player.game.GetNewPlanetCommandDelegateBean" />
<!-- Game: planet list --> <!-- Game: planet list -->

View file

@ -29,15 +29,17 @@ BEGIN
CREATE TEMPORARY TABLE mset_update( CREATE TEMPORARY TABLE mset_update(
empire_id INT , empire_id INT ,
resource_name_id INT , resource_name TEXT ,
empmset_weight INT empmset_weight INT
) ON COMMIT DROP; ) ON COMMIT DROP;
INSERT INTO mset_update INSERT INTO mset_update
SELECT _mset.empire_id , _mset.resource_name_id , 2 SELECT _mset.empire_id , _str.name , 2
FROM emp.empires _empire FROM emp.empires _empire
INNER JOIN emp.mining_settings _mset INNER JOIN emp.mining_settings _mset
ON _empire.name_id = _mset.empire_id 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 WHERE _empire.name_id = _empire_id
FOR SHARE OF _empire FOR SHARE OF _empire
FOR UPDATE OF _mset; FOR UPDATE OF _mset;
@ -81,7 +83,7 @@ BEGIN
CREATE TEMPORARY TABLE mset_update( CREATE TEMPORARY TABLE mset_update(
empire_id INT , empire_id INT ,
planet_id INT , planet_id INT ,
resource_name_id INT , resource_name TEXT ,
empmset_weight INT empmset_weight INT
) ON COMMIT DROP; ) ON COMMIT DROP;
@ -106,8 +108,10 @@ BEGIN
FOR UPDATE; FOR UPDATE;
INSERT INTO mset_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 FROM verse.resource_providers
INNER JOIN defs.strings _str
ON _str.id = resource_name_id
WHERE planet_id = _planet_id; WHERE planet_id = _planet_id;
RETURN TRUE; RETURN TRUE;
@ -131,14 +135,14 @@ GRANT EXECUTE
* must be called after emp.mset_update_start() has initialised the table. * must be called after emp.mset_update_start() has initialised the table.
* *
* Parameters: * Parameters:
* _resource_id The resource's identifier * _resource The resource's text identifier
* _weight The setting's new value * _weight The setting's new value
* *
* Returns: * Returns:
* ? True if the resource exists, false otherwise. * ? True if the resource exists, false otherwise.
*/ */
DROP FUNCTION IF EXISTS emp.mset_update_set( INT , INT ); DROP FUNCTION IF EXISTS emp.mset_update_set( TEXT , INT );
CREATE FUNCTION emp.mset_update_set( _resource_id INT , _weight INT ) CREATE FUNCTION emp.mset_update_set( _resource TEXT , _weight INT )
RETURNS BOOLEAN RETURNS BOOLEAN
STRICT VOLATILE STRICT VOLATILE
SECURITY DEFINER SECURITY DEFINER
@ -147,7 +151,7 @@ BEGIN
UPDATE mset_update UPDATE mset_update
SET empmset_weight = _weight SET empmset_weight = _weight
WHERE resource_name_id = _resource_id; WHERE resource_name = _resource;
RETURN FOUND; RETURN FOUND;
END; END;
@ -155,10 +159,10 @@ $mset_update_set$ LANGUAGE PLPGSQL;
REVOKE EXECUTE REVOKE EXECUTE
ON FUNCTION emp.mset_update_set( INT , INT ) ON FUNCTION emp.mset_update_set( TEXT , INT )
FROM PUBLIC; FROM PUBLIC;
GRANT EXECUTE GRANT EXECUTE
ON FUNCTION emp.mset_update_set( INT , INT ) ON FUNCTION emp.mset_update_set( TEXT , INT )
TO :dbuser; TO :dbuser;
@ -201,8 +205,10 @@ BEGIN
empire_id , planet_id , resource_name_id , empire_id , planet_id , resource_name_id ,
emppmset_weight emppmset_weight
) SELECT empire_id , planet_id , ) SELECT empire_id , planet_id ,
resource_name_id , empmset_weight _str.id , empmset_weight
FROM mset_update; FROM mset_update
INNER JOIN defs.strings _str
ON _str.name = resource_name;
EXCEPTION EXCEPTION
@ -211,8 +217,10 @@ BEGIN
UPDATE emp.mining_settings _settings UPDATE emp.mining_settings _settings
SET empmset_weight = _update.empmset_weight SET empmset_weight = _update.empmset_weight
FROM mset_update _update FROM mset_update _update
INNER JOIN defs.strings _str
ON _str.name = _update.resource_name
WHERE _update.empire_id = _settings.empire_id WHERE _update.empire_id = _settings.empire_id
AND _update.resource_name_id = _settings.resource_name_id; AND _str.id = _settings.resource_name_id;
END; END;
RETURN TRUE; RETURN TRUE;

View file

@ -23,7 +23,7 @@ BEGIN;
SELECT ok( NOT emp.mset_update_start( _get_bad_emp_name( ) ) ); 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 diag_test_name( 'emp.mset_update_start( INT ) - Temporary table exists despite bad empire identifier' );
SELECT has_table( 'mset_update' ); 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' ); SELECT diag_test_name( 'emp.mset_update_start( INT ) - Return value on valid empire identifier' );

View file

@ -28,31 +28,31 @@ BEGIN;
SELECT ok( NOT emp.mset_update_start( _get_bad_emp_name( ) , _get_map_name( 'testPlanet1' ) ) ); 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 diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite bad empire identifier' );
SELECT has_table( 'mset_update' ); 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 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 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 diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite bad planet identifier' );
SELECT has_table( 'mset_update' ); 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 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 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 diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite unowned planet identifier' );
SELECT has_table( 'mset_update' ); 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 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 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 diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite unowned planet identifier' );
SELECT has_table( 'mset_update' ); 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 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 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 diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite planet with no resource providers' );
SELECT has_table( 'mset_update' ); 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' ); SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on valid identifiers' );

View file

@ -4,34 +4,34 @@
BEGIN; BEGIN;
CREATE TEMPORARY TABLE mset_update( CREATE TEMPORARY TABLE mset_update(
empire_id INT , empire_id INT ,
resource_name_id INT , resource_name TEXT ,
empmset_weight INT empmset_weight INT
) ON COMMIT DROP; ) 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 *****/ /***** TESTS BEGIN HERE *****/
SELECT plan( 7 ); SELECT plan( 7 );
SELECT diag_test_name( 'emp.mset_update_set( ) - Valid update' ); 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 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 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; 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 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 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 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; 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 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( ); SELECT * FROM finish( );
ROLLBACK; ROLLBACK;

View file

@ -2,6 +2,11 @@
* Test the emp.mset_update_apply() function * Test the emp.mset_update_apply() function
*/ */
BEGIN; 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 * Remove foreign keys from the empire mining settings table, insert some
* data into it. * data into it.
@ -10,15 +15,17 @@ BEGIN;
DROP CONSTRAINT fk_empmset_empire , DROP CONSTRAINT fk_empmset_empire ,
DROP CONSTRAINT fk_empmset_resource; DROP CONSTRAINT fk_empmset_resource;
INSERT INTO emp.mining_settings ( empire_id , resource_name_id ) 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 the temporary table */
CREATE TEMPORARY TABLE mset_update( CREATE TEMPORARY TABLE mset_update(
empire_id INT , empire_id INT ,
resource_name_id INT , resource_name TEXT ,
empmset_weight INT empmset_weight INT
) ON COMMIT DROP; ) 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 *****/ /***** TESTS BEGIN HERE *****/
SELECT plan( 8 ); SELECT plan( 8 );
@ -27,23 +34,31 @@ BEGIN;
SELECT ok( emp.mset_update_apply( ) ); SELECT ok( emp.mset_update_apply( ) );
SELECT diag_test_name( 'emp.mset_update_apply() - Empire update results' ); SELECT diag_test_name( 'emp.mset_update_apply() - Empire update results' );
SELECT set_eq( SELECT set_eq(
$$ SELECT resource_name_id , empmset_weight FROM emp.mining_settings $$ , $$ SELECT name , empmset_weight
$$ VALUES ( 1 , 0 ) , ( 2 , 4 ) $$ FROM emp.mining_settings
INNER JOIN defs.strings
ON resource_name_id = id $$ ,
$$ VALUES ( 'a' , 0 ) , ( 'b' , 4 ) $$
); );
/* Reset temporary table and settings */ /* Reset temporary table and settings */
DELETE FROM mset_update; DELETE FROM mset_update;
DELETE FROM emp.mining_settings; DELETE FROM emp.mining_settings;
INSERT INTO emp.mining_settings ( empire_id , resource_name_id ) 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 diag_test_name( 'emp.mset_update_apply() - Applying invalid empire update' );
SELECT ok( NOT emp.mset_update_apply( ) ); SELECT ok( NOT emp.mset_update_apply( ) );
SELECT diag_test_name( 'emp.mset_update_apply() - Invalid empire update results' ); SELECT diag_test_name( 'emp.mset_update_apply() - Invalid empire update results' );
SELECT set_eq( SELECT set_eq(
$$ SELECT resource_name_id , empmset_weight FROM emp.mining_settings $$ , $$ SELECT name , empmset_weight
$$ VALUES ( 1 , 2 ) , ( 2 , 2 ) $$ 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_empire ,
DROP CONSTRAINT fk_emppmset_resource; DROP CONSTRAINT fk_emppmset_resource;
INSERT INTO emp.planet_mining_settings ( empire_id , planet_id , resource_name_id ) 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; DROP TABLE mset_update;
CREATE TEMPORARY TABLE mset_update( CREATE TEMPORARY TABLE mset_update(
empire_id INT , empire_id INT ,
planet_id INT , planet_id INT ,
resource_name_id INT , resource_name TEXT ,
empmset_weight INT empmset_weight INT
) ON COMMIT DROP; ) 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 diag_test_name( 'emp.mset_update_apply() - Applying valid planet update' );
SELECT ok( emp.mset_update_apply( ) ); SELECT ok( emp.mset_update_apply( ) );
SELECT diag_test_name( 'emp.mset_update_apply() - Planet update results' ); SELECT diag_test_name( 'emp.mset_update_apply() - Planet update results' );
SELECT set_eq( SELECT set_eq(
$$ SELECT resource_name_id , emppmset_weight FROM emp.planet_mining_settings $$ , $$ SELECT name , emppmset_weight
$$ VALUES ( 1 , 0 ) , ( 2 , 4 ) $$ FROM emp.planet_mining_settings
INNER JOIN defs.strings
ON resource_name_id = id $$ ,
$$ VALUES ( 'a' , 0 ) , ( 'b' , 4 ) $$
); );
/* Reset temporary table and settings */ /* Reset temporary table and settings */
DELETE FROM mset_update; DELETE FROM mset_update;
DELETE FROM emp.planet_mining_settings; DELETE FROM emp.planet_mining_settings;
INSERT INTO emp.planet_mining_settings ( empire_id , planet_id , resource_name_id ) 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 diag_test_name( 'emp.mset_update_apply() - Applying invalid planet update' );
SELECT ok( NOT emp.mset_update_apply( ) ); SELECT ok( NOT emp.mset_update_apply( ) );
SELECT diag_test_name( 'emp.mset_update_apply() - Invalid planet update results' ); SELECT diag_test_name( 'emp.mset_update_apply() - Invalid planet update results' );
SELECT set_eq( SELECT set_eq(
$$ SELECT resource_name_id , emppmset_weight FROM emp.planet_mining_settings $$ , $$ SELECT name , emppmset_weight
$$ VALUES ( 1 , 2 ) , ( 2 , 2 ) $$ FROM emp.planet_mining_settings
INNER JOIN defs.strings
ON resource_name_id = id $$ ,
$$ VALUES ( 'a' , 2 ) , ( 'b' , 2 ) $$
); );
SELECT * FROM finish( ); SELECT * FROM finish( );

View file

@ -7,7 +7,7 @@ BEGIN;
SELECT diag_test_name( 'emp.mset_update_set() - Privileges' ); SELECT diag_test_name( 'emp.mset_update_set() - Privileges' );
SELECT lives_ok( $$ SELECT lives_ok( $$
SELECT emp.mset_update_set( 1 , -1 ) SELECT emp.mset_update_set( 'a' , -1 )
$$ ); $$ );
SELECT * FROM finish( ); SELECT * FROM finish( );

View file

@ -0,0 +1,60 @@
package com.deepclone.lw.interfaces.game.resources;
/**
* Data access object for mining settings
*
* <p>
* This interface provides methods which call stored procedures that control mining settings for
* both empires and planets.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public interface MiningSettingsDAO
{
/**
* Start an empire settings update
*
* <p>
* Start an empire settings update by calling the <code>emp.mset_update_start(INT)</code> stored
* procedure.
*
* @param empireId
* the identifier of the empire whose settings will be updated
*
* @return <code>true</code> on success, <code>false</code> on failure
*/
public boolean startUpdate( int empireId );
/**
* Set the new extraction priority of a resource
*
* <p>
* Call the <code>emp.mset_update_set(TEXT,INT)</code> 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 <code>true</code> on success, <code>false</code> if the resource did not exist.
*/
public boolean setNewPriority( String resource , int priority );
/**
* Apply the current settings update
*
* <p>
* This method applies a previously initiated mining settings update by calling the
* <code>emp.mset_update_apply()</code> stored procedure.
*
* @return <code>true</code> on success, <code>false</code> if one of the priorities was
* invalid.
*/
public boolean applyUpdate( );
}

View file

@ -0,0 +1,30 @@
package com.deepclone.lw.interfaces.game.resources;
import java.util.Map;
/**
* Resources control interface
*
* <p>
* This interface corresponds to the component which controls resources from the game's point of
* view. It contains methods that update mining settings.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
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 );
}

View file

@ -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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
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
* <code>null</code> 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 <code>true</code> if {@link #applyUpdate()} was called */
public boolean wasApplyCalled( )
{
return this.applyCalled;
}
/**
* Determine whether calls to {@link #startUpdate(int)} will succeed
*
* @param startUpdateSucceeds
* <code>true</code> if the call is to succeed, <code>false</code> if it is to fail
*/
public void setStartUpdateSucceeds( boolean startUpdateSucceeds )
{
this.startUpdateSucceeds = startUpdateSucceeds;
}
/**
* Determine whether calls to {@link #applyUpdate()} will succeed
*
* @param applyUpdateSucceeds
* <code>true</code> if the call is to succeed, <code>false</code> 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 <code>null</code> 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;
}
}

View file

@ -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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
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( ) );
}
}

View file

@ -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 <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class UpdateEmpireMiningSettingsCommand
extends Command
{
/**
* Serialisation version identifier
*
* <ul>
* <li>Introduced in B6M2
* </ul>
*/
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;
}
}

View file

@ -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 */ /* Planet list */
public ListPlanetsResponse listPlanets( ) public ListPlanetsResponse listPlanets( )

View file

@ -63,60 +63,8 @@
</@tab> </@tab>
<@tab id="economy" title="Economy"> <@tab id="economy" title="Economy">
<#include "overview/resources.ftl" />
<@listview> <@overviewResources />
<@lv_line headers=true>
<@lv_column width=30>&nbsp;</@lv_column>
<@lv_column width="x">Resource</@lv_column>
<@lv_column width=100 centered=true><@over_time "Income" /></@lv_column>
<@lv_column width=100 centered=true><@over_time "Upkeep" /></@lv_column>
<@lv_column width=100 centered=true>Reserves</@lv_column>
<@lv_column width=100 centered=true>Mining priority</@lv_column>
</@lv_line>
<#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>
<td colspan="5"><strong>${resource.category?xhtml}</strong></td>
<#else>
<td colspan="5"><hr /></td>
</#if>
</@lv_line>
<#local previousCategory=resource.category>
</#if>
<@lv_line>
<@lv_column>&nbsp;</@lv_column>
<@lv_column>${resource.title?xhtml}
<div class="auto-hide">${resource.description?xhtml}</div>
</@lv_column>
<@lv_column centered=true>${resource.income?string(",##0")}</@lv_column>
<@lv_column centered=true>${resource.upkeep?string(",##0")}</@lv_column>
<@lv_column centered=true>${resource.stockpiled?string(",##0")}</@lv_column>
<@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>
</#switch>
<#else>
N/A
</#if>
</@lv_column>
</@lv_line>
</#list>
</@listview>
</@tab> </@tab>
<@tab id="research" title="Research"> <@tab id="research" title="Research">

View file

@ -0,0 +1,64 @@
<#macro overviewResources>
<form action="update-mining-settings.action" method="POST"><@listview>
<@lv_line headers=true>
<@lv_column width=30>&nbsp;</@lv_column>
<@lv_column width="x">Resource</@lv_column>
<@lv_column width=100 centered=true><@over_time "Income" /></@lv_column>
<@lv_column width=100 centered=true><@over_time "Upkeep" /></@lv_column>
<@lv_column width=100 centered=true>Reserves</@lv_column>
<@lv_column width=100 centered=true>Mining priority</@lv_column>
</@lv_line>
<#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>
<td colspan="5"><strong>${resource.category?xhtml}</strong></td>
<#else>
<td colspan="5"><hr /></td>
</#if>
</@lv_line>
<#local previousCategory=resource.category>
</#if>
<@lv_line>
<@lv_column>&nbsp;</@lv_column>
<@lv_column>${resource.title?xhtml}
<div class="auto-hide">${resource.description?xhtml}</div>
</@lv_column>
<@lv_column centered=true>${resource.income?string(",##0")}</@lv_column>
<@lv_column centered=true>${resource.upkeep?string(",##0")}</@lv_column>
<@lv_column centered=true>${resource.stockpiled?string(",##0")}</@lv_column>
<@lv_column centered=true>
<#if resource.miningPriority?has_content>
<select name="ems-${resource.identifier?xhtml}" class="input">
<option style="padding: 0 5px" value="0" <#if resource.miningPriority = 0>selected="selected"</#if>>lowest</option>
<option style="padding: 0 5px" value="1" <#if resource.miningPriority = 1>selected="selected"</#if>>low</option>
<option style="padding: 0 5px" value="2" <#if resource.miningPriority = 2>selected="selected"</#if>>normal</option>
<option style="padding: 0 5px" value="3" <#if resource.miningPriority = 3>selected="selected"</#if>>high</option>
<option style="padding: 0 5px" value="4" <#if resource.miningPriority = 4>selected="selected"</#if>>highest</option>
</select>
<#else>
N/A
</#if>
</@lv_column>
</@lv_line>
</#list>
<@lv_line headers=true>
<@lv_column width="x" colspan=6>&nbsp;</@lv_column>
</@lv_line>
<@lv_line>
<@lv_column colspan=4>&nbsp;</@lv_column>
<@lv_column right=true colspan=2>
<input type="submit" value="Update mining priorities" class="input" style="margin: 15px 0 0 0" />
</@lv_column>
</@lv_line>
</@listview></form>
</#macro>

View file

@ -63,60 +63,8 @@
</@tab> </@tab>
<@tab id="economy" title="Économie"> <@tab id="economy" title="Économie">
<#include "overview/resources.ftl" />
<@listview> <@overviewResources />
<@lv_line headers=true>
<@lv_column width=30>&nbsp;</@lv_column>
<@lv_column width="x">Ressource</@lv_column>
<@lv_column width=100 centered=true><@over_time "Bénéfice" /></@lv_column>
<@lv_column width=100 centered=true><@over_time title="Charges" feminin=true pluriel=true /></@lv_column>
<@lv_column width=100 centered=true>Réserves</@lv_column>
<@lv_column width=100 centered=true>Priorité d'extraction</@lv_column>
</@lv_line>
<#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>
<td colspan="5"><strong>${resource.category?xhtml}</strong></td>
<#else>
<td colspan="5"><hr /></td>
</#if>
</@lv_line>
<#local previousCategory=resource.category>
</#if>
<@lv_line>
<@lv_column>&nbsp;</@lv_column>
<@lv_column>${resource.title?xhtml}
<div class="auto-hide">${resource.description?xhtml}</div>
</@lv_column>
<@lv_column centered=true>${resource.income?string(",##0")}</@lv_column>
<@lv_column centered=true>${resource.upkeep?string(",##0")}</@lv_column>
<@lv_column centered=true>${resource.stockpiled?string(",##0")}</@lv_column>
<@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>
</#switch>
<#else>
N/A
</#if>
</@lv_column>
</@lv_line>
</#list>
</@listview>
</@tab> </@tab>
<@tab id="research" title="Recherche"> <@tab id="research" title="Recherche">

View file

@ -0,0 +1,64 @@
<#macro overviewResources>
<form action="update-mining-settings.action" method="POST"><@listview>
<@lv_line headers=true>
<@lv_column width=30>&nbsp;</@lv_column>
<@lv_column width="x">Ressource</@lv_column>
<@lv_column width=100 centered=true><@over_time "Bénéfice" /></@lv_column>
<@lv_column width=100 centered=true><@over_time title="Charges" feminin=true pluriel=true /></@lv_column>
<@lv_column width=100 centered=true>Réserves</@lv_column>
<@lv_column width=100 centered=true>Priorité d'extraction</@lv_column>
</@lv_line>
<#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>
<td colspan="5"><strong>${resource.category?xhtml}</strong></td>
<#else>
<td colspan="5"><hr /></td>
</#if>
</@lv_line>
<#local previousCategory=resource.category>
</#if>
<@lv_line>
<@lv_column>&nbsp;</@lv_column>
<@lv_column>${resource.title?xhtml}
<div class="auto-hide">${resource.description?xhtml}</div>
</@lv_column>
<@lv_column centered=true>${resource.income?string(",##0")}</@lv_column>
<@lv_column centered=true>${resource.upkeep?string(",##0")}</@lv_column>
<@lv_column centered=true>${resource.stockpiled?string(",##0")}</@lv_column>
<@lv_column centered=true>
<#if resource.miningPriority?has_content>
<select name="ems-${resource.identifier?xhtml}" class="input">
<option style="padding: 0 5px" value="0" <#if resource.miningPriority = 0>selected="selected"</#if>>très basse</option>
<option style="padding: 0 5px" value="1" <#if resource.miningPriority = 1>selected="selected"</#if>>basse</option>
<option style="padding: 0 5px" value="2" <#if resource.miningPriority = 2>selected="selected"</#if>>normale</option>
<option style="padding: 0 5px" value="3" <#if resource.miningPriority = 3>selected="selected"</#if>>haute</option>
<option style="padding: 0 5px" value="4" <#if resource.miningPriority = 4>selected="selected"</#if>>très haute</option>
</select>
<#else>
N/A
</#if>
</@lv_column>
</@lv_line>
</#list>
<@lv_line headers=true>
<@lv_column width="x" colspan=6>&nbsp;</@lv_column>
</@lv_line>
<@lv_line>
<@lv_column colspan=4>&nbsp;</@lv_column>
<@lv_column right=true colspan=2>
<input type="submit" value="Modifier les priorités" class="input" style="margin: 15px 0 0 0" />
</@lv_column>
</@lv_line>
</@listview></form>
</#macro>

View file

@ -1,6 +1,10 @@
package com.deepclone.lw.web.main.game; 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 javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -20,6 +24,15 @@ import com.deepclone.lw.web.csess.PlayerSession;
/**
* Overview page controller
*
* <p>
* This page controller implements the "Overview" page, as well as the commands it supports
* (implement technology, update empire mining settings).
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@Controller @Controller
@SessionRequirement( value = true , redirectTo = "player-session" , subType = "game" ) @SessionRequirement( value = true , redirectTo = "player-session" , subType = "game" )
@SessionAttributes( "language" ) @SessionAttributes( "language" )
@ -27,6 +40,29 @@ public class OverviewPage
extends PageControllerBase extends PageControllerBase
{ {
/**
* Main overview display
*
* <p>
* 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" ) @RequestMapping( "/overview" )
public String overview( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model ) public String overview( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model )
throws SessionException , SessionServerException , SessionMaintenanceException throws SessionException , SessionServerException , SessionMaintenanceException
@ -36,6 +72,30 @@ public class OverviewPage
} }
/**
* "Implement technology" command
*
* <p>
* 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 ) @RequestMapping( value = "/implement-{tech}.action" , method = RequestMethod.POST )
public String implement( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model , public String implement( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model ,
@PathVariable String tech ) @PathVariable String tech )
@ -52,4 +112,67 @@ public class OverviewPage
return this.render( model , "game" , language , "overview" , pSession.implementTechnology( techId ) ); 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
*
* <p>
* 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 <code>null</code> 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;
}
} }

View file

@ -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 <<EOF
admin=$admin_user
db=$test_db
user=$test_user
password=$test_user
EOF
(
cd $tempdir
if [ $create_db -eq 1 ]; then
echo "Creating DB..."
psql -vQUIET=1 -vON_ERROR_STOP=1 --file database.sql || exit 1
psql -vQUIET=1 -f tests/pgtap.sql $test_db || exit 1
fi
cd tests
if [ "x$run_name" = "x" ]; then
run_name='*.sql'
else
run_name='*'"$run_name"'*'
fi
pg_prove -d $test_db `find admin/ -type f -name "$run_name" | sort` || exit 1
pg_prove -U $test_user -d $test_db `find user/ -type f -name "$run_name" | sort` || exit 1
)
result=$?
rm -rf $tempdir
exit $result