class RetrySimulator {

	private final SleepingBackOffPolicy<?> backOffPolicy;

	private final RetryPolicy retryPolicy;

	public RetrySimulator(SleepingBackOffPolicy<?> backOffPolicy, RetryPolicy retryPolicy) {
		this.backOffPolicy = backOffPolicy;
		this.retryPolicy = retryPolicy;
	}

	/**
	 * Execute the simulator for a give # of iterations.
	 * @param numSimulations Number of simulations to run
	 * @return the outcome of all simulations
	 */
	public RetrySimulation executeSimulation(int numSimulations) {<FILL_FUNCTION_BODY>}

	/**
	 * Execute a single simulation
	 * @return The sleeps which occurred within the single simulation.
	 */
	public List<Long> executeSingleSimulation() {
		StealingSleeper stealingSleeper = new StealingSleeper();
		SleepingBackOffPolicy<?> stealingBackoff = backOffPolicy.withSleeper(stealingSleeper);

		RetryTemplate template = new RetryTemplate();
		template.setBackOffPolicy(stealingBackoff);
		template.setRetryPolicy(retryPolicy);

		try {
			template.execute(new FailingRetryCallback());
		}
		catch (FailingRetryException e) {

		}
		catch (Throwable e) {
			throw new RuntimeException("Unexpected exception", e);
		}

		return stealingSleeper.getSleeps();
	}

	static class FailingRetryCallback implements RetryCallback<Object, Exception> {

		public Object doWithRetry(RetryContext context) throws Exception {
			throw new FailingRetryException();
		}

	}

	@SuppressWarnings("serial")
	static class FailingRetryException extends Exception {

	}

	@SuppressWarnings("serial")
	static class StealingSleeper implements Sleeper {

		private final List<Long> sleeps = new ArrayList<>();

		public void sleep(long backOffPeriod) throws InterruptedException {
			sleeps.add(backOffPeriod);
		}

		public List<Long> getSleeps() {
			return sleeps;
		}

	}

}

		RetrySimulation simulation = new RetrySimulation();

		for (int i = 0; i < numSimulations; i++) {
			simulation.addSequence(executeSingleSimulation());
		}
		return simulation;
	
<no_super_class>