/*
* File : ComplexEvaluator.java
* Created : 11-jun-2001 14:56
* By : fbusquets
*
* JClic - Authoring and playing system for educational activities
*
* Copyright (C) 2000 - 2005 Francesc Busquets & Departament
* d'Educacio de la Generalitat de Catalunya
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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. See the
* GNU General Public License for more details (see the LICENSE file).
*/
package edu.xtec.jclic.activities.text;
import edu.xtec.jclic.project.JClicProject;
import edu.xtec.util.JDomUtility;
/**
*
* @author Francesc Busquets (fbusquets@xtec.cat)
* @version 13.08.28
*/
public class ComplexEvaluator extends BasicEvaluator {
public static final String DETAIL="detail";
public static final String CHECK_STEPS="checkSteps";
public static final int DEFAULT_CHECK_STEPS=3;
public static final String CHECK_SCOPE="checkScope";
public static final int DEFAULT_CHECK_SCOPE=6;
protected boolean detail;
protected int checkSteps;
protected int checkScope;
/** Creates new ComplexEvaluator */
public ComplexEvaluator(JClicProject project){
super(project);
detail=true;
checkSteps=DEFAULT_CHECK_STEPS;
checkScope=DEFAULT_CHECK_SCOPE;
}
@Override
public org.jdom.Element getJDomElement(){
org.jdom.Element e=super.getJDomElement();
if(!detail)
e.setAttribute(DETAIL, JDomUtility.boolString(detail));
if(checkSteps!=DEFAULT_CHECK_STEPS)
e.setAttribute(CHECK_STEPS, Integer.toString(checkSteps));
if(checkScope!=DEFAULT_CHECK_SCOPE)
e.setAttribute(CHECK_SCOPE, Integer.toString(checkScope));
return e;
}
@Override
public void setProperties(org.jdom.Element e, Object aux) throws Exception{
super.setProperties(e, aux);
detail=JDomUtility.getBoolAttr(e, DETAIL, true);
checkSteps=JDomUtility.getIntAttr(e, CHECK_STEPS, DEFAULT_CHECK_STEPS);
checkScope=JDomUtility.getIntAttr(e, CHECK_SCOPE, DEFAULT_CHECK_SCOPE);
}
@Override
public void setProperties(edu.xtec.jclic.clic3.Clic3Activity c3a){
super.setProperties(c3a);
detail=c3a.avLletra;
checkSteps=c3a.avScope;
checkScope=c3a.avMaxScope;
}
@Override
protected void init(){
super.init();
}
@Override
public byte[] evalText(String text, String[] match){
if(!detail)
return super.evalText(text, match);
int [] numChecks=new int[match.length];
int maxCheck=-1, maxCheckIndex=-1;
byte [][]flags=new byte[match.length][];
boolean [] skipped=new boolean[text.length()];
String sText=getClearedText(text, skipped);
for(int i=0; i<match.length; i++){
String sMatch=getClearedText(match[i]);
flags[i]=new byte[sText.length()];
boolean ok=compareSegment(sText, sText.length(), match[i], match[i].length(), flags[i], false);
numChecks[i]=countFlagsOk(flags[i]);
if(ok){
maxCheckIndex=i;
maxCheck=numChecks[i];
}
}
if(maxCheckIndex==-1){
for(int i=0; i<match.length; i++){
if(numChecks[i]>maxCheck){
maxCheck=numChecks[i];
maxCheckIndex=i;
}
}
}
byte[] returnFlags=new byte[text.length()];
for(int i=0, k=0; i<text.length(); i++){
if(skipped[i]) returnFlags[i]=FLAG_OK;
else returnFlags[i]=flags[maxCheckIndex][k++];
}
return returnFlags;
}
private int countFlagsOk(byte[] flags){
int r=0;
for(int i=0; i<flags.length; i++)
if(flags[i]==Evaluator.FLAG_OK) r++;
return r;
}
private boolean compareSegment(String src, int ls, String ok, int lok, byte[] attr, boolean iterate){
int coinci;
int is, iok, lastIs;
boolean lastiok=true;
boolean result=true;
char chs, chok;
coinci=0;
if(ls==0 || lok==0 || src==null || ok==null) return false;
//chs=chok= iterate ? 0 : ' ';
lastIs=0;
for(iok=0, is=0; is<ls; is++, iok++){
chs=src.charAt(is);
lastIs=is;
if(iok>=0 && iok<lok)
chok=ok.charAt(iok);
else
chok=0;
if(collator.equals(new String(new char[]{chs}), new String(new char[]{chok}))){
coinci++;
attr[is]=Evaluator.FLAG_OK;
lastiok=true;
} else{
result=false;
attr[is]=Evaluator.FLAG_DEFAULT_ERROR;
if(!iterate && lastiok && chok!=0 && checkSteps>0 && checkScope>0){
int lbloc=2*checkSteps+1;
int[] itcoinc=new int[lbloc];
int i=0, j, is2, iok2, ls2, lok2, jmax;
for(j=0; j<lbloc; j++){
itcoinc[j]=0;
i=iok+((j+1)/2)*((j&1)!=0 ? 1 : -1);
if(i>=lok) continue;
is2=(i<0 ? is-i:is);
if(is2>=ls) continue;
ls2=(ls2=ls-is2)>checkScope ? checkScope : ls2;
iok2=(i<0 ? 0:i);
lok2=(lok2=lok-iok2)>checkScope ? checkScope : lok2;
byte[] flags2=new byte[src.length()-is2];
boolean result2=compareSegment(src.substring(is2), ls2, ok.substring(iok2), lok2, flags2, true);
itcoinc[j]=countFlagsOk(flags2);
if(result2) break;
}
if(j==lbloc){
//jmax=itcoinc[checkSteps];
jmax=checkSteps;
for(j=0; j<lbloc; j++) if(itcoinc[j]>itcoinc[jmax]) jmax=j;
i=iok+((jmax+1)/2)*((jmax&1)!=0 ? 1 : -1);
} else if(itcoinc[j]>0) coinci++;
iok=i;
lastiok=false;
}
}
}
if(iok!=lok){
result=false;
attr[lastIs]=Evaluator.FLAG_DEFAULT_ERROR;
}
return result;
}
}