New research and technology page
* Added legacyworlds-server-beans-technologies Maven module, including the player-level DAO and controller. * Added session classes to carry technology information, modified web client session façade accordingly * Various changes to common UI elements (forms, lists, etc...) so the start and end of some element can be drawn separately * Added controller, templates and JavaScript for research page
This commit is contained in:
parent
154f215e24
commit
6dcd59d7bc
45 changed files with 2314 additions and 178 deletions
|
@ -27,7 +27,6 @@ public class EmpireDAOBean
|
|||
implements EmpireDAO
|
||||
{
|
||||
private JdbcTemplate dTemplate;
|
||||
private StoredProc fImplementTech;
|
||||
private StoredProc fAddEmpEnemy;
|
||||
private StoredProc fAddAllEnemy;
|
||||
private StoredProc fRemoveEmpEnemy;
|
||||
|
@ -42,10 +41,6 @@ public class EmpireDAOBean
|
|||
{
|
||||
this.dTemplate = new JdbcTemplate( dataSource );
|
||||
|
||||
this.fImplementTech = new StoredProc( dataSource , "emp" , "implement_tech" );
|
||||
this.fImplementTech.addParameter( "empire_id" , Types.INTEGER );
|
||||
this.fImplementTech.addParameter( "line_id" , Types.INTEGER );
|
||||
|
||||
this.fAddEmpEnemy = new StoredProc( dataSource , "emp" , "add_enemy_empire" );
|
||||
this.fAddEmpEnemy.addParameter( "empire_id" , Types.INTEGER );
|
||||
this.fAddEmpEnemy.addParameter( "enemy_name" , Types.VARCHAR );
|
||||
|
@ -141,13 +136,6 @@ public class EmpireDAOBean
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void implementTechnology( int empireId , int lineId )
|
||||
{
|
||||
this.fImplementTech.execute( empireId , lineId );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List< PlanetListData > getPlanetList( int empireId )
|
||||
{
|
||||
|
|
|
@ -146,14 +146,6 @@ public class EmpireManagementBean
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EmpireResponse implementTechnology( int empireId , int techId )
|
||||
{
|
||||
this.empireDao.implementTechnology( empireId , techId );
|
||||
return this.getOverview( empireId );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ListPlanetsResponse getPlanetList( int empireId )
|
||||
{
|
||||
|
|
26
legacyworlds-server-beans-technologies/pom.xml
Normal file
26
legacyworlds-server-beans-technologies/pom.xml
Normal file
|
@ -0,0 +1,26 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>legacyworlds-server-beans</artifactId>
|
||||
<groupId>com.deepclone.lw</groupId>
|
||||
<version>1.0.0</version>
|
||||
<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>legacyworlds-server-beans-technologies</artifactId>
|
||||
<name>Legacy Worlds - Server - Components - Technologies</name>
|
||||
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
|
||||
<description>This module contains the components which manage and access in-universe technologies.</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,143 @@
|
|||
package com.deepclone.lw.beans.game.technologies;
|
||||
|
||||
|
||||
import java.sql.Types;
|
||||
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.ResearchData;
|
||||
import com.deepclone.lw.interfaces.game.technologies.PlayerTechnologiesDAO;
|
||||
import com.deepclone.lw.utils.StoredProc;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Data access component for player technologies
|
||||
*
|
||||
* <p>
|
||||
* This class implements database queries and calls to stored procedures which allow players to
|
||||
* access and manage their empires' research.
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
class PlayerTechnologiesDAOBean
|
||||
implements PlayerTechnologiesDAO
|
||||
{
|
||||
|
||||
/** SQL query that fetches an empire's research state */
|
||||
private static final String Q_EMPIRE_RESEARCH = "SELECT * FROM emp.technologies_v2_view WHERE empire_id = ?";
|
||||
|
||||
/** Row mapper for research state entries */
|
||||
private final ResearchRowMapper mResearch;
|
||||
|
||||
/** Stored procedure that initiates a research priority update */
|
||||
private StoredProc fResprioUpdateStart;
|
||||
|
||||
/** Stored procedure that uploads a single research priority */
|
||||
private StoredProc fResprioUpdateSet;
|
||||
|
||||
/** Stored procedure that applies a research priority update */
|
||||
private StoredProc fResprioUpdateApply;
|
||||
|
||||
/** Stored procedure that implements a technology */
|
||||
private StoredProc fTechnologyImplement;
|
||||
|
||||
/** Spring JDBC interface */
|
||||
private JdbcTemplate dTemplate;
|
||||
|
||||
|
||||
/** Initialise the necessary row mappers */
|
||||
public PlayerTechnologiesDAOBean( )
|
||||
{
|
||||
this.mResearch = new ResearchRowMapper( );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dependency injector that sets the data source and initialises stored procedures
|
||||
*
|
||||
* @param dataSource
|
||||
* the data source
|
||||
*/
|
||||
@Autowired( required = true )
|
||||
public void setDataSource( DataSource dataSource )
|
||||
{
|
||||
this.dTemplate = new JdbcTemplate( dataSource );
|
||||
|
||||
this.fResprioUpdateStart = new StoredProc( dataSource , "emp" , "resprio_update_start" )
|
||||
.addParameter( "_empire" , Types.INTEGER )
|
||||
.addOutput( "_result" , Types.BOOLEAN );
|
||||
|
||||
this.fResprioUpdateSet = new StoredProc( dataSource , "emp" , "resprio_update_set" )
|
||||
.addParameter( "_technology" , Types.VARCHAR )
|
||||
.addParameter( "_priority" , Types.INTEGER )
|
||||
.addOutput( "_result" , Types.BOOLEAN );
|
||||
|
||||
this.fResprioUpdateApply = new StoredProc( dataSource , "emp" , "resprio_update_apply" )
|
||||
.addOutput( "_result" , Types.BOOLEAN );
|
||||
|
||||
this.fTechnologyImplement = new StoredProc( dataSource , "emp" , "technology_implement" )
|
||||
.addParameter( "_empire" , Types.INTEGER )
|
||||
.addParameter( "_technology" , Types.VARCHAR )
|
||||
.addOutput( "_result" , Types.BOOLEAN );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query and map research entries for an empire
|
||||
*
|
||||
* <p>
|
||||
* Run the query against <code>emp.technologies_view</code> then map all rows using a
|
||||
* {@link ResearchRowMapper}.
|
||||
*/
|
||||
@Override
|
||||
public List< ResearchData > getResearchData( int empire )
|
||||
{
|
||||
return this.dTemplate.query( Q_EMPIRE_RESEARCH , this.mResearch , empire );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call <code>emp.resprio_update_start</code>
|
||||
*/
|
||||
@Override
|
||||
public boolean startPriorityUpdate( int empire )
|
||||
{
|
||||
return (Boolean) this.fResprioUpdateStart.execute( empire ).get( "_result" );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call <code>emp.resprio_update_set</code>
|
||||
*/
|
||||
@Override
|
||||
public boolean uploadResearchPriority( String identifier , int priority )
|
||||
{
|
||||
return (Boolean) this.fResprioUpdateSet.execute( identifier , priority ).get( "_result" );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call <code>emp.resprio_update_apply</code>
|
||||
*/
|
||||
@Override
|
||||
public boolean applyPriorityUpdate( )
|
||||
{
|
||||
return (Boolean) this.fResprioUpdateApply.execute( ).get( "_result" );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call <code>emp.technology_implement</code>
|
||||
*/
|
||||
@Override
|
||||
public boolean implement( int empire , String technology )
|
||||
{
|
||||
return (Boolean) this.fTechnologyImplement.execute( empire , technology ).get( "_result" );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
package com.deepclone.lw.beans.game.technologies;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.deepclone.lw.cmd.player.gdata.GamePageData;
|
||||
import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
|
||||
import com.deepclone.lw.cmd.player.tech.GetResearchResponse;
|
||||
import com.deepclone.lw.interfaces.game.EmpireManagement;
|
||||
import com.deepclone.lw.interfaces.game.technologies.PlayerTechnologiesDAO;
|
||||
import com.deepclone.lw.interfaces.game.technologies.ResearchController;
|
||||
import com.deepclone.lw.interfaces.i18n.TranslationException;
|
||||
import com.deepclone.lw.interfaces.i18n.Translator;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Research control component
|
||||
*
|
||||
* <p>
|
||||
* This component implements all actions allowing a player to view and update its empire's research
|
||||
* state.
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
@Transactional
|
||||
class ResearchControllerBean
|
||||
implements ResearchController
|
||||
{
|
||||
/** Main empire management component */
|
||||
private EmpireManagement empireManagement;
|
||||
|
||||
/** String translator */
|
||||
private Translator translator;
|
||||
|
||||
/** Data access object for technologies */
|
||||
private PlayerTechnologiesDAO playerTechnologiesDAO;
|
||||
|
||||
|
||||
/**
|
||||
* Dependency injector that sets the empire management component
|
||||
*
|
||||
* @param empireManagement
|
||||
* the empire management component
|
||||
*/
|
||||
@Autowired( required = true )
|
||||
public void setEmpireManagement( EmpireManagement empireManagement )
|
||||
{
|
||||
this.empireManagement = empireManagement;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dependency injector that sets the translation component
|
||||
*
|
||||
* @param translator
|
||||
* the translation component
|
||||
*/
|
||||
@Autowired( required = true )
|
||||
public void setTranslator( Translator translator )
|
||||
{
|
||||
this.translator = translator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dependency injector that sets the data access object for technologies
|
||||
*
|
||||
* @param playerTechnologiesDAO
|
||||
* the data access object for technologies
|
||||
*/
|
||||
@Autowired( required = true )
|
||||
public void setPlayerTechnologiesDAO( PlayerTechnologiesDAO playerTechnologiesDAO )
|
||||
{
|
||||
this.playerTechnologiesDAO = playerTechnologiesDAO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the raw research data from the database, then handle translation and dependencies
|
||||
*
|
||||
* <p>
|
||||
* In order to generate the response, this method fetches the raw research state information
|
||||
* from the database. It then proceeds with translating all categories, names and descriptions,
|
||||
* then adds reverse dependency information to all loaded technologies.
|
||||
*/
|
||||
@Override
|
||||
public GetResearchResponse getResearchData( int empire )
|
||||
{
|
||||
GamePageData pageData = this.empireManagement.getGeneralInformation( empire );
|
||||
List< ResearchData > technologies = this.playerTechnologiesDAO.getResearchData( empire );
|
||||
|
||||
// Translate categories, names and descriptions
|
||||
Map< String , String > translations = this.getTranslationsFor( technologies , pageData.getLanguage( ) );
|
||||
Map< String , ResearchData > byId = new HashMap< String , ResearchData >( );
|
||||
for ( ResearchData tech : technologies ) {
|
||||
byId.put( tech.getIdentifier( ) , tech );
|
||||
tech.setCategory( translations.get( tech.getCategory( ) ) );
|
||||
if ( tech.getName( ) != null ) {
|
||||
tech.setName( translations.get( tech.getName( ) ) );
|
||||
tech.setDescription( translations.get( tech.getDescription( ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Add reverse dependency identifiers
|
||||
for ( ResearchData tech : technologies ) {
|
||||
for ( String dependency : tech.getDependencies( ) ) {
|
||||
byId.get( dependency ).addReverseDependency( tech.getIdentifier( ) );
|
||||
}
|
||||
}
|
||||
|
||||
return new GetResearchResponse( pageData , technologies );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get translations used by a list of raw research entries
|
||||
*
|
||||
* <p>
|
||||
* This method is fed the raw research state data from the player technologies data access
|
||||
* object. It generates a set of string identifiers which contains all categories, names and
|
||||
* descriptions, then fetches these strings' translations.
|
||||
*
|
||||
* @param technologies
|
||||
* the research state data from the DAO
|
||||
* @param language
|
||||
* the player's selected language
|
||||
*
|
||||
* @return the map of string identifiers to string contents
|
||||
*/
|
||||
private Map< String , String > getTranslationsFor( List< ResearchData > technologies , String language )
|
||||
{
|
||||
Set< String > identifiers = new HashSet< String >( );
|
||||
for ( ResearchData tech : technologies ) {
|
||||
identifiers.add( tech.getCategory( ) );
|
||||
if ( tech.getName( ) != null ) {
|
||||
identifiers.add( tech.getName( ) );
|
||||
identifiers.add( tech.getDescription( ) );
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return this.translator.translate( language , identifiers );
|
||||
} catch ( TranslationException e ) {
|
||||
throw new RuntimeException( "error while translating technology-related data" , e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update research priorities
|
||||
*
|
||||
* <p>
|
||||
* This method will start a research priority update for the specified empire, then upload each
|
||||
* value in the map to the database. Finally, it will try to apply the update.
|
||||
*
|
||||
* <p>
|
||||
* If any of the above steps fail, the method will abort.
|
||||
*/
|
||||
@Override
|
||||
public boolean updatePriorities( int empire , Map< String , Integer > priorities )
|
||||
{
|
||||
if ( !this.playerTechnologiesDAO.startPriorityUpdate( empire ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( Map.Entry< String , Integer > entry : priorities.entrySet( ) ) {
|
||||
if ( !this.playerTechnologiesDAO.uploadResearchPriority( entry.getKey( ) , entry.getValue( ) ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return this.playerTechnologiesDAO.applyPriorityUpdate( );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implement a technology
|
||||
*
|
||||
* <p>
|
||||
* Call the DAO's technology implementation method in order to access the corresponding stored
|
||||
* procedure.
|
||||
*/
|
||||
@Override
|
||||
public boolean implement( int empire , String technology )
|
||||
{
|
||||
return this.playerTechnologiesDAO.implement( empire , technology );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.deepclone.lw.beans.game.technologies;
|
||||
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.postgresql.util.PGobject;
|
||||
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Row mapper for empire research state entries
|
||||
*
|
||||
* <p>
|
||||
* This class is responsible for converting empire research state information rows into instances of
|
||||
* the corresponding class, {@link ResearchData}. The instances it produces are "raw": they contain
|
||||
* string identifiers instead of translations, and their reverse dependencies are not set.
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*
|
||||
*/
|
||||
class ResearchRowMapper
|
||||
implements RowMapper< ResearchData >
|
||||
{
|
||||
|
||||
/**
|
||||
* Map a row from <code>emp.technologies_view</code>
|
||||
*
|
||||
* <p>
|
||||
* This method maps a single row from the <code>emp.technologies_view</code> view into a
|
||||
* {@link ResearchData} instance.
|
||||
*/
|
||||
@Override
|
||||
public ResearchData mapRow( ResultSet rs , int rowNum )
|
||||
throws SQLException
|
||||
{
|
||||
ResearchData output = new ResearchData( );
|
||||
|
||||
output.setIdentifier( rs.getString( "emptech_id" ) );
|
||||
output.setCategory( rs.getString( "technology_category" ) );
|
||||
|
||||
if ( rs.getBoolean( "emptech_visible" ) ) {
|
||||
output.setName( rs.getString( "technology_name" ) );
|
||||
output.setDescription( rs.getString( "technology_description" ) );
|
||||
output.setPrice( rs.getLong( "technology_price" ) );
|
||||
}
|
||||
|
||||
int ratio = rs.getInt( "emptech_ratio" );
|
||||
if ( rs.wasNull( ) ) {
|
||||
String state = ( (PGobject) rs.getObject( "emptech_state" ) ).getValue( );
|
||||
output.setImplemented( "KNOWN".equals( state ) );
|
||||
} else {
|
||||
output.setCompletion( ratio );
|
||||
output.setPriority( rs.getInt( "emptech_priority" ) );
|
||||
}
|
||||
|
||||
String dependencies = rs.getString( "technology_dependencies" );
|
||||
if ( ! "".equals( dependencies ) ) {
|
||||
output.setDependencies( dependencies.split( "," ) );
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?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="playerTechnologiesDAO" class="com.deepclone.lw.beans.game.technologies.PlayerTechnologiesDAOBean" />
|
||||
<bean id="reesearchController" class="com.deepclone.lw.beans.game.technologies.ResearchControllerBean" />
|
||||
|
||||
</beans>
|
|
@ -1,56 +0,0 @@
|
|||
package com.deepclone.lw.beans.user.player.game;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
|
||||
import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
|
||||
import com.deepclone.lw.beans.user.player.GameSubTypeBean;
|
||||
import com.deepclone.lw.cmd.player.ImplementTechCommand;
|
||||
import com.deepclone.lw.interfaces.game.EmpireManagement;
|
||||
import com.deepclone.lw.interfaces.session.ServerSession;
|
||||
import com.deepclone.lw.session.Command;
|
||||
import com.deepclone.lw.session.CommandResponse;
|
||||
|
||||
|
||||
|
||||
public class ImplementTechCommandDelegateBean
|
||||
implements AutowiredCommandDelegate
|
||||
|
||||
{
|
||||
|
||||
private EmpireManagement empireManagement;
|
||||
|
||||
|
||||
@Autowired( required = true )
|
||||
public void setEmpireManager( EmpireManagement manager )
|
||||
{
|
||||
this.empireManagement = manager;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class< ? extends Command > getType( )
|
||||
{
|
||||
return ImplementTechCommand.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class< ? extends SessionCommandHandler > getCommandHandler( )
|
||||
{
|
||||
return GameSubTypeBean.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CommandResponse execute( ServerSession session , Command cParam )
|
||||
{
|
||||
ImplementTechCommand command = (ImplementTechCommand) cParam;
|
||||
int empireId = session.get( "empireId" , Integer.class );
|
||||
if ( session.get( "vacation" , Boolean.class ) ) {
|
||||
return this.empireManagement.getOverview( empireId );
|
||||
}
|
||||
return this.empireManagement.implementTechnology( empireId , command.getTech( ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.deepclone.lw.beans.user.player.game.tech;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
|
||||
import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
|
||||
import com.deepclone.lw.beans.user.player.GameSubTypeBean;
|
||||
import com.deepclone.lw.cmd.player.tech.GetResearchCommand;
|
||||
import com.deepclone.lw.interfaces.game.technologies.ResearchController;
|
||||
import com.deepclone.lw.interfaces.session.ServerSession;
|
||||
import com.deepclone.lw.session.Command;
|
||||
import com.deepclone.lw.session.CommandResponse;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Command delegate for {@link GetResearchCommand}
|
||||
*
|
||||
* <p>
|
||||
* This command delegate uses the {@link ResearchController} to obtain all information pertaining to
|
||||
* an empire's research.
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
class GetResearchCommandDelegateBean
|
||||
implements AutowiredCommandDelegate
|
||||
{
|
||||
/** The research controller */
|
||||
private ResearchController researchController;
|
||||
|
||||
|
||||
/**
|
||||
* Dependency injector that sets the research controller
|
||||
*
|
||||
* @param researchController
|
||||
* the research controller
|
||||
*/
|
||||
@Autowired
|
||||
public void setResearchController( ResearchController researchController )
|
||||
{
|
||||
this.researchController = researchController;
|
||||
}
|
||||
|
||||
|
||||
/** This delegate handles {@link GetResearchCommand} instances */
|
||||
@Override
|
||||
public Class< ? extends Command > getType( )
|
||||
{
|
||||
return GetResearchCommand.class;
|
||||
}
|
||||
|
||||
|
||||
/** This delegate is part of the game session sub-type */
|
||||
@Override
|
||||
public Class< ? extends SessionCommandHandler > getCommandHandler( )
|
||||
{
|
||||
return GameSubTypeBean.class;
|
||||
}
|
||||
|
||||
|
||||
/** When the command is executed, fetch relevant data from the research controller */
|
||||
@Override
|
||||
public CommandResponse execute( ServerSession session , Command command )
|
||||
{
|
||||
int empire = session.get( "empireId" , Integer.class );
|
||||
return this.researchController.getResearchData( empire );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.deepclone.lw.beans.user.player.game.tech;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
|
||||
import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
|
||||
import com.deepclone.lw.beans.user.player.GameSubTypeBean;
|
||||
import com.deepclone.lw.cmd.player.tech.ImplementTechCommand;
|
||||
import com.deepclone.lw.interfaces.game.technologies.ResearchController;
|
||||
import com.deepclone.lw.interfaces.session.ServerSession;
|
||||
import com.deepclone.lw.session.Command;
|
||||
import com.deepclone.lw.session.CommandResponse;
|
||||
import com.deepclone.lw.session.NullResponse;
|
||||
|
||||
|
||||
|
||||
public class ImplementTechCommandDelegateBean
|
||||
implements AutowiredCommandDelegate
|
||||
|
||||
{
|
||||
/** The research controller */
|
||||
private ResearchController researchController;
|
||||
|
||||
|
||||
/**
|
||||
* Dependency injector that sets the research controller
|
||||
*
|
||||
* @param researchController
|
||||
* the research controller
|
||||
*/
|
||||
@Autowired( required = true )
|
||||
public void setResearchController( ResearchController researchController )
|
||||
{
|
||||
this.researchController = researchController;
|
||||
}
|
||||
|
||||
|
||||
/** This class handles {@link ImplementTechCommand} instances */
|
||||
@Override
|
||||
public Class< ? extends Command > getType( )
|
||||
{
|
||||
return ImplementTechCommand.class;
|
||||
}
|
||||
|
||||
|
||||
/** This class is enabled for the {@link GameSubTypeBean} session type */
|
||||
@Override
|
||||
public Class< ? extends SessionCommandHandler > getCommandHandler( )
|
||||
{
|
||||
return GameSubTypeBean.class;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implement a technology
|
||||
*
|
||||
* <p>
|
||||
* If the empire is not in vacation mode, try to implement the technology. Always return a
|
||||
* {@link NullResponse}.
|
||||
*/
|
||||
@Override
|
||||
public CommandResponse execute( ServerSession session , Command cParam )
|
||||
{
|
||||
ImplementTechCommand command = (ImplementTechCommand) cParam;
|
||||
int empire = session.get( "empireId" , Integer.class );
|
||||
if ( !session.get( "vacation" , Boolean.class ) ) {
|
||||
this.researchController.implement( empire , command.getTech( ) );
|
||||
}
|
||||
return new NullResponse( );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package com.deepclone.lw.beans.user.player.game.tech;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
|
||||
import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
|
||||
import com.deepclone.lw.beans.user.player.GameSubTypeBean;
|
||||
import com.deepclone.lw.cmd.player.tech.UpdateResearchPrioritiesCommand;
|
||||
import com.deepclone.lw.interfaces.game.technologies.ResearchController;
|
||||
import com.deepclone.lw.interfaces.session.ServerSession;
|
||||
import com.deepclone.lw.session.Command;
|
||||
import com.deepclone.lw.session.CommandResponse;
|
||||
import com.deepclone.lw.session.NullResponse;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Command handler for research priority updates
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
class UpdateResearchPrioritiesCommandDelegateBean
|
||||
implements AutowiredCommandDelegate
|
||||
{
|
||||
/** The research controller */
|
||||
private ResearchController researchController;
|
||||
|
||||
|
||||
/**
|
||||
* Dependency injector that sets the research controller
|
||||
*
|
||||
* @param researchController
|
||||
* the research controller
|
||||
*/
|
||||
@Autowired( required = true )
|
||||
public void setResearchController( ResearchController researchController )
|
||||
{
|
||||
this.researchController = researchController;
|
||||
}
|
||||
|
||||
|
||||
/** This class handles {@link UpdateResearchPrioritiesCommand} instances */
|
||||
@Override
|
||||
public Class< ? extends Command > getType( )
|
||||
{
|
||||
return UpdateResearchPrioritiesCommand.class;
|
||||
}
|
||||
|
||||
|
||||
/** This class is enabled for the {@link GameSubTypeBean} session type */
|
||||
@Override
|
||||
public Class< ? extends SessionCommandHandler > getCommandHandler( )
|
||||
{
|
||||
return GameSubTypeBean.class;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update research priorities
|
||||
*
|
||||
* <p>
|
||||
* If the empire is not in vacation mode, access the research controller and update mining
|
||||
* priorities using the specified values. Return a {@link NullResponse} in all cases.
|
||||
*/
|
||||
@Override
|
||||
public CommandResponse execute( ServerSession session , Command command )
|
||||
{
|
||||
if ( !session.get( "vacation" , Boolean.class ) ) {
|
||||
int empireId = session.get( "empireId" , Integer.class );
|
||||
this.researchController.updatePriorities( empireId ,
|
||||
( (UpdateResearchPrioritiesCommand) command ).getPriorities( ) );
|
||||
}
|
||||
return new NullResponse( );
|
||||
}
|
||||
|
||||
}
|
|
@ -44,9 +44,13 @@
|
|||
|
||||
<!-- Game: empire -->
|
||||
<bean class="com.deepclone.lw.beans.user.player.game.OverviewCommandDelegateBean" />
|
||||
<bean class="com.deepclone.lw.beans.user.player.game.ImplementTechCommandDelegateBean" />
|
||||
<bean class="com.deepclone.lw.beans.user.player.game.tech.ImplementTechCommandDelegateBean" />
|
||||
<bean class="com.deepclone.lw.beans.user.player.game.UpdateEmpireMiningSettingsCommandDelegateBean" />
|
||||
<bean class="com.deepclone.lw.beans.user.player.game.GetNewPlanetCommandDelegateBean" />
|
||||
|
||||
<!-- Game: research -->
|
||||
<bean class="com.deepclone.lw.beans.user.player.game.tech.GetResearchCommandDelegateBean" />
|
||||
<bean class="com.deepclone.lw.beans.user.player.game.tech.UpdateResearchPrioritiesCommandDelegateBean" />
|
||||
|
||||
<!-- Game: planet list -->
|
||||
<bean class="com.deepclone.lw.beans.user.player.game.ListPlanetsCommandDelegateBean" />
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
<module>../legacyworlds-server-beans-resources</module>
|
||||
<module>../legacyworlds-server-beans-simple</module>
|
||||
<module>../legacyworlds-server-beans-system</module>
|
||||
<module>../legacyworlds-server-beans-technologies</module>
|
||||
<module>../legacyworlds-server-beans-updates</module>
|
||||
<module>../legacyworlds-server-beans-user</module>
|
||||
</modules>
|
||||
|
|
|
@ -134,6 +134,10 @@ REVOKE EXECUTE
|
|||
ON FUNCTION emp.technology_make_identifier( INT , TEXT , BOOLEAN )
|
||||
FROM PUBLIC;
|
||||
|
||||
GRANT EXECUTE
|
||||
ON FUNCTION emp.technology_make_identifier( INT , TEXT , BOOLEAN )
|
||||
TO :dbuser;
|
||||
|
||||
|
||||
/*
|
||||
* Initialise a research priorities update
|
||||
|
|
|
@ -23,9 +23,6 @@ public interface EmpireDAO
|
|||
public OverviewData getOverview( int empireId );
|
||||
|
||||
|
||||
public void implementTechnology( int empireId , int lineId );
|
||||
|
||||
|
||||
public List< PlanetListData > getPlanetList( int empireId );
|
||||
|
||||
|
||||
|
|
|
@ -22,9 +22,6 @@ public interface EmpireManagement
|
|||
public EmpireResponse getOverview( int empireId );
|
||||
|
||||
|
||||
public EmpireResponse implementTechnology( int empireId , int techId );
|
||||
|
||||
|
||||
public ListPlanetsResponse getPlanetList( int empireId );
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package com.deepclone.lw.interfaces.game.technologies;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Player-oriented data access interface for technologies
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
public interface PlayerTechnologiesDAO
|
||||
{
|
||||
|
||||
/**
|
||||
* Obtain the list of technologies for an empire
|
||||
*
|
||||
* <p>
|
||||
* Query the database for technology entries as seen from an empire's perspective. The
|
||||
* technologies will be returned with I18N string identifiers for categories, names and
|
||||
* descriptions (unless the details are not available).
|
||||
*
|
||||
* @param empire
|
||||
* the empire's identifier
|
||||
*
|
||||
* @return the list of technology entries
|
||||
*/
|
||||
public List< ResearchData > getResearchData( int empire );
|
||||
|
||||
|
||||
/**
|
||||
* Start a research priority update
|
||||
*
|
||||
* <p>
|
||||
* This method initialises a research priorities update by calling the appropriate stored
|
||||
* procedure.
|
||||
*
|
||||
* @param empire
|
||||
* the empire for which an update is being performed
|
||||
*
|
||||
* @return <code>true</code> on success, <code>false</code> on failure
|
||||
*/
|
||||
public boolean startPriorityUpdate( int empire );
|
||||
|
||||
|
||||
/**
|
||||
* Upload a single research priority
|
||||
*
|
||||
* <p>
|
||||
* This method uploads the priority for one of the in-progress research items. It must be called
|
||||
* only after a research priority update has been initiated.
|
||||
*
|
||||
* @param identifier
|
||||
* the technology's identifier
|
||||
* @param priority
|
||||
* the research priority
|
||||
*
|
||||
* @return <code>true</code> on success, <code>false</code> on failure
|
||||
*/
|
||||
public boolean uploadResearchPriority( String identifier , int priority );
|
||||
|
||||
|
||||
/**
|
||||
* Apply an in-progress research priority update
|
||||
*
|
||||
* <p>
|
||||
* This method applies a previously uploaded set of research priority updates.
|
||||
*
|
||||
* @return <code>true</code> on success, <code>false</code> on failure
|
||||
*/
|
||||
public boolean applyPriorityUpdate( );
|
||||
|
||||
|
||||
/**
|
||||
* Implement a technology
|
||||
*
|
||||
* <p>
|
||||
* This method calls the stored procedure which causes an empire to implement a technology.
|
||||
*
|
||||
* @param empire
|
||||
* the empire's identifier
|
||||
* @param technology
|
||||
* the technology's identifier
|
||||
*
|
||||
* @return <code>true</code> on success, <code>false</code> on failure
|
||||
*/
|
||||
public boolean implement( int empire , String technology );
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.deepclone.lw.interfaces.game.technologies;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.deepclone.lw.cmd.player.tech.GetResearchCommand;
|
||||
import com.deepclone.lw.cmd.player.tech.GetResearchResponse;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Research control interface
|
||||
*
|
||||
* <p>
|
||||
* This interface is implemented by the component which allows empires (and therefore players) to
|
||||
* view the research state and control it.
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
public interface ResearchController
|
||||
{
|
||||
|
||||
/**
|
||||
* Obtain the state of an empire's research
|
||||
*
|
||||
* <p>
|
||||
* This method must be overridden to generate the response to a {@link GetResearchCommand}.
|
||||
*
|
||||
* @param empire
|
||||
* the empire's identifier
|
||||
*
|
||||
* @return the appropriate {@link GetResearchResponse} instance
|
||||
*/
|
||||
public GetResearchResponse getResearchData( int empire );
|
||||
|
||||
|
||||
/**
|
||||
* Update research priorities
|
||||
*
|
||||
* <p>
|
||||
* This method must be implemented so it updates research priorities for an empire.
|
||||
*
|
||||
* @param empire
|
||||
* the empire to update
|
||||
* @param priorities
|
||||
* the new research priorities, as a map associating technology identifiers to
|
||||
* priority values
|
||||
*
|
||||
* @return <code>true</code> on success, <code>false</code> otherwise
|
||||
*/
|
||||
public boolean updatePriorities( int empire , Map< String , Integer > priorities );
|
||||
|
||||
|
||||
/**
|
||||
* Implement a technology
|
||||
*
|
||||
* <p>
|
||||
* This method implements a technology which has been fully researched.
|
||||
*
|
||||
* @param empire
|
||||
* the empire trying to implement a technology
|
||||
* @param technology
|
||||
* the technology's identifier
|
||||
*
|
||||
* @return <code>true</code> on success, <code>false</code> otherwise
|
||||
*/
|
||||
public boolean implement( int empire , String technology );
|
||||
|
||||
}
|
|
@ -50,6 +50,10 @@
|
|||
<artifactId>legacyworlds-server-beans-system</artifactId>
|
||||
<groupId>com.deepclone.lw</groupId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>legacyworlds-server-beans-technologies</artifactId>
|
||||
<groupId>com.deepclone.lw</groupId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>legacyworlds-server-beans-updates</artifactId>
|
||||
<groupId>com.deepclone.lw</groupId>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<!-- Spring configuration loader for all "real" game components -->
|
||||
<!-- ========================================================== -->
|
||||
<import resource="game/resources.xml" />
|
||||
<import resource="game/technologies.xml" />
|
||||
<import resource="game/updates.xml" />
|
||||
|
||||
</beans>
|
|
@ -1,28 +0,0 @@
|
|||
package com.deepclone.lw.cmd.player;
|
||||
|
||||
|
||||
import com.deepclone.lw.session.Command;
|
||||
|
||||
|
||||
|
||||
public class ImplementTechCommand
|
||||
extends Command
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int tech;
|
||||
|
||||
|
||||
public ImplementTechCommand( int tech )
|
||||
{
|
||||
this.tech = tech;
|
||||
}
|
||||
|
||||
|
||||
public int getTech( )
|
||||
{
|
||||
return tech;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,373 @@
|
|||
package com.deepclone.lw.cmd.player.gdata.empire;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An entry from the research page
|
||||
*
|
||||
* <p>
|
||||
* This class represents entries from the research page. It is capable of representing in-progress
|
||||
* research (with or without details), as well as pending and implemented technologies.
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
public class ResearchData
|
||||
implements Serializable , Comparable< ResearchData >
|
||||
{
|
||||
|
||||
/**
|
||||
* The serialisation version identifier
|
||||
*
|
||||
* <ul>
|
||||
* <li>Introduced in B6M2 with ID 1
|
||||
* </ul>
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** The identifier of the technology */
|
||||
private String identifier;
|
||||
|
||||
/** The category the technology belongs to */
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* The translated name of the technology, or <code>null</code> if the technology is being
|
||||
* researched and progress is insufficient to display details.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The description of the technology, or <code>null</code> if the technology is being researched
|
||||
* and progress is insufficient to display details.
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* The implementation price of the technology, or <code>null</code> if the technology is being
|
||||
* researched and progress is insufficient to display details.
|
||||
*/
|
||||
private Long price;
|
||||
|
||||
/**
|
||||
* The completion percentage of the technology, or <code>null</code> if the technology has been
|
||||
* fully researched.
|
||||
*/
|
||||
private Integer completion;
|
||||
|
||||
/**
|
||||
* Priority of the research on this technology, or <code>null</code> if the technology is not
|
||||
* being researched.
|
||||
*/
|
||||
private Integer priority;
|
||||
|
||||
/**
|
||||
* Whether the technology is being researched (<code>null</code>), pending implementation (
|
||||
* <code>false</code>) or implemented (<code>true</code>).
|
||||
*/
|
||||
private Boolean implemented;
|
||||
|
||||
/** List of identifiers of technologies the current technology depends on. */
|
||||
private List< String > dependencies = new ArrayList< String >( );
|
||||
|
||||
/** List of identifiers of technologies that depend on the current technology. */
|
||||
private List< String > revDependencies = new LinkedList< String >( );
|
||||
|
||||
|
||||
/**
|
||||
* Gets the identifier of the technology.
|
||||
*
|
||||
* @return the identifier of the technology
|
||||
*/
|
||||
public String getIdentifier( )
|
||||
{
|
||||
return this.identifier;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the identifier of the technology.
|
||||
*
|
||||
* @param identifier
|
||||
* the new identifier of the technology
|
||||
*/
|
||||
public void setIdentifier( String identifier )
|
||||
{
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the category the technology belongs to.
|
||||
*
|
||||
* @return the category the technology belongs to
|
||||
*/
|
||||
public String getCategory( )
|
||||
{
|
||||
return this.category;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the category the technology belongs to.
|
||||
*
|
||||
* @param category
|
||||
* the new category the technology belongs to
|
||||
*/
|
||||
public void setCategory( String category )
|
||||
{
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the translated name of the technology
|
||||
*
|
||||
* @return the translated name of the technology, or <code>null</code> if the technology is
|
||||
* being researched and progress is insufficient to display details
|
||||
*/
|
||||
public String getName( )
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the translated name of the technology
|
||||
*
|
||||
* @param name
|
||||
* the new translated name of the technology
|
||||
*/
|
||||
public void setName( String name )
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the description of the technology
|
||||
*
|
||||
* @return the description of the technology, or <code>null</code> if the technology is being
|
||||
* researched and progress is insufficient to display details
|
||||
*/
|
||||
public String getDescription( )
|
||||
{
|
||||
return this.description;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the description of the technology
|
||||
*
|
||||
* @param description
|
||||
* the new description of the technology
|
||||
*/
|
||||
public void setDescription( String description )
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the implementation price of the technology
|
||||
*
|
||||
* @return the implementation price of the technology, or <code>null</code> if the technology is
|
||||
* being researched and progress is insufficient to display details
|
||||
*/
|
||||
public Long getPrice( )
|
||||
{
|
||||
return this.price;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the implementation price of the technology
|
||||
*
|
||||
* @param price
|
||||
* the new implementation price of the technology
|
||||
*/
|
||||
public void setPrice( Long price )
|
||||
{
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the completion percentage of the technology.
|
||||
*
|
||||
* @return the completion percentage of the technology, or <code>null</code> if the technology
|
||||
* has been fully researched
|
||||
*/
|
||||
public Integer getCompletion( )
|
||||
{
|
||||
return this.completion;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the completion percentage of the technology.
|
||||
*
|
||||
* @param completion
|
||||
* the new completion percentage of the technology
|
||||
*/
|
||||
public void setCompletion( Integer completion )
|
||||
{
|
||||
this.completion = completion;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the priority of the research on this technology
|
||||
*
|
||||
* @return the priority of the research on this technology, or <code>null</code> if the
|
||||
* technology is not being researched
|
||||
*/
|
||||
public Integer getPriority( )
|
||||
{
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the priority of the research on this technology.
|
||||
*
|
||||
* @param priority
|
||||
* the new priority of the research on this technology
|
||||
*/
|
||||
public void setPriority( Integer priority )
|
||||
{
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether the technology is being researched (<code>null</code>), pending implementation (
|
||||
* <code>false</code>) or implemented (<code>true</code>).
|
||||
*
|
||||
* @return whether the technology is being researched (<code>null</code>), pending
|
||||
* implementation ( <code>false</code>) or implemented (<code>true</code>)
|
||||
*/
|
||||
public Boolean getImplemented( )
|
||||
{
|
||||
return this.implemented;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether the technology is being researched (<code>null</code>), pending implementation (
|
||||
* <code>false</code>) or implemented (<code>true</code>).
|
||||
*
|
||||
* @param implemented
|
||||
* whether the technology is being researched (<code>null</code>), pending
|
||||
* implementation ( <code>false</code>) or implemented (<code>true</code>)
|
||||
*/
|
||||
public void setImplemented( Boolean implemented )
|
||||
{
|
||||
this.implemented = implemented;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the list of dependencies
|
||||
*
|
||||
* @return the list of dependencies
|
||||
*/
|
||||
public List< String > getDependencies( )
|
||||
{
|
||||
return Collections.unmodifiableList( this.dependencies );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the list of dependencies
|
||||
*
|
||||
* @param dependencies
|
||||
* the new list of dependencies
|
||||
*/
|
||||
public void setDependencies( String[] dependencies )
|
||||
{
|
||||
this.dependencies = Arrays.asList( dependencies );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the list of reverse dependencies
|
||||
*
|
||||
* @return the list of reverse dependencies
|
||||
*/
|
||||
public List< String > getReverseDependencies( )
|
||||
{
|
||||
return this.revDependencies;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a reverse dependency
|
||||
*
|
||||
* @param identifier
|
||||
* the identifier of the reverse dependency
|
||||
*/
|
||||
public void addReverseDependency( String identifier )
|
||||
{
|
||||
this.revDependencies.add( identifier );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Research page entry comparison
|
||||
*
|
||||
* <p>
|
||||
* This method compares research entries based on:
|
||||
* <ul>
|
||||
* <li>The entries' states (in progress, pending implementation, implemented),
|
||||
* <li>For in-progress entries, their current completion ratio,
|
||||
* <li>The entries' names
|
||||
* </ul>
|
||||
*
|
||||
* @param other
|
||||
* the entry to compare to
|
||||
*
|
||||
* @return 1 if the current entry is "bigger", -1 if it is "smaller", and 0 if both entries are
|
||||
* equal
|
||||
*/
|
||||
@Override
|
||||
public int compareTo( ResearchData other )
|
||||
{
|
||||
if ( other == null ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( this.implemented == null && other.implemented != null ) {
|
||||
return -1;
|
||||
}
|
||||
if ( other.implemented == null && this.implemented != null ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( this.implemented != null ) {
|
||||
if ( this.implemented && !other.implemented ) {
|
||||
return 1;
|
||||
}
|
||||
if ( other.implemented && !this.implemented ) {
|
||||
return -1;
|
||||
}
|
||||
return this.name.compareTo( other.name );
|
||||
}
|
||||
|
||||
if ( this.completion != other.completion ) {
|
||||
return other.completion - this.completion;
|
||||
}
|
||||
if ( this.name == null ) {
|
||||
return other.name == null ? 0 : -1;
|
||||
}
|
||||
return this.name.compareTo( other.name );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.deepclone.lw.cmd.player.tech;
|
||||
|
||||
|
||||
import com.deepclone.lw.session.Command;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Command that obtains the current research & technology data
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
public class GetResearchCommand
|
||||
extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The serialisation version identifier
|
||||
*
|
||||
* <ul>
|
||||
* <li>Introduced in B6M2 with ID 1
|
||||
* </ul>
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.deepclone.lw.cmd.player.tech;
|
||||
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.deepclone.lw.cmd.player.gdata.GamePageData;
|
||||
import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
|
||||
import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Response that lists all research entries (sent by the server in response to
|
||||
* {@link GetResearchCommand})
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
public class GetResearchResponse
|
||||
extends GameResponseBase
|
||||
{
|
||||
|
||||
/**
|
||||
* The serialisation version identifier
|
||||
*
|
||||
* <ul>
|
||||
* <li>Introduced in B6M2 with ID 1
|
||||
* </ul>
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Sorted list of research entries */
|
||||
private final List< ResearchData > researchData;
|
||||
|
||||
|
||||
/**
|
||||
* Initialise the response
|
||||
*
|
||||
* <p>
|
||||
* Copy and sort the list of research entries
|
||||
*
|
||||
* @param page
|
||||
* the common page information
|
||||
* @param technologies
|
||||
* the list of research entries
|
||||
*/
|
||||
public GetResearchResponse( GamePageData page , List< ResearchData > technologies )
|
||||
{
|
||||
super( page );
|
||||
this.researchData = new LinkedList< ResearchData >( technologies );
|
||||
Collections.sort( this.researchData );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the list of research entries
|
||||
*
|
||||
* @return the sorted list of research entries
|
||||
*/
|
||||
public List< ResearchData > getResearchData( )
|
||||
{
|
||||
return this.researchData;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.deepclone.lw.cmd.player.tech;
|
||||
|
||||
|
||||
import com.deepclone.lw.session.Command;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Technology implementation command
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
public class ImplementTechCommand
|
||||
extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The 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;
|
||||
|
||||
/** Identifier of the technology to implement */
|
||||
private final String tech;
|
||||
|
||||
|
||||
/**
|
||||
* Initialise the command
|
||||
*
|
||||
* @param tech
|
||||
* the identifier of the technology to implement
|
||||
*/
|
||||
public ImplementTechCommand( String tech )
|
||||
{
|
||||
this.tech = tech;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the identifier of the technology to implement
|
||||
*
|
||||
* @return the identifier of the technology to implement
|
||||
*/
|
||||
public String getTech( )
|
||||
{
|
||||
return this.tech;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.deepclone.lw.cmd.player.tech;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.deepclone.lw.session.Command;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Command that updates research priorities
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
public class UpdateResearchPrioritiesCommand
|
||||
extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* Serialisation version identifier
|
||||
*
|
||||
* <ul>
|
||||
* <li>Introduced in B6M2
|
||||
* </ul>
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** The new research priorities */
|
||||
private final Map< String , Integer > priorities;
|
||||
|
||||
|
||||
/**
|
||||
* Initialise the command using research priority values
|
||||
*
|
||||
* @param priorities
|
||||
* a map that associates technology identifiers to priorities
|
||||
*/
|
||||
public UpdateResearchPrioritiesCommand( Map< String , Integer > priorities )
|
||||
{
|
||||
this.priorities = priorities;
|
||||
}
|
||||
|
||||
|
||||
/** @return the new research priorities */
|
||||
public Map< String , Integer > getPriorities( )
|
||||
{
|
||||
return this.priorities;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,10 @@ import com.deepclone.lw.cmd.player.elist.*;
|
|||
import com.deepclone.lw.cmd.player.fleets.*;
|
||||
import com.deepclone.lw.cmd.player.gdata.*;
|
||||
import com.deepclone.lw.cmd.player.planets.*;
|
||||
import com.deepclone.lw.cmd.player.tech.GetResearchCommand;
|
||||
import com.deepclone.lw.cmd.player.tech.GetResearchResponse;
|
||||
import com.deepclone.lw.cmd.player.tech.ImplementTechCommand;
|
||||
import com.deepclone.lw.cmd.player.tech.UpdateResearchPrioritiesCommand;
|
||||
import com.deepclone.lw.cmd.player.msgs.*;
|
||||
import com.deepclone.lw.session.Command;
|
||||
import com.deepclone.lw.session.SessionException;
|
||||
|
@ -78,10 +82,41 @@ public class PlayerSession
|
|||
}
|
||||
|
||||
|
||||
public EmpireResponse implementTechnology( int technology )
|
||||
/**
|
||||
* Request research information
|
||||
*
|
||||
* @return the research information response
|
||||
*/
|
||||
public GetResearchResponse getResearch( )
|
||||
throws SessionException , SessionServerException , SessionMaintenanceException
|
||||
{
|
||||
return (EmpireResponse) this.execute( new ImplementTechCommand( technology ) );
|
||||
return (GetResearchResponse) this.execute( new GetResearchCommand( ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update research priorities
|
||||
*
|
||||
* @param priorities
|
||||
* the map of research identifiers to priority values
|
||||
*/
|
||||
public void updateResearchPriorities( Map< String , Integer > priorities )
|
||||
throws SessionException , SessionServerException , SessionMaintenanceException
|
||||
{
|
||||
this.execute( new UpdateResearchPrioritiesCommand( priorities ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implement a technology
|
||||
*
|
||||
* @param technology
|
||||
* the technology's identifier
|
||||
*/
|
||||
public void implementTechnology( String technology )
|
||||
throws SessionException , SessionServerException , SessionMaintenanceException
|
||||
{
|
||||
this.execute( new ImplementTechCommand( technology ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -618,4 +653,5 @@ public class PlayerSession
|
|||
{
|
||||
return (PostCommentResponse) this.execute( new PostCommentCommand( bugId , comment ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@
|
|||
<div class="button">
|
||||
<a href="map" title="Map of the universe">Map</a>
|
||||
</div>
|
||||
<div class="button">
|
||||
<a href="research" title="Manage research priorities, implement new technologies and browse known technologies">Research</a>
|
||||
</div>
|
||||
<div class="button">
|
||||
<a href="alliance" title="Alliance">Alliance</a>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<@page title="Empire">
|
||||
|
||||
<#assign ov = data.overview >
|
||||
<#assign rs = data.research >
|
||||
|
||||
<@tabs>
|
||||
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
<#--
|
||||
Macro that starts a research tab for one of the 3 existing modes
|
||||
|
||||
Parameters:
|
||||
curMode The tab to start: R for "in progress", P for pending, K for implemented
|
||||
-->
|
||||
<#macro startResearchTab curMode>
|
||||
<#switch curMode>
|
||||
|
||||
<#case 'R'>
|
||||
<@tabStart "research" "In progress" />
|
||||
<@rawFormStart "research-set-priorities" "form-priorities" "research" />
|
||||
<@listviewStart />
|
||||
<@lv_line headers=true>
|
||||
<@lv_column width=150>Category</@lv_column>
|
||||
<@lv_column width="x">Name</@lv_column>
|
||||
<@lv_column width=100 centered=true>Progress</@lv_column>
|
||||
<@lv_column width=150 centered=true>Priority</@lv_column>
|
||||
</@lv_line>
|
||||
<#break>
|
||||
|
||||
<#case 'P'>
|
||||
<@tabStart "pending" "Pending implementation" />
|
||||
<@listviewStart />
|
||||
<@lv_line headers=true>
|
||||
<@lv_column width=150>Category</@lv_column>
|
||||
<@lv_column width="x">Name</@lv_column>
|
||||
<@lv_column width=150 right=true>Cost</@lv_column>
|
||||
<@lv_column width=100 centered=true> </@lv_column>
|
||||
</@lv_line>
|
||||
<#break>
|
||||
|
||||
<#case 'K'>
|
||||
<@tabStart "implemented" "Implemented" />
|
||||
<@listviewStart />
|
||||
<@lv_line headers=true>
|
||||
<@lv_column width=150>Category</@lv_column>
|
||||
<@lv_column width="x">Name</@lv_column>
|
||||
</@lv_line>
|
||||
<#break>
|
||||
|
||||
</#switch>
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that finishes a research tab depending on its type
|
||||
|
||||
Parameters:
|
||||
mode The type of tab that is being closed
|
||||
-->
|
||||
<#macro endResearchTab mode>
|
||||
<#switch mode>
|
||||
|
||||
<#case 'R'>
|
||||
<@lv_line headers=true>
|
||||
<@lv_column width="x" colspan=4> </@lv_column>
|
||||
</@lv_line>
|
||||
<@lv_line>
|
||||
<@lv_column colspan=3> </@lv_column>
|
||||
<@lv_column centered=true>
|
||||
<input type="submit" value="Update" class="input" style="margin: 15px 0 0 0" />
|
||||
</@lv_column>
|
||||
</@lv_line>
|
||||
<@listviewEnd />
|
||||
</form>
|
||||
<#break>
|
||||
|
||||
<#case 'P'>
|
||||
<#case 'K'>
|
||||
<@listviewEnd />
|
||||
<#break>
|
||||
|
||||
</#switch>
|
||||
<@tabEnd />
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that renders an in-progress research entry
|
||||
|
||||
Parameters:
|
||||
entry the entry
|
||||
-->
|
||||
<#macro drawInProgressResearch entry>
|
||||
<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
|
||||
<@lv_column>${entry.category?xhtml}</@lv_column>
|
||||
<@lv_column>
|
||||
<#if entry.name?has_content>
|
||||
<strong>${entry.name?xhtml}</strong>
|
||||
<#else>
|
||||
Unknown technology
|
||||
</#if>
|
||||
</@lv_column>
|
||||
<@lv_column centered=true>${entry.completion} %</@lv_column>
|
||||
<@lv_column centered=true>
|
||||
<select name="rp-${entry.identifier?xhtml}" class="input">
|
||||
<option style="padding: 0 5px" value="0" <#if entry.priority = 0>selected="selected"</#if>>lowest</option>
|
||||
<option style="padding: 0 5px" value="1" <#if entry.priority = 1>selected="selected"</#if>>low</option>
|
||||
<option style="padding: 0 5px" value="2" <#if entry.priority = 2>selected="selected"</#if>>normal</option>
|
||||
<option style="padding: 0 5px" value="3" <#if entry.priority = 3>selected="selected"</#if>>high</option>
|
||||
<option style="padding: 0 5px" value="4" <#if entry.priority = 4>selected="selected"</#if>>highest</option>
|
||||
</select>
|
||||
</@lv_column>
|
||||
</@lv_line>
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that renders a pending technology
|
||||
|
||||
Parameters:
|
||||
entry the technology
|
||||
-->
|
||||
<#macro drawPendingTechnology entry>
|
||||
<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
|
||||
<@lv_column>${entry.category?xhtml}</@lv_column>
|
||||
<@lv_column>
|
||||
<strong>${entry.name?xhtml}</strong>
|
||||
</@lv_column>
|
||||
<@lv_column right=true>
|
||||
<strong>${entry.price?string(",##0")}</strong> <@abbr_bgc/>
|
||||
</@lv_column>
|
||||
<@lv_column right=true>
|
||||
<#if data.page.cash >= entry.price>
|
||||
<@rawFormStart "research-implement" "form-implement-${entry.identifier}" entry.identifier />
|
||||
<input type="hidden" name="technology" value="${entry.identifier?xhtml}" />
|
||||
<input type="submit" value="Implement" class="input" />
|
||||
</form>
|
||||
<#else>
|
||||
|
||||
</#if>
|
||||
</@lv_column>
|
||||
</@lv_line>
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that renders an implemented technology
|
||||
|
||||
Parameters:
|
||||
entry the technology
|
||||
-->
|
||||
<#macro drawImplementedTechnology entry>
|
||||
<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
|
||||
<@lv_column>${entry.category?xhtml}</@lv_column>
|
||||
<@lv_column>
|
||||
<strong>${entry.name?xhtml}</strong>
|
||||
</@lv_column>
|
||||
</@lv_line>
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that renders a single entry
|
||||
|
||||
Parameters:
|
||||
mode the current tab (see startResearchTab for details)
|
||||
entry the entry
|
||||
-->
|
||||
<#macro drawResearchEntry mode entry>
|
||||
<#switch mode>
|
||||
|
||||
<#case 'R'>
|
||||
<@drawInProgressResearch entry />
|
||||
<#break>
|
||||
|
||||
<#case 'P'>
|
||||
<@drawPendingTechnology entry />
|
||||
<#break>
|
||||
|
||||
<#case 'K'>
|
||||
<@drawImplementedTechnology entry />
|
||||
<#break>
|
||||
|
||||
</#switch>
|
||||
</#macro>
|
||||
<#--
|
||||
Render the visible part of the research page
|
||||
|
||||
Parameters:
|
||||
entries the sorted list of research entries
|
||||
-->
|
||||
<#macro renderResearchTabs entries>
|
||||
<#local prevMode = ''>
|
||||
|
||||
<@tabs>
|
||||
<#list entries as entry>
|
||||
|
||||
<#-- Determine type of entry to display -->
|
||||
<#if entry.implemented?has_content>
|
||||
<#if entry.implemented>
|
||||
<#local curMode = 'K'>
|
||||
<#else>
|
||||
<#local curMode = 'P'>
|
||||
</#if>
|
||||
<#else>
|
||||
<#local curMode = 'R'>
|
||||
</#if>
|
||||
|
||||
<#-- Start/end tabs -->
|
||||
<#if curMode != prevMode>
|
||||
<#if prevMode != ''>
|
||||
<@endResearchTab prevMode />
|
||||
</#if>
|
||||
<@startResearchTab curMode />
|
||||
<#local prevMode = curMode>
|
||||
</#if>
|
||||
|
||||
|
||||
<@drawResearchEntry curMode entry />
|
||||
|
||||
</#list>
|
||||
<@endResearchTab prevMode />
|
||||
</@tabs>
|
||||
</#macro>
|
||||
<#--
|
||||
Render all research information in a hidden layer which will be used by
|
||||
the client-side code to display more information.
|
||||
-->
|
||||
<#macro renderFullResearchData entries>
|
||||
<div style="display: none">
|
||||
<#list entries as tech>
|
||||
<div class="tech-description" id="tdesc-${tech.identifier?xhtml}">
|
||||
<h4><#if tech.name?has_content>${tech.name?xhtml}<#else>Unknown technology</#if></h4>
|
||||
<div class="tech-info"><strong>Category:</strong> ${tech.category?xhtml}</div>
|
||||
<#if tech.description?has_content><div class="tech-info">${tech.description?xhtml}</div></#if>
|
||||
<#if tech.price?has_content>
|
||||
<div class="tech-info"><strong>Implementation cost:</strong> ${tech.price?string(",##0")} <@abbr_bgc /></div>
|
||||
</#if>
|
||||
<#if tech.dependencies?has_content>
|
||||
<div class="tech-info"><strong>Depends on:</strong>
|
||||
<ul>
|
||||
<#list tech.dependencies as depId>
|
||||
<li class="dep">${depId}</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</div>
|
||||
</#if>
|
||||
<#if tech.reverseDependencies?has_content>
|
||||
<div class="tech-info"><strong>Required by:</strong>
|
||||
<ul>
|
||||
<#list tech.reverseDependencies as depId>
|
||||
<li class="dep">${depId}</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</#list>
|
||||
</div>
|
||||
<script type="text/javascript" charset="utf-8" src="js/research.js"></script>
|
||||
</#macro>
|
||||
<#--
|
||||
Main research page
|
||||
-->
|
||||
<#macro render>
|
||||
<@page title="Research">
|
||||
|
||||
<#local entries = data.researchData>
|
||||
<@renderResearchTabs entries />
|
||||
<@renderFullResearchData entries />
|
||||
|
||||
</@page>
|
||||
</#macro>
|
|
@ -63,11 +63,14 @@
|
|||
<div class="button">
|
||||
<a href="map" title="Carte de l'univers">Carte</a>
|
||||
</div>
|
||||
<div class="button">
|
||||
<a href="research" title="Gestion des priorités de recherche, implémentation et visualisation de technologies">Recherche</a>
|
||||
</div>
|
||||
<div class="button">
|
||||
<a href="alliance" title="Alliance">Alliance</a>
|
||||
</div>
|
||||
<div class="button">
|
||||
<a href="enemies" title="Gèstion des listes de joueurs et alliances ennemis">Listes d'ennemis</a>
|
||||
<a href="enemies" title="Gestion des listes de joueurs et alliances ennemis">Listes d'ennemis</a>
|
||||
</div>
|
||||
<div class="button">
|
||||
<a href="messages" title="Messages">Messages</a>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<@page title="Empire">
|
||||
|
||||
<#assign ov = data.overview >
|
||||
<#assign rs = data.research >
|
||||
|
||||
<@tabs>
|
||||
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
<#--
|
||||
Macro that starts a research tab for one of the 3 existing modes
|
||||
|
||||
Parameters:
|
||||
curMode The tab to start: R for "in progress", P for pending, K for implemented
|
||||
-->
|
||||
<#macro startResearchTab curMode>
|
||||
<#switch curMode>
|
||||
|
||||
<#case 'R'>
|
||||
<@tabStart "research" "En cours" />
|
||||
<@rawFormStart "research-set-priorities" "form-priorities" "research" />
|
||||
<@listviewStart />
|
||||
<@lv_line headers=true>
|
||||
<@lv_column width=150>Catégorie</@lv_column>
|
||||
<@lv_column width="x">Nom</@lv_column>
|
||||
<@lv_column width=100 centered=true>Progrès</@lv_column>
|
||||
<@lv_column width=150 centered=true>Priorité</@lv_column>
|
||||
</@lv_line>
|
||||
<#break>
|
||||
|
||||
<#case 'P'>
|
||||
<@tabStart "pending" "En attente" />
|
||||
<@listviewStart />
|
||||
<@lv_line headers=true>
|
||||
<@lv_column width=150>Catégorie</@lv_column>
|
||||
<@lv_column width="x">Nom</@lv_column>
|
||||
<@lv_column width=150 right=true>Coût</@lv_column>
|
||||
<@lv_column width=100 centered=true> </@lv_column>
|
||||
</@lv_line>
|
||||
<#break>
|
||||
|
||||
<#case 'K'>
|
||||
<@tabStart "implemented" "Recherchées" />
|
||||
<@listviewStart />
|
||||
<@lv_line headers=true>
|
||||
<@lv_column width=150>Catégorie</@lv_column>
|
||||
<@lv_column width="x">Nom</@lv_column>
|
||||
</@lv_line>
|
||||
<#break>
|
||||
|
||||
</#switch>
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that finishes a research tab depending on its type
|
||||
|
||||
Parameters:
|
||||
mode The type of tab that is being closed
|
||||
-->
|
||||
<#macro endResearchTab mode>
|
||||
<#switch mode>
|
||||
|
||||
<#case 'R'>
|
||||
<@lv_line headers=true>
|
||||
<@lv_column width="x" colspan=4> </@lv_column>
|
||||
</@lv_line>
|
||||
<@lv_line>
|
||||
<@lv_column colspan=3> </@lv_column>
|
||||
<@lv_column centered=true>
|
||||
<input type="submit" value="Modifier" class="input" style="margin: 15px 0 0 0" />
|
||||
</@lv_column>
|
||||
</@lv_line>
|
||||
<@listviewEnd />
|
||||
</form>
|
||||
<#break>
|
||||
|
||||
<#case 'P'>
|
||||
<#case 'K'>
|
||||
<@listviewEnd />
|
||||
<#break>
|
||||
|
||||
</#switch>
|
||||
<@tabEnd />
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that renders an in-progress research entry
|
||||
|
||||
Parameters:
|
||||
entry the entry
|
||||
-->
|
||||
<#macro drawInProgressResearch entry>
|
||||
<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
|
||||
<@lv_column>${entry.category?xhtml}</@lv_column>
|
||||
<@lv_column>
|
||||
<#if entry.name?has_content>
|
||||
<strong>${entry.name?xhtml}</strong>
|
||||
<#else>
|
||||
Technologie inconnue
|
||||
</#if>
|
||||
</@lv_column>
|
||||
<@lv_column centered=true>${entry.completion} %</@lv_column>
|
||||
<@lv_column centered=true>
|
||||
<select name="rp-${entry.identifier?xhtml}" class="input">
|
||||
<option style="padding: 0 5px" value="0" <#if entry.priority = 0>selected="selected"</#if>>très basse</option>
|
||||
<option style="padding: 0 5px" value="1" <#if entry.priority = 1>selected="selected"</#if>>basse</option>
|
||||
<option style="padding: 0 5px" value="2" <#if entry.priority = 2>selected="selected"</#if>>normale</option>
|
||||
<option style="padding: 0 5px" value="3" <#if entry.priority = 3>selected="selected"</#if>>élevée</option>
|
||||
<option style="padding: 0 5px" value="4" <#if entry.priority = 4>selected="selected"</#if>>très élevée</option>
|
||||
</select>
|
||||
</@lv_column>
|
||||
</@lv_line>
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that renders a pending technology
|
||||
|
||||
Parameters:
|
||||
entry the technology
|
||||
-->
|
||||
<#macro drawPendingTechnology entry>
|
||||
<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
|
||||
<@lv_column>${entry.category?xhtml}</@lv_column>
|
||||
<@lv_column>
|
||||
<strong>${entry.name?xhtml}</strong>
|
||||
</@lv_column>
|
||||
<@lv_column right=true>
|
||||
<strong>${entry.price?string(",##0")}</strong> <@abbr_bgc/>
|
||||
</@lv_column>
|
||||
<@lv_column right=true>
|
||||
<#if data.page.cash >= entry.price>
|
||||
<@rawFormStart "research-implement" "form-implement-${entry.identifier}" entry.identifier />
|
||||
<input type="hidden" name="technology" value="${entry.identifier?xhtml}" />
|
||||
<input type="submit" value="Implémenter" class="input" />
|
||||
</form>
|
||||
<#else>
|
||||
|
||||
</#if>
|
||||
</@lv_column>
|
||||
</@lv_line>
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that renders an implemented technology
|
||||
|
||||
Parameters:
|
||||
entry the technology
|
||||
-->
|
||||
<#macro drawImplementedTechnology entry>
|
||||
<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
|
||||
<@lv_column>${entry.category?xhtml}</@lv_column>
|
||||
<@lv_column>
|
||||
<strong>${entry.name?xhtml}</strong>
|
||||
</@lv_column>
|
||||
</@lv_line>
|
||||
</#macro>
|
||||
<#--
|
||||
Macro that renders a single entry
|
||||
|
||||
Parameters:
|
||||
mode the current tab (see startResearchTab for details)
|
||||
entry the entry
|
||||
-->
|
||||
<#macro drawResearchEntry mode entry>
|
||||
<#switch mode>
|
||||
|
||||
<#case 'R'>
|
||||
<@drawInProgressResearch entry />
|
||||
<#break>
|
||||
|
||||
<#case 'P'>
|
||||
<@drawPendingTechnology entry />
|
||||
<#break>
|
||||
|
||||
<#case 'K'>
|
||||
<@drawImplementedTechnology entry />
|
||||
<#break>
|
||||
|
||||
</#switch>
|
||||
</#macro>
|
||||
<#--
|
||||
Render the visible part of the research page
|
||||
|
||||
Parameters:
|
||||
entries the sorted list of research entries
|
||||
-->
|
||||
<#macro renderResearchTabs entries>
|
||||
<#local prevMode = ''>
|
||||
|
||||
<@tabs>
|
||||
<#list entries as entry>
|
||||
|
||||
<#-- Determine type of entry to display -->
|
||||
<#if entry.implemented?has_content>
|
||||
<#if entry.implemented>
|
||||
<#local curMode = 'K'>
|
||||
<#else>
|
||||
<#local curMode = 'P'>
|
||||
</#if>
|
||||
<#else>
|
||||
<#local curMode = 'R'>
|
||||
</#if>
|
||||
|
||||
<#-- Start/end tabs -->
|
||||
<#if curMode != prevMode>
|
||||
<#if prevMode != ''>
|
||||
<@endResearchTab prevMode />
|
||||
</#if>
|
||||
<@startResearchTab curMode />
|
||||
<#local prevMode = curMode>
|
||||
</#if>
|
||||
|
||||
|
||||
<@drawResearchEntry curMode entry />
|
||||
|
||||
</#list>
|
||||
<@endResearchTab prevMode />
|
||||
</@tabs>
|
||||
</#macro>
|
||||
<#--
|
||||
Render all research information in a hidden layer which will be used by
|
||||
the client-side code to display more information.
|
||||
-->
|
||||
<#macro renderFullResearchData entries>
|
||||
<div style="display: none">
|
||||
<#list entries as tech>
|
||||
<div class="tech-description" id="tdesc-${tech.identifier?xhtml}">
|
||||
<h4><#if tech.name?has_content>${tech.name?xhtml}<#else>Technologie inconnue</#if></h4>
|
||||
<div class="tech-info"><strong>Catégorie:</strong> ${tech.category?xhtml}</div>
|
||||
<#if tech.description?has_content><div class="tech-info">${tech.description?xhtml}</div></#if>
|
||||
<#if tech.price?has_content>
|
||||
<div class="tech-info"><strong>Coût d'implémentation:</strong> ${tech.price?string(",##0")} <@abbr_bgc /></div>
|
||||
</#if>
|
||||
<#if tech.dependencies?has_content>
|
||||
<div class="tech-info"><strong>Requiert:</strong>
|
||||
<ul>
|
||||
<#list tech.dependencies as depId>
|
||||
<li class="dep">${depId}</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</div>
|
||||
</#if>
|
||||
<#if tech.reverseDependencies?has_content>
|
||||
<div class="tech-info"><strong>Requis par:</strong>
|
||||
<ul>
|
||||
<#list tech.reverseDependencies as depId>
|
||||
<li class="dep">${depId}</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</#list>
|
||||
</div>
|
||||
<script type="text/javascript" charset="utf-8" src="js/research.js"></script>
|
||||
</#macro>
|
||||
<#--
|
||||
Main research page
|
||||
-->
|
||||
<#macro render>
|
||||
<@page title="Recherche">
|
||||
|
||||
<#local entries = data.researchData>
|
||||
<@renderResearchTabs entries />
|
||||
<@renderFullResearchData entries />
|
||||
|
||||
</@page>
|
||||
</#macro>
|
|
@ -1,12 +1,21 @@
|
|||
<#macro form action name="" hash="">
|
||||
<#macro rawFormStart action name="" hash="">
|
||||
<form action="${action?url}.action<#if hash != "">#${hash?url}</#if>" method="post">
|
||||
</#macro>
|
||||
<#macro formStart action name="" hash="">
|
||||
<div class="form-container">
|
||||
<form action="${action?url}.action<#if hash != "">#${hash?url}</#if>" method="post">
|
||||
<@rawFormStart action name hash />
|
||||
<table>
|
||||
<#nested>
|
||||
</#macro>
|
||||
<#macro formEnd>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</#macro>
|
||||
<#macro form action name="" hash="">
|
||||
<@formStart action name hash />
|
||||
<#nested>
|
||||
<@formEnd />
|
||||
</#macro>
|
||||
<#macro form_field_line label id>
|
||||
<tr class="form-field">
|
||||
<th><label for="ff-${id?xhtml}">${label?xhtml}:</label></th>
|
||||
|
|
|
@ -1,24 +1,30 @@
|
|||
<#macro listview>
|
||||
<#macro listviewStart>
|
||||
<table class="list-view">
|
||||
<#nested>
|
||||
</#macro>
|
||||
<#macro listviewEnd>
|
||||
</table>
|
||||
</#macro>
|
||||
<#macro listview>
|
||||
<@listviewStart />
|
||||
<#nested>
|
||||
<@listviewEnd />
|
||||
</#macro>
|
||||
<#macro lv_line headers=false class="">
|
||||
<tr<#if class != ""> class="${class}<#if headers>headers</#if>"<#elseif headers> class="headers"</#if>>
|
||||
<#macro lv_line headers=false class="" id="">
|
||||
<tr<#if class != ""> class="${class}<#if headers>headers</#if>"<#elseif headers> class="headers"</#if><#if id != ""> id="${id?xhtml}"</#if>>
|
||||
<#nested>
|
||||
</tr>
|
||||
</#macro>
|
||||
<#macro lv_column width=0 centered=false right=false colspan=0>
|
||||
<#macro lv_column width=0 centered=false right=false colspan=0 id="">
|
||||
<#if width?is_string>
|
||||
<th style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if>>
|
||||
<th style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if><#if id != ""> id="${id?xhtml}"</#if>>
|
||||
<#nested>
|
||||
</th>
|
||||
<#elseif width gt 0>
|
||||
<th style="width: ${width}px; text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if>>
|
||||
<th style="width: ${width}px; text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if><#if id != ""> id="${id?xhtml}"</#if>>
|
||||
<#nested>
|
||||
</th>
|
||||
<#else>
|
||||
<td style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if>>
|
||||
<td style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if><#if id != ""> id="${id?xhtml}"</#if>>
|
||||
<#nested>
|
||||
</td>
|
||||
</#if>
|
||||
|
|
|
@ -3,11 +3,17 @@
|
|||
<#nested>
|
||||
</div>
|
||||
</#macro>
|
||||
<#macro tab id title>
|
||||
<#macro tabStart id title>
|
||||
<div class="tab" id="${id?xhtml}">
|
||||
<h3>${title?xhtml}</h3>
|
||||
<div class="tab-contents">
|
||||
<#nested>
|
||||
</#macro>
|
||||
<#macro tabEnd>
|
||||
</div>
|
||||
</div>
|
||||
</#macro>
|
||||
<#macro tab id title>
|
||||
<@tabStart id title />
|
||||
<#nested>
|
||||
<@tabEnd />
|
||||
</#macro>
|
|
@ -266,10 +266,10 @@ div.button a:focus,div.button a:hover {
|
|||
|
||||
/* Forms */
|
||||
.form-container {
|
||||
width: -moz-calc( 100% - 128px );
|
||||
width: -webkit-calc( 100% - 128px );
|
||||
width: -o-calc( 100% - 128px );
|
||||
width: calc( 100% - 128px );
|
||||
width: -moz-calc(100% - 128px);
|
||||
width: -webkit-calc(100% - 128px);
|
||||
width: -o-calc(100% - 128px);
|
||||
width: calc(100% - 128px);
|
||||
margin: 0 64px;
|
||||
}
|
||||
|
||||
|
@ -304,10 +304,10 @@ div.button a:focus,div.button a:hover {
|
|||
padding: 5px 20px;
|
||||
}
|
||||
|
||||
.form-submit .input:hover , .form-submit .input:focus {
|
||||
.form-submit .input:hover,.form-submit .input:focus {
|
||||
padding: 5px 20px;
|
||||
border-color: #dfdfdf;
|
||||
background-color: rgba(127,127,127,0.6);
|
||||
background-color: rgba(127, 127, 127, 0.6);
|
||||
}
|
||||
|
||||
.form-extra td {
|
||||
|
@ -323,7 +323,7 @@ div.button a:focus,div.button a:hover {
|
|||
.form-error td {
|
||||
font-size: 11pt;
|
||||
color: white;
|
||||
background-color: rgba(255,0,0,0.4);
|
||||
background-color: rgba(255, 0, 0, 0.4);
|
||||
font-weight: bold;
|
||||
margin: 2px 0px;
|
||||
padding: 5px 10px;
|
||||
|
@ -334,7 +334,7 @@ div.button a:focus,div.button a:hover {
|
|||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: #afafaf;
|
||||
background-color: rgba(63,63,63,0.6);
|
||||
background-color: rgba(63, 63, 63, 0.6);
|
||||
color: white;
|
||||
font-size: 10pt;
|
||||
margin: 1px 0px;
|
||||
|
@ -371,10 +371,10 @@ div.button a:focus,div.button a:hover {
|
|||
|
||||
/* List display */
|
||||
.list-view {
|
||||
width: -moz-calc( 100% - 64px );
|
||||
width: -webkit-calc( 100% - 64px );
|
||||
width: -o-calc( 100% - 64px );
|
||||
width: calc( 100% - 64px );
|
||||
width: -moz-calc(100% - 64px);
|
||||
width: -webkit-calc(100% - 64px);
|
||||
width: -o-calc(100% - 64px);
|
||||
width: calc(100% - 64px);
|
||||
margin: 0 32px 20px 32px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
@ -604,20 +604,20 @@ table.fleets-planet,table.fleets-moving {
|
|||
border: 1px solid white;
|
||||
border-collapse: collapse;
|
||||
margin: 0 0 20px 5px;
|
||||
width: -moz-calc( 100% - 20px );
|
||||
width: -webkit-calc( 100% - 20px );
|
||||
width: -o-calc( 100% - 20px );
|
||||
width: calc( 100% - 20px );
|
||||
width: -moz-calc(100% - 20px);
|
||||
width: -webkit-calc(100% - 20px);
|
||||
width: -o-calc(100% - 20px);
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
table.selected-fleets {
|
||||
border: 1px solid white;
|
||||
border-collapse: collapse;
|
||||
margin: 10px 0 20px 15px;
|
||||
width: -moz-calc( 100% - 30px );
|
||||
width: -webkit-calc( 100% - 30px );
|
||||
width: -o-calc( 100% - 30px );
|
||||
width: calc( 100% - 30px );
|
||||
width: -moz-calc(100% - 30px);
|
||||
width: -webkit-calc(100% - 30px);
|
||||
width: -o-calc(100% - 30px);
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
|
||||
table.fleets-planet td {
|
||||
|
@ -799,4 +799,20 @@ tr.alliance-msg * {
|
|||
|
||||
tr.empire-msg * {
|
||||
color: #afafaf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Research page
|
||||
*/
|
||||
.tech-line {
|
||||
height: 22px;
|
||||
}
|
||||
.tech-view h4 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.tech-view .tech-info {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
.tech-line.selected, .tech-line.selected td {
|
||||
background-color: rgba(127, 127, 127, 0.25);
|
||||
}
|
87
legacyworlds-web-main/Content/Raw/js/research.js
Normal file
87
legacyworlds-web-main/Content/Raw/js/research.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
$(function() {
|
||||
|
||||
/* Replace dependency identifiers */
|
||||
$('.tech-info li.dep').each(
|
||||
function() {
|
||||
var _id = this.innerHTML;
|
||||
var _targetTitle = $('#tdesc-' + _id + ' h4');
|
||||
this.innerHTML = '';
|
||||
$('<a/>').attr('href', '#tl-' + _id)
|
||||
.append(_targetTitle.html()).appendTo($(this));
|
||||
});
|
||||
|
||||
/* Map entries to tabs */
|
||||
var _entries = {};
|
||||
var _tabs = {};
|
||||
$('.tech-line').each(
|
||||
function() {
|
||||
var _id = $(this).attr('id').replace(/^tl-/, '');
|
||||
var _tab = $(this).parents('.tab-contents').attr('id').replace(
|
||||
/^tabc-/, '');
|
||||
_entries[_id] = _tab;
|
||||
if (!_tabs[_tab]) {
|
||||
_tabs[_tab] = [];
|
||||
}
|
||||
_tabs[_tab].push(_id);
|
||||
});
|
||||
var _selected = {};
|
||||
for ( var _tab in _tabs) {
|
||||
_selected[_tab] = _tabs[_tab][0];
|
||||
$('#tl-' + _selected[_tab]).toggleClass('selected');
|
||||
}
|
||||
|
||||
/* Insert viewing area */
|
||||
var _viewingArea = $('<div/>').css({
|
||||
'float' : 'right',
|
||||
'width' : '300px',
|
||||
'position' : 'relative',
|
||||
}).attr('class', 'tech-view').prependTo($('#page-contents'));
|
||||
$('div.tabs').css({
|
||||
'margin-right' : '300px'
|
||||
});
|
||||
|
||||
/* When an entry is clicked, set contents of viewing area */
|
||||
var _displayed = '';
|
||||
$('.tech-line').click(function() {
|
||||
var _id = $(this).attr('id').replace(/^tl-/, '');
|
||||
if (_id == _displayed) {
|
||||
return;
|
||||
}
|
||||
_viewingArea.html($('#tdesc-' + _id).html());
|
||||
$('a', _viewingArea).click(function() {
|
||||
var _target = $(this).attr('href').replace(/^#tl-/, '');
|
||||
$('#tabb-' + _entries[_target]).click();
|
||||
$('#tl-' + _target).click();
|
||||
});
|
||||
if (_selected[_entries[_id]] != _id) {
|
||||
$('#tl-' + _selected[_entries[_id]]).toggleClass('selected');
|
||||
$(this).toggleClass('selected');
|
||||
_selected[_entries[_id]] = _id;
|
||||
}
|
||||
location.hash = '#tl-'+_id;
|
||||
return true;
|
||||
});
|
||||
|
||||
/* When a tab button is clicked, select the appropriate entry */
|
||||
$('.tab-buttons a').click(function() {
|
||||
var _id = $(this).attr('id').replace(/^tabb-/, '');
|
||||
var _tech = _selected[_id];
|
||||
$('#tl-' + _tech).click();
|
||||
});
|
||||
|
||||
(function() {
|
||||
var _current = location.hash;
|
||||
if (_current.match(/^#tl-/)) {
|
||||
_current = _current.replace(/#tl-/, '');
|
||||
} else if (_current.match(/^#/)) {
|
||||
_current = _selected[_current.replace(/^#/, '')];
|
||||
} else {
|
||||
for ( var _tab in _selected) {
|
||||
_current = _selected[_tab];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$('#tabb-' + _entries[_current]).click();
|
||||
$('#tl-' + _current).click();
|
||||
})();
|
||||
});
|
|
@ -10,7 +10,6 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
|
@ -73,21 +72,15 @@ public class OverviewPage
|
|||
|
||||
|
||||
/**
|
||||
* "Implement technology" command
|
||||
* Empire-wide mining settings update command
|
||||
*
|
||||
* <p>
|
||||
* This method is mapped to the technology implementation command URL.
|
||||
* This method is called when a command to update empire-wide mining settings is received.
|
||||
*
|
||||
* @param request
|
||||
* the HTTP request
|
||||
* @param language
|
||||
* the language from the session
|
||||
* @param model
|
||||
* the model
|
||||
* @param tech
|
||||
* the technology identifier
|
||||
*
|
||||
* @return the overview page rendering order
|
||||
* @return a redirection to the overview page's "economy" tab
|
||||
*
|
||||
* @throws SessionException
|
||||
* if some error occurs on the server
|
||||
|
@ -96,26 +89,8 @@ public class OverviewPage
|
|||
* @throws SessionMaintenanceException
|
||||
* if the game is under maintenance
|
||||
*/
|
||||
@RequestMapping( value = "/implement-{tech}.action" , method = RequestMethod.POST )
|
||||
public String implement( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model ,
|
||||
@PathVariable String tech )
|
||||
throws SessionException , SessionServerException , SessionMaintenanceException
|
||||
{
|
||||
int techId;
|
||||
try {
|
||||
techId = Integer.parseInt( tech );
|
||||
} catch ( NumberFormatException e ) {
|
||||
return this.redirect( "overview" );
|
||||
}
|
||||
|
||||
PlayerSession pSession = this.getSession( PlayerSession.class , request );
|
||||
return this.render( model , "game" , language , "overview" , pSession.implementTechnology( techId ) );
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping( value = "/update-mining-settings.action" , method = RequestMethod.POST )
|
||||
public String updateMiningSettings( HttpServletRequest request , @ModelAttribute( "language" ) String language ,
|
||||
Model model )
|
||||
public String updateMiningSettings( HttpServletRequest request )
|
||||
throws SessionException , SessionServerException , SessionMaintenanceException
|
||||
{
|
||||
Map< String , Integer > miningSettings = this.getMiningSettings( request );
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
package com.deepclone.lw.web.main.game;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
|
||||
import com.deepclone.lw.session.SessionException;
|
||||
import com.deepclone.lw.web.beans.intercept.SessionRequirement;
|
||||
import com.deepclone.lw.web.beans.session.SessionMaintenanceException;
|
||||
import com.deepclone.lw.web.beans.session.SessionServerException;
|
||||
import com.deepclone.lw.web.beans.view.PageControllerBase;
|
||||
import com.deepclone.lw.web.csess.PlayerSession;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Controller for the Research page
|
||||
*
|
||||
* <p>
|
||||
* This controller contains all URL handlers associated with the research page: viewing research
|
||||
* state, setting research priorities, and implementing technologies.
|
||||
*
|
||||
* @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
|
||||
*/
|
||||
@Controller
|
||||
@SessionRequirement( value = true , redirectTo = "player-session" , subType = "game" )
|
||||
@SessionAttributes( "language" )
|
||||
public class ResearchPage
|
||||
extends PageControllerBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Research page view
|
||||
*
|
||||
* <p>
|
||||
* This method fetches all research information from the game server then requests the page
|
||||
* rendering.
|
||||
*
|
||||
* @param request
|
||||
* the HTTP request
|
||||
* @param language
|
||||
* the language from the session
|
||||
* @param model
|
||||
* the model
|
||||
*
|
||||
* @return the research page rendering information
|
||||
*
|
||||
* @throws SessionException
|
||||
* if some error occurs on the server
|
||||
* @throws SessionServerException
|
||||
* if the server is unreachable
|
||||
* @throws SessionMaintenanceException
|
||||
* if the game is under maintenance
|
||||
*/
|
||||
@RequestMapping( "/research" )
|
||||
public String view( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model )
|
||||
throws SessionException , SessionServerException , SessionMaintenanceException
|
||||
{
|
||||
PlayerSession pSession = this.getSession( PlayerSession.class , request );
|
||||
return this.render( model , "game" , language , "research" , pSession.getResearch( ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Research priorities update command
|
||||
*
|
||||
* <p>
|
||||
* This method handles the research priorities update command, which is triggered when the
|
||||
* "Update" button is clicked on the "In progress" tab of the research page.
|
||||
*
|
||||
* @param request
|
||||
* the HTTP request
|
||||
*
|
||||
* @return a redirection to the research page's "in progress" tab
|
||||
*
|
||||
* @throws SessionException
|
||||
* if some error occurs on the server
|
||||
* @throws SessionServerException
|
||||
* if the server is unreachable
|
||||
* @throws SessionMaintenanceException
|
||||
* if the game is under maintenance
|
||||
*/
|
||||
@RequestMapping( value = "/research-set-priorities.action" , method = RequestMethod.POST )
|
||||
public String setPriorities( HttpServletRequest request )
|
||||
throws SessionException , SessionServerException , SessionMaintenanceException
|
||||
{
|
||||
Map< String , Integer > priorities = this.getPriorities( request );
|
||||
if ( priorities != null ) {
|
||||
this.getSession( PlayerSession.class , request ).updateResearchPriorities( priorities );
|
||||
}
|
||||
return this.redirect( "research#research" );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract research priorities from the HTTP request
|
||||
*
|
||||
* <p>
|
||||
* Look for all submitted fields that begin with "rp-" then try to extract their values into a
|
||||
* map that associates technology identifiers to priorities.
|
||||
*
|
||||
* @param request
|
||||
* the HTTP request
|
||||
*
|
||||
* @return the map containing the submitted priorities, or <code>null</code> if one of the
|
||||
* values was incorrect.
|
||||
*/
|
||||
private Map< String , Integer > getPriorities( HttpServletRequest request )
|
||||
{
|
||||
Map< String , Object > input = this.getInput( request );
|
||||
Map< String , Integer > priorities = new HashMap< String , Integer >( );
|
||||
for ( Entry< String , Object > entry : input.entrySet( ) ) {
|
||||
// Ignore items which are not priorities
|
||||
String name = entry.getKey( );
|
||||
if ( !name.startsWith( "rp-" ) ) {
|
||||
continue;
|
||||
}
|
||||
name = name.substring( 3 );
|
||||
|
||||
// Get values
|
||||
if ( ! ( entry.getValue( ) instanceof String[] ) ) {
|
||||
continue;
|
||||
}
|
||||
String[] values = (String[]) entry.getValue( );
|
||||
if ( values.length < 1 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Pre-validate them
|
||||
int value;
|
||||
try {
|
||||
value = Integer.parseInt( values[ 0 ] );
|
||||
} catch ( NumberFormatException e ) {
|
||||
value = -1;
|
||||
}
|
||||
if ( value < 0 || value > 4 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
priorities.put( name , value );
|
||||
}
|
||||
return priorities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Technology implementation command
|
||||
*
|
||||
* <p>
|
||||
* This method handles the technology implementation command, which is triggered when the
|
||||
* "Implement" button is clicked on the "Pending" tab of the research page.
|
||||
*
|
||||
* @param request
|
||||
* the HTTP request
|
||||
* @param tech
|
||||
* the identifier of the technology
|
||||
*
|
||||
* @return a redirection to the research page's "Implemented" tab
|
||||
*
|
||||
* @throws SessionException
|
||||
* if some error occurs on the server
|
||||
* @throws SessionServerException
|
||||
* if the server is unreachable
|
||||
* @throws SessionMaintenanceException
|
||||
* if the game is under maintenance
|
||||
*/
|
||||
@RequestMapping( value = "/research-implement.action" , method = RequestMethod.POST )
|
||||
public String implement( HttpServletRequest request , @RequestParam( "technology" ) String technology )
|
||||
throws SessionException , SessionServerException , SessionMaintenanceException
|
||||
{
|
||||
this.getSession( PlayerSession.class , request ).implementTechnology( technology );
|
||||
return this.redirect( "research#implemented" );
|
||||
}
|
||||
|
||||
}
|
|
@ -168,6 +168,11 @@
|
|||
<groupId>com.deepclone.lw</groupId>
|
||||
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>legacyworlds-server-beans-technologies</artifactId>
|
||||
<groupId>com.deepclone.lw</groupId>
|
||||
<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>legacyworlds-server-beans-updates</artifactId>
|
||||
<groupId>com.deepclone.lw</groupId>
|
||||
|
|
Reference in a new issue