All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jadex.web.examples.puzzle.agent.PuzzleService Maven / Gradle / Ivy

The newest version!
package jadex.web.examples.puzzle.agent;

import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

import jadex.bdiv3.runtime.IGoal;
import jadex.bdiv3x.features.IBDIXAgentFeature;
import jadex.bridge.IComponentStep;
import jadex.bridge.IExternalAccess;
import jadex.bridge.IInternalAccess;
import jadex.bridge.component.IExecutionFeature;
import jadex.bridge.service.ServiceScope;
import jadex.bridge.service.annotation.OnEnd;
import jadex.bridge.service.annotation.OnStart;
import jadex.bridge.service.annotation.Service;
import jadex.bridge.service.annotation.ServiceComponent;
import jadex.bridge.service.annotation.ServiceShutdown;
import jadex.bridge.service.component.IRequiredServicesFeature;
import jadex.bridge.service.search.ServiceQuery;
import jadex.bridge.service.types.clock.IClockService;
import jadex.bridge.service.types.settings.ISettingsService;
import jadex.commons.IPropertiesProvider;
import jadex.commons.Properties;
import jadex.commons.Property;
import jadex.commons.future.DelegationResultListener;
import jadex.commons.future.ExceptionDelegationResultListener;
import jadex.commons.future.Future;
import jadex.commons.future.IFuture;
import jadex.commons.future.IResultListener;
import jadex.web.examples.puzzle.Board;
import jadex.web.examples.puzzle.HighscoreEntry;
import jadex.web.examples.puzzle.IPuzzleService;
import jadex.web.examples.puzzle.Move;
import jadex.xml.bean.JavaReader;
import jadex.xml.bean.JavaWriter;
/**
 *  Implementation of the puzzle service.
 */
@Service(IPuzzleService.class)
public class PuzzleService implements IPuzzleService, IPropertiesProvider
{
	//-------- constants --------
	
	/** The number of entries per board size in the high score list. */
	protected static final int	MAX_ENTRIES	= 10;
	
	//-------- attributes --------
	
	/** The agent to which the service belongs. */
	@ServiceComponent
	protected IInternalAccess	agent;
	
	/** The external access for decoupling settings service calls. */
	// Hack!!! Remove.
	protected IExternalAccess	exta;
	
	/** The highscore entries (boardsize->sorted set). */
	protected Map>	entries;
	
	//-------- constructors --------
	
	/**
	 *  Init method called on service startup.
	 */
	//@ServiceStart
	@OnStart
	public IFuture	startService()
	{
		final Future	ret	= new Future();
		
		exta	= agent.getExternalAccess();
		entries	= new HashMap>();
		
		agent.getFeature(IRequiredServicesFeature.class).searchService(new ServiceQuery<>(ISettingsService.class, ServiceScope.PLATFORM))
			.addResultListener(new IResultListener()
		{
			public void resultAvailable(ISettingsService settings)
			{
				settings.registerPropertiesProvider("puzzle", PuzzleService.this)
					.addResultListener(new DelegationResultListener(ret)
				{
					@Override
					public void customResultAvailable(Void result)
					{
						super.customResultAvailable(result);
					}
					
					@Override
					public void exceptionOccurred(Exception exception)
					{
						super.exceptionOccurred(exception);
					}
				});
			}

			public void exceptionOccurred(Exception exception)
			{
				ret.setResult(null);
			}
		});
		
		return ret;
	}
	
	/**
	 *  Termination method called on service shutdown.
	 */
	//@ServiceShutdown
	@OnEnd
	public IFuture	shutdownService()
	{
		final Future	ret	= new Future();
		
		// Does not work, because capability service container no longer available after component cleanup. 
//		agent.getServiceContainer().searchService(ISettingsService.class, ServiceScope.PLATFORM)
		exta.searchService( new ServiceQuery<>( ISettingsService.class, ServiceScope.PLATFORM))
			.addResultListener(new IResultListener()
		{
			public void resultAvailable(ISettingsService settings)
			{
				settings.deregisterPropertiesProvider("puzzle")
					.addResultListener(new DelegationResultListener(ret));
			}

			public void exceptionOccurred(Exception exception)
			{
				ret.setResult(null);
			}
		});

		return ret;
	}
	
	//-------- IPuzzleService interface --------
	
	/**
	 *  Solve the game and give a hint on the next move.
	 *  @param board	The current board state.
	 *  @param timeout	A timeout to stop, when no solution is found in time (-1 for no timeout).
	 *  @return The tile to move next.
	 *  @throws Exception in future, when puzzle can not be solved in time.
	 */
	public IFuture	hint(final Board board, final long timeout)
	{
		final Future	ret	= new Future();
		final int depth	= board.getMoves().size();
		
		final IGoal	goal	= agent.getFeature(IBDIXAgentFeature.class).getGoalbase().createGoal("makemove");
		goal.getParameter("board").setValue(board);	// It is safe to use the board object, as it is passed as a copy to the service automatically.
		long time = agent.getFeature(IRequiredServicesFeature.class).getLocalService(new ServiceQuery<>( IClockService.class, ServiceScope.PLATFORM)).getTime();
		goal.getParameter("deadline").setValue(timeout!=-1 ? time+timeout : -1);
		
		agent.getFeature(IBDIXAgentFeature.class).getGoalbase().dispatchTopLevelGoal(goal)
			.addResultListener(new ExceptionDelegationResultListener(ret)
		{
			public void customResultAvailable(Object result)
			{
				ret.setResult(board.getMoves().get(depth));
			}
		});
		return ret;
	}

	
	/**
	 *  Add a highscore entry and save the highscore list.
	 *  @param entry	The highscore entry.
	 */
	public IFuture	addHighscore(HighscoreEntry entry)
	{
		Future	ret	= new Future();

		SortedSet	set	= entries.get(Integer.valueOf(entry.getBoardSize()));
		if(set==null)
		{
			set	= new TreeSet();
			entries.put(Integer.valueOf(entry.getBoardSize()), set);
		}
		
		// Add new entry to non-full highscore.
		if(set.size()(ret));
		}
		// Replace with last entry of full highscore, if better.
		else if(entry.compareTo(set.last())<0)
		{
			set.remove(set.last());
			set.add(entry);

			// Save new highscore.
			save().addResultListener(new DelegationResultListener(ret));
		}
		// Entry is not worth to be included.
		else
		{
			ret.setException(new RuntimeException("Entry is not worth to be included."));
		}
		
		return ret;
	}
	
	/**
	 *  Get the highscore entries for a given board size.
	 *  @param size	The board size (e.g. 3, 5, ...).
	 *  @return	The sorted set of highscore entries (highest entry first).
	 */
	public IFuture>	getHighscore(int size)
	{
		return new Future>(entries.containsKey(Integer.valueOf(size))
			? entries.get(Integer.valueOf(size)) : new TreeSet());
	}
	
	//-------- helper methods --------
	
	/**
	 *  Save highscore using settings service.
	 */
	protected IFuture	save()
	{
		final Future	ret	= new Future();
		
		agent.getFeature(IRequiredServicesFeature.class).searchService(new ServiceQuery<>(ISettingsService.class, ServiceScope.PLATFORM))
			.addResultListener(new IResultListener()
		{
			public void resultAvailable(ISettingsService settings)
			{
				settings.saveProperties().addResultListener(new DelegationResultListener(ret));
			}

			public void exceptionOccurred(Exception exception)
			{
				ret.setResult(null);
			}
		});
		
		return ret;
	}

	/**
	 *  Update from given properties.
	 */
	public IFuture setProperties(final Properties props)
	{
		// Hack!!! Should be decoupled by platform automatically
		return exta.scheduleStep(IExecutionFeature.STEP_PRIORITY_IMMEDIATE, false, new IComponentStep()
		{
			public IFuture execute(IInternalAccess ia)
			{
				Property	prop	= props.getProperty("entries");
				if(prop!=null)
				{
					PuzzleService.this.entries	= JavaReader.objectFromXML(prop.getValue(), agent.getClassLoader());
				}
				else
				{
					PuzzleService.this.entries	= new HashMap>();			
				}
				
				return IFuture.DONE;
			}
		});
	}
	
	/**
	 *  Write current state into properties.
	 */
	public IFuture getProperties()
	{
		// Hack!!! Should be decoupled by platform automatically
		return exta.scheduleStep(IExecutionFeature.STEP_PRIORITY_IMMEDIATE, false, new IComponentStep()
		{
			public IFuture execute(IInternalAccess ia)
			{
				Properties	props	= new Properties();
				props.addProperty(new Property("entries", JavaWriter.objectToXML(entries, agent.getClassLoader())));
				return new Future(props);
			}
		});
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy