text:
package com.mygdx.game;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.ai.msg.MessageManager;
import com.badlogic.gdx.ai.msg.Telegram;
import com.badlogic.gdx.ai.msg.Telegraph;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.Ray;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;
import com.badlogic.gdx.scenes.scene2d.ui.Cell;
import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextField;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Bits;
import com.badlogic.gdx.utils.IntIntMap;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.mygdx.game.objects.DogCharacter;
import com.mygdx.game.objects.GameCharacter;
import com.mygdx.game.objects.HumanCharacter;
import com.mygdx.game.objects.HumanCharacter.HumanState;
import com.mygdx.game.settings.DebugViewSettings;
import com.mygdx.game.settings.GameSettings;
import com.mygdx.game.settings.ShaderSettings;
import com.mygdx.game.ui.BooleanSettingsMenu;
import com.mygdx.game.ui.FloatSettingsMenu;
import com.mygdx.game.ui.FloatValueLabel;
import com.mygdx.game.ui.GameSpeedController;
import com.mygdx.game.ui.IntValueLabel;
import com.mygdx.game.utilities.BehaviorTreeController;
import com.mygdx.game.utilities.CameraController;
import com.mygdx.game.utilities.Constants;
import com.mygdx.game.utilities.Entity;
import com.mygdx.game.utilities.Observable;
import com.mygdx.game.utilities.Observer;

/**
 * @author jsjolund
 */
public class GameStage extends Stage implements Observable {

	private class LayerController extends Table {
		private final Slider slider;
		int minLayer = 1;
		int maxLayer = 4;

		public LayerController(TextureAtlas buttonAtlas) {
			Slider.SliderStyle sliderStyle = new Slider.SliderStyle();
			sliderStyle.knob = new TextureRegionDrawable(buttonAtlas.findRegion("slider-knob-up"));
			sliderStyle.knobDown = new TextureRegionDrawable(buttonAtlas.findRegion("slider-knob-down"));
			sliderStyle.knobOver = new TextureRegionDrawable(buttonAtlas.findRegion("slider-knob-down"));
			sliderStyle.background = new TextureRegionDrawable(buttonAtlas.findRegion("slider-background"));

			slider = new Slider(minLayer, maxLayer, 1, true, sliderStyle);
			slider.setValue(maxLayer);
			slider.setAnimateDuration(0.1f);

			slider.addCaptureListener(new ChangeListener() {
				@Override
				public void changed(ChangeEvent event, Actor actor) {
					setLayer((int) slider.getValue());
				}
			});
			add(slider).height(300);
		}

		public void setLayer(int layer) {
			layer = MathUtils.clamp(layer, minLayer, maxLayer);
			slider.setValue(layer);
			visibleLayers.clear();
			for (int i = 0; i < layer; i++) {
				visibleLayers.set(i);
			}
			notifyObserversLayerChanged(visibleLayers);
		}
	}

	public class WorldInputProcessor implements InputProcessor {

		private final Ray dragCurrentRay = new Ray();
		private final Ray lastDragProcessedRay = new Ray();
		private final Ray touchDownRay = new Ray();
		private final Ray touchUpRay = new Ray();
		private final Ray movedRay = new Ray();

		private final Vector2 lastDragProcessed = new Vector2();
		private final Vector2 cursorDelta = new Vector2();
		private final Vector2 dragCurrent = new Vector2();
		private final Vector2 keyPanDirection = new Vector2();
		private final Vector2 lastTouchDown = new Vector2();

		private final Vector3 tmp = new Vector3();
		private final Vector3 mouseNavMeshPos = new Vector3();
		private final Vector2 mouseScreenPos = new Vector2();

		private final IntIntMap keys = new IntIntMap();

		private boolean isDragging = false;

		@Override
		public boolean keyDown(int keycode) {
			keys.put(keycode, keycode);
			if (keycode == GameSettings.KEY_PAUSE) {
				speedController.setGameSpeed();
			}
			return true;
		}

		@Override
		public boolean keyUp(int keycode) {
			keys.remove(keycode, 0);
			return true;
		}

		@Override
		public boolean keyTyped(char keyChar) {
			if (keyChar >= '1' && keyChar <= '9') {
				layerController.setLayer(keyChar - '0');
			}
			return true;
		}

		@Override
		public boolean touchDown(int screenX, int screenY, int pointer, int button) {
			lastTouchDown.set(screenX, screenY);
			lastDragProcessed.set(screenX, screenY);
			if (button == Input.Buttons.LEFT) {
				touchDownRay.set(viewport.getPickRay(screenX, screenY));
				cameraController.processTouchDownLeft(touchDownRay);

			} else if (button == Input.Buttons.RIGHT) {
				cameraController.processTouchDownRight();
			}
			return true;
		}

		@Override
		public boolean touchUp(int screenX, int screenY, int pointer, int button) {
			if (!isDragging) {
				touchUpRay.set(viewport.getPickRay(screenX, screenY));

				Entity hitEntity = engine.rayTest(
						touchUpRay, tmp,
						GameEngine.ALL_FLAG,
						GameEngine.ALL_FLAG,
						GameSettings.CAMERA_PICK_RAY_DST, visibleLayers);

				Gdx.app.debug(TAG, "Hit entity " + hitEntity);

				if (hitEntity instanceof GameCharacter) {
					characterController.handleCharacterSelection((GameCharacter) hitEntity);

				} else if (hitEntity == engine.getScene().navmeshBody) {
					characterController.handleMovementRequest(touchUpRay, visibleLayers);
				}
			}
			isDragging = false;
			dragCurrent.setZero();
			lastDragProcessed.setZero();
			return true;
		}

		@Override
		public boolean touchDragged(int screenX, int screenY, int pointer) {
			dragCurrent.set(screenX, screenY);
			if (dragCurrent.dst2(lastTouchDown) > GameSettings.MOUSE_DRAG_THRESHOLD) {
				isDragging = true;
				if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
					dragCurrentRay.set(viewport.getPickRay(dragCurrent.x, dragCurrent.y));
					lastDragProcessedRay.set(viewport.getPickRay(lastDragProcessed.x, lastDragProcessed.y));
					cameraController.processDragPan(dragCurrentRay, lastDragProcessedRay);

				} else if (Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
					cursorDelta.set(lastDragProcessed).sub(screenX, screenY).scl(GameSettings.MOUSE_SENSITIVITY);
					cameraController.processDragRotation(cursorDelta);
				}
				lastDragProcessed.set(screenX, screenY);
			}
			mouseMoved(screenX, screenY);
			return true;
		}

		@Override
		public boolean mouseMoved(int screenX, int screenY) {
			movedRay.set(viewport.getPickRay(screenX, screenY));
			Entity e = engine.rayTest(movedRay, mouseNavMeshPos, GameEngine.NAVMESH_FLAG,
					GameEngine.NAVMESH_FLAG, GameSettings.CAMERA_PICK_RAY_DST, null);
			if (e == null) mouseNavMeshPos.set(Float.NaN, Float.NaN, Float.NaN);
			notifyCursorWorldPosition(mouseNavMeshPos.x, mouseNavMeshPos.y, mouseNavMeshPos.z);
			mouseScreenPos.set(screenX, screenY);
			return true;
		}

		@Override
		public boolean scrolled(int amount) {
			cameraController.processZoom(amount);
			return true;
		}

		public void update(float deltaTime) {
			keyPanDirection.setZero();
			if (keys.containsKey(GameSettings.KEY_PAN_FORWARD)) {
				keyPanDirection.y++;
			}
			if (keys.containsKey(GameSettings.KEY_PAN_BACKWARD)) {
				keyPanDirection.y--;
			}
			if (keys.containsKey(GameSettings.KEY_PAN_LEFT)) {
				keyPanDirection.x--;
			}
			if (keys.containsKey(GameSettings.KEY_PAN_RIGHT)) {
				keyPanDirection.x++;
			}
			if (!keyPanDirection.isZero()) {
				keyPanDirection.nor();
				cameraController.processKeyboardPan(keyPanDirection, deltaTime);
			}
		}
	}

	private class CharacterController extends Table implements Telegraph {
		private class CharacterButton extends ImageButton {

			HumanState state;

			CharacterButton(HumanState state, TextureAtlas buttonAtlas, String up, String down, String checked) {
				super(new TextureRegionDrawable(buttonAtlas.findRegion(up)),
						new TextureRegionDrawable(buttonAtlas.findRegion(down)),
						new TextureRegionDrawable(buttonAtlas.findRegion(checked)));
				this.state = state;
				this.addListener(new ClickListener() {
					@Override
					public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
						if (!CharacterButton.this.isChecked()) {
							if (selectedCharacter instanceof HumanCharacter) {
								HumanCharacter human = (HumanCharacter) selectedCharacter;
								if (CharacterButton.this.state.isMovementState()) {
									HumanState hs = human.stateMachine.getCurrentState();
									if (hs.isMovementState()) {
										human.handleStateCommand(CharacterButton.this.state);
									} else {
										human.moveState = CharacterButton.this.state;
										human.handleStateCommand(CharacterButton.this.state.idleState);
									}
								} else {
									human.handleStateCommand(CharacterButton.this.state);
								}
							}
						}
						return true;
					}
				});
			}
		}

		private ButtonGroup<CharacterButton> radioGroup;
		private CharacterButton whistleButton;
		private CharacterButton throwButton;
		private Cell<CharacterButton> dogCell;
		private GameCharacter selectedCharacter;

		public CharacterController(TextureAtlas buttonAtlas) {
			whistleButton = new CharacterButton(HumanState.WHISTLE, buttonAtlas, "whistle-up", "whistle-down", "whistle-down");
			throwButton = new CharacterButton(HumanState.THROW, buttonAtlas, "throw-up", "throw-down", "throw-down");

			radioGroup = new ButtonGroup<CharacterButton>(
					new CharacterButton(HumanState.MOVE_RUN, buttonAtlas, "run-up", "run-down", "run-down"),
					new CharacterButton(HumanState.MOVE_WALK, buttonAtlas, "walk-up", "walk-down", "walk-down"),
					new CharacterButton(HumanState.MOVE_CROUCH, buttonAtlas, "crouch-up", "crouch-down", "crouch-down"),
					//new CharacterButton(CharacterState.MOVE_CRAWL, buttonAtlas, "crawl-up", "crawl-down", "crawl-down"),
					new CharacterButton(HumanState.DEAD, buttonAtlas, "kill-up", "kill-down", "kill-down")
			);

			// Add whistle button and save the reference to the 1st cell
			this.dogCell = add(whistleButton);

			// Add radio buttons
			for (CharacterButton btn : radioGroup.getButtons()) {
				add(btn);
			}

			// Register this controller's interests
			MessageManager.getInstance().addListeners(this,
					Constants.MSG_GUI_CLEAR_DOG_BUTTON,
					Constants.MSG_GUI_SET_DOG_BUTTON_TO_WHISTLE,
					Constants.MSG_GUI_SET_DOG_BUTTON_TO_THROW);
		}

		private final void setDogButton(CharacterButton btn, HumanCharacter human) {
			if (human != null && human == selectedCharacter) {
				whistleButton.setVisible(false);
				throwButton.setVisible(false);
				dogCell.setActor(btn);
				btn.setVisible(true);
				btn.setChecked(false);
				Gdx.app.log("CharacterController", "setDogButton: " + (btn == whistleButton ? "whistleButton" : (btn == throwButton ? "throwButton" : "???")));
			}
		}

		private final void clearDogButton(HumanCharacter human) {
			if (human != null && human == selectedCharacter) {
				whistleButton.setVisible(false);
				throwButton.setVisible(false);
				Gdx.app.log("CharacterController", "clearDogButton");
			}
		}

		public void handleCharacterSelection(GameCharacter character) {
			cameraController.setFollowTarget(character.motionState.transform);

			if (selectedCharacter == character)
				return;

			// Remove selection from previously selected human (if any)
			if (selectedCharacter != null && selectedCharacter instanceof HumanCharacter) {
				HumanCharacter human = (HumanCharacter) selectedCharacter;
				human.selected = false;
			}

			// Select new character
			selectedCharacter = character;
			notifyObserversEntitySelected(selectedCharacter);

			if (character instanceof HumanCharacter) {
				steerSettings.clearChildren();
				steerSettings.add(humanSteerSettings);
				steerSettings.invalidateHierarchy();

				HumanCharacter human = (HumanCharacter) character;
				human.selected = true;
				// Restore the controller based on the newly selected human
				updateDogButton(human);
				for (CharacterButton btn : radioGroup.getButtons()) {
					if (btn.state == HumanState.DEAD && human.isDead()) {
						btn.setChecked(true);
						break;
					}
					if (btn.state == human.getCurrentMoveState()) {
						btn.setChecked(true);
						break;
					}
				}
				this.setVisible(true);
			} else if (character instanceof DogCharacter) {
				steerSettings.clearChildren();
				steerSettings.add(dogSteerSettings);
				steerSettings.invalidateHierarchy();
				this.setVisible(false);  // no controller for dogs

				btreeController.setCurrentDog((DogCharacter) character);
			}
		}

		public void handleMovementRequest(Ray ray, Bits visibleLayers) {
			// Handle movement request only if a character is selected and a movement button is checked
			if (selectedCharacter != null && radioGroup.getCheckedIndex() > -1 && radioGroup.getChecked().state.isMovementState()) {
				selectedCharacter.handleMovementRequest(ray, visibleLayers);
			}
		}

		// Restore the controller for the given human if it is currently selected
		private void updateDogButton(HumanCharacter human) {
			if (selectedCharacter != null && selectedCharacter == human) {
				if (human.dog != null && !human.isDead()) {
					if (!human.dog.humanWantToPlay) {
						this.setDogButton(whistleButton, human);
					} else if (!human.dog.stickThrown) {
						this.setDogButton(throwButton, human);
					} else {
						this.clearDogButton(human);
					}
				} else {
					this.clearDogButton(human);
				}
			}
		}

		@Override
		public boolean handleMessage(Telegram telegram) {
			switch (telegram.message) {
				case Constants.MSG_GUI_SET_DOG_BUTTON_TO_WHISTLE:
					setDogButton(whistleButton, (HumanCharacter) telegram.extraInfo);
					return true;
				case Constants.MSG_GUI_SET_DOG_BUTTON_TO_THROW:
					setDogButton(throwButton, (HumanCharacter) telegram.extraInfo);
					return true;
				case Constants.MSG_GUI_CLEAR_DOG_BUTTON:
					clearDogButton((HumanCharacter) telegram.extraInfo);
					return true;
				case Constants.MSG_GUI_UPDATE_DOG_BUTTON:
					updateDogButton((HumanCharacter) telegram.extraInfo);
					return true;
			}
			return false;
		}
	}

	private class MouseNavMeshCoordTable extends Table {
		public MouseNavMeshCoordTable(Skin skin) {
			align(Align.topLeft); // Fix flickering due to the variable width of rows

			// Create label X
			FloatValueLabel mouseLabelX = new FloatValueLabel("x: ", 0, skin) {
				@Override
				public float getValue() {
					return worldInputProcessor.mouseNavMeshPos.x;
				}
			};
			// Create label Y
			FloatValueLabel mouseLabelY = new FloatValueLabel("y: ", 0, skin) {
				@Override
				public float getValue() {
					return worldInputProcessor.mouseNavMeshPos.y;
				}
			};
			// Create label Z
			FloatValueLabel mouseLabelZ = new FloatValueLabel("z: ", 0, skin) {
				@Override
				public float getValue() {
					return worldInputProcessor.mouseNavMeshPos.z;
				}
			};
			// This should be floating
			add(mouseLabelX).left();
			row();
			add(mouseLabelY).left();
			row();
			add(mouseLabelZ).left();
		}

		@Override
		public void act(float delta) {
			boolean visible = DebugViewSettings.drawMouseNavMeshPos;
			setVisible(visible);
			if (visible) {
				screenToStageCoordinates(tmpV2.set(worldInputProcessor.mouseScreenPos));
				setPosition(tmpV2.x + 10, tmpV2.y - 10);
				super.act(delta);  // No need to update this actor if it's not visible
			}
		}
	}
	private static final String TAG = "GameStage";
	private final Viewport viewport;
	private final SpriteBatch batch;
	private final ShapeRenderer shapeRenderer;
	private final Table rootTable;
	private final TextureAtlas buttonsAtlas;
	private final Camera cameraUI;
	private final Skin skin;
	private final CameraController cameraController;
	private final GameEngine engine;
	private final Array<Observer> observers = new Array<Observer>();
	private final WorldInputProcessor worldInputProcessor;
	private final GameSpeedController speedController;
	private final CharacterController characterController;
	private final LayerController layerController;
	private final FloatSettingsMenu humanSteerSettings;
	private final FloatSettingsMenu dogSteerSettings;
	private final Table steerSettings;
	private final Vector3 tmp = new Vector3();
	private final Vector2 tmpV2 = new Vector2();
	private Bits visibleLayers;

	public final BehaviorTreeController btreeController;
	private final TextButton toggle;

	public GameStage(GameEngine engine, Viewport viewport, CameraController cameraController) {
		super(viewport);
		this.engine = engine;
		this.viewport = viewport;
		this.cameraController = cameraController;

		visibleLayers = new Bits();

		InputMultiplexer multiplexer = new InputMultiplexer();
		multiplexer.addProcessor(this);
		multiplexer.addProcessor(worldInputProcessor = new WorldInputProcessor());
		Gdx.input.setInputProcessor(multiplexer);

		cameraUI = new OrthographicCamera(viewport.getScreenWidth(), viewport.getScreenHeight());
		cameraUI.position.set(viewport.getScreenWidth() / 2, viewport.getScreenHeight() / 2, 0);
		cameraUI.update();

		batch = new SpriteBatch();
		shapeRenderer = new ShapeRenderer();
		shapeRenderer.setAutoShapeType(true);
		skin = new Skin(Gdx.files.internal("skins/uiskin.json"));

		buttonsAtlas = new TextureAtlas(Gdx.files.internal("skins/buttons.atlas"));

		addActor(new MouseNavMeshCoordTable(skin));

		// Create controllers
		speedController = new GameSpeedController(buttonsAtlas);
		characterController = new CharacterController(buttonsAtlas);
		characterController.setVisible(false); // initially no character is selected, so hide the controller
		layerController = new LayerController(buttonsAtlas);

		// Create a root table that auto-scales on resize
		rootTable = new Table() {
			@Override
			protected void sizeChanged () {
				super.sizeChanged();

				float scaleX = 1;
				float scaleY = 1;
				float scaleTolerance = 0.001f;
				if (getPrefWidth() > getWidth())
					scaleX -= (rootTable.getPrefWidth() - getWidth()) / (float) getPrefWidth();
//				if (getPrefHeight() > getHeight())
//					scaleY -= (getPrefHeight() - getHeight()) / (float)getPrefHeight();

				if (MathUtils.isEqual(scaleX, 1, scaleTolerance) && MathUtils.isEqual(scaleY, 1, scaleTolerance)) {
					Gdx.app.log(TAG, "No need to scale rootTable: scaleX = " + scaleX + "  scaleY = " + scaleY);
					setTransform(false);
					setOrigin(0, 0);
					setScale(1);
				} else {
					Gdx.app.log(TAG, "Scaling rootTable: scaleX = " + scaleX + "  scaleY = " + scaleY);
					setTransform(true);
					setOrigin(0, 0);
					setScale(scaleX, scaleY);
				}
			}
		};
		addActor(rootTable);
		rootTable.setDebug(true, true);

		// Add top left row with FPS label
		rootTable.row().top().left().colspan(3);
		rootTable.add(new IntValueLabel("FPS: ", 999, skin) {
			@Override
			public int getValue() {
				return Gdx.graphics.getFramesPerSecond();
			}
		});

		rootTable.row().bottom();
		humanSteerSettings = new FloatSettingsMenu("Steering (human)", skin,
				HumanCharacter.HumanSteerSettings.class);
		dogSteerSettings = new FloatSettingsMenu("Steering (dog)", skin,
				DogCharacter.DogSteerSettings.class);
		steerSettings = new Table();
		steerSettings.add(humanSteerSettings);

		btreeController = new BehaviorTreeController();
		toggle = new TextButton("Show editor", skin);
		toggle.addListener(new ClickListener(){
			@Override public void clicked (InputEvent event, float x, float y) {
				btreeController.toggleEditorWindow(rootTable, toggle);
			}
		});
		btreeController.toggleEditorWindow(rootTable, toggle);

		// Add bottom left table with settings
		Table bottomLeftTable = new Table();
		bottomLeftTable.add(new FloatSettingsMenu("Shader", skin, ShaderSettings.class)).bottom();
		bottomLeftTable.add(new BooleanSettingsMenu("Debug", skin, DebugViewSettings.class)).bottom();
		bottomLeftTable.add(steerSettings).bottom();
		bottomLeftTable.add(toggle).bottom();
		rootTable.add(bottomLeftTable).left();

		// Add space between bottom left and bottom right tables
		rootTable.add(new Actor()).width(10).grow();

		// Add bottom right table with controllers
		//
		// FIXME: This is pretty ugly but we have to scale
		// the table because button's images are too big.
		// Unfortunately, scaling the table does not change
		// its size, so we have to override the preferred size. :(
		// Atlas and texture should be resized instead.
		// Maybe sooner or later someone will do :)
		final float scale = 0.5f;
		Table bottomRightTable = new Table() {
			public float getPrefWidth() {
				return super.getPrefWidth() * scale;
			}

			public float getPrefHeight() {
				return super.getPrefHeight() * scale;
			}
		};
		bottomRightTable.add(layerController).right().colspan(2);
		bottomRightTable.row();
		bottomRightTable.add(characterController);
		bottomRightTable.add(speedController);
		bottomRightTable.setTransform(true);
		bottomRightTable.setOrigin(bottomRightTable.getPrefWidth() * scale, bottomRightTable.getPrefHeight() * scale);
		bottomRightTable.setScale(scale);
		rootTable.add(bottomRightTable).width(bottomRightTable.getPrefWidth()).height(bottomRightTable.getPrefHeight()).bottom().right();

		rootTable.left().bottom();

		getRoot().addCaptureListener(new InputListener() {
			public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
				if (!(event.getTarget() instanceof TextField)) setKeyboardFocus(null);
				return false;
			}
		});
	}

	// Code modified from super.calculateScissors()
	@Override
	public void calculateScissors (Rectangle localRect, Rectangle scissorRect) {
		ScissorStack.calculateScissors(cameraUI, viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight(), batch.getTransformMatrix(), localRect, scissorRect);
		Matrix4 transformMatrix;
		if (shapeRenderer != null && shapeRenderer.isDrawing())
			transformMatrix = shapeRenderer.getTransformMatrix();
		else
			transformMatrix = batch.getTransformMatrix();
		ScissorStack.calculateScissors(cameraUI, viewport.getScreenX(), viewport.getScreenY(), viewport.getScreenWidth(), viewport.getScreenHeight(), transformMatrix, localRect, scissorRect);
	}

	public Bits getVisibleLayers(Bits out) {
		out.clear();
		out.or(visibleLayers);
		return out;
	}

	@Override
	public void dispose() {
		super.dispose();
		batch.dispose();
		skin.dispose();
		shapeRenderer.dispose();
		buttonsAtlas.dispose();
	}

	public void resize(int width, int height) {
		getViewport().update(width, height, false);
		cameraUI.viewportWidth = viewport.getScreenWidth();
		cameraUI.viewportHeight = viewport.getScreenHeight();
		cameraUI.position.set(viewport.getScreenWidth() / 2, viewport.getScreenHeight() / 2, 0);
		cameraUI.update();
		batch.setProjectionMatrix(cameraUI.combined);
		shapeRenderer.setProjectionMatrix(cameraUI.combined);

		// Resize the root table that will auto-scale if needed
		rootTable.setSize(viewport.getScreenWidth(), viewport.getScreenHeight());
	}

	@Override
	public Vector2 screenToStageCoordinates(Vector2 screenCoords) {
		tmp.set(screenCoords.x, screenCoords.y, 1);
		cameraUI.unproject(tmp, viewport.getScreenX(), viewport.getScreenY(),
				viewport.getScreenWidth(), viewport.getScreenHeight());
		screenCoords.set(tmp.x, tmp.y);
		return screenCoords;
	}

	@Override
	public void act(float delta) {
		super.act(delta);
		worldInputProcessor.update(delta);
	}

	@Override
	public void draw() {
		batch.begin();
		for (Actor actor : getActors()) {
			if (actor.isVisible()) {
				actor.draw(batch, 1);
			}
		}
		batch.end();

		if (DebugViewSettings.drawUIDebug) {
			shapeRenderer.begin();
			rootTable.drawDebug(shapeRenderer);
			shapeRenderer.end();
		}
		cameraController.update();
	}

	@Override
	public void addObserver(Observer observer) {
		observers.add(observer);
	}

	@Override
	public void removeObserver(Observer observer) {
		observers.removeValue(observer, true);
	}

	@Override
	public void notifyObserversEntitySelected(GameCharacter entity) {
		for (Observer observer : observers) {
			observer.notifyEntitySelected(entity);
		}
	}

	@Override
	public void notifyObserversLayerChanged(Bits layer) {
		for (Observer observer : observers) {
			observer.notifyLayerChanged(layer);
		}
	}

	@Override
	public void notifyCursorWorldPosition(float x, float y, float z) {
		for (Observer observer : observers) {
			observer.notifyCursorWorldPosition(x, y, z);
		}
	}

	public void setVisibleLayers(Bits visibleLayers) {
		this.visibleLayers.clear();
		this.visibleLayers.or(visibleLayers);
		layerController.setLayer(visibleLayers.nextClearBit(0) - 1);
		notifyObserversLayerChanged(this.visibleLayers);
	}
}


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Magyar Bot. Lapok 21: 13 (1922)

#### Original name
Plectophomella Moesz

### Remarks
null

redpajama_set_name: RedPajamaGithub


text:
require 'minitest/autorun'
load 'models/persona.rb'

class PersonaTest < MiniTest::Unit::TestCase

  def setup
    @persona = Persona.new("salias","martin")
  end

  def test_first_name
    assert_equal "martin", @persona.first_name
  end

  def test_last_name
    assert_equal "salias", @persona.last_name
  end

  def test_asign_new_first_name
    @persona.first_name = "luis"
    assert_equal "luis", @persona.first_name
  end

end


text:
HipChat
=======
`HipChat`_ is hosted group chat and video chat for companies and teams.

kawasemi uses one of the `Room API`_ for sending notification to HipChat.

Settings
--------
You can obtain a Room API ID and a Room Notification Token from `HipChat Rooms Page`_.

.. code-block:: python

   config = {
       "CHANNELS": {
           "hipchat": {
               "_backend": "kawasemi.backends.hipchat.HipChatChannel",
               # Required
               # Room API ID
               "api_id": "1234567",
               # Room Notification Token
               "token": "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
               # Optional
               # Only for HipChat Server
               "base_url": "https://api.hipchat.com/v2/",
               # Background color for message
               # Valid values: yellow, green, red, purple, gray, random
               "color": "random",
               # Whether this message should trigger a user notification
               "notify": True,
               # Determines how the message is treated by HipChat server and rendered inside HipChat applications
               # Valid values: html, text
               "message_format": "html"
           }
       }
   }

Options
-------
You can specify all options available in the `Room API`_. For instance:

.. code-block:: python

   kawasemi.send("Sample notification.", options={
       "hipchat": {
           "color": "green",
           "notify": False,
           "message_format": "text"
       }
   })

.. _HipChat: https://www.hipchat.com/
.. _Room API: https://www.hipchat.com/docs/apiv2/method/send_room_notification
.. _HipChat Rooms Page: https://my.hipchat.com/rooms


text:
<?php
namespace Deployer;

require_once __DIR__ . '/common.php';

add('recipes', ['drupal7']);

task('deploy', [
    'deploy:prepare',
    'deploy:publish',
]);

//Set Drupal 7 site. Change if you use different site
set('drupal_site', 'default');

//Drupal 7 shared dirs
set('shared_dirs', [
    'sites/{{drupal_site}}/files',
]);

//Drupal 7 shared files
set('shared_files', [
    'sites/{{drupal_site}}/settings.php',
]);

//Drupal 7 writable dirs
set('writable_dirs', [
    'sites/{{drupal_site}}/files',
]);

//Create and upload Drupal 7 settings.php using values from secrets
task('drupal:settings', function () {
    if (askConfirmation('Are you sure to generate and upload settings.php file?')) {

        //Get template
        $template = get('settings_template');

        //Import secrets
        $secrets = get('settings');

        //Prepare replacement variables
        $iterator = new \RecursiveIteratorIterator(
            new \RecursiveArrayIterator($secrets)
        );

        $replacements = [];
        foreach ($iterator as $key => $value) {
            $keys = [];
            for ($i = $iterator->getDepth(); $i > 0; $i --) {
                $keys[] = $iterator->getSubIterator($i - 1)->key();
            }
            $keys[] = $key;

            $replacements['{{' . implode('.', $keys) . '}}'] = $value;
        }

        //Create settings from template
        $settings = file_get_contents($template);

        $settings = strtr($settings, $replacements);

        writeln('settings.php created successfully');

        $tmpFilename = tempnam(sys_get_temp_dir(), 'tmp_settings_');
        file_put_contents($tmpFilename, $settings);

        upload($tmpFilename, '{{deploy_path}}/shared/sites/{{drupal_site}}/settings.php');

        unlink($tmpFilename);
    }
});

//Upload Drupal 7 files folder
task('drupal:upload_files', function () {
    if (askConfirmation('Are you sure?')) {
        upload('sites/{{drupal_site}}/files', '{{deploy_path}}/shared/sites/{{drupal_site}}/files');
    }
});


text:
#pragma once

#include "view.hpp"

class MainWindowController : public MainWindowView
{
    Q_OBJECT

public:
    MainWindowController(QObject* parent);
    ~MainWindowController();

private:
    void open_rom();

signals:
    void handle_rom(char*, const quint64);
};


text:
package com.opengamma.strata.report;

/**
 * Runs a report for a specific template type.
 *

 * A report is a transformation from trade and/or aggregate calculation results into a
 * specific business format.
 *
 * @param <T>  the type of the report template
 */
public interface ReportRunner<T extends ReportTemplate> {

  /**
   * Gets a description of the requirements to run a report for the given template.
   * Requirements include trade-level measures.
   *

   * The report may be run on calculation results including at least these requirements.
   *
   * @param reportTemplate  the report template
   * @return the requirements to run the report
   */
  public abstract ReportRequirements requirements(T reportTemplate);

  /**
   * Runs a report from a set of calculation results.
   * The contents of the report are dictated by the template provided.
   * The calculation results may be substantially more complete than the template requires.
   *
   * @param calculationResults  the calculation results
   * @param reportTemplate  the report template
   * @return  the report
   */
  public abstract Report runReport(ReportCalculationResults calculationResults, T reportTemplate);

}


text:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:updatePeriodMillis="0"
    android:configure="net.wizardfactory.todayweather.widget.SettingsActivity"
    android:initialKeyguardLayout="@layout/w4x2_clock_current_hourly"
    android:initialLayout="@layout/w4x2_clock_current_hourly"
    android:minHeight="110dp"
    android:minWidth="250dp"
    android:previewImage="@drawable/w4x2_clock_current_hourly"
    android:resizeMode="horizontal"
    android:widgetCategory="home_screen"></appwidget-provider>


text:
using Android.Util;
using Java.Lang;
using Java.Util;

namespace BuildIt.Forms.Controls.Platforms.Android
{
    public class CompareSizesByArea : Object, IComparator
    {
        public int Compare(Object lhs, Object rhs)
        {
            var lhsSize = (Size)lhs;
            var rhsSize = (Size)rhs;

            // We cast here to ensure the multiplications won't overflow
            return Long.Signum(((long)lhsSize.Width * lhsSize.Height) - ((long)rhsSize.Width * rhsSize.Height));
        }
    }
}


text:
import _ from 'underscore';

const sortRevisions = (revisions) => _.sortBy(revisions, 'created').reverse();

export default sortRevisions;


text:
'''
Created on 24/05/2013

@author: jruiperezv
'''
from __future__ import division
import webapp2
import logging
from viewer_code.profileviewer_models import UserProfile
from viewer_code.profileviewer_models import ViewerUser
from viewer_code.profileviewer_models import ViewerVideo
from viewer_code.profileviewer_models import ViewerExercise
from google.appengine.ext.db import GqlQuery
import viewer_code.viewer_consts
from google.appengine.api import taskqueue
from models import UserData
from models import ProblemLog
from numpy.polynomial import polynomial
from numpy import array
import datetime

from goals.models import Goal

class TimeDistribution(webapp2.RequestHandler):

    def get(self):

        studentUsers =  GqlQuery("SELECT * FROM ViewerUser WHERE student = True")

        logging.info("NOTE: Starting Time Distribution of Use of the Platform cron job");
        for studentUser in studentUsers:
            taskqueue.add(queue_name='time-distribution', url='/admin/time_distribution', params={'userId': studentUser.key().name()})

        logging.info("NOTE: Calculating mean value of Time Distribution of Use of the Platform");

        taskqueue.add(queue_name='time-distribution', url='/admin/mean_calculator', params={'profileName': viewer_code.viewer_consts.TIME_DISTRIBUTION})

        logging.info("NOTE: Finished Use of Platform cron job");

    def post(self):
        user_id = self.request.get('userId')
        usuario = ViewerUser.get_by_key_name(user_id)

        time_schedule_measure = self.time_schedule(usuario)
        efficiency_schedule_measure = self.efficiency_schedule(usuario)
        constancy = self.constancy_meanvar(usuario)

        userProfile = UserProfile.get_by_key_name(user_id)

        if(userProfile == None):
            userProfile = UserProfile(key_name = user_id, user = usuario.user, user_nickname = usuario.user_nickname,
                                      user_id = usuario.user_id,
                                      time_schedule_morning = time_schedule_measure[0], time_schedule_afternoon = time_schedule_measure[1], time_schedule_night = time_schedule_measure[2],
                                      morning_schedule_efficiency = efficiency_schedule_measure[0], afternoon_schedule_efficiency = efficiency_schedule_measure[1], night_schedule_efficiency = efficiency_schedule_measure[2], average_schedule_efficiency = efficiency_schedule_measure[3],
                                      constancy_mean = constancy[0], constancy_variance = constancy[1])
        else:
            userProfile.time_schedule_morning = time_schedule_measure[0]
            userProfile.time_schedule_afternoon = time_schedule_measure[1]
            userProfile.time_schedule_night = time_schedule_measure[2]
            userProfile.morning_schedule_efficiency = efficiency_schedule_measure[0]
            userProfile.afternoon_schedule_efficiency = efficiency_schedule_measure[1]
            userProfile.night_schedule_efficiency = efficiency_schedule_measure[2]
            userProfile.average_schedule_efficiency = efficiency_schedule_measure[3]
            userProfile.constancy_mean = constancy[0]
            userProfile.constancy_variance = constancy[1]

        userProfile.put()

    def time_schedule(self, usuario):

        subject_videos = GqlQuery("SELECT * FROM ViewerVideo")
        subject_exercises = GqlQuery("SELECT * FROM ViewerExercise")

        morningTimeExercises = 0
        afternoonTimeExercises = 0
        nightTimeExercises = 0
        morningTimeVideos = 0
        afternoonTimeVideos = 0
        nightTimeVideos = 0

        totalTime = 0

        for subject_exercise in subject_exercises:
            problemLogs = GqlQuery("SELECT * FROM ProblemLog WHERE exercise = :1 AND user = :2", subject_exercise.name, usuario.user)
            for problemLog in problemLogs:
                hour = problemLog.backup_timestamp.hour
                totalTime += problemLog.time_taken
                if( 6 < hour and hour < 14 ):
                    morningTimeExercises += problemLog.time_taken
                elif( 14 <= hour and hour < 21):
                    afternoonTimeExercises += problemLog.time_taken
                elif( hour <= 6 or hour == 21 or hour == 22 or hour == 23 or hour == 0):
                    nightTimeExercises += problemLog.time_taken
                else:
                    print "WRONG HOUR EXERCISE"

        for subject_video in subject_videos:
            videoLogs = GqlQuery("SELECT * FROM VideoLog WHERE video = :1 AND user = :2", subject_video.video, usuario.user)
            for videoLog in videoLogs:
                hour = videoLog.backup_timestamp.hour
                totalTime += videoLog.seconds_watched
                if( 6 < hour and hour < 14 ):
                    morningTimeVideos += videoLog.seconds_watched
                elif( 14 <= hour and hour < 21):
                    afternoonTimeVideos += videoLog.seconds_watched
                elif( hour <= 6 or hour == 21 or hour == 22 or hour == 23 or hour == 0):
                    nightTimeVideos += videoLog.seconds_watched
                else:
                    print "WRONG HOUR VIDEO"

        totalTimeMorning = morningTimeExercises + morningTimeVideos
        totalTimeAfternoon = afternoonTimeExercises + afternoonTimeVideos
        totalTimeNight = nightTimeExercises + nightTimeVideos

        if(totalTime == 0):
            return [0, 0, 0]
        else:
            morningPercentage = int((totalTimeMorning/totalTime)*100)
            afternoonPercentage = int((totalTimeAfternoon/totalTime)*100)
            nightPercentage = 100 - morningPercentage - afternoonPercentage
            return [morningPercentage, afternoonPercentage, nightPercentage]

    def efficiency_schedule(self, usuario):

        subject_exercises = GqlQuery("SELECT * FROM ViewerExercise")

        morningExercises = 0
        afternoonExercises = 0
        nightExercises = 0
        correctMorningExercises = 0
        correctAfternoonExercises = 0
        correctNightExercises = 0

        for subject_exercise in subject_exercises:
            problemLogs = GqlQuery("SELECT * FROM ProblemLog WHERE exercise = :1 AND user = :2", subject_exercise.name, usuario.user)
            for problemLog in problemLogs:
                hour = problemLog.backup_timestamp.hour
                if( 6 < hour and hour < 14 ):
                    morningExercises += 1
                    if((problemLog.correct == True) and (problemLog.count_hints == 0) and (problemLog.count_attempts == 1) and (problemLog.time_taken < 60)):
                        correctMorningExercises += 1
                elif( 14 <= hour and hour < 21):
                    afternoonExercises += 1
                    if((problemLog.correct == True) and (problemLog.count_hints == 0) and (problemLog.count_attempts == 1) and (problemLog.time_taken < 60)):
                        correctAfternoonExercises += 1
                elif( hour <= 6 or hour == 21 or hour == 22 or hour == 23 or hour == 0):
                    nightExercises += 1
                    if((problemLog.correct == True) and (problemLog.count_hints == 0) and (problemLog.count_attempts == 1) and (problemLog.time_taken < 60)):
                        correctNightExercises += 1
                else:
                    print "WRONG HOUR EXERCISE"

        if(morningExercises == 0):
            morningPercentage = 0
        else:
            morningPercentage = (correctMorningExercises/morningExercises)*100

        if(afternoonExercises == 0):
            afternoonPercentage = 0
        else:
            afternoonPercentage = (correctAfternoonExercises/afternoonExercises)*100

        if(nightExercises == 0):
            nightPercentage = 0
        else:
            nightPercentage = (correctNightExercises/nightExercises)*100

        totalExercises = morningExercises + afternoonExercises + nightExercises
        totalCorrectExercises = correctMorningExercises + correctAfternoonExercises + correctNightExercises
        if(totalExercises == 0):
            averagePercentage = 0
        else:
            averagePercentage = (totalCorrectExercises/totalExercises)*100

        return [int(morningPercentage), int(afternoonPercentage), int(nightPercentage), int(averagePercentage)]

    # Constancia para las pruebas con periodo temporal prefijado
    def constancy_meanvar(self, usuario):

        userDayList = []
        startDate = datetime.datetime(2012,8,1,0,0,1)
        endDate = datetime.datetime(2012,8,2,0,0,1)
        numberOfDays = 0

        subject_videos = GqlQuery("SELECT * FROM ViewerVideo")
        subject_exercises = GqlQuery("SELECT * FROM ViewerExercise")

        while(numberOfDays < 40):

            timeSpentThisDay = 0

            for subject_exercise in subject_exercises:
                problemLogs = GqlQuery("SELECT * FROM ProblemLog WHERE exercise = :1 AND user = :2 AND time_done >= :3 AND time_done < :4", subject_exercise.name, usuario.user, startDate, endDate)
                for problemLog in problemLogs:
                    timeSpentThisDay += problemLog.time_taken

            for subject_video in subject_videos:
                videoLogs = GqlQuery("SELECT * FROM VideoLog WHERE video = :1 AND user = :2 AND time_watched >= :3 AND time_watched < :4", subject_video.video, usuario.user, startDate, endDate)
                for videoLog in videoLogs:
                    timeSpentThisDay += videoLog.seconds_watched

            startDate += datetime.timedelta(days=1)
            endDate += datetime.timedelta(days=1)
            numberOfDays += 1
            userDayList.append(timeSpentThisDay/60)

        # Mean calculation
        suma = 0
        for userDay in userDayList:
            suma += userDay

        userMean = int(suma/numberOfDays)

        std = 0
        for userDay in userDayList:
            std += (userDay-userMean)**2

        userVar = int(std/(numberOfDays-1))

        return [userMean, userVar]

    """
    # Constancia con fecha actual como fecha final
    def constancy_meanvar(self, usuario):

        userDayList = []
        startDate = datetime.datetime(2013,7,25,0,0,1)
        endDate = startDate + datetime.timedelta(days=1)
        numberOfDays = 0

        subject_videos = GqlQuery("SELECT * FROM ViewerVideo")
        subject_exercises = GqlQuery("SELECT * FROM ViewerExercise")
        todayDate = datetime.datetime.now()

        while(endDate < todayDate):

            timeSpentThisDay = 0

            for subject_exercise in subject_exercises:
                problemLogs = GqlQuery("SELECT * FROM ProblemLog WHERE exercise = :1 AND user = :2 AND time_done >= :3 AND time_done < :4", subject_exercise.name, usuario.user, startDate, endDate)
                for problemLog in problemLogs:
                    timeSpentThisDay += problemLog.time_taken

            for subject_video in subject_videos:
                videoLogs = GqlQuery("SELECT * FROM VideoLog WHERE video = :1 AND user = :2 AND time_watched >= :3 AND time_watched < :4", subject_video.video, usuario.user, startDate, endDate)
                for videoLog in videoLogs:
                    timeSpentThisDay += videoLog.seconds_watched

            startDate += datetime.timedelta(days=1)
            endDate += datetime.timedelta(days=1)
            numberOfDays += 1
            userDayList.append(timeSpentThisDay/60)

        # Mean calculation
        suma = 0
        for userDay in userDayList:
            suma += userDay

        userMean = int(suma/numberOfDays)

        std = 0
        for userDay in userDayList:
            std += (userDay-userMean)**2

        userVar = int(std/(numberOfDays-1))

        return [userMean, userVar]

    """

    def constancy(self, usuario):

        userDayList = []
        startDate = datetime.datetime(2012,8,1,0,0,1)
        endDate = datetime.datetime(2012,8,2,0,0,1)
        numberOfDays = 0

        subject_videos = GqlQuery("SELECT * FROM ViewerVideo")
        subject_exercises = GqlQuery("SELECT * FROM ViewerExercise")

        while(numberOfDays < 40):

            timeSpentThisDay = 0

            for subject_exercise in subject_exercises:
                problemLogs = GqlQuery("SELECT * FROM ProblemLog WHERE exercise = :1 AND user = :2 AND time_done >= :3 AND time_done < :4", subject_exercise.name, usuario.user, startDate, endDate)
                for problemLog in problemLogs:
                    timeSpentThisDay += problemLog.time_taken

            for subject_video in subject_videos:
                videoLogs = GqlQuery("SELECT * FROM VideoLog WHERE video = :1 AND user = :2 AND time_watched >= :3 AND time_watched < :4", subject_video.video, usuario.user, startDate, endDate)
                for videoLog in videoLogs:
                    timeSpentThisDay += videoLog.seconds_watched

            startDate += datetime.timedelta(days=1)
            endDate += datetime.timedelta(days=1)
            numberOfDays += 1
            userDayList.append(timeSpentThisDay/60)

        # Mean calculation
        suma = 0
        for userDay in userDayList:
            suma += userDay

        userMean = int(suma/numberOfDays)

        constancy = 0

        if(userMean != 0):
            for userDay in userDayList:
                constancy += abs((userDay-userMean)/userMean)
            return constancy/len(userDayList)
        else:
            return 0


text:
//
//  GTLYouTubeVideoGetRatingResponse.h
//

// ----------------------------------------------------------------------------
// NOTE: This file is generated from Google APIs Discovery Service.
// Service:
//   YouTube Data API (youtube/v3)
// Description:
//   Supports core YouTube features, such as uploading videos, creating and
//   managing playlists, searching for content, and much more.
// Documentation:
//   https://developers.google.com/youtube/v3
// Classes:
//   GTLYouTubeVideoGetRatingResponse (0 custom class methods, 5 custom properties)

#if GTL_BUILT_AS_FRAMEWORK
  #import "GTL/GTLObject.h"
#else
  #import "GTLObject.h"
#endif

@class GTLYouTubeVideoRating;

// ----------------------------------------------------------------------------
//
//   GTLYouTubeVideoGetRatingResponse
//

// This class supports NSFastEnumeration over its "items" property. It also
// supports -itemAtIndex: to retrieve individual objects from "items".

@interface GTLYouTubeVideoGetRatingResponse : GTLCollectionObject

// Etag of this resource.
@property (nonatomic, copy) NSString *ETag;

// Serialized EventId of the request which produced this response.
@property (nonatomic, copy) NSString *eventId;

// A list of ratings that match the request criteria.
@property (nonatomic, retain) NSArray *items;  // of GTLYouTubeVideoRating

// Identifies what kind of resource this is. Value: the fixed string
// "youtube#videoGetRatingResponse".
@property (nonatomic, copy) NSString *kind;

// The visitorId identifies the visitor.
@property (nonatomic, copy) NSString *visitorId;

@end


text:
package com.blackcrowsys.canvas.command;

import com.blackcrowsys.canvas.Canvas;
import com.blackcrowsys.canvas.Coordinate;
import com.blackcrowsys.canvas.exception.CanvasOperationException;
import org.junit.Test;

import static org.mockito.Mockito.*;

public class TestDrawLine {

    private Canvas canvas = mock(Canvas.class);

    @Test
    public void testDrawingLine() throws CanvasOperationException {
        Coordinate from = new Coordinate(1, 2);
        Coordinate to = new Coordinate(6, 2);

        Command drawLine = new DrawLine(from, to);
        drawLine.execute(canvas);
        verify(canvas, times(1)).drawLine(from, to);
    }
}


text:
<?php

namespace WellidUsageExamples;

/**
 * Generated by PHPUnit_SkeletonGenerator on 2016-01-24 at 19:20:33.
 */
class SanitorWellidEmailExampleTest extends \PHPUnit_Framework_TestCase {

    /**
     * @var SanitorWellidEmailExample
     */
    protected $object;

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp() {
        $_SESSION['validemail'] = 'mail@benedict\roeser.de';
        $_SESSION['invalidemail'] = '';
        $this->object = new SanitorWellidEmailExample;
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown() {

    }

    /**
     * @covers WellidUsageExamples\SanitorWellidEmailExample::getSanitizer
     */
    public function testGetSanitizer() {
        $this->assertEquals(FILTER_SANITIZE_EMAIL, $this->object->getSanitizer()->getSanitizeFilter());
        $this->assertEquals(FILTER_NULL_ON_FAILURE, $this->object->getSanitizer()->getSanitizeFlags());
    }

	/**
     * @covers WellidUsageExamples\SanitorWellidEmailExample::setRawValue
	 * @covers WellidUsageExamples\SanitorWellidEmailExample::addSanitorMatchValidator
     */
	public function testSetRawValue() {
		$this->assertNull($this->object->getRawValue());
		$this->object->setRawValue('example@exam\ple.org');
		$this->assertEquals('example@exam\ple.org', $this->object->getRawValue());
		$this->assertTrue($this->object->validateBool());
		$this->object->setRawValue('foooo');
		$this->assertFalse($this->object->validateBool());
		$this->assertInstanceOf('WellidUsageExamples\SanitorWellidEmailExample', $this->object->addSanitorMatchValidator());
		$this->object->setRawValue('example@exam\ple.org');
		$this->assertFalse($this->object->validateBool());
	}

    /**
     * @covers WellidUsageExamples\SanitorWellidEmailExample::setSanitizer
     * @covers WellidUsageExamples\SanitorWellidEmailExample::__construct
     * @covers WellidUsageExamples\SanitorWellidEmailExample::addValidators
     * @covers WellidUsageExamples\SanitorWellidEmailExample::getValidators
     */
    public function testSetSanitizer() {
        $x = new SanitorWellidEmailExample();
        $this->assertCount(2, $x->getValidators());
    }

    /**
     * @covers WellidUsageExamples\SanitorWellidEmailExample::rawValueFromInput
     * @covers WellidUsageExamples\SanitorWellidEmailExample::getRawValue
     * @covers WellidUsageExamples\SanitorWellidEmailExample::getFilteredValue
     * @covers WellidUsageExamples\SanitorWellidEmailExample::getValue
     */
    public function testRawValueFromInput() {
        $this->object->rawValueFromInput(\INPUT_SESSION, 'foo');
        $this->assertNull($this->object->getRawValue());
        $this->object->rawValueFromInput(\INPUT_SESSION, 'validemail');
        $this->assertEquals('mail@benedict\roeser.de', $this->object->getRawValue());
        $this->assertEquals('mail@benedictroeser.de', $this->object->getFilteredValue());
        $this->assertEquals('mail@benedictroeser.de', $this->object->getValue());
        $this->assertTrue($this->object->validate()->hasPassed());
        $this->object->rawValueFromInput(\INPUT_SESSION, 'invalidemail');
        $this->assertFalse($this->object->validate()->hasPassed());

        $_REQUEST['rq_valid'] = 'mail@exa\mple.org';
        $_REQUEST['rq_invalid'] = 'mailexample.org';
        $this->object->rawValueFromInput(\INPUT_REQUEST, 'rq_valid');
        $this->assertTrue($this->object->validate()->hasPassed());
        $this->object->rawValueFromInput(\INPUT_REQUEST, 'rq_invalid');
        $this->assertFalse($this->object->validate()->hasPassed());

        $this->object->rawValueFromInput(\INPUT_ENV, 'env_valid');
        $this->assertTrue($this->object->validate()->hasPassed());
        $this->object->rawValueFromInput(\INPUT_ENV, 'env_invalid');
        $this->assertFalse($this->object->validate()->hasPassed());

        $this->object->rawValueFromInput(\INPUT_SERVER, 'PHP_SELF');
        $this->assertFalse($this->object->validate()->hasPassed());
        $this->assertEquals('phpunit', substr(strtolower($this->object->getFilteredValue()), -7));

        $this->object->rawValueFromInput(\INPUT_GET, 'mail');
        $this->assertFalse($this->object->validate()->hasPassed());
        $this->assertNull($this->object->getRawValue());
        $this->assertEquals('', $this->object->getFilteredValue());
        $this->object->rawValueFromInput(\INPUT_POST, 'mail');
        $this->assertFalse($this->object->validate()->hasPassed());
        $this->assertNull($this->object->getRawValue());
        $this->assertEquals('', $this->object->getFilteredValue());
        $this->object->rawValueFromInput(\INPUT_COOKIE, 'mail');
        $this->assertFalse($this->object->validate()->hasPassed());
        $this->assertNull($this->object->getRawValue());
        $this->assertEquals('', $this->object->getFilteredValue());
    }

}


text:
<?php namespace Tilmeld;

use SciActive\Hook;
use Nymph\Nymph;
use Tilmeld\Entities\User;
use Tilmeld\Entities\Group;

class Tilmeld {
  const VERSION = '1.0.0-beta.1';

  const NO_ACCESS = 0;
  const READ_ACCESS = 1;
  const WRITE_ACCESS = 2;
  const FULL_ACCESS = 4;

  /**
   * The Tilmeld config array.
   *
   * @var array
   * @access public
   */
  public static $config;

  /**
   * The currently logged in user.
   *
   * @var \Tilmeld\Entities\User|null
   * @access public
   */
  public static $currentUser = null;

  /**
   * The server's timezone.
   *
   * @var string|null
   * @access private
   */
  private static $serverTimezone;

  /**
   * Check to see if the current user has an ability.
   *
   * If $ability is null, it will check to see if a user is currently logged
   * in.
   *
   * @param string $ability The ability.
   * @return bool True or false.
   */
  public static function gatekeeper($ability = null) {
    if (!isset(self::$currentUser)) {
      return false;
    }
    return self::$currentUser->gatekeeper($ability);
  }

  /**
   * Apply configuration to Tilmeld.
   *
   * $config should be an associative array of Tilmeld configuration. Use the
   * following form:
   *
   * [
   *   'setup_url' => 'http://example.com/tilmeld/',
   *   'create_admin' => false
   * ]
   *
   * @param array $config An associative array of Tilmeld's configuration.
   */
  public static function configure($config = []) {
    $defaults = include dirname(__DIR__).'/conf/defaults.php';
    self::$config = array_replace($defaults, $config);

    // Set up access control hooks when Nymph is called.
    if (!isset(Nymph::$driver)) {
      throw new Exception('Tilmeld can\'t be configured before Nymph.');
    }
    HookMethods::setup();
    self::authenticate();
  }

  /**
   * Add selectors to a list of options and selectors which will limit results
   * to only entities the current user has access to.
   *
   * @param array &$optionsAndSelectors The options and selectors of the query.
   */
  public static function addAccessControlSelectors(&$optionsAndSelectors) {
    $user = self::$currentUser;

    if (isset($user) && $user->gatekeeper('system/admin')) {
      // The user is a system admin, so they can see everything.
      return;
    }

    if (!isset($optionsAndSelectors[0])) {
      throw new Exception('No options in argument.');
    } elseif (isset($optionsAndSelectors[0]['class'])
        && (
          $optionsAndSelectors[0]['class'] === '\Tilmeld\Entities\User'
          || $optionsAndSelectors[0]['class'] === '\Tilmeld\Entities\Group'
          || $optionsAndSelectors[0]['class'] === 'Tilmeld\Entities\User'
          || $optionsAndSelectors[0]['class'] === 'Tilmeld\Entities\Group'
        )
      ) {
      // They are requesting a user/group. Always accessible for reading.
      return;
    }

    if ($user === null) {
      $optionsAndSelectors[] = ['|',
        // Other access control is sufficient.
        'gte' => ['acOther', Tilmeld::READ_ACCESS],
        // The user and group are not set.
        ['&',
          '!isset' => ['user', 'group']
        ]
      ];
    } else {
      $selector = ['|',
        // Other access control is sufficient.
        'gte' => ['acOther', Tilmeld::READ_ACCESS],
        // The user and group are not set.
        ['&',
          '!isset' => [
            'user',
            'group'
          ]
        ],
        // It is owned by the user.
        ['&',
          'ref' => ['user', $user],
          'gte' => ['acUser', Tilmeld::READ_ACCESS]
        ],
        // The user is listed in acRead, acWrite, or acFull.
        'ref' => [
          ['acRead', $user],
          ['acWrite', $user],
          ['acFull', $user]
        ]
      ];
      $groupRefs = [];
      $acRefs = [];
      if (isset($user->group) && isset($user->group->guid)) {
        // It belongs to the user's primary group.
        $groupRefs[] = ['group', $user->group];
        // User's primary group is listed in acRead, acWrite, or acFull.
        $acRefs[] = ['acRead', $user->group];
        $acRefs[] = ['acWrite', $user->group];
        $acRefs[] = ['acFull', $user->group];
      }
      foreach ($user->groups as $curSecondaryGroup) {
        if (isset($curSecondaryGroup) && isset($curSecondaryGroup->guid)) {
          // It belongs to the user's secondary group.
          $groupRefs[] = ['group', $curSecondaryGroup];
          // User's secondary group is listed in acRead, acWrite, or acFull.
          $acRefs[] = ['acRead', $curSecondaryGroup];
          $acRefs[] = ['acWrite', $curSecondaryGroup];
          $acRefs[] = ['acFull', $curSecondaryGroup];
        }
      }
      foreach ($user->getDescendantGroups() as $curDescendantGroup) {
        if (isset($curDescendantGroup) && isset($curDescendantGroup->guid)) {
          // It belongs to the user's secondary group.
          $groupRefs[] = ['group', $curDescendantGroup];
          // User's secondary group is listed in acRead, acWrite, or acFull.
          $acRefs[] = ['acRead', $curDescendantGroup];
          $acRefs[] = ['acWrite', $curDescendantGroup];
          $acRefs[] = ['acFull', $curDescendantGroup];
        }
      }
      // All the group refs.
      if (!empty($groupRefs)) {
        $selector[] = ['&',
          'gte' => ['acGroup', Tilmeld::READ_ACCESS],
          ['|',
            'ref' => $groupRefs
          ]
        ];
      }
      // All the acRead, acWrite, and acFull refs.
      if (!empty($acRefs)) {
        $selector[] = ['|',
          'ref' => $acRefs
        ];
      }
      $optionsAndSelectors[] = $selector;
    }
  }

  /**
   * Check an entity's permissions for a user.
   *
   * This will check the AC (Access Control) properties of the entity. These
   * include the following properties:
   *
   * - acUser
   * - acGroup
   * - acOther
   * - acRead
   * - acWrite
   * - acFull
   *
   * "acUser" refers to the entity's owner, "acGroup" refers to all users in the
   * entity's group and all ancestor groups, and "acOther" refers to any user
   * who doesn't fit these descriptions.
   *
   * Each of these properties should be either NO_ACCESS, READ_ACCESS,
   * WRITE_ACCESS, or FULL_ACCESS.
   *
   * - NO_ACCESS - the user has no access to the entity.
   * - READ_ACCESS, the user has read access to the entity.
   * - WRITE_ACCESS, the user has read and write access to the entity, but can't
   *   delete it, change its access controls, or change its ownership.
   * - FULL_ACCESS, the user has read, write, and delete access to the entity,
   *   as well as being able to manage its access controls and ownership.
   *
   * These properties defaults to:
   *
   * - acUser = Tilmeld::FULL_ACCESS
   * - acGroup = Tilmeld::READ_ACCESS
   * - acOther = Tilmeld::NO_ACCESS
   *
   * "acRead", "acWrite", and "acFull" are arrays of users and/or groups that
   * also have those permissions.
   *
   * Only users with FULL_ACCESS have the ability to change any of the ac*,
   * user, and group properties.
   *
   * The following conditions will result in different checks, which determine
   * whether the check passes:
   *
   * - The user has the "system/admin" ability. (Always true.)
   * - It is a user or group. (True for READ_ACCESS or Tilmeld admins.)
   * - The entity has no "user" and no "group". (Always true.)
   * - No user is logged in. (Check other AC.)
   * - The entity is the user. (Always true.)
   * - It is the user's primary group. (True for READ_ACCESS.)
   * - The user or its groups are listed in "acRead". (True for READ_ACCESS.)
   * - The user or its groups are listed in "acWrite". (True for READ_ACCESS and
   *   WRITE_ACCESS.)
   * - The user or its groups are listed in "acFull". (Always true.)
   * - Its "user" is the user. (It is owned by the user.) (Check user AC.)
   * - Its "group" is the user's primary group. (Check group AC.)
   * - Its "group" is one of the user's secondary groups. (Check group AC.)
   * - Its "group" is a descendant of one of the user's groups. (Check group
   *   AC.)
   * - None of the above. (Check other AC.)
   *
   * @param object &$entity The entity to check.
   * @param int $type The lowest level of permission to consider a pass. One of
   *                  Tilmeld::READ_ACCESS, Tilmeld::WRITE_ACCESS, or
   *                  Tilmeld::FULL_ACCESS.
   * @param \Tilmeld\Entities\User|null $user The user to check permissions for.
   *                                          If null, uses the current user. If
   *                                          false, checks for public access.
   * @return bool Whether the current user has at least $type permission for the
   *              entity.
   */
  public static function checkPermissions(
      &$entity,
      $type = Tilmeld::READ_ACCESS,
      $user = null
  ) {
    // Only works for entities.
    if (!is_object($entity) || !is_callable([$entity, 'is'])) {
      return false;
    }

    // Calculate the user.
    if ($user === null) {
      $userOrNull = self::$currentUser;
      $userOrEmpty = User::current(true);
    } elseif ($user === false) {
      $userOrNull = null;
      $userOrEmpty = User::factory();
    } else {
      $userOrNull = $userOrEmpty = $user;
    }

    if ($userOrEmpty->gatekeeper('system/admin')) {
      return true;
    }

    // Users and groups are always readable. Editable by Tilmeld admins.
    if ((
          is_a($entity, '\Tilmeld\Entities\User')
          || is_a($entity, '\Tilmeld\Entities\Group')
          || is_a($entity, '\SciActive\HookOverride_Tilmeld_Entities_User')
          || is_a($entity, '\SciActive\HookOverride_Tilmeld_Entities_Group')
        )
        && (
          $type === Tilmeld::READ_ACCESS
          || $userOrEmpty->gatekeeper('tilmeld/admin')
        )
      ) {
      return true;
    }

    // Entities with no owners are always editable.
    if (!isset($entity->user) && !isset($entity->group)) {
      return true;
    }

    // Load access control, since we need it now...
    $acUser = $entity->acUser ?? Tilmeld::FULL_ACCESS;
    $acGroup = $entity->acGroup ?? Tilmeld::READ_ACCESS;
    $acOther = $entity->acOther ?? Tilmeld::NO_ACCESS;

    if ($userOrNull === null) {
      return ($acOther >= $type);
    }

    // Check if the entity is the user.
    if ($userOrEmpty->is($entity)) {
      return true;
    }

    // Check if the entity is the user's group. Always readable.
    if (isset($userOrEmpty->group)
        && is_callable([$userOrEmpty->group, 'is'])
        && $userOrEmpty->group->is($entity)
        && $type === Tilmeld::READ_ACCESS
      ) {
      return true;
    }

    // Calculate all the groups the user belongs to.
    $allGroups = isset($userOrEmpty->group) ? [$userOrEmpty->group] : [];
    $allGroups = array_merge($allGroups, $userOrEmpty->groups);
    $allGroups = array_merge($allGroups, $userOrEmpty->getDescendantGroups());

    // Check access ac properties.
    $checks = [
      ['type' => Tilmeld::FULL_ACCESS, 'array' => (array) $entity->acFull],
      ['type' => Tilmeld::WRITE_ACCESS, 'array' => (array) $entity->acWrite],
      ['type' => Tilmeld::READ_ACCESS, 'array' => (array) $entity->acRead]
    ];
    foreach ($checks as $curCheck) {
      if ($type <= $curCheck['type']) {
        if ($userOrEmpty->inArray($curCheck['array'])) {
          return true;
        }
        foreach ($allGroups as $curGroup) {
          if (is_callable([$curGroup, 'inArray'])
              && $curGroup->inArray($curCheck['array'])
            ) {
            return true;
          }
        }
      }
    }

    // Check ownership ac properties.
    if (is_callable([$entity->user, 'is'])
        && $entity->user->is($userOrNull)
      ) {
      return ($acUser >= $type);
    }
    if (is_callable([$entity->group, 'is'])
        && $entity->group->inArray($allGroups)
      ) {
      return ($acGroup >= $type);
    }
    return ($acOther >= $type);
  }

  /**
   * Fill session user data.
   *
   * Also sets the default timezone to the user's timezone.
   *
   * @param \Tilmeld\Entities\User $user The user.
   */
  public static function fillSession($user) {
    if (!isset(self::$serverTimezone)) {
      self::$serverTimezone = date_default_timezone_get();
    }
    self::$currentUser = $user;
    date_default_timezone_set($user->getTimezone());
    self::$currentUser->updateDataProtection();
  }

  /**
   * Clear session user data.
   *
   * Also sets the default timezone to the server default.
   */
  public static function clearSession() {
    $user = self::$currentUser;
    self::$currentUser = null;
    if (isset(self::$serverTimezone)) {
      date_default_timezone_set(self::$serverTimezone);
    }
    if ($user) {
      $user->updateDataProtection();
    }
  }

  /**
   * Validate and extract the user from a token.
   *
   * @param string $token The authentication token.
   * @return \Tilmeld\Entities\User|bool The user on success, false on failure.
   */
  public static function extractToken($token) {
    $extract = self::$config['jwt_extract']($token);
    if (!$extract) {
      return false;
    }
    $guid = $extract['guid'];

    $user = Nymph::getEntity(
        ['class' => '\Tilmeld\Entities\User'],
        ['&',
          'guid' => $guid
        ]
    );
    if (!$user || !$user->guid || !$user->enabled) {
      return false;
    }

    return $user;
  }

  /**
   * Check for a TILMELDAUTH cookie, and, if set, authenticate from it.
   *
   * @return bool True if a user was authenticated, false on any failure.
   */
  public static function authenticate() {
    // If a client does't support cookies, they can use the X-TILMELDAUTH header
    // to provide the auth token.
    if (!empty($_SERVER['HTTP_X_TILMELDAUTH']) && empty($_COOKIE['TILMELDAUTH'])) {
      $fromAuthHeader = true;
      $authToken = $_SERVER['HTTP_X_TILMELDAUTH'];
    } elseif (!empty($_COOKIE['TILMELDAUTH'])) {
      $fromAuthHeader = false;
      $authToken = $_COOKIE['TILMELDAUTH'];
    } else {
      return false;
    }
    $setupUrlParts = parse_url(self::$config['setup_url']);
    $setupHost = $setupUrlParts['host'].
      (array_key_exists('port', $setupUrlParts) ? ':'.$setupUrlParts['port'] : '');
    if ($_SERVER['HTTP_HOST'] === $setupHost
        && $_SERVER['REQUEST_URI'] === $setupUrlParts['path']
      ) {
      // The request is for the setup app, so don't check for the XSRF token.
      $extract = self::$config['jwt_extract']($authToken);
    } else {
      // The request is for something else, so check for a valid XSRF token.
      if (empty($_SERVER['HTTP_X_XSRF_TOKEN'])) {
        return false;
      }

      $extract = self::$config['jwt_extract'](
          $authToken,
          $_SERVER['HTTP_X_XSRF_TOKEN']
      );
    }

    if (!$extract) {
      self::logout();
      return false;
    }
    $guid = $extract['guid'];
    $expire = $extract['expire'];

    $user = Nymph::getEntity(
        ['class' => '\Tilmeld\Entities\User'],
        ['&',
          'guid' => $guid
        ]
    );
    if (!$user || !$user->guid || !$user->enabled) {
      self::logout();
      return false;
    }

    if ($expire < time() + self::$config['jwt_renew']) {
      // If the user is less than renew time from needing a new token, give them
      // a new one.
      self::login($user, $fromAuthHeader);
    } else {
      self::fillSession($user);
    }
    return true;
  }

  /**
   * Logs the given user into the system.
   *
   * @param \Tilmeld\Entities\User $user The user.
   * @param bool $alwaysSendAuthHeader When true, a custom header with the auth
   *                                   token will be sent.
   * @return bool True on success, false on failure.
   */
  public static function login($user, $sendAuthHeader) {
    if (isset($user->guid) && $user->enabled) {
      $token = self::$config['jwt_builder']($user);
      $appUrlParts = parse_url(self::$config['app_url']);
      setcookie(
          'TILMELDAUTH',
          $token,
          time() + self::$config['jwt_expire'],
          $appUrlParts['path'],
          $appUrlParts['host'],
          $appUrlParts['scheme'] === 'https',
          false // Allow JS access (for CSRF protection).
      );
      if ($sendAuthHeader) {
        header("X-TILMELDAUTH: $token");
      }
      self::fillSession($user);
      return true;
    }
    return false;
  }

  /**
   * Logs the current user out of the system.
   */
  public static function logout() {
    self::clearSession();
    $appUrlParts = parse_url(self::$config['app_url']);
    setcookie(
        'TILMELDAUTH',
        '',
        null,
        $appUrlParts['path'],
        $appUrlParts['host']
    );
  }

  /**
   * Sort an array of groups hierarchically.
   *
   * An additional property of the groups can be used to sort them under their
   * parents.
   *
   * @param array &$array The array of groups.
   * @param string|null $property The name of the property to sort groups by.
   *                              Null for no additional sorting.
   * @param bool $caseSensitive Sort case sensitively.
   * @param bool $reverse Reverse the sort order.
   */
  public static function groupSort(
      &$array,
      $property = null,
      $caseSensitive = false,
      $reverse = false
  ) {
    Nymph::hsort($array, $property, 'parent', $caseSensitive, $reverse);
  }
}


text:
package com.edwise.pocs.lombok.withlombok;

import org.junit.Test;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

public class BookTest {

    @Test
    public void testBuilderBook() {
        Book book = Book.builder()
                .id(12L)
                .title("The Hobbit")
                .type((short) 2)
                .isbn("111-232323-4544")
                .build();

        assertThat(book.getId(), is(12L));
        assertThat(book.getTitle(), is("The Hobbit"));
        assertThat(book.getType(), is((short) 2));
        assertThat(book.getIsbn(), is("111-232323-4544"));
    }
}


text:
"""proper unique in repo

Revision ID: 560af4d735a7
Revises: 49989f23adc6
Create Date: 2014-08-25 14:34:16.816783

"""

# revision identifiers, used by Alembic.
revision = '560af4d735a7'
down_revision = '49989f23adc6'

from alembic import op

def upgrade():
    op.drop_constraint('idx_repositories_name', 'repositories', type_='unique')
    op.drop_constraint('repo_name', 'repositories', type_='unique')
    op.create_unique_constraint('uk_repositories_repo_name', 'repositories', ['repo_name', 'user_id'])

def downgrade():
    op.drop_constraint('uk_repositories_repo_name', 'repositories')


text:
typedef struct BBEdges {
    CGFloat top, left, bottom, right;
} BBEdges;

UIKIT_STATIC_INLINE BBEdges BBEdgesMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right) {
    BBEdges edges = {top, left, bottom, right};
    return edges;
}

UIKIT_STATIC_INLINE BBEdges BBEdgesMakeUniform(CGFloat value) {
    BBEdges edges = {value, value, value, value};
    return edges;
}

typedef NS_ENUM(NSInteger, BBFlexDirection) {
    BBFlexDirectionColumn,
    BBFlexDirectionColumnReverse,
    BBFlexDirectionRow,
    BBFlexDirectionRowReverse,
};

typedef NS_ENUM(NSInteger, BBJustification) {
    BBJustificationFlexStart,
    BBJustificationCenter,
    BBJustificationFlexEnd,
    BBJustificationSpaceBetween,
    BBJustificationSpaceAround,
};

typedef NS_ENUM(NSInteger, BBChildAlignment) {
    BBChildAlignmentFlexStart = 1,
    BBChildAlignmentCenter,
    BBChildAlignmentFlexEnd,
    BBChildAlignmentStretch,
};

typedef NS_ENUM(NSInteger, BBSelfAlignment) {
    BBSelfAlignmentAuto,
    BBSelfAlignmentFlexStart,
    BBSelfAlignmentCenter,
    BBSelfAlignmentFlexEnd,
    BBSelfAlignmentStretch,
};

@class BBLayout;

@interface BBNode : NSObject

@property (nonatomic) BOOL wrap;
@property (nonatomic) CGFloat flex;
@property (nonatomic) CGSize size;
@property (nonatomic) CGFloat width;
@property (nonatomic) CGFloat height;
@property (nonatomic) BBFlexDirection flexDirection;
@property (nonatomic) BBEdges margin;
@property (nonatomic) CGFloat leftMargin;
@property (nonatomic) CGFloat rightMargin;
@property (nonatomic) CGFloat topMargin;
@property (nonatomic) CGFloat bottomMargin;
@property (nonatomic) BBEdges padding;
@property (nonatomic) CGFloat leftPadding;
@property (nonatomic) CGFloat rightPadding;
@property (nonatomic) CGFloat topPadding;
@property (nonatomic) CGFloat bottomPadding;
@property (nonatomic) BBJustification justification;
@property (nonatomic) BBSelfAlignment selfAlignment;
@property (nonatomic) BBChildAlignment childAlignment;
@property (nonatomic) NSArray *children;

@property (nonatomic, copy) CGSize (^measure)(CGFloat width);

- (BBLayout *)layoutWithMaxWidth:(CGFloat)maxWidth;

@end


text:
package com.java110.api.listener.mapping;

import com.alibaba.fastjson.JSONObject;
import com.java110.api.listener.AbstractServiceApiListener;
import com.java110.utils.constant.*;
import com.java110.utils.exception.ListenerExecuteException;
import com.java110.utils.util.Assert;
import com.java110.utils.util.BeanConvertUtil;
import com.java110.core.context.DataFlowContext;
import com.java110.intf.community.IMappingInnerServiceSMO;
import com.java110.dto.mapping.MappingDto;
import com.java110.core.event.service.api.ServiceDataFlowEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import com.java110.core.annotation.Java110Listener;

/**
 * 保存小区侦听
 * add by wuxw 2019-06-30
 */
@Java110Listener("deleteMappingListener")
public class DeleteMappingListener extends AbstractServiceApiListener {

    @Autowired
    private IMappingInnerServiceSMO mappingInnerServiceSMOImpl;
    @Override
    protected void validate(ServiceDataFlowEvent event, JSONObject reqJson) {
        //Assert.hasKeyAndValue(reqJson, "xxx", "xxx");

        Assert.hasKeyAndValue(reqJson, "id", "编码ID不能为空");

    }

    @Override
    protected void doSoService(ServiceDataFlowEvent event, DataFlowContext context, JSONObject reqJson) {

        MappingDto mappingDto = BeanConvertUtil.covertBean(reqJson, MappingDto.class);

        int count = mappingInnerServiceSMOImpl.deleteMapping(mappingDto);

        if (count < 1) {
            throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR, "编辑数据失败");
        }

        ResponseEntity<String> responseEntity = new ResponseEntity<String>("", HttpStatus.OK);

        context.setResponseEntity(responseEntity);
    }

    @Override
    public String getServiceCode() {
        return ServiceCodeMappingConstant.DELETE_MAPPING;
    }

    @Override
    public HttpMethod getHttpMethod() {
        return HttpMethod.POST;
    }

    @Override
    public int getOrder() {
        return DEFAULT_ORDER;
    }

    public IMappingInnerServiceSMO getMappingInnerServiceSMOImpl() {
        return mappingInnerServiceSMOImpl;
    }

    public void setMappingInnerServiceSMOImpl(IMappingInnerServiceSMO mappingInnerServiceSMOImpl) {
        this.mappingInnerServiceSMOImpl = mappingInnerServiceSMOImpl;
    }
}