In-game resources views

* Added session records to carry resource information over to the
clients

* Added SQL support code for the various views

* Added interface and implementation of the resource information access
component

* Hooked resources information queries into both the empire and planet
management component

* Added resources display to planet and overview pages
This commit is contained in:
Emmanuel BENOîT 2012-02-04 10:43:12 +01:00
parent 56eddcc4f0
commit 597429fadf
45 changed files with 3211 additions and 52 deletions

View file

@ -0,0 +1,61 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
/**
* Base class for resource information row mappers
*
* <p>
* This class can be used to map resource information rows (for either planets or empires). It
* provides a method which maps the resource information's descriptive fields, and implements
* Spring's {@link RowMapper} for the correct type.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
* @param <RTYPE>
* a resource information record based on {@link AbstractResourceRecord}.
*/
abstract class AbstractResourceMapper< RTYPE extends AbstractResourceRecord >
implements RowMapper< RTYPE >
{
/**
* Extract a resource information row's descriptive fields
*
* <p>
* This method will extract the descriptive fields from a resource information row and store
* them in a resource information instance. It extracts:
* <ul>
* <li>the resource's text identifier,
* <li>the resource's internationalised name,
* <li>the resource's internationalised description,
* <li>the resource's internationalised category name, if there is one.
* </ul>
*
* @param resource
* the resource information record
* @param rs
* the result set with the correct row selected
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
protected final void getResourceDescription( RTYPE resource , ResultSet rs )
throws SQLException
{
resource.setIdentifier( rs.getString( "resource_identifier" ) );
resource.setTitle( rs.getString( "resource_name" ) );
resource.setDescription( rs.getString( "resource_description" ) );
resource.setCategory( rs.getString( "resource_category" ) );
}
}

View file

@ -0,0 +1,72 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
/**
* Row mapper for empire resources
*
* <p>
* This class is responsible for converting empire resource information rows into instances of the
* corresponding class, {@link EmpireResourceRecord}.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class EmpireResourceMapper
extends AbstractResourceMapper< EmpireResourceRecord >
{
/**
* Map a row from <code>emp.resources_view</code>
*
* <p>
* This method extracts the resource's description and the fields specific to empire resource
* information from the row, returning the information as an {@link EmpireResourceRecord}
* instance.
*/
@Override
public EmpireResourceRecord mapRow( ResultSet rs , int rowNum )
throws SQLException
{
EmpireResourceRecord resource = new EmpireResourceRecord( );
this.getResourceDescription( resource , rs );
this.getEmpireFields( resource , rs );
return resource;
}
/**
* Read empire-specific resource information from a row
*
* <p>
* This method extracts the stockpiled quantity as well as income and upkeep from the row. If a
* mining setting is set, it extracts it as well.
*
* @param resource
* the empire resource record
* @param rs
* the result set with the correct row selected
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
private void getEmpireFields( EmpireResourceRecord resource , ResultSet rs )
throws SQLException
{
resource.setStockpiled( rs.getLong( "empres_possessed" ) );
resource.setPlanetUpkeep( rs.getLong( "planets_upkeep" ) );
resource.setIncome( rs.getLong( "planets_income" ) );
resource.setFleetUpkeep( rs.getLong( "fleets_upkeep" ) );
int miningPriority = rs.getInt( "empmset_weight" );
if ( !rs.wasNull( ) ) {
resource.setMiningPriority( miningPriority );
}
}
}

View file

@ -0,0 +1,105 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
import com.deepclone.lw.cmd.player.gdata.planets.ResourceProviderRecord;
/**
* Row mapper for planet resources
*
* <p>
* This class maps rows obtained from the planet resources information stored procedure into
* instances of {@link PlanetResourceRecord} which can be sent to a client.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
class PlanetResourceMapper
extends AbstractResourceMapper< PlanetResourceRecord >
{
/**
* Map a row from <code>emp.get_planet_resources( )</code>
*
* <p>
* This method extracts fields that are always present, generating the
* {@link PlanetResourceRecord} instance and setting it accordingly, then reads resource
* provider columns and adds a {@link ResourceProviderRecord} instance to the record if
* necessary.
*/
@Override
public PlanetResourceRecord mapRow( ResultSet rs , int rowNum )
throws SQLException
{
PlanetResourceRecord resource = getResourceFields( rs );
getResourceProvider( rs , resource );
return resource;
}
/**
* Map common fields into a {@link PlanetResourceRecord} instance
*
* <p>
* This method creates the instance then reads descriptive fields, then extracts the income,
* upkeep and investment fields.
*
* @param rs
* the JDBC result set that contains the row being extracted
*
* @return the new {@link PlanetResourceRecord} instance with its common fields set
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
private PlanetResourceRecord getResourceFields( ResultSet rs )
throws SQLException
{
PlanetResourceRecord resource = new PlanetResourceRecord( );
this.getResourceDescription( resource , rs );
resource.setIncome( rs.getLong( "pres_income" ) );
resource.setUpkeep( rs.getLong( "pres_upkeep" ) );
resource.setInvested( rs.getLong( "pres_invested" ) );
return resource;
}
/**
* Map resource provider fields if they are present.
*
* <p>
* Check if the record includes resource provider information. If it does, extract the fields'
* values into a {@link ResourceProviderRecord} instance and add it to the
* {@link PlanetResourceRecord}.
*
* @param rs
* the JDBC result set that contains the row being extracted
* @param resource
* the {@link PlanetResourceRecord} instance to add information to
*
* @throws SQLException
* if a SQLException is encountered getting column values
*/
private void getResourceProvider( ResultSet rs , PlanetResourceRecord resource )
throws SQLException
{
long capacity = rs.getLong( "resprov_capacity" );
if ( rs.wasNull( ) ) {
return;
}
ResourceProviderRecord provider = new ResourceProviderRecord( );
provider.setCapacity( capacity );
provider.setQuantity( rs.getLong( "resprov_quantity" ) );
provider.setDifficulty( rs.getInt( "resprov_difficulty" ) );
provider.setPriority( rs.getInt( "mset_weight" ) );
resource.setResourceProvider( provider );
}
}

View file

@ -0,0 +1,99 @@
package com.deepclone.lw.beans.game.resources;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
import com.deepclone.lw.interfaces.game.resources.ResourcesInformationDAO;
/**
* Resource information access component
*
* <p>
* This component's goal is to read information about resources from the database and return the
* records in some usable format.
*
* <p>
* It does not contain any method that actually change the database.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
class ResourcesInformationDAOBean
implements ResourcesInformationDAO
{
/** SQL query that fetches a planet's resources information */
private static final String Q_PLANET_RESOURCES = "SELECT * FROM emp.get_planet_resources( ? )";
/** SQL query that fetches an empire's resources information */
private static final String Q_EMPIRE_RESOURCES = "SELECT * FROM emp.resources_view WHERE empire_id = ?";
/** Row mapper for planet resources */
private final PlanetResourceMapper mPlanetResource;
/** Row mapper for empire resources */
private final EmpireResourceMapper mEmpireResource;
/** Spring JDBC interface */
private JdbcTemplate dTemplate;
/** Initialise the necessary row mappers */
public ResourcesInformationDAOBean( )
{
this.mPlanetResource = new PlanetResourceMapper( );
this.mEmpireResource = new EmpireResourceMapper( );
}
/**
* Dependency injector that sets the data source
*
* @param dataSource
* the data source
*/
@Autowired( required = true )
public void setDataSource( DataSource dataSource )
{
this.dTemplate = new JdbcTemplate( dataSource );
}
/**
* Run the planet resources information query and extract the data
*
* <p>
* This implementation simply executes a query using the <code>emp.get_planet_resources()</code>
* stored procedure and maps the resulting rows into a list of {@link PlanetResourceRecord}
* instances.
*/
@Override
public List< PlanetResourceRecord > getPlanetInformation( int planet )
{
return this.dTemplate.query( Q_PLANET_RESOURCES , this.mPlanetResource , planet );
}
/**
* Run the empire resources information query and extract the data
*
* <p>
* This implementation executes a query on <code>emp.resources_view</code> for a specific
* empire, and maps the resulting rows into a list of {@link EmpireResourceRecord} instances.
*/
@Override
public List< EmpireResourceRecord > getEmpireInformation( int empire )
{
return this.dTemplate.query( Q_EMPIRE_RESOURCES , this.mEmpireResource , empire );
}
}

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="resourcesInformationDAO" class="com.deepclone.lw.beans.game.resources.ResourcesInformationDAOBean" />
</beans>

View file

@ -25,6 +25,7 @@ import com.deepclone.lw.interfaces.game.BattlesCache;
import com.deepclone.lw.interfaces.game.BattlesDAO; import com.deepclone.lw.interfaces.game.BattlesDAO;
import com.deepclone.lw.interfaces.game.EmpireDAO; import com.deepclone.lw.interfaces.game.EmpireDAO;
import com.deepclone.lw.interfaces.game.EmpireManagement; import com.deepclone.lw.interfaces.game.EmpireManagement;
import com.deepclone.lw.interfaces.game.resources.ResourcesInformationDAO;
import com.deepclone.lw.interfaces.naming.NamingDAO; import com.deepclone.lw.interfaces.naming.NamingDAO;
import com.deepclone.lw.interfaces.prefs.AccountPreferences; import com.deepclone.lw.interfaces.prefs.AccountPreferences;
import com.deepclone.lw.interfaces.prefs.PreferencesDAO; import com.deepclone.lw.interfaces.prefs.PreferencesDAO;
@ -46,6 +47,7 @@ public class EmpireManagementBean
private EmpireDAO empireDao; private EmpireDAO empireDao;
private PreferencesDAO prefsDao; private PreferencesDAO prefsDao;
private BattlesDAO battlesDao; private BattlesDAO battlesDao;
private ResourcesInformationDAO resourcesInformationDao;
@Autowired( required = true ) @Autowired( required = true )
@ -83,6 +85,13 @@ public class EmpireManagementBean
} }
@Autowired( required = true )
public void setResourcesInformationDao( ResourcesInformationDAO resourcesInformationDao )
{
this.resourcesInformationDao = resourcesInformationDao;
}
@Override @Override
public Integer getEmpireId( EmailAddress address ) public Integer getEmpireId( EmailAddress address )
{ {
@ -103,8 +112,9 @@ public class EmpireManagementBean
AccountPreferences prefs = this.prefsDao.getPreferences( generalInformation.getAccountId( ) ); AccountPreferences prefs = this.prefsDao.getPreferences( generalInformation.getAccountId( ) );
boolean rlTime = prefs.getPreference( "useRLTime" , Boolean.class ); boolean rlTime = prefs.getPreference( "useRLTime" , Boolean.class );
return new GamePageData( generalInformation.getName( ) , generalInformation.getStatus( ) , generalInformation return new GamePageData( generalInformation.getName( ) , generalInformation.getStatus( ) ,
.getTag( ) , generalInformation.getCash( ) , generalInformation.getNextTick( ) , planets , rlTime ); generalInformation.getTag( ) , generalInformation.getCash( ) , generalInformation.getNextTick( ) ,
planets , rlTime );
} }
@ -150,6 +160,8 @@ public class EmpireManagementBean
battles.add( entry ); battles.add( entry );
} }
overview.setEconomy( this.resourcesInformationDao.getEmpireInformation( empireId ) );
return new EmpireResponse( this.getGeneralInformation( empireId ) , overview , research , battles ); return new EmpireResponse( this.getGeneralInformation( empireId ) , overview , research , battles );
} }

View file

@ -19,6 +19,7 @@ import com.deepclone.lw.cmd.player.planets.ViewPlanetResponse;
import com.deepclone.lw.interfaces.game.EmpireManagement; import com.deepclone.lw.interfaces.game.EmpireManagement;
import com.deepclone.lw.interfaces.game.PlanetDAO; import com.deepclone.lw.interfaces.game.PlanetDAO;
import com.deepclone.lw.interfaces.game.PlanetsManagement; import com.deepclone.lw.interfaces.game.PlanetsManagement;
import com.deepclone.lw.interfaces.game.resources.ResourcesInformationDAO;
import com.deepclone.lw.interfaces.naming.NamingDAO; import com.deepclone.lw.interfaces.naming.NamingDAO;
import com.deepclone.lw.sqld.game.PlanetData; import com.deepclone.lw.sqld.game.PlanetData;
import com.deepclone.lw.sqld.game.PlanetData.AccessType; import com.deepclone.lw.sqld.game.PlanetData.AccessType;
@ -36,6 +37,7 @@ public class PlanetsManagementBean
private EmpireManagement empireManagement; private EmpireManagement empireManagement;
private PlanetDAO planetDao; private PlanetDAO planetDao;
private NamingDAO namingDao; private NamingDAO namingDao;
private ResourcesInformationDAO resourcesInformationDao;
@Autowired( required = true ) @Autowired( required = true )
@ -59,6 +61,13 @@ public class PlanetsManagementBean
} }
@Autowired( required = true )
public void setResourcesInformationDao( ResourcesInformationDAO resourcesInformationDao )
{
this.resourcesInformationDao = resourcesInformationDao;
}
private PlanetOrbitalView getOrbitalView( int empireId , int planetId , AccessType access ) private PlanetOrbitalView getOrbitalView( int empireId , int planetId , AccessType access )
{ {
if ( access == AccessType.BASIC ) { if ( access == AccessType.BASIC ) {
@ -107,6 +116,8 @@ public class PlanetsManagementBean
view.setbBuildings( this.planetDao.getAvailableBuildings( planetId ) ); view.setbBuildings( this.planetDao.getAvailableBuildings( planetId ) );
view.setbShips( this.planetDao.getAvailableShips( planetId ) ); view.setbShips( this.planetDao.getAvailableShips( planetId ) );
view.setResources( this.resourcesInformationDao.getPlanetInformation( planetId ) );
return view; return view;
} }
@ -199,8 +210,8 @@ public class PlanetsManagementBean
if ( one == null ) { if ( one == null ) {
return new ViewPlanetResponse( planetId , page , this.getBasicView( basic ) , orbital , owner ); return new ViewPlanetResponse( planetId , page , this.getBasicView( basic ) , orbital , owner );
} }
return new RenamePlanetResponse( planetId , page , this.getBasicView( basic ) , orbital , owner , name , one return new RenamePlanetResponse( planetId , page , this.getBasicView( basic ) , orbital , owner , name ,
.toString( ) ); one.toString( ) );
} }

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<import resource="game/resources-beans.xml" />
</beans>

View file

@ -505,3 +505,59 @@ GRANT EXECUTE
DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
DOUBLE PRECISION ) DOUBLE PRECISION )
TO :dbuser; TO :dbuser;
/*
* View of resource category weights
*
* This view computes the average resource weight per category for all
* resource definitions.
*
* Fields:
* resource_category_id The category's identifier
* resource_category_weight The average weight of resource defintions
* in the category.
*/
DROP VIEW IF EXISTS defs.resource_category_weight_view CASCADE;
CREATE VIEW defs.resource_category_weight_view
AS SELECT resource_category_id ,
AVG( resource_weight ) AS resource_category_weight
FROM defs.resources
WHERE resource_category_id IS NOT NULL
GROUP BY resource_category_id;
/*
* Ordered resource definitions
*
* This view contains the name, category and description identifier for all
* resource definitions, ordered based on the category's average weight and
* the resource's own weight.
*
* Fields:
* resource_name_id The identifier of the resource's name
* resource_category_id The identifier of the category's name, or NULL
* if the resource is not in a category
* resource_description_id The identifier of the resource's description
* resource_ordering The index of the resource in a sorted view
*/
DROP VIEW IF EXISTS defs.ordered_resources_view CASCADE;
CREATE VIEW defs.ordered_resources_view
AS SELECT resource_name_id , resource_category_id , resource_description_id ,
row_number( ) OVER(
ORDER BY (
CASE
WHEN resource_category_id IS NULL THEN
resource_weight
ELSE
resource_category_weight
END ) , resource_weight
) AS resource_ordering
FROM defs.resources
LEFT OUTER JOIN defs.resource_category_weight_view
USING ( resource_category_id )
;

View file

@ -669,3 +669,111 @@ CREATE VIEW emp.enemy_lists
) AS x; ) AS x;
GRANT SELECT ON emp.enemy_lists TO :dbuser; GRANT SELECT ON emp.enemy_lists TO :dbuser;
/*
* Planets income and upkeep totals
*
* This view computes the totals of planets' incomes and upkeeps for each
* empire and resource type.
*
* FIXME: time-related factor is hardcoded
*
* Fields:
* empire_id The empire's identifier
* resource_name_id The identifier of the resource type
* planets_income The planets' income over 12h RT / 1 month GT,
* rounded down
* planets_upkeep The planets' upkeep over 12h RT / 1 month GT,
* rounded up
*/
DROP VIEW IF EXISTS emp.planet_resources_view CASCADE;
CREATE VIEW emp.planet_resources_view
AS SELECT
empire_id , resource_name_id ,
FLOOR( SUM( pres_income ) * 720.0 )::BIGINT AS planets_income ,
CEIL( SUM( pres_upkeep ) * 720.0 )::BIGINT AS planets_upkeep
FROM emp.planets
LEFT OUTER JOIN verse.planet_resources
USING ( planet_id )
GROUP BY empire_id , resource_name_id;
/*
* Empire resources view
*
* This view contains all resource-related information for each empire and
* resource type.
*
* FIXME: fleets upkeep is set to 0 at the moment.
*
* Fields:
* empire_id The empire's identifier
* resource_identifier The text identifier of the resource
* resource_name The internationalised name of the resource
* resource_description The internationalised description of the
* resource
* resource_category The internationalised category of the resource,
* or NULL if the resource is not in a
* category.
* empres_possessed The empire's stockpile of this type of
* resource, rounded down
* empmset_weight The empire-wide mining setting for the
* resource type, or NULL if this is a basic
* resource
* planets_income The planets' total income
* planets_upkeep The planets' total upkeep
* fleets_upkeep The fleets' total upkeep
*/
DROP VIEW IF EXISTS emp.resources_view CASCADE;
CREATE VIEW emp.resources_view
AS SELECT
empire_id ,
_r_name_str.name AS resource_identifier ,
_r_name.translated_string AS resource_name ,
_r_desc.translated_string AS resource_description ,
_r_cat.translated_string AS resource_category ,
FLOOR( empres_possessed )::BIGINT AS empres_possessed ,
empmset_weight ,
( CASE
WHEN planets_income IS NULL THEN
0::BIGINT
ELSE
planets_income
END ) AS planets_income ,
( CASE
WHEN planets_upkeep IS NULL THEN
0::BIGINT
ELSE
planets_upkeep
END ) AS planets_upkeep ,
0::BIGINT AS fleets_upkeep
FROM defs.ordered_resources_view
INNER JOIN emp.resources
USING ( resource_name_id )
INNER JOIN naming.empire_names _name
ON _name.id = empire_id
INNER JOIN users.credentials _creds
ON _creds.address_id = _name.owner_id
INNER JOIN defs.strings _r_name_str
ON _r_name_str.id = resource_name_id
INNER JOIN defs.translations _r_name
ON _r_name.string_id = resource_name_id
AND _r_name.lang_id = _creds.language_id
INNER JOIN defs.translations _r_desc
ON _r_desc.string_id = resource_description_id
AND _r_desc.lang_id = _creds.language_id
LEFT OUTER JOIN defs.translations _r_cat
ON _r_cat.string_id = resource_category_id
AND _r_cat.lang_id = _creds.language_id
LEFT OUTER JOIN emp.mining_settings
USING ( empire_id , resource_name_id )
LEFT OUTER JOIN emp.planet_resources_view
USING ( empire_id , resource_name_id )
ORDER BY resource_ordering;
GRANT SELECT
ON emp.resources_view
TO :dbuser;

View file

@ -139,3 +139,139 @@ REVOKE EXECUTE
DOUBLE PRECISION , DOUBLE PRECISION ) DOUBLE PRECISION , DOUBLE PRECISION )
FROM PUBLIC; FROM PUBLIC;
/*
* Planet resources type
*
* This type is used to transmit a planet's resources information to the game
* server. It contains the resource's description, the planet's economic data
* and, if there is a resource provider on the planet, the provider's
* information and mining priority.
*/
DROP TYPE IF EXISTS emp.planet_resources_type CASCADE;
CREATE TYPE emp.planet_resources_type AS (
/* Text identifier of the resource */
resource_identifier TEXT ,
/* Internationalised name of the resource */
resource_name TEXT ,
/* Internationalised description of the resource */
resource_description TEXT ,
/* Internationalised name of the category the resource is a part of, or
* NULL if the resource is not in any category.
*/
resource_category TEXT ,
/* The planet's income for this resource, over a period of 12h RT/ 1 month
* GT.
*/
pres_income BIGINT ,
/* The planet's upkeep for this resource, over a period of 12h RT/ 1 month
* GT.
*/
pres_upkeep BIGINT ,
/* The current quantity of this resource invested in the planet's build
* queues.
*/
pres_invested BIGINT ,
/** The capacity of the resource provider, if there is one, or NULL if
* there is no provider.
*/
resprov_capacity BIGINT ,
/** The quantity of resources in the resource provider, if there is one,
* or NULL if there is no provider.
*/
resprov_quantity BIGINT ,
/** The extraction difficulty of the resource provider as a percentage, or
* NULL if there is no provider.
*/
resprov_difficulty INT ,
/* The mining priority for the resource in question, or NULL if there is no
* resource provider.
*/
mset_weight INT
);
/*
* Access all available information about a planet's resources
*
* This function retrieves resource information about an empire-owned planet,
* and converts it to the format used in the game server (rounded quantities,
* difficulty as percentage, internationalised strings).
*
* FIXME:
* 1) pres_invested is always set to 0 in the output
* 2) time-related computations use hardcoded values
*
* Parameters:
* _planet The planet's identifier
*
* Returns:
* N/A Resource information records, ordered using resource
* weights.
*/
DROP FUNCTION IF EXISTS emp.get_planet_resources( INT );
CREATE FUNCTION emp.get_planet_resources( _planet INT )
RETURNS SETOF emp.planet_resources_type
STRICT STABLE
SECURITY DEFINER
AS $get_planet_resources$
SELECT _name_str.name AS resource_identifier ,
_name_trans.translated_string AS resource_name ,
_desc_trans.translated_string AS resource_description ,
_cat_trans.translated_string AS resource_category ,
FLOOR( pres_income * 720.0 )::BIGINT AS pres_income ,
CEIL( pres_upkeep * 720.0 )::BIGINT AS pres_upkeep ,
0::BIGINT AS pres_invested ,
ROUND( resprov_quantity_max )::BIGINT AS resprov_capacity ,
ROUND( resprov_quantity )::BIGINT AS resprov_quantity ,
ROUND( 100.0 * resprov_difficulty )::INT AS resprov_difficulty ,
mset_weight
FROM defs.ordered_resources_view
INNER JOIN verse.planet_resources USING ( resource_name_id )
INNER JOIN emp.planets USING ( planet_id )
INNER JOIN naming.empire_names _emp_name
ON _emp_name.id = empire_id
INNER JOIN users.credentials _user
ON _emp_name.owner_id = _user.address_id
INNER JOIN defs.strings _name_str
ON _name_str.id = resource_name_id
INNER JOIN defs.translations _name_trans
ON _name_trans.string_id = resource_name_id
AND _name_trans.lang_id = _user.language_id
INNER JOIN defs.translations _desc_trans
ON _desc_trans.string_id = resource_description_id
AND _desc_trans.lang_id = _user.language_id
LEFT OUTER JOIN defs.translations _cat_trans
ON _cat_trans.string_id = resource_category_id
AND _cat_trans.lang_id = _user.language_id
LEFT OUTER JOIN verse.resource_providers
USING ( planet_id , resource_name_id )
LEFT OUTER JOIN emp.mining_settings_view
USING ( planet_id , resource_name_id )
WHERE planet_id = $1
ORDER BY resource_ordering;
$get_planet_resources$ LANGUAGE SQL;
REVOKE EXECUTE
ON FUNCTION emp.get_planet_resources( INT )
FROM PUBLIC;
GRANT EXECUTE
ON FUNCTION emp.get_planet_resources( INT )
TO :dbuser;

View file

@ -0,0 +1,47 @@
/*
* Tests for defs.resource_category_weight_view
*/
BEGIN;
/*
* We need a few resources, with a known average per category. Some of the
* resources must not belong to any category.
*/
\i utils/strings.sql
SELECT _create_test_strings( 5 , 'resource' );
SELECT _create_test_strings( 5 , 'resDesc' );
SELECT _create_test_strings( 2 , 'resCat' );
INSERT INTO defs.resources(
resource_name_id , resource_description_id ,
resource_category_id , resource_weight
) VALUES (
_get_string( 'resource1' ) , _get_string( 'resDesc1' ) ,
_get_string( 'resCat1' ) , 2
) , (
_get_string( 'resource2' ) , _get_string( 'resDesc2' ) ,
_get_string( 'resCat1' ) , 4
) , (
_get_string( 'resource3' ) , _get_string( 'resDesc3' ) ,
_get_string( 'resCat2' ) , 3
) , (
_get_string( 'resource4' ) , _get_string( 'resDesc4' ) ,
_get_string( 'resCat2' ) , 5
) , (
_get_string( 'resource5' ) , _get_string( 'resDesc5' ) ,
NULL , 150
);
SELECT plan( 1 );
SELECT diag_test_name( 'defs.resource_category_weight_view - Resulting set contains correct values' );
SELECT set_eq(
$$ SELECT * FROM defs.resource_category_weight_view $$ ,
$$ VALUES (
_get_string( 'resCat1' ) , 3
) , (
_get_string( 'resCat2' ) , 4
) $$
);
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,57 @@
/*
* Tests for defs.ordered_resources_view
*/
BEGIN;
/*
* We need:
* - one resource without category with weight 1,
* - one resource with category 1 and weight 2,
* - one resource with weight 4 and no category,
* - two resourcew with weights 3 and 7 and category 2.
*/
\i utils/strings.sql
SELECT _create_test_strings( 5 , 'resource' );
SELECT _create_test_strings( 5 , 'resDesc' );
SELECT _create_test_strings( 2 , 'resCat' );
INSERT INTO defs.resources(
resource_name_id , resource_description_id ,
resource_category_id , resource_weight
) VALUES (
_get_string( 'resource1' ) , _get_string( 'resDesc1' ) ,
NULL , 1
) , (
_get_string( 'resource2' ) , _get_string( 'resDesc2' ) ,
_get_string( 'resCat1' ) , 2
) , (
_get_string( 'resource3' ) , _get_string( 'resDesc3' ) ,
NULL , 4
) , (
_get_string( 'resource4' ) , _get_string( 'resDesc4' ) ,
_get_string( 'resCat2' ) , 3
) , (
_get_string( 'resource5' ) , _get_string( 'resDesc5' ) ,
_get_string( 'resCat2' ) , 7
);
SELECT plan( 1 );
SELECT diag_test_name( 'defs.ordered_resources_view - Resources are in the correct order' );
SELECT set_eq(
$$ SELECT resource_name_id , resource_ordering
FROM defs.ordered_resources_view $$ ,
$$ VALUES (
_get_string( 'resource1' ) , 1
) , (
_get_string( 'resource2' ) , 2
) , (
_get_string( 'resource3' ) , 3
) , (
_get_string( 'resource4' ) , 4
) , (
_get_string( 'resource5' ) , 5
) $$
);
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,56 @@
/*
* Tests for emp.planet_resources_view
*/
BEGIN;
/*
* Create two empires, one with 2 planets, the other without. Add 2 planet
* resources records.
*
* Disable all foreign keys to avoid a lot of work.
*/
ALTER TABLE emp.planets
DROP CONSTRAINT fk_eplanets_empire ,
DROP CONSTRAINT fk_eplanets_planet;
ALTER TABLE verse.planet_resources
DROP CONSTRAINT fk_pres_planet ,
DROP CONSTRAINT fk_pres_resource;
INSERT INTO verse.planet_resources (
planet_id , resource_name_id , pres_income , pres_upkeep
) VALUES
( 1 , 1 , 1 , 2 ) , ( 1 , 2 , 3 , 4 ) ,
( 2 , 1 , 3 , 4 ) , ( 2 , 2 , 5 , 6 ) ,
( 3 , 1 , 0.1 / 720 , 0.4 / 720 ) ,
( 3 , 2 , 0.9 / 720, 0.9 / 720 );
INSERT INTO emp.planets( empire_id , planet_id )
VALUES ( 1 , 1 ) , ( 1 , 2 ) , ( 2 , 3 );
/***** TESTS BEGIN HERE *****/
SELECT plan( 3 );
SELECT diag_test_name( 'emp.planet_resources_view - Sums' );
SELECT set_eq(
$$ SELECT * FROM emp.planet_resources_view WHERE empire_id = 1 $$ ,
$$ VALUES ( 1 , 1 , 4 * 720 , 6 * 720 ) , ( 1 , 2 , 8 * 720 , 10 * 720 ) $$
);
SELECT diag_test_name( 'emp.planet_resources_view - Incomes are rounded down' );
SELECT set_eq(
$$ SELECT resource_name_id , planets_income
FROM emp.planet_resources_view
WHERE empire_id = 2 $$ ,
$$ VALUES ( 1 , 0 ) , ( 2 , 0 ) $$
);
SELECT diag_test_name( 'emp.planet_resources_view - Upkeeps are rounded up' );
SELECT set_eq(
$$ SELECT resource_name_id , planets_upkeep
FROM emp.planet_resources_view
WHERE empire_id = 2 $$ ,
$$ VALUES ( 1 , 1 ) , ( 2 , 1 ) $$
);
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,169 @@
/*
* Tests for emp.resources_view
*/
BEGIN;
/*
* We will use a fake emp.planet_resources_view to avoid having to set
* planet resources.
*
* In terms of data, we need two resources (one with a category, the other
* without, and two empires (one with "planet resources", the other
* without). Both empires will have mining settings for one of the resource
* types.
*/
\i utils/strings.sql
SELECT _create_test_strings( 2 , 'resource' , 'Resource name ' );
SELECT _create_test_strings( 2 , 'rDesc' , 'Resource description ' );
SELECT _create_test_strings( 1 , 'rCat' , 'Resource category ' );
INSERT INTO defs.resources (
resource_name_id , resource_description_id ,
resource_category_id , resource_weight
) VALUES (
_get_string( 'resource1' ) , _get_string( 'rDesc1' ) ,
_get_string( 'rCat1' ) , 2
) , (
_get_string( 'resource2' ) , _get_string( 'rDesc2' ) ,
NULL , 1
);
\i utils/accounts.sql
\i utils/naming.sql
SELECT _create_emp_names( 2 , 'emp' );
INSERT INTO emp.empires( name_id , cash )
SELECT id , 0 FROM naming.empire_names;
ALTER TABLE emp.mining_settings DROP CONSTRAINT fk_empmset_resource;
INSERT INTO emp.mining_settings ( empire_id , resource_name_id , empmset_weight )
SELECT id , _get_string( 'resource1' ) , row_number( ) OVER ()
FROM naming.empire_names
ORDER BY id;
INSERT INTO emp.resources ( empire_id , resource_name_id , empres_possessed )
SELECT name_id , resource_name_id , 0.4 * row_number( ) OVER ()
FROM emp.empires
CROSS JOIN defs.resources
ORDER BY name_id , resource_name_id;
CREATE TABLE fake_planet_resources_view (
empire_id INT ,
resource_name_id INT ,
planets_income BIGINT ,
planets_upkeep BIGINT
);
CREATE OR REPLACE VIEW emp.planet_resources_view
AS SELECT * FROM fake_planet_resources_view;
INSERT INTO fake_planet_resources_view
VALUES (
_get_emp_name( 'emp1' ) , _get_string( 'resource1' ) , 1 , 2
) , (
_get_emp_name( 'emp1' ) , _get_string( 'resource2' ) , 3 , 4
);
/***** TESTS BEGIN HERE *****/
SELECT plan( 13 );
SELECT diag_test_name( 'emp.resources_view - One row per empire/resource combination' );
SELECT is( COUNT(*)::INT , 4 ) FROM emp.resources_view;
SELECT diag_test_name( 'emp.resources_view - Resource ordering' );
SELECT set_eq(
$$ SELECT resource_identifier , row_number( ) OVER ( )
FROM emp.resources_view
WHERE empire_id = _get_emp_name( 'emp1' ) $$ ,
$$ VALUES ( 'resource2' , 1 ) , ( 'resource1' , 2 ) $$
);
SELECT diag_test_name( 'emp.resources_view - Name translation' );
SELECT is_empty( $$
SELECT *
FROM emp.resources_view
WHERE resource_name NOT LIKE 'Resource name %'
$$ );
SELECT diag_test_name( 'emp.resources_view - Description translation' );
SELECT is_empty( $$
SELECT *
FROM emp.resources_view
WHERE resource_description NOT LIKE 'Resource description %'
$$ );
SELECT diag_test_name( 'emp.resources_view - Category translation' );
SELECT is_empty( $$
SELECT *
FROM emp.resources_view
WHERE resource_identifier = 'resource1'
AND resource_category NOT LIKE 'Resource category %'
$$ );
SELECT diag_test_name( 'emp.resources_view - NULL category -> NULL translation' );
SELECT is_empty( $$
SELECT *
FROM emp.resources_view
WHERE resource_identifier <> 'resource1'
AND resource_category IS NOT NULL
$$ );
SELECT diag_test_name( 'emp.resources_view - Possessed quantities are rounded down' );
SELECT set_eq(
$$ SELECT empire_id , resource_identifier , empres_possessed
FROM emp.resources_view $$ ,
$$ VALUES (
_get_emp_name( 'emp1' ) , 'resource1' , 0
) , (
_get_emp_name( 'emp1' ) , 'resource2' , 0
) , (
_get_emp_name( 'emp2' ) , 'resource1' , 1
) , (
_get_emp_name( 'emp2' ) , 'resource2' , 1
) $$
);
SELECT diag_test_name( 'emp.resources_view - Basic resources have NULL mining settings' );
SELECT is( COUNT(*)::INT , 2 )
FROM emp.resources_view
WHERE resource_identifier = 'resource2'
AND empmset_weight IS NULL;
SELECT diag_test_name( 'emp.resources_view - Mining settings for natural resources' );
SELECT set_eq(
$$ SELECT empire_id , empmset_weight
FROM emp.resources_view
WHERE resource_identifier = 'resource1' $$ ,
$$ VALUES ( _get_emp_name( 'emp1' ) , 1 ) ,
( _get_emp_name( 'emp2' ) , 2 ) $$
);
SELECT is( COUNT(*)::INT , 2 )
FROM emp.resources_view
WHERE resource_identifier = 'resource1'
AND empmset_weight IS NOT NULL;
SELECT diag_test_name( 'emp.resources_view - Planet upkeep/income is zero when there are no planets' );
SELECT is( COUNT(*)::INT , 2 )
FROM emp.resources_view
WHERE empire_id = _get_emp_name( 'emp2' )
AND planets_upkeep = 0
AND planets_income = 0;
SELECT diag_test_name( 'emp.resources_view - Planet upkeep/income from planet resources view' );
SELECT set_eq(
$$ SELECT resource_identifier , planets_upkeep , planets_income
FROM emp.resources_view
WHERE empire_id = _get_emp_name( 'emp1' ) $$ ,
$$ VALUES ( 'resource1' , 2 , 1 ) , ( 'resource2' , 4 , 3 ) $$
);
SELECT diag_test_name( 'emp.resources_view - FIXME - Fleets upkeep set to zero' );
SELECT is_empty(
$$ SELECT * FROM emp.resources_view
WHERE fleets_upkeep <> 0 $$
);
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,187 @@
/*
* Tests for the emp.get_planet_resources() function
*/
BEGIN;
/*
* We need two planets, one being owned by some empire, the other being
* neutral. Both planets' resource records must exist. Both planets will
* also include resource providers which will serve as tests for the
* various rounding which takes place.
*
* To avoid having to define actual natural resources, we disable the
* foreign keys on resource providers and mining settings. We can't do
* that for the empire, tho: we need an actual account as the translations
* must be looked up.
*/
\i utils/strings.sql
SELECT _create_test_strings( 3 , 'resource' , 'Resource name ' );
SELECT _create_test_strings( 3 , 'rDesc' , 'Resource description ' );
SELECT _create_test_strings( 1 , 'rCat' , 'Resource category ' );
INSERT INTO defs.resources (
resource_name_id , resource_description_id ,
resource_category_id , resource_weight
) VALUES (
_get_string( 'resource1' ) , _get_string( 'rDesc1' ) ,
_get_string( 'rCat1' ) , 2
) , (
_get_string( 'resource2' ) , _get_string( 'rDesc2' ) ,
NULL , 1
) , (
_get_string( 'resource3' ) , _get_string( 'rDesc3' ) ,
NULL , 3
);
\i utils/accounts.sql
\i utils/naming.sql
SELECT _create_emp_names( 1 , 'emp' );
INSERT INTO emp.empires( name_id , cash )
VALUES( _get_emp_name( 'emp1' ) , 0 );
ALTER TABLE emp.mining_settings DROP CONSTRAINT fk_empmset_resource;
INSERT INTO emp.mining_settings ( empire_id , resource_name_id )
SELECT _get_emp_name( 'emp1' ) , resource_name_id
FROM defs.resources;
\i utils/universe.sql
SELECT _create_raw_planets( 2 , 'planet' );
INSERT INTO verse.planet_resources (
planet_id , resource_name_id , pres_income , pres_upkeep
) VALUES (
_get_map_name( 'planet1' ) , _get_string( 'resource1' ) ,
99.4 / 720.0 , 99.4 / 720.0
) , (
_get_map_name( 'planet1' ) , _get_string( 'resource2' ) ,
99.5 / 720.0 , 99.5 / 720.0
) , (
_get_map_name( 'planet1' ) , _get_string( 'resource3' ) ,
99.6 / 720.0 , 99.6 / 720.0
);
INSERT INTO verse.planet_resources ( planet_id , resource_name_id )
SELECT _get_map_name( 'planet2' ) , resource_name_id
FROM defs.resources;
ALTER TABLE verse.resource_providers DROP CONSTRAINT fk_resprov_resource;
INSERT INTO verse.resource_providers(
planet_id , resource_name_id , resprov_quantity_max ,
resprov_quantity , resprov_difficulty , resprov_recovery
) VALUES (
_get_map_name( 'planet1' ) , _get_string( 'resource1' ) , 99.4 ,
99.4 , 0.494 , 0.5
) , (
_get_map_name( 'planet1' ) , _get_string( 'resource2' ) , 99.5 ,
99.5 , 0.495 , 0.5
) , (
_get_map_name( 'planet2' ) , _get_string( 'resource1' ) , 100 ,
100 , 0.5 , 0.5
);
INSERT INTO emp.planets ( empire_id , planet_id )
VALUES ( _get_emp_name( 'emp1' ) , _get_map_name( 'planet1' ) );
/***** TESTS BEGIN HERE *****/
SELECT plan( 13 );
SELECT diag_test_name( 'emp.get_planet_resources() - No results on missing planets' );
SELECT is_empty( $$ SELECT * FROM emp.get_planet_resources( _get_bad_map_name( ) ) $$ );
SELECT diag_test_name( 'emp.get_planet_resources() - No results on neutral planets' );
SELECT is_empty( $$ SELECT * FROM emp.get_planet_resources( _get_map_name( 'planet2' ) ) $$ );
SELECT diag_test_name( 'emp.get_planet_resources() - One row per resource type' );
SELECT is( COUNT(*)::INT , 3 ) FROM emp.get_planet_resources( _get_map_name( 'planet1' ) );
SELECT diag_test_name( 'emp.get_planet_resources() - Row ordering' );
SELECT set_eq(
$$ SELECT resource_identifier , row_number() OVER ( )
FROM emp.get_planet_resources( _get_map_name( 'planet1' ) ) $$ ,
$$ VALUES (
'resource1' , 2
) , (
'resource2' , 1
) , (
'resource3' , 3
) $$
);
SELECT diag_test_name( 'emp.get_planet_resources() - Name translation' );
SELECT is_empty( $$
SELECT *
FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE resource_name NOT LIKE 'Resource name %'
$$ );
SELECT diag_test_name( 'emp.get_planet_resources() - Description translation' );
SELECT is_empty( $$
SELECT *
FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE resource_description NOT LIKE 'Resource description %'
$$ );
SELECT diag_test_name( 'emp.get_planet_resources() - Category translation' );
SELECT is_empty( $$
SELECT *
FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE resource_identifier = 'resource1'
AND resource_category NOT LIKE 'Resource category %'
$$ );
SELECT diag_test_name( 'emp.get_planet_resources() - NULL category -> NULL translation' );
SELECT is_empty( $$
SELECT *
FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE resource_identifier <> 'resource1'
AND resource_category IS NOT NULL
$$ );
SELECT diag_test_name( 'emp.get_planet_resources() - Upkeep is valid and rounded up' );
SELECT is_empty( $$
SELECT *
FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE pres_upkeep IS NULL OR pres_upkeep <> 100
$$ );
SELECT diag_test_name( 'emp.get_planet_resources() - Income is valid and rounded down' );
SELECT is_empty( $$
SELECT * FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE pres_income IS NULL OR pres_income <> 99
$$ );
SELECT diag_test_name( 'emp.get_planet_resources() - No mining-related fields when there is no resource provider' );
SELECT is_empty( $$
SELECT * FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE resource_identifier = 'resource3' AND NOT (
resprov_capacity IS NULL
AND resprov_quantity IS NULL
AND resprov_difficulty IS NULL
AND mset_weight IS NULL
);
$$ );
SELECT diag_test_name( 'emp.get_planet_resources() - Resource provider fields are present' );
SELECT is_empty( $$
SELECT * FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE resource_identifier <> 'resource3' AND (
resprov_capacity IS NULL
OR resprov_quantity IS NULL
OR resprov_difficulty IS NULL
OR mset_weight IS NULL
);
$$ );
SELECT diag_test_name( 'emp.get_planet_resources() - Resource provider values' );
SELECT set_eq( $$
SELECT resource_identifier , resprov_capacity , resprov_quantity , resprov_difficulty
FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
WHERE resource_identifier <> 'resource3'
$$ , $$ VALUES (
'resource1' , 99 , 99 , 49
) , (
'resource2' , 100 , 100 , 50
) $$ );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,11 @@
/*
* Test privileges on defs.resource_category_weight_view
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'defs.resource_category_weight_view - Privileges' );
SELECT throws_ok( 'SELECT * FROM defs.resource_category_weight_view' , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,11 @@
/*
* Test privileges on defs.ordered_resources_view
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'defs.ordered_resources_view - Privileges' );
SELECT throws_ok( 'SELECT * FROM defs.ordered_resources_view' , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,11 @@
/*
* Test privileges on emp.planet_resources_view
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'emp.planet_resources_view - Privileges' );
SELECT throws_ok( 'SELECT * FROM emp.planet_resources_view' , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,11 @@
/*
* Test privileges on emp.resources_view
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'emp.resources_view - Privileges' );
SELECT lives_ok( 'SELECT * FROM emp.resources_view' );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,13 @@
/*
* Test privileges on emp.get_planet_resources()
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'emp.get_planet_resources() - Privileges' );
SELECT lives_ok( $$
SELECT emp.get_planet_resources( 1 )
$$ );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -29,24 +29,11 @@ CREATE FUNCTION _get_string( TEXT ) RETURNS INT AS $$
$$ LANGUAGE SQL; $$ LANGUAGE SQL;
/*
* Function that creates some quantity of test strings
*/
CREATE FUNCTION _create_test_strings( _quantity INT )
RETURNS VOID
AS $$
DECLARE
i INT;
BEGIN
PERFORM _create_test_strings( _quantity , 'test' );
END;
$$ LANGUAGE PLPGSQL;
/* /*
* Function that creates some quantity of test strings using a specific prefix * Function that creates some quantity of test strings using a specific prefix
* and translation prefix.
*/ */
CREATE FUNCTION _create_test_strings( _quantity INT , _prefix TEXT ) CREATE FUNCTION _create_test_strings( _quantity INT , _prefix TEXT , _trans TEXT )
RETURNS VOID RETURNS VOID
AS $$ AS $$
DECLARE DECLARE
@ -59,7 +46,27 @@ BEGIN
LOOP LOOP
i := i + 1; i := i + 1;
PERFORM defs.uoc_translation( 't' , _prefix || i::TEXT , PERFORM defs.uoc_translation( 't' , _prefix || i::TEXT ,
'Test string #' || i::TEXT ); _trans || i::TEXT );
END LOOP; END LOOP;
END; END;
$$ LANGUAGE PLPGSQL; $$ LANGUAGE PLPGSQL;
/*
* Function that creates some quantity of test strings using a specific prefix
*/
CREATE FUNCTION _create_test_strings( _quantity INT , _prefix TEXT )
RETURNS VOID
AS $$
SELECT _create_test_strings( $1 , $2 , 'Test string #' );
$$ LANGUAGE SQL;
/*
* Function that creates some quantity of test strings
*/
CREATE FUNCTION _create_test_strings( _quantity INT )
RETURNS VOID
AS $$
SELECT _create_test_strings( $1 , 'test' );
$$ LANGUAGE SQL;

View file

@ -0,0 +1,43 @@
package com.deepclone.lw.interfaces.game.resources;
import java.util.List;
import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
/**
* Resources information access component interface
*
* <p>
* This interface defines the methods which execute the queries required to extract information
* about resources from the database.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public interface ResourcesInformationDAO
{
/**
* Obtain resources information for a planet
*
* @param planet
* the planet to obtain information about
*
* @return the list of planetary resource records
*/
public List< PlanetResourceRecord > getPlanetInformation( int planet );
/**
* Obtain resources information for an empire
*
* @param empire
* the empire to obtain information about
*
* @return the list of empire economic records
*/
public List< EmpireResourceRecord > getEmpireInformation( int empire );
}

View file

@ -13,14 +13,13 @@
<!-- Load transaction manager --> <!-- Load transaction manager -->
<import resource="configuration/transaction-bean.xml" /> <import resource="configuration/transaction-bean.xml" />
<!-- Load all server beans --> <!-- Load all system and low-level beans -->
<import resource="configuration/accounts-beans.xml" /> <import resource="configuration/accounts-beans.xml" />
<import resource="configuration/bt-beans.xml" /> <import resource="configuration/bt-beans.xml" />
<import resource="configuration/eventlog-beans.xml" /> <import resource="configuration/eventlog-beans.xml" />
<import resource="configuration/i18n-beans.xml" /> <import resource="configuration/i18n-beans.xml" />
<import resource="configuration/mailer-beans.xml" /> <import resource="configuration/mailer-beans.xml" />
<import resource="configuration/naming-beans.xml" /> <import resource="configuration/naming-beans.xml" />
<import resource="configuration/simple-beans.xml" />
<import resource="configuration/system-beans.xml" /> <import resource="configuration/system-beans.xml" />
<import resource="configuration/user-beans.xml" /> <import resource="configuration/user-beans.xml" />
@ -29,5 +28,4 @@
<import resource="configuration/game.xml" /> <import resource="configuration/game.xml" />
<import resource="configuration/simple-beans.xml" /> <import resource="configuration/simple-beans.xml" />
</beans> </beans>

View file

@ -0,0 +1,126 @@
package com.deepclone.lw.beans.game.resources;
import static org.junit.Assert.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
import com.deepclone.lw.testing.MockResultSet;
/**
* Tests of the {@link AbstractResourceMapper} class
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class TestAbstractResourceMapper
{
/** Strings used for the various fields */
private static final String TEST_STRINGS[] = {
"1" , "2" , "3" , "4"
};
/**
* An empty resource record used to test the {@link AbstractResourceMapper}
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
@SuppressWarnings( "serial" )
private static class EmptyResourceRecord
extends AbstractResourceRecord
{
// EMPTY
}
/**
* Resource row mapper that calls
* {@link AbstractResourceMapper#getResourceDescription(AbstractResourceRecord, ResultSet)}
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
private static class EmptyResourceMapper
extends AbstractResourceMapper< EmptyResourceRecord >
{
@Override
public EmptyResourceRecord mapRow( ResultSet rs , int rowNum )
throws SQLException
{
EmptyResourceRecord record = new EmptyResourceRecord( );
this.getResourceDescription( record , rs );
return record;
}
}
/** The result set fed to the resource row mapper */
private ResultSet resultSet;
/** The mapper used in the tests */
private EmptyResourceMapper mapper;
/**
* Create the test mapper and a fake result set with two results: one that includes a category,
* and another without category.
*/
@Before
public void setUp( )
{
this.mapper = new EmptyResourceMapper( );
@SuppressWarnings( "unchecked" )
HashMap< String , Object > rows[] = new HashMap[ 2 ];
for ( int i = 0 ; i < 2 ; i++ ) {
HashMap< String , Object > row = new HashMap< String , Object >( );
row.put( "resource_identifier" , TEST_STRINGS[ 0 ] );
row.put( "resource_name" , TEST_STRINGS[ 1 ] );
row.put( "resource_description" , TEST_STRINGS[ 2 ] );
if ( i == 1 ) {
row.put( "resource_category" , TEST_STRINGS[ 3 ] );
}
rows[ i ] = row;
}
this.resultSet = MockResultSet.create( rows );
}
/** Test mapping a row with a NULL category */
@Test
public void testMapRowWithoutCategory( )
throws SQLException
{
this.resultSet.absolute( 1 );
EmptyResourceRecord record = this.mapper.mapRow( this.resultSet , 1 );
assertEquals( TEST_STRINGS[ 0 ] , record.getIdentifier( ) );
assertEquals( TEST_STRINGS[ 1 ] , record.getTitle( ) );
assertEquals( TEST_STRINGS[ 2 ] , record.getDescription( ) );
assertNull( record.getCategory( ) );
}
/** Test mapping a row with a non-NULL category */
@Test
public void testMapRowWithCategory( )
throws SQLException
{
this.resultSet.absolute( 2 );
EmptyResourceRecord record = this.mapper.mapRow( this.resultSet , 1 );
assertEquals( TEST_STRINGS[ 0 ] , record.getIdentifier( ) );
assertEquals( TEST_STRINGS[ 1 ] , record.getTitle( ) );
assertEquals( TEST_STRINGS[ 2 ] , record.getDescription( ) );
assertEquals( TEST_STRINGS[ 3 ] , record.getCategory( ) );
}
}

View file

@ -0,0 +1,104 @@
package com.deepclone.lw.beans.game.resources;
import static org.junit.Assert.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
import com.deepclone.lw.testing.MockResultSet;
/**
* Tests of the {@link EmpireResourceMapper} class.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class TestEmpireResourceMapper
{
private static final String TEST_STRING = "Test";
private static final long POSSESSED_VALUE = 2L;
private static final long P_INCOME_VALUE = 3L;
private static final long P_UPKEEP_VALUE = 4L;
private static final long F_UPKEEP_VALUE = 5L;
private static final Integer PRIORITY_VALUE = 6;
/** The fake result set fed to the mapper */
private ResultSet resultSet;
/** The mapper being tested */
private EmpireResourceMapper mapper;
@Before
public void setUp( )
{
this.mapper = new EmpireResourceMapper( );
@SuppressWarnings( "unchecked" )
HashMap< String , Object > rows[] = new HashMap[ 2 ];
for ( int i = 0 ; i < 2 ; i++ ) {
HashMap< String , Object > row = new HashMap< String , Object >( );
row.put( "resource_identifier" , TEST_STRING );
row.put( "empres_possessed" , POSSESSED_VALUE + i );
row.put( "planets_income" , P_INCOME_VALUE + i );
row.put( "planets_upkeep" , P_UPKEEP_VALUE + i );
row.put( "fleets_upkeep" , F_UPKEEP_VALUE + i );
if ( i == 1 ) {
row.put( "empmset_weight" , PRIORITY_VALUE + i );
}
rows[ i ] = row;
}
this.resultSet = MockResultSet.create( rows );
}
/** Test mapping a row that does not include a mining priority */
@Test
public void testMapWithoutPriority( )
throws SQLException
{
this.resultSet.absolute( 1 );
EmpireResourceRecord record = this.mapper.mapRow( this.resultSet , 1 );
assertEquals( TEST_STRING , record.getIdentifier( ) );
assertEquals( POSSESSED_VALUE , record.getStockpiled( ) );
assertEquals( P_INCOME_VALUE , record.getIncome( ) );
assertEquals( P_UPKEEP_VALUE , record.getPlanetUpkeep( ) );
assertEquals( F_UPKEEP_VALUE , record.getFleetUpkeep( ) );
assertNull( record.getMiningPriority( ) );
}
/** Test mapping a row that includes a mining priority */
@Test
public void testMapWithPriority( )
throws SQLException
{
this.resultSet.absolute( 2 );
EmpireResourceRecord record = this.mapper.mapRow( this.resultSet , 1 );
assertEquals( TEST_STRING , record.getIdentifier( ) );
assertEquals( 1 + POSSESSED_VALUE , record.getStockpiled( ) );
assertEquals( 1 + P_INCOME_VALUE , record.getIncome( ) );
assertEquals( 1 + P_UPKEEP_VALUE , record.getPlanetUpkeep( ) );
assertEquals( 1 + F_UPKEEP_VALUE , record.getFleetUpkeep( ) );
assertNotNull( record.getMiningPriority( ) );
assertEquals( 1 + PRIORITY_VALUE , (int) record.getMiningPriority( ) );
}
}

View file

@ -0,0 +1,131 @@
package com.deepclone.lw.beans.game.resources;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
import com.deepclone.lw.cmd.player.gdata.planets.ResourceProviderRecord;
import com.deepclone.lw.testing.MockResultSet;
/**
* Tests for {@link PlanetResourceMapper}
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class TestPlanetResourceMapper
{
/** Value used as the resource identifier */
private static final Object RID_VALUE = "resource id";
/** Value used as the income */
private static final long P_INCOME_VALUE = 1;
/** Value used as the upkeep */
private static final long P_UPKEEP_VALUE = 2;
/** Value used as the investment */
private static final long P_INVEST_VALUE = 3;
/** Value used as the resource provider's capacity */
private static final long RP_CAPACITY_VALUE = 5L;
/** Value used as the resource provider's current quantity */
private static final long RP_QUANTITY_VALUE = 6L;
/** Value used as the resource provider's difficulty */
private static final int RP_DIFF_VALUE = 7;
/** Value used as the mining setting */
private static final int MS_WEIGHT_VALUE = 8;
/** The mapper under test */
private PlanetResourceMapper mapper;
/** The fake result set fed to the mapper */
private ResultSet resultSet;
/**
* Create the mapper and a result set to test it with.
*/
@Before
public void setUp( )
{
this.mapper = new PlanetResourceMapper( );
@SuppressWarnings( "unchecked" )
HashMap< String , Object > rows[] = new HashMap[ 2 ];
for ( int i = 0 ; i < 2 ; i++ ) {
HashMap< String , Object > row = new HashMap< String , Object >( );
row.put( "resource_identifier" , RID_VALUE );
row.put( "pres_income" , P_INCOME_VALUE + i );
row.put( "pres_upkeep" , P_UPKEEP_VALUE + i );
row.put( "pres_invested" , P_INVEST_VALUE + i );
if ( i == 1 ) {
row.put( "resprov_capacity" , RP_CAPACITY_VALUE );
row.put( "resprov_quantity" , RP_QUANTITY_VALUE );
row.put( "resprov_difficulty" , RP_DIFF_VALUE );
row.put( "mset_weight" , MS_WEIGHT_VALUE );
}
rows[ i ] = row;
}
this.resultSet = MockResultSet.create( rows );
}
/**
* Planet resource row with no resource provider
*/
@Test
public void testRowWithoutResourceProvider( )
throws SQLException
{
this.resultSet.absolute( 1 );
PlanetResourceRecord row = this.mapper.mapRow( this.resultSet , 1 );
assertEquals( RID_VALUE , row.getIdentifier( ) );
assertEquals( P_INCOME_VALUE , row.getIncome( ) );
assertEquals( P_UPKEEP_VALUE , row.getUpkeep( ) );
assertEquals( P_INVEST_VALUE , row.getInvested( ) );
assertNull( row.getResourceProvider( ) );
}
/**
* Planet resource row with a resource provider
*/
@Test
public void testRowWithResourceProvider( )
throws SQLException
{
this.resultSet.absolute( 2 );
PlanetResourceRecord row = this.mapper.mapRow( this.resultSet , 2 );
assertEquals( RID_VALUE , row.getIdentifier( ) );
assertEquals( P_INCOME_VALUE + 1 , row.getIncome( ) );
assertEquals( P_UPKEEP_VALUE + 1 , row.getUpkeep( ) );
assertEquals( P_INVEST_VALUE + 1 , row.getInvested( ) );
ResourceProviderRecord rp = row.getResourceProvider( );
assertNotNull( rp );
assertEquals( RP_CAPACITY_VALUE , rp.getCapacity( ) );
assertEquals( RP_QUANTITY_VALUE , rp.getQuantity( ) );
assertEquals( RP_DIFF_VALUE , rp.getDifficulty( ) );
assertEquals( MS_WEIGHT_VALUE , rp.getPriority( ) );
}
}

View file

@ -225,6 +225,28 @@ public class MockResultSet
} }
/**
* Return the object in some column of the current "row" as a long integer
*
* @param columnName
* the column's name
*
* @return the object from the fake results, as a long integer
*
* @throws SQLException
* if no row is selected
*/
public long getLong( String columnName )
throws SQLException
{
Object object = this.getObject( columnName );
if ( object != null ) {
return (Long) object;
}
return 0;
}
/** /**
* Return the object in some column of the current "row" as a double * Return the object in some column of the current "row" as a double
* *

View file

@ -0,0 +1,109 @@
package com.deepclone.lw.cmd.player.gdata;
import java.io.Serializable;
public abstract class AbstractResourceRecord
implements Serializable
{
/**
* The serialisation version identifier
*
* <ul>
* <li>Introduced in B6M2 with ID 1
* </ul>
*/
private static final long serialVersionUID = 1L;
/** The text identifier of the resource */
private String identifier;
/** The internationalised name of the resource's category */
private String category;
/** The internationalised name of the resource */
private String title;
/** The internationalised description of the resource */
private String description;
/** @return the text identifying the resource */
public String getIdentifier( )
{
return this.identifier;
}
/**
* Set the text identifying the resource
*
* @param identifier
* the text identifying the resource
*/
public void setIdentifier( String identifier )
{
this.identifier = identifier;
}
/** @return the internationalised title of the resource */
public String getTitle( )
{
return this.title;
}
/**
* Set the internationalised title of the resource
*
* @param title
* the internationalised title of the resource
*/
public void setTitle( String title )
{
this.title = title;
}
/** @return the internationalised name of the category of the resource */
public String getCategory( )
{
return this.category;
}
/**
* Set the internationalised name of the category of the resource
*
* @param category
* the internationalised name of the category of the resource
*/
public void setCategory( String category )
{
this.category = category;
}
/** @return the internationalised description of the resource */
public String getDescription( )
{
return this.description;
}
/**
* Set the internationalised description of the resource
*
* @param description
* the internationalised description of the resource
*/
public void setDescription( String description )
{
this.description = description;
}
}

View file

@ -0,0 +1,152 @@
package com.deepclone.lw.cmd.player.gdata.empire;
import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
/**
* Resource economic record
*
* <p>
* This record describes a resource. It is used in the empire overview's economic information and
* for mining settings.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
public class EmpireResourceRecord
extends AbstractResourceRecord
{
/**
* The serialisation version identifier
*
* <ul>
* <li>Introduced in B6M2 with ID 1
* </ul>
*/
private static final long serialVersionUID = 1L;
/** The income for this type of resource over 12h RT / 1 month GT */
private long income;
/** The planet upkeep for this type of resource over 12h RT / 1 month GT */
private long planetUpkeep;
/** The fleet upkeep for this type of resource over 12h RT / 1 month GT */
private long fleetUpkeep;
/** The amount of resources of this type possessed by the empire */
private long stockpiled;
/** The resource's mining priority, or <code>null</code> for basic resources */
private Integer miningPriority;
/** @return the income for this type of resource over a period of 12h RT / 1 month GT */
public long getIncome( )
{
return this.income;
}
/**
* Set the income for this type of resource over a period of 12h RT / 1 month GT
*
* @param income
* the income for this type of resource over a period of 12h RT / 1 month GT
*/
public void setIncome( long income )
{
this.income = income;
}
/** @return the upkeep for this type of resource over a period of 12h RT / 1 month GT on planets */
public long getPlanetUpkeep( )
{
return this.planetUpkeep;
}
/**
* Set the upkeep for this type of resource over a period of 12h RT / 1 month GT on planets
*
* @param planetUpkeep
* the upkeep for this type of resource over a period of 12h RT / 1 month GT on
* planets
*/
public void setPlanetUpkeep( long planetUpkeep )
{
this.planetUpkeep = planetUpkeep;
}
/** @return the upkeep for this type of resource over a period of 12h RT / 1 month GT on planets */
public long getFleetUpkeep( )
{
return this.fleetUpkeep;
}
/**
* Set the fleet upkeep for this type of resource over a period of 12h RT / 1 month GT
*
* @param fleetUpkeep
* the fleet upkeep for this type of resource over a period of 12h RT / 1 month GT
*/
public void setFleetUpkeep( long fleetUpkeep )
{
this.fleetUpkeep = fleetUpkeep;
}
/** @return the total upkeep (including both fleet and planet upkeep) */
public long getUpkeep( )
{
return this.fleetUpkeep + this.planetUpkeep;
}
/** @return the amount of resources of this type the empire possesses */
public long getStockpiled( )
{
return this.stockpiled;
}
/**
* Set the amount of resources of this type the empire possesses
*
* @param stockpiled
* the amount of resources of this type the empire possesses
*/
public void setStockpiled( long stockpiled )
{
this.stockpiled = stockpiled;
}
/**
* @return the mining priority for this type of resource, or <code>null</code> if it is a basic
* resource
*/
public Integer getMiningPriority( )
{
return this.miningPriority;
}
/**
* Set the mining priority for this type of resource
*
* @param miningPriority
* the mining priority for this type of resource
*/
public void setMiningPriority( int miningPriority )
{
this.miningPriority = miningPriority;
}
}

View file

@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.gdata.empire;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
@ -9,124 +10,234 @@ public class OverviewData
implements Serializable implements Serializable
{ {
private static final long serialVersionUID = 1L; /**
* Serialisation version identifier
*
* <ul>
* <li>Introduced in B6M1 with ID 1
* <li>Modified in B6M2, ID set to 2
* </ul>
*/
private static final long serialVersionUID = 2L;
/** Quantity of planets owned by the empire */
private long planets; private long planets;
/** Amount of unread messages */
private int newMessages; private int newMessages;
/** Total population in the empire */
private long population; private long population;
/** Average happiness of the population on the planets, as a percentage */
private int avgHappiness; private int avgHappiness;
/** Total fleet power */
private long fleetPower; private long fleetPower;
/** Total monetary income from planets */
private long planetIncome; private long planetIncome;
/** Total monetary upkeep for planets */
private long planetUpkeep; private long planetUpkeep;
/** Total monetary fleet upkeep */
private long fleetUpkeep; private long fleetUpkeep;
/** Total amount of money in the various queues */
private long investment; private long investment;
/** Economic information */
private List< EmpireResourceRecord > economy;
/** @return the quantity of planets owned by the empire */
public long getPlanets( ) public long getPlanets( )
{ {
return planets; return this.planets;
} }
/**
* Set the quantity of planets owned by the empire
*
* @param planets
* the quantity of planets owned by the empire
*/
public void setPlanets( long planets ) public void setPlanets( long planets )
{ {
this.planets = planets; this.planets = planets;
} }
/** @return the quantity of unread messages */
public int getNewMessages( ) public int getNewMessages( )
{ {
return newMessages; return this.newMessages;
} }
/**
* Set the quantity of unread messages
*
* @param newMessages
* the quantity of unread messages
*/
public void setNewMessages( int newMessages ) public void setNewMessages( int newMessages )
{ {
this.newMessages = newMessages; this.newMessages = newMessages;
} }
/** @return the empire's total population */
public long getPopulation( ) public long getPopulation( )
{ {
return population; return this.population;
} }
/**
* Set the empire's total population
*
* @param population
* the empire's total population
*/
public void setPopulation( long population ) public void setPopulation( long population )
{ {
this.population = population; this.population = population;
} }
/** @return the average happiness on the empire's planets */
public int getAvgHappiness( ) public int getAvgHappiness( )
{ {
return avgHappiness; return this.avgHappiness;
} }
/**
* Set the average happiness on the empire's planets
*
* @param avgHappiness
* the average happiness on the empire's planets
*/
public void setAvgHappiness( int avgHappiness ) public void setAvgHappiness( int avgHappiness )
{ {
this.avgHappiness = avgHappiness; this.avgHappiness = avgHappiness;
} }
/** @return the total fleet power */
public long getFleetPower( ) public long getFleetPower( )
{ {
return fleetPower; return this.fleetPower;
} }
/**
* Set the total fleet power
*
* @param fleetPower
* the total fleet power
*/
public void setFleetPower( long fleetPower ) public void setFleetPower( long fleetPower )
{ {
this.fleetPower = fleetPower; this.fleetPower = fleetPower;
} }
/** @return the monetary income from the empire's planets */
public long getPlanetIncome( ) public long getPlanetIncome( )
{ {
return planetIncome; return this.planetIncome;
} }
/**
* Set the monetary income from the empire's planets
*
* @param planetIncome
* the monetary income from the empire's planets
*/
public void setPlanetIncome( long planetIncome ) public void setPlanetIncome( long planetIncome )
{ {
this.planetIncome = planetIncome; this.planetIncome = planetIncome;
} }
/** @return the monetary upkeep for the empire's planets */
public long getPlanetUpkeep( ) public long getPlanetUpkeep( )
{ {
return planetUpkeep; return this.planetUpkeep;
} }
/**
* Set the monetary upkeep for the empire's planets
*
* @param planetUpkeep
* the monetary upkeep for the empire's planets
*/
public void setPlanetUpkeep( long planetUpkeep ) public void setPlanetUpkeep( long planetUpkeep )
{ {
this.planetUpkeep = planetUpkeep; this.planetUpkeep = planetUpkeep;
} }
/** @return the monetary upkeep for the empire's fleets */
public long getFleetUpkeep( ) public long getFleetUpkeep( )
{ {
return fleetUpkeep; return this.fleetUpkeep;
} }
/**
* Set the monetary upkeep for the empire's fleets
*
* @param fleetUpkeep
* the monetary upkeep for the empire's fleets
*/
public void setFleetUpkeep( long fleetUpkeep ) public void setFleetUpkeep( long fleetUpkeep )
{ {
this.fleetUpkeep = fleetUpkeep; this.fleetUpkeep = fleetUpkeep;
} }
/** @return the total amount of money invested in civilian or military queues */
public long getInvestment( ) public long getInvestment( )
{ {
return investment; return this.investment;
} }
/**
* Set the total amount of money invested in civilian or military queues
*
* @param investment
* the total amount of money invested in civilian or military queues
*/
public void setInvestment( long investment ) public void setInvestment( long investment )
{ {
this.investment = investment; this.investment = investment;
} }
/** @return the list of economic information records */
public List< EmpireResourceRecord > getEconomy( )
{
return this.economy;
}
/**
* Set the list of economic information records
*
* @param economy
* the list of economic information records
*/
public void setEconomy( List< EmpireResourceRecord > economy )
{
this.economy = economy;
}
} }

View file

@ -6,128 +6,283 @@ import java.util.List;
/**
* Planet view details available to planet owners
*
* <p>
* This class carries the part of the planet view which is only available to empires owning the
* planet being viewed.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class PlanetOwnView public class PlanetOwnView
implements Serializable implements Serializable
{ {
private static final long serialVersionUID = 1L; /**
* Serialisation version identifier
*
* <ul>
* <li>Introduced in B6M1 with ID 1
* <li>Modified in B6M2, ID set to 2
* </ul>
*/
private static final long serialVersionUID = 2L;
/** Happiness of the planet's population as a percentage */
private int happiness; private int happiness;
/**
* Happiness change indicator
*
* <p>
* This field's value is an integer between -2 and 2 (inclusive). It indicates the direction of
* the happiness' change (positive meaning that the happiness is increasing, negative meaning it
* is decreasing), and the strength of the change (absolute value 1 meaning a relatively small
* change, 2 a bigger one)
*/
private int hChange; private int hChange;
/** Planet monetary income for 24h of RL time */
private long income; private long income;
/** Planet monetary upkeep for 24h of RL time */
private long upkeep; private long upkeep;
/**
* Various planet state indicators
*
* <p>
* This field carries a few flags about whether it is possible to rename or abandon the planet,
* and similar information.
*/
private OwnPlanetStatusData status; private OwnPlanetStatusData status;
/** Civilian construction queue */
private QueueData civQueue; private QueueData civQueue;
/** Military construction queue */
private QueueData milQueue; private QueueData milQueue;
/** Descriptions of ships that can be built */
private List< BuildableShipData > bShips; private List< BuildableShipData > bShips;
/** Descriptions of buildings that can be constructed */
private List< BuildableBuildingData > bBuildings; private List< BuildableBuildingData > bBuildings;
/** List of the planet's resources */
private List< PlanetResourceRecord > resources;
/** Is the planet using specific mining settings? */
private boolean ownMiningSettings;
/** @return the planet's happiness */
public int getHappiness( ) public int getHappiness( )
{ {
return happiness; return this.happiness;
} }
/**
* Set the planet's happiness
*
* @param happiness
* the planet's happiness
*/
public void setHappiness( int happiness ) public void setHappiness( int happiness )
{ {
this.happiness = happiness; this.happiness = happiness;
} }
/** @return the planet's happiness change indicator */
public int gethChange( ) public int gethChange( )
{ {
return hChange; return this.hChange;
} }
/**
* Set the planet's happiness change indicator
*
* @param hChange
* the planet's happiness change indicator
*/
public void sethChange( int hChange ) public void sethChange( int hChange )
{ {
this.hChange = hChange; this.hChange = hChange;
} }
/** @return the planet's monetary income */
public long getIncome( ) public long getIncome( )
{ {
return income; return this.income;
} }
/**
* Set the planet's monetary income
*
* @param income
* the planet's monetary income
*/
public void setIncome( long income ) public void setIncome( long income )
{ {
this.income = income; this.income = income;
} }
/** @return the planet's monetary upkeep */
public long getUpkeep( ) public long getUpkeep( )
{ {
return upkeep; return this.upkeep;
} }
/**
* Set the planet's monetary upkeep
*
* @param upkeep
* the planet's monetary upkeep
*/
public void setUpkeep( long upkeep ) public void setUpkeep( long upkeep )
{ {
this.upkeep = upkeep; this.upkeep = upkeep;
} }
/** @return the planet status object */
public OwnPlanetStatusData getStatus( ) public OwnPlanetStatusData getStatus( )
{ {
return status; return this.status;
} }
/**
* Set the planet status object
*
* @param status
* the planet status object
*/
public void setStatus( OwnPlanetStatusData status ) public void setStatus( OwnPlanetStatusData status )
{ {
this.status = status; this.status = status;
} }
/** @return the civilian construction queue */
public QueueData getCivQueue( ) public QueueData getCivQueue( )
{ {
return civQueue; return this.civQueue;
} }
/**
* Set the civilian construction queue
*
* @param civQueue
* the civilian construction queue
*/
public void setCivQueue( QueueData civQueue ) public void setCivQueue( QueueData civQueue )
{ {
this.civQueue = civQueue; this.civQueue = civQueue;
} }
/** @return the military construction queue */
public QueueData getMilQueue( ) public QueueData getMilQueue( )
{ {
return milQueue; return this.milQueue;
} }
/**
* Set the military construction queue
*
* @param milQueue
* the military construction queue
*/
public void setMilQueue( QueueData milQueue ) public void setMilQueue( QueueData milQueue )
{ {
this.milQueue = milQueue; this.milQueue = milQueue;
} }
/** @return the descriptions of all ships which can be constructed */
public List< BuildableShipData > getbShips( ) public List< BuildableShipData > getbShips( )
{ {
return bShips; return this.bShips;
} }
/**
* Set the descriptions of ships which can be constructed
*
* @param bShips
* the descriptions of ships which can be constructed
*/
public void setbShips( List< BuildableShipData > bShips ) public void setbShips( List< BuildableShipData > bShips )
{ {
this.bShips = bShips; this.bShips = bShips;
} }
/** @return the descriptions of all buildings which can be constructed */
public List< BuildableBuildingData > getbBuildings( ) public List< BuildableBuildingData > getbBuildings( )
{ {
return bBuildings; return this.bBuildings;
} }
/**
* Set the descriptions of buildings which can be constructed
*
* @param bBuildings
* the descriptions of buildings which can be constructed
*/
public void setbBuildings( List< BuildableBuildingData > bBuildings ) public void setbBuildings( List< BuildableBuildingData > bBuildings )
{ {
this.bBuildings = bBuildings; this.bBuildings = bBuildings;
} }
/** @return the list of resources */
public List< PlanetResourceRecord > getResources( )
{
return this.resources;
}
/**
* Set the list of resources
*
* @param resourceProviders
* the list of resources
*/
public void setResources( List< PlanetResourceRecord > resources )
{
this.resources = resources;
}
/** @return whether the planet is using specific mining settings */
public boolean getOwnMiningSettings( )
{
return this.ownMiningSettings;
}
/**
* Set whether the planet is using specific mining settings
*
* @param ownMiningSettings
* whether the planet is using specific mining settings
*/
public void setOwnMiningSettings( boolean ownMiningSettings )
{
this.ownMiningSettings = ownMiningSettings;
}
} }

View file

@ -0,0 +1,125 @@
package com.deepclone.lw.cmd.player.gdata.planets;
import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
/**
* Planet resources information
*
* <p>
* This class carries information about a resource type, including all required strings, as well as
* income, upkeep and investment. It also contains information about the planet's resource provider
* if there is one.
*
* <p>
* The class is used by {@link PlanetOwnView} to represent all of a planet's resources.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class PlanetResourceRecord
extends AbstractResourceRecord
{
/**
* The serialisation version identifier
*
* <ul>
* <li>Introduced in B6M2 with ID 1
* </ul>
*/
private static final long serialVersionUID = 1L;
/** Income for 12h RT / 1 month GT */
private long income;
/** Upkeep for 12h RT / 1 month GT */
private long upkeep;
/** Quantity of that resource that will be used by the planet's queues */
private long invested;
/** Information about the planet's resource provider of that type, if there is one */
private ResourceProviderRecord resourceProvider;
/** @return the planet's income for that resource, over 12h RT / 1 month GT */
public long getIncome( )
{
return this.income;
}
/**
* Set the planet's income for that resource
*
* @param income
* the planet's income for that resource, over 12h RT / 1 month GT
*/
public void setIncome( long income )
{
this.income = income;
}
/** @return the planet's upkeep for that resource, over 12h RT / 1 month GT */
public long getUpkeep( )
{
return this.upkeep;
}
/**
* Set the planet's upkeep for that resource
*
* @param upkeep
* the planet's upkeep for that resource, over 12h RT / 1 month GT
*/
public void setUpkeep( long upkeep )
{
this.upkeep = upkeep;
}
/** @return the amount of that resource invested in the planet's build queues */
public long getInvested( )
{
return this.invested;
}
/**
* Set the amount of that resource invested in the planet's build queues
*
* @param invested
* the amount of that resource invested in the planet's build queues
*/
public void setInvested( long invested )
{
this.invested = invested;
}
/**
* @return the resource provider data on that planet for the current resource type or
* <code>null</code> if there is no resource provider of that type.
*/
public ResourceProviderRecord getResourceProvider( )
{
return this.resourceProvider;
}
/**
* Set the resource provider data on that planet for the current resource type
*
* @param resourceProvider
* the resource provider data on that planet for the current resource type
*/
public void setResourceProvider( ResourceProviderRecord resourceProvider )
{
this.resourceProvider = resourceProvider;
}
}

View file

@ -0,0 +1,117 @@
package com.deepclone.lw.cmd.player.gdata.planets;
import java.io.Serializable;
/**
* Information displayed about a resource provider
*
* <p>
* This class carries the information about a resource provider and associated mining priorities.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class ResourceProviderRecord
implements Serializable
{
/**
* The serialisation version identifier
*
* <ul>
* <li>Introduced in B6M2 with ID 1
* </ul>
*/
private static final long serialVersionUID = 1L;
/** The resource provider's capacity (maximal quantity of resources) */
private long capacity;
/** The current quantity of resources in the provider */
private long quantity;
/** The extraction difficulty as a percentage */
private int difficulty;
/** The extraction priority */
private int priority;
/** @return the resource provider's capacity */
public long getCapacity( )
{
return this.capacity;
}
/**
* Set the resource provider's capacity
*
* @param capacity
* the resource provider's capacity
*/
public void setCapacity( long capacity )
{
this.capacity = capacity;
}
/** @return the resource provider's current quantity */
public long getQuantity( )
{
return this.quantity;
}
/**
* Set the resource provider's current quantity
*
* @param quantity
* the resource provider's current quantity
*/
public void setQuantity( long quantity )
{
this.quantity = quantity;
}
/** @return the extraction difficulty */
public int getDifficulty( )
{
return this.difficulty;
}
/**
* Set the extraction difficulty
*
* @param difficulty
* the extraction difficulty
*/
public void setDifficulty( int difficulty )
{
this.difficulty = difficulty;
}
/** @return the extraction priority */
public int getPriority( )
{
return this.priority;
}
/**
* Set the extraction priority
*
* @param priority
* the extraction priority
*/
public void setPriority( int priority )
{
this.priority = priority;
}
}

View file

@ -0,0 +1,88 @@
package com.deepclone.lw.cmd.player.gdata;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
/**
* Tests of the {@link AbstractResourceRecord} class
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class TestAbstractResourceRecord
{
/** String used in tests */
private static final String TEST_STRING = "Test";
/** Class used in the tests */
@SuppressWarnings( "serial" )
private static class FakeChild
extends AbstractResourceRecord
{
// EMPTY
}
/** Guinea pig instance */
private FakeChild resource;
/** Create the "guinea pig" instance */
@Before
public void setUp( )
{
this.resource = new FakeChild( );
}
/** Test default values */
@Test
public void testDefaults( )
{
assertNull( this.resource.getIdentifier( ) );
assertNull( this.resource.getCategory( ) );
assertNull( this.resource.getTitle( ) );
assertNull( this.resource.getDescription( ) );
}
/** Test setting and reading the identifier */
@Test
public void testIdentifier( )
{
this.resource.setIdentifier( TEST_STRING );
assertEquals( TEST_STRING , this.resource.getIdentifier( ) );
}
/** Test setting and reading the category */
@Test
public void testCategory( )
{
this.resource.setCategory( TEST_STRING );
assertEquals( TEST_STRING , this.resource.getCategory( ) );
}
/** Test setting and reading the title */
@Test
public void testTitle( )
{
this.resource.setTitle( TEST_STRING );
assertEquals( TEST_STRING , this.resource.getTitle( ) );
}
/** Test setting and reading the description */
@Test
public void testDescription( )
{
this.resource.setDescription( TEST_STRING );
assertEquals( TEST_STRING , this.resource.getDescription( ) );
}
}

View file

@ -0,0 +1,125 @@
package com.deepclone.lw.cmd.player.gdata.empire;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for the {@link EmpireResourceRecord} class
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class TestEmpireResourceRecord
{
/** String used in tests */
private static final String TEST_STRING = "Test";
/** Long integer used in tests */
private static final long TEST_LONG = 42L;
private static final int TEST_INTEGER = 42;
/** The "guinea pig" instance */
private EmpireResourceRecord instance;
/** Create the "guinea pig" instance */
@Before
public void setUp( )
{
this.instance = new EmpireResourceRecord( );
}
/** Check default values */
@Test
public void testDefaults( )
{
assertNull( this.instance.getIdentifier( ) );
assertNull( this.instance.getDescription( ) );
assertEquals( 0L , this.instance.getIncome( ) );
assertEquals( 0L , this.instance.getPlanetUpkeep( ) );
assertEquals( 0L , this.instance.getFleetUpkeep( ) );
assertEquals( 0L , this.instance.getUpkeep( ) );
assertEquals( 0L , this.instance.getStockpiled( ) );
assertNull( this.instance.getMiningPriority( ) );
}
/** Setting and reading the identifier */
@Test
public void testIdentifier( )
{
this.instance.setIdentifier( TEST_STRING );
assertEquals( TEST_STRING , this.instance.getIdentifier( ) );
}
/** Setting and reading the description */
@Test
public void testDescription( )
{
this.instance.setDescription( TEST_STRING );
assertEquals( TEST_STRING , this.instance.getDescription( ) );
}
/** Setting and reading the income */
@Test
public void testIncome( )
{
this.instance.setIncome( TEST_LONG );
assertEquals( TEST_LONG , this.instance.getIncome( ) );
}
/** Setting and reading the planet upkeep */
@Test
public void testPlanetUpkeep( )
{
this.instance.setPlanetUpkeep( TEST_LONG );
assertEquals( TEST_LONG , this.instance.getPlanetUpkeep( ) );
}
/** Setting and reading the fleet upkeep */
@Test
public void testFleetUpkeep( )
{
this.instance.setFleetUpkeep( TEST_LONG );
assertEquals( TEST_LONG , this.instance.getFleetUpkeep( ) );
}
/** Setting and reading the stockpiled quantity */
@Test
public void testStockpiled( )
{
this.instance.setStockpiled( TEST_LONG );
assertEquals( TEST_LONG , this.instance.getStockpiled( ) );
}
/** Setting and reading the mining priority */
@Test
public void testMiningPriority( )
{
this.instance.setMiningPriority( TEST_INTEGER );
assertEquals( (Integer) TEST_INTEGER , this.instance.getMiningPriority( ) );
}
/** Total upkeep = fleet upkeep + planet upkeep */
@Test
public void testTotalUpkeep( )
{
this.instance.setPlanetUpkeep( TEST_LONG );
assertEquals( TEST_LONG , this.instance.getUpkeep( ) );
this.instance.setFleetUpkeep( TEST_LONG + 1 );
assertEquals( TEST_LONG * 2 + 1 , this.instance.getUpkeep( ) );
}
}

View file

@ -0,0 +1,82 @@
package com.deepclone.lw.cmd.player.gdata.planets;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for the {@link PlanetResourceRecord} class.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*/
public class TestPlanetResourceRecord
{
/** Long integer used in tests */
private static final long TEST_LONG = 42L;
/** Resource data instance to test on */
private PlanetResourceRecord resourceData;
/** Create the "guinea pig" instance */
@Before
public void setUp( )
{
this.resourceData = new PlanetResourceRecord( );
}
/** Test default values */
@Test
public void testDefaults( )
{
assertEquals( 0L , this.resourceData.getIncome( ) );
assertEquals( 0L , this.resourceData.getUpkeep( ) );
assertEquals( 0L , this.resourceData.getInvested( ) );
assertNull( this.resourceData.getResourceProvider( ) );
}
/** Test setting and reading the income */
@Test
public void testIncome( )
{
this.resourceData.setIncome( TEST_LONG );
assertEquals( TEST_LONG , this.resourceData.getIncome( ) );
}
/** Test setting and reading the upkeep */
@Test
public void testUpkeep( )
{
this.resourceData.setUpkeep( TEST_LONG );
assertEquals( TEST_LONG , this.resourceData.getUpkeep( ) );
}
/** Test setting and reading the invested amount */
@Test
public void testInvested( )
{
this.resourceData.setInvested( TEST_LONG );
assertEquals( TEST_LONG , this.resourceData.getInvested( ) );
}
/** Test setting and reading the resource provider */
@Test
public void testResourceProvider( )
{
ResourceProviderRecord rpd = new ResourceProviderRecord( );
rpd.setCapacity( TEST_LONG );
this.resourceData.setResourceProvider( rpd );
rpd = this.resourceData.getResourceProvider( );
assertNotNull( rpd );
assertEquals( TEST_LONG , rpd.getCapacity( ) );
}
}

View file

@ -0,0 +1,83 @@
package com.deepclone.lw.cmd.player.gdata.planets;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for the {@link ResourceProviderRecord} class.
*
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
*
*/
public class TestResourceProviderRecord
{
/** Long integer used in tests */
private static final long TEST_LONG = 42L;
/** Integer used in tests */
private static final int TEST_INT = 42;
/** Resource provider data instance to test on */
private ResourceProviderRecord resProvData;
/** Create the "guinea pig" instance */
@Before
public void setUp( )
{
this.resProvData = new ResourceProviderRecord( );
}
/** Check default values */
@Test
public void testDefaults( )
{
assertEquals( 0L , this.resProvData.getCapacity( ) );
assertEquals( 0L , this.resProvData.getQuantity( ) );
assertEquals( 0 , this.resProvData.getDifficulty( ) );
assertEquals( 0 , this.resProvData.getPriority( ) );
}
/** Setting and reading the capacity */
@Test
public void testSetCapacity( )
{
this.resProvData.setCapacity( TEST_LONG );
assertEquals( TEST_LONG , this.resProvData.getCapacity( ) );
}
/** Setting and reading the quantity */
@Test
public void testSetQuantity( )
{
this.resProvData.setQuantity( TEST_LONG );
assertEquals( TEST_LONG , this.resProvData.getQuantity( ) );
}
/** Setting and reading the difficulty */
@Test
public void testSetDifficulty( )
{
this.resProvData.setDifficulty( TEST_INT );
assertEquals( TEST_INT , this.resProvData.getDifficulty( ) );
}
/** Setting and reading the priority */
@Test
public void testSetPriority( )
{
this.resProvData.setPriority( TEST_INT );
assertEquals( TEST_INT , this.resProvData.getPriority( ) );
}
}

View file

@ -64,3 +64,10 @@
<#macro abbr_bgc><abbr title="billion galactic credits">bgc</abbr></#macro> <#macro abbr_bgc><abbr title="billion galactic credits">bgc</abbr></#macro>
<#macro abbr_st><abbr title="Server time">ST</abbr></#macro> <#macro abbr_st><abbr title="Server time">ST</abbr></#macro>
<#macro abbr_gt><abbr title="Time in the game universe">GT</abbr></#macro> <#macro abbr_gt><abbr title="Time in the game universe">GT</abbr></#macro>
<#macro over_time title>
<#if data.page.useRLTime>
${title?xhtml} (for 12h)
<#else>
Monthly ${title?xhtml}
</#if>
</#macro>

View file

@ -62,6 +62,63 @@
</@right_column> </@right_column>
</@tab> </@tab>
<@tab id="economy" title="Economy">
<@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>
<#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 id="research" title="Research"> <@tab id="research" title="Research">
<#if rs?size == 0> <#if rs?size == 0>
<p>Our scientists are still settling in.</p> <p>Our scientists are still settling in.</p>

View file

@ -109,6 +109,55 @@
</@tab> </@tab>
<#if data.own?has_content && data.own.resources?size gt 0>
<@tab id="resources" title="Economy">
<@listview>
<#local previousCategory="">
<@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>Invested</@lv_column>
</@lv_line>
<#list data.own.resources 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.invested?string(",##0")}</@lv_column>
</@lv_line>
</#list>
</@listview>
</@tab>
</#if>
<#if data.orbit?has_content> <#if data.orbit?has_content>
<#if data.orbit.buildings?size gt 0 || data.own?has_content> <#if data.orbit.buildings?size gt 0 || data.own?has_content>
@ -143,6 +192,7 @@
<#case "DEF">defence<#break> <#case "DEF">defence<#break>
<#case "WORK">mil. output<#break> <#case "WORK">mil. output<#break>
<#case "POP">growth<#break> <#case "POP">growth<#break>
<#case "MINE">res. extraction<#break>
</#switch> </#switch>
</@lv_column> </@lv_column>
<@lv_column centered=true>${building.jobs?string(",##0")}</@lv_column> <@lv_column centered=true>${building.jobs?string(",##0")}</@lv_column>
@ -189,6 +239,7 @@
<#case "DEF">defence<#break> <#case "DEF">defence<#break>
<#case "WORK">mil. output<#break> <#case "WORK">mil. output<#break>
<#case "POP">growth<#break> <#case "POP">growth<#break>
<#case "MINE">res. extraction<#break>
</#switch> </#switch>
</@dt_entry> </@dt_entry>
</@dt_main> </@dt_main>
@ -251,6 +302,7 @@
</#if> </#if>
<#if data.own?has_content> <#if data.own?has_content>
<@tab id="ships" title="Shipyards"> <@tab id="ships" title="Shipyards">
<#if data.page.special! != 'v'> <#if data.page.special! != 'v'>
<#if data.own.milQueue.appendPossible> <#if data.own.milQueue.appendPossible>
@ -321,7 +373,58 @@
</@listview> </@listview>
</#if> </#if>
</@tab> </@tab>
</#if> </#if>
<#list data.own.resources as resource>
<#if resource.resourceProvider?has_content>
<#local showResources=true>
<#break>
</#if>
</#list>
<#if showResources?has_content>
<@tab id="natres" title="Natural resources">
<@listview>
<@lv_line headers=true>
<@lv_column width="x">Resource</@lv_column>
<@lv_column width=100 right=true>Quantity&nbsp;</@lv_column>
<@lv_column width=100>&nbsp;&nbsp;Capacity</@lv_column>
<@lv_column width=100 centered=true>Extraction<br/>difficulty</@lv_column>
<@lv_column width=100 centered=true>Priority</@lv_column>
</@lv_line>
<#list data.own.resources as resource>
<#if resource.resourceProvider?has_content>
<#local resProv=resource.resourceProvider>
<@lv_line>
<@lv_column>
${resource.title?xhtml}
<div class="auto-hide">${resource.description?xhtml}</div>
</@lv_column>
<@lv_column right=true>${resProv.quantity?string(",##0")}&nbsp;</@lv_column>
<@lv_column>/&nbsp;${resProv.capacity?string(",##0")}</@lv_column>
<@lv_column centered=true>${resProv.difficulty}&nbsp;%</@lv_column>
<@lv_column centered=true>
<#switch resProv.priority>
<#case 0>lowest<#break>
<#case 1>low<#break>
<#case 2>normal<#break>
<#case 3>high<#break>
<#case 4>highest<#break>
</#switch>
</@lv_column>
</@lv_line>
</#if>
</#list>
</@listview>
</@tab>
</#if>
</#if> </#if>
</@tabs> </@tabs>

View file

@ -64,3 +64,10 @@
<#macro abbr_bgc><abbr title="milliards de crédits galactiques">mcg</abbr></#macro> <#macro abbr_bgc><abbr title="milliards de crédits galactiques">mcg</abbr></#macro>
<#macro abbr_st><abbr title="Temps Serveur">TS </abbr></#macro> <#macro abbr_st><abbr title="Temps Serveur">TS </abbr></#macro>
<#macro abbr_gt><abbr title="Temps dans l'univers du jeu">TJ </abbr></#macro> <#macro abbr_gt><abbr title="Temps dans l'univers du jeu">TJ </abbr></#macro>
<#macro over_time title feminin=false pluriel=false>
<#if data.page.useRLTime>
${title?xhtml} (pour 12h)
<#else>
${title?xhtml} mensuel<#if feminin>le</#if><#if pluriel>s</#if>
</#if>
</#macro>

View file

@ -62,6 +62,63 @@
</@right_column> </@right_column>
</@tab> </@tab>
<@tab id="economy" title="Économie">
<@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>
<#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 id="research" title="Recherche"> <@tab id="research" title="Recherche">
<#if rs?size == 0> <#if rs?size == 0>
<p>Nos scientifiques sont encore en train de s'installer.</p> <p>Nos scientifiques sont encore en train de s'installer.</p>

View file

@ -109,6 +109,55 @@
</@tab> </@tab>
<#if data.own?has_content && data.own.resources?size gt 0>
<@tab id="resources" title="Économie">
<@listview>
<#local previousCategory="">
<@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>Investissement</@lv_column>
</@lv_line>
<#list data.own.resources 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.invested?string(",##0")}</@lv_column>
</@lv_line>
</#list>
</@listview>
</@tab>
</#if>
<#if data.orbit?has_content> <#if data.orbit?has_content>
<#if data.orbit.buildings?size gt 0 || data.own?has_content> <#if data.orbit.buildings?size gt 0 || data.own?has_content>
@ -143,6 +192,7 @@
<#case "DEF">défense<#break> <#case "DEF">défense<#break>
<#case "WORK">production mil.<#break> <#case "WORK">production mil.<#break>
<#case "POP">croissance<#break> <#case "POP">croissance<#break>
<#case "MINE">extraction<#break>
</#switch> </#switch>
</@lv_column> </@lv_column>
<@lv_column centered=true>${building.jobs?string(",##0")}</@lv_column> <@lv_column centered=true>${building.jobs?string(",##0")}</@lv_column>
@ -189,6 +239,7 @@
<#case "DEF">défense<#break> <#case "DEF">défense<#break>
<#case "WORK">production mil.<#break> <#case "WORK">production mil.<#break>
<#case "POP">croissance<#break> <#case "POP">croissance<#break>
<#case "MINE">extraction<#break>
</#switch> </#switch>
</@dt_entry> </@dt_entry>
</@dt_main> </@dt_main>
@ -322,6 +373,56 @@
</#if> </#if>
</@tab> </@tab>
</#if> </#if>
<#list data.own.resources as resource>
<#if resource.resourceProvider?has_content>
<#local showResources=true>
<#break>
</#if>
</#list>
<#if showResources?has_content>
<@tab id="natres" title="Ressources naturelles">
<@listview>
<@lv_line headers=true>
<@lv_column width="x">Ressource</@lv_column>
<@lv_column width=100 right=true>Quantité&nbsp;</@lv_column>
<@lv_column width=100>&nbsp;&nbsp;Capacité</@lv_column>
<@lv_column width=100 centered=true>Difficulté<br/>d'extraction</@lv_column>
<@lv_column width=100 centered=true>Priorité</@lv_column>
</@lv_line>
<#list data.own.resources as resource>
<#if resource.resourceProvider?has_content>
<#local resProv=resource.resourceProvider>
<@lv_line>
<@lv_column>
${resource.title?xhtml}
<div class="auto-hide">${resource.description?xhtml}</div>
</@lv_column>
<@lv_column right=true>${resProv.quantity?string(",##0")}&nbsp;</@lv_column>
<@lv_column>/&nbsp;${resProv.capacity?string(",##0")}</@lv_column>
<@lv_column centered=true>${resProv.difficulty}&nbsp;%</@lv_column>
<@lv_column centered=true>
<#switch resProv.priority>
<#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>
</@lv_column>
</@lv_line>
</#if>
</#list>
</@listview>
</@tab>
</#if>
</#if> </#if>
</@tabs> </@tabs>

View file

@ -8,17 +8,17 @@
<#nested> <#nested>
</tr> </tr>
</#macro> </#macro>
<#macro lv_column width=0 centered=false right=false> <#macro lv_column width=0 centered=false right=false colspan=0>
<#if width?is_string> <#if width?is_string>
<th style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"> <th style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1>colspan="${colspan}"</#if>>
<#nested> <#nested>
</th> </th>
<#elseif width gt 0> <#elseif width gt 0>
<th style="width: ${width}px; text-align: <#if centered>center<#elseif right>right<#else>left</#if>"> <th style="width: ${width}px; text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1>colspan="${colspan}"</#if>>
<#nested> <#nested>
</th> </th>
<#else> <#else>
<td style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"> <td style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>" <#if colspan gt 1>colspan="${colspan}"</#if>>
<#nested> <#nested>
</td> </td>
</#if> </#if>