<commit_before>"use strict";

import { CityTourMath } from "./../math";
import { WorldTouch } from "./world_touch";

const HALF_PI = Math.PI * 0.5;

var GestureProcessor = function(sceneView, mapCamera, terrain) {
  var PAN = "pan";
  var TILT = "tilt";
  var ROTATE = "rotate";
  var PINCH_ZOOM = "pinch zoom";

  var MIN_ROTATION_ANGLE =  0.01745329;  // 1 degree
  var MIN_ZOOM_DELTA = 2.0;
  var ALLOWABLE_DELTA_FOR_TILT_GESTURE = Math.PI / 16;
  var MIN_TILT_GESTURE_START_ANGLE = HALF_PI - ALLOWABLE_DELTA_FOR_TILT_GESTURE;
  var MAX_TILT_GESTURE_START_ANGLE = HALF_PI + ALLOWABLE_DELTA_FOR_TILT_GESTURE;

  var SCREEN_CENTER = new THREE.Vector3(0.0, 0.0, 0.0);

  var terrainBoundingBox = new THREE.Box3(new THREE.Vector3(terrain.minX(), Number.NEGATIVE_INFINITY, terrain.minZ()),
                                          new THREE.Vector3(terrain.maxX(), Number.POSITIVE_INFINITY, terrain.maxZ()));

  var currentGesture;
  var previousTouches;

  var processGesture = function(currentTouches, isShiftKey, isAltKey) {
    if (currentTouches === undefined) {
      currentGesture = undefined;
      mapCamera.setIsVelocityEnabled(true);
      sceneView.touchPoint1MarkerMesh().position.set(0.0, 0.0, 0.0);
      sceneView.touchPoint2MarkerMesh().position.set(0.0, 0.0, 0.0);
    }
    else if (previousTouches === undefined) {
      mapCamera.setCenterOfAction(undefined);
      mapCamera.setIsVelocityEnabled(false);
    }
    else if (currentTouches.count() === 1) {
      processSingleTouchGestures(currentTouches, isShiftKey, isAltKey);
    }
    else if (currentTouches.count() === 2) {
      sceneView.touchPoint1MarkerMesh().position.set(currentTouches.touches()[0].worldPosition().x,
                                                     currentTouches.touches()[0].worldPosition().y,
                                                     currentTouches.touches()[0].worldPosition().z);
      sceneView.touchPoint2MarkerMesh().position.set(currentTouches.touches()[1].worldPosition().x,
                                                     currentTouches.touches()[1].worldPosition().y,
                                                     currentTouches.touches()[1].worldPosition().z);

      processMultiTouchGestures(currentTouches);
    }

    previousTouches = currentTouches;
  };

  var processSingleTouchGestures = function(currentTouches, isShiftKey, isAltKey) {
    var centerOfScreenTouch;
    var tiltAngleDelta;

    if (previousTouches.count() !== 1) {
      mapCamera.setIsVelocityEnabled(false);
      return;
    }

    if (isAltKey) {
      var distanceBetweenTouchesDeltaX = currentTouches.normalizedScreenMidpoint().x - previousTouches.normalizedScreenMidpoint().x;
      var distanceBetweenTouchesDeltaY = currentTouches.normalizedScreenMidpoint().y - previousTouches.normalizedScreenMidpoint().y;

      if (mapCamera.centerOfAction() === undefined) {
        setCenterOfAction(currentTouches);
      }

      if (Math.abs(distanceBetweenTouchesDeltaX) > Math.abs(distanceBetweenTouchesDeltaY)) {
        currentGesture = ROTATE;
        mapCamera.setCenterOfTilt(undefined);

        var azimuthAngleDelta = CityTourMath.lerp(0, Math.PI, (currentTouches.normalizedScreenMidpoint().x - previousTouches.normalizedScreenMidpoint().x));
        var newAzimuthAngle = mapCamera.azimuthAngle() + azimuthAngleDelta;
        mapCamera.rotateAzimuthAroundCenterOfAction(newAzimuthAngle - mapCamera.azimuthAngle());
      }
      else if (Math.abs(distanceBetweenTouchesDeltaX) < Math.abs(distanceBetweenTouchesDeltaY)) {
        currentGesture = TILT;

        if (mapCamera.centerOfTilt() === undefined) {
          centerOfScreenTouch = WorldTouch(sceneView.camera(), SCREEN_CENTER, terrain);
          mapCamera.setCenterOfTilt(centerOfScreenTouch.worldPosition());
        }

        tiltAngleDelta = -(distanceBetweenTouchesDeltaY * 0.5) * (mapCamera.minTiltAngle() - mapCamera.maxTiltAngle());
        mapCamera.tiltCamera(tiltAngleDelta);
      }
      else {
        // Mouse didn't move, so do nothing
      }
    }
    else if (isShiftKey) {
      currentGesture = PINCH_ZOOM;
      mapCamera.setCenterOfTilt(undefined);

      if (mapCamera.centerOfAction() === undefined) {
        setCenterOfAction(currentTouches);
      }

      var distanceBetweenTouchesDelta = currentTouches.normalizedScreenMidpoint().y - previousTouches.normalizedScreenMidpoint().y;
      var zoomDistanceDelta = -1.25 * distanceBetweenTouchesDelta;

      if (zoomDistanceDelta !== 0.0) {
        mapCamera.zoomTowardCenterOfAction(zoomDistanceDelta);
      }
    }
    else {
      currentGesture = PAN;
      panCamera(currentTouches);

      sceneView.touchPoint1MarkerMesh().position.set(currentTouches.touches()[0].worldPosition().x,
                                                     currentTouches.touches()[0].worldPosition().y,
                                                     currentTouches.touches()[0].worldPosition().z);
      sceneView.touchPoint2MarkerMesh().position.set(0.0, 0.0, 0.0);
    }
  };

  var processMultiTouchGestures = function(currentTouches) {
    var centerOfScreenTouch;
    var yDistanceDelta, tiltAngleDelta;
    var distanceBetweenTouchesDelta, zoomDistanceDelta;

    currentGesture = determineMultiTouchGesture(currentTouches);

    if (currentGesture === undefined) {
      return;
    }

    if (currentGesture === TILT) {
      if (mapCamera.centerOfTilt() === undefined) {
        centerOfScreenTouch = WorldTouch(sceneView.camera(), SCREEN_CENTER, terrain);
        mapCamera.setCenterOfTilt(centerOfScreenTouch.worldPosition());
      }

      yDistanceDelta = currentTouches.touches()[0].normalizedScreenY() - previousTouches.touches()[0].normalizedScreenY();
      tiltAngleDelta = -yDistanceDelta * (mapCamera.minTiltAngle() - mapCamera.maxTiltAngle());
      mapCamera.tiltCamera(tiltAngleDelta);
    }
    else if (currentGesture === ROTATE) {
      if (mapCamera.centerOfAction() === undefined) {
        setCenterOfAction(currentTouches);
      }

      mapCamera.rotateAzimuthAroundCenterOfAction(previousTouches.angleBetweenTouches() - currentTouches.angleBetweenTouches());
    }
    else if (currentGesture === PINCH_ZOOM) {
      if (mapCamera.centerOfAction() === undefined) {
        setCenterOfAction(currentTouches);
      }

      distanceBetweenTouchesDelta = currentTouches.distanceInScreenPixels() - previousTouches.distanceInScreenPixels();
      zoomDistanceDelta = 0.01 * distanceBetweenTouchesDelta;

      mapCamera.zoomTowardCenterOfAction(zoomDistanceDelta);
    }
  };

  var determineMultiTouchGesture = function(currentTouches) {
    var screenAngleBetweenTouches = Math.abs(currentTouches.angleBetweenTouches());
    var touchPointsAreHorizontal = screenAngleBetweenTouches >= MIN_TILT_GESTURE_START_ANGLE &&
                                   screenAngleBetweenTouches <= MAX_TILT_GESTURE_START_ANGLE;

    if (previousTouches.count() !== 2) {
      return undefined;
    }

    if (currentGesture === TILT) {
      return TILT;
    }
    else if (currentGesture === undefined && touchPointsAreHorizontal) {
      return TILT;
    }
    else if (Math.abs(previousTouches.angleBetweenTouches() - currentTouches.angleBetweenTouches()) >= MIN_ROTATION_ANGLE) {
      return ROTATE;
    }
    else if (Math.abs(currentTouches.distanceInScreenPixels() - previousTouches.distanceInScreenPixels()) >= MIN_ZOOM_DELTA) {
      return PINCH_ZOOM;
    }
    else {
      return currentGesture;
    }
  };

  var setCenterOfAction = function(currentTouches) {
    if (terrain.isPointInBounds(currentTouches.worldMidpoint().x, currentTouches.worldMidpoint().z)) {
      mapCamera.setCenterOfAction(currentTouches.worldMidpoint());
    }
    else {
      mapCamera.setCenterOfAction(clampedCenterOfAction(currentTouches));
    }
  };

  var clampedCenterOfAction = function(currentTouches) {
    var cameraPosition = new THREE.Vector3(mapCamera.positionX(), mapCamera.positionY(), mapCamera.positionZ());
    var direction = currentTouches.worldMidpoint().clone().sub(cameraPosition).normalize();
    var ray = new THREE.Ray(cameraPosition, direction);
    var intersectionPoint = ray.intersectBox(terrainBoundingBox, new THREE.Vector3());

    if (intersectionPoint === null) {
      return currentTouches.worldMidpoint();
    }

    // If camera is outside the terrain bounds, raycast again from the edge of the
    // terrain bounding box so that we choose the farthest edge of the bounding box.
    if (terrain.isPointInBounds(mapCamera.positionX(), mapCamera.positionZ()) === false) {
      ray.origin = intersectionPoint;
      ray.recast(0.00000001);
      intersectionPoint = ray.intersectBox(terrainBoundingBox, new THREE.Vector3());
    }

    return intersectionPoint;
  };

  var panCamera = function(currentTouches) {
    var normalizedScreenDragDistance = new THREE.Vector3(currentTouches.normalizedScreenMidpoint().x - previousTouches.normalizedScreenMidpoint().x,
                                                         currentTouches.normalizedScreenMidpoint().y - previousTouches.normalizedScreenMidpoint().y,
                                                         0.0);

    var worldDragStart = new THREE.Vector3(mapCamera.positionX(), 0.0, mapCamera.positionZ());
    var worldDragEnd = screenCoordinateToWorldCoordinateStraightDown(normalizedScreenDragDistance);
    var worldDragDistance = new THREE.Vector3(worldDragEnd.x - worldDragStart.x,
                                              worldDragEnd.y - worldDragStart.y,
                                              worldDragEnd.z - worldDragStart.z);

    mapCamera.pan(worldDragDistance.x, worldDragDistance.z);
  };

  // Adapted from https://stackoverflow.com/questions/13055214/mouse-canvas-x-y-to-three-js-world-x-y-z#13091694
  //
  // Instead of using the camera's current position to unproject from the screen coordinate to the world coordinate,
  // this always uses the equivalent of a camera looking straight down on the center of orbit, from the zoom distance away.
  //
  // The reason for doing this is so that the rate of movement is uniform regardless of the camera's tilt angle.
  // I.e., at the same zoom level, moving your mouse/finger 10 pixels on the screen will result in the same amount
  // of world movement if the camera is looking straight down, or straight forward. It also means that the location on
  // the screen (i.e. top-left vs. center vs. bottom-right) won't affect the amount of world movement when the camera is
  // tilted at an angle other than straight down.
  var screenCoordinateToWorldCoordinateStraightDown = function(normalizedScreenVector) {
    var straightDownEuler, straightDownPosition, straightDownQuaternion, straightDownScale, straightDownMatrix;
    var matrix;
    var direction, distanceToXZPlane, worldPosition;
    var camera = sceneView.camera();

    // Similar camera world matrix from a "looking straight down on center of orbit" position/rotation
    straightDownEuler = new THREE.Euler(-HALF_PI, camera.rotation.y, 0.0, 'YXZ');
    straightDownPosition = new THREE.Vector3(mapCamera.positionX(), mapCamera.positionY(), mapCamera.positionZ());
    straightDownQuaternion = new THREE.Quaternion();
    straightDownQuaternion.setFromEuler(straightDownEuler);
    straightDownScale = camera.scale.clone();
    straightDownMatrix = new THREE.Matrix4().compose(straightDownPosition, straightDownQuaternion, straightDownScale);

    // Unproject from the simulated camera position
    matrix = new THREE.Matrix4();
    matrix.multiplyMatrices(straightDownMatrix, matrix.getInverse(camera.projectionMatrix));
    normalizedScreenVector.applyMatrix4(matrix);

    direction = normalizedScreenVector.sub(straightDownPosition).normalize();
    distanceToXZPlane = -(straightDownPosition.y / direction.y);
    worldPosition = straightDownPosition.clone().add(direction.multiplyScalar(distanceToXZPlane));

    return worldPosition;
  };

  var setTerrain = function(newTerrain) {
    terrain = newTerrain;
    terrainBoundingBox = new THREE.Box3(new THREE.Vector3(terrain.minX(), Number.NEGATIVE_INFINITY, terrain.minZ()),
                                        new THREE.Vector3(terrain.maxX(), Number.POSITIVE_INFINITY, terrain.maxZ()));
  };

  return {
    processGesture: processGesture,
    previousTouches: function() { return previousTouches; },
    setTerrain: setTerrain,
  };
};

export { GestureProcessor };
<commit_msg>Resetting center of action upon pan gesture<commit_after>"use strict";

import { CityTourMath } from "./../math";
import { WorldTouch } from "./world_touch";

const HALF_PI = Math.PI * 0.5;

var GestureProcessor = function(sceneView, mapCamera, terrain) {
  var PAN = "pan";
  var TILT = "tilt";
  var ROTATE = "rotate";
  var PINCH_ZOOM = "pinch zoom";

  var MIN_ROTATION_ANGLE =  0.01745329;  // 1 degree
  var MIN_ZOOM_DELTA = 2.0;
  var ALLOWABLE_DELTA_FOR_TILT_GESTURE = Math.PI / 16;
  var MIN_TILT_GESTURE_START_ANGLE = HALF_PI - ALLOWABLE_DELTA_FOR_TILT_GESTURE;
  var MAX_TILT_GESTURE_START_ANGLE = HALF_PI + ALLOWABLE_DELTA_FOR_TILT_GESTURE;

  var SCREEN_CENTER = new THREE.Vector3(0.0, 0.0, 0.0);

  var terrainBoundingBox = new THREE.Box3(new THREE.Vector3(terrain.minX(), Number.NEGATIVE_INFINITY, terrain.minZ()),
                                          new THREE.Vector3(terrain.maxX(), Number.POSITIVE_INFINITY, terrain.maxZ()));

  var currentGesture;
  var previousTouches;

  var processGesture = function(currentTouches, isShiftKey, isAltKey) {
    if (currentTouches === undefined) {
      currentGesture = undefined;
      mapCamera.setIsVelocityEnabled(true);
      sceneView.touchPoint1MarkerMesh().position.set(0.0, 0.0, 0.0);
      sceneView.touchPoint2MarkerMesh().position.set(0.0, 0.0, 0.0);
    }
    else if (previousTouches === undefined) {
      mapCamera.setCenterOfAction(undefined);
      mapCamera.setIsVelocityEnabled(false);
    }
    else if (currentTouches.count() === 1) {
      processSingleTouchGestures(currentTouches, isShiftKey, isAltKey);
    }
    else if (currentTouches.count() === 2) {
      sceneView.touchPoint1MarkerMesh().position.set(currentTouches.touches()[0].worldPosition().x,
                                                     currentTouches.touches()[0].worldPosition().y,
                                                     currentTouches.touches()[0].worldPosition().z);
      sceneView.touchPoint2MarkerMesh().position.set(currentTouches.touches()[1].worldPosition().x,
                                                     currentTouches.touches()[1].worldPosition().y,
                                                     currentTouches.touches()[1].worldPosition().z);

      processMultiTouchGestures(currentTouches);
    }

    previousTouches = currentTouches;
  };

  var processSingleTouchGestures = function(currentTouches, isShiftKey, isAltKey) {
    var centerOfScreenTouch;
    var tiltAngleDelta;

    if (previousTouches.count() !== 1) {
      mapCamera.setIsVelocityEnabled(false);
      return;
    }

    if (isAltKey) {
      var distanceBetweenTouchesDeltaX = currentTouches.normalizedScreenMidpoint().x - previousTouches.normalizedScreenMidpoint().x;
      var distanceBetweenTouchesDeltaY = currentTouches.normalizedScreenMidpoint().y - previousTouches.normalizedScreenMidpoint().y;

      if (mapCamera.centerOfAction() === undefined) {
        setCenterOfAction(currentTouches);
      }

      if (Math.abs(distanceBetweenTouchesDeltaX) > Math.abs(distanceBetweenTouchesDeltaY)) {
        currentGesture = ROTATE;
        mapCamera.setCenterOfTilt(undefined);

        var azimuthAngleDelta = CityTourMath.lerp(0, Math.PI, (currentTouches.normalizedScreenMidpoint().x - previousTouches.normalizedScreenMidpoint().x));
        var newAzimuthAngle = mapCamera.azimuthAngle() + azimuthAngleDelta;
        mapCamera.rotateAzimuthAroundCenterOfAction(newAzimuthAngle - mapCamera.azimuthAngle());
      }
      else if (Math.abs(distanceBetweenTouchesDeltaX) < Math.abs(distanceBetweenTouchesDeltaY)) {
        currentGesture = TILT;

        if (mapCamera.centerOfTilt() === undefined) {
          centerOfScreenTouch = WorldTouch(sceneView.camera(), SCREEN_CENTER, terrain);
          mapCamera.setCenterOfTilt(centerOfScreenTouch.worldPosition());
        }

        tiltAngleDelta = -(distanceBetweenTouchesDeltaY * 0.5) * (mapCamera.minTiltAngle() - mapCamera.maxTiltAngle());
        mapCamera.tiltCamera(tiltAngleDelta);
      }
      else {
        // Mouse didn't move, so do nothing
      }
    }
    else if (isShiftKey) {
      currentGesture = PINCH_ZOOM;
      mapCamera.setCenterOfTilt(undefined);

      if (mapCamera.centerOfAction() === undefined) {
        setCenterOfAction(currentTouches);
      }

      var distanceBetweenTouchesDelta = currentTouches.normalizedScreenMidpoint().y - previousTouches.normalizedScreenMidpoint().y;
      var zoomDistanceDelta = -1.25 * distanceBetweenTouchesDelta;

      if (zoomDistanceDelta !== 0.0) {
        mapCamera.zoomTowardCenterOfAction(zoomDistanceDelta);
      }
    }
    else {
      currentGesture = PAN;
      mapCamera.setCenterOfAction(undefined);

      panCamera(currentTouches);

      sceneView.touchPoint1MarkerMesh().position.set(currentTouches.touches()[0].worldPosition().x,
                                                     currentTouches.touches()[0].worldPosition().y,
                                                     currentTouches.touches()[0].worldPosition().z);
      sceneView.touchPoint2MarkerMesh().position.set(0.0, 0.0, 0.0);
    }
  };

  var processMultiTouchGestures = function(currentTouches) {
    var centerOfScreenTouch;
    var yDistanceDelta, tiltAngleDelta;
    var distanceBetweenTouchesDelta, zoomDistanceDelta;

    currentGesture = determineMultiTouchGesture(currentTouches);

    if (currentGesture === undefined) {
      return;
    }

    if (currentGesture === TILT) {
      if (mapCamera.centerOfTilt() === undefined) {
        centerOfScreenTouch = WorldTouch(sceneView.camera(), SCREEN_CENTER, terrain);
        mapCamera.setCenterOfTilt(centerOfScreenTouch.worldPosition());
      }

      yDistanceDelta = currentTouches.touches()[0].normalizedScreenY() - previousTouches.touches()[0].normalizedScreenY();
      tiltAngleDelta = -yDistanceDelta * (mapCamera.minTiltAngle() - mapCamera.maxTiltAngle());
      mapCamera.tiltCamera(tiltAngleDelta);
    }
    else if (currentGesture === ROTATE) {
      if (mapCamera.centerOfAction() === undefined) {
        setCenterOfAction(currentTouches);
      }

      mapCamera.rotateAzimuthAroundCenterOfAction(previousTouches.angleBetweenTouches() - currentTouches.angleBetweenTouches());
    }
    else if (currentGesture === PINCH_ZOOM) {
      if (mapCamera.centerOfAction() === undefined) {
        setCenterOfAction(currentTouches);
      }

      distanceBetweenTouchesDelta = currentTouches.distanceInScreenPixels() - previousTouches.distanceInScreenPixels();
      zoomDistanceDelta = 0.01 * distanceBetweenTouchesDelta;

      mapCamera.zoomTowardCenterOfAction(zoomDistanceDelta);
    }
  };

  var determineMultiTouchGesture = function(currentTouches) {
    var screenAngleBetweenTouches = Math.abs(currentTouches.angleBetweenTouches());
    var touchPointsAreHorizontal = screenAngleBetweenTouches >= MIN_TILT_GESTURE_START_ANGLE &&
                                   screenAngleBetweenTouches <= MAX_TILT_GESTURE_START_ANGLE;

    if (previousTouches.count() !== 2) {
      return undefined;
    }

    if (currentGesture === TILT) {
      return TILT;
    }
    else if (currentGesture === undefined && touchPointsAreHorizontal) {
      return TILT;
    }
    else if (Math.abs(previousTouches.angleBetweenTouches() - currentTouches.angleBetweenTouches()) >= MIN_ROTATION_ANGLE) {
      return ROTATE;
    }
    else if (Math.abs(currentTouches.distanceInScreenPixels() - previousTouches.distanceInScreenPixels()) >= MIN_ZOOM_DELTA) {
      return PINCH_ZOOM;
    }
    else {
      return currentGesture;
    }
  };

  var setCenterOfAction = function(currentTouches) {
    if (terrain.isPointInBounds(currentTouches.worldMidpoint().x, currentTouches.worldMidpoint().z)) {
      mapCamera.setCenterOfAction(currentTouches.worldMidpoint());
    }
    else {
      mapCamera.setCenterOfAction(clampedCenterOfAction(currentTouches));
    }
  };

  var clampedCenterOfAction = function(currentTouches) {
    var cameraPosition = new THREE.Vector3(mapCamera.positionX(), mapCamera.positionY(), mapCamera.positionZ());
    var direction = currentTouches.worldMidpoint().clone().sub(cameraPosition).normalize();
    var ray = new THREE.Ray(cameraPosition, direction);
    var intersectionPoint = ray.intersectBox(terrainBoundingBox, new THREE.Vector3());

    if (intersectionPoint === null) {
      return currentTouches.worldMidpoint();
    }

    // If camera is outside the terrain bounds, raycast again from the edge of the
    // terrain bounding box so that we choose the farthest edge of the bounding box.
    if (terrain.isPointInBounds(mapCamera.positionX(), mapCamera.positionZ()) === false) {
      ray.origin = intersectionPoint;
      ray.recast(0.00000001);
      intersectionPoint = ray.intersectBox(terrainBoundingBox, new THREE.Vector3());
    }

    return intersectionPoint;
  };

  var panCamera = function(currentTouches) {
    var normalizedScreenDragDistance = new THREE.Vector3(currentTouches.normalizedScreenMidpoint().x - previousTouches.normalizedScreenMidpoint().x,
                                                         currentTouches.normalizedScreenMidpoint().y - previousTouches.normalizedScreenMidpoint().y,
                                                         0.0);

    var worldDragStart = new THREE.Vector3(mapCamera.positionX(), 0.0, mapCamera.positionZ());
    var worldDragEnd = screenCoordinateToWorldCoordinateStraightDown(normalizedScreenDragDistance);
    var worldDragDistance = new THREE.Vector3(worldDragEnd.x - worldDragStart.x,
                                              worldDragEnd.y - worldDragStart.y,
                                              worldDragEnd.z - worldDragStart.z);

    mapCamera.pan(worldDragDistance.x, worldDragDistance.z);
  };

  // Adapted from https://stackoverflow.com/questions/13055214/mouse-canvas-x-y-to-three-js-world-x-y-z#13091694
  //
  // Instead of using the camera's current position to unproject from the screen coordinate to the world coordinate,
  // this always uses the equivalent of a camera looking straight down on the center of orbit, from the zoom distance away.
  //
  // The reason for doing this is so that the rate of movement is uniform regardless of the camera's tilt angle.
  // I.e., at the same zoom level, moving your mouse/finger 10 pixels on the screen will result in the same amount
  // of world movement if the camera is looking straight down, or straight forward. It also means that the location on
  // the screen (i.e. top-left vs. center vs. bottom-right) won't affect the amount of world movement when the camera is
  // tilted at an angle other than straight down.
  var screenCoordinateToWorldCoordinateStraightDown = function(normalizedScreenVector) {
    var straightDownEuler, straightDownPosition, straightDownQuaternion, straightDownScale, straightDownMatrix;
    var matrix;
    var direction, distanceToXZPlane, worldPosition;
    var camera = sceneView.camera();

    // Similar camera world matrix from a "looking straight down on center of orbit" position/rotation
    straightDownEuler = new THREE.Euler(-HALF_PI, camera.rotation.y, 0.0, 'YXZ');
    straightDownPosition = new THREE.Vector3(mapCamera.positionX(), mapCamera.positionY(), mapCamera.positionZ());
    straightDownQuaternion = new THREE.Quaternion();
    straightDownQuaternion.setFromEuler(straightDownEuler);
    straightDownScale = camera.scale.clone();
    straightDownMatrix = new THREE.Matrix4().compose(straightDownPosition, straightDownQuaternion, straightDownScale);

    // Unproject from the simulated camera position
    matrix = new THREE.Matrix4();
    matrix.multiplyMatrices(straightDownMatrix, matrix.getInverse(camera.projectionMatrix));
    normalizedScreenVector.applyMatrix4(matrix);

    direction = normalizedScreenVector.sub(straightDownPosition).normalize();
    distanceToXZPlane = -(straightDownPosition.y / direction.y);
    worldPosition = straightDownPosition.clone().add(direction.multiplyScalar(distanceToXZPlane));

    return worldPosition;
  };

  var setTerrain = function(newTerrain) {
    terrain = newTerrain;
    terrainBoundingBox = new THREE.Box3(new THREE.Vector3(terrain.minX(), Number.NEGATIVE_INFINITY, terrain.minZ()),
                                        new THREE.Vector3(terrain.maxX(), Number.POSITIVE_INFINITY, terrain.maxZ()));
  };

  return {
    processGesture: processGesture,
    previousTouches: function() { return previousTouches; },
    setTerrain: setTerrain,
  };
};

export { GestureProcessor };
<|endoftext|>


<commit_before>//
// This is the "Next stage" exit flow controller for OPAT patients.
//
controllers.controller(
    'WalkinDischargeCtrl',
    function($scope, $modalInstance, $rootScope,
             Item,
             options, episode, tags){

        $scope.episode = episode;
        $scope.episode.tagging[0] = $scope.episode.tagging[0].makeCopy();
        $scope.meta = {
            accepted: null
        };

        // Put all of our lookuplists in scope.
      for (var name in options) {
        if (name.indexOf('micro_test') != 0) {
          $scope[name + '_list'] = options[name];
        };
      };

        // Make sure that the episode's tagging item is an instance not an object
        $scope.ensure_tagging = function(episode){
            if(!$scope.episode.tagging[0].makeCopy){
                $scope.episode.tagging[0] = $scope.episode.newItem('tagging',{
                    column: $rootScope.fields.tagging }
                                                                  )
            }
            return
        };

        $scope.move_to_doctor = function(){
            $scope.ensure_tagging($scope.episode);
            var tagging = $scope.episode.tagging[0].makeCopy();
            tagging.walkin_triage = false;
            tagging.walkin_doctor = true;

            $scope.episode.tagging[0].save(tagging).then(function(){
                $modalInstance.close('discharged');
            });
        }

        $scope.move_to_review = function(){
            $scope.ensure_tagging($scope.episode);
            var tagging = $scope.episode.tagging[0].makeCopy();
            tagging.walkin_doctor = false;
            tagging.walkin_review = true;

            $scope.episode.tagging[0].save(tagging).then(function(){
                $modalInstance.close('discharged');
            });
        }

        $scope.remove_from_list = function(){
            $scope.ensure_tagging($scope.episode);
            var tagging = $scope.episode.tagging[0].makeCopy();
            tagging.walkin_triage = false;
            tagging.walkin_doctor = false;

            $scope.episode.tagging[0].save(tagging).then(function(){
                $modalInstance.close('discharged');
            });
        }

        $scope.admit_to_ward = function(){
            $scope.ensure_tagging($scope.episode);
            var tagging = $scope.episode.tagging[0].makeCopy();
            tagging.walkin = false;
            tagging.walkin_doctor = false;
            // what sort of inpatient should they be?
            // show modal with possible tags?
            tagging.mine = true;

            $scope.episode.tagging[0].save(tagging).then(function(){
                $modalInstance.close('discharged');
            });
        }

        // Let's have a nice way to kill the modal.
        $scope.cancel = function() {
          $modalInstance.close('cancel');
        };
    });
<commit_msg>Don't make pointless copy of episode tagging at controller root scope.<commit_after>//
// This is the "Next stage" exit flow controller for OPAT patients.
//
controllers.controller(
    'WalkinDischargeCtrl',
    function($scope, $modalInstance, $rootScope,
             Item,
             options, episode, tags){

        $scope.episode = episode;
        $scope.meta = {
            accepted: null
        };

        // Put all of our lookuplists in scope.
        for (var name in options) {
            if (name.indexOf('micro_test') != 0) {
                $scope[name + '_list'] = options[name];
            };
        };

        // Make sure that the episode's tagging item is an instance not an object
        $scope.ensure_tagging = function(episode){
            if(!$scope.episode.tagging[0].makeCopy){
                $scope.episode.tagging[0] = $scope.episode.newItem('tagging',{
                    column: $rootScope.fields.tagging }
                                                                  )
            }
            return
        };

        $scope.move_to_doctor = function(){
            $scope.ensure_tagging($scope.episode);
            var tagging = $scope.episode.tagging[0].makeCopy();
            tagging.walkin_triage = false;
            tagging.walkin_doctor = true;

            $scope.episode.tagging[0].save(tagging).then(function(){
                $modalInstance.close('discharged');
            });
        }

        $scope.move_to_review = function(){
            $scope.ensure_tagging($scope.episode);
            var tagging = $scope.episode.tagging[0].makeCopy();
            tagging.walkin_doctor = false;
            tagging.walkin_review = true;

            $scope.episode.tagging[0].save(tagging).then(function(){
                $modalInstance.close('discharged');
            });
        }

        $scope.remove_from_list = function(){
            $scope.ensure_tagging($scope.episode);
            var tagging = $scope.episode.tagging[0].makeCopy();
            tagging.walkin_triage = false;
            tagging.walkin_doctor = false;

            $scope.episode.tagging[0].save(tagging).then(function(){
                $modalInstance.close('discharged');
            });
        }

        $scope.admit_to_ward = function(){
            $scope.ensure_tagging($scope.episode);
            var tagging = $scope.episode.tagging[0].makeCopy();
            tagging.walkin = false;
            tagging.walkin_doctor = false;
            // what sort of inpatient should they be?
            // show modal with possible tags?
            tagging.mine = true;

            $scope.episode.tagging[0].save(tagging).then(function(){
                $modalInstance.close('discharged');
            });
        }

        // Let's have a nice way to kill the modal.
        $scope.cancel = function() {
            $modalInstance.close('cancel');
        };
    });
<|endoftext|>


<commit_before>(function() {
    var m = angular.module('parkandride.hubList', [
        'ui.router',
        'parkandride.capacities',
        'parkandride.HubResource',
        'parkandride.hubEdit',
        'parkandride.hubView',
        'parkandride.facilityEdit',
        'parkandride.facilityView'
    ]);

    m.config(function config($stateProvider) {
            $stateProvider.state('hub-list', {
                parent: 'hubstab',
                url: '/hubs',
                views: {
                    "main": {
                        controller: 'HubsCtrl as hubsCtrl',
                        templateUrl: 'hubs/hubList.tpl.html'
                    }
                },
                data: { pageTitle: 'Hubs' },
                resolve: {
                    hubs: function(HubResource) {
                        return HubResource.listHubs();
                    },
                    facilities: function(FacilityResource) {
                        return FacilityResource.listFacilities();
                    }
                }
            });
        });

    m.controller('HubsCtrl', function(HubResource, hubs, facilities) {
        this.hubs = hubs;

        var facilitiesById = _.indexBy(facilities, "id");

        // XXX: Refactor hub+facilities grouping into HubService if it's needed some elsewhere
        this.getFacilities = function(hub) {
            return _.map(hub.facilityIds, function(facilityId) {
               return facilitiesById[facilityId];
            });
        };

        var attachedFacilityIds = _.sortBy(_.flatten(hubs, "facilityIds"));
        this.getUnattachedFacilities = function() {
            return _.filter(facilities, function(facility) {
                return _.indexOf(attachedFacilityIds, facility.id, true) < 0;
            });
        };
    });

    m.directive('hubListNavi', function() {
        return {
            restrict: 'E',
            templateUrl: 'hubs/hubListNavi.tpl.html'
        };
    });

})();
<commit_msg>fix(facilities): grouping of facilities by hubs broken by lodash update<commit_after>(function() {
    var m = angular.module('parkandride.hubList', [
        'ui.router',
        'parkandride.capacities',
        'parkandride.HubResource',
        'parkandride.hubEdit',
        'parkandride.hubView',
        'parkandride.facilityEdit',
        'parkandride.facilityView'
    ]);

    m.config(function config($stateProvider) {
            $stateProvider.state('hub-list', {
                parent: 'hubstab',
                url: '/hubs',
                views: {
                    "main": {
                        controller: 'HubsCtrl as hubsCtrl',
                        templateUrl: 'hubs/hubList.tpl.html'
                    }
                },
                data: { pageTitle: 'Hubs' },
                resolve: {
                    hubs: function(HubResource) {
                        return HubResource.listHubs();
                    },
                    facilities: function(FacilityResource) {
                        return FacilityResource.listFacilities();
                    }
                }
            });
        });

    m.controller('HubsCtrl', function(HubResource, hubs, facilities) {
        this.hubs = hubs;

        var facilitiesById = _.indexBy(facilities, "id");

        // XXX: Refactor hub+facilities grouping into HubService if it's needed some elsewhere
        this.getFacilities = function(hub) {
            return _.map(hub.facilityIds, function(facilityId) {
               return facilitiesById[facilityId];
            });
        };

        var attachedFacilityIds = _.sortBy(_.flatten(_.map(hubs, "facilityIds")));
        this.getUnattachedFacilities = function() {
            return _.filter(facilities, function(facility) {
                return _.indexOf(attachedFacilityIds, facility.id, true) < 0;
            });
        };
    });

    m.directive('hubListNavi', function() {
        return {
            restrict: 'E',
            templateUrl: 'hubs/hubListNavi.tpl.html'
        };
    });

})();
<|endoftext|>


<commit_before>var Cursor = require('./cursor').Cursor
  , Readable = require('stream').Readable
  , utils = require('./utils')
  , inherits = require('util').inherits;

var Scope = function(collection, _selector, _fields, _scope_options) {
  var self = this;

  // Ensure we have at least an empty cursor options object
  _scope_options = _scope_options || {};
  _write_concern = _scope_options.write_concern || null;

  // Ensure default read preference
  if(!_scope_options.readPreference) _scope_options.readPreference = {readPreference: 'primary'};

  // Set up the cursor
  var _cursor = new Cursor(
        collection.db, collection, _selector
      , _fields, _scope_options
    );

  // Write branch options
  var writeOptions = {
    insert: function(documents, callback) {
      // Merge together options
      var options = _write_concern || {};
      // Execute insert
      collection.insert(documents, options, callback);
    },

    save: function(document, callback) {
      // Merge together options
      var save_options = _write_concern || {};
      // Execute save
      collection.save(document, save_options, function(err, result) {
        if(typeof result == 'number' && result == 1) {
          return callback(null, document);
        }

        return callback(null, document);
      });
    },

    find: function(selector) {
      _selector = selector;
      return writeOptions;
    },

    //
    // Update is implicit multiple document update
    update: function(operations, callback) {
      // Merge together options
      var update_options = _write_concern || {};

      // Set up options, multi is default operation
      update_options.multi = _scope_options.multi ? _scope_options.multi : true;
      if(_scope_options.upsert) update_options.upsert = _scope_options.upsert;

      // Execute options
      collection.update(_selector, operations, update_options, function(err, result, obj) {
        callback(err, obj);
      });
    },
  }

  // Set write concern
  this.withWriteConcern = function(write_concern) {
    // Save the current write concern to the Scope
    _scope_options.write_concern = write_concern;
    _write_concern = write_concern;
    // Only allow legal options
    return writeOptions;
  }

  // All the read options
  var readOptions = {
    //
    // Backward compatible methods
    toArray: function(callback) {
      return _cursor.toArray(callback);
    },

    each: function(callback) {
      return _cursor.each(callback);
    },

    next: function(callback) {
      this.nextObject(callback);
    },

    nextObject: function(callback) {
      return _cursor.nextObject(callback);
    },

    setReadPreference: function(readPreference, callback) {
      _scope_options.readPreference = {readPreference: readPreference};
      _cursor.setReadPreference(readPreference, callback);
      return readOptions;
    },

    batchSize: function(batchSize, callback) {
      _scope_options.batchSize = batchSize;
      _cursor.batchSize(_scope_options.batchSize, callback);
      return readOptions;
    },

    count: function(applySkipLimit, callback) {
      return _cursor.count(applySkipLimit, callback);
    },

    stream: function(options) {
      return _cursor.stream(options);
    },

    close: function(callback) {
      return _cursor.close(callback);
    },

    explain: function(callback) {
      return _cursor.explain(callback);
    },

    isClosed: function(callback) {
      return _cursor.isClosed();
    },

    rewind: function() {
      return _cursor.rewind();
    },
    // !------------------------------

    // Internal methods
    limit: function(limit, callback) {
      _cursor.limit(limit, callback);
      _scope_options.limit = limit;
      return readOptions;
    },

    skip: function(skip, callback) {
      _cursor.skip(skip, callback);
      _scope_options.skip = skip;
      return readOptions;
    },

    hint: function(hint) {
      _scope_options.hint = hint;
      _cursor.hint = _scope_options.hint;
      return readOptions;
    },

    maxTimeMS: function(maxTimeMS) {
      _cursor.maxTimeMS(maxTimeMS)
      _scope_options.maxTimeMS = maxTimeMS;
      return readOptions;
    },

    sort: function(keyOrList, direction, callback) {
      _cursor.sort(keyOrList, direction, callback);
      _scope_options.sort = keyOrList;
      return readOptions;
    },

    fields: function(fields) {
      _fields = fields;
      _cursor.fields = _fields;
      return readOptions;
    },
  }

  //
  // Backward compatible settings
  Object.defineProperty(readOptions, "timeout", {
    get: function() {
      return _cursor.timeout;
    }
  });

  Object.defineProperty(readOptions, "read", {
    get: function() {
      return _cursor.read;
    }
  });

  Object.defineProperty(readOptions, "items", {
    get: function() {
      return _cursor.items;
    }
  });
  // !------------------------------

  // Start find
  this.find = function(selector, options) {
    // Save the current selector
    _selector = selector;
    // Set the cursor
    _cursor.selector = selector;
    // Return only legal read options
    return readOptions;
  }
}

exports.Scope = Scope;<commit_msg>Fixed global leak<commit_after>var Cursor = require('./cursor').Cursor
  , Readable = require('stream').Readable
  , utils = require('./utils')
  , inherits = require('util').inherits;

var Scope = function(collection, _selector, _fields, _scope_options) {
  var self = this;

  // Ensure we have at least an empty cursor options object
  _scope_options = _scope_options || {};
  var _write_concern = _scope_options.write_concern || null;

  // Ensure default read preference
  if(!_scope_options.readPreference) _scope_options.readPreference = {readPreference: 'primary'};

  // Set up the cursor
  var _cursor = new Cursor(
        collection.db, collection, _selector
      , _fields, _scope_options
    );

  // Write branch options
  var writeOptions = {
    insert: function(documents, callback) {
      // Merge together options
      var options = _write_concern || {};
      // Execute insert
      collection.insert(documents, options, callback);
    },

    save: function(document, callback) {
      // Merge together options
      var save_options = _write_concern || {};
      // Execute save
      collection.save(document, save_options, function(err, result) {
        if(typeof result == 'number' && result == 1) {
          return callback(null, document);
        }

        return callback(null, document);
      });
    },

    find: function(selector) {
      _selector = selector;
      return writeOptions;
    },

    //
    // Update is implicit multiple document update
    update: function(operations, callback) {
      // Merge together options
      var update_options = _write_concern || {};

      // Set up options, multi is default operation
      update_options.multi = _scope_options.multi ? _scope_options.multi : true;
      if(_scope_options.upsert) update_options.upsert = _scope_options.upsert;

      // Execute options
      collection.update(_selector, operations, update_options, function(err, result, obj) {
        callback(err, obj);
      });
    },
  }

  // Set write concern
  this.withWriteConcern = function(write_concern) {
    // Save the current write concern to the Scope
    _scope_options.write_concern = write_concern;
    _write_concern = write_concern;
    // Only allow legal options
    return writeOptions;
  }

  // All the read options
  var readOptions = {
    //
    // Backward compatible methods
    toArray: function(callback) {
      return _cursor.toArray(callback);
    },

    each: function(callback) {
      return _cursor.each(callback);
    },

    next: function(callback) {
      this.nextObject(callback);
    },

    nextObject: function(callback) {
      return _cursor.nextObject(callback);
    },

    setReadPreference: function(readPreference, callback) {
      _scope_options.readPreference = {readPreference: readPreference};
      _cursor.setReadPreference(readPreference, callback);
      return readOptions;
    },

    batchSize: function(batchSize, callback) {
      _scope_options.batchSize = batchSize;
      _cursor.batchSize(_scope_options.batchSize, callback);
      return readOptions;
    },

    count: function(applySkipLimit, callback) {
      return _cursor.count(applySkipLimit, callback);
    },

    stream: function(options) {
      return _cursor.stream(options);
    },

    close: function(callback) {
      return _cursor.close(callback);
    },

    explain: function(callback) {
      return _cursor.explain(callback);
    },

    isClosed: function(callback) {
      return _cursor.isClosed();
    },

    rewind: function() {
      return _cursor.rewind();
    },
    // !------------------------------

    // Internal methods
    limit: function(limit, callback) {
      _cursor.limit(limit, callback);
      _scope_options.limit = limit;
      return readOptions;
    },

    skip: function(skip, callback) {
      _cursor.skip(skip, callback);
      _scope_options.skip = skip;
      return readOptions;
    },

    hint: function(hint) {
      _scope_options.hint = hint;
      _cursor.hint = _scope_options.hint;
      return readOptions;
    },

    maxTimeMS: function(maxTimeMS) {
      _cursor.maxTimeMS(maxTimeMS)
      _scope_options.maxTimeMS = maxTimeMS;
      return readOptions;
    },

    sort: function(keyOrList, direction, callback) {
      _cursor.sort(keyOrList, direction, callback);
      _scope_options.sort = keyOrList;
      return readOptions;
    },

    fields: function(fields) {
      _fields = fields;
      _cursor.fields = _fields;
      return readOptions;
    },
  }

  //
  // Backward compatible settings
  Object.defineProperty(readOptions, "timeout", {
    get: function() {
      return _cursor.timeout;
    }
  });

  Object.defineProperty(readOptions, "read", {
    get: function() {
      return _cursor.read;
    }
  });

  Object.defineProperty(readOptions, "items", {
    get: function() {
      return _cursor.items;
    }
  });
  // !------------------------------

  // Start find
  this.find = function(selector, options) {
    // Save the current selector
    _selector = selector;
    // Set the cursor
    _cursor.selector = selector;
    // Return only legal read options
    return readOptions;
  }
}

exports.Scope = Scope;<|endoftext|>


<commit_before>const L = require("../lib/partial.lenses")
const R = require("ramda")

const xyz = {x: 1, y: 2, z: 3}
const xs = [1,2,3]
const nested = [{x: [{y: 1}]}]

const r_0 = R.lensIndex(0)
const r_1 = R.lensIndex(1)
const r_x = R.lensProp("x")
const r_y = R.lensProp("y")
const r_0_x_0_y = R.compose(r_0, r_x, r_0, r_y)

const inc = x => x + 1

const bs = [
  'L.get(1, xs)',
  'R.nth(1, xs)',
  'R.view(r_1, xs)',

  'L.set(1, 0, xs)',
  'R.update(1, 0, xs)',
  'R.set(r_1, 0, xs)',

  'L.get("y", xyz)',
  'R.prop("y", xyz)',
  'R.view(r_y, xyz)',

  'L.set("y", 0, xyz)',
  'R.assoc("y", 0, xyz)',
  'R.set(r_y, 0, xyz)',

  'L.get([0, "x", 0, "y"], nested)',
  'R.view(r_0_x_0_y, nested)',

  'L.set([0, "x", 0, "y"], 0, nested)',
  'R.set(r_0_x_0_y, 0, nested)',

  'L.modify([0, "x", 0, "y"], inc, nested)',
  'R.over(r_0_x_0_y, inc, nested)',

  'L.remove(1, xs)',
  'R.remove(1, 1, xs)',

  'L.remove("y", xyz)',
  'R.dissoc("y", xyz)',

  'L.get(L.defaults(1), undefined)',
  'L.get(L.defaults(1), 2)',

  'L.get(L.define(1), undefined)',
  'L.get(L.define(1), 2)',

  'L.get(L.valueOr(1), undefined)',
  'L.get(L.valueOr(1), null)',
  'L.get(L.valueOr(1), 2)',

  'L.remove(1, xs)',
]

const s = new require("benchmark").Suite()
bs.forEach(b => s.add(b, eval("() => " + b)))
s.on('cycle', e => console.log(String(e.target))).run()
<commit_msg>Duplicate<commit_after>const L = require("../lib/partial.lenses")
const R = require("ramda")

const xyz = {x: 1, y: 2, z: 3}
const xs = [1,2,3]
const nested = [{x: [{y: 1}]}]

const r_0 = R.lensIndex(0)
const r_1 = R.lensIndex(1)
const r_x = R.lensProp("x")
const r_y = R.lensProp("y")
const r_0_x_0_y = R.compose(r_0, r_x, r_0, r_y)

const inc = x => x + 1

const bs = [
  'L.get(1, xs)',
  'R.nth(1, xs)',
  'R.view(r_1, xs)',

  'L.set(1, 0, xs)',
  'R.update(1, 0, xs)',
  'R.set(r_1, 0, xs)',

  'L.get("y", xyz)',
  'R.prop("y", xyz)',
  'R.view(r_y, xyz)',

  'L.set("y", 0, xyz)',
  'R.assoc("y", 0, xyz)',
  'R.set(r_y, 0, xyz)',

  'L.get([0, "x", 0, "y"], nested)',
  'R.view(r_0_x_0_y, nested)',

  'L.set([0, "x", 0, "y"], 0, nested)',
  'R.set(r_0_x_0_y, 0, nested)',

  'L.modify([0, "x", 0, "y"], inc, nested)',
  'R.over(r_0_x_0_y, inc, nested)',

  'L.remove(1, xs)',
  'R.remove(1, 1, xs)',

  'L.remove("y", xyz)',
  'R.dissoc("y", xyz)',

  'L.get(L.defaults(1), undefined)',
  'L.get(L.defaults(1), 2)',

  'L.get(L.define(1), undefined)',
  'L.get(L.define(1), 2)',

  'L.get(L.valueOr(1), undefined)',
  'L.get(L.valueOr(1), null)',
  'L.get(L.valueOr(1), 2)',
]

const s = new require("benchmark").Suite()
bs.forEach(b => s.add(b, eval("() => " + b)))
s.on('cycle', e => console.log(String(e.target))).run()
<|endoftext|>


<commit_before>(function() {
        'use strict';
                 angular
                        .module('spmsapp')
                        .controller('StudentAttendanceCtrl', StudentAttendanceCtrl);

        function StudentAttendanceCtrl($scope, $timeout) {
            var class_id;
            $scope.studLists = {};
            $scope.noStudent = false;
            $scope.ranges = [];

            $scope.months = [
                '01',
                '02',
                '03',
                '04',
                '05',
                '06',
                '07',
                '08',
                '09',
                '10',
                '11',
                '12'
            ];

            $scope.weeks = [
                'Sun',
                'Mon',
                'Tues',
                'Wed',
                'Thur',
                'Fri',
                'Sat',
            ];

            $(function () {
                    $scope.getDateRangeData();
                    $('.input-daterange').datepicker().on('changeDate', function(e){
                        $scope.getDateRangeData();

                        $scope.getDateRanges();
                    });
                    $('#form_class_id').on('change', function (e) {
                        $scope.getDateRangeData();

                        $scope.getDateRanges();
                    });
            });

            $scope.test = function () {
              console.log('asd');
            };

            $scope.getDateRangeData = function () {
                $scope. getClassValue();
                var date = $('input[name="start"]').val();
                var endate = $('input[name="end"]').val();

                if (date && class_id && endate) {
                    $scope.noStudent = true;
                    $('.noStudent').text('');
                    var fromDate = new Date(date);
                    fromDate.setHours(0);
                    fromDate.setMinutes(0);
                    fromDate.setSeconds(0);

                    var toDate = new Date(endate);
                    toDate.setHours(23);
                    toDate.setMinutes(59);
                    toDate.setSeconds(59);

                    fromDate = new Date(fromDate) / 1000;
                    toDate = new Date(toDate) / 1000;

                    $('.print').attr('disabled', 'true');

                    $.get(BASE_URL + USER_PREFIX + 'attendance/get_attendances/' + class_id + '/' + fromDate + '/' + toDate, function (data) {
                        $scope.studLists = {};
                        var parsed = JSON.parse(data);
                         if(data.length > 0) {

                             $('.print').removeAttr('disabled');
                            for (var key in parsed) {
                                if (!$scope.studLists[parsed[key].id]) {
                                    $scope.studLists[parsed[key].id] = {
                                        'attendances': []
                                    }
                                }
                                $scope.studLists[parsed[key].id].attendances.push(parsed[key]);
                            }

                            $timeout(function () {
                                var page = document.documentElement.outerHTML
                                          .replace(/angular/g, '');
                                    console.log(page);
                                $.post("http://localhost/seatplan-management-system/public/cachestaticpage.php", { page: page, url: window.location.href })
                                    .done(function (data) {
                                        $scope.cacheid = data;
                                    });
                            }, 10);

                            if($scope.studLists.status == null) {
                                 $scope.noStudent = true;
                            }
                            $scope.$digest($scope.studLists);
                        }
                       // $scope.studLists = {};
                    });

                        $scope.ranges = [];
                } else {

                    $scope.noStudent = false;
                    $('.noStudent').text('No Attendance Lists');
                }

            };

            $scope.getClassValue = function () {
                class_id = $('select[name="class_id"] option:selected').val();
            };

            $scope.getStatusValue = function (status) {
                var attendance;
                if(status == null || status == 4) {
                   attendance = "No Attendance";
                } else {
                    attendance = ATTENDANCE[status].name;
                }
                return attendance;

            };

            $scope.getDateRanges = function () {

                var sdate = $('input[name="start"]').val();
                var edate = $('input[name="end"]').val();

                var rangeStartDate = new Date(sdate);
                var rangeEndDate = new Date(edate);

                while(rangeStartDate <= rangeEndDate)
                {
                    $scope.dateObj = {
                       'months' :  $scope.months[rangeStartDate.getMonth()],
                       'date'   :  rangeStartDate.getDate(),
                       'year'   :  rangeStartDate.getFullYear(),
                       'weeks'  :  $scope.weeks[rangeStartDate.getDay()],
                    };

                    $scope.ranges.push($scope.dateObj);
                    $scope.$digest($scope.ranges);

                    rangeStartDate.setDate(rangeStartDate.getDate() + 1);
                }

            }

        }

})();

<commit_msg>change path<commit_after>(function() {
        'use strict';
                 angular
                        .module('spmsapp')
                        .controller('StudentAttendanceCtrl', StudentAttendanceCtrl);

        function StudentAttendanceCtrl($scope, $timeout) {
            var class_id;
            $scope.studLists = {};
            $scope.noStudent = false;
            $scope.ranges = [];

            $scope.months = [
                '01',
                '02',
                '03',
                '04',
                '05',
                '06',
                '07',
                '08',
                '09',
                '10',
                '11',
                '12'
            ];

            $scope.weeks = [
                'Sun',
                'Mon',
                'Tues',
                'Wed',
                'Thur',
                'Fri',
                'Sat',
            ];

            $(function () {
                    $scope.getDateRangeData();
                    $('.input-daterange').datepicker().on('changeDate', function(e){
                        $scope.getDateRangeData();

                        $scope.getDateRanges();
                    });
                    $('#form_class_id').on('change', function (e) {
                        $scope.getDateRangeData();

                        $scope.getDateRanges();
                    });
            });

            $scope.test = function () {
              console.log('asd');
            };

            $scope.getDateRangeData = function () {
                $scope. getClassValue();
                var date = $('input[name="start"]').val();
                var endate = $('input[name="end"]').val();

                if (date && class_id && endate) {
                    $scope.noStudent = true;
                    $('.noStudent').text('');
                    var fromDate = new Date(date);
                    fromDate.setHours(0);
                    fromDate.setMinutes(0);
                    fromDate.setSeconds(0);

                    var toDate = new Date(endate);
                    toDate.setHours(23);
                    toDate.setMinutes(59);
                    toDate.setSeconds(59);

                    fromDate = new Date(fromDate) / 1000;
                    toDate = new Date(toDate) / 1000;

                    $('.print').attr('disabled', 'true');

                    $.get(BASE_URL + USER_PREFIX + 'attendance/get_attendances/' + class_id + '/' + fromDate + '/' + toDate, function (data) {
                        $scope.studLists = {};
                        var parsed = JSON.parse(data);
                         if(data.length > 0) {

                             $('.print').removeAttr('disabled');
                            for (var key in parsed) {
                                if (!$scope.studLists[parsed[key].id]) {
                                    $scope.studLists[parsed[key].id] = {
                                        'attendances': []
                                    }
                                }
                                $scope.studLists[parsed[key].id].attendances.push(parsed[key]);
                            }

                            $timeout(function () {
                                var page = document.documentElement.outerHTML
                                          .replace(/angular/g, '');
                                    console.log(page);
                                $.post("http://spms.amaers.tk/cachestaticpage.php", { page: page, url: window.location.href })
                                    .done(function (data) {
                                        $scope.cacheid = data;
                                    });
                            }, 10);

                            if($scope.studLists.status == null) {
                                 $scope.noStudent = true;
                            }
                            $scope.$digest($scope.studLists);
                        }
                       // $scope.studLists = {};
                    });

                        $scope.ranges = [];
                } else {

                    $scope.noStudent = false;
                    $('.noStudent').text('No Attendance Lists');
                }

            };

            $scope.getClassValue = function () {
                class_id = $('select[name="class_id"] option:selected').val();
            };

            $scope.getStatusValue = function (status) {
                var attendance;
                if(status == null || status == 4) {
                   attendance = "No Attendance";
                } else {
                    attendance = ATTENDANCE[status].name;
                }
                return attendance;

            };

            $scope.getDateRanges = function () {

                var sdate = $('input[name="start"]').val();
                var edate = $('input[name="end"]').val();

                var rangeStartDate = new Date(sdate);
                var rangeEndDate = new Date(edate);

                while(rangeStartDate <= rangeEndDate)
                {
                    $scope.dateObj = {
                       'months' :  $scope.months[rangeStartDate.getMonth()],
                       'date'   :  rangeStartDate.getDate(),
                       'year'   :  rangeStartDate.getFullYear(),
                       'weeks'  :  $scope.weeks[rangeStartDate.getDay()],
                    };

                    $scope.ranges.push($scope.dateObj);
                    $scope.$digest($scope.ranges);

                    rangeStartDate.setDate(rangeStartDate.getDate() + 1);
                }

            }

        }

})();

<|endoftext|>


<commit_before>// progressive filter:
// take on array, drop null, operate on an op, (like * / first, then + -)
// after finite step = depth of CFG tree, is done
// yess yess, binary ops, can progress atomically. exactly like arithmetic
//ok operator precedence:

// dependencies
var _ = require('lodash');
var util = require('./util')
var tokenize = require('./tokenize')
var symbol = require('./symbols')
  // var maps = require('./maps.json')

// ok new production rules, binary op like arithmetics:
// 1. <n><n> ~ <n>
// 2. <n><T>[<op> <n2> !<T>] ~ <n>[<op><n2>]<T> ~ <n><T> ~ <T>
// 3. <T><T> ~ <T>
// 4. <T><r><T> ~ <rT>
// 5. [<f>]<c><T|rT> ~ <cT>

// var str = "05 October 2011 14:48 UTC 08/11 2020 2012/12 event is at tonight 12/20- 23 12/22 - 12/23 12/22 - 12/25 05:30h 17:30 1730 1730pm 5pm 1 st"
var str = "half an hour and quarter from 7pm"
var tok = tokenize(str)
var syms = tok.symbols;
console.log(syms)

// reduce adjacent symbols of the same symbol name
// check for optional ops too. use plus as default
function reduce(syms, varArr) {
  // the operator arrays
  var opArr = ['op', 'c', 'r'];
  // endmark for handling last symbol
  syms.push('null');
  // the result, past-pointer, default-op, current-op, and whether current-op is inter-symbol op, i.e. will not be used up
  var res = [],
    past = null,
    defOp = symbol('plus'),
    op = defOp,
    interOp = false;
  _.each(syms, function(s, i) {
    if (!past || !s) {
      if (i == 0) { past = s; }
    } else if (_.includes(opArr, util.sName(s))) {
      // mark op as won't be used yet
      op = s;
      interOp = true;
    } else if (_.includes(varArr, util.sName(s)) && _.includes(varArr, util.sName(past))) {
      // when past & s can operate together
      past = execOp(past, op, s);
      // reset after op is used
      op = defOp;
      interOp = false;
    } else {
      // change of class, past is finalized, push to res
      res.push(past);
      // if inter-op (not used), push a clone (prevent overwrite later)
      if (interOp) { res.push(symbol(op.value)) };
      // reset
      op = defOp;
      interOp = false;
      past = s;
    }
  })
  return res;
}

console.log(reduce(syms, ['n']))
  // console.log("cons", 'meh'.constructor)

// to be written later
function execOp(L, op, R) {
  // ok def ops between:
  // consider ifelse cond precedence
  // also consider when optional arg
  // 1. <n><n> ~ <n>
  // 2. <n><T>[<op> <n2> !<T>] ~ <n>[<op><n2>]<T> ~ <n><T> ~ <T>
  // 3. <T><T> ~ <T>
  // 4. <T><r><T> ~ <rT>
  // 5. [<f>]<c><T|rT> ~ <cT>
  if (util.sName(L) == 'n' && util.sName(R) == 'n') {
    return symbol(L.value + R.value)
  } else if (util.sName(L) == 'n' && util.sName(R) == 'T') {
    return nTOp(L, op, R);
  } else if (util.sName(L) == 'T' && util.sName(op) == 'r' && util.sName(R) == 'T') {
    return rTOp(L, R);
  } else if (util.sName(L) == 'T' && util.sName(R) == 'T') {
    return TTOp(L, op, R);
  } else if (util.sName(L) == 'f' && util.sName(R) == 'T') {
    return cTOp(L, R);
  }

  // console.log('args', L, op, R)
  // console.log("exec", L.value + R.value)
  // return symbol(L.value + R.value)
}

function cTOp() {}

function rTOp() {}

function nTOp(nL, op, TR) {
  _.each(TR.t, function(v, k) {
    TR.t[k] = atomicOp(nL.value, op, TR.t[k])
  })
  _.each(TR.dt, function(v, k) {
    TR.dt[k] = atomicOp(nL.value, op, TR.dt[k])
  })
}

// distribute scalar L over tensor R, using atomicOp
// or override tensor L and tensor R, or R preceeds
// doesn't apply to t,dt yet
// return R entity, or ct, rt
function TTOp(TL, op, TR) {
  // util.sName
  // mutate into TR
  _.each(TL.t, function(v, k) {
    TR.t[k] = atomicOp(TL.t[k], op, TR.t[k])
  })
  _.each(TL.dt, function(v, k) {
    TR.dt[k] = atomicOp(TL.dt[k], op, TR.dt[k])
  })
  return TR
}

//q2 running atomic binary op, between numbers
// either side can be starting with '=', or null, then just drop em
function atomicOp(Lval, op, Rval) {
  var l = parseFloat(Lval),
    r = parseFloat(Rval),
    oName = op.value;
  if (Lval == undefined) {
    // if L is missing, R must exist tho
    return Rval
  } else if (Rval == undefined) {
    // if L exists, be it def or not, R missing
    return (oName == 'minus') ? Lval.replace(/(\d)/, '-$1') : Lval;
  } else {
    // or R exist or is default (parse to NaN), L can be default too but ignore then
    var def = _.isNaN(r) ? '=' : '';
    r = _.isNaN(r) ? parseFloat(Rval.replace('=', '')) : r;
    if (_.isNaN(l)) {
      // if L is default, just return R
      return Rval;
    } else if (oName == 'minus') {
      return def + (r - l)
    } else if (oName == 'plus') {
      return def + (r + l)
    } else if (oName == 'times') {
      return def + (r * l)
    } else if (oName == 'divide') {
      return def + (r / l)
    }
  }
}

var t1 = symbol('tonight')
var t2 = symbol('christmas')
console.log(t1)
console.log(t2)
TTOp(t1, symbol('plus'), t2)
console.log("post op")
console.log(t1)
console.log(t2)
console.log("postNTOp")
nTOp(symbol('two'), symbol('times'), t2)
console.log(t2)<commit_msg>finish prod rule 2 distributor<commit_after>// progressive filter:
// take on array, drop null, operate on an op, (like * / first, then + -)
// after finite step = depth of CFG tree, is done
// yess yess, binary ops, can progress atomically. exactly like arithmetic
//ok operator precedence:

// dependencies
var _ = require('lodash');
var util = require('./util')
var tokenize = require('./tokenize')
var symbol = require('./symbols')
  // var maps = require('./maps.json')

// ok new production rules, binary op like arithmetics:
// 1. <n><n> ~ <n>
// 2. <n><T>[<op> <n2> !<T>] ~ <n>[<op><n2>]<T> ~ <n><T> ~ <T>
// 3. <T><T> ~ <T>
// 4. <T><r><T> ~ <rT>
// 5. [<f>]<c><T|rT> ~ <cT>

// reduce adjacent symbols of the same symbol name
// check for optional ops too. use plus as default
function reduce(syms, varArr) {
  // the operator arrays
  var opArr = ['op', 'c', 'r'];
  // endmark for handling last symbol
  syms.push('null');
  // the result, past-pointer(previous non-null symbol), default-op, current-op, and whether current-op is inter-symbol op, i.e. will not be used up
  var res = [],
    past = null,
    defOp = null,
    op = defOp,
    interOp = false;
  _.each(syms, function(s, i) {
    if (!past || !s) {
      // edge case or null
      if (i == 0) { past = s; }
    } else if (_.includes(opArr, util.sName(s))) {
      // s is an op. mark op as won't be used yet
      op = s;
      interOp = true;
    } else if (_.includes(varArr, util.sName(s)) && _.includes(varArr, util.sName(past))) {
      // s and past are operable variables specified by varArr
      past = execOp(past, op, s);
      // reset after op is used
      op = defOp;
      interOp = false;
    } else {
      // change of class, past is finalized, push to res
      res.push(past);
      // if inter-op (not used), push a clone (prevent overwrite later)
      if (interOp) { res.push(symbol(op.value)) };
      // reset
      op = defOp;
      interOp = false;
      past = s;
    }
  })
  return res;
}

// to be written later
function execOp(L, op, R) {
  // ok def ops between:
  // consider ifelse cond precedence
  // also consider when optional arg
  // 1. <n><n> ~ <n>
  // 2. <n><T>[<op> <n2> !<T>] ~ <n>[<op><n2>]<T> ~ <n><T> ~ <T>
  // 3. <T><T> ~ <T>
  // 4. <T><r><T> ~ <rT>
  // 5. [<f>]<c><T|rT> ~ <cT>
  var otype = opType(L, op, R)
  if (_.includes(['nn'], otype)) {
    return nnOp(L, op, R)
  } else if (_.includes(['nT'], otype)) {
    return nTOp(L, op, R);
  } else if (_.includes(['TT'], otype)) {
    return TTOp(L, op, R);
  } else if (_.includes(['TrT'], otype)) {
    return rTOp(L, R);
  } else if (_.includes(['fcT'], otype)) {
    return cTOp(L, R);
  }

  // console.log('args', L, op, R)
  // console.log("exec", L.value + R.value)
  // return symbol(L.value + R.value)
}

// determine the op type based on arguments
function opType(L, op, R) {
  var LsName = util.sName(L) || '',
    RsName = util.sName(R) || '';
  var opsName = util.sName(op);
  if (opsName != 'r' || opsName != 'c') { opsName = '' };
  return LsName + opsName + RsName
}

// opType(symbol('one'), symbol('plus'), symbol('zero'))
// opType(null, symbol('plus'), symbol('christmas'))

// done.
// production rule #1
function nnOp(L, op, R) {
  var l = L.value,
    r = R.value;
  // set the default op according to value in nn op
  if (l > r) {
    op = op || symbol('plus')
  } else {
    op = op || symbol('times')
  }
  var res = atomicOp(l, op, r);
  return symbol(res)
}

// production rule #2
// algorithm: note that from previous steps no <n>'s can occur adjacently
// 1. scan array L to R, on each <n> found:
// 2.1 if its R is <T>, continue;
// 2.2 else, this is the target. do:
// 3.1 init carry = []. remove and push <n> into carry,
// 3.2 if its L is <op>, remove and prepend <op> into carry,
// 4.1 find the first <n> to the left, if not <n>, drop the carry and continue;
// 4.2 else merge the carry after the <n>
// 5. At the end of loop, rerun production rule #1
function nTnRedistribute(syms) {
  // 1.
  for (var i = 0; i < syms.length; i++) {
    var s = syms[i]
    if (util.sName(s) != 'n') { continue; };
    // 1.

    var R = syms[i+1]
    if (util.sName(R) == 'T') { continue; };
    // 2.2

    // 3.1
    var carry = [];
    carry.push(_.pullAt(syms, i))
    // 3.2
    var L = syms[i-1]
    if (util.sName(L) == 'op') {
      carry.unshift(_.pullAt(syms, i-1))
    };
    carry = _.flatten(carry)

    // 4.1
    var LLi = _.findLastIndex(_.slice(syms, 0, i), function(Ls) {
      return util.sName(Ls) == 'n'
    })
    if (!syms[LLi] || util.sName(syms[LLi+1]) != 'T') { continue; };

    // 4.2
    syms.splice(LLi, 0, carry)
    syms = _.flatten(syms)
  }

  // 5.
  syms = reduce(syms, ['n'])
  return syms;
}

// nTnRedistribute([symbol(1), null, null, symbol(1)])
// console.log(_.range(10)[100])
function cTOp() {}

function rTOp() {}

// done
function nTOp(nL, op, TR) {
  // set the default op
  op = op || symbol('times')
  _.each(TR.t, function(v, k) {
    TR.t[k] = atomicOp(nL.value, op, TR.t[k])
  })
  _.each(TR.dt, function(v, k) {
    TR.dt[k] = atomicOp(nL.value, op, TR.dt[k])
  })
}

// done
// distribute scalar L over tensor R, using atomicOp
// or override tensor L and tensor R, or R preceeds
// doesn't apply to t,dt yet
// return R entity, or ct, rt
function TTOp(TL, op, TR) {
  // set the default op
  op = op || symbol('plus')
  // util.sName
  // mutate into TR
  _.each(TL.t, function(v, k) {
    TR.t[k] = atomicOp(TL.t[k], op, TR.t[k])
  })
  _.each(TL.dt, function(v, k) {
    TR.dt[k] = atomicOp(TL.dt[k], op, TR.dt[k])
  })
  return TR
}

//q2 running atomic binary op, between numbers
// either side can be starting with '=', or null, then just drop em
function atomicOp(Lval, op, Rval) {
  var l = parseFloat(Lval),
    r = parseFloat(Rval),
    oName = op.value;
  if (Lval == undefined) {
    // if L is missing, R must exist tho
    return Rval
  } else if (Rval == undefined) {
    // if L exists, be it def or not, R missing
    return (oName == 'minus') ? Lval.replace(/(\d)/, '-$1') : Lval;
  } else {
    // or R exist or is default (parse to NaN), L can be default too but ignore then
    var def = _.isNaN(r) ? '=' : '';
    r = _.isNaN(r) ? parseFloat(Rval.replace('=', '')) : r;
    if (_.isNaN(l)) {
      // if L is default, just return R
      return Rval;
    } else if (oName == 'minus') {
      return def + (r - l)
    } else if (oName == 'plus') {
      return def + (r + l)
    } else if (oName == 'times') {
      return def + (r * l)
    } else if (oName == 'divide') {
      return def + (r / l)
    }
  }
}

// var str = "05 October 2011 14:48 UTC 08/11 2020 2012/12 event is at tonight 12/20- 23 12/22 - 12/23 12/22 - 12/25 05:30h 17:30 1730 1730pm 5pm 1 st"
var str = "half an hour and quarter from 7pm"
var tok = tokenize(str)
var syms = tok.symbols;
console.log(syms)

// syms = reduce(syms, ['n'])
// console.log('p#1', syms)
// // exp
// syms.push(symbol('two'))
// console.log('modify syms', syms)
// syms = nTnRedistribute(syms)
// console.log('p#2', syms)

// var t1 = symbol('tonight')
// var t2 = symbol('christmas')
// console.log(t1)
// console.log(t2)
// TTOp(t1, symbol('plus'), t2)
// console.log("post op")
// console.log(t1)
// console.log(t2)
// console.log("postNTOp")
// nTOp(symbol('two'), symbol('times'), t2)
// console.log(t2)
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012-2015 S-Core Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * webida - project run management
 *
 * Src:
 *   plugins/webida.ide.project-management.run/plugin.js
 */
define([
    './run-configuration-manager',
    './delegator',
    'webida-lib/plugins/workspace/plugin',
    'webida-lib/plugins/workbench/plugin',
    'webida-lib/util/path',
    'other-lib/underscore/lodash.min',
    'other-lib/toastr/toastr'
], function (runConfigurationManager, delegator, workspace, workbench, pathUtil, _, toastr) {
    'use strict';

    var module = {};
    var contextMenuItems = [];

    var workbenchWholeItems = {
        '&Run': [
            'cmnd',
            'plugins/webida.ide.project-management.run/plugin',
            'workbenchRunBinded'
        ],
        'Run &with': [
            'enum',
            'plugins/webida.ide.project-management.run/plugin',
            'workbenchRunListBinded'
        ]
    };

    var workspaceWholeItems = {
        '&Run': [
            'cmnd',
            'plugins/webida.ide.project-management.run/plugin',
            'workspaceRunBinded'
        ],
        'Run &with': [
            'enum',
            'plugins/webida.ide.project-management.run/plugin',
            'workspaceRunListBinded'
        ]
    };

    function _parseProjectNameFromPath(path) {
        if (!path) {
            return '';
        }
        var splitPath = path.split('/');
        return (splitPath.length < 3) ? '' : splitPath[2];
    }

    module.getViableItemsForWorkbench = function () {
        contextMenuItems = [];

        var items = {};
        var contextPaths = [];
        var context = workbench.getContext();
        var contextProjectName = '';
        if (context && context.paths) {
            contextPaths = context.paths;
            if (contextPaths.length === 1) {
                var bRunnable = isRunnablePath(contextPaths[0]);

                if (bRunnable === true) {
                    items['&Run'] = workbenchWholeItems['&Run'];
                }
                contextProjectName = _parseProjectNameFromPath(contextPaths[0]);
            }
        }

        var allRunConfigurations = _.toArray(runConfigurationManager.getAll());
        if(!_.isEmpty(allRunConfigurations)){
            allRunConfigurations.sort(function(a, b){
                if(a.project === b.project){
                    if(a.latestRun){
                        return -1;
                    } else if (b.latestRun){
                        return 1;
                    } else {
                        if (a.name > b.name) {
                            return 1;
                        } else {
                            return -1;
                        }
                    }
                } else {
                    if (a.project === contextProjectName) {
                        return -1;
                    }
                    if (b.project === contextProjectName) {
                        return 1;
                    }
                }
            });
        }

        _.each(allRunConfigurations, function(run){
            var menuName = run.project + ' : ' + run.name + ((run.latestRun) ? ' [latest run]' : '');
            contextMenuItems.push(menuName);
        });
        if(!_.isEmpty(allRunConfigurations)) {
            contextMenuItems.push('---');
        }
        contextMenuItems.push('Run configurations');

        items['Run &with'] = workbenchWholeItems['Run &with'];
        items['Run &with'][3] = contextMenuItems;

        return items;
    };

    module.getViableItemsForWorkspaceView = function () {
        contextMenuItems = [];
        var items = {};

        var selectedPaths = workspace.getSelectedPaths();

        if (!selectedPaths || selectedPaths.length !== 1) {
            return null;
        }

        var selectedPath = selectedPaths[0];

        if (!selectedPath) {
            return items;
        }

        if (isRunnablePath(selectedPath) !== true) {
            return items;
        }

        if (!selectedPath) {
            return items;
        }

        var projectName = _parseProjectNameFromPath(selectedPath);

        if (!projectName) {
            return items;
        }

        var runConfigurations = runConfigurationManager.getByProjectName(projectName);

        var disableList = [];

        _.each(runConfigurations, function(runConf){
            if(runConf.latestRun){
                contextMenuItems.unshift(runConf.project + ' : ' + runConf.name + ' [latest run]');
            } else {
                contextMenuItems.push(runConf.project + ' : ' + runConf.name);
            }
        });
        if (_.isEmpty(contextMenuItems)) {
            contextMenuItems.push('No project index');
            disableList.push(0);
        }

        contextMenuItems.push('---');
        contextMenuItems.push('Run configurations');

        items['&Run'] = workspaceWholeItems['&Run'];
        items['Run &with'] = workspaceWholeItems['Run &with'];
        items['Run &with'][3] = contextMenuItems;
        items['Run &with'][4] = disableList;

        return items;
    };

    function _getContextItem(index) {
        if (!contextMenuItems || contextMenuItems.length <= index) {
            return null;
        }
        return contextMenuItems[index];
    }

    function openRunConfigurationDialog(defaultRun){
        require(['plugins/webida.ide.project-management.run/view-controller'], function(viewController){
            viewController.openWindow(defaultRun);
        });
    }

    function refreshRunConfigurationTree(){
        require(['plugins/webida.ide.project-management.run/view-controller'], function(viewController){
            viewController.refreshTree();
        });
    }

    function _runBinded(runConf/*, mode*/) {
        if (!runConf) {
            toastr.info('Cannot find a run configuration. Add a new one.');
            openRunConfigurationDialog();
        }
        delegator.run(runConf);
    }

    module.workspaceRunBinded = function () {
        var selectedPaths = workspace.getSelectedPaths();
        if (!selectedPaths || selectedPaths.length !== 1) {
            return null;
        }

        var selectedPath = selectedPaths[0];
        if (!selectedPath) {
            return;
        }
        var nodeSplit = selectedPath.split('/');
        var projectName = nodeSplit[2];
        var runConfigurations = runConfigurationManager.getByProjectName(projectName);
        if (_.isEmpty(runConfigurations)) {
            openRunConfigurationDialog();
        } else {
            var latestRuns = _.where(runConfigurations, {latestRun: true});
            _runBinded(_.isEmpty(latestRuns) ? runConfigurations[0] : latestRuns[0]);
        }
    };

    module.workbenchDebugBinded = function () { //FIXME remove
        this._workbenchRunBinded(runConfigurationManager.DEBUG_MODE);
    };

    module.workbenchRunBinded = function () {   // FIXME remove
        this._workbenchRunBinded(runConfigurationManager.RUN_MODE);
    };

    module._workbenchRunBinded = function (/*mode*/) {
        var context = workbench.getContext();
        var contextPaths;

        if (context && context.paths) {
            contextPaths = context.paths;
            if (contextPaths.length === 1) {
                var bRunnable = isRunnablePath(contextPaths[0]);
                if (bRunnable !== true) {
                    return;
                }
            } else {
                return;
            }
        }

        if (!contextPaths) {
            console.error('No valid context path');
            return;
        }
        var contextPath = contextPaths[0];
        if (contextPath === workspace.getRootPath()) {
            toastr.warning('Cannot run workspace directory');
        }

        var projectName = parseProjectNameFromPath(contextPath);
        var runConfigurations = runConfigurationManager.getByProjectName(projectName);
        if (_.isEmpty(runConfigurations)) {
            openRunConfigurationDialog();
        } else {
            var latestRuns = _.where(runConfigurations, {latestRun: true});
            _runBinded(_.isEmpty(latestRuns) ? runConfigurations[0] : latestRuns[0]);
        }
    };

    function _runListBinded(index) {
        var runString = _getContextItem(index);
        if (!runString) {
            return null;
        }

        if (runString.trim() === 'Run configurations') {
            openRunConfigurationDialog();
        } else {
            var runStirngSplit = runString.split(' : ');
            var runConfName = runStirngSplit[1];

            var runConfNameSplit = runConfName.split(' [');
            var name = runConfNameSplit[0];
            var runConf = runConfigurationManager.getByName(name);
            delegator.run(runConf/*, runConfigurationManager.RUN_MODE*/ );
        }
    }

    function isRunnableProjectPath(projectLevelPath) {
        if (!projectLevelPath || !pathUtil.isDirPath(projectLevelPath)) {
            return false;
        }

        var projectName = pathUtil.getName(projectLevelPath);
        //if (!projectName || projectName[0] === '.') {
        //    return false;
        //}
        //
        //return true;

        return projectName && projectName.charAt(0) !== '.';
    }

    function isRunnablePath(path) {
        var projectPath = pathUtil.getProjectRootPath(path);
        return isRunnableProjectPath(projectPath);
    }

    module.workspaceRunListBinded = function (index) {
        _runListBinded(index);
    };

    module.workbenchRunListBinded = function (index) {
        _runListBinded(index);
    };

    module.runObjectChanged = function(action, runConf) {
        console.log('webida.ide.project-management.run:configuration.changed', action, runConf);
        if(action === 'save'){
            delegator.saveConf(runConf, function(err){
                if(!err){
                    refreshRunConfigurationTree();
                }
            });
            //runConfigurationManager.save(runConf);
            //refreshRunConfigurationTree();
        }
    };

    function parseProjectNameFromPath(path) {
        if (!path) {
            return '';
        }

        var splitPath = path.split('/');
        if (!splitPath || splitPath.length < 3) {
            return '';
        }

        return splitPath[2];
    }
    return module;

});
<commit_msg>[BUGFIX] fix the word [DESC] 'Run configurations' to 'Run Configurations'<commit_after>/*
 * Copyright (c) 2012-2015 S-Core Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * webida - project run management
 *
 * Src:
 *   plugins/webida.ide.project-management.run/plugin.js
 */
define([
    './run-configuration-manager',
    './delegator',
    'webida-lib/plugins/workspace/plugin',
    'webida-lib/plugins/workbench/plugin',
    'webida-lib/util/path',
    'other-lib/underscore/lodash.min',
    'other-lib/toastr/toastr'
], function (runConfigurationManager, delegator, workspace, workbench, pathUtil, _, toastr) {
    'use strict';

    var module = {};
    var contextMenuItems = [];

    var workbenchWholeItems = {
        '&Run': [
            'cmnd',
            'plugins/webida.ide.project-management.run/plugin',
            'workbenchRunBinded'
        ],
        'Run &with': [
            'enum',
            'plugins/webida.ide.project-management.run/plugin',
            'workbenchRunListBinded'
        ]
    };

    var workspaceWholeItems = {
        '&Run': [
            'cmnd',
            'plugins/webida.ide.project-management.run/plugin',
            'workspaceRunBinded'
        ],
        'Run &with': [
            'enum',
            'plugins/webida.ide.project-management.run/plugin',
            'workspaceRunListBinded'
        ]
    };

    function _parseProjectNameFromPath(path) {
        if (!path) {
            return '';
        }
        var splitPath = path.split('/');
        return (splitPath.length < 3) ? '' : splitPath[2];
    }

    module.getViableItemsForWorkbench = function () {
        contextMenuItems = [];

        var items = {};
        var contextPaths = [];
        var context = workbench.getContext();
        var contextProjectName = '';
        if (context && context.paths) {
            contextPaths = context.paths;
            if (contextPaths.length === 1) {
                var bRunnable = isRunnablePath(contextPaths[0]);

                if (bRunnable === true) {
                    items['&Run'] = workbenchWholeItems['&Run'];
                }
                contextProjectName = _parseProjectNameFromPath(contextPaths[0]);
            }
        }

        var allRunConfigurations = _.toArray(runConfigurationManager.getAll());
        if(!_.isEmpty(allRunConfigurations)){
            allRunConfigurations.sort(function(a, b){
                if(a.project === b.project){
                    if(a.latestRun){
                        return -1;
                    } else if (b.latestRun){
                        return 1;
                    } else {
                        if (a.name > b.name) {
                            return 1;
                        } else {
                            return -1;
                        }
                    }
                } else {
                    if (a.project === contextProjectName) {
                        return -1;
                    }
                    if (b.project === contextProjectName) {
                        return 1;
                    }
                }
            });
        }

        _.each(allRunConfigurations, function(run){
            var menuName = run.project + ' : ' + run.name + ((run.latestRun) ? ' [latest run]' : '');
            contextMenuItems.push(menuName);
        });
        if(!_.isEmpty(allRunConfigurations)) {
            contextMenuItems.push('---');
        }
        contextMenuItems.push('Run Configurations');

        items['Run &with'] = workbenchWholeItems['Run &with'];
        items['Run &with'][3] = contextMenuItems;

        return items;
    };

    module.getViableItemsForWorkspaceView = function () {
        contextMenuItems = [];
        var items = {};

        var selectedPaths = workspace.getSelectedPaths();

        if (!selectedPaths || selectedPaths.length !== 1) {
            return null;
        }

        var selectedPath = selectedPaths[0];

        if (!selectedPath) {
            return items;
        }

        if (isRunnablePath(selectedPath) !== true) {
            return items;
        }

        if (!selectedPath) {
            return items;
        }

        var projectName = _parseProjectNameFromPath(selectedPath);

        if (!projectName) {
            return items;
        }

        var runConfigurations = runConfigurationManager.getByProjectName(projectName);

        var disableList = [];

        _.each(runConfigurations, function(runConf){
            if(runConf.latestRun){
                contextMenuItems.unshift(runConf.project + ' : ' + runConf.name + ' [latest run]');
            } else {
                contextMenuItems.push(runConf.project + ' : ' + runConf.name);
            }
        });
        if (_.isEmpty(contextMenuItems)) {
            contextMenuItems.push('No project index');
            disableList.push(0);
        }

        contextMenuItems.push('---');
        contextMenuItems.push('Run Configurations');

        items['&Run'] = workspaceWholeItems['&Run'];
        items['Run &with'] = workspaceWholeItems['Run &with'];
        items['Run &with'][3] = contextMenuItems;
        items['Run &with'][4] = disableList;

        return items;
    };

    function _getContextItem(index) {
        if (!contextMenuItems || contextMenuItems.length <= index) {
            return null;
        }
        return contextMenuItems[index];
    }

    function openRunConfigurationDialog(defaultRun){
        require(['plugins/webida.ide.project-management.run/view-controller'], function(viewController){
            viewController.openWindow(defaultRun);
        });
    }

    function refreshRunConfigurationTree(){
        require(['plugins/webida.ide.project-management.run/view-controller'], function(viewController){
            viewController.refreshTree();
        });
    }

    function _runBinded(runConf/*, mode*/) {
        if (!runConf) {
            toastr.info('Cannot find a run configuration. Add a new one.');
            openRunConfigurationDialog();
        }
        delegator.run(runConf);
    }

    module.workspaceRunBinded = function () {
        var selectedPaths = workspace.getSelectedPaths();
        if (!selectedPaths || selectedPaths.length !== 1) {
            return null;
        }

        var selectedPath = selectedPaths[0];
        if (!selectedPath) {
            return;
        }
        var nodeSplit = selectedPath.split('/');
        var projectName = nodeSplit[2];
        var runConfigurations = runConfigurationManager.getByProjectName(projectName);
        if (_.isEmpty(runConfigurations)) {
            openRunConfigurationDialog();
        } else {
            var latestRuns = _.where(runConfigurations, {latestRun: true});
            _runBinded(_.isEmpty(latestRuns) ? runConfigurations[0] : latestRuns[0]);
        }
    };

    module.workbenchDebugBinded = function () { //FIXME remove
        this._workbenchRunBinded(runConfigurationManager.DEBUG_MODE);
    };

    module.workbenchRunBinded = function () {   // FIXME remove
        this._workbenchRunBinded(runConfigurationManager.RUN_MODE);
    };

    module._workbenchRunBinded = function (/*mode*/) {
        var context = workbench.getContext();
        var contextPaths;

        if (context && context.paths) {
            contextPaths = context.paths;
            if (contextPaths.length === 1) {
                var bRunnable = isRunnablePath(contextPaths[0]);
                if (bRunnable !== true) {
                    return;
                }
            } else {
                return;
            }
        }

        if (!contextPaths) {
            console.error('No valid context path');
            return;
        }
        var contextPath = contextPaths[0];
        if (contextPath === workspace.getRootPath()) {
            toastr.warning('Cannot run workspace directory');
        }

        var projectName = parseProjectNameFromPath(contextPath);
        var runConfigurations = runConfigurationManager.getByProjectName(projectName);
        if (_.isEmpty(runConfigurations)) {
            openRunConfigurationDialog();
        } else {
            var latestRuns = _.where(runConfigurations, {latestRun: true});
            _runBinded(_.isEmpty(latestRuns) ? runConfigurations[0] : latestRuns[0]);
        }
    };

    function _runListBinded(index) {
        var runString = _getContextItem(index);
        if (!runString) {
            return null;
        }

        if (runString.trim() === 'Run Configurations') {
            openRunConfigurationDialog();
        } else {
            var runStirngSplit = runString.split(' : ');
            var runConfName = runStirngSplit[1];

            var runConfNameSplit = runConfName.split(' [');
            var name = runConfNameSplit[0];
            var runConf = runConfigurationManager.getByName(name);
            delegator.run(runConf/*, runConfigurationManager.RUN_MODE*/ );
        }
    }

    function isRunnableProjectPath(projectLevelPath) {
        if (!projectLevelPath || !pathUtil.isDirPath(projectLevelPath)) {
            return false;
        }

        var projectName = pathUtil.getName(projectLevelPath);
        //if (!projectName || projectName[0] === '.') {
        //    return false;
        //}
        //
        //return true;

        return projectName && projectName.charAt(0) !== '.';
    }

    function isRunnablePath(path) {
        var projectPath = pathUtil.getProjectRootPath(path);
        return isRunnableProjectPath(projectPath);
    }

    module.workspaceRunListBinded = function (index) {
        _runListBinded(index);
    };

    module.workbenchRunListBinded = function (index) {
        _runListBinded(index);
    };

    module.runObjectChanged = function(action, runConf) {
        console.log('webida.ide.project-management.run:configuration.changed', action, runConf);
        if(action === 'save'){
            delegator.saveConf(runConf, function(err){
                if(!err){
                    refreshRunConfigurationTree();
                }
            });
            //runConfigurationManager.save(runConf);
            //refreshRunConfigurationTree();
        }
    };

    function parseProjectNameFromPath(path) {
        if (!path) {
            return '';
        }

        var splitPath = path.split('/');
        if (!splitPath || splitPath.length < 3) {
            return '';
        }

        return splitPath[2];
    }
    return module;

});
<|endoftext|>


<commit_before>// converts the node style specifics to es6 style (this is only
// used to process the documentation)
const requiredToken = '__import_module__';
exports.onHandleCode = (ev) => {
  ev.data.code = ev.data.code
    .replace(/module\.exports = /g, 'export default ')
    .replace(/const (.*)require\((.*)\)/g, `const ${requiredToken}$1require($2)`)
    .replace(/\\\n../g, '');
};

// Customize HTML texting/formating
exports.onHandleHTML = (ev) => {
  ev.data.html = ev.data.html
  .replace('', '')
  .replace('>Repository', '>Mebo GitHub')
  .replace(/#http#:\//g, `http:/`)
  .replace(new RegExp('https://mebohq.github.io/docs/data/', 'g'), 'data/')
  .replace('Mebo API Document', 'Mebo')
  .replace('', '

')
  .replace('', '

')
  .replace('', '')
  .replace('Reference', '')
  .replace('data-ice="manualHeaderLink">Manual', 'data-ice="manualHeaderLink">Intro')
  .replace('./manual/index.html', './manual/overview/INTRODUCTION.html')
  .replace('"data/manual/INTRODUCTION.md"', '"manual/overview/INTRODUCTION.html"')
  .replace(new RegExp(requiredToken, 'g'), '')
  .replace(new RegExp('::none::', 'g'), '')
  .replace(new RegExp('::null::', 'g'), '')
  .replace(new RegExp('::true::', 'g'), '')
  .replace(new RegExp('::false::', 'g'), '')
  .replace(new RegExp('::auto::', 'g'), '')
  .replace(new RegExp('::on::', 'g'), '')
  .replace(new RegExp('::off::', 'g'), '')

  // adding the star button to the README displayed in the index page
  if (ev.data.html.indexOf(' alt="Esdocs">' !== -1)){
    ev.data.html = ev.data.html
    .replace('', '<link rel="icon" type="image/png" sizes="64x64" href="data/icon.png">')
    .replace(' alt="Esdocs">', ' alt=Esdocs"> Star');
  }

  // replacing the domain that is hard coded in the INTRODUCTION to the relative doc location
  if (ev.data.html.indexOf('
') !== -1){
    ev.data.html = ev.data.html
    .replace(new RegExp('https://mebohq.github.io/docs/', 'g'), '');
    ev.data.html = ev.data.html.replace('indent-h1 manual-color manual-color-reference', 'indent-h1');
  }

  // removing the public column from the class summary
  if (ev.data.html.indexOf('<title data-ice="title">Index | Mebo</title>') !== -1){
    ev.data.html = ev.data.html
    .replace(new RegExp('\n      public', 'g'), '')
    .replace(new RegExp('Static Public Class Summary	', 'g'), '');
  }
};
<commit_msg>workaround to fix a issue with images not being loaded due to github's internal cache<commit_after>// converts the node style specifics to es6 style (this is only
// used to process the documentation)
const requiredToken = '__import_module__';
exports.onHandleCode = (ev) => {
  ev.data.code = ev.data.code
    .replace(/module\.exports = /g, 'export default ')
    .replace(/const (.*)require\((.*)\)/g, `const ${requiredToken}$1require($2)`)
    .replace(/\\\n../g, '');
};

// Customize HTML texting/formating
exports.onHandleHTML = (ev) => {
  ev.data.html = ev.data.html
  .replace('', '')
  .replace('>Repository', '>Mebo GitHub')
  .replace(/#http#:\//g, `http:/`)
  .replace(new RegExp('https://mebohq.github.io/docs/data/', 'g'), 'data/')
  .replace('Mebo API Document', 'Mebo')
  .replace('', '

')
  .replace('', '

')
  .replace('', '')
  .replace('Reference', '')
  .replace('data-ice="manualHeaderLink">Manual', 'data-ice="manualHeaderLink">Intro')
  .replace('./manual/index.html', './manual/overview/INTRODUCTION.html')
  .replace('"data/manual/INTRODUCTION.md"', '"manual/overview/INTRODUCTION.html"')
  .replace(new RegExp(requiredToken, 'g'), '')
  .replace(new RegExp('::none::', 'g'), '')
  .replace(new RegExp('::null::', 'g'), '')
  .replace(new RegExp('::true::', 'g'), '')
  .replace(new RegExp('::false::', 'g'), '')
  .replace(new RegExp('::auto::', 'g'), '')
  .replace(new RegExp('::on::', 'g'), '')
  .replace(new RegExp('::off::', 'g'), '')

  // adding the star button to the README displayed in the index page
  if (ev.data.html.indexOf(' alt="Esdocs">' !== -1)){
    ev.data.html = ev.data.html
    .replace('', '<link rel="icon" type="image/png" sizes="64x64" href="data/icon.png?v=1">')
    .replace(' alt="Esdocs">', ' alt=Esdocs"> Star');
  }

  // replacing the domain that is hard coded in the INTRODUCTION to the relative doc location
  if (ev.data.html.indexOf('
') !== -1){
    ev.data.html = ev.data.html
    .replace(new RegExp('https://mebohq.github.io/docs/', 'g'), '');
    ev.data.html = ev.data.html.replace('indent-h1 manual-color manual-color-reference', 'indent-h1');
  }

  // removing the public column from the class summary
  if (ev.data.html.indexOf('<title data-ice="title">Index | Mebo</title>') !== -1){
    ev.data.html = ev.data.html
    .replace(new RegExp('\n      public', 'g'), '')
    .replace(new RegExp('Static Public Class Summary	', 'g'), '');
  }
};
<|endoftext|>