package edu.vserver.exercises.math.essentials.layout;
import java.util.ArrayList;
import java.util.Random;
import fi.utu.ville.exercises.model.ExerciseData;
import fi.utu.ville.standardutils.Localizer;
public abstract class AbstractMathState<E extends ExerciseData, P extends Problem>
implements MathExerciseState<P> {
/**
*
*/
private static final long serialVersionUID = -5528193973308381408L;
private int points;
private final int rounds;
private int currentProblem = -1;
private final ArrayList<P> problems = new ArrayList<P>();
private final boolean[] problemsReplaced;
protected final Localizer localizer;
private final int AMOUNT_OF_TRIES = 6;
public AbstractMathState(E data, Localizer localizer) {
this.localizer = localizer;
this.rounds = loadDataAndGetAmount(data);
problemsReplaced = new boolean[rounds];
initProblems();
}
/**
* Saves the specific ExerciseData for this exercise type for later use.
*
* @param data
* The data used to generate exercises.
* @return The number of exercises what will be generated.
*/
abstract protected int loadDataAndGetAmount(E data);
/**
* Creates a single problem.
*
* @return a single problem that conforms to the exercise data loaded in <b>loadDataAndGetAmount </b>
*/
abstract protected P createProblem();
protected Localizer getLocalizer() {
return localizer;
}
@Override
public double getCorrectness() {
double points = 0.0;
points = (double) getPoints() / (double) rounds;
return points;
}
public int getPoints() {
return points;
}
public void setPoints() {
points++;
}
@Override
public int getProblemCount() {
return rounds;
}
@Override
public P getProblem(int i) {
return problems.get(i);
}
@Override
public P getCurrentProblem() {
return problems.get(currentProblem);
}
@Override
public P nextProblem() {
currentProblem++;
return getCurrentProblem();
}
private void initProblems() {
problems.clear();
for (int i = 0; i < rounds; i++) {
P prob = createUnequalProblem(AMOUNT_OF_TRIES);
if (prob != null) {
problems.add(prob);
problemsReplaced[i] = false;
} else {
break;
}
}
}
private P createUnequalProblem(int amountOfTries) {
try {
if (amountOfTries < 1) {
return createProblem();
}
P problemProposition = createProblem();
for (P p : problems) {
if (p.getQuestion(localizer).equals(problemProposition.getQuestion(localizer))) {
// System.out.println("Found an equal problem: " + p.getQuestion(localizer));
return createUnequalProblem(--amountOfTries);
}
}
// System.out.println("Not equal problems: " + problemProposition.getQuestion(localizer));
if (problemProposition == null) {
System.out.println("problem proposition = null");
}
return problemProposition;
} catch (Exception e) {
return null;
}
}
@Override
public void reset() {
points = 0;
currentProblem = -1;
initProblems();
}
@Override
public boolean tryAnswer(AbstractMathAnswer answer) {
if (getCurrentProblem().tryAnswer(answer)) {
setPoints();
}
return getCurrentProblem().tryAnswer(answer);
}
@Override
public boolean tryAnswer(AbstractMathAnswer answer, boolean isExam) {
if (getCurrentProblem().tryAnswer(answer)) {
setPoints();
} else {
if (!isExam) {
// System.out.println("CurrentP: " + problems.get(currentProblem).getQuestion(localizer));
// System.out.println("NextP: " + problems.get(currentProblem + 1).getQuestion(localizer));
if (problems.size() - currentProblem >= 3) {
// Random rand = new Random();
int randomIndex = getRandomUnusedInt();
if (problems.size() > randomIndex || randomIndex < 1) {
P clone = getCurrentProblem().cloneThis(getCurrentProblem());
if (clone != null) {
problems.set(randomIndex, clone);
}
} else {
// System.out.println("Faulty random number generated: " + randomIndex);
}
}
}
}
return getCurrentProblem().tryAnswer(answer);
}
@Override
public boolean hasNextProblem() {
return currentProblem < problems.size() - 1;
}
private int getRandomUnusedInt() {
Random rand = new Random();
int randomIndex = 0;
for (int i = 0; i < 4; i++) {
randomIndex = rand.nextInt((problems.size() - 1) - (currentProblem + 2) + 1) + currentProblem + 2;
if (problemsReplaced[randomIndex] == false) {
// System.out.println("problem inserted to: " + randomIndex);
problemsReplaced[randomIndex] = true;
return randomIndex;
} else {
// System.out.println("already modified: " + randomIndex);
}
}
return randomIndex;
}
}