/*
* Copyright 2015 Daniel Dittmar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dan.dit.whatsthat.solution;
import android.support.annotation.NonNull;
import android.view.MotionEvent;
import dan.dit.whatsthat.util.compaction.Compactable;
import dan.dit.whatsthat.util.compaction.CompactedDataCorruptException;
import dan.dit.whatsthat.util.compaction.Compacter;
/**
* Abstract class of some way a user can find a {@link Solution}. A SolutionInput is drawn onto a
* canvas and user can interact by pressing down or flinging on the view. The SolutionInput
* allows a way to find the main solution word and -implementation dependant - the other solution
* words if present.<br>State of the SolutionInput can be saved by compacting it and recreating
* it with the compacted data.
* Created by daniel on 30.03.15.
*/
public abstract class SolutionInput implements Compactable {
Solution mSolution;
SolutionInputListener mListener;
/**
* Recreates the SolutionInput from the given compacted data.
* @param compacted The compacted data to recreate the SolutionInput from.
* @throws CompactedDataCorruptException If any data is missing or corrupt.
*/
SolutionInput(Compacter compacted) throws CompactedDataCorruptException {
unloadData(compacted);
}
/**
* Creates a new SolutionInput initializing it with the given Solution.
* @param solution The non null Solution to initialize.
*/
SolutionInput(@NonNull Solution solution) {
if (solution == null) {
throw new IllegalArgumentException("No solution given.");
}
initSolution(solution);
}
/**
* Sets the SolutionInputListener.
* @param listener The SolutionInputListener.
*/
synchronized void setListener(SolutionInputListener listener) {
mListener = listener;
}
/**
* Resets any user input and makes the input look like it was newly created. This is useful
* for sharing the solution input without showing the currently (partly) entered solution.
*/
public abstract void reset();
public static final int HINT_LEVEL_NONE = 0;
public static final int HINT_LEVEL_MINIMAL = 1;
public static final int HINT_LEVEL_GOOD_HELP = 10;
public static final int HINT_LEVEL_LIMITLESS = Integer.MAX_VALUE;
/**
* Provides a hint, making it easier to find the solution. How this hint is given is up to the
* implementation, though the effect of the hint should be accelerating, that is: the first
* given hint(s) should have minimal effect and hints should never make the SolutionInput
* auto solve itself.<br>
* Possible parameters: {@link SolutionInput#HINT_LEVEL_MINIMAL}, {@link
* SolutionInput#HINT_LEVEL_GOOD_HELP} or {@link SolutionInput#HINT_LEVEL_LIMITLESS}.
* @param hintLevel The maximum level of impact of the hint to provide. If there are no more
* hints available for this threshold, no new hint may be provided.
* @return True if a new hint was provided.
*/
public abstract boolean provideHint(int hintLevel);
/**
* Returns the maximum provided hint level currently given to the user. This is {@link
* SolutionInput#HINT_LEVEL_NONE} if no hint was provided yet.
* @return The maximum provided hint level.
*/
public abstract int getProvidedHintLevel();
/**
* Returns an estimated solved value between {@link Solution#SOLVED_NOTHING} and {@link
* Solution#SOLVED_COMPLETELY} to show how much the input to the SolutionInput reached the
* initialized solution. If the given solution is reached, exactly {@link
* Solution#SOLVED_COMPLETELY} is returned. Do not rely on intermediate values as this is
* just a feature for some SolutionInputs.
* @return An estimation of the solving state of the SolutionInput.
*/
public abstract int estimateSolvedValue();
/**
* Initializes a new solution for this SolutionInput. This will build the SolutionInput as
* required. If the SolutionInput supports more than the main word of the Solution is
* implementation dependant.
* @param solution A valid solution to initialize the SolutionInput with.
*/
protected abstract void initSolution(@NonNull Solution solution);
/**
* Returns the assoziated SolutionInputLayout responsible for displaying the SolutionInput.
* @return The SolutionInputLayout.
*/
abstract @NonNull SolutionInputLayout getLayout();
/**
* A fling gesture happened with a set threshold velocity and can be handled by the
* SolutionInput.
* @param startEvent The start motion event that triggered the fling gesture.
* @param endEvent The end motion event that triggered the fling gesture.
* @param velocityX The fling velocity in x direction in pixels per second.
* @param velocityY The fling velocity in y direction in pixels per second.
* @return If true, the SolutionInput will be invalidated and redrawn afterwards.
*/
public abstract boolean onFling(MotionEvent startEvent, MotionEvent endEvent, float velocityX, float velocityY);
/**
* A touch down gesture happened at the given point.
* @param x The x location of the touch down point.
* @param y The y location of the touch down point.
* @return If true, the SolutionInput will be invalidated and redrawn afterwards.
*/
public abstract boolean onUserTouchDown(float x, float y);
/**
* Returns a String representation of the currently entered user solution. This can be an
* empty String and mostly an arbitrary String as allowed by the SolutionInput.
* @return The currently entered user solution.
*/
public abstract @NonNull Solution getCurrentUserSolution();
}