<commit_before>package com.planetmayo.debrief.satc.model.generator;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import com.planetmayo.debrief.satc.model.Precision;
import com.planetmayo.debrief.satc.model.contributions.BaseContribution;
import com.planetmayo.debrief.satc.model.legs.AlteringLeg;
import com.planetmayo.debrief.satc.model.legs.CompositeRoute;
import com.planetmayo.debrief.satc.model.legs.CoreLeg;
import com.planetmayo.debrief.satc.model.legs.CoreRoute;
import com.planetmayo.debrief.satc.model.legs.LegType;
import com.planetmayo.debrief.satc.model.legs.StraightLeg;
import com.planetmayo.debrief.satc.model.states.BaseRange.IncompatibleStateException;
import com.planetmayo.debrief.satc.model.states.BoundedState;
import com.planetmayo.debrief.satc.model.states.ProblemSpace;

public class SolutionGenerator implements IConstrainSpaceListener,
		ISolutionGenerator, PropertyChangeListener
{
	/**
	 * how many cells shall we break the polygons down into?
	 * 
	 */
	final int NUM_CELLS = 20;

	/**
	 * anybody interested in a new solution being ready?
	 * 
	 */
	final private ArrayList<IGenerateSolutionsListener> _readyListeners;

	/**
	 * the current set of legs
	 * 
	 */
	private ArrayList<CoreLeg> _theLegs;

	/**
	 * the source of states plus contributions
	 * 
	 */
	private IBoundsManager _boundsManager;

	public SolutionGenerator()
	{
		_readyListeners = new ArrayList<IGenerateSolutionsListener>();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.planetmayo.debrief.satc.model.generator.ISolutionGenerator#addReadyListener
	 * (com.planetmayo.debrief.satc.model.generator.IGenerateSolutionsListener)
	 */
	@Override
	public void addReadyListener(IGenerateSolutionsListener listener)
	{
		_readyListeners.add(listener);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.planetmayo.debrief.satc.model.generator.ISolutionGenerator#
	 * removeReadyListener
	 * (com.planetmayo.debrief.satc.model.generator.IGenerateSolutionsListener)
	 */
	@Override
	public void removeReadyListener(IGenerateSolutionsListener listener)
	{
		_readyListeners.remove(listener);
	}

	public void statesBounded(final IBoundsManager boundsManager)
	{
		_boundsManager = boundsManager;

		// ok - it's complete. now we can process it
		ProblemSpace mySpace = boundsManager.getSpace();

		// clear the legs
		if (_theLegs != null)
			_theLegs.clear();

		// get the legs
		_theLegs = getTheLegs(mySpace.states());

		// get the legs to dice themselves up
		generateRoutes(_theLegs);

		// get the legs to sort out what is achievable
		decideAchievable(_theLegs);

		// do the fancy multiplication
		int[][] achievableRes = calculateAchievableRoutesFor(_theLegs);

		// ditch the duff permutations
		cancelUnachievable(_theLegs, achievableRes);

		// ok, look for the top performer
		recalculateTopLegs();
	}

	/**
	 * calculate the top performer. this method is refactored on its own since it
	 * may get called when an estimate has changed - so the algorithm doesn't need
	 * to re-do all the leg definition bits
	 */
	private void recalculateTopLegs()
	{
		// just check we have data
		if (_boundsManager == null || _theLegs == null)
			return;

		// score the possible routes
		calculateOptimalRoutes(_boundsManager.getContributions(), _theLegs);

		// share the news
		fireLegsScored(_theLegs);

		// generate some candidate solutions
		CompositeRoute[] routes = generateCandidates(_theLegs);

		// and we're done, share the good news!
		fireSolutionsReady(routes);
	}

	/**
	 * for the set of generated routes, work out which have the highest score
	 * 
	 * @param boundsManager
	 *          the c
	 * @param theLegs
	 */
	public void calculateOptimalRoutes(
			final Collection<BaseContribution> contribs, ArrayList<CoreLeg> theLegs)
	{<commit_msg>make the recalc method vis, so we can call it from testing<commit_after>package com.planetmayo.debrief.satc.model.generator;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import com.planetmayo.debrief.satc.model.Precision;
import com.planetmayo.debrief.satc.model.contributions.BaseContribution;
import com.planetmayo.debrief.satc.model.legs.AlteringLeg;
import com.planetmayo.debrief.satc.model.legs.CompositeRoute;
import com.planetmayo.debrief.satc.model.legs.CoreLeg;
import com.planetmayo.debrief.satc.model.legs.CoreRoute;
import com.planetmayo.debrief.satc.model.legs.LegType;
import com.planetmayo.debrief.satc.model.legs.StraightLeg;
import com.planetmayo.debrief.satc.model.states.BaseRange.IncompatibleStateException;
import com.planetmayo.debrief.satc.model.states.BoundedState;
import com.planetmayo.debrief.satc.model.states.ProblemSpace;

public class SolutionGenerator implements IConstrainSpaceListener,
		ISolutionGenerator, PropertyChangeListener
{
	/**
	 * how many cells shall we break the polygons down into?
	 * 
	 */
	final int NUM_CELLS = 20;

	/**
	 * anybody interested in a new solution being ready?
	 * 
	 */
	final private ArrayList<IGenerateSolutionsListener> _readyListeners;

	/**
	 * the current set of legs
	 * 
	 */
	private ArrayList<CoreLeg> _theLegs;

	/**
	 * the source of states plus contributions
	 * 
	 */
	private IBoundsManager _boundsManager;

	public SolutionGenerator()
	{
		_readyListeners = new ArrayList<IGenerateSolutionsListener>();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.planetmayo.debrief.satc.model.generator.ISolutionGenerator#addReadyListener
	 * (com.planetmayo.debrief.satc.model.generator.IGenerateSolutionsListener)
	 */
	@Override
	public void addReadyListener(IGenerateSolutionsListener listener)
	{
		_readyListeners.add(listener);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.planetmayo.debrief.satc.model.generator.ISolutionGenerator#
	 * removeReadyListener
	 * (com.planetmayo.debrief.satc.model.generator.IGenerateSolutionsListener)
	 */
	@Override
	public void removeReadyListener(IGenerateSolutionsListener listener)
	{
		_readyListeners.remove(listener);
	}

	public void statesBounded(final IBoundsManager boundsManager)
	{
		_boundsManager = boundsManager;

		// ok - it's complete. now we can process it
		ProblemSpace mySpace = boundsManager.getSpace();

		// clear the legs
		if (_theLegs != null)
			_theLegs.clear();

		// get the legs
		_theLegs = getTheLegs(mySpace.states());

		// get the legs to dice themselves up
		generateRoutes(_theLegs);

		// get the legs to sort out what is achievable
		decideAchievable(_theLegs);

		// do the fancy multiplication
		int[][] achievableRes = calculateAchievableRoutesFor(_theLegs);

		// ditch the duff permutations
		cancelUnachievable(_theLegs, achievableRes);

		// ok, look for the top performer
		recalculateTopLegs();
	}

	/**
	 * calculate the top performer. this method is refactored on its own since it
	 * may get called when an estimate has changed - so the algorithm doesn't need
	 * to re-do all the leg definition bits
	 */
	void recalculateTopLegs()
	{
		// just check we have data
		if (_boundsManager == null || _theLegs == null)
			return;

		// score the possible routes
		calculateOptimalRoutes(_boundsManager.getContributions(), _theLegs);

		// share the news
		fireLegsScored(_theLegs);

		// generate some candidate solutions
		CompositeRoute[] routes = generateCandidates(_theLegs);

		// and we're done, share the good news!
		fireSolutionsReady(routes);
	}

	/**
	 * for the set of generated routes, work out which have the highest score
	 * 
	 * @param boundsManager
	 *          the c
	 * @param theLegs
	 */
	public void calculateOptimalRoutes(
			final Collection<BaseContribution> contribs, ArrayList<CoreLeg> theLegs)
	{
{'fraction_non_alphanumeric': 0.09574604806580131, 'fraction_numerical': 0.0005140727412928929, 'mean_word_length': 4.319207108680793, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1377015', 'n_tokens_mistral': 2680, 'n_tokens_neox': 2418, 'n_words': 564}