package org.geogebra.common.main;
import java.util.Date;
import java.util.LinkedList;
import org.geogebra.common.kernel.commands.CmdGetTime;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.main.settings.Settings;
import org.geogebra.common.util.debug.Log;
//import com.google.gwt.i18n.client.DateTimeFormat;
public class ExamEnvironment {
long examStartTime = -1;
protected LinkedList<Long> cheatingTimes = null;
protected enum CheatingEvent {
WINDOWS_LEFT, WINDOW_ENTERED, AIRPLANE_MODE_OFF, AIRPLANE_MODE_ON, WIFI_ENABLED, WIFI_DISABLED,
TASK_UNLOCKED, TASK_LOCKED, BLUETOOTH_ENABLED, BLUETOOTH_DISABLED,
SCREEN_ON, SCREEN_OFF
}
protected LinkedList<CheatingEvent> cheatingEvents = null;
private long closed = -1;
private long maybeCheating = -1;
private boolean lastCheatingEventWindowWasLeft;
private boolean hasGraph = false;
public long getStart() {
return examStartTime;
}
public void setStart(long time) {
examStartTime = time;
lastCheatingEventWindowWasLeft = false;
}
public void startCheating(String os) {
maybeCheating = System.currentTimeMillis();
checkCheating(os); // needed for ctr+win+down
}
public void checkCheating(String os) {
boolean delay;
// needed for GGB-1211
if (os.contains("iOS")) {
if (maybeCheating < System.currentTimeMillis() - 100) {
delay = true;
} else {
delay = false;
}
} else {
delay = true;
}
// if (maybeCheating > 0 && maybeCheating < System.currentTimeMillis() -
// 100) {
if (maybeCheating > 0 && delay) {
maybeCheating = -1;
if (getStart() > 0) {
initLists();
if (cheatingEvents.size() == 0
|| !lastCheatingEventWindowWasLeft) {
addCheatingWindowsLeft(System.currentTimeMillis());
lastCheatingEventWindowWasLeft = true;
Log.debug("STARTED CHEATING");
}
}
}
}
protected void addCheatingWindowsLeft(long time) {
cheatingTimes.add(time);
cheatingEvents.add(CheatingEvent.WINDOWS_LEFT);
}
public void stopCheating() {
maybeCheating = -1;
if (cheatingTimes == null || getStart() < 0) {
return;
}
if (cheatingEvents.size() > 0 && lastCheatingEventWindowWasLeft) {
cheatingTimes.add(System.currentTimeMillis());
cheatingEvents.add(CheatingEvent.WINDOW_ENTERED);
lastCheatingEventWindowWasLeft = false;
Log.debug("STOPPED CHEATING");
}
}
protected void initLists() {
if (cheatingTimes == null) {
cheatingTimes = new LinkedList<Long>();
cheatingEvents = new LinkedList<CheatingEvent>();
}
}
public boolean isCheating() {
return cheatingTimes != null;
}
private static String getLocalizedTimeOnly(Localization loc, long time) {
// eg "14:08:48"
return CmdGetTime.buildLocalizedDate("\\H:\\i:\\s", new Date(time),
loc);
}
private static String getLocalizedDateOnly(Localization loc, long time) {
// eg "Fri 23 October 2015"
// don't use \\S for 23rd (not used in eg French)
return CmdGetTime.buildLocalizedDate("\\D, \\j \\F \\Y", new Date(time),
loc);
}
/**
* NEW LOG DIALOG
*/
public String getLog(Localization loc, Settings settings) {
StringBuilder sb = new StringBuilder();
// Deactivated Views
boolean supportsCAS = settings.getCasSettings().isEnabled();
boolean supports3D = settings.getEuclidian(-1).isEnabled();
if (!hasGraph) {
if (!supportsCAS || !supports3D) {
sb.append(loc.getMenu("exam_views_deactivated"));
sb.append(": ");
}
if (!supportsCAS) {
sb.append(loc.getMenu("Perspective.CAS"));
}
if (!supportsCAS && !supports3D) {
sb.append(", ");
}
if (!supports3D) {
sb.append(loc.getMenu("Perspective.3DGraphics"));
}
sb.append("<br>");
}
// Exam Start Date
sb.append(loc.getMenu("exam_start_date"));
sb.append(": ");
sb.append(getLocalizedDateOnly(loc, examStartTime));
sb.append("<br>");
// Exam Start Time
sb.append(loc.getMenu("exam_start_time"));
sb.append(": ");
sb.append(getLocalizedTimeOnly(loc, examStartTime));
sb.append("<br>");
// Exam End Time
if (closed > 0) {
sb.append(loc.getMenu("exam_end_time"));
sb.append(": ");
sb.append(getLocalizedTimeOnly(loc, closed));
sb.append("<br>");
}
sb.append("<hr>");
sb.append("<br>");
// Log times
sb.append("0:00");
sb.append(' ');
sb.append(loc.getMenu("exam_started"));
sb.append("<br>");
if (cheatingTimes != null) {
for (int i = 0; i < cheatingTimes.size(); i++) {
sb.append(timeToString(cheatingTimes.get(i)));
sb.append(' ');
sb.append(getCheatingString(cheatingEvents.get(i), loc));
sb.append("<br>");
}
}
if (closed > 0) {
sb.append(timeToString(closed)); // get exit timestamp
sb.append(' ');
sb.append(loc.getMenu("exam_ended"));
}
return sb.toString();
}
static private String getCheatingString(CheatingEvent cheatingEvent,
Localization loc) {
switch (cheatingEvent) {
case WINDOWS_LEFT: // CHEATING ALERT: exam left
return loc.getMenu("exam_log_window_left");
case WINDOW_ENTERED: // exam active again
return loc.getMenu("exam_log_window_entered");
case AIRPLANE_MODE_OFF:
return loc.getMenu("exam_log_airplane_mode_off");
case AIRPLANE_MODE_ON:
return loc.getMenu("exam_log_airplane_mode_on");
case WIFI_DISABLED:
return loc.getMenu("exam_log_wifi_disabled");
case WIFI_ENABLED:
return loc.getMenu("exam_log_wifi_enabled");
case TASK_LOCKED:
return loc.getMenu("exam_log_pin");
case TASK_UNLOCKED:
return loc.getMenu("exam_log_unpin");
case BLUETOOTH_ENABLED:
return loc.getMenu("exam_log_bluetooth_enabled");
case BLUETOOTH_DISABLED:
return loc.getMenu("exam_log_bluetooth_disabled");
case SCREEN_OFF:
return loc.getMenu("exam_log_screen_off");
case SCREEN_ON:
return loc.getMenu("exam_log_screen_on");
}
return "";
}
public boolean getHasGraph() {
return hasGraph;
}
public void setHasGraph(boolean hasGraph) {
this.hasGraph = hasGraph;
}
public String timeToString(long timestamp) {
if (examStartTime < 0) {
return "0:00";
}
int secs = (int) ((timestamp - examStartTime) / 1000);
int mins = secs / 60;
secs -= mins * 60;
String secsS = secs + "";
if (secs < 10) {
secsS = "0" + secsS;
}
return mins + ":" + secsS;
}
public void exit() {
this.closed = System.currentTimeMillis();
}
public String getSyntax(String cmdInt, Localization loc,
Settings settings) {
if (settings.getCasSettings().isEnabled()) {
return loc.getCommandSyntax(cmdInt);
}
Commands cmd = null;
try {
cmd = Commands.valueOf(cmdInt);
} catch (Exception e) {
// macro or error
}
if (cmd == null) {
return loc.getCommandSyntax(cmdInt);
}
// IntegralBetween gives all syntaxes. Typing Integral or NIntegral
// gives suggestions for NIntegral
switch (cmd) {
case Integral:
case NIntegral:
return loc.getCommandSyntaxCAS("NIntegral");
case LocusEquation:
case Envelope:
case TrigSimplify:
case Expand:
case Factor:
case IFactor:
case Simplify:
case SurdText:
case ParametricDerivative:
case Derivative:
case TrigExpand:
case TrigCombine:
case Limit:
case LimitBelow:
case LimitAbove:
case Degree:
case Coefficients:
case PartialFractions:
case SolveODE:
case ImplicitDerivative:
case NextPrime:
case PreviousPrime:
return null;
default:
return loc.getCommandSyntax(cmdInt);
}
}
}