package org.sikuli.slides.api.interpreters;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.sikuli.api.DesktopScreenRegion;
import org.sikuli.api.robot.desktop.DesktopScreen;
import org.sikuli.slides.api.Context;
import org.sikuli.slides.api.actions.RobotAction;
import org.sikuli.slides.api.actions.Action;
import org.sikuli.slides.api.actions.ActionExecutionException;
import org.sikuli.slides.api.actions.SequentialAction;
import org.sikuli.slides.api.actions.ConfigAction;
import org.sikuli.slides.api.models.Slide;
import org.sikuli.slides.api.models.SlideElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class ConfigInterpreter implements Interpreter {
static Logger log = LoggerFactory.getLogger(ConfigInterpreter.class);
class SequentialConfigAction extends ConfigAction {
List<Action> configs = Lists.newArrayList();
public void addChild(Action action) {
configs.add(action);
}
@Override
public void execute(Context context) throws ActionExecutionException{
for (Action config : configs){
config.execute(context);
}
}
public String toString(){
return configs.toString();
}
}
@Override
public Action interpret(Slide slide) {
SlideElement keywordElement = slide.select().textMatches("(?i)config").first();
if (keywordElement == null)
return null;
List<Interpreter> interpreters = Lists.newArrayList(
configMinScoreInterpreter,
configScreenRegionInterpreter,
configParamsInterpreter
);
SequentialConfigAction seqAction = new SequentialConfigAction();
for (Interpreter interpreter : interpreters){
Action action = interpreter.interpret(slide);
if (action != null){
seqAction.addChild(action);
}
}
log.debug("result: {}", seqAction);
return seqAction;
}
static Interpreter configRangeInterpreter = new Interpreter(){
@Override
public Action interpret(Slide slide) {
SlideElement heading = slide.select().hasText().textContains("RANGE").first();
if (heading == null)
return null;
SlideElement startLabel = slide.select().orderByY().print()
.textContains("Start Slide").below(heading).orderByY().first();
if (startLabel == null)
return null;
SlideElement endLabel = slide.select()
.textContains("End Slide").below(heading).orderByY().first();
if (endLabel == null)
return null;
SlideElement startValue = slide.select().toRightOf(startLabel).orderByX().hasText()
.overlapVerticallyWith(startLabel, 0.9f).print().first();
if (startValue == null)
return null;
SlideElement endValue = slide.select().toRightOf(endLabel).orderByX().hasText()
.overlapVerticallyWith(endLabel, 0.9f).print().first();
if (endValue == null)
return null;
Action action = new ConfigAction(){
@Override
public void execute(Context context)
throws ActionExecutionException {
// context.setScreenRegion(new DesktopScreenRegion(idToSet));
}
};
return action;
}
};
static Interpreter configScreenRegionInterpreter = new Interpreter(){
@Override
public Action interpret(Slide slide) {
SlideElement heading = slide.select().hasText().textContains("SCREEN").first();
if (heading == null)
return null;
SlideElement selection = slide.select()
.hasNoText().nameStartsWith("Rectangle").below(heading).orderByY().first();
if (selection == null)
return null;
SlideElement value = slide.select().intersects(selection).hasText().first();
if (value == null)
return null;
Pattern pattern = Pattern.compile("(\\d)");
Matcher matcher = pattern.matcher(value.getText());
int id = 0;
if (matcher.find()){
try {
id = Integer.parseInt(matcher.group(1));
}catch (NumberFormatException e) {
return null;
}
}
final int idToSet = id;
Action action = new ConfigAction(){
@Override
public void execute(Context context)
throws ActionExecutionException {
if (idToSet < DesktopScreen.getNumberScreens()){
context.setScreenRegion(new DesktopScreenRegion(idToSet));
}
}
};
return action;
}
};
static class ConfigParamsAction extends ConfigAction {
private Map<String, String> map;
public ConfigParamsAction(Map<String, String> params){
this.map = params;
}
@Override
public void execute(Context context)
throws ActionExecutionException {
for (Entry<String,String> entry : map.entrySet())
context.addParameter(entry.getKey(),entry.getValue());
}
public String toString(){
List<String> params = Lists.newArrayList();
for (Entry<String,String> entry : map.entrySet()){
params.add(entry.getKey() + "=" + entry.getValue());
}
return "ConfigParamsAction{" + Joiner.on(",").join(params) + "}";
}
}
static class ConfigMinScoreAction extends ConfigAction {
private float scoreToSet;
public ConfigMinScoreAction(float minScore){
this.scoreToSet = minScore;
}
@Override
public void execute(Context context)
throws ActionExecutionException {
context.setMinScore(scoreToSet);
}
public String toString(){
return "ConfigMinScoreAction{" + scoreToSet + "}";
}
}
static class ConfigParamsInterpreter implements Interpreter {
@Override
public Action interpret(Slide slide) {
SlideElement heading = slide.select().hasText().textContains("PARAMETERS").first();
if (heading == null)
return null;
slide.remove(heading);
List<SlideElement> strings = slide.select().hasText().below(heading).orderByY().all();
final Map<String,String> map = Maps.newHashMap();
for (int i = 0; i < strings.size(); i = i + 2){
String key = strings.get(i).getText();
SlideElement valElement = strings.get(i+1);
if (valElement.getLineColor() != null){
String val = strings.get(i+1).getText();
map.put(key, val);
}
}
Action action = new ConfigParamsAction(map);
return action;
}
}
static Interpreter configParamsInterpreter = new ConfigParamsInterpreter();
static Interpreter configMinScoreInterpreter = new MinScoreInterpreter();
static class MinScoreInterpreter implements Interpreter{
@Override
public Action interpret(Slide slide) {
SlideElement heading = slide.select().hasText().textContains("MIN SCORE").first();
if (heading == null)
return null;
SlideElement selection = slide.select()
.hasNoText().nameStartsWith("Rectangle").below(heading).orderByY().first();
if (selection == null)
return null;
SlideElement value = slide.select().intersects(selection).hasText().first();
if (value == null)
return null;
float score = 0;
try {
score = Float.parseFloat(value.getText()) / 10f;
}catch (NumberFormatException e) {
return null;
}
Action action = new ConfigMinScoreAction(score);
return action;
}
};
}