<commit_before>/*
 *    Debrief - the Open Source Maritime Analysis Application
 *    http://debrief.info
 *
 *    (C) 2000-2014, PlanetMayo Ltd
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the Eclipse Public License v1.0
 *    (http://www.eclipse.org/legal/epl-v10.html)
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 */
package org.mwc.debrief.core.ContextOperations;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.mwc.cmap.core.CorePlugin;
import org.mwc.cmap.core.operations.CMAPOperation;
import org.mwc.cmap.core.property_support.RightClickSupport.RightClickContextItemGenerator;

import Debrief.Wrappers.FixWrapper;
import Debrief.Wrappers.TrackWrapper;
import Debrief.Wrappers.Track.TrackSegment;
import MWC.GUI.Editable;
import MWC.GUI.Layer;
import MWC.GUI.Layers;
import MWC.GenericData.HiResDate;
import MWC.GenericData.WorldDistance;
import MWC.GenericData.WorldLocation;
import MWC.GenericData.WorldSpeed;
import MWC.GenericData.WorldVector;

/**
 * @author ian.mayo
 */
public class RemoveTrackJumps implements RightClickContextItemGenerator
{

	/**
	 * @param parent
	 *          menu
	 * @param theLayers
	 *          the whole layers
	 * @param parentLayers
	 *          the parent layers for the selected items
	 * @param subjects
	 *          the selected items
	 */
	public void generate(final IMenuManager parent, final Layers theLayers,
			final Layer[] parentLayers, final Editable[] subjects)
	{
		Collection<Editable> points = null;
		String tmpTitle = null;

		// how many items are selected?
		if (subjects.length == 1)
		{
			// is it a track?
			final Editable thisE = subjects[0];
			if (thisE instanceof TrackSegment)
			{
				TrackSegment ts = (TrackSegment) thisE;
				points = ts.getData();
				tmpTitle = "Remove jumps for selected track";
			}
		}
		else
		{
			// see if it's a series of points
			final Editable thisE = subjects[0];
			if (thisE instanceof FixWrapper)
			{
				// collate the points into a collection
				points = new Vector<Editable>();

				// loop through the data
				for (int i = 0; i < subjects.length; i++)
				{
					Editable editable = subjects[i];
					points.add(editable);
				}

				tmpTitle = "Remove jumps in selected positions";
			}
		}

		// ok, is it worth going for?
		if (points != null)
		{
			final String title = tmpTitle;
			final Collection<Editable> permPoints = points;

			// right,stick in a separator
			parent.add(new Separator());

			final TrackWrapper track = (TrackWrapper) parentLayers[0];

			// and the new drop-down list of interpolation frequencies

			// yes, create the action
			final Action convertToTrack = new Action(title)
			{
				public void run()
				{
					// ok, go for it.
					// sort it out as an operation
					final IUndoableOperation removeJumps = new RemoveJumps(title,
							theLayers, track, permPoints);

					// ok, stick it on the buffer
					CorePlugin.run(removeJumps);
				}

			};
			parent.add(convertToTrack);
		}

	}

	static ArrayList<Leg> getLegs(final Collection<Editable> points)
	{
		// prepare to store the legs
		ArrayList<Leg> legs = new ArrayList<Leg>();

		// get the points
		Iterator<Editable> iter = points.iterator();

		// store the first point as a start
		FixWrapper startP = (FixWrapper) iter.next();

		// remember the previous position
		FixWrapper prevprev = null;
		FixWrapper prev = startP;

		while (iter.hasNext())
		{
			FixWrapper fix = (FixWrapper) iter.next();

			// ok, what's the distance from the previous position
			double locDeltaDegs = fix.getLocation().rangeFrom(prev.getLocation());
			WorldDistance delta = new WorldDistance(locDeltaDegs, WorldDistance.DEGS);

			// and how long did it take?
			double timeDeltaMillis = fix.getDateTimeGroup().getDate().getTime()
					- prev.getDateTimeGroup().getDate().getTime();
			double timeDeltaHours = timeDeltaMillis / 1000 / 60 / 60d;

			// what's the effective speed
			WorldSpeed speedTravelled = new WorldSpeed(
					delta.getValueIn(WorldDistance.MINUTES) / timeDeltaHours,
					WorldSpeed.Kts);

			// is there a previous position?
			if (prev != null)
			{
				// what was the previous speed?
				double thisSpeedKts = speedTravelled.getValueIn(WorldSpeed.Kts);
				double lastSpdKts = prev.getSpeed();

				// is this so fast that it can only be a jump?
				if (thisSpeedKts > 3 * lastSpdKts)
				{
					// ok, we've found a jump
					legs.add(new Leg(startP, prevprev, prev, fix));

					// ok, the lock point becomes the first point of the next leg
					startP = fix;
				}
			}
			// ok, now move along the bed
			prevprev = prev;
			prev = fix;
		}

		return legs;
	}

	/**
	 * which leg is this position in?
	 * 
	 * @param thisP
	 *          the position
	 * @param legs
	 *          the lsit of legs
	 * @return
	 */
	static Leg findLegFor(FixWrapper thisP, ArrayList<Leg> legs)
	{
		HiResDate theTime = thisP.getTime();

		Leg res = null;

		// loop through the legs
		for (Iterator<Leg> iterator = legs.iterator(); iterator.hasNext();)<commit_msg>last tidying<commit_after>/*
 *    Debrief - the Open Source Maritime Analysis Application
 *    http://debrief.info
 *
 *    (C) 2000-2014, PlanetMayo Ltd
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the Eclipse Public License v1.0
 *    (http://www.eclipse.org/legal/epl-v10.html)
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 */
package org.mwc.debrief.core.ContextOperations;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.mwc.cmap.core.CorePlugin;
import org.mwc.cmap.core.operations.CMAPOperation;
import org.mwc.cmap.core.property_support.RightClickSupport.RightClickContextItemGenerator;

import Debrief.Wrappers.FixWrapper;
import Debrief.Wrappers.TrackWrapper;
import Debrief.Wrappers.Track.TrackSegment;
import MWC.GUI.Editable;
import MWC.GUI.Layer;
import MWC.GUI.Layers;
import MWC.GenericData.HiResDate;
import MWC.GenericData.WorldDistance;
import MWC.GenericData.WorldLocation;
import MWC.GenericData.WorldSpeed;
import MWC.GenericData.WorldVector;

/**
 * @author ian.mayo
 */
public class RemoveTrackJumps implements RightClickContextItemGenerator
{

	/**
	 * @param parent
	 *          menu
	 * @param theLayers
	 *          the whole layers
	 * @param parentLayers
	 *          the parent layers for the selected items
	 * @param subjects
	 *          the selected items
	 */
	public void generate(final IMenuManager parent, final Layers theLayers,
			final Layer[] parentLayers, final Editable[] subjects)
	{
		Collection<Editable> points = null;
		String tmpTitle = null;

		// how many items are selected?
		if (subjects.length == 1)
		{
			// is it a track?
			final Editable thisE = subjects[0];
			if (thisE instanceof TrackSegment)
			{
				TrackSegment ts = (TrackSegment) thisE;
				points = ts.getData();
				tmpTitle = "Remove jumps for selected track";
			}
		}
		else
		{
			// see if it's a series of points
			final Editable thisE = subjects[0];
			if (thisE instanceof FixWrapper)
			{
				// collate the points into a collection
				points = new Vector<Editable>();

				// loop through the data
				for (int i = 0; i < subjects.length; i++)
				{
					Editable editable = subjects[i];
					points.add(editable);
				}

				tmpTitle = "Remove jumps in selected positions";
			}
		}

		// ok, is it worth going for?
		if (points != null)
		{
			final String title = tmpTitle;
			final Collection<Editable> permPoints = points;

			// right,stick in a separator
			parent.add(new Separator());

			final TrackWrapper track = (TrackWrapper) parentLayers[0];

			// and the new drop-down list of interpolation frequencies

			// yes, create the action
			final Action convertToTrack = new Action(title)
			{
				public void run()
				{
					// ok, go for it.
					// sort it out as an operation
					final IUndoableOperation removeJumps = new RemoveJumps(title,
							theLayers, track, permPoints);

					// ok, stick it on the buffer
					CorePlugin.run(removeJumps);
				}

			};
			parent.add(convertToTrack);
		}

	}

	/** find the legs in the block of data
	 * 
	 * @param points
	 * @return
	 */
	static ArrayList<Leg> getLegs(final Collection<Editable> points)
	{
		// prepare to store the legs
		final ArrayList<Leg> legs = new ArrayList<Leg>();

		// get the points
		final Iterator<Editable> iter = points.iterator();

		// store the first point as a start
		FixWrapper startP = (FixWrapper) iter.next();

		// remember the previous position (which we use to "plot on" the last point)
		FixWrapper prevprev = null;
		FixWrapper prev = startP;

		while (iter.hasNext())
		{
			final FixWrapper fix = (FixWrapper) iter.next();

			// is there a previous position?
			if (prev != null)
			{
				// ok, what's the distance from the previous position
				final double locDeltaDegs = fix.getLocation().rangeFrom(prev.getLocation());
				final WorldDistance delta = new WorldDistance(locDeltaDegs, WorldDistance.DEGS);

				// and how long did it take?
				final double timeDeltaMillis = fix.getDateTimeGroup().getDate().getTime()
						- prev.getDateTimeGroup().getDate().getTime();
				final double timeDeltaHours = timeDeltaMillis / 1000 / 60 / 60d;
				
				// what's the effective speed
				final WorldSpeed speedTravelled = new WorldSpeed(
						delta.getValueIn(WorldDistance.MINUTES) / timeDeltaHours,
						WorldSpeed.Kts);

				// what was the previous speed?
				double thisSpeedKts = speedTravelled.getValueIn(WorldSpeed.Kts);
				double lastSpdKts = prev.getSpeed();

				// is this so fast that it can only be a jump?
				if (thisSpeedKts > 3 * lastSpdKts)
				{
					// ok, we've found a jump
					legs.add(new Leg(startP, prevprev, prev, fix));

					// ok, the lock point becomes the first point of the next leg
					startP = fix;
				}
			}
			
			// ok, now move along the bed
			prevprev = prev;
			prev = fix;
		}

		return legs;
	}

	/**
	 * which leg is this position in?
	 * 
	 * @param thisP
	 *          the position
	 * @param legs
	 *          the lsit of legs
	 * @return
	 */
	static Leg findLegFor(FixWrapper thisP, ArrayList<Leg> legs)
	{
		HiResDate theTime = thisP.getTime();

		Leg res = null;

		// loop through the legs
		for (Iterator<Leg> iterator = legs.iterator(); iterator.hasNext();)
{'fraction_non_alphanumeric': 0.10086926585764695, 'fraction_numerical': 0.004475428177984336, 'mean_word_length': 3.158911954187545, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5715132', 'n_tokens_mistral': 4117, 'n_tokens_neox': 3485, 'n_words': 1070}