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

import java.util.Date;
import java.util.Iterator;

import com.planetmayo.debrief.satc.model.states.BaseRange.IncompatibleStateException;
import com.planetmayo.debrief.satc.model.states.BoundedState;
import com.planetmayo.debrief.satc.model.states.CourseRange;
import com.planetmayo.debrief.satc.model.states.LocationRange;
import com.planetmayo.debrief.satc.model.states.ProblemSpace;
import com.planetmayo.debrief.satc.model.states.SpeedRange;
import com.planetmayo.debrief.satc.util.GeoSupport;
import com.vividsolutions.jts.algorithm.Angle;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.util.AffineTransformation;

public class LocationAnalysisContribution extends BaseContribution
{

	@Override
	public void actUpon(ProblemSpace space) throws IncompatibleStateException
	{
		// remember the previous state
		BoundedState _lastState = null;

		// ok, loop through the states
		Iterator<BoundedState> iter = space.states().iterator();
		while (iter.hasNext())
		{
			BoundedState thisS = (BoundedState) iter.next();

			// does it have a location?
			LocationRange loc = thisS.getLocation();
			if (loc != null)
			{
				// ok, do we have a previous state
				if (_lastState != null)
				{

					// ok. sort out the constraints from the last state
					LocationRange newConstraint = getRangeFor(_lastState, thisS.getTime());

					// now apply those constraints to me
					loc.constrainTo(newConstraint);
				}

				// ok, remember, and move on
				_lastState = thisS;
			}

		}
	}

	public LinearRing getCourseRing(CourseRange course, double maxRng)
	{
		// double the max range = to be sure we cover the possible curved arc

		// ok, produce the arcs
		Coordinate[] coords = new Coordinate[5];

		double minC = Angle.toRadians(course.getMin());
		double maxC = Angle.toRadians(course.getMax());
		double centreC = minC + (maxC - minC) / 2d;

		// start with the origin
		coords[0] = new Coordinate(0, 0);

		// now the start course
		coords[1] = new Coordinate(Math.sin(minC) * maxRng, Math.cos(minC) * maxRng);

		// give us a centre course
		coords[2] = new Coordinate(Math.sin(centreC) * (maxRng * 1.4),
				Math.cos(centreC) * (maxRng * 1.4));

		// now the end course
		coords[3] = new Coordinate(Math.sin(maxC) * maxRng, Math.cos(maxC) * maxRng);

		// back to the orgin
		coords[4] = new Coordinate(0, 0);

		return GeoSupport.getFactory().createLinearRing(coords);
	}

	public LocationRange getRangeFor(BoundedState state, Date newDate)
	{
		LinearRing res = null;

		// how long have we travelled?
		long diff = newDate.getTime() - state.getTime().getTime();

		// ok, generate the achievable bounds for the state
		CourseRange course = state.getCourse();
		LinearRing courseR = getCourseRing(course,
				getMaxRangeDegs(state.getSpeed(), diff));

		Polygon speedR = getSpeedRing(state.getSpeed(), diff);

		GeoSupport.writeGeometry("course geometry", courseR);
	//	GeoSupport.writeGeometry("speed geometry", speedR);

		// now combine the two
		final LineString achievable;
		if (speedR != null)
		{
			if (courseR != null)
			{
				// ok, first we do the overlaps one at a time
				LinearRing outer = (LinearRing) speedR.getExteriorRing();
				GeoSupport.writeGeometry("outer", outer);
				Geometry nextR = outer.intersection(courseR);
				GeoSupport.writeGeometry("constrained outer", nextR);
				
				
				
				Geometry multiL = courseR.intersection(speedR);
		//		GeoSupport.writeGeometry("intersected speed", multiL);
				achievable = (LineString) speedR.getGeometryN(0);
			}
			else
			{
				achievable = (LineString) speedR.clone();
			}
		}
		else
		{
			if (courseR != null)
			{
				achievable = (LineString) courseR.clone();
			}
			else
			{
				// nope, we don't have any bounds<commit_msg>minor comment<commit_after>package com.planetmayo.debrief.satc.model.contributions;

import java.util.Date;
import java.util.Iterator;

import com.planetmayo.debrief.satc.model.states.BaseRange.IncompatibleStateException;
import com.planetmayo.debrief.satc.model.states.BoundedState;
import com.planetmayo.debrief.satc.model.states.CourseRange;
import com.planetmayo.debrief.satc.model.states.LocationRange;
import com.planetmayo.debrief.satc.model.states.ProblemSpace;
import com.planetmayo.debrief.satc.model.states.SpeedRange;
import com.planetmayo.debrief.satc.util.GeoSupport;
import com.vividsolutions.jts.algorithm.Angle;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.util.AffineTransformation;

public class LocationAnalysisContribution extends BaseContribution
{

	@Override
	public void actUpon(ProblemSpace space) throws IncompatibleStateException
	{
		// remember the previous state
		BoundedState _lastState = null;

		// ok, loop through the states
		Iterator<BoundedState> iter = space.states().iterator();
		while (iter.hasNext())
		{
			BoundedState thisS = (BoundedState) iter.next();

			// does it have a location?
			LocationRange loc = thisS.getLocation();
			if (loc != null)
			{
				// ok, do we have a previous state
				if (_lastState != null)
				{

					// ok. sort out the constraints from the last state
					LocationRange newConstraint = getRangeFor(_lastState, thisS.getTime());

					// now apply those constraints to me
					loc.constrainTo(newConstraint);
				}

				// ok, remember, and move on
				_lastState = thisS;
			}

		}
	}

	public LinearRing getCourseRing(CourseRange course, double maxRng)
	{
		// double the max range = to be sure we cover the possible curved arc

		// ok, produce the arcs
		Coordinate[] coords = new Coordinate[5];

		double minC = Angle.toRadians(course.getMin());
		double maxC = Angle.toRadians(course.getMax());
		double centreC = minC + (maxC - minC) / 2d;

		// start with the origin
		coords[0] = new Coordinate(0, 0);

		// now the start course
		coords[1] = new Coordinate(Math.sin(minC) * maxRng, Math.cos(minC) * maxRng);

		// give us a centre course
		coords[2] = new Coordinate(Math.sin(centreC) * (maxRng * 1.4),
				Math.cos(centreC) * (maxRng * 1.4));

		// now the end course
		coords[3] = new Coordinate(Math.sin(maxC) * maxRng, Math.cos(maxC) * maxRng);

		// back to the orgin
		coords[4] = new Coordinate(0, 0);

		return GeoSupport.getFactory().createLinearRing(coords);
	}

	public LocationRange getRangeFor(BoundedState state, Date newDate)
	{
		LinearRing res = null;

		// how long have we travelled?
		long diff = newDate.getTime() - state.getTime().getTime();

		// ok, generate the achievable bounds for the state
		CourseRange course = state.getCourse();
		LinearRing courseR = getCourseRing(course,
				getMaxRangeDegs(state.getSpeed(), diff));

		Polygon speedR = getSpeedRing(state.getSpeed(), diff);

		GeoSupport.writeGeometry("course geometry", courseR);
	//	GeoSupport.writeGeometry("speed geometry", speedR);

		// now combine the two
		final LineString achievable;
		if (speedR != null)
		{
			if (courseR != null)
			{
				// ok, first we do the overlaps one at a time
				LinearRing outer = (LinearRing) speedR.getExteriorRing();
				GeoSupport.writeGeometry("outer", outer);
				Geometry nextR = outer.intersection(courseR);
				GeoSupport.writeGeometry("constrained outer", nextR);
				
				// TODO: nextR is just two points, I'm sure it should be a region
				
				Geometry multiL = courseR.intersection(speedR);
		//		GeoSupport.writeGeometry("intersected speed", multiL);
				achievable = (LineString) speedR.getGeometryN(0);
			}
			else
			{
				achievable = (LineString) speedR.clone();
			}
		}
		else
		{
			if (courseR != null)
			{
				achievable = (LineString) courseR.clone();
			}
			else
			{
				// nope, we don't have any bounds
{'fraction_non_alphanumeric': 0.1154364059248378, 'fraction_numerical': 0.003917248133186437, 'mean_word_length': 3.8087110064743968, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '2281820', 'n_tokens_mistral': 3114, 'n_tokens_neox': 2688, 'n_words': 639}