@Override public FormulaElement clone() { FormulaElement leftChildClone = leftChild == null ? null : leftChild.clone(); FormulaElement rightChildClone = rightChild == null ? null : rightChild.clone(); return new FormulaElement( type, value == null ? "" : value, null, leftChildClone, rightChildClone); }
public FormulaElement getRoot() { FormulaElement root = this; while (root.getParent() != null) { root = root.getParent(); } return root; }
private Object interpretFunctionListItem(Object left, Sprite sprite) { UserList userList = null; if (rightChild.getElementType() == ElementType.USER_LIST) { DataContainer dataContainer = ProjectManager.getInstance().getSceneToPlay().getDataContainer(); userList = dataContainer.getUserList(rightChild.getValue(), sprite); } if (userList == null) { return ""; } int index = 0; if (left instanceof String) { try { Double doubleValueOfLeftChild = Double.valueOf((String) left); index = doubleValueOfLeftChild.intValue(); } catch (NumberFormatException numberFormatexception) { Log.d(getClass().getSimpleName(), "Couldn't parse String", numberFormatexception); } } else { index = ((Double) left).intValue(); } index--; if (index < 0) { return ""; } else if (index >= userList.getList().size()) { return ""; } return userList.getList().get(index); }
public boolean containsElement(ElementType elementType) { if (type.equals(elementType) || (leftChild != null && leftChild.containsElement(elementType)) || (rightChild != null && rightChild.containsElement(elementType))) { return true; } return false; }
public List<InternToken> getInternTokenList() { List<InternToken> internTokenList = new LinkedList<InternToken>(); switch (type) { case BRACKET: internTokenList.add(new InternToken(InternTokenType.BRACKET_OPEN)); if (rightChild != null) { internTokenList.addAll(rightChild.getInternTokenList()); } internTokenList.add(new InternToken(InternTokenType.BRACKET_CLOSE)); break; case OPERATOR: if (leftChild != null) { internTokenList.addAll(leftChild.getInternTokenList()); } internTokenList.add(new InternToken(InternTokenType.OPERATOR, this.value)); if (rightChild != null) { internTokenList.addAll(rightChild.getInternTokenList()); } break; case FUNCTION: internTokenList.add(new InternToken(InternTokenType.FUNCTION_NAME, value)); boolean functionHasParameters = false; if (leftChild != null) { internTokenList.add(new InternToken(InternTokenType.FUNCTION_PARAMETERS_BRACKET_OPEN)); functionHasParameters = true; internTokenList.addAll(leftChild.getInternTokenList()); } if (rightChild != null) { internTokenList.add(new InternToken(InternTokenType.FUNCTION_PARAMETER_DELIMITER)); internTokenList.addAll(rightChild.getInternTokenList()); } if (functionHasParameters) { internTokenList.add(new InternToken(InternTokenType.FUNCTION_PARAMETERS_BRACKET_CLOSE)); } break; case USER_VARIABLE: internTokenList.add(new InternToken(InternTokenType.USER_VARIABLE, this.value)); break; case USER_LIST: internTokenList.add(new InternToken(InternTokenType.USER_LIST, this.value)); break; case NUMBER: internTokenList.add(new InternToken(InternTokenType.NUMBER, this.value)); break; case SENSOR: internTokenList.add(new InternToken(InternTokenType.SENSOR, this.value)); break; case STRING: internTokenList.add(new InternToken(InternTokenType.STRING, value)); break; case COLLISION_FORMULA: internTokenList.add(new InternToken(InternTokenType.COLLISION_FORMULA, this.value)); break; } return internTokenList; }
public void updateVariableReferences(String oldName, String newName) { if (leftChild != null) { leftChild.updateVariableReferences(oldName, newName); } if (rightChild != null) { rightChild.updateVariableReferences(oldName, newName); } if (type == ElementType.USER_VARIABLE && value.equals(oldName)) { value = newName; } }
public void getVariableAndListNames(List<String> variables, List<String> lists) { if (leftChild != null) { leftChild.getVariableAndListNames(variables, lists); } if (rightChild != null) { rightChild.getVariableAndListNames(variables, lists); } if (type == ElementType.USER_VARIABLE && !variables.contains(value)) { variables.add(value); } if (type == ElementType.USER_LIST && !lists.contains(value)) { lists.add(value); } }
public void replaceElement(FormulaElement current) { parent = current.parent; leftChild = current.leftChild; rightChild = current.rightChild; value = current.value; type = current.type; if (leftChild != null) { leftChild.parent = this; } if (rightChild != null) { rightChild.parent = this; } }
public void replaceWithSubElement(String operator, FormulaElement rightChild) { FormulaElement cloneThis = new FormulaElement(ElementType.OPERATOR, operator, this.getParent(), this, rightChild); cloneThis.parent.rightChild = cloneThis; }
private Object interpretFunctionContains(Object right, Sprite sprite) { if (leftChild.getElementType() == ElementType.USER_LIST) { DataContainer dataContainer = ProjectManager.getInstance().getSceneToPlay().getDataContainer(); UserList userList = dataContainer.getUserList(leftChild.getValue(), sprite); if (userList == null) { return 0d; } for (Object userListElement : userList.getList()) { if (interpretOperatorEqual(userListElement, right) == 1d) { return 1d; } } } return 0d; }
private Object interpretFunctionLength(Object left, Sprite sprite) { if (leftChild == null) { return 0d; } if (leftChild.type == ElementType.NUMBER) { return (double) leftChild.value.length(); } if (leftChild.type == ElementType.STRING) { return (double) leftChild.value.length(); } if (leftChild.type == ElementType.USER_VARIABLE) { return (double) handleLengthUserVariableParameter(sprite); } if (leftChild.type == ElementType.USER_LIST) { DataContainer dataContainer = ProjectManager.getInstance().getSceneToPlay().getDataContainer(); UserList userList = dataContainer.getUserList(leftChild.getValue(), sprite); if (userList == null) { return 0d; } if (userList.getList().size() == 0) { return 0d; } Object interpretedList = leftChild.interpretRecursive(sprite); if (interpretedList instanceof Double) { Double interpretedListDoubleValue = (Double) interpretedList; if (interpretedListDoubleValue.isNaN() || interpretedListDoubleValue.isInfinite()) { return 0d; } return (double) (String.valueOf(interpretedListDoubleValue.intValue())).length(); } if (interpretedList instanceof String) { String interpretedListStringValue = (String) interpretedList; return (double) interpretedListStringValue.length(); } } if (left instanceof Double && ((Double) left).isNaN()) { return 0d; } return (double) (String.valueOf(left)).length(); }
public boolean containsSpriteInCollision(String name) { boolean contained = false; if (leftChild != null) { contained |= leftChild.containsSpriteInCollision(name); } if (rightChild != null) { contained |= rightChild.containsSpriteInCollision(name); } if (type == ElementType.COLLISION_FORMULA) { String collisionTag = CatroidApplication.getAppContext().getString(R.string.formula_editor_function_collision); String firstSprite = value.substring(0, value.indexOf(collisionTag) - 1); String secondSprite = value.substring(value.indexOf(collisionTag) + collisionTag.length() + 1, value.length()); if (firstSprite.equals(name) || secondSprite.equals(name)) { contained = true; } } return contained; }
public boolean isSingleNumberFormula() { if (type == ElementType.OPERATOR) { Operators operator = Operators.getOperatorByValue(value); return (operator == Operators.MINUS) && (leftChild == null) && rightChild.isSingleNumberFormula(); } else if (type == ElementType.NUMBER) { return true; } return false; }
public void updateCollisionFormula(String oldName, String newName) { if (leftChild != null) { leftChild.updateCollisionFormula(oldName, newName); } if (rightChild != null) { rightChild.updateCollisionFormula(oldName, newName); } if (type == ElementType.COLLISION_FORMULA && value.contains(oldName)) { String collisionTag = CatroidApplication.getAppContext().getString(R.string.formula_editor_function_collision); String firstSprite = value.substring(0, value.indexOf(collisionTag) - 1); String secondSprite = value.substring(value.indexOf(collisionTag) + collisionTag.length() + 1, value.length()); if (firstSprite.equals(oldName)) { value = newName + " " + collisionTag + " " + secondSprite; } else if (secondSprite.equals(oldName)) { value = firstSprite + " " + collisionTag + " " + newName; } } }
private String interpretInterpretFunctionJoinParameter(FormulaElement child, Sprite sprite) { String parameterInterpretation = ""; if (child != null) { if (child.getElementType() == ElementType.NUMBER) { Double number = Double.valueOf((String) child.interpretRecursive(sprite)); if (number.isNaN()) { parameterInterpretation = ""; } else { if (isInteger(number)) { parameterInterpretation += number.intValue(); } else { parameterInterpretation += number; } } } else if (child.getElementType() == ElementType.STRING) { parameterInterpretation = child.value; } else { parameterInterpretation += child.interpretRecursive(sprite); } } return parameterInterpretation; }
public Object interpretRecursive(Sprite sprite) { Object returnValue = 0d; switch (type) { case BRACKET: returnValue = rightChild.interpretRecursive(sprite); break; case NUMBER: returnValue = value; break; case OPERATOR: Operators operator = Operators.getOperatorByValue(value); returnValue = interpretOperator(operator, sprite); break; case FUNCTION: Functions function = Functions.getFunctionByValue(value); returnValue = interpretFunction(function, sprite); break; case SENSOR: returnValue = interpretSensor(sprite); break; case USER_VARIABLE: returnValue = interpretUserVariable(sprite); break; case USER_LIST: returnValue = interpretUserList(sprite); break; case STRING: returnValue = value; break; case COLLISION_FORMULA: try { returnValue = interpretCollision(value); } catch (Exception exception) { returnValue = 0d; Log.e(getClass().getSimpleName(), Log.getStackTraceString(exception)); } } return normalizeDegeneratedDoubleValues(returnValue); }
private Object interpretOperator(Operators operator, Sprite sprite) { if (leftChild != null) { // binary operator Object leftObject; Object rightObject; try { leftObject = leftChild.interpretRecursive(sprite); } catch (NumberFormatException numberFormatException) { leftObject = Double.NaN; } try { rightObject = rightChild.interpretRecursive(sprite); } catch (NumberFormatException numberFormatException) { rightObject = Double.NaN; } Double left; Double right; switch (operator) { case PLUS: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left + right; case MINUS: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left - right; case MULT: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left * right; case DIVIDE: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left / right; case POW: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return java.lang.Math.pow(left, right); case EQUAL: return interpretOperatorEqual(leftObject, rightObject); case NOT_EQUAL: return interpretOperatorEqual(leftObject, rightObject) == 1d ? 0d : 1d; case GREATER_THAN: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left.compareTo(right) > 0 ? 1d : 0d; case GREATER_OR_EQUAL: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left.compareTo(right) >= 0 ? 1d : 0d; case SMALLER_THAN: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left.compareTo(right) < 0 ? 1d : 0d; case SMALLER_OR_EQUAL: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left.compareTo(right) <= 0 ? 1d : 0d; case LOGICAL_AND: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return (left * right) != 0d ? 1d : 0d; case LOGICAL_OR: left = interpretOperator(leftObject); right = interpretOperator(rightObject); return left != 0d || right != 0d ? 1d : 0d; } } else { // unary operators Object rightObject; try { rightObject = rightChild.interpretRecursive(sprite); } catch (NumberFormatException numberFormatException) { rightObject = Double.NaN; } switch (operator) { case MINUS: Double result = interpretOperator(rightObject); return -result; case LOGICAL_NOT: return interpretOperator(rightObject) == 0d ? 1d : 0d; } } return 0d; }
private Object interpretFunction(Functions function, Sprite sprite) { Object left = null; Object right = null; Double doubleValueOfLeftChild = null; Double doubleValueOfRightChild = null; if (leftChild != null) { left = leftChild.interpretRecursive(sprite); if (left instanceof String) { try { doubleValueOfLeftChild = Double.valueOf((String) left); } catch (NumberFormatException numberFormatException) { Log.d(getClass().getSimpleName(), "Couldn't parse String", numberFormatException); } } else { doubleValueOfLeftChild = (Double) left; } } if (rightChild != null) { right = rightChild.interpretRecursive(sprite); if (right instanceof String) { try { doubleValueOfRightChild = Double.valueOf((String) right); } catch (NumberFormatException numberFormatException) { Log.d(getClass().getSimpleName(), "Couldn't parse String", numberFormatException); } } else { doubleValueOfRightChild = (Double) right; } } switch (function) { case SIN: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.sin(Math.toRadians(doubleValueOfLeftChild)); case COS: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.cos(Math.toRadians(doubleValueOfLeftChild)); case TAN: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.tan(Math.toRadians(doubleValueOfLeftChild)); case LN: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.log(doubleValueOfLeftChild); case LOG: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.log10(doubleValueOfLeftChild); case SQRT: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.sqrt(doubleValueOfLeftChild); case RAND: return (doubleValueOfLeftChild == null || doubleValueOfRightChild == null) ? 0d : interpretFunctionRand(doubleValueOfLeftChild, doubleValueOfRightChild); case ABS: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.abs(doubleValueOfLeftChild); case ROUND: return doubleValueOfLeftChild == null ? 0d : (double) java.lang.Math.round(doubleValueOfLeftChild); case PI: return java.lang.Math.PI; case MOD: return (doubleValueOfLeftChild == null || doubleValueOfRightChild == null) ? 0d : interpretFunctionMod(doubleValueOfLeftChild, doubleValueOfRightChild); case ARCSIN: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.toDegrees(Math.asin(doubleValueOfLeftChild)); case ARCCOS: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.toDegrees(Math.acos(doubleValueOfLeftChild)); case ARCTAN: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.toDegrees(Math.atan(doubleValueOfLeftChild)); case EXP: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.exp(doubleValueOfLeftChild); case POWER: return (doubleValueOfLeftChild == null || doubleValueOfRightChild == null) ? 0d : java.lang.Math.pow(doubleValueOfLeftChild, doubleValueOfRightChild); case FLOOR: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.floor(doubleValueOfLeftChild); case CEIL: return doubleValueOfLeftChild == null ? 0d : java.lang.Math.ceil(doubleValueOfLeftChild); case MAX: return (doubleValueOfLeftChild == null || doubleValueOfRightChild == null) ? 0d : java.lang.Math.max(doubleValueOfLeftChild, doubleValueOfRightChild); case MIN: return (doubleValueOfLeftChild == null || doubleValueOfRightChild == null) ? 0d : java.lang.Math.min(doubleValueOfLeftChild, doubleValueOfRightChild); case TRUE: return 1d; case FALSE: return 0d; case LETTER: return interpretFunctionLetter(right, left); case LENGTH: return interpretFunctionLength(left, sprite); case JOIN: return interpretFunctionJoin(sprite); case ARDUINODIGITAL: Arduino arduinoDigital = ServiceProvider.getService(CatroidService.BLUETOOTH_DEVICE_SERVICE) .getDevice(BluetoothDevice.ARDUINO); if (arduinoDigital != null && left != null) { if (doubleValueOfLeftChild < 0 || doubleValueOfLeftChild > 13) { return 0d; } return arduinoDigital.getDigitalArduinoPin(doubleValueOfLeftChild.intValue()); } break; case ARDUINOANALOG: Arduino arduinoAnalog = ServiceProvider.getService(CatroidService.BLUETOOTH_DEVICE_SERVICE) .getDevice(BluetoothDevice.ARDUINO); if (arduinoAnalog != null && left != null) { if (doubleValueOfLeftChild < 0 || doubleValueOfLeftChild > 5) { return 0d; } return arduinoAnalog.getAnalogArduinoPin(doubleValueOfLeftChild.intValue()); } break; case RASPIDIGITAL: RPiSocketConnection connection = RaspberryPiService.getInstance().connection; int pin = doubleValueOfLeftChild.intValue(); try { return connection.getPin(pin) ? 1d : 0d; } catch (Exception e) { Log.e(getClass().getSimpleName(), "RPi: exception during getPin: " + e); } break; case MULTI_FINGER_TOUCHED: return TouchUtil.isFingerTouching(doubleValueOfLeftChild.intValue()) ? 1d : 0d; case MULTI_FINGER_X: return Double.valueOf(TouchUtil.getX(doubleValueOfLeftChild.intValue())); case MULTI_FINGER_Y: return Double.valueOf(TouchUtil.getY(doubleValueOfLeftChild.intValue())); case LIST_ITEM: return interpretFunctionListItem(left, sprite); case CONTAINS: return interpretFunctionContains(right, sprite); case NUMBER_OF_ITEMS: return interpretFunctionNumberOfItems(left, sprite); } return 0d; }
public int getRequiredResources() { int resources = Brick.NO_RESOURCES; if (leftChild != null) { resources |= leftChild.getRequiredResources(); } if (rightChild != null) { resources |= rightChild.getRequiredResources(); } if (type == ElementType.FUNCTION) { Functions functions = Functions.getFunctionByValue(value); switch (functions) { case ARDUINOANALOG: case ARDUINODIGITAL: resources |= Brick.BLUETOOTH_SENSORS_ARDUINO; break; case RASPIDIGITAL: resources |= Brick.SOCKET_RASPI; break; } } if (type == ElementType.SENSOR) { Sensors sensor = Sensors.getSensorByValue(value); switch (sensor) { case X_ACCELERATION: case Y_ACCELERATION: case Z_ACCELERATION: resources |= Brick.SENSOR_ACCELERATION; break; case X_INCLINATION: case Y_INCLINATION: resources |= Brick.SENSOR_INCLINATION; break; case COMPASS_DIRECTION: resources |= Brick.SENSOR_COMPASS; break; case LATITUDE: case LONGITUDE: case LOCATION_ACCURACY: case ALTITUDE: resources |= Brick.SENSOR_GPS; break; case FACE_DETECTED: case FACE_SIZE: case FACE_X_POSITION: case FACE_Y_POSITION: resources |= Brick.FACE_DETECTION; break; case NXT_SENSOR_1: case NXT_SENSOR_2: case NXT_SENSOR_3: case NXT_SENSOR_4: resources |= Brick.BLUETOOTH_LEGO_NXT; break; case PHIRO_FRONT_LEFT: case PHIRO_FRONT_RIGHT: case PHIRO_SIDE_LEFT: case PHIRO_SIDE_RIGHT: case PHIRO_BOTTOM_LEFT: case PHIRO_BOTTOM_RIGHT: resources |= Brick.BLUETOOTH_PHIRO; break; case DRONE_BATTERY_STATUS: case DRONE_CAMERA_READY: case DRONE_EMERGENCY_STATE: case DRONE_FLYING: case DRONE_INITIALIZED: case DRONE_NUM_FRAMES: case DRONE_RECORD_READY: case DRONE_RECORDING: case DRONE_USB_ACTIVE: case DRONE_USB_REMAINING_TIME: resources |= Brick.ARDRONE_SUPPORT; break; case NFC_TAG_ID: resources |= Brick.NFC_ADAPTER; break; default: } } if (type == ElementType.COLLISION_FORMULA) { resources |= Brick.COLLISION; } return resources; }