<commit_before>
/*
#     CloudBoost - Core Engine that powers Bakend as a Service
#     (c) 2014 HackerBay, Inc.
#     CloudBoost may be freely distributed under the Apache 2 License
*/

var customHelper = require('../../helpers/custom.js');

module.exports = function() {

    global.app.put('/data/:appId/:tableName', function (req, res) { //save a new document into <tableName> of app
        if(req.body && req.body.method=="DELETE"){
            /******************DELETE API*********************/
            _deleteApi(req, res);
            /******************DELETE API*********************/
        }else{
            /******************SAVE API*********************/
            console.log("SAVE API");
            var appId = req.params.appId;
            var document = req.body.document;
            var collectionName = req.params.tableName;
            var appKey = req.body.key || req.params.key;
            var sdk = req.body.sdk || "REST";

            global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
                return global.customService.save(appId, collectionName, document, customHelper.getAccessList(req), isMasterKey);
            }).then(function (result) {
                console.log('+++ Save Success +++');
                console.log(result);
                res.status(200).send(result);
            }, function (error) {
                console.log('++++++ Save Error +++++++');
                console.log(error);
                res.status(400).send(error);
            });

            global.apiTracker.log(appId,"Object / Save", req.url,sdk);
            /******************SAVE API*********************/
        }
    });

    global.app.get('/data/:appId/:tableName/find', _getData);
    global.app.post('/data/:appId/:tableName/find', _getData);

    global.app.get('/data/:appId/:tableName/count', _count);
    global.app.post('/data/:appId/:tableName/count', _count);

    global.app.get('/data/:appId/:tableName/distinct', _distinct);
    global.app.post('/data/:appId/:tableName/distinct', _distinct);

    global.app.get('/data/:appId/:tableName/findOne', _findOne);
    global.app.post('/data/:appId/:tableName/findOne', _findOne);

	global.app.delete('/data/:appId/:tableName', _deleteApi);

    function _deleteApi(req, res) { //delete a document matching the <objectId>
        console.log("DELETE API");
        var appId = req.params.appId;
        var collectionName = req.params.tableName;
        var document = req.body.document;
        var appKey = req.body.key || req.param('key');
        var sdk = req.body.sdk || "REST";

        global.appService.isMasterKey(appId,appKey).then(function(isMasterKey){
            return global.customService.delete(appId, collectionName, document, customHelper.getAccessList(req),isMasterKey);
        }).then(function(result) {
            res.json(result);
        }, function(error) {
            res.status(400).send(error);
        });

        global.apiTracker.log(appId,"Object / Delete", req.url,sdk);

    }

};

function _getData(req, res) { //get document(s) object based on query and various parameters
    console.log("FIND API");
    var appId = req.params.appId;
    var collectionName = req.params.tableName;
    var query = req.body.query;
    var select = req.body.select;
    var sort = req.body.sort;
    var limit = req.body.limit;
    var skip = req.body.skip;
    var appKey = req.body.key || req.param('key');
    var sdk = req.body.sdk || "REST";

    global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
        return global.customService.find(appId, collectionName, query, select, sort, limit, skip, customHelper.getAccessList(req), isMasterKey);
    }).then(function (results) {
        res.json(results);
    }, function (error) {
        res.status(400).send(error);
    });

    global.apiTracker.log(appId,"Object / Find", req.url,sdk);
}

function _count(req, res) { //get document(s) object based on query and various parameters
    console.log("COUNT API");
    var appId = req.params.appId;
    var collectionName = req.params.tableName;
    var query = req.body.query;
    var limit = req.body.limit;
    var skip = req.body.skip;
    var appKey = req.body.key || req.param('key');
    var sdk = req.body.sdk || "REST";

    global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
        return global.customService.count(appId, collectionName, query, limit, skip, customHelper.getAccessList(req), isMasterKey);
    }).then(function (result) {
        res.json(result);
    }, function (error) {
        res.status(400).send(error);
    });

    global.apiTracker.log(appId,"Object / Count", req.url,sdk);
}

function _distinct(req, res, next) { //get document(s) object based on query and various parameters
    console.log("DISTINCT API");
    var appId = req.params.appId;
    var collectionName = req.params.tableName;
    var onKey = req.body.onKey;
    var query = req.body.query;
    var select = req.body.select;
    var sort = req.body.sort;
    var limit = req.body.limit;
    var skip = req.body.skip;
    var appKey = req.body.key || req.param('key');
    var sdk = req.body.sdk || "REST";

    global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
        return global.customService.distinct(appId, collectionName, onKey, query, select, sort, limit, skip, customHelper.getAccessList(req), isMasterKey);
    }).then(function (results) {
        res.json(results);
    }, function (error) {
        res.status(400).send(error);
    });

    global.apiTracker.log(appId,"Object / Distinct", req.url,sdk);
}

function _findOne(req, res) { //get a single document matching the search query
    console.log("FIND ONE API");
    var appId = req.params.appId;
    var collectionName = req.params.tableName;
    var query = req.body.query;
    var select = req.body.select;
    var sort = req.body.sort;
    var skip = req.body.skip;
    var appKey = req.body.key || req.param('key');
    var sdk = req.body.sdk || "REST";

    global.appService.isMasterKey(appId, appKey).then(function (isMasterKey) {
        return global.customService.findOne(appId, collectionName, query, select, sort, skip, customHelper.getAccessList(req), isMasterKey);
    }).then(function (result) {
        res.json(result);
    }, function (error) {
        res.status(400).send(error);
    });

    global.apiTracker.log(appId,"Object / FindOne", req.url,sdk);
}
<commit_msg>query.find fix<commit_after>/*
#     CloudBoost - Core Engine that powers Bakend as a Service
#     (c) 2014 HackerBay, Inc.
#     CloudBoost may be freely distributed under the Apache 2 License
*/

var customHelper = require('../../helpers/custom.js');

module.exports = function() {

    global.app.put('/data/:appId/:tableName', function(req, res) { //save a new document into <tableName> of app
        if (req.body && req.body.method == "DELETE") {
            /******************DELETE API*********************/
            _deleteApi(req, res);
            /******************DELETE API*********************/
        } else {
            /******************SAVE API*********************/
            console.log("SAVE API");
            var appId = req.params.appId;
            var document = req.body.document;
            var collectionName = req.params.tableName;
            var appKey = req.body.key || req.params.key;
            var sdk = req.body.sdk || "REST";

            global.appService.isMasterKey(appId, appKey).then(function(isMasterKey) {
                return global.customService.save(appId, collectionName, document, customHelper.getAccessList(req), isMasterKey);
            }).then(function(result) {
                console.log('+++ Save Success +++');
                console.log(result);
                res.status(200).send(result);
            }, function(error) {
                console.log('++++++ Save Error +++++++');
                console.log(error);
                res.status(400).send(error);
            });

            global.apiTracker.log(appId, "Object / Save", req.url, sdk);
            /******************SAVE API*********************/
        }
    });

    global.app.get('/data/:appId/:tableName/find', _getData);
    global.app.post('/data/:appId/:tableName/find', _getData);

    global.app.get('/data/:appId/:tableName/count', _count);
    global.app.post('/data/:appId/:tableName/count', _count);

    global.app.get('/data/:appId/:tableName/distinct', _distinct);
    global.app.post('/data/:appId/:tableName/distinct', _distinct);

    global.app.get('/data/:appId/:tableName/findOne', _findOne);
    global.app.post('/data/:appId/:tableName/findOne', _findOne);

    global.app.delete('/data/:appId/:tableName', _deleteApi);

    function _deleteApi(req, res) { //delete a document matching the <objectId>
        console.log("DELETE API");
        var appId = req.params.appId;
        var collectionName = req.params.tableName;
        var document = req.body.document;
        var appKey = req.body.key || req.param('key');
        var sdk = req.body.sdk || "REST";

        global.appService.isMasterKey(appId, appKey).then(function(isMasterKey) {
            return global.customService.delete(appId, collectionName, document, customHelper.getAccessList(req), isMasterKey);
        }).then(function(result) {
            res.json(result);
        }, function(error) {
            res.status(400).send(error);
        });

        global.apiTracker.log(appId, "Object / Delete", req.url, sdk);

    }

};

function _getData(req, res) { //get document(s) object based on query and various parameters
    console.log("FIND API");
    var appId = req.params.appId;
    var collectionName = req.params.tableName;
    var query = req.body.query;
    var select = req.body.select;
    var sort = req.body.sort;
    var limit = req.body.limit;
    var skip = req.body.skip;
    var appKey = req.body.key || req.param('key');
    var sdk = req.body.sdk || "REST";

    //default sort added
    if (Object.keys(sort).length === 0 && sort.constructor === Object)
        sort = {
            createdAt: 1
        }

    global.appService.isMasterKey(appId, appKey).then(function(isMasterKey) {
        return global.customService.find(appId, collectionName, query, select, sort, limit, skip, customHelper.getAccessList(req), isMasterKey);
    }).then(function(results) {
        res.json(results);
    }, function(error) {
        res.status(400).send(error);
    });

    global.apiTracker.log(appId, "Object / Find", req.url, sdk);
}

function _count(req, res) { //get document(s) object based on query and various parameters
    console.log("COUNT API");
    var appId = req.params.appId;
    var collectionName = req.params.tableName;
    var query = req.body.query;
    var limit = req.body.limit;
    var skip = req.body.skip;
    var appKey = req.body.key || req.param('key');
    var sdk = req.body.sdk || "REST";

    global.appService.isMasterKey(appId, appKey).then(function(isMasterKey) {
        return global.customService.count(appId, collectionName, query, limit, skip, customHelper.getAccessList(req), isMasterKey);
    }).then(function(result) {
        res.json(result);
    }, function(error) {
        res.status(400).send(error);
    });

    global.apiTracker.log(appId, "Object / Count", req.url, sdk);
}

function _distinct(req, res, next) { //get document(s) object based on query and various parameters
    console.log("DISTINCT API");
    var appId = req.params.appId;
    var collectionName = req.params.tableName;
    var onKey = req.body.onKey;
    var query = req.body.query;
    var select = req.body.select;
    var sort = req.body.sort;
    var limit = req.body.limit;
    var skip = req.body.skip;
    var appKey = req.body.key || req.param('key');
    var sdk = req.body.sdk || "REST";

    global.appService.isMasterKey(appId, appKey).then(function(isMasterKey) {
        return global.customService.distinct(appId, collectionName, onKey, query, select, sort, limit, skip, customHelper.getAccessList(req), isMasterKey);
    }).then(function(results) {
        res.json(results);
    }, function(error) {
        res.status(400).send(error);
    });

    global.apiTracker.log(appId, "Object / Distinct", req.url, sdk);
}

function _findOne(req, res) { //get a single document matching the search query
    console.log("FIND ONE API");
    var appId = req.params.appId;
    var collectionName = req.params.tableName;
    var query = req.body.query;
    var select = req.body.select;
    var sort = req.body.sort;
    var skip = req.body.skip;
    var appKey = req.body.key || req.param('key');
    var sdk = req.body.sdk || "REST";

    global.appService.isMasterKey(appId, appKey).then(function(isMasterKey) {
        return global.customService.findOne(appId, collectionName, query, select, sort, skip, customHelper.getAccessList(req), isMasterKey);
    }).then(function(result) {
        res.json(result);
    }, function(error) {
        res.status(400).send(error);
    });

    global.apiTracker.log(appId, "Object / FindOne", req.url, sdk);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

(function() {
"use strict";

var DEBUG_ENABLED = false;
var MATCH_HIGHLIGHT_ACTIVE = "#f19750";
var MATCH_HIGHLIGHT_INACTIVE = "#ffde49";
var SCROLL_INTERVAL_INCREMENT = 5;
var SCROLL_INTERVAL_DURATION = 400;

var activeHighlightSpan = null;
var lastSearch;
var scrollInterval;
var activeIndex = 0;
var highlightSpans = [];

function debug(str) {
  if (DEBUG_ENABLED) {
    console.log("FindInPage: " + str);
  }
}

function isElementVisible(elem) {
  return getComputedStyle(elem).visibility !== "hidden";
}

function isRectInViewport(rect) {
  var left = rect.left + document.body.scrollLeft;
  var right = rect.right + document.body.scrollLeft;
  var top = rect.top + document.body.scrollTop;
  var bottom = rect.bottom + document.body.scrollTop;

  return rect.width > 0 &&
         rect.height > 0 &&
         right >= 0 &&
         bottom >= 0 &&
         left <= document.body.scrollWidth &&
         top <= document.body.scrollHeight;
}

function findMatches(text) {
  // For case-insensitive matching.
  var lowerText = text.toLocaleLowerCase();
  var upperText = text.toLocaleUpperCase();

  var matches = [];
  var range = document.createRange();
  var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
  var textLength = text.length;
  var node;
  while (node = walker.nextNode()) {
    var textContent = node.textContent;
    findString: for (var i = 0; i < textContent.length - textLength + 1; ++i) {
      for (var j = 0; j < textLength; ++j) {
        var nextChar = textContent[i + j];
        if (lowerText[j] !== nextChar && upperText[j] !== nextChar) {
          continue findString;
        }
      }

      // This node is a TextNode, not an Element. Its parent is the nearest Element.
      var element = node.parentNode;

      // Find the rect of just the text for this match.
      range.setStart(node, i);
      range.setEnd(node, i + textLength);
      var textRect = range.getBoundingClientRect();

      // We have a match, but we need to make sure it's visible. The condition
      // below checks the following cases:
      // * If this element or any of its parents has style visibility hidden.
      //   The visibility style is inherited, so we need to check only this
      //   element and not all of its ancestors.
      // * If the highlight will be outside of the page's bounds. We determine
      //   this by comparing the bounds of the text rect.
      // * If the element style display is set to none. display:none collapses
      //   the element's space, so this will again be detected by looking at
      //   the text's rect: if the element is collapsed, the width and height
      //   will be zero.
      if (isElementVisible(element) && isRectInViewport(textRect)) {
        matches.push({ node: node, index: i });

        // Resume searching after this match to prevent overlapping results.
        i += textLength- 1;
      }
    }
  }

  return matches;
}

function flattenNode(node) {
  var parent = node.parentNode;
  if (!parent) {
    return;
  }

  while (node.firstChild) {
    parent.insertBefore(node.firstChild, node);
  }

  node.remove();
  parent.normalize();
}

function clearHighlights() {
  if (highlightSpans.length > 0) {
    for (var span of highlightSpans) {
      flattenNode(span);
    }
    highlightSpans = [];
  }

  activeHighlightSpan = null;
}

function highlightAllMatches(text) {
  debug("Searching: " + text);

  clearHighlights();

  if (!text.trim()) {
    webkit.messageHandlers.findInPageHandler.postMessage({ totalResults: 0 });
    return;
  }

  var range = document.createRange();
  var matches = findMatches(text);
  var highlightTemplate = document.createElement("span");
  highlightTemplate.style.backgroundColor = MATCH_HIGHLIGHT_INACTIVE;

  // If there are multiple matches in the same node, inserting a highlight span before other matches
  // in that node will invalidate other matches since the node itself changes. By iterating through
  // results in reverse, we highlight matches last in the node first so earlier matches are unaffected.
  for (var i = matches.length - 1; i >= 0; --i) {
    var match = matches[i];
    var highlight = highlightTemplate.cloneNode();

    range.setStart(match.node, match.index);
    range.setEnd(match.node, match.index + text.length);
    range.surroundContents(highlight);
    highlightSpans.unshift(highlight);
  }

  debug(matches.length + " highlighted rects created!");
  webkit.messageHandlers.findInPageHandler.postMessage({ totalResults: matches.length });
}

function getIDForRect(rect) {
  return rect.top + "," + rect.bottom + "," + rect.left + "," + rect.right;
}

function updateActiveHighlight() {
  // Reset the color of the previous highlight.
  if (activeHighlightSpan) {
    activeHighlightSpan.style.backgroundColor = MATCH_HIGHLIGHT_INACTIVE;
  }

  if (!highlightSpans.length) {
    return;
  }

  activeHighlightSpan = highlightSpans[activeIndex];
  activeHighlightSpan.style.backgroundColor = MATCH_HIGHLIGHT_ACTIVE;

  // Find the position of the element centered on the screen, then scroll to it.
  var rect = activeHighlightSpan.getBoundingClientRect();
  var top = rect.top + scrollY - window.innerHeight / 2;
  var left = rect.left + scrollX - window.innerWidth / 2;
  left = clamp(left, 0, document.body.scrollWidth);
  top = clamp(top, 0, document.body.scrollHeight);
  scrollToSelection(left, top, SCROLL_INTERVAL_DURATION);
  debug("Scrolled to: " + left + ", " + top);
}

function scrollToSelection(left, top, duration) {
  var time = 0;
  var startX = scrollX;
  var startY = scrollY;
  clearInterval(scrollInterval);
  scrollInterval = setInterval(function() {
    var xStep = easeOutCubic(time, startX, left - startX, duration);
    var yStep = easeOutCubic(time, startY, top - startY, duration);
    window.scrollTo(xStep, yStep);
    time += SCROLL_INTERVAL_INCREMENT;
    if (time >= duration) {
      clearInterval(scrollInterval);
    }
  }, SCROLL_INTERVAL_INCREMENT);
}

function easeOutCubic(currentTime, startValue, changeInValue, duration) {
  return changeInValue * (Math.pow(currentTime / duration - 1, 3) + 1) + startValue;
}

function clamp(number, min, max) {
  return Math.max(min, Math.min(number, max));
}

function updateSearch(text) {
  if (lastSearch == text) {
    // The text is the same, so we're either finding either the next or previous result.
    var totalResults = highlightSpans.length;
    activeIndex = (activeIndex + totalResults) % totalResults;
  } else {
    // Store the current active rect to decide which new match should be active.
    var activeHighlightRect = null;
    if (activeHighlightSpan) {
      activeHighlightRect = activeHighlightSpan.getBoundingClientRect();
    }

    // The search text changed, so scan the page for new results.
    highlightAllMatches(text);

    // If we found a match at or after the last match, use that position
    // instead of starting again from the top.
    activeIndex = 0;
    if (activeHighlightRect) {
      for (var i = 0; i < highlightSpans.length; i++) {
        var highlight = highlightSpans[i];
        var highlightRect = highlight.getBoundingClientRect();
        if ((highlightRect.top == activeHighlightRect.top && highlightRect.left >= activeHighlightRect.left) ||
            (highlightRect.top > activeHighlightRect.top)) {
          activeIndex = i;
          break;
        }
      }
    }

    lastSearch = text;
  }

  // Update the UI with the current match index.
  var currentResult = highlightSpans.length ? activeIndex + 1 : 0;
  webkit.messageHandlers.findInPageHandler.postMessage({ currentResult: currentResult });

  updateActiveHighlight();
}

if (!window.__firefox__) {
  window.__firefox__ = {};
}

window.__firefox__.find = function (text) {
  updateSearch(text);
};

window.__firefox__.findNext = function (text) {
  activeIndex++;
  updateSearch(text);
};

window.__firefox__.findPrevious = function (text) {
  activeIndex--;
  updateSearch(text);
};

window.__firefox__.findDone = function () {
  clearHighlights();
  lastSearch = null;
};

}) ();
<commit_msg>Bug 1258695 - Add offset for highlighted text when using Find in page. With this highlighted content on 3.5 is visible. (#1709) <commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

(function() {
"use strict";

var DEBUG_ENABLED = false;
var MATCH_HIGHLIGHT_ACTIVE = "#f19750";
var MATCH_HIGHLIGHT_INACTIVE = "#ffde49";
var SCROLL_INTERVAL_INCREMENT = 5;
var SCROLL_INTERVAL_DURATION = 400;
var SCROLL_OFFSET = 60;

var activeHighlightSpan = null;
var lastSearch;
var scrollInterval;
var activeIndex = 0;
var highlightSpans = [];

function debug(str) {
  if (DEBUG_ENABLED) {
    console.log("FindInPage: " + str);
  }
}

function isElementVisible(elem) {
  return getComputedStyle(elem).visibility !== "hidden";
}

function isRectInViewport(rect) {
  var left = rect.left + document.body.scrollLeft;
  var right = rect.right + document.body.scrollLeft;
  var top = rect.top + document.body.scrollTop;
  var bottom = rect.bottom + document.body.scrollTop;

  return rect.width > 0 &&
         rect.height > 0 &&
         right >= 0 &&
         bottom >= 0 &&
         left <= document.body.scrollWidth &&
         top <= document.body.scrollHeight;
}

function findMatches(text) {
  // For case-insensitive matching.
  var lowerText = text.toLocaleLowerCase();
  var upperText = text.toLocaleUpperCase();

  var matches = [];
  var range = document.createRange();
  var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
  var textLength = text.length;
  var node;
  while (node = walker.nextNode()) {
    var textContent = node.textContent;
    findString: for (var i = 0; i < textContent.length - textLength + 1; ++i) {
      for (var j = 0; j < textLength; ++j) {
        var nextChar = textContent[i + j];
        if (lowerText[j] !== nextChar && upperText[j] !== nextChar) {
          continue findString;
        }
      }

      // This node is a TextNode, not an Element. Its parent is the nearest Element.
      var element = node.parentNode;

      // Find the rect of just the text for this match.
      range.setStart(node, i);
      range.setEnd(node, i + textLength);
      var textRect = range.getBoundingClientRect();

      // We have a match, but we need to make sure it's visible. The condition
      // below checks the following cases:
      // * If this element or any of its parents has style visibility hidden.
      //   The visibility style is inherited, so we need to check only this
      //   element and not all of its ancestors.
      // * If the highlight will be outside of the page's bounds. We determine
      //   this by comparing the bounds of the text rect.
      // * If the element style display is set to none. display:none collapses
      //   the element's space, so this will again be detected by looking at
      //   the text's rect: if the element is collapsed, the width and height
      //   will be zero.
      if (isElementVisible(element) && isRectInViewport(textRect)) {
        matches.push({ node: node, index: i });

        // Resume searching after this match to prevent overlapping results.
        i += textLength- 1;
      }
    }
  }

  return matches;
}

function flattenNode(node) {
  var parent = node.parentNode;
  if (!parent) {
    return;
  }

  while (node.firstChild) {
    parent.insertBefore(node.firstChild, node);
  }

  node.remove();
  parent.normalize();
}

function clearHighlights() {
  if (highlightSpans.length > 0) {
    for (var span of highlightSpans) {
      flattenNode(span);
    }
    highlightSpans = [];
  }

  activeHighlightSpan = null;
}

function highlightAllMatches(text) {
  debug("Searching: " + text);

  clearHighlights();

  if (!text.trim()) {
    webkit.messageHandlers.findInPageHandler.postMessage({ totalResults: 0 });
    return;
  }

  var range = document.createRange();
  var matches = findMatches(text);
  var highlightTemplate = document.createElement("span");
  highlightTemplate.style.backgroundColor = MATCH_HIGHLIGHT_INACTIVE;

  // If there are multiple matches in the same node, inserting a highlight span before other matches
  // in that node will invalidate other matches since the node itself changes. By iterating through
  // results in reverse, we highlight matches last in the node first so earlier matches are unaffected.
  for (var i = matches.length - 1; i >= 0; --i) {
    var match = matches[i];
    var highlight = highlightTemplate.cloneNode();

    range.setStart(match.node, match.index);
    range.setEnd(match.node, match.index + text.length);
    range.surroundContents(highlight);
    highlightSpans.unshift(highlight);
  }

  debug(matches.length + " highlighted rects created!");
  webkit.messageHandlers.findInPageHandler.postMessage({ totalResults: matches.length });
}

function getIDForRect(rect) {
  return rect.top + "," + rect.bottom + "," + rect.left + "," + rect.right;
}

function updateActiveHighlight() {
  // Reset the color of the previous highlight.
  if (activeHighlightSpan) {
    activeHighlightSpan.style.backgroundColor = MATCH_HIGHLIGHT_INACTIVE;
  }

  if (!highlightSpans.length) {
    return;
  }

  activeHighlightSpan = highlightSpans[activeIndex];
  activeHighlightSpan.style.backgroundColor = MATCH_HIGHLIGHT_ACTIVE;

  // Find the position of the element centered on the screen, then scroll to it.
  var rect = activeHighlightSpan.getBoundingClientRect();
  var top = SCROLL_OFFSET + rect.top + scrollY - window.innerHeight / 2;
  var left = rect.left + scrollX - window.innerWidth / 2;
  left = clamp(left, 0, document.body.scrollWidth);
  top = clamp(top, 0, document.body.scrollHeight);
  scrollToSelection(left, top, SCROLL_INTERVAL_DURATION);
  debug("Scrolled to: " + left + ", " + top);
}

function scrollToSelection(left, top, duration) {
  var time = 0;
  var startX = scrollX;
  var startY = scrollY;
  clearInterval(scrollInterval);
  scrollInterval = setInterval(function() {
    var xStep = easeOutCubic(time, startX, left - startX, duration);
    var yStep = easeOutCubic(time, startY, top - startY, duration);
    window.scrollTo(xStep, yStep);
    time += SCROLL_INTERVAL_INCREMENT;
    if (time >= duration) {
      clearInterval(scrollInterval);
    }
  }, SCROLL_INTERVAL_INCREMENT);
}

function easeOutCubic(currentTime, startValue, changeInValue, duration) {
  return changeInValue * (Math.pow(currentTime / duration - 1, 3) + 1) + startValue;
}

function clamp(number, min, max) {
  return Math.max(min, Math.min(number, max));
}

function updateSearch(text) {
  if (lastSearch == text) {
    // The text is the same, so we're either finding either the next or previous result.
    var totalResults = highlightSpans.length;
    activeIndex = (activeIndex + totalResults) % totalResults;
  } else {
    // Store the current active rect to decide which new match should be active.
    var activeHighlightRect = null;
    if (activeHighlightSpan) {
      activeHighlightRect = activeHighlightSpan.getBoundingClientRect();
    }

    // The search text changed, so scan the page for new results.
    highlightAllMatches(text);

    // If we found a match at or after the last match, use that position
    // instead of starting again from the top.
    activeIndex = 0;
    if (activeHighlightRect) {
      for (var i = 0; i < highlightSpans.length; i++) {
        var highlight = highlightSpans[i];
        var highlightRect = highlight.getBoundingClientRect();
        if ((highlightRect.top == activeHighlightRect.top && highlightRect.left >= activeHighlightRect.left) ||
            (highlightRect.top > activeHighlightRect.top)) {
          activeIndex = i;
          break;
        }
      }
    }

    lastSearch = text;
  }

  // Update the UI with the current match index.
  var currentResult = highlightSpans.length ? activeIndex + 1 : 0;
  webkit.messageHandlers.findInPageHandler.postMessage({ currentResult: currentResult });

  updateActiveHighlight();
}

if (!window.__firefox__) {
  window.__firefox__ = {};
}

window.__firefox__.find = function (text) {
  updateSearch(text);
};

window.__firefox__.findNext = function (text) {
  activeIndex++;
  updateSearch(text);
};

window.__firefox__.findPrevious = function (text) {
  activeIndex--;
  updateSearch(text);
};

window.__firefox__.findDone = function () {
  clearHighlights();
  lastSearch = null;
};

}) ();
<|endoftext|>


<commit_before>
//custom directive to insert card html from template for Night forecast
angular.module("myapp")
  .directive("nightcardinfo", function(){
    return {
    restrict: 'E',
    scope: {
      info: '='
    }
    templateUrl: 'js/directives2/cardNight.html'
  };
  });
<commit_msg>Update directive2.js<commit_after>
//custom directive to insert card html from template for Night forecast
angular.module("myapp")
  .directive("nightcardinfo", function(){
    return {
    restrict: 'E',
    scope: {
      info: '='
    }
    templateUrl: 'js/directives/cardNight.html'
  };
  });
<|endoftext|>


<commit_before>import React from 'react';
import Articles from '../../../components/Articles';
import ArticleSources from '../../../components/ArticleSources';
import { connect } from "react-redux";
import { Map } from "immutable";
import _ from "underscore";
import {
  fetchPopular,
} from "actions/articles";
import {
  fetchArticleSources,
  setActiveSource,
} from "actions/articleSources";

export class HomeView extends React.Component {

  static defaultProps = {
  	articles: [],
    articleSources: [],
    activeSource: null,
  }

  componentDidMount() {
    this.props.fetchArticleSources();
  	// this.props.fetchPopular(this.props.params.sourceId);
        console.log('article source size', !this.props.articleSources)

  }

  componentDidUpdate() {
  	console.log('did update', this.props.articles);
        console.log('article source size', !this.props.articleSources)

  }

  componentWillReceiveProps(nextProps) {
    if ( (!this.props.articleSources.length && nextProps.articleSources)
          || nextProps.params.sourceId != this.props.params.sourceId ) {
      let activeSource = _.findWhere(nextProps.articleSources, {id: nextProps.params.sourceId ? nextProps.params.sourceId : nextProps.articleSources[0].id})
      this.props.setActiveSource(activeSource);
      this.props.fetchPopular(activeSource.id, activeSource.sortBysAvailable[0])
    }
  }

  render() {
  	let { articles, articleSources } = this.props;
  	console.log('articles', articles);
    console.log('article sources', articleSources);
  	return (

        <ArticleSources sources={articleSources}></ArticleSources>
    		<Articles articles={articles}></Articles>

  	);
  }
}

const mapStateToProps = state => {
  return {
   	articles: state.articles.get("items"),
    articleSources: state.articleSources.get("sources", []),
    activeSource: state.articleSources.get("active"),
  };
};

const mapDispatchToProps = dispatch => {
  return {
    fetchPopular: (sourceId, sort) => dispatch(fetchPopular(sourceId, sort)),
    fetchArticleSources: () => dispatch(fetchArticleSources()),
    setActiveSource: (source) => dispatch(setActiveSource(source)),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(HomeView);<commit_msg>removed some logs<commit_after>import React from 'react';
import Articles from '../../../components/Articles';
import ArticleSources from '../../../components/ArticleSources';
import { connect } from "react-redux";
import { Map } from "immutable";
import _ from "underscore";
import {
  fetchPopular,
} from "actions/articles";
import {
  fetchArticleSources,
  setActiveSource,
} from "actions/articleSources";

export class HomeView extends React.Component {

  static defaultProps = {
  	articles: [],
    articleSources: [],
    activeSource: null,
  }

  componentDidMount() {
    this.props.fetchArticleSources();
  }

  componentWillReceiveProps(nextProps) {
    if ( (!this.props.articleSources.length && nextProps.articleSources)
          || nextProps.params.sourceId != this.props.params.sourceId ) {
      let activeSource = _.findWhere(nextProps.articleSources, {id: nextProps.params.sourceId ? nextProps.params.sourceId : nextProps.articleSources[0].id})
      this.props.setActiveSource(activeSource);
      this.props.fetchPopular(activeSource.id, activeSource.sortBysAvailable[0])
    }
  }

  render() {
  	let { articles, articleSources } = this.props;
  	return (

        <ArticleSources sources={articleSources}></ArticleSources>
    		<Articles articles={articles}></Articles>

  	);
  }
}

const mapStateToProps = state => {
  return {
   	articles: state.articles.get("items"),
    articleSources: state.articleSources.get("sources", []),
    activeSource: state.articleSources.get("active"),
  };
};

const mapDispatchToProps = dispatch => {
  return {
    fetchPopular: (sourceId, sort) => dispatch(fetchPopular(sourceId, sort)),
    fetchArticleSources: () => dispatch(fetchArticleSources()),
    setActiveSource: (source) => dispatch(setActiveSource(source)),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(HomeView);<|endoftext|>


<commit_before>// install   :     cordova plugin add cordova-plugin-device-motion
// link      :     https://github.com/apache/cordova-plugin-device-motion

angular.module('ngCordova.plugins.deviceMotion', [])

  .factory('$cordovaDeviceMotion', ['$q', function ($q) {

    return {
      getCurrentAcceleration: function () {
        var q = $q.defer();

        if (angular.isUndefined(navigator.accelerometer) ||
        !angular.isFunction(navigator.accelerometer.getCurrentAcceleration)) {
          q.reject('Device do not support watchAcceleration');
        }

        navigator.accelerometer.getCurrentAcceleration(function (result) {
          q.resolve(result);
        }, function (err) {
          q.reject(err);
        });

        return q.promise;
      },

      watchAcceleration: function (options) {
        var q = $q.defer();

        if (angular.isUndefined(navigator.accelerometer) ||
        !angular.isFunction(navigator.accelerometer.watchAcceleration)) {
          q.reject('Device do not support watchAcceleration');
        }

        var watchID = navigator.accelerometer.watchAcceleration(function (result) {
          q.notify(result);
        }, function (err) {
          q.reject(err);
        }, options);

        q.promise.cancel = function () {
          navigator.accelerometer.clearWatch(watchID);
        };

        q.promise.clearWatch = function (id) {
          navigator.accelerometer.clearWatch(id || watchID);
        };

        q.promise.watchID = watchID;

        return q.promise;
      },

      clearWatch: function (watchID) {
        return navigator.accelerometer.clearWatch(watchID);
      }
    };
  }]);
<commit_msg>fix($cordovaDeviceMotion): proper handling when no accelerometer available<commit_after>// install   :     cordova plugin add cordova-plugin-device-motion
// link      :     https://github.com/apache/cordova-plugin-device-motion

angular.module('ngCordova.plugins.deviceMotion', [])

  .factory('$cordovaDeviceMotion', ['$q', function ($q) {

    return {
      getCurrentAcceleration: function () {
        var q = $q.defer();

        if (angular.isUndefined(navigator.accelerometer) ||
        !angular.isFunction(navigator.accelerometer.getCurrentAcceleration)) {
          q.reject('Device do not support watchAcceleration');
          return q.promise;
        }

        navigator.accelerometer.getCurrentAcceleration(function (result) {
          q.resolve(result);
        }, function (err) {
          q.reject(err);
        });

        return q.promise;
      },

      watchAcceleration: function (options) {
        var q = $q.defer();

        if (angular.isUndefined(navigator.accelerometer) ||
        !angular.isFunction(navigator.accelerometer.watchAcceleration)) {
          q.reject('Device do not support watchAcceleration');
          return q.promise;
        }

        var watchID = navigator.accelerometer.watchAcceleration(function (result) {
          q.notify(result);
        }, function (err) {
          q.reject(err);
        }, options);

        q.promise.cancel = function () {
          navigator.accelerometer.clearWatch(watchID);
        };

        q.promise.clearWatch = function (id) {
          navigator.accelerometer.clearWatch(id || watchID);
        };

        q.promise.watchID = watchID;

        return q.promise;
      },

      clearWatch: function (watchID) {
        return navigator.accelerometer.clearWatch(watchID);
      }
    };
  }]);
<|endoftext|>


<commit_before>// This script inserts commas in long numbers such as the price of items.

// These are the steps I follows to create this script:
// Have Rydian send you a picture of where the price of an item is being read
// from memory.
//
// Or find the function that references the string:
// code.interface.window.buy.price_text
// which will have the instruction that reads the number close by.
//
// Reverse the functions that are called after the price has been read from
// memory.
// Notice that one of the functions references the string `%s`.
// This is the 'format string' string which means the number is being converted
// to a string prior to that function being called.
// Look above to see the function called immediately after reading the price
// and notice that its return value is being fed into the format string
// function we found.
// That function is the one that converts an integer to a string.
// Reverse that function and find a call to a function that calls itow_s
// multipul times.
// itow_s converts an integer to a wide string.
// Notice that the actual itow_s calls don't seem to be called all that
// regularly though.
// Notice that the function also references the string `%d`.
// This is the 'format decimal' string, which means this could also be
// converting our number.
// Notice that this part of the function is called as expected.
// Intercept the function and fix the number on return.

var intToStringFunction = scan('55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 83 EC 28 A1 ? ? ? ? 33 C5 89 45 F0 53 56 57 50 8D 45 F4 64 A3 ? ? ? ? 33 C0');

Interceptor.attach(intToStringFunction, {
    onLeave(retval) {
        // Destructure the mabi str.
        var mabiStr = Memory.readPointer(retval);
        var strPtr = mabiStr.add(0x1C);
        var lenPtr = mabiStr.add(0xC)

        // Read the current string (the number value without commas).
        var str = Memory.readUtf16String(strPtr);

        // Add commas to it.
        str = str.replace(/\B(?=(\d{3})+(?!\d))/g, ',');

        dmsg(str);

        // Write the new string to the mabi str and update the length of the
        // mabistr.
        Memory.writeUtf16String(strPtr, str);
        Memory.writeU32(lenPtr, str.length);
    }
});<commit_msg>Added original credits to FFriendlyNumbers.js<commit_after>// Originally from Step29 and kotarou3.

// This script inserts commas in long numbers such as the price of items.

// These are the steps I followed to create this script:
// Have Rydian send you a picture of where the price of an item is being read
// from memory.
//
// Or find the function that references the string:
// code.interface.window.buy.price_text
// which will have the instruction that reads the number close by.
//
// Reverse the functions that are called after the price has been read from
// memory.
// Notice that one of the functions references the string `%s`.
// This is the 'format string' string which means the number is being converted
// to a string prior to that function being called.
// Look above to see the function called immediately after reading the price
// and notice that its return value is being fed into the format string
// function we found.
// That function is the one that converts an integer to a string.
// Reverse that function and find a call to a function that calls itow_s
// multipul times.
// itow_s converts an integer to a wide string.
// Notice that the actual itow_s calls don't seem to be called all that
// regularly though.
// Notice that the function also references the string `%d`.
// This is the 'format decimal' string, which means this could also be
// converting our number.
// Notice that this part of the function is called as expected.
// Intercept the function and fix the number on return.

var intToStringFunction = scan('55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 83 EC 28 A1 ? ? ? ? 33 C5 89 45 F0 53 56 57 50 8D 45 F4 64 A3 ? ? ? ? 33 C0');

Interceptor.attach(intToStringFunction, {
    onLeave(retval) {
        // Destructure the mabi str.
        var mabiStr = Memory.readPointer(retval);
        var strPtr = mabiStr.add(0x1C);
        var lenPtr = mabiStr.add(0xC)

        // Read the current string (the number value without commas).
        var str = Memory.readUtf16String(strPtr);

        // Add commas to it.
        str = str.replace(/\B(?=(\d{3})+(?!\d))/g, ',');

        dmsg(str);

        // Write the new string to the mabi str and update the length of the
        // mabistr.
        Memory.writeUtf16String(strPtr, str);
        Memory.writeU32(lenPtr, str.length);
    }
});<|endoftext|>


<commit_before>function waitCursor() {
    $("body").addClass("wait");
}

function normalCursor() {
    $("body").removeClass("wait");
}

// http://stackoverflow.com/questions/4156101/javascript-push-array-values-into-another-array
Array.prototype.pushArray = function (arr) {
    this.push.apply(this, arr);
};<commit_msg>Added String.repeat() method<commit_after>function waitCursor() {
    $("body").addClass("wait");
}

function normalCursor() {
    $("body").removeClass("wait");
}

// http://stackoverflow.com/questions/4156101/javascript-push-array-values-into-another-array
Array.prototype.pushArray = function (arr) {
    this.push.apply(this, arr);
};

String.prototype.repeat = function (count) {
    if (count < 1) return '';
    var result = '', pattern = this.valueOf();
    while (count > 1) {
        if (count & 1) result += pattern;
        count >>= 1, pattern += pattern;
    }
    return result + pattern;
};
<|endoftext|>


<commit_before>// TODO: destroy the websocket

module.exports = WebSocketTracker

var debug = require('debug')('bittorrent-tracker:websocket-tracker')
var EventEmitter = require('events').EventEmitter
var hat = require('hat')
var inherits = require('inherits')
var Peer = require('simple-peer')
var Socket = require('simple-websocket')

var wrtc
try {
  wrtc = require('wrtc') // WebRTC in node - empty object in browser
  if (!wrtc.RTCPeerConnection) wrtc = null
} catch (err) {
  wrtc = null // optional dependency failed to install
}

var WEBRTC_SUPPORT = !!wrtc

var common = require('./common')

// It turns out that you can't open multiple websockets to the same server within one
// browser tab, so let's reuse them.
var socketPool = {}

inherits(WebSocketTracker, EventEmitter)

function WebSocketTracker (client, announceUrl, opts) {
  var self = this
  EventEmitter.call(self)
  debug('new websocket tracker %s', announceUrl)

  self.client = client

  self._opts = opts
  self._announceUrl = announceUrl
  self._peers = {} // peers (offer id -> peer)
  self._socket = null
  self._intervalMs = self.client._intervalMs // use client interval initially
  self._interval = null

  if (socketPool[announceUrl]) self._socket = socketPool[announceUrl]
  else self._socket = socketPool[announceUrl] = new Socket(announceUrl)

  self._socket.on('error', self._onSocketError.bind(self))
  self._socket.on('data', self._onSocketData.bind(self))
}

WebSocketTracker.supported = WEBRTC_SUPPORT

WebSocketTracker.prototype.announce = function (opts) {
  var self = this
  if (!self._socket.connected) {
    return self._socket.on('connect', self.announce.bind(self, opts))
  }

  opts.info_hash = self.client._infoHash.toString('binary')
  opts.peer_id = self.client._peerId.toString('binary')

  self._generateOffers(opts.numWant, function (offers) {
    opts.offers = offers

    if (self._trackerId) {
      opts.trackerid = self._trackerId
    }
    self._send(opts)
  })
}

WebSocketTracker.prototype.scrape = function (opts) {
  var self = this
  self._onSocketError(new Error('scrape not supported ' + self._announceUrl))
}

// TODO: Improve this interface
WebSocketTracker.prototype.setInterval = function (intervalMs) {
  var self = this
  clearInterval(self._interval)

  self._intervalMs = intervalMs
  if (intervalMs) {
    // HACK
    var update = self.announce.bind(self, self.client._defaultAnnounceOpts())
    self._interval = setInterval(update, self._intervalMs)
  }
}

WebSocketTracker.prototype._onSocketError = function (err) {
  var self = this
  self.client.emit('error', err)
}

WebSocketTracker.prototype._onSocketData = function (data) {
  var self = this

  if (!(typeof data === 'object' && data !== null)) {
    return self.client.emit('warning', new Error('Invalid tracker response'))
  }

  if (data.info_hash !== self.client._infoHash.toString('binary')) {
    return self.client.emit('warning', new Error('Invalid tracker response'))
  }

  debug('received %s from %s', JSON.stringify(data), self._announceUrl)

  var failure = data['failure reason']
  if (failure) return self.client.emit('warning', new Error(failure))

  var warning = data['warning message']
  if (warning) self.client.emit('warning', new Error(warning))

  var interval = data.interval || data['min interval']
  if (interval && !self._opts.interval && self._intervalMs !== 0) {
    // use the interval the tracker recommends, UNLESS the user manually specifies an
    // interval they want to use
    self.setInterval(interval * 1000)
  }

  var trackerId = data['tracker id']
  if (trackerId) {
    // If absent, do not discard previous trackerId value
    self._trackerId = trackerId
  }

  if (data.complete) {
    self.client.emit('update', {
      announce: self._announceUrl,
      complete: data.complete,
      incomplete: data.incomplete
    })
  }

  var peer
  if (data.offer) {
    peer = new Peer({ trickle: false, config: self._opts.rtcConfig, wrtc: wrtc })
    peer.id = common.binaryToHex(data.peer_id)
    peer.once('signal', function (answer) {
      var params = {
        info_hash: self.client._infoHash.toString('binary'),
        peer_id: self.client._peerId.toString('binary'),
        to_peer_id: data.peer_id,
        answer: answer,
        offer_id: data.offer_id
      }
      if (self._trackerId) params.trackerid = self._trackerId
      self._send(params)
    })
    peer.signal(data.offer)
    self.client.emit('peer', peer)
  }

  if (data.answer) {
    peer = self._peers[common.binaryToHex(data.offer_id)]
    if (peer) {
      peer.id = common.binaryToHex(data.peer_id)
      peer.signal(data.answer)
      self.client.emit('peer', peer)
    } else {
      debug('got unexpected answer: ' + JSON.stringify(data.answer))
    }
  }
}

WebSocketTracker.prototype._send = function (params) {
  var self = this
  debug('send %s', JSON.stringify(params))
  self._socket.send(params)
}

WebSocketTracker.prototype._generateOffers = function (numWant, cb) {
  var self = this
  var offers = []
  debug('generating %s offers', numWant)

  // TODO: cleanup dead peers and peers that never get a return offer, from self._peers
  for (var i = 0; i < numWant; ++i) {
    generateOffer()
  }

  function generateOffer () {
    var offerId = hat(160)
    var peer = self._peers[offerId] = new Peer({
      initiator: true,
      trickle: false,
      config: self._opts.rtcConfig,
      wrtc: wrtc
    })
    peer.once('signal', function (offer) {
      offers.push({
        offer: offer,
        offer_id: common.hexToBinary(offerId)
      })
      checkDone()
    })
  }

  function checkDone () {
    if (offers.length === numWant) {
      debug('generated %s offers', numWant)
      cb(offers)
    }
  }
}
<commit_msg>fix webrtc support detection in browser<commit_after>// TODO: destroy the websocket

module.exports = WebSocketTracker

var debug = require('debug')('bittorrent-tracker:websocket-tracker')
var EventEmitter = require('events').EventEmitter
var hat = require('hat')
var inherits = require('inherits')
var Peer = require('simple-peer')
var Socket = require('simple-websocket')

var wrtc
try {
  wrtc = require('wrtc') // WebRTC in node - empty object in browser
  if (!wrtc.RTCPeerConnection) wrtc = null
} catch (err) {
  wrtc = null // optional dependency failed to install
}

var WEBRTC_SUPPORT = !!wrtc || typeof window !== 'undefined'

var common = require('./common')

// It turns out that you can't open multiple websockets to the same server within one
// browser tab, so let's reuse them.
var socketPool = {}

inherits(WebSocketTracker, EventEmitter)

function WebSocketTracker (client, announceUrl, opts) {
  var self = this
  EventEmitter.call(self)
  debug('new websocket tracker %s', announceUrl)

  self.client = client

  self._opts = opts
  self._announceUrl = announceUrl
  self._peers = {} // peers (offer id -> peer)
  self._socket = null
  self._intervalMs = self.client._intervalMs // use client interval initially
  self._interval = null

  if (socketPool[announceUrl]) self._socket = socketPool[announceUrl]
  else self._socket = socketPool[announceUrl] = new Socket(announceUrl)

  self._socket.on('error', self._onSocketError.bind(self))
  self._socket.on('data', self._onSocketData.bind(self))
}

WebSocketTracker.supported = WEBRTC_SUPPORT

WebSocketTracker.prototype.announce = function (opts) {
  var self = this
  if (!self._socket.connected) {
    return self._socket.on('connect', self.announce.bind(self, opts))
  }

  opts.info_hash = self.client._infoHash.toString('binary')
  opts.peer_id = self.client._peerId.toString('binary')

  self._generateOffers(opts.numWant, function (offers) {
    opts.offers = offers

    if (self._trackerId) {
      opts.trackerid = self._trackerId
    }
    self._send(opts)
  })
}

WebSocketTracker.prototype.scrape = function (opts) {
  var self = this
  self._onSocketError(new Error('scrape not supported ' + self._announceUrl))
}

// TODO: Improve this interface
WebSocketTracker.prototype.setInterval = function (intervalMs) {
  var self = this
  clearInterval(self._interval)

  self._intervalMs = intervalMs
  if (intervalMs) {
    // HACK
    var update = self.announce.bind(self, self.client._defaultAnnounceOpts())
    self._interval = setInterval(update, self._intervalMs)
  }
}

WebSocketTracker.prototype._onSocketError = function (err) {
  var self = this
  self.client.emit('error', err)
}

WebSocketTracker.prototype._onSocketData = function (data) {
  var self = this

  if (!(typeof data === 'object' && data !== null)) {
    return self.client.emit('warning', new Error('Invalid tracker response'))
  }

  if (data.info_hash !== self.client._infoHash.toString('binary')) {
    return self.client.emit('warning', new Error('Invalid tracker response'))
  }

  debug('received %s from %s', JSON.stringify(data), self._announceUrl)

  var failure = data['failure reason']
  if (failure) return self.client.emit('warning', new Error(failure))

  var warning = data['warning message']
  if (warning) self.client.emit('warning', new Error(warning))

  var interval = data.interval || data['min interval']
  if (interval && !self._opts.interval && self._intervalMs !== 0) {
    // use the interval the tracker recommends, UNLESS the user manually specifies an
    // interval they want to use
    self.setInterval(interval * 1000)
  }

  var trackerId = data['tracker id']
  if (trackerId) {
    // If absent, do not discard previous trackerId value
    self._trackerId = trackerId
  }

  if (data.complete) {
    self.client.emit('update', {
      announce: self._announceUrl,
      complete: data.complete,
      incomplete: data.incomplete
    })
  }

  var peer
  if (data.offer) {
    peer = new Peer({ trickle: false, config: self._opts.rtcConfig, wrtc: wrtc })
    peer.id = common.binaryToHex(data.peer_id)
    peer.once('signal', function (answer) {
      var params = {
        info_hash: self.client._infoHash.toString('binary'),
        peer_id: self.client._peerId.toString('binary'),
        to_peer_id: data.peer_id,
        answer: answer,
        offer_id: data.offer_id
      }
      if (self._trackerId) params.trackerid = self._trackerId
      self._send(params)
    })
    peer.signal(data.offer)
    self.client.emit('peer', peer)
  }

  if (data.answer) {
    peer = self._peers[common.binaryToHex(data.offer_id)]
    if (peer) {
      peer.id = common.binaryToHex(data.peer_id)
      peer.signal(data.answer)
      self.client.emit('peer', peer)
    } else {
      debug('got unexpected answer: ' + JSON.stringify(data.answer))
    }
  }
}

WebSocketTracker.prototype._send = function (params) {
  var self = this
  debug('send %s', JSON.stringify(params))
  self._socket.send(params)
}

WebSocketTracker.prototype._generateOffers = function (numWant, cb) {
  var self = this
  var offers = []
  debug('generating %s offers', numWant)

  // TODO: cleanup dead peers and peers that never get a return offer, from self._peers
  for (var i = 0; i < numWant; ++i) {
    generateOffer()
  }

  function generateOffer () {
    var offerId = hat(160)
    var peer = self._peers[offerId] = new Peer({
      initiator: true,
      trickle: false,
      config: self._opts.rtcConfig,
      wrtc: wrtc
    })
    peer.once('signal', function (offer) {
      offers.push({
        offer: offer,
        offer_id: common.hexToBinary(offerId)
      })
      checkDone()
    })
  }

  function checkDone () {
    if (offers.length === numWant) {
      debug('generated %s offers', numWant)
      cb(offers)
    }
  }
}
<|endoftext|>


<commit_before>var dl = require('datalib'),
    log = require('vega-logging'),
    ChangeSet = require('./ChangeSet'),
    Collector = require('./Collector'),
    Tuple = require('./Tuple'),
    Node = require('./Node'); // jshint ignore:line

function DataSource(graph, name, facet) {
  this._graph = graph;
  this._name = name;
  this._data = [];
  this._source = null;
  this._facet  = facet;
  this._input  = ChangeSet.create();
  this._output = null; // Output changeset
  this._indexes = {};
  this._indexFields = [];

  this._inputNode  = null;
  this._outputNode = null;
  this._pipeline  = null; // Pipeline of transformations.
  this._collector = null; // Collector to materialize output of pipeline.
  this._mutates = false;  // Does any pipeline operator mutate tuples?
}

var prototype = DataSource.prototype;

prototype.name = function(name) {
  if (!arguments.length) return this._name;
  return (this._name = name, this);
};

prototype.source = function(src) {
  if (!arguments.length) return this._source;
  return (this._source = this._graph.data(src));
};

prototype.insert = function(tuples) {
  this._input.add = this._input.add.concat(tuples.map(Tuple.ingest));
  return this;
};

prototype.remove = function(where) {
  var remove = this._data.filter(where);
  this._input.rem = this._input.rem.concat(remove);
  return this;
};

prototype.update = function(where, field, func) {
  var mod = this._input.mod,
      ids = Tuple.idMap(mod);

  this._input.fields[field] = 1;

  this._data.filter(where).forEach(function(x) {
    var prev = x[field],
        next = func(x);
    if (prev !== next) {
      Tuple.set(x, field, next);
      if (ids[x._id] !== 1) {
        mod.push(x);
        ids[x._id] = 1;
      }
    }
  });

  return this;
};

prototype.values = function(data) {
  if (!arguments.length) return this._collector.data();

  // Replace backing data
  this._input.rem = this._data.slice();
  if (data) { this.insert(data); }
  return this;
};

prototype.mutates = function(m) {
  if (!arguments.length) return this._mutates;
  this._mutates = this._mutates || m;
  return this;
};

prototype.last = function() {
  return this._output;
};

prototype.fire = function(input) {
  if (input) this._input = input;
  this._graph.propagate(this._input, this._pipeline[0]);
  return this;
};

prototype.pipeline = function(pipeline) {
  if (!arguments.length) return this._pipeline;

  var graph = this._graph,
      status;

  pipeline.unshift(this._inputNode = DataSourceInput(this));
  status = graph.preprocess(pipeline);

  if (status.router) {
    pipeline.push(status.collector = new Collector(graph));
  }

  pipeline.push(this._outputNode = DataSourceOutput(this));
  this._collector = status.collector;
  this._mutates = !!status.mutates;
  graph.connect(this._pipeline = pipeline);

  return this;
};

prototype.synchronize = function() {
  // update indices
  var pulse = this.last(),
      fields = this._indexFields,
      i, j, f, key, index, value;

  for (i=0; i<fields.length; ++i) {
    key = fields[i];
    index = this._indexes[key];
    f = dl.$(key);

    for (j=0; j<pulse.add.length; ++j) {
      value = f(pulse.add[j]);
      Tuple.prev_init(pulse.add[j]);
      index[value] = (index[value] || 0) + 1;
    }
    for (j=0; j<pulse.rem.length; ++j) {
      value = f(pulse.rem[j]);
      index[value] = (index[value] || 0) - 1;
    }
    for (j=0; j<pulse.mod.length; ++j) {
      value = f(pulse.mod[j]._prev);
      index[value] = (index[value] || 0) - 1;
      value = f(pulse.mod[j]);
      index[value] = (index[value] || 0) + 1;
    }
  }

  this._graph.synchronize(this._pipeline);
  return this;
};

prototype.getIndex = function(field) {
  var data = this.values(),
      f = dl.$(field),
      index, i, len, value;

  if (!this._indexes[field]) {
    index = {};
    this._indexes[field] = index;
    this._indexFields.push(field);
    for (i=0, len=data.length; i<len; ++i) {
      value = f(this._data[i]);
      index[value] = (index[value] || 0) + 1;
      Tuple.prev_init(this._data[i]);
    }
  }
  return this._indexes[field];
};

prototype.listener = function() {
  return DataSourceListener(this).addListener(this._inputNode);
};

prototype.addListener = function(l) {
  if (l instanceof DataSource) {
    this._collector.addListener(l.listener());
  } else {
    this._outputNode.addListener(l);
  }
  return this;
};

prototype.removeListener = function(l) {
  this._outputNode.removeListener(l);
};

prototype.listeners = function(ds) {
  return (ds ? this._collector : this._outputNode).listeners();
};

// Input node applies the datasource's delta, and propagates it to
// the rest of the pipeline. It receives touches to reflow data.
function DataSourceInput(ds) {
  var input = new Node(ds._graph)
    .router(true)
    .collector(true);

  input.data = function() {
    return ds._data;
  };

  input.evaluate = function(input) {
    log.debug(input, ['input', ds._name]);

    var delta = ds._input,
        out = ChangeSet.create(input), f;

    // Delta might contain fields updated through API
    for (f in delta.fields) {
      out.fields[f] = 1;
    }

    // update data
    if (delta.rem.length) {
      ds._data = Tuple.idFilter(ds._data, delta.rem);
    }

    if (delta.add.length) {
      ds._data = ds._data.concat(delta.add);
    }

    if (delta.sort) {
      ds._data.sort(delta.sort);
    }

    // if reflowing, add any other tuples not currently in changeset
    if (input.reflow) {
      delta.mod = delta.mod.concat(
        Tuple.idFilter(ds._data, delta.add, delta.mod, delta.rem));
    }

    // reset change list
    ds._input = ChangeSet.create();

    out.add = delta.add;
    out.mod = delta.mod;
    out.rem = delta.rem;
    out.facet = ds._facet;
    return out;
  };

  return input;
}

// Output node captures the last changeset seen by this datasource
// (needed for joins and builds) and materializes any nested data.
// If this datasource is faceted, materializes the values in the facet.
function DataSourceOutput(ds) {
  var output = new Node(ds._graph)
    .router(true)
    .reflows(true)
    .collector(true);

  output.data = function() {
    return ds._collector ? ds._collector.data() : ds._data;
  };

  output.evaluate = function(input) {
    log.debug(input, ['output', ds._name]);

    var out = ChangeSet.create(input, true);

    if (ds._facet) {
      ds._facet.values = ds.values();
      input.facet = null;
    }

    ds._output = input;
    out.data[ds._name] = 1;
    return out;
  };

  return output;
}

function DataSourceListener(ds) {
  var l = new Node(ds._graph).router(true);

  l.evaluate = function(input) {
    // Tuple derivation carries a cost. So only derive if the pipeline has
    // operators that mutate, and thus would override the source data.
    if (ds.mutates()) {
      var map = ds._srcMap || (ds._srcMap = {}), // to propagate tuples correctly
          output = ChangeSet.create(input);

      output.add = input.add.map(function(t) {
        return (map[t._id] = Tuple.derive(t));
      });

      output.mod = input.mod.map(function(t) {
        return Tuple.rederive(t, map[t._id]);
      });

      output.rem = input.rem.map(function(t) {
        var o = map[t._id];
        return (map[t._id] = null, o);
      });

      return (ds._input = output);
    } else {
      return (ds._input = input);
    }
  };

  return l;
}

module.exports = DataSource;
<commit_msg>Fix indexing bugs.<commit_after>var dl = require('datalib'),
    log = require('vega-logging'),
    ChangeSet = require('./ChangeSet'),
    Collector = require('./Collector'),
    Tuple = require('./Tuple'),
    Node = require('./Node'); // jshint ignore:line

function DataSource(graph, name, facet) {
  this._graph = graph;
  this._name = name;
  this._data = [];
  this._source = null;
  this._facet  = facet;
  this._input  = ChangeSet.create();
  this._output = null; // Output changeset
  this._indexes = {};
  this._indexFields = [];

  this._inputNode  = null;
  this._outputNode = null;
  this._pipeline  = null; // Pipeline of transformations.
  this._collector = null; // Collector to materialize output of pipeline.
  this._mutates = false;  // Does any pipeline operator mutate tuples?
}

var prototype = DataSource.prototype;

prototype.name = function(name) {
  if (!arguments.length) return this._name;
  return (this._name = name, this);
};

prototype.source = function(src) {
  if (!arguments.length) return this._source;
  return (this._source = this._graph.data(src));
};

prototype.insert = function(tuples) {
  this._input.add = this._input.add.concat(tuples.map(Tuple.ingest));
  return this;
};

prototype.remove = function(where) {
  var remove = this._data.filter(where);
  this._input.rem = this._input.rem.concat(remove);
  return this;
};

prototype.update = function(where, field, func) {
  var mod = this._input.mod,
      ids = Tuple.idMap(mod);

  this._input.fields[field] = 1;

  this._data.filter(where).forEach(function(x) {
    var prev = x[field],
        next = func(x);
    if (prev !== next) {
      Tuple.set(x, field, next);
      if (ids[x._id] !== 1) {
        mod.push(x);
        ids[x._id] = 1;
      }
    }
  });

  return this;
};

prototype.values = function(data) {
  if (!arguments.length) return this._collector.data();

  // Replace backing data
  this._input.rem = this._data.slice();
  if (data) { this.insert(data); }
  return this;
};

prototype.mutates = function(m) {
  if (!arguments.length) return this._mutates;
  this._mutates = this._mutates || m;
  return this;
};

prototype.last = function() {
  return this._output;
};

prototype.fire = function(input) {
  if (input) this._input = input;
  this._graph.propagate(this._input, this._pipeline[0]);
  return this;
};

prototype.pipeline = function(pipeline) {
  if (!arguments.length) return this._pipeline;

  var graph = this._graph,
      status;

  pipeline.unshift(this._inputNode = DataSourceInput(this));
  status = graph.preprocess(pipeline);

  if (status.router) {
    pipeline.push(status.collector = new Collector(graph));
  }

  pipeline.push(this._outputNode = DataSourceOutput(this));
  this._collector = status.collector;
  this._mutates = !!status.mutates;
  graph.connect(this._pipeline = pipeline);

  return this;
};

prototype.synchronize = function() {
  this._graph.synchronize(this._pipeline);
  return this;
};

prototype.getIndex = function(field) {
  var data = this.values(),
      f = dl.$(field),
      index, i, len, value;

  if (!this._indexes[field]) {
    index = {};
    this._indexes[field] = index;
    this._indexFields.push(field);
    for (i=0, len=data.length; i<len; ++i) {
      value = f(data[i]);
      index[value] = (index[value] || 0) + 1;
      Tuple.prev_init(data[i]);
    }
  }
  return this._indexes[field];
};

prototype.listener = function() {
  return DataSourceListener(this).addListener(this._inputNode);
};

prototype.addListener = function(l) {
  if (l instanceof DataSource) {
    this._collector.addListener(l.listener());
  } else {
    this._outputNode.addListener(l);
  }
  return this;
};

prototype.removeListener = function(l) {
  this._outputNode.removeListener(l);
};

prototype.listeners = function(ds) {
  return (ds ? this._collector : this._outputNode).listeners();
};

// Input node applies the datasource's delta, and propagates it to
// the rest of the pipeline. It receives touches to reflow data.
function DataSourceInput(ds) {
  var input = new Node(ds._graph)
    .router(true)
    .collector(true);

  input.data = function() {
    return ds._data;
  };

  input.evaluate = function(input) {
    log.debug(input, ['input', ds._name]);

    var delta = ds._input,
        out = ChangeSet.create(input), f;

    // Delta might contain fields updated through API
    for (f in delta.fields) {
      out.fields[f] = 1;
    }

    // update data
    if (delta.rem.length) {
      ds._data = Tuple.idFilter(ds._data, delta.rem);
    }

    if (delta.add.length) {
      ds._data = ds._data.concat(delta.add);
    }

    if (delta.sort) {
      ds._data.sort(delta.sort);
    }

    // if reflowing, add any other tuples not currently in changeset
    if (input.reflow) {
      delta.mod = delta.mod.concat(
        Tuple.idFilter(ds._data, delta.add, delta.mod, delta.rem));
    }

    // reset change list
    ds._input = ChangeSet.create();

    out.add = delta.add;
    out.mod = delta.mod;
    out.rem = delta.rem;
    out.facet = ds._facet;
    return out;
  };

  return input;
}

// Output node captures the last changeset seen by this datasource
// (needed for joins and builds) and materializes any nested data.
// If this datasource is faceted, materializes the values in the facet.
function DataSourceOutput(ds) {
  var output = new Node(ds._graph)
    .router(true)
    .reflows(true)
    .collector(true);

  function updateIndices(pulse) {
    var fields = ds._indexFields,
        i, j, f, key, index, value;

    for (i=0; i<fields.length; ++i) {
      key = fields[i];
      index = ds._indexes[key];
      f = dl.$(key);

      for (j=0; j<pulse.add.length; ++j) {
        value = f(pulse.add[j]);
        Tuple.prev_init(pulse.add[j]);
        index[value] = (index[value] || 0) + 1;
      }
      for (j=0; j<pulse.rem.length; ++j) {
        value = f(pulse.rem[j]);
        index[value] = (index[value] || 0) - 1;
      }
      for (j=0; j<pulse.mod.length; ++j) {
        value = f(pulse.mod[j]._prev);
        index[value] = (index[value] || 0) - 1;
        value = f(pulse.mod[j]);
        index[value] = (index[value] || 0) + 1;
      }
    }
  }

  output.data = function() {
    return ds._collector ? ds._collector.data() : ds._data;
  };

  output.evaluate = function(input) {
    log.debug(input, ['output', ds._name]);

    updateIndices(input);
    var out = ChangeSet.create(input, true);

    if (ds._facet) {
      ds._facet.values = ds.values();
      input.facet = null;
    }

    ds._output = input;
    out.data[ds._name] = 1;
    return out;
  };

  return output;
}

function DataSourceListener(ds) {
  var l = new Node(ds._graph).router(true);

  l.evaluate = function(input) {
    // Tuple derivation carries a cost. So only derive if the pipeline has
    // operators that mutate, and thus would override the source data.
    if (ds.mutates()) {
      var map = ds._srcMap || (ds._srcMap = {}), // to propagate tuples correctly
          output = ChangeSet.create(input);

      output.add = input.add.map(function(t) {
        return (map[t._id] = Tuple.derive(t));
      });

      output.mod = input.mod.map(function(t) {
        return Tuple.rederive(t, map[t._id]);
      });

      output.rem = input.rem.map(function(t) {
        var o = map[t._id];
        return (map[t._id] = null, o);
      });

      return (ds._input = output);
    } else {
      return (ds._input = input);
    }
  };

  return l;
}

module.exports = DataSource;
<|endoftext|>


<commit_before>
var app = angular.module( 'app', [ 'ngRoute' ] );

app.config( [ '$routeProvider', function( $routeProvider ){
    $routeProvider
    .when( '/search', {
        templateUrl: '/static/jsframework/views/search.html',
        title: 'Search Page',
        controller: 'searchC',
        controllerAs: 'pc',
        css: 'static/app/css/search.css'
     } )
    .when( '/binge_list', {
        templateUrl: '/static/jsframework/views/bingeList.html',
        controller: 'bingeListC',
        controllerAs: 'pc',
        title: 'Binges to Be',
        css: 'static/app/css/bingeList.css'
     } )
    .when( '/community', {
        templateUrl: '/static/jsframework/views/communityBRs.html',
        controller: 'communityBRsC',
        controllerAs: 'pc',
        title: 'Community Bingether Requests',
        css: 'static/app/css/communityBRs.css'
     } )
    .when( '/my_bingethers', {
        templateUrl: '/static/jsframework/views/myBingethers.html',
        controller: 'myBingethersC',
        controllerAs: 'pc',
        title: 'My Bingethers',
        css: 'static/app/css/myBingethers.css'
     } )
    .when( '/log_out', {
        templateUrl: '/static/jsframework/views/logOut.html',
        controller: 'logOutC',
        controllerAs: 'pc',
        title: 'Take care!',
        css: 'static/app/css/logOut.css'
    })
    .when( '/', {
        templateUrl: '/static/jsframework/views/index.html',
        controller: 'indexC',
        controllerAs: 'pc',
        title: 'Welcome',
        css: 'static/app/css/index.css'
    })
    .when( '/uh_oh', {
        templateUrl: '/static/jsframework/views/uhOh.html',
        controller: 'uhOhC',
        controllerAs: 'pc',
        title: 'Oh no...',
        css: 'static/app/css/uhOh.css'
    })
    .otherwise({
        redirectTo: '/uh_oh'
    })
}]);

app.run( [ '$location', '$rootScope', function( $location, $rootScope ){
    $rootScope.$on( '$routeChangeSuccess', function( event, current, previous ){
        if ( current.$$route ){
            document.getElementById( 'pageTitle' ).innerHTML = current.$$route.title;
            document.getElementById( 'pageCSS' ).setAttribute( 'href', current.$$route.css );
        }
    } )
}]);<commit_msg>Removed dummy logOut route. Fixes #91.<commit_after>
var app = angular.module( 'app', [ 'ngRoute' ] );

app.config( [ '$routeProvider', function( $routeProvider ){
    $routeProvider
    .when( '/search', {
        templateUrl: '/static/jsframework/views/search.html',
        title: 'Search Page',
        controller: 'searchC',
        controllerAs: 'pc',
        css: 'static/app/css/search.css'
     } )
    .when( '/binge_list', {
        templateUrl: '/static/jsframework/views/bingeList.html',
        controller: 'bingeListC',
        controllerAs: 'pc',
        title: 'Binges to Be',
        css: 'static/app/css/bingeList.css'
     } )
    .when( '/community', {
        templateUrl: '/static/jsframework/views/communityBRs.html',
        controller: 'communityBRsC',
        controllerAs: 'pc',
        title: 'Community Bingether Requests',
        css: 'static/app/css/communityBRs.css'
     } )
    .when( '/my_bingethers', {
        templateUrl: '/static/jsframework/views/myBingethers.html',
        controller: 'myBingethersC',
        controllerAs: 'pc',
        title: 'My Bingethers',
        css: 'static/app/css/myBingethers.css'
     } )
    .when( '/', {
        templateUrl: '/static/jsframework/views/index.html',
        controller: 'indexC',
        controllerAs: 'pc',
        title: 'Welcome',
        css: 'static/app/css/index.css'
    })
    .when( '/uh_oh', {
        templateUrl: '/static/jsframework/views/uhOh.html',
        controller: 'uhOhC',
        controllerAs: 'pc',
        title: 'Oh no...',
        css: 'static/app/css/uhOh.css'
    })
    .otherwise({
        redirectTo: '/uh_oh'
    })
}]);

app.run( [ '$location', '$rootScope', function( $location, $rootScope ){
    $rootScope.$on( '$routeChangeSuccess', function( event, current, previous ){
        if ( current.$$route ){
            document.getElementById( 'pageTitle' ).innerHTML = current.$$route.title;
            document.getElementById( 'pageCSS' ).setAttribute( 'href', current.$$route.css );
        }
    } )
}]);<|endoftext|>


<commit_before>let roleClaimer = {
   run: function(creep) {
        let reservedControllerIDs = [
            "5873bb7f11e3e4361b4d5f13"
            , "5873bbab11e3e4361b4d6401"
            , "5873bbe111e3e4361b4d6ac5"
            , "5873bb9411e3e4361b4d6139"
            , "5873bbaa11e3e4361b4d63d1"
            , "5873bb9311e3e4361b4d612e"
        ]; // TODO: Get an array of controller.id from harvest rooms to check against here instead of hard coding the array
        if (_.includes(reservedControllerIDs, creep.memory.controllerID) == true && (Game.time < _.get(Memory.rooms, [_.get(Memory.controllers, [creep.memory.controllerID, "pos", "roomName"], ""), "avoidTravelUntil"], 0))) {
            ROLES["recyclable"].run(creep);
        }
        let theController = Game.getObjectById(creep.memory.controllerID);
        let canAttack = (_.countBy(creep.body, "type")[CLAIM] || 0) >= 5;
        if (theController == undefined || creep.room.name != theController.room.name) {
            let controllerMem = Memory.controllers[creep.memory.controllerID];
            if (controllerMem != undefined) {
                if ((_.get(Memory.controllers, [creep.memory.controllerID, "owner", "username"], "dragoonreas") != "dragoonreas" || _.get(Memory.controllers, [creep.memory.controllerID, "reservation", "owner"], "dragoonreas") != "dragoonreas") && canAttack == false) { // TODO: Add additional checks to make sure we're not accidently attacking an ally
                    creep.memory.role = "recyclable"; // recycle this creep so we can spawn another with more parts
                }
                else if (creep.memory.controllerID == "577b935b0f9d51615fa48076" && creep.room.name != "W9N45") {
                    creep.say(ICONS["moveTo"] + controllerMem.pos.roomName, true);
                    ROLES["scout"].run(creep);
                }
                else {
                    creep.say(ICONS["moveTo"] + controllerMem.pos.roomName, true);
                    creep.travelTo(_.create(RoomPosition.prototype, controllerMem.pos));
                }
            }
            else if (creep.memory.controllerID == "5873bb7f11e3e4361b4d5f13") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W88N29", true);
                creep.travelTo(new RoomPosition(13, 32, "W88N29"));
            }
            else if (creep.memory.controllerID == "5873bbab11e3e4361b4d6401") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W86N28", true);
                creep.travelTo(new RoomPosition(31, 12, "W86N28"));
            }
            else if (creep.memory.controllerID == "5873bbe111e3e4361b4d6ac5") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W84N23", true);
                creep.travelTo(new RoomPosition(23, 22, "W84N23"));
            }
            else if (creep.memory.controllerID == "5873bb9411e3e4361b4d6139") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W87N39", true);
                creep.travelTo(new RoomPosition(24, 40, "W87N39"));
            }
            else if (creep.memory.controllerID == "5873bbaa11e3e4361b4d63d1") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W86N38", true);
                creep.travelTo(new RoomPosition(44, 5, "W86N38"));
            }
            else if (creep.memory.controllerID == "5873bb9311e3e4361b4d612e") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W87N43", true);
                creep.travelTo(new RoomPosition(8, 39, "W87N43"));
            }
            else if (creep.memory.controllerID == "5873bbaa11e3e4361b4d63cd") {
                creep.say(ICONS["moveTo"] + "W86N39", true);
                creep.travelTo(new RoomPosition(19, 19, "W86N39"));
            }
            else if (creep.memory.controllerID == "5873bbc711e3e4361b4d6732") {
                creep.say(ICONS["moveTo"] + "W85N38", true);
                creep.travelTo(new RoomPosition(43, 37, "W85N38"));
            }
            else if (creep.memory.controllerID == "5873bbaa11e3e4361b4d63c3") {
                creep.say(ICONS["moveTo"] + "W86N43", true);
                creep.travelTo(new RoomPosition(30, 17, "W86N43"));
            }
            else if (creep.memory.controllerID == "577b935b0f9d51615fa48076") {
                creep.say(ICONS["moveTo"] + "W9N45", true);
                ROLES["scout"].run(creep);
            }
            else {
                creep.say(ICONS[STRUCTURE_CONTROLLER] + "?", true);
                //creep.memory.role = "recyclable"; // recycle this creep since it can't seem to do anything
            }
        }
        else {
            let err = ERR_GCL_NOT_ENOUGH;
            if (_.get(Memory.controllers, [creep.memory.controllerID, "owner", "username"], "dragoonreas") != "dragoonreas" || _.get(Memory.controllers, [creep.memory.controllerID, "reservation", "owner"], "dragoonreas") != "dragoonreas") { // TODO: Add additional checks to make sure we're not accidently attacking an ally
                if (canAttack == false) {
                    err == ERR_NO_BODYPART;
                }
                else {
                    err = creep.attackController(theController);
                }
                if (err == ERR_NOT_IN_RANGE) {
                    creep.say(ICONS["moveTo"] + ICONS[STRUCTURE_CONTROLLER], true);
                    creep.travelTo(theController);
                }
                else if (err == ERR_NO_BODYPART) {
                    creep.memory.role = "recyclable"; // recycle this creep so we can spawn another with more parts
                }
                else if (err == OK) {
                    creep.say(ICONS["attackController"] + ICONS[STRUCTURE_CONTROLLER], true);
                }
            }
            else if (_.some(reservedControllerIDs, (cID) => (cID == creep.memory.controllerID)) == false) { // NOTE: Using _.some in this way breaks earlier than _.each when false
                err = creep.claimController(theController);
                if (err == ERR_NOT_IN_RANGE) {
                    creep.say(ICONS["moveTo"] + ICONS[STRUCTURE_CONTROLLER], true);
                    creep.travelTo(theController);
                }
                else if (err == OK) {
                    creep.say(ICONS["claimController"] + ICONS[STRUCTURE_CONTROLLER], true);
                    console.log("Claimed controller in " + creep.room.name);
                    Game.notify("Claimed controller in " + creep.room.name);
                }
            }
            if (err == ERR_GCL_NOT_ENOUGH) {
                err = creep.reserveController(theController);
                if (creep.reserveController(theController) == ERR_NOT_IN_RANGE) {
                    creep.say(ICONS["moveTo"] + ICONS[STRUCTURE_CONTROLLER], true);
                    creep.travelTo(theController);
                }
                else if (err == OK) {
                    creep.say(ICONS["reserveController"] + ICONS[STRUCTURE_CONTROLLER], true);
                }
            }
            if (err != OK && err != ERR_NOT_IN_RANGE) {
                /*
                if (_.some(reservedControllerIDs, (cID) => (cID == creep.memory.controllerID)) == false) { // TODO: Get an array of controller.id from harvest rooms to check against here instead of hard coding the array
                    Memory.rooms[creep.memory.roomID].creepMins.claimer = 0;
                }
                */
                console.log("Can't interact with controller in " + _.get(Memory.controllers, [creep.memory.controllerID, "pos", "roomName"], creep.room.name) + ": " + err);
                creep.say(ICONS[STRUCTURE_CONTROLLER] + "?", true);
                creep.memory.role = "recyclable"; // recycle this creep since it can't seem to do anything
            }
        }
    }
};

module.exports = roleClaimer;
<commit_msg>Fixed bug with claimers not recycling themselves when an invader was in the harvest room they’re reserving.<commit_after>let roleClaimer = {
   run: function(creep) {
        let reservedControllerIDs = [
            "5873bb7f11e3e4361b4d5f13"
            , "5873bbab11e3e4361b4d6401"
            , "5873bbe111e3e4361b4d6ac5"
            , "5873bb9411e3e4361b4d6139"
            , "5873bbaa11e3e4361b4d63d1"
            , "5873bb9311e3e4361b4d612e"
        ]; // TODO: Get an array of controller.id from harvest rooms to check against here instead of hard coding the array
        if (_.includes(reservedControllerIDs, creep.memory.controllerID) == true && (Game.time < _.get(Memory.rooms, [_.get(Memory.controllers, [creep.memory.controllerID, "pos", "roomName"], ""), "avoidTravelUntil"], 0))) {
            ROLES["recyclable"].run(creep);
            return;
        }
        let theController = Game.getObjectById(creep.memory.controllerID);
        let canAttack = (_.countBy(creep.body, "type")[CLAIM] || 0) >= 5;
        if (theController == undefined || creep.room.name != theController.room.name) {
            let controllerMem = Memory.controllers[creep.memory.controllerID];
            if (controllerMem != undefined) {
                if ((_.get(Memory.controllers, [creep.memory.controllerID, "owner", "username"], "dragoonreas") != "dragoonreas" || _.get(Memory.controllers, [creep.memory.controllerID, "reservation", "owner"], "dragoonreas") != "dragoonreas") && canAttack == false) { // TODO: Add additional checks to make sure we're not accidently attacking an ally
                    creep.memory.role = "recyclable"; // recycle this creep so we can spawn another with more parts
                }
                else if (creep.memory.controllerID == "577b935b0f9d51615fa48076" && creep.room.name != "W9N45") {
                    creep.say(ICONS["moveTo"] + controllerMem.pos.roomName, true);
                    ROLES["scout"].run(creep);
                }
                else {
                    creep.say(ICONS["moveTo"] + controllerMem.pos.roomName, true);
                    creep.travelTo(_.create(RoomPosition.prototype, controllerMem.pos));
                }
            }
            else if (creep.memory.controllerID == "5873bb7f11e3e4361b4d5f13") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W88N29", true);
                creep.travelTo(new RoomPosition(13, 32, "W88N29"));
            }
            else if (creep.memory.controllerID == "5873bbab11e3e4361b4d6401") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W86N28", true);
                creep.travelTo(new RoomPosition(31, 12, "W86N28"));
            }
            else if (creep.memory.controllerID == "5873bbe111e3e4361b4d6ac5") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W84N23", true);
                creep.travelTo(new RoomPosition(23, 22, "W84N23"));
            }
            else if (creep.memory.controllerID == "5873bb9411e3e4361b4d6139") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W87N39", true);
                creep.travelTo(new RoomPosition(24, 40, "W87N39"));
            }
            else if (creep.memory.controllerID == "5873bbaa11e3e4361b4d63d1") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W86N38", true);
                creep.travelTo(new RoomPosition(44, 5, "W86N38"));
            }
            else if (creep.memory.controllerID == "5873bb9311e3e4361b4d612e") { // TODO: Store controller.pos in memory for controllers in harvest rooms
                creep.say(ICONS["moveTo"] + "W87N43", true);
                creep.travelTo(new RoomPosition(8, 39, "W87N43"));
            }
            else if (creep.memory.controllerID == "5873bbaa11e3e4361b4d63cd") {
                creep.say(ICONS["moveTo"] + "W86N39", true);
                creep.travelTo(new RoomPosition(19, 19, "W86N39"));
            }
            else if (creep.memory.controllerID == "5873bbc711e3e4361b4d6732") {
                creep.say(ICONS["moveTo"] + "W85N38", true);
                creep.travelTo(new RoomPosition(43, 37, "W85N38"));
            }
            else if (creep.memory.controllerID == "5873bbaa11e3e4361b4d63c3") {
                creep.say(ICONS["moveTo"] + "W86N43", true);
                creep.travelTo(new RoomPosition(30, 17, "W86N43"));
            }
            else if (creep.memory.controllerID == "577b935b0f9d51615fa48076") {
                creep.say(ICONS["moveTo"] + "W9N45", true);
                ROLES["scout"].run(creep);
            }
            else {
                creep.say(ICONS[STRUCTURE_CONTROLLER] + "?", true);
                //creep.memory.role = "recyclable"; // recycle this creep since it can't seem to do anything
            }
        }
        else {
            let err = ERR_GCL_NOT_ENOUGH;
            if (_.get(Memory.controllers, [creep.memory.controllerID, "owner", "username"], "dragoonreas") != "dragoonreas" || _.get(Memory.controllers, [creep.memory.controllerID, "reservation", "owner"], "dragoonreas") != "dragoonreas") { // TODO: Add additional checks to make sure we're not accidently attacking an ally
                if (canAttack == false) {
                    err == ERR_NO_BODYPART;
                }
                else {
                    err = creep.attackController(theController);
                }
                if (err == ERR_NOT_IN_RANGE) {
                    creep.say(ICONS["moveTo"] + ICONS[STRUCTURE_CONTROLLER], true);
                    creep.travelTo(theController);
                }
                else if (err == ERR_NO_BODYPART) {
                    creep.memory.role = "recyclable"; // recycle this creep so we can spawn another with more parts
                }
                else if (err == OK) {
                    creep.say(ICONS["attackController"] + ICONS[STRUCTURE_CONTROLLER], true);
                }
            }
            else if (_.some(reservedControllerIDs, (cID) => (cID == creep.memory.controllerID)) == false) { // NOTE: Using _.some in this way breaks earlier than _.each when false
                err = creep.claimController(theController);
                if (err == ERR_NOT_IN_RANGE) {
                    creep.say(ICONS["moveTo"] + ICONS[STRUCTURE_CONTROLLER], true);
                    creep.travelTo(theController);
                }
                else if (err == OK) {
                    creep.say(ICONS["claimController"] + ICONS[STRUCTURE_CONTROLLER], true);
                    console.log("Claimed controller in " + creep.room.name);
                    Game.notify("Claimed controller in " + creep.room.name);
                }
            }
            if (err == ERR_GCL_NOT_ENOUGH) {
                err = creep.reserveController(theController);
                if (creep.reserveController(theController) == ERR_NOT_IN_RANGE) {
                    creep.say(ICONS["moveTo"] + ICONS[STRUCTURE_CONTROLLER], true);
                    creep.travelTo(theController);
                }
                else if (err == OK) {
                    creep.say(ICONS["reserveController"] + ICONS[STRUCTURE_CONTROLLER], true);
                }
            }
            if (err != OK && err != ERR_NOT_IN_RANGE) {
                /*
                if (_.some(reservedControllerIDs, (cID) => (cID == creep.memory.controllerID)) == false) { // TODO: Get an array of controller.id from harvest rooms to check against here instead of hard coding the array
                    Memory.rooms[creep.memory.roomID].creepMins.claimer = 0;
                }
                */
                console.log("Can't interact with controller in " + _.get(Memory.controllers, [creep.memory.controllerID, "pos", "roomName"], creep.room.name) + ": " + err);
                creep.say(ICONS[STRUCTURE_CONTROLLER] + "?", true);
                creep.memory.role = "recyclable"; // recycle this creep since it can't seem to do anything
            }
        }
    }
};

module.exports = roleClaimer;
<|endoftext|>