<commit_before>/*jshint esversion: 6 */
export default (state = {notes: [], deleted: []}, action) => {
  if (action.type === 'SUBMIT_NOTE') {
    action.socket.emit('new note', {content: action.content, thought: action.thought});
  }

  if (action.type === 'ADD_NOTE') {
    let notes = state.notes.concat([action.note]);
    notes.sort((a, b) => a.audioTimestamp - b.audioTimestamp);
    return {
      ...state,
      notes,
    };
  }

  if (action.type === 'EDIT_NOTE') {
    state.notes = state.notes.map((note, i) => {
      if (note.id === action.noteId) {
        note.content = action.newText;
        note.changed = true;
      }
      return note;
    });
  }

  if (action.type === 'EDIT_TIMESTAMP') {
    const notes = state.notes.map((note, i) => {
      if (note.id === action.noteId) {
        note.audioTimestamp = action.newTimestamp;
        note.changed = true;
      }
      return note;
    });
    return {
      ...state,
      notes,
    };
  }

  if (action.type === 'REPLACE_NOTES') {
    let notes = action.allNotes.sort((a, b) => a.audioTimestamp - b.audioTimestamp);

    state.notes = [{audioTimestamp: 0}].concat(notes);
    // console.log('state.notes in noteReducer', notes);
    state.justNotes = state.notes.filter(note=>!note.thought);
    state.justThoughts = notes.filter(note=>note.thought);
    state.audioTimestampArray = state.justNotes.map(note=> Number(note.audioTimestamp) / 1000);
    // console.log('notes in justNotes', state.justNotes);
    action.cb && action.cb();
    return {...state};
  }

  if (action.type === 'REMOVE_NOTES') {
    return {
      ...state,
      notes: [],
      audioTimestamp: []
    };
  }

  if (action.type === 'DELETE_NOTE') {
    let index = -1;
    for (let i = 0; i < state.notes.length; i++) {
      if (state.notes[i].id === action.noteId) {
        index = i;
        break;
      }
    }
    return {
      ...state,
      deleted: state.deleted.concat(state.notes.splice(index, 1)),
    };
  }

  if (action.type === 'CLEAR_DELETED_NOTES') {
    return {
      ...state,
      deleted: [],
    };
  }

  if (action.type === 'SELECT_NOTE') {
    let notes = state.notes;

    for (let i = 0; i < notes.length; i++) {
      if (notes[i].id === action.noteId) {
        notes[i].show = !notes[i].show;
        if (notes[i].changed) {
          delete notes[i].changed;
        } else {
          notes[i].changed = true;
        }
        break;
      }
    }
    return {...state};
  }

  if (action.type === 'SET_CLASS') {

    if (window.timer) {
      window.clearTimeout(window.timer);
    }

    let upcomingNoteIndex = action.index;
    let wavePos = action.wavePos;

    const updateNote = (idx) => {
      state.justNotes.forEach(note => note['highlight'] = null);
      state.justNotes[idx]['highlight'] = true;
      let diff = state.audioTimestampArray[idx + 1] - wavePos;
      wavePos = wavePos + diff;
      idx++;
      if (state.audioTimestampArray[idx] > -1) {
        window.timer = window.setTimeout(updateNote.bind(this, idx), diff * 1000);
      }
    };
    let idx = upcomingNoteIndex - 1 < 0 ? 0 : upcomingNoteIndex - 1;
    if (action.actionState === 'paused') {
      state.justNotes.forEach(note => note['highlight'] = null);
      state.justNotes[idx]['highlight'] = true;
    } else {
      updateNote(idx);
    }

    return state;
  }

  if (action.type === 'REMOVE_TIMER') {
    // console.log('removing the timer', window.timer);
    if (window.timer) {
      window.clearTimeout(window.timer);
    }
    return state;
  }
  if (action.type === 'SET_ARROW') {
    state.justNotes.forEach(note => delete note['arrow']);
    state.justNotes[action.arrowPos]['arrow'] = true;
    return {...state};
  }
  if (action.type === 'REMOVE_ARROW') {
    console.log('removing arrows');
    state.justNotes.forEach(note => delete note['arrow']);
    return {...state};
  }

  return {...state};
};
<commit_msg>trying to fix the pointer<commit_after>/*jshint esversion: 6 */
export default (state = {notes: [], deleted: []}, action) => {
  if (action.type === 'SUBMIT_NOTE') {
    action.socket.emit('new note', {content: action.content, thought: action.thought});
  }

  if (action.type === 'ADD_NOTE') {
    let notes = state.notes.concat([action.note]);
    notes = notes.sort((a, b) => a.audioTimestamp - b.audioTimestamp);
    return {
      ...state,
      notes: notes,
    };
  }

  if (action.type === 'EDIT_NOTE') {
    state.notes = state.notes.map((note, i) => {
      if (note.id === action.noteId) {
        note.content = action.newText;
        note.changed = true;
      }
      return note;
    });
  }

  if (action.type === 'EDIT_TIMESTAMP') {
    const notes = state.notes.map((note, i) => {
      if (note.id === action.noteId) {
        note.audioTimestamp = action.newTimestamp;
        note.changed = true;
      }
      return note;
    });
    return {
      ...state,
      notes,
    };
  }

  if (action.type === 'REPLACE_NOTES') {
    let notes = action.allNotes.sort((a, b) => a.audioTimestamp - b.audioTimestamp);

    state.notes = [{audioTimestamp: 0}].concat(notes);
    // console.log('state.notes in noteReducer', notes);
    state.justNotes = state.notes.filter(note=>!note.thought);
    state.justThoughts = notes.filter(note=>note.thought);
    state.audioTimestampArray = state.justNotes.map(note=> Number(note.audioTimestamp) / 1000);
    // console.log('notes in justNotes', state.justNotes);
    action.cb && action.cb();
    return {...state};
  }

  if (action.type === 'REMOVE_NOTES') {
    return {
      ...state,
      notes: [],
      audioTimestamp: []
    };
  }

  if (action.type === 'DELETE_NOTE') {
    let index = -1;
    for (let i = 0; i < state.notes.length; i++) {
      if (state.notes[i].id === action.noteId) {
        index = i;
        break;
      }
    }
    return {
      ...state,
      deleted: state.deleted.concat(state.notes.splice(index, 1)),
    };
  }

  if (action.type === 'CLEAR_DELETED_NOTES') {
    return {
      ...state,
      deleted: [],
    };
  }

  if (action.type === 'SELECT_NOTE') {
    let notes = state.notes;

    for (let i = 0; i < notes.length; i++) {
      if (notes[i].id === action.noteId) {
        notes[i].show = !notes[i].show;
        if (notes[i].changed) {
          delete notes[i].changed;
        } else {
          notes[i].changed = true;
        }
        break;
      }
    }
    return {...state};
  }

  if (action.type === 'SET_CLASS') {

    if (window.timer) {
      window.clearTimeout(window.timer);
    }

    let upcomingNoteIndex = action.index;
    let wavePos = action.wavePos;

    const updateNote = (idx) => {
      state.justNotes.forEach(note => note['highlight'] = null);
      state.justNotes[idx]['highlight'] = true;
      let diff = state.audioTimestampArray[idx + 1] - wavePos;
      wavePos = wavePos + diff;
      idx++;
      if (state.audioTimestampArray[idx] > -1) {
        window.timer = window.setTimeout(updateNote.bind(this, idx), diff * 1000);
      }
    };
    let idx = upcomingNoteIndex - 1 < 0 ? 0 : upcomingNoteIndex - 1;
    if (action.actionState === 'paused') {
      state.justNotes.forEach(note => note['highlight'] = null);
      state.justNotes[idx]['highlight'] = true;
    } else {
      updateNote(idx);
    }

    return state;
  }

  if (action.type === 'REMOVE_TIMER') {
    // console.log('removing the timer', window.timer);
    if (window.timer) {
      window.clearTimeout(window.timer);
    }
    return state;
  }
  if (action.type === 'SET_ARROW') {
    state.justNotes.forEach(note => delete note['arrow']);
    state.justNotes[action.arrowPos]['arrow'] = true;
    return {...state};
  }
  if (action.type === 'REMOVE_ARROW') {
    console.log('removing arrows');
    state.justNotes.forEach(note => delete note['arrow']);
    return {...state};
  }

  return {...state};
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require("fs");
var os = require("os");
var path = require("path");
var tele = require("../index");
var argv = require("optimist")
  .default("id", "./seed.json")
  .default("port", 42424)
  .boolean("bridge").default("bridge",true)
  .boolean("v").describe("v", "verbose")
  .boolean("nolan").describe("nolan", "disable lan usage")
  .describe("ip", "force set the public IP address to override any NAT detection")
  .argv;

if(argv.v) tele.debug(console.log);
tele.info(function(){console.log.apply(console,arguments)});

if(argv.port == 42420)
{
  console.log("that port is reserved");
  process.exit(1);
}

// localize our id file
var idfile = path.join(__dirname, argv.id);

// load the pub/private key or create one
var keys;
if(fs.existsSync(idfile) && (keys = require(idfile)) && keys.parts)
{
  init(keys);
}else{
  tele.genkeys(function(err, keys){
    fs.writeFileSync(idfile, JSON.stringify(keys, null, 4));
    init(keys);
  });
}

function init(keys)
{
  var seed = tele.hashname(keys, {port:parseInt(argv.port), ip:argv.ip, nolan:argv.nolan});
  if(!seed) return console.log("something went wrong :(");
  if(argv.seeds) seed.addSeeds(argv.seeds);
  if(!argv.nohttp) seed.http(argv.http, require('socket.io').listen(argv.port, {log:false}));
  seed.bridging = argv.bridge;
  seed.online(function(err){
    var lan4 = seed.paths.lan4 || {};
    var pub4 = seed.paths.pub4 || {};
    var ip = pub4.ip||lan4.ip;
    var port = pub4.port||lan4.port;
    var info = {paths:[], hashname:seed.hashname, parts:seed.parts, keys:seed.keys};
    info.paths.push({type:"ipv4",ip:ip,port:port});
    if(seed.paths.lan6) info.paths.push({type:"ipv6",ip:seed.paths.lan6.ip,port:seed.paths.lan6.port});
    if(!argv.nohttp) info.paths.push({type:"http",http:seed.paths.http.http});
    if(seed.bridging) info.bridge = true;
    console.log(JSON.stringify(info, null, 4));
    if(seed.nat) console.log("warning, may be behind a NAT, IP and Port may not be stable");
    console.log((err?err:"connected to mesh seed peers"));
  });
}
<commit_msg>optional set selection for creation<commit_after>#!/usr/bin/env node

var fs = require("fs");
var os = require("os");
var path = require("path");
var tele = require("../index");
var argv = require("optimist")
  .default("id", "./seed.json")
  .default("port", 42424)
  .boolean("bridge").default("bridge",true)
  .boolean("v").describe("v", "verbose")
  .boolean("nolan").describe("nolan", "disable lan usage")
  .string("cs").describe("cs", "cipher sets to generate id with, comma delim")
  .describe("ip", "force set the public IP address to override any NAT detection")
  .argv;

if(argv.v) tele.debug(console.log);
tele.info(function(){console.log.apply(console,arguments)});
var sets;
if(typeof argv.cs == "string")
{
  sets = {};
  argv.cs.split(",").forEach(function(cs){sets[cs]=true});
}

if(argv.port == 42420)
{
  console.log("that port is reserved");
  process.exit(1);
}

// localize our id file
var idfile = path.join(__dirname, argv.id);

// load the pub/private key or create one
var keys;
if(fs.existsSync(idfile) && (keys = require(idfile)) && keys.parts)
{
  init(keys);
}else{
  tele.genkeys(function(err, keys){
    fs.writeFileSync(idfile, JSON.stringify(keys, null, 4));
    init(keys);
  },false,sets);
}

function init(keys)
{
  var seed = tele.hashname(keys, {port:parseInt(argv.port), ip:argv.ip, nolan:argv.nolan});
  if(!seed) return console.log("something went wrong :(");
  if(argv.seeds) seed.addSeeds(argv.seeds);
  if(!argv.nohttp) seed.http(argv.http, require('socket.io').listen(argv.port, {log:false}));
  seed.bridging = argv.bridge;
  seed.online(function(err,count){
    var lan4 = seed.paths.lan4 || {};
    var pub4 = seed.paths.pub4 || {};
    var ip = pub4.ip||lan4.ip;
    var port = pub4.port||lan4.port;
    var info = {paths:[], hashname:seed.hashname, parts:seed.parts, keys:seed.keys};
    info.paths.push({type:"ipv4",ip:ip,port:port});
    if(seed.paths.lan6) info.paths.push({type:"ipv6",ip:seed.paths.lan6.ip,port:seed.paths.lan6.port});
    if(!argv.nohttp) info.paths.push({type:"http",http:seed.paths.http.http});
    if(seed.bridging) info.bridge = true;
    console.log("[\n\t"+JSON.stringify(info)+"\n]");
    if(seed.nat) console.log("warning, may be behind a NAT, IP and Port may not be stable");
    console.log((err?err:"connected to "+count+" mesh seed peers"));
  });
}
<|endoftext|>


<commit_before>/*jshint esversion: 6 */
const createSocketRoom = (state, host, pathUrl, createRoom) => {
  // this is if server is localhost
  var socket = io();
  // if server is not localhost,
  // then set up io to know where the server is
  socket.emit('create room', pathUrl, host);
  socket.on('create room success', function() {
    console.log('successfully created socket room');
    createRoom(pathUrl);
  });
  return socket;
};

export default (state = {}, action) => {
  if (action.type === 'CREATE_ROOM') {
    // ajax call passing in action.data and then setting state in the success
    $.ajax({
      method: 'POST',
      url: '/api/rooms',
      contentType: 'application/json',
      data: JSON.stringify(action.data),
      success: function(res, status) {
        console.log('the response: ', res);
        state.participants = [action.user];
        state.socket = createSocketRoom(state, action.user, res.pathUrl, action.createRoom);
        state.roomInfo = res;
      },
      error: function( res, status ) {
        console.log(res);
      }
    });
  }

  if (action.type === 'JOIN_SOCKET_ROOM') {
    var socket = io();
    console.log('joining room');
    socket.emit('join room', action.pathUrl, action.user);

    socket.on('join room error', () => {
      console.log('join room error');
      socket.disconnect();
      state.socket = null;
      action.joinedRoom('error');
    });

    socket.on('join room success', (participants, roomInfo) => {
      console.log(`join room success, ${JSON.stringify(participants)} are here`);
      state.socket = socket;
      state.roomInfo = roomInfo;
      state.participants = participants;
      action.joinedRoom(null, 'success');
    });
  }

  if (action.type === 'LEAVE_SOCKET_ROOM') {
    state.socket.disconnect();
    state.socket = null;
  }
  if (action.type === 'ADD_PARTICIPANT') {
    state.participants.push(action.participant);
  }
  if (action.type === 'REMOVE_PARTICIPANT') {
    console.log('this is the participant to remove', state.participants.findIndex((obj) => obj.facebookId === action.participant.facebookId));
    state.participants.splice(state.participants.findIndex((obj) => obj.facebookId === action.participant.facebookId), 1);
  }

  return state;
};
<commit_msg>added some handling for deletion of user. it works now<commit_after>/*jshint esversion: 6 */
const createSocketRoom = (state, host, pathUrl, createRoom) => {
  // this is if server is localhost
  var socket = io();
  // if server is not localhost,
  // then set up io to know where the server is
  socket.emit('create room', pathUrl, host);
  socket.on('create room success', function() {
    console.log('successfully created socket room');
    createRoom(pathUrl);
  });
  return socket;
};

export default (state = {}, action) => {
  if (action.type === 'CREATE_ROOM') {
    // ajax call passing in action.data and then setting state in the success
    $.ajax({
      method: 'POST',
      url: '/api/rooms',
      contentType: 'application/json',
      data: JSON.stringify(action.data),
      success: function(res, status) {
        console.log('the response: ', res);
        state.participants = [action.user];
        state.socket = createSocketRoom(state, action.user, res.pathUrl, action.createRoom);
        state.roomInfo = res;
      },
      error: function( res, status ) {
        console.log(res);
      }
    });
  }

  if (action.type === 'JOIN_SOCKET_ROOM') {
    var socket = io();
    console.log('joining room');
    socket.emit('join room', action.pathUrl, action.user);

    socket.on('join room error', () => {
      console.log('join room error');
      socket.disconnect();
      state.socket = null;
      action.joinedRoom('error');
    });

    socket.on('join room success', (participants, roomInfo) => {
      console.log('join room success');
      state.socket = socket;
      state.roomInfo = roomInfo;
      state.participants = participants;
      action.joinedRoom(null, 'success');
    });
  }

  if (action.type === 'LEAVE_SOCKET_ROOM') {
    state.socket.disconnect();
    state.socket = null;
  }
  if (action.type === 'ADD_PARTICIPANT') {
    state.participants.push(action.participant);
  }
  if (action.type === 'REMOVE_PARTICIPANT') {
    console.log('this is the participant to remove', state.participants.findIndex((obj) => obj.facebookId === action.participant.facebookId));
    state.participants.splice(state.participants.findIndex((obj) => obj.facebookId === action.participant.facebookId), 1);
  }

  return state;
};
<|endoftext|>


<commit_before>import { SpriteWidth, SpriteHeight, SpriteRatioX, SpriteRatioY, Bounds } from "../Constants.js";
import { Wall } from "../SpriteConstants";

class Room extends Phaser.Group {

  constructor(game, parent, name) {
    super(game, parent, name, false, false, Phaser.Physics.ARCADE);
  }

  createRandomLine(x1, y1, x2, y2, division = 1, varX = 0, varY = 0) {
    const middleX = (x1 + x2) / 2 + (varX * SpriteWidth);
    const middleY = (y1 + y2) / 2 + (varY * SpriteHeight);

    const middleXBefore = middleX - (middleX % SpriteWidth);
    const middleXAfter =  middleX + (middleX % SpriteWidth);
    const middleYBefore = middleY - (middleY % SpriteHeight);
    const middleYAfter = middleY + (middleY % SpriteHeight);
    if(division > 1) {
      this.createRandomLine(x1, y1, middleXBefore, middleYBefore, division - 1, varX, varY);
      this.createRandomLine(middleXAfter, middleYAfter, x2, y2, division - 1, varX, varY);
    } else {
      this.createLine(x1,y1, middleXBefore, middleYBefore);
      this.createLine(middleXAfter, middleYAfter, x2, y2);
    }
  }

  createLineByTile(x1, y1, nbTilesX, nbTilesY, division, varX = 0, varY = 0) {
    if(nbTilesX < 0 ) {
      throw `createLineByTile ${nbTilesX} is negative`;
    }
    if(nbTilesY < 0 ) {
      throw `createLineByTile ${nbTilesY} is negative`;
    }
    this.createRandomLine(x1, y1, (nbTilesX-1) * SpriteWidth + x1 , (nbTilesY-1) * SpriteHeight + y1, division, varX, varY);
  }

  // //Brasenhem algorithm
  createLine(x1,y1, x2, y2) {
    const dx = Math.abs(x2 - x1);
    const sx = x1 < x2 ? SpriteWidth : -SpriteWidth;
    const dy = Math.abs(y2 - y1);
    const sy = y1 < y2 ? SpriteHeight : -SpriteHeight;
    var err = (dx > dy ? dx : -dy) / 2;

    let x = x1;
    let y = y1;
    while (true) {
      this.createSprite(x,y);
      if (x >= x2 && y >= y2) break;
      if(x < 0 || y < 0 || x > Bounds || y > Bounds) break;
      let e2 = err;
      if (e2 > - dx) {
        err -= dy;
        x += sx;
      }
      if (e2 < dy) {
        err += dx;
        y += sy;
      }
    }
  }

  createSprite(x,y) {
    let sprite = this.create(x, y, Wall);
    sprite.scale.setTo(SpriteRatioX, SpriteRatioY);
  }

  ////
  //       ####
  //       #  #
  //       #  #
  //       #  #
  // (x,y) ####
  //
  ///
  createSquare(x, y, nbTilesBySide) {
    this.createRandomSquare(x, y, nbTilesBySide, 1, 0, 0);
  }

  // const division = 3;
  // const varX = -1;
  // const varY = 1;
  createRandomSquare(x, y, nbTilesBySide, division, varX, varY) {
    this.createLineByTile(x, y, nbTilesBySide, 1, division, varX, varY);
    this.createLineByTile(x, y + (nbTilesBySide-1) * SpriteHeight, nbTilesBySide, 1, division, varX, varY);

    //nbtiles - 2 because corner  was drawn  by vertical line
    this.createLineByTile(x, y + SpriteHeight, 1, nbTilesBySide - 2, division, varX, varY);
    this.createLineByTile(x + (nbTilesBySide-1) * SpriteWidth, y + SpriteHeight, 1, nbTilesBySide - 2, division, varX, varY);
  }
}

export default Room;<commit_msg>change some parameters....stil not perfect<commit_after>import { SpriteWidth, SpriteHeight, SpriteRatioX, SpriteRatioY, Bounds } from "../Constants.js";
import { Wall } from "../SpriteConstants";

const MaxX = 1;
const MaxY = 0;

class Room extends Phaser.Group {

  constructor(game, parent, name) {
    super(game, parent, name, false, false, Phaser.Physics.ARCADE);
  }

  createRandomLine(x1, y1, x2, y2, division = 1, varX = 0, varY = 0) {
    const middleX = (x1 + x2) / 2 + (varX * SpriteWidth);
    const middleY = (y1 + y2) / 2 + (varY * SpriteHeight);

    const middleXBefore = middleX - (middleX % SpriteWidth);
    const middleXAfter =  middleX + (middleX % SpriteWidth);
    const middleYBefore = middleY - (middleY % SpriteHeight);
    const middleYAfter = middleY + (middleY % SpriteHeight);
    if(division > 1) {
      this.createRandomLine(x1, y1, middleXBefore, middleYBefore, division - 1, varX, varY);
      this.createRandomLine(middleXAfter, middleYAfter, x2, y2, division - 1, varX, varY);
    } else {
      this.createLine(x1,y1, middleXBefore, middleYBefore);
      this.createLine(middleXAfter, middleYAfter, x2, y2);
    }
  }

  createLineByTile(x1, y1, nbTilesX, nbTilesY, division, varX, varY) {
    if(nbTilesX < 0 ) {
      throw `createLineByTile ${nbTilesX} is negative`;
    }
    if(nbTilesY < 0 ) {
      throw `createLineByTile ${nbTilesY} is negative`;
    }
    this.createRandomLine(x1, y1, (nbTilesX-1) * SpriteWidth + x1 , (nbTilesY-1) * SpriteHeight + y1, division, varX, varY);
  }

  // //Brasenhem algorithm
  createLine(x1,y1, x2, y2) {
    const dx = Math.abs(x2 - x1);
    const sx = x1 < x2 ? SpriteWidth : -SpriteWidth;
    const dy = Math.abs(y2 - y1);
    const sy = y1 < y2 ? SpriteHeight : -SpriteHeight;
    var err = (dx > dy ? dx : -dy) / 2;

    let x = x1;
    let y = y1;
    while (true) {
      this.createSprite(x,y);
      if (x >= x2 && y >= y2) break;
      if(x < 0 || y < 0 || x > Bounds || y > Bounds) break;
      let e2 = err;
      if (e2 > - dx) {
        err -= dy;
        x += sx;
      }
      if (e2 < dy) {
        err += dx;
        y += sy;
      }
    }
  }

  createSprite(x,y) {
    let sprite = this.create(x, y, Wall);
    sprite.scale.setTo(SpriteRatioX, SpriteRatioY);
  }

  ////
  // (x,y) ####
  //       #  #
  //       #  #
  //       #  #
  //       ####
  //
  ///
  createSquare(x, y, nbTilesBySide) {
    this.createRandomSquare(x, y, nbTilesBySide, 1, 0, 0);
  }

  // const division = 3;
  // const varX = -1;
  // const varY = 1;
  createRandomSquare(x, y, nbTilesBySide, division = 3, varX = -1, varY = 1) {
    this.createLineByTile(x, y, nbTilesBySide, 1, division, varX, varY);
    this.createLineByTile(x, y + (nbTilesBySide-1) * SpriteHeight, nbTilesBySide, 1, division, varX, varY);

    //nbtiles - 2 because corner  was drawn  by vertical line
    this.createLineByTile(x, y + SpriteHeight, 1, nbTilesBySide - 2, division, varX, varY);
    this.createLineByTile(x + (nbTilesBySide-1) * SpriteWidth, y + SpriteHeight, 1, nbTilesBySide - 2, division, varX, varY);
  }
}

export default Room;<|endoftext|>


<commit_before>// Create new object with same values, but remapped keys

'use strict';

var f       = require('../../Function/functionalize')
  , forEach = require('./for-each').call;

module.exports = f(function (callback, scope) {
	var o = {};
	forEach(this, function (value, key) {
		o[callback.call(this, key, value)] = value;
	}, scope);
	return o;
});
<commit_msg>keysMap should also pass scope object<commit_after>// Create new object with same values, but remapped keys

'use strict';

var f       = require('../../Function/functionalize')
  , forEach = require('./for-each').call;

module.exports = f(function (callback, scope) {
	var o = {};
	forEach(this, function (value, key) {
		o[callback.call(scope, key, value, this)] = value;
	}, this);
	return o;
});
<|endoftext|>


<commit_before>/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
 * full list of contributors). Published under the 2-clause BSD license.
 * See license.txt in the OpenLayers distribution or repository for the
 * full text of the license. */

/**
 * @requires OpenLayers/Layer/XYZ.js
 */

/**
 * Class: OpenLayers.Layer.Bing
 * Bing layer using direct tile access as provided by Bing Maps REST Services.
 * See http://msdn.microsoft.com/en-us/library/ff701713.aspx for more
 * information. Note: Terms of Service compliant use requires the map to be
 * configured with an <OpenLayers.Control.Attribution> control and the
 * attribution placed on or near the map.
 *
 * Inherits from:
 *  - <OpenLayers.Layer.XYZ>
 */
OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, {

    /**
     * Property: key
     * {String} API key for Bing maps, get your own key
     *     at http://bingmapsportal.com/ .
     */
    key: null,

    /**
     * Property: serverResolutions
     * {Array} the resolutions provided by the Bing servers.
     */
    serverResolutions: [
        156543.03390625, 78271.516953125, 39135.7584765625,
        19567.87923828125, 9783.939619140625, 4891.9698095703125,
        2445.9849047851562, 1222.9924523925781, 611.4962261962891,
        305.74811309814453, 152.87405654907226, 76.43702827453613,
        38.218514137268066, 19.109257068634033, 9.554628534317017,
        4.777314267158508, 2.388657133579254, 1.194328566789627,
        0.5971642833948135, 0.29858214169740677, 0.14929107084870338,
        0.07464553542435169
    ],

    /**
     * Property: attributionTemplate
     * {String}
     */
    attributionTemplate: '' +
         '
' +
         '
${copyrights}' +
         '' +
         'Terms of Use',

    /**
     * Property: metadata
     * {Object} Metadata for this layer, as returned by the callback script
     */
    metadata: null,

    /**
     * Property: protocolRegex
     * {RegExp} Regular expression to match and replace http: in bing urls
     */
    protocolRegex: /^http:/i,

    /**
     * APIProperty: type
     * {String} The layer identifier.  Any non-birdseye imageryType
     *     from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be
     *     used.  Default is "Road".
     */
    type: "Road",

    /**
     * APIProperty: culture
     * {String} The culture identifier.  See http://msdn.microsoft.com/en-us/library/ff701709.aspx
     * for the definition and the possible values.  Default is "en-US".
     */
    culture: "en-US",

    /**
     * APIProperty: metadataParams
     * {Object} Optional url parameters for the Get Imagery Metadata request
     * as described here: http://msdn.microsoft.com/en-us/library/ff701716.aspx
     */
    metadataParams: null,

    /** APIProperty: tileOptions
     *  {Object} optional configuration options for <OpenLayers.Tile> instances
     *  created by this Layer. Default is
     *
     *  (code)
     *  {crossOriginKeyword: 'anonymous'}
     *  (end)
     */
    tileOptions: null,

    /** APIProperty: protocol
     *  {String} Protocol to use to fetch Imagery Metadata, tiles and bing logo
     *  Can be 'http:' 'https:' or ''
     *
     *  Warning: tiles may not be available under both HTTP and HTTPS protocols.
     *  Microsoft approved use of both HTTP and HTTPS urls for tiles. However
     *  this is undocumented and the Imagery Metadata API always returns HTTP
     *  urls.
     *
     *  Default is '', unless when executed from a file:/// uri, in which case
     *  it is 'http:'.
     */
    protocol: ~window.location.href.indexOf('http') ? '' : 'http:',

    /**
     * Constructor: OpenLayers.Layer.Bing
     * Create a new Bing layer.
     *
     * Example:
     * (code)
     * var road = new OpenLayers.Layer.Bing({
     *     name: "My Bing Aerial Layer",
     *     type: "Aerial",
     *     key: "my-api-key-here",
     * });
     * (end)
     *
     * Parameters:
     * options - {Object} Configuration properties for the layer.
     *
     * Required configuration properties:
     * key - {String} Bing Maps API key for your application. Get one at
     *     http://bingmapsportal.com/.
     * type - {String} The layer identifier.  Any non-birdseye imageryType
     *     from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be
     *     used.
     *
     * Any other documented layer properties can be provided in the config object.
     */
    initialize: function(options) {
        options = OpenLayers.Util.applyDefaults({
            sphericalMercator: true
        }, options);
        var name = options.name || "Bing " + (options.type || this.type);

        var newArgs = [name, null, options];
        OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArgs);
        this.tileOptions = OpenLayers.Util.extend({
            crossOriginKeyword: 'anonymous'
        }, this.options.tileOptions);
        this.loadMetadata();
    },

    /**
     * Method: loadMetadata
     */
    loadMetadata: function() {
        this._callbackId = "_callback_" + this.id.replace(/\./g, "_");
        // link the processMetadata method to the global scope and bind it
        // to this instance
        window[this._callbackId] = OpenLayers.Function.bind(
            OpenLayers.Layer.Bing.processMetadata, this
        );
        var params = OpenLayers.Util.applyDefaults({
            key: this.key,
            jsonp: this._callbackId,
            include: "ImageryProviders"
        }, this.metadataParams);
        var url = this.protocol + "//dev.virtualearth.net/REST/v1/Imagery/Metadata/" +
            this.type + "?" + OpenLayers.Util.getParameterString(params);
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = url;
        script.id = this._callbackId;
        document.getElementsByTagName("head")[0].appendChild(script);
    },

    /**
     * Method: initLayer
     *
     * Sets layer properties according to the metadata provided by the API
     */
    initLayer: function() {
        var res = this.metadata.resourceSets[0].resources[0];
        var url = res.imageUrl.replace("{quadkey}", "${quadkey}");
        url = url.replace("{culture}", this.culture);
        url = url.replace(this.protocolRegex, this.protocol);
        this.url = [];
        for (var i=0; i<res.imageUrlSubdomains.length; ++i) {
            this.url.push(url.replace("{subdomain}", res.imageUrlSubdomains[i]));
        }
        this.addOptions({
            maxResolution: Math.min(
                this.serverResolutions[res.zoomMin],
                this.maxResolution || Number.POSITIVE_INFINITY
            ),
            numZoomLevels: Math.min(
                res.zoomMax + 1 - res.zoomMin, this.numZoomLevels
            )
        }, true);
        if (!this.isBaseLayer) {
            this.redraw();
        }
        this.updateAttribution();
    },

    /**
     * Method: getURL
     *
     * Paramters:
     * bounds - {<OpenLayers.Bounds>}
     */
    getURL: function(bounds) {
        if (!this.url) {
            return;
        }
        var xyz = this.getXYZ(bounds), x = xyz.x, y = xyz.y, z = xyz.z;
        var quadDigits = [];
        for (var i = z; i > 0; --i) {
            var digit = '0';
            var mask = 1 << (i - 1);
            if ((x & mask) != 0) {
                digit++;
            }
            if ((y & mask) != 0) {
                digit++;
                digit++;
            }
            quadDigits.push(digit);
        }
        var quadKey = quadDigits.join("");
        var url = this.selectUrl('' + x + y + z, this.url);

        return OpenLayers.String.format(url, {'quadkey': quadKey});
    },

    /**
     * Method: updateAttribution
     * Updates the attribution according to the requirements outlined in
     * http://gis.638310.n2.nabble.com/Bing-imagery-td5789168.html
     */
    updateAttribution: function() {
        var metadata = this.metadata;
        if (!metadata.resourceSets || !this.map || !this.map.center) {
            return;
        }
        var res = metadata.resourceSets[0].resources[0];
        var extent = this.map.getExtent().transform(
            this.map.getProjectionObject(),
            new OpenLayers.Projection("EPSG:4326")
        );
        var providers = res.imageryProviders || [],
            zoom = OpenLayers.Util.indexOf(this.serverResolutions,
                                           this.getServerResolution()),
            copyrights = "", provider, i, ii, j, jj, bbox, coverage;
        for (i=0,ii=providers.length; i<ii; ++i) {
            provider = providers[i];
            for (j=0,jj=provider.coverageAreas.length; j<jj; ++j) {
                coverage = provider.coverageAreas[j];
                // axis order provided is Y,X
                bbox = OpenLayers.Bounds.fromArray(coverage.bbox, true);
                if (extent.intersectsBounds(bbox) &&
                        zoom <= coverage.zoomMax && zoom >= coverage.zoomMin) {
                    copyrights += provider.attribution + " ";
                }
            }
        }
        var logo = metadata.brandLogoUri.replace(this.protocolRegex, this.protocol);
        this.attribution = OpenLayers.String.format(this.attributionTemplate, {
            type: this.type.toLowerCase(),
            logo: logo,
            copyrights: copyrights
        });
        this.map && this.map.events.triggerEvent("changelayer", {
            layer: this,
            property: "attribution"
        });
    },

    /**
     * Method: setMap
     */
    setMap: function() {
        OpenLayers.Layer.XYZ.prototype.setMap.apply(this, arguments);
        this.map.events.register("moveend", this, this.updateAttribution);
    },

    /**
     * APIMethod: clone
     *
     * Parameters:
     * obj - {Object}
     *
     * Returns:
     * {<OpenLayers.Layer.Bing>} An exact clone of this <OpenLayers.Layer.Bing>
     */
    clone: function(obj) {
        if (obj == null) {
            obj = new OpenLayers.Layer.Bing(this.options);
        }
        //get all additions from superclasses
        obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
        // copy/set any non-init, non-simple values here
        return obj;
    },

    /**
     * Method: destroy
     */
    destroy: function() {
        this.map &&
            this.map.events.unregister("moveend", this, this.updateAttribution);
        OpenLayers.Layer.XYZ.prototype.destroy.apply(this, arguments);
    },

    CLASS_NAME: "OpenLayers.Layer.Bing"
});

/**
 * Function: OpenLayers.Layer.Bing.processMetadata
 * This function will be bound to an instance, linked to the global scope with
 * an id, and called by the JSONP script returned by the API.
 *
 * Parameters:
 * metadata - {Object} metadata as returned by the API
 */
OpenLayers.Layer.Bing.processMetadata = function(metadata) {
    this.metadata = metadata;
    this.initLayer();
    var script = document.getElementById(this._callbackId);
    script.parentNode.removeChild(script);
    window[this._callbackId] = undefined; // cannot delete from window in IE
    delete this._callbackId;
};
<commit_msg>Update serverResolutions<commit_after>/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
 * full list of contributors). Published under the 2-clause BSD license.
 * See license.txt in the OpenLayers distribution or repository for the
 * full text of the license. */

/**
 * @requires OpenLayers/Layer/XYZ.js
 */

/**
 * Class: OpenLayers.Layer.Bing
 * Bing layer using direct tile access as provided by Bing Maps REST Services.
 * See http://msdn.microsoft.com/en-us/library/ff701713.aspx for more
 * information. Note: Terms of Service compliant use requires the map to be
 * configured with an <OpenLayers.Control.Attribution> control and the
 * attribution placed on or near the map.
 *
 * Inherits from:
 *  - <OpenLayers.Layer.XYZ>
 */
OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, {

    /**
     * Property: key
     * {String} API key for Bing maps, get your own key
     *     at http://bingmapsportal.com/ .
     */
    key: null,

    /**
     * Property: serverResolutions
     * {Array} the resolutions provided by the Bing servers.
     */
    serverResolutions: [
        156543.03390625, 78271.516953125, 39135.7584765625,
        19567.87923828125, 9783.939619140625, 4891.9698095703125,
        2445.9849047851562, 1222.9924523925781, 611.4962261962891,
        305.74811309814453, 152.87405654907226, 76.43702827453613,
        38.218514137268066, 19.109257068634033, 9.554628534317017,
        4.777314267158508, 2.388657133579254, 1.194328566789627,
        0.5971642833948135, 0.29858214169740677, 0.14929107084870338,
        0.07464553542435169, 0.03732276771218, 0.01866138385609
    ],

    /**
     * Property: attributionTemplate
     * {String}
     */
    attributionTemplate: '' +
         '
' +
         '
${copyrights}' +
         '' +
         'Terms of Use',

    /**
     * Property: metadata
     * {Object} Metadata for this layer, as returned by the callback script
     */
    metadata: null,

    /**
     * Property: protocolRegex
     * {RegExp} Regular expression to match and replace http: in bing urls
     */
    protocolRegex: /^http:/i,

    /**
     * APIProperty: type
     * {String} The layer identifier.  Any non-birdseye imageryType
     *     from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be
     *     used.  Default is "Road".
     */
    type: "Road",

    /**
     * APIProperty: culture
     * {String} The culture identifier.  See http://msdn.microsoft.com/en-us/library/ff701709.aspx
     * for the definition and the possible values.  Default is "en-US".
     */
    culture: "en-US",

    /**
     * APIProperty: metadataParams
     * {Object} Optional url parameters for the Get Imagery Metadata request
     * as described here: http://msdn.microsoft.com/en-us/library/ff701716.aspx
     */
    metadataParams: null,

    /** APIProperty: tileOptions
     *  {Object} optional configuration options for <OpenLayers.Tile> instances
     *  created by this Layer. Default is
     *
     *  (code)
     *  {crossOriginKeyword: 'anonymous'}
     *  (end)
     */
    tileOptions: null,

    /** APIProperty: protocol
     *  {String} Protocol to use to fetch Imagery Metadata, tiles and bing logo
     *  Can be 'http:' 'https:' or ''
     *
     *  Warning: tiles may not be available under both HTTP and HTTPS protocols.
     *  Microsoft approved use of both HTTP and HTTPS urls for tiles. However
     *  this is undocumented and the Imagery Metadata API always returns HTTP
     *  urls.
     *
     *  Default is '', unless when executed from a file:/// uri, in which case
     *  it is 'http:'.
     */
    protocol: ~window.location.href.indexOf('http') ? '' : 'http:',

    /**
     * Constructor: OpenLayers.Layer.Bing
     * Create a new Bing layer.
     *
     * Example:
     * (code)
     * var road = new OpenLayers.Layer.Bing({
     *     name: "My Bing Aerial Layer",
     *     type: "Aerial",
     *     key: "my-api-key-here",
     * });
     * (end)
     *
     * Parameters:
     * options - {Object} Configuration properties for the layer.
     *
     * Required configuration properties:
     * key - {String} Bing Maps API key for your application. Get one at
     *     http://bingmapsportal.com/.
     * type - {String} The layer identifier.  Any non-birdseye imageryType
     *     from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be
     *     used.
     *
     * Any other documented layer properties can be provided in the config object.
     */
    initialize: function(options) {
        options = OpenLayers.Util.applyDefaults({
            sphericalMercator: true
        }, options);
        var name = options.name || "Bing " + (options.type || this.type);

        var newArgs = [name, null, options];
        OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArgs);
        this.tileOptions = OpenLayers.Util.extend({
            crossOriginKeyword: 'anonymous'
        }, this.options.tileOptions);
        this.loadMetadata();
    },

    /**
     * Method: loadMetadata
     */
    loadMetadata: function() {
        this._callbackId = "_callback_" + this.id.replace(/\./g, "_");
        // link the processMetadata method to the global scope and bind it
        // to this instance
        window[this._callbackId] = OpenLayers.Function.bind(
            OpenLayers.Layer.Bing.processMetadata, this
        );
        var params = OpenLayers.Util.applyDefaults({
            key: this.key,
            jsonp: this._callbackId,
            include: "ImageryProviders"
        }, this.metadataParams);
        var url = this.protocol + "//dev.virtualearth.net/REST/v1/Imagery/Metadata/" +
            this.type + "?" + OpenLayers.Util.getParameterString(params);
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = url;
        script.id = this._callbackId;
        document.getElementsByTagName("head")[0].appendChild(script);
    },

    /**
     * Method: initLayer
     *
     * Sets layer properties according to the metadata provided by the API
     */
    initLayer: function() {
        var res = this.metadata.resourceSets[0].resources[0];
        var url = res.imageUrl.replace("{quadkey}", "${quadkey}");
        url = url.replace("{culture}", this.culture);
        url = url.replace(this.protocolRegex, this.protocol);
        this.url = [];
        for (var i=0; i<res.imageUrlSubdomains.length; ++i) {
            this.url.push(url.replace("{subdomain}", res.imageUrlSubdomains[i]));
        }
        this.addOptions({
            maxResolution: Math.min(
                this.serverResolutions[res.zoomMin],
                this.maxResolution || Number.POSITIVE_INFINITY
            ),
            numZoomLevels: Math.min(
                res.zoomMax + 1 - res.zoomMin, this.numZoomLevels
            )
        }, true);
        if (!this.isBaseLayer) {
            this.redraw();
        }
        this.updateAttribution();
    },

    /**
     * Method: getURL
     *
     * Paramters:
     * bounds - {<OpenLayers.Bounds>}
     */
    getURL: function(bounds) {
        if (!this.url) {
            return;
        }
        var xyz = this.getXYZ(bounds), x = xyz.x, y = xyz.y, z = xyz.z;
        var quadDigits = [];
        for (var i = z; i > 0; --i) {
            var digit = '0';
            var mask = 1 << (i - 1);
            if ((x & mask) != 0) {
                digit++;
            }
            if ((y & mask) != 0) {
                digit++;
                digit++;
            }
            quadDigits.push(digit);
        }
        var quadKey = quadDigits.join("");
        var url = this.selectUrl('' + x + y + z, this.url);

        return OpenLayers.String.format(url, {'quadkey': quadKey});
    },

    /**
     * Method: updateAttribution
     * Updates the attribution according to the requirements outlined in
     * http://gis.638310.n2.nabble.com/Bing-imagery-td5789168.html
     */
    updateAttribution: function() {
        var metadata = this.metadata;
        if (!metadata.resourceSets || !this.map || !this.map.center) {
            return;
        }
        var res = metadata.resourceSets[0].resources[0];
        var extent = this.map.getExtent().transform(
            this.map.getProjectionObject(),
            new OpenLayers.Projection("EPSG:4326")
        );
        var providers = res.imageryProviders || [],
            zoom = OpenLayers.Util.indexOf(this.serverResolutions,
                                           this.getServerResolution()),
            copyrights = "", provider, i, ii, j, jj, bbox, coverage;
        for (i=0,ii=providers.length; i<ii; ++i) {
            provider = providers[i];
            for (j=0,jj=provider.coverageAreas.length; j<jj; ++j) {
                coverage = provider.coverageAreas[j];
                // axis order provided is Y,X
                bbox = OpenLayers.Bounds.fromArray(coverage.bbox, true);
                if (extent.intersectsBounds(bbox) &&
                        zoom <= coverage.zoomMax && zoom >= coverage.zoomMin) {
                    copyrights += provider.attribution + " ";
                }
            }
        }
        var logo = metadata.brandLogoUri.replace(this.protocolRegex, this.protocol);
        this.attribution = OpenLayers.String.format(this.attributionTemplate, {
            type: this.type.toLowerCase(),
            logo: logo,
            copyrights: copyrights
        });
        this.map && this.map.events.triggerEvent("changelayer", {
            layer: this,
            property: "attribution"
        });
    },

    /**
     * Method: setMap
     */
    setMap: function() {
        OpenLayers.Layer.XYZ.prototype.setMap.apply(this, arguments);
        this.map.events.register("moveend", this, this.updateAttribution);
    },

    /**
     * APIMethod: clone
     *
     * Parameters:
     * obj - {Object}
     *
     * Returns:
     * {<OpenLayers.Layer.Bing>} An exact clone of this <OpenLayers.Layer.Bing>
     */
    clone: function(obj) {
        if (obj == null) {
            obj = new OpenLayers.Layer.Bing(this.options);
        }
        //get all additions from superclasses
        obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
        // copy/set any non-init, non-simple values here
        return obj;
    },

    /**
     * Method: destroy
     */
    destroy: function() {
        this.map &&
            this.map.events.unregister("moveend", this, this.updateAttribution);
        OpenLayers.Layer.XYZ.prototype.destroy.apply(this, arguments);
    },

    CLASS_NAME: "OpenLayers.Layer.Bing"
});

/**
 * Function: OpenLayers.Layer.Bing.processMetadata
 * This function will be bound to an instance, linked to the global scope with
 * an id, and called by the JSONP script returned by the API.
 *
 * Parameters:
 * metadata - {Object} metadata as returned by the API
 */
OpenLayers.Layer.Bing.processMetadata = function(metadata) {
    this.metadata = metadata;
    this.initLayer();
    var script = document.getElementById(this._callbackId);
    script.parentNode.removeChild(script);
    window[this._callbackId] = undefined; // cannot delete from window in IE
    delete this._callbackId;
};
<|endoftext|>


<commit_before>shellHelper.grep = function (cmd) {
	var hlStart = "\033[01;31m\033[K";   // red
	var hlEnd = "\033[m\033[K";          // clear

	var flags = "g";
	var negate = false;

	// parse options/pattern

	try {
		// do this properly with https://github.com/substack/node-shell-quote
		// FIXME: still doesn't work in common cases, because the parser output ends up like:
		// [ ": false", "db.getParameter", { "op" : "(" }, { "op" : ")" } ]
		var parse = require('shell-quote').parse;
		var parser = function (str) {
			return parse(str);
		};
	} catch (e) {
		// crappy fallback
		print("grep: Warning: Unable to load `shell-quote` module");
		var parser = function (str) {
			return str.split(" ");
		};
	}
	var words = parser(cmd);

	var i = 0;
	while (i < words.length) {
		if (words[i] == "-i") {
			flags += "i";
		} else if (words[i] == "-v") {
			negate = true;
		// FIXME: -c
		// FIXME: --color/--nocolor
		// FIXME: -m
		// FIXME: -n
		// FIXME: -A/-B/-C would be awesome
		} else if (words[i] == "--") {
			i++; // eat the "--"
			break;
		} else if (words[i][0] != "-") {
			break;
		}
		i++;
	}
	// next word is the pattern
	var patternStr = words[i];
	i++;

	// get rid of the first i words, what's left is the actual cmd to run
	var prefix = "";
	for (var j = 0; j < i; j++) {
		prefix += words[j] + "  *";
	}
	cmd = cmd.replace(new RegExp(prefix), "");

	var pattern = new RegExp(patternStr, flags);

	var lines = print.captureAllOutput(function () { shellPrint(eval(cmd)) }).output;
	for (var l in lines) {
		var line = lines[l];
		var found = false;
		var highlighted = line.replace(pattern, function (match) { found = true; return hlStart + match + hlEnd; });
		if ( (!negate && found) || (negate && !found) ) {
			print(highlighted);
		}
	}
};

<commit_msg>Anonymous namespace for grep<commit_after>shellHelper.grep = (function () {

return function (cmd) {
	var hlStart = "\033[01;31m\033[K";   // red
	var hlEnd = "\033[m\033[K";          // clear

	var flags = "g";
	var negate = false;

	// parse options/pattern

	try {
		// do this properly with https://github.com/substack/node-shell-quote
		// FIXME: still doesn't work in common cases, because the parser output ends up like:
		// [ ": false", "db.getParameter", { "op" : "(" }, { "op" : ")" } ]
		var parse = require('shell-quote').parse;
		var parser = function (str) {
			return parse(str);
		};
	} catch (e) {
		// crappy fallback
		print("grep: Warning: Unable to load `shell-quote` module");
		var parser = function (str) {
			return str.split(" ");
		};
	}
	var words = parser(cmd);

	var i = 0;
	while (i < words.length) {
		if (words[i] == "-i") {
			flags += "i";
		} else if (words[i] == "-v") {
			negate = true;
		// FIXME: -c
		// FIXME: --color/--nocolor
		// FIXME: -m
		// FIXME: -n
		// FIXME: -A/-B/-C would be awesome
		} else if (words[i] == "--") {
			i++; // eat the "--"
			break;
		} else if (words[i][0] != "-") {
			break;
		}
		i++;
	}
	// next word is the pattern
	var patternStr = words[i];
	i++;

	// get rid of the first i words, what's left is the actual cmd to run
	var prefix = "";
	for (var j = 0; j < i; j++) {
		prefix += words[j] + "  *";
	}
	cmd = cmd.replace(new RegExp(prefix), "");

	var pattern = new RegExp(patternStr, flags);

	var lines = print.captureAllOutput(function () { shellPrint(eval(cmd)) }).output;
	for (var l in lines) {
		var line = lines[l];
		var found = false;
		var highlighted = line.replace(pattern, function (match) { found = true; return hlStart + match + hlEnd; });
		if ( (!negate && found) || (negate && !found) ) {
			print(highlighted);
		}
	}
};

})();

<|endoftext|>


<commit_before>import BaseLfo from '../core/BaseLfo';
import initWindow from '../utils/windows';
import parameters from 'parameters';

// https://code.soundsoftware.ac.uk/projects/js-dsp-test/repository/entry/fft/nayuki-obj/fft.js
/*
 * Free FFT and convolution (JavaScript)
 *
 * Copyright (c) 2014 Project Nayuki
 * http://www.nayuki.io/page/free-small-fft-in-multiple-languages
 *
 * (MIT License)
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * - The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 * - The Software is provided "as is", without warranty of any kind, express or
 *   implied, including but not limited to the warranties of merchantability,
 *   fitness for a particular purpose and noninfringement. In no event shall the
 *   authors or copyright holders be liable for any claim, damages or other
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 *   out of or in connection with the Software or the use or other dealings in the
 *   Software.
 *
 * Slightly restructured by Chris Cannam, cannam@all-day-breakfast.com
 *
 * @private
 */
/*
 * Construct an object for calculating the discrete Fourier transform (DFT) of
 * size n, where n is a power of 2.
 *
 * @private
 */
function FFTNayuki(n) {

  this.n = n;
  this.levels = -1;

  for (var i = 0; i < 32; i++) {
    if (1 << i == n) {
      this.levels = i;  // Equal to log2(n)
    }
  }

  if (this.levels == -1) {
    throw "Length is not a power of 2";
  }

  this.cosTable = new Array(n / 2);
  this.sinTable = new Array(n / 2);

  for (var i = 0; i < n / 2; i++) {
    this.cosTable[i] = Math.cos(2 * Math.PI * i / n);
    this.sinTable[i] = Math.sin(2 * Math.PI * i / n);
  }

  /*
   * Computes the discrete Fourier transform (DFT) of the given complex vector,
   * storing the result back into the vector.
   * The vector's length must be equal to the size n that was passed to the
   * object constructor, and this must be a power of 2. Uses the Cooley-Tukey
   * decimation-in-time radix-2 algorithm.
   *
   * @private
   */
  this.forward = function(real, imag) {
    var n = this.n;

    // Bit-reversed addressing permutation
    for (var i = 0; i < n; i++) {
      var j = reverseBits(i, this.levels);

      if (j > i) {
        var temp = real[i];
        real[i] = real[j];
        real[j] = temp;
        temp = imag[i];
        imag[i] = imag[j];
        imag[j] = temp;
      }
    }

    // Cooley-Tukey decimation-in-time radix-2 FFT
    for (var size = 2; size <= n; size *= 2) {
      var halfsize = size / 2;
      var tablestep = n / size;

      for (var i = 0; i < n; i += size) {
        for (var j = i, k = 0; j < i + halfsize; j++, k += tablestep) {
          var tpre =  real[j+halfsize] * this.cosTable[k] +
                      imag[j+halfsize] * this.sinTable[k];
          var tpim = -real[j+halfsize] * this.sinTable[k] +
                      imag[j+halfsize] * this.cosTable[k];
          real[j + halfsize] = real[j] - tpre;
          imag[j + halfsize] = imag[j] - tpim;
          real[j] += tpre;
          imag[j] += tpim;
        }
      }
    }

    // Returns the integer whose value is the reverse of the lowest 'bits'
    // bits of the integer 'x'.
    function reverseBits(x, bits) {
      var y = 0;

      for (var i = 0; i < bits; i++) {
        y = (y << 1) | (x & 1);
        x >>>= 1;
      }

      return y;
    }
  }

  /*
   * Computes the inverse discrete Fourier transform (IDFT) of the given complex
   * vector, storing the result back into the vector.
   * The vector's length must be equal to the size n that was passed to the
   * object constructor, and this must be a power of 2. This is a wrapper
   * function. This transform does not perform scaling, so the inverse is not
   * a true inverse.
   *
   * @private
   */
  this.inverse = function(real, imag) {
    forward(imag, real);
  }
}

const sqrt = Math.sqrt;

const isPowerOfTwo = function(number) {
  while ((number % 2 === 0) && number > 1)
    number = number / 2;

  return number === 1;
}

const definitions = {
  size: {
    type: 'integer',
    default: 1024,
    metas: { kind: 'static' },
  },
  window: {
    type: 'enum',
    list: ['none', 'hann', 'hanning', 'hamming', 'blackman', 'blackmanharris', 'sine', 'rectangle'],
    default: 'none',
    metas: { kind: 'static' },
  },
  mode: {
    type: 'enum',
    list: ['magnitude', 'power'], // add complex output
    default: 'magnitude',
  },
  norm: {
    type: 'enum',
    default: 'auto',
    list: ['auto', 'none', 'linear', 'power'],
  },
}

/**
 * Perfom a Fast Fourier Transform on the incomming signal.
 * This node is based on the [FFT implementation by Nayuki](https://code.soundsoftware.ac.uk/projects/js-dsp-test/repository/entry/fft/nayuki-obj/fft.js)
 *
 * @memberof module:operator
 *
 * @param {Object} options - Override default parameters.
 * @param {Number} [options.size=1024] - Size of the fft, should be a power of
 *  2. If the the frame size of the incomming signal is lower than this value,
 *  it is zero padded to match the fft size.
 * @param {String} [options.window='none'] - Name of the window applied on the
 *  incomming signal. Available windows are: 'none', 'hann', 'hanning',
 *  'hamming', 'blackman', 'blackmanharris', 'sine', 'rectangle'.
 * @param {String} [options.mode='magnitude'] - Type of the output (`magnitude`
 *  or `power`)
 * @param {String} [options.norm='auto'] - Type of normalization applied on the
 *  output. Possible values are 'auto', 'none', 'linear', 'power'. When set to
 *  `auto`, a `linear` normalization is applied on the magnitude spectrum, while
 *  a `power` normalizetion is applied on the power spectrum.
 *
 * @example
 * // assuming an `audioBuffer` exists
 * const source = new AudioInBuffer({ audioBuffer });
 *
 * const slicer = new Slicer({
 *   frameSize: 256,
 * });
 *
 * const fft = new FFT({
 *   mode: 'power',
 *   window: 'hann',
 *   norm: 'power',
 *   size: 256,
 * });
 *
 * source.connect(slicer);
 * slicer.connect(fft);
 * source.start();
 *
 * // > outputs 129 bins containing the values of the power spectrum (including
 * // > DC and Nyuist frequencies).
 *
 * @todo - check if 'rectangle' and 'none' windows are not redondant.
 * @todo - check default values for all params.
 */
class FFT extends BaseLfo {
  constructor(options) {
    super();

    this.params = parameters(definitions, options);

    this.windowSize = null;
    this.normalizeCoefs = null;
    this.window = null;
    this.real = null;
    this.imag = null;
    this.fft = null;

    if (!isPowerOfTwo(this.params.get('size')))
      throw new Error('fftSize must be a power of two');
  }

  /** @private */
  processStreamParams(prevStreamParams) {
    this.prepareStreamParams(prevStreamParams);
    // set the output frame size
    const inFrameSize = prevStreamParams.frameSize;
    const fftSize = this.params.get('size');
    const mode = this.params.get('mode');
    const norm = this.params.get('norm');
    const windowName = this.params.get('window');

    this.streamParams.frameSize = fftSize / 2 + 1;
    this.streamParams.frameType = 'vector';
    this.streamParams.description = [];
    // size of the window to apply on the input frame
    this.windowSize = (inFrameSize < fftSize) ? inFrameSize : fftSize;

    // references to populate in the window functions (cf. `initWindow`)
    this.normalizeCoefs = { linear: 0, power: 0 };
    this.window = new Float32Array(this.windowSize);

    if (windowName !== 'none') {
      initWindow(
        windowName, // name of the window
        this.window, // buffer populated with the window signal
        this.windowSize, // size of the window
        this.normalizeCoefs // object populated with the normalization coefs
      );
    } else {
      this.window.fill(1);
    }

    const { linear, power } = this.normalizeCoefs;

    switch (norm) {
      case 'none':
        this.windowNorm = 1;
        break;

      case 'linear':
        this.windowNorm = linear;
        break;

      case 'power':
        this.windowNorm = power;
        break;

      case 'auto':
        if (mode === 'magnitude')
          this.windowNorm = linear;
        else if (mode === 'power')
          this.windowNorm = power;
        else
          this.windowNorm = 1;

        break;
    }

    this.real = new Float32Array(fftSize);
    this.imag = new Float32Array(fftSize);
    this.fft = new FFTNayuki(fftSize);

    this.propagateStreamParams();
  }

  /** @private */
  inputSignal(signal) {
    const mode = this.params.get('mode');
    const windowSize = this.windowSize;
    const frameSize = this.streamParams.frameSize;
    const fftSize = this.params.get('size');
    const outData = this.frame.data;

    // apply window on the input signal and reset imag buffer
    for (let i = 0; i < windowSize; i++) {
      this.real[i] = signal[i] * this.window[i] * this.windowNorm;
      this.imag[i] = 0;
    }

    // if real is bigger than input signal, fill with zeros
    for (let i = windowSize; i < fftSize; i++) {
      this.real[i] = 0;
      this.imag[i] = 0;
    }

    this.fft.forward(this.real, this.imag);

    if (mode === 'magnitude') {
      const norm = 1 / fftSize;

      // DC index
      const realDc = this.real[0];
      const imagDc = this.imag[0];
      outData[0] = sqrt(realDc * realDc + imagDc * imagDc) * norm;

      // Nquyst index
      const realNy = this.real[fftSize / 2];
      const imagNy = this.imag[fftSize / 2];
      outData[fftSize / 2] = sqrt(realNy * realNy + imagNy * imagNy) * norm;

      // power spectrum
      for (let i = 1, j = fftSize - 1; i < fftSize / 2; i++, j--) {
        const real = 0.5 * (this.real[i] + this.real[j]);
        const imag = 0.5 * (this.imag[i] - this.imag[j]);

        outData[i] = 2 * sqrt(real * real + imag * imag) * norm;
      }

    } else if (mode === 'power') {
      const norm = 1 / (fftSize * fftSize);

      // DC index
      const realDc = this.real[0];
      const imagDc = this.imag[0];
      outData[0] = (realDc * realDc + imagDc * imagDc) * norm;

      // Nquyst index
      const realNy = this.real[fftSize / 2];
      const imagNy = this.imag[fftSize / 2];
      outData[fftSize / 2] = (realNy * realNy + imagNy * imagNy) * norm;

      // power spectrum
      for (let i = 1, j = fftSize - 1; i < fftSize / 2; i++, j--) {
        const real = 0.5 * (this.real[i] + this.real[j]);
        const imag = 0.5 * (this.imag[i] - this.imag[j]);

        outData[i] = 4 * (real * real + imag * imag) * norm;
      }
    }

    return outData;
  }

  /** @private */
  processSignal(frame) {
    this.inputSignal(frame.data);
  }
}

export default FFT;
<commit_msg>fixed rect/none windowing (to be confirmed)<commit_after>import BaseLfo from '../core/BaseLfo';
import initWindow from '../utils/windows';
import parameters from 'parameters';

// https://code.soundsoftware.ac.uk/projects/js-dsp-test/repository/entry/fft/nayuki-obj/fft.js
/*
 * Free FFT and convolution (JavaScript)
 *
 * Copyright (c) 2014 Project Nayuki
 * http://www.nayuki.io/page/free-small-fft-in-multiple-languages
 *
 * (MIT License)
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * - The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 * - The Software is provided "as is", without warranty of any kind, express or
 *   implied, including but not limited to the warranties of merchantability,
 *   fitness for a particular purpose and noninfringement. In no event shall the
 *   authors or copyright holders be liable for any claim, damages or other
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 *   out of or in connection with the Software or the use or other dealings in the
 *   Software.
 *
 * Slightly restructured by Chris Cannam, cannam@all-day-breakfast.com
 *
 * @private
 */
/*
 * Construct an object for calculating the discrete Fourier transform (DFT) of
 * size n, where n is a power of 2.
 *
 * @private
 */
function FFTNayuki(n) {

  this.n = n;
  this.levels = -1;

  for (var i = 0; i < 32; i++) {
    if (1 << i == n) {
      this.levels = i;  // Equal to log2(n)
    }
  }

  if (this.levels == -1) {
    throw "Length is not a power of 2";
  }

  this.cosTable = new Array(n / 2);
  this.sinTable = new Array(n / 2);

  for (var i = 0; i < n / 2; i++) {
    this.cosTable[i] = Math.cos(2 * Math.PI * i / n);
    this.sinTable[i] = Math.sin(2 * Math.PI * i / n);
  }

  /*
   * Computes the discrete Fourier transform (DFT) of the given complex vector,
   * storing the result back into the vector.
   * The vector's length must be equal to the size n that was passed to the
   * object constructor, and this must be a power of 2. Uses the Cooley-Tukey
   * decimation-in-time radix-2 algorithm.
   *
   * @private
   */
  this.forward = function(real, imag) {
    var n = this.n;

    // Bit-reversed addressing permutation
    for (var i = 0; i < n; i++) {
      var j = reverseBits(i, this.levels);

      if (j > i) {
        var temp = real[i];
        real[i] = real[j];
        real[j] = temp;
        temp = imag[i];
        imag[i] = imag[j];
        imag[j] = temp;
      }
    }

    // Cooley-Tukey decimation-in-time radix-2 FFT
    for (var size = 2; size <= n; size *= 2) {
      var halfsize = size / 2;
      var tablestep = n / size;

      for (var i = 0; i < n; i += size) {
        for (var j = i, k = 0; j < i + halfsize; j++, k += tablestep) {
          var tpre =  real[j+halfsize] * this.cosTable[k] +
                      imag[j+halfsize] * this.sinTable[k];
          var tpim = -real[j+halfsize] * this.sinTable[k] +
                      imag[j+halfsize] * this.cosTable[k];
          real[j + halfsize] = real[j] - tpre;
          imag[j + halfsize] = imag[j] - tpim;
          real[j] += tpre;
          imag[j] += tpim;
        }
      }
    }

    // Returns the integer whose value is the reverse of the lowest 'bits'
    // bits of the integer 'x'.
    function reverseBits(x, bits) {
      var y = 0;

      for (var i = 0; i < bits; i++) {
        y = (y << 1) | (x & 1);
        x >>>= 1;
      }

      return y;
    }
  }

  /*
   * Computes the inverse discrete Fourier transform (IDFT) of the given complex
   * vector, storing the result back into the vector.
   * The vector's length must be equal to the size n that was passed to the
   * object constructor, and this must be a power of 2. This is a wrapper
   * function. This transform does not perform scaling, so the inverse is not
   * a true inverse.
   *
   * @private
   */
  this.inverse = function(real, imag) {
    forward(imag, real);
  }
}

const sqrt = Math.sqrt;

const isPowerOfTwo = function(number) {
  while ((number % 2 === 0) && number > 1)
    number = number / 2;

  return number === 1;
}

const definitions = {
  size: {
    type: 'integer',
    default: 1024,
    metas: { kind: 'static' },
  },
  window: {
    type: 'enum',
    list: ['none', 'hann', 'hanning', 'hamming', 'blackman', 'blackmanharris', 'sine', 'rectangle'],
    default: 'none',
    metas: { kind: 'static' },
  },
  mode: {
    type: 'enum',
    list: ['magnitude', 'power'], // add complex output
    default: 'magnitude',
  },
  norm: {
    type: 'enum',
    default: 'auto',
    list: ['auto', 'none', 'linear', 'power'],
  },
}

/**
 * Perfom a Fast Fourier Transform on the incomming signal.
 * This node is based on the [FFT implementation by Nayuki](https://code.soundsoftware.ac.uk/projects/js-dsp-test/repository/entry/fft/nayuki-obj/fft.js)
 *
 * @memberof module:operator
 *
 * @param {Object} options - Override default parameters.
 * @param {Number} [options.size=1024] - Size of the fft, should be a power of
 *  2. If the the frame size of the incomming signal is lower than this value,
 *  it is zero padded to match the fft size.
 * @param {String} [options.window='none'] - Name of the window applied on the
 *  incomming signal. Available windows are: 'none', 'hann', 'hanning',
 *  'hamming', 'blackman', 'blackmanharris', 'sine', 'rectangle'.
 * @param {String} [options.mode='magnitude'] - Type of the output (`magnitude`
 *  or `power`)
 * @param {String} [options.norm='auto'] - Type of normalization applied on the
 *  output. Possible values are 'auto', 'none', 'linear', 'power'. When set to
 *  `auto`, a `linear` normalization is applied on the magnitude spectrum, while
 *  a `power` normalizetion is applied on the power spectrum.
 *
 * @example
 * // assuming an `audioBuffer` exists
 * const source = new AudioInBuffer({ audioBuffer });
 *
 * const slicer = new Slicer({
 *   frameSize: 256,
 * });
 *
 * const fft = new FFT({
 *   mode: 'power',
 *   window: 'hann',
 *   norm: 'power',
 *   size: 256,
 * });
 *
 * source.connect(slicer);
 * slicer.connect(fft);
 * source.start();
 *
 * // > outputs 129 bins containing the values of the power spectrum (including
 * // > DC and Nyuist frequencies).
 *
 * @todo - check if 'rectangle' and 'none' windows are not redondant.
 * @todo - check default values for all params.
 */
class FFT extends BaseLfo {
  constructor(options) {
    super();

    this.params = parameters(definitions, options);

    this.windowSize = null;
    this.normalizeCoefs = null;
    this.window = null;
    this.real = null;
    this.imag = null;
    this.fft = null;

    if (!isPowerOfTwo(this.params.get('size')))
      throw new Error('fftSize must be a power of two');
  }

  /** @private */
  processStreamParams(prevStreamParams) {
    this.prepareStreamParams(prevStreamParams);
    // set the output frame size
    const inFrameSize = prevStreamParams.frameSize;
    const fftSize = this.params.get('size');
    const mode = this.params.get('mode');
    const norm = this.params.get('norm');
    let windowName = this.params.get('window');
    // window `none` and `rectangle` are aliases
    if (windowName === 'none')
      windowName = 'rectangle';

    this.streamParams.frameSize = fftSize / 2 + 1;
    this.streamParams.frameType = 'vector';
    this.streamParams.description = [];
    // size of the window to apply on the input frame
    this.windowSize = (inFrameSize < fftSize) ? inFrameSize : fftSize;

    // references to populate in the window functions (cf. `initWindow`)
    this.normalizeCoefs = { linear: 0, power: 0 };
    this.window = new Float32Array(this.windowSize);

    initWindow(
      windowName,         // name of the window
      this.window,        // buffer populated with the window signal
      this.windowSize,    // size of the window
      this.normalizeCoefs // object populated with the normalization coefs
    );

    const { linear, power } = this.normalizeCoefs;

    switch (norm) {
      case 'none':
        this.windowNorm = 1;
        break;

      case 'linear':
        this.windowNorm = linear;
        break;

      case 'power':
        this.windowNorm = power;
        break;

      case 'auto':
        if (mode === 'magnitude')
          this.windowNorm = linear;
        else if (mode === 'power')
          this.windowNorm = power;
        break;
    }

    this.real = new Float32Array(fftSize);
    this.imag = new Float32Array(fftSize);
    this.fft = new FFTNayuki(fftSize);

    this.propagateStreamParams();
  }

  /**
   * @todo
   */
  inputSignal(signal) {
    const mode = this.params.get('mode');
    const windowSize = this.windowSize;
    const frameSize = this.streamParams.frameSize;
    const fftSize = this.params.get('size');
    const outData = this.frame.data;

    // apply window on the input signal and reset imag buffer
    for (let i = 0; i < windowSize; i++) {
      this.real[i] = signal[i] * this.window[i] * this.windowNorm;
      this.imag[i] = 0;
    }

    // if real is bigger than input signal, fill with zeros
    for (let i = windowSize; i < fftSize; i++) {
      this.real[i] = 0;
      this.imag[i] = 0;
    }

    this.fft.forward(this.real, this.imag);

    if (mode === 'magnitude') {
      const norm = 1 / fftSize;

      // DC index
      const realDc = this.real[0];
      const imagDc = this.imag[0];
      outData[0] = sqrt(realDc * realDc + imagDc * imagDc) * norm;

      // Nquyst index
      const realNy = this.real[fftSize / 2];
      const imagNy = this.imag[fftSize / 2];
      outData[fftSize / 2] = sqrt(realNy * realNy + imagNy * imagNy) * norm;

      // power spectrum
      for (let i = 1, j = fftSize - 1; i < fftSize / 2; i++, j--) {
        const real = 0.5 * (this.real[i] + this.real[j]);
        const imag = 0.5 * (this.imag[i] - this.imag[j]);

        outData[i] = 2 * sqrt(real * real + imag * imag) * norm;
      }

    } else if (mode === 'power') {
      const norm = 1 / (fftSize * fftSize);

      // DC index
      const realDc = this.real[0];
      const imagDc = this.imag[0];
      outData[0] = (realDc * realDc + imagDc * imagDc) * norm;

      // Nquyst index
      const realNy = this.real[fftSize / 2];
      const imagNy = this.imag[fftSize / 2];
      outData[fftSize / 2] = (realNy * realNy + imagNy * imagNy) * norm;

      // power spectrum
      for (let i = 1, j = fftSize - 1; i < fftSize / 2; i++, j--) {
        const real = 0.5 * (this.real[i] + this.real[j]);
        const imag = 0.5 * (this.imag[i] - this.imag[j]);

        outData[i] = 4 * (real * real + imag * imag) * norm;
      }
    }

    return outData;
  }

  /** @private */
  processSignal(frame) {
    this.inputSignal(frame.data);
  }
}

export default FFT;
<|endoftext|>


<commit_before>/**
 * exposes public channels to HTTP - instant api ;)
 */

var vine = require('vine'),
prettyjson = require('./prettyjson'),
Url = require('url'),
mime = require('mime'),
Structr = require('structr'),
Middleware = require('./middleware'),
fs = require('fs');

exports.plugin = function(router, params)
{
 	var mw = new Middleware();

 	//TODO: this shouldn't be here :/
 	mw.add(function(ops, next)
 	{

 		//channel exists? skip
 		if(ops.exists) return next();

		var fullPath = ((params.dir || '') + '/' + ops.pathname).replace(/\/+/g,'/'),
		res = ops.res;

		// fileName = unescape(fp);

		fs.stat(fullPath, function(err,stat)
		{
			if(err || stat.isDirectory())
			{
				res.writeHead(404, {'Content-Type': 'text/plain'});
				res.end("404");
				return;
			}

			res.writeHead(200, { 'Content-Length': stat.size, 'Content-Type': ops.mime } );

			fs.createReadStream(fullPath, {flags: 'r',
			encoding: 'binary',
			mode: 0666,
			bufferSize: 4 * 1024})

			.addListener("data", function(chunk){
				res.write(chunk, 'binary');
			})
			.addListener("end", function(chunk){
				//  emitter.emit("success", statCode);
			})
			.addListener("close",function() {
				res.end();
			})
			.addListener("error", function (e) {
				//emitter.emit("error", 500, e);
			});
		});
 	})

	function tryMeta(uri, key, value)
	{
		var meta = {};
		meta[key] = value;

		//return filter, or 1 for "the given request has this metadata"
		return router.has(uri, { meta: meta, type: 'pull'}) ? value : 1;
	}

	function routeListener(channel)
	{
		var route = router.getRoute(channel, { type: 'pull'});

		return route.listeners.length ? route.listeners[0] : null;
	}

	function _404(res)
	{
		res.writeHead(404, {'Content-Type': 'text/plain'});
		res.end("Not Found");
	}

	function _401(res)
	{
		res.writeHead(401, {'Content-Type': 'text/plain'});
		res.end("Unauthorized");
	}

	function onRequest(req, res)
	{

		var urlParts = Url.parse(req.url, true),
		pathParts = urlParts.pathname.match(/(.*?)(?:\.(\w+))?$/);

		var channel = pathParts[1],
		fileType = pathParts[2],
		//mime needed for the response
		mimeType = mime.lookup(fileType || '', 'text/plain'),

		//query data
		query = Structr.copy(urlParts.query, req.query, true);

		//need to check a few things
		var listener = routeListener(channel),
		meta = listener ? listener.meta : null;

		//not public? no http specified? it's private.
		if(meta && !meta['public'] && !meta['http'] && !meta['api'])
		{
			return _401(res);
		}

		var ops = {

			//chanel we're invoking
			channel: channel,

			host: req.headers.host,

			//un-altered pathname
			pathname: urlParts.pathname,

			//data attached in the QS of the data
			query: query,

			//channel exists? use for FS
			exists: !!meta,

			mime: mimeType,

			fileType: fileType,

			//tjhe actual request object
			req: req,

			res: res,

			//metadata by the channel
			channelMeta: meta || {},

			//meta used for the request
			requestMeta: {

				//stream so we can pipe to the user
				stream: 1,

				//passive = return even if the request doesn't exist
				passive: 1,

				//try filtering out the request method before going to the default. e.g: GET, POST, PUT
				method: tryMeta(channel, 'method', req.method.toUpperCase()),
			}
		};

		//run through the middleware, modify anything
		mw.request(ops, function(newOps)
		{

			//finally make the request
			router.pull(newOps.channel, newOps.query, { req: req, meta: newOps.requestMeta, host: newOps.host }, function(request)
			{

				//no request? channel doesn't exist
				if(!request) return _404(res);

				var headers = { };

				//this chunk is used to allow ajax applications to load data from the server
				headers['Access-Control-Allow-Origin'] =  req.headers.origin || '*';

				//is ajax
				if(req.headers['access-control-request-headers'])
				{
					//i believe the timestamp is used so the access control is cached client side, omitting the need
					//to hit the server on every request
					headers['Date'] = (new Date()).toGMTString();

					//allow the headers that were sent
					headers['Access-Control-Allow-Headers'] =  request.headers['access-control-request-headers'];

					//allow only the most common methods
					headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS';

					//allow session data to be passed to the server from ajax. this should really be oauth since this is NOT supported
					//in older browsers
					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
					//from W3C: The string "*" cannot be used for a resource that supports credentials.
					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
					// r.headers['Access-Control-Allow-Credentials'] = 'true';

					//tell the client to store the access control for 17000 seconds
					headers['Access-Control-Max-Age'] = 17000;

					//cache for the time to live, OR 30 days
					// headers['Expires'] = new Date(new Date().getTime() + (route.ttl.client || 3600*24*30)*1000).toGMTString();
				}

				this.pipe({

					/**
					 * translations from beanpole
					 */

					respond: function(response)
					{
						if(response.session)
						{
							headers['Set-Cookie'] = response.session.http;
						}

						//redirect to a different location
						if(response.redirect)
						{
							request.statusCode = 301;
							headers['Location'] = response.redirect.indexOf('://') > -1 ? response.redirect : 'http://' + (req.headers.host+'/'+response.redirect).replace(/\/+/g,'\/');
						}

						if(response.mime)
						{
							newOps.mime = response.mime;
						}

						headers['Expires']		 = '17-Jan-2038 19:14:07 GMT';
						headers['Connection'] 	 = 'keep-alive';
						headers['Content-Type']  = urlParts.query.callback ? 'application/x-javascript' : newOps.mime;
						headers['Cache-Control'] = 'max-age=29030400, public';

						res.writeHead(request.statusCode || 200, headers);
					},

					/**
					 */

					write: function(data)
					{
						//is the data an object? is pretty provided?
						var chunk = data instanceof Object ? JSON.stringify(data) : data;

						//meh >.>
						if(typeof chunk == 'boolean') chunk = chunk.toString();

						//pretty print? helps with debugging.
						if(query.pretty != undefined) chunk = prettyjson(chunk);

						//callback provided? wrap the response up
						if(urlParts.query.callback) chunk = request.data.callback +' (' + chunk + ');';

						//send the chunk
						res.write(chunk);
					},

					/**
					 */

					end: function()
					{
						res.end();
					}
				})
			});
		});

	}

 	var startingPort;

    router.on({

    	/**
    	 */

        'push init': function()
        {
        	//params present? start the http port
			if(params)
			{
				if(params.http)
				{
					router.pull('http/start', { port: params.http.port }, function(){});
				}
			}

			router.on({

		        /**
		         * middleware for the requests
		         */

		        'push -pull -multi http/request/middleware': function(middleware)
		        {
		        	mw.add(middleware);
		        }
			});
	    },

        /**
         */

        'push http/server': function(server)
        {
            server.on('request', onRequest);
        }
    })
}
<commit_msg>added basic auth<commit_after>/**
 * exposes public channels to HTTP - instant api ;)
 */

var vine = require('vine'),
prettyjson = require('./prettyjson'),
Url = require('url'),
mime = require('mime'),
Structr = require('structr'),
Middleware = require('./middleware'),
fs = require('fs');

exports.plugin = function(router, params)
{
 	var mw = new Middleware();

 	//TODO: this shouldn't be here :/
 	mw.add(function(ops, next)
 	{

 		//channel exists? skip
 		if(ops.exists) return next();

		var fullPath = ((params.dir || '') + '/' + ops.pathname).replace(/\/+/g,'/'),
		res = ops.res;

		// fileName = unescape(fp);

		fs.stat(fullPath, function(err,stat)
		{
			if(err || stat.isDirectory())
			{
				res.writeHead(404, {'Content-Type': 'text/plain'});
				res.end("404");
				return;
			}

			res.writeHead(200, { 'Content-Length': stat.size, 'Content-Type': ops.mime } );

			fs.createReadStream(fullPath, {flags: 'r',
			encoding: 'binary',
			mode: 0666,
			bufferSize: 4 * 1024})

			.addListener("data", function(chunk){
				res.write(chunk, 'binary');
			})
			.addListener("end", function(chunk){
				//  emitter.emit("success", statCode);
			})
			.addListener("close",function() {
				res.end();
			})
			.addListener("error", function (e) {
				//emitter.emit("error", 500, e);
			});
		});
 	})

	function tryMeta(uri, key, value)
	{
		var meta = {};
		meta[key] = value;

		//return filter, or 1 for "the given request has this metadata"
		return router.has(uri, { meta: meta, type: 'pull'}) ? value : 1;
	}

	function routeListener(channel)
	{
		var route = router.getRoute(channel, { type: 'pull'});

		return route.listeners.length ? route.listeners[0] : null;
	}

	function _404(res)
	{
		res.writeHead(404, {'Content-Type': 'text/plain'});
		res.end("Not Found");
	}

	function _401(res)
	{
		res.writeHead(401, {'Content-Type': 'text/plain'});
		res.end("Unauthorized");
	}

	function onRequest(req, res)
	{

		var urlParts = Url.parse(req.url, true),
		pathParts = urlParts.pathname.match(/(.*?)(?:\.(\w+))?$/);

		var channel = pathParts[1],
		fileType = pathParts[2],
		//mime needed for the response
		mimeType = mime.lookup(fileType || '', 'text/plain'),

		//query data
		query = Structr.copy(urlParts.query, req.query, true);

		//need to check a few things
		var listener = routeListener(channel),
		meta = listener ? listener.meta : null;

		//not public? no http specified? it's private.
		if(meta && !meta['public'] && !meta['http'] && !meta['api'])
		{
			return _401(res);
		}

		var ops = {

			//chanel we're invoking
			channel: channel,

			host: req.headers.host,

			//un-altered pathname
			pathname: urlParts.pathname,

			//data attached in the QS of the data
			query: query,

			//channel exists? use for FS
			exists: !!meta,

			mime: mimeType,

			fileType: fileType,

			//tjhe actual request object
			req: req,

			res: res,

			//metadata by the channel
			channelMeta: meta || {},

			//meta used for the request
			requestMeta: {

				//stream so we can pipe to the user
				stream: 1,

				//passive = return even if the request doesn't exist
				passive: 1,

				//try filtering out the request method before going to the default. e.g: GET, POST, PUT
				method: tryMeta(channel, 'method', req.method.toUpperCase()),
			}
		};

		//run through the middleware, modify anything
		mw.request(ops, function(newOps)
		{

			//finally make the request
			router.pull(newOps.channel, newOps.query, { req: req, meta: newOps.requestMeta, host: newOps.host }, function(request)
			{

				//no request? channel doesn't exist
				if(!request) return _404(res);

				var headers = { };

				//this chunk is used to allow ajax applications to load data from the server
				headers['Access-Control-Allow-Origin'] =  req.headers.origin || '*';

				//is ajax
				if(req.headers['access-control-request-headers'])
				{
					//i believe the timestamp is used so the access control is cached client side, omitting the need
					//to hit the server on every request
					headers['Date'] = (new Date()).toGMTString();

					//allow the headers that were sent
					headers['Access-Control-Allow-Headers'] =  request.headers['access-control-request-headers'];

					//allow only the most common methods
					headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS';

					//allow session data to be passed to the server from ajax. this should really be oauth since this is NOT supported
					//in older browsers
					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
					//from W3C: The string "*" cannot be used for a resource that supports credentials.
					//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
					// r.headers['Access-Control-Allow-Credentials'] = 'true';

					//tell the client to store the access control for 17000 seconds
					headers['Access-Control-Max-Age'] = 17000;

					//cache for the time to live, OR 30 days
					// headers['Expires'] = new Date(new Date().getTime() + (route.ttl.client || 3600*24*30)*1000).toGMTString();
				}

				this.pipe({

					/**
					 * translations from beanpole
					 */

					respond: function(response)
					{
						if(response.session)
						{
							headers['Set-Cookie'] = response.session.http;
						}

						//redirect to a different location
						if(response.redirect)
						{
							request.statusCode = 301;
							headers['Location'] = response.redirect.indexOf('://') > -1 ? response.redirect : 'http://' + (req.headers.host+'/'+response.redirect).replace(/\/+/g,'\/');
						}

						if(response.authorization)
						{
							headers['WWW-Authenticate'] = response.authorization.http;
							request.statusCode = 401;
						}

						if(response.mime)
						{
							newOps.mime = response.mime;
						}

						headers['Expires']		 = '17-Jan-2038 19:14:07 GMT';
						headers['Connection'] 	 = 'keep-alive';
						headers['Content-Type']  = urlParts.query.callback ? 'application/x-javascript' : newOps.mime;
						headers['Cache-Control'] = 'max-age=29030400, public';

						res.writeHead(request.statusCode || 200, headers);
					},

					/**
					 */

					write: function(data)
					{
						//is the data an object? is pretty provided?
						var chunk = data instanceof Object ? JSON.stringify(data) : data;

						//meh >.>
						if(typeof chunk == 'boolean') chunk = chunk.toString();

						//pretty print? helps with debugging.
						if(query.pretty != undefined) chunk = prettyjson(chunk);

						//callback provided? wrap the response up
						if(urlParts.query.callback) chunk = request.data.callback +' (' + chunk + ');';

						//send the chunk
						res.write(chunk);
					},

					/**
					 */

					end: function()
					{
						res.end();
					}
				})
			});
		});

	}

 	var startingPort;

    router.on({

    	/**
    	 */

        'push init': function()
        {
        	//params present? start the http port
			if(params)
			{
				if(params.http)
				{
					router.pull('http/start', { port: params.http.port }, function(){});
				}
			}

			router.on({

		        /**
		         * middleware for the requests
		         */

		        'push -pull -multi http/request/middleware': function(middleware)
		        {
		        	mw.add(middleware);
		        }
			});
	    },

        /**
         */

        'push http/server': function(server)
        {
            server.on('request', onRequest);
        }
    })
}
<|endoftext|>


<commit_before>(function(window, document, undefined) {

	// data specifically for the members page
	var membersData = {
		header: "Member Profiles",
		description: "Get to know the contributors",
		members: [
			{
				name: 'Scott Powers',
				position: 'Co-President',
				joined: 2014,
				image: 'https://lh3.googleusercontent.com/bMun0W0Rf54Z9Nz48tkbaupLPe09EiJk-kegj5l9Grw=s623-no',
				description: "Scott is a PhD student in statistics and an analytics consultant to the Oakland Athletics. In the 2016 spring quarter he will lecture Stanford's STATS 50: Analytic Methods in Sports. Outside of work, he is a catcher on the club baseball team and a setter on the club volleyball team.",
				posts: [
					{
						title: 'The Frictional Cost of a Call to the Bullpen',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/03/24/the-frictional-cost-of-a-call-to-the-bullpen/'
					},
					{
						title: 'A Fresh Take on Batting the Pitcher Eighth',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/05/06/a-fresh-take-on-batting-the-pitcher-eighth/'
					}
				]
			},
			{
				name: 'Vihan Lakshman',
				position: 'Co-President',
				joined: 2014,
				image: 'images/portfolio-2.jpg',
				description: 'I was on the champion 2015 SABR Case Competition team!',
				posts: [
					{
						title: 'Examing MLB Postseason Cluster Luck: Or, Why the Playoffs Might Be a Crapshoot',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/03/24/examining-mlb-postseason-cluster-luck-or-why-the-playoffs-might-be-a-crapshoot/'
					}
				]
			},
			{
				name: 'Eli Shayer',
				position: 'Technology Officer',
				joined: 2014,
				image: 'images/portfolio-3.jpg',
				description: 'I like baseball and stuff',
				posts: [
					{
						title: 'The Frictional Cost of a Call to the Bullpen',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/03/24/the-frictional-cost-of-a-call-to-the-bullpen/'
					},
					{
						title: 'A Fresh Take on Batting the Pitcher Eighth',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/05/06/a-fresh-take-on-batting-the-pitcher-eighth/'
					}
				]
			},
			{
				name: 'Sandy Huang',
				position: 'Financial Officer',
				joined: 2014,
				image: 'images/portfolio-4.jpg',
				description: 'I hold down all the finances',
				posts: [
					{
						title: 'Why We Love Sports Analytics and Richard Sherman',
						link: 'https://stanfordsportsanalytics.wordpress.com/2014/10/08/why-we-love-sports-analytics-and-richard-sherman/'
					}
				]
			},
			{
				name: 'General Member',
				joined: 2015,
				description: 'I like sports. My favorite team is the Stanford Cardinal.'
			}
		]
	};

	var membersTemplate = [
	'{{#with pageData}}',
	    '{{#if members}}',
	        '{{#each members}}',
	            '
',
	                '
',
	                    '
{{ name }}
',
	                    '{{#if position}}
{{ position }}
 {{/if}}',
	                    '{{#if joined}}
Member since {{ joined }}
 {{/if}}',
	                '
',
	                '
',
	                    '{{#if image}}  {{/if}}',
	                '
',
	                '
',
	                    '
{{ description }}
',
	                    '{{#if posts}}',
	                        '
Blog posts:
',
	                        '
',
	                            '{{#each posts}}',
	                                '
{{title}}
',
	                            '{{/each}}',
	                        '
',
	                    '{{/if}}',
	                '
',
	            '
',
	            '
',
	        '{{/each}}',
	    '{{else}}',
	        'No members found.',
	    '{{/if}}',
	'{{/with}}'
	].join('\n');

	// populate page with the above data
	populatePage(membersTemplate, membersData, "#members");

})(this, this.document);
<commit_msg>Fix image src attribute<commit_after>(function(window, document, undefined) {

	// data specifically for the members page
	var membersData = {
		header: "Member Profiles",
		description: "Get to know the contributors",
		members: [
			{
				name: 'Scott Powers',
				position: 'Co-President',
				joined: 2014,
				image: 'https://lh3.googleusercontent.com/bMun0W0Rf54Z9Nz48tkbaupLPe09EiJk-kegj5l9Grw=s623-no',
				description: "Scott is a PhD student in statistics and an analytics consultant to the Oakland Athletics. In the 2016 spring quarter he will lecture Stanford's STATS 50: Analytic Methods in Sports. Outside of work, he is a catcher on the club baseball team and a setter on the club volleyball team.",
				posts: [
					{
						title: 'The Frictional Cost of a Call to the Bullpen',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/03/24/the-frictional-cost-of-a-call-to-the-bullpen/'
					},
					{
						title: 'A Fresh Take on Batting the Pitcher Eighth',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/05/06/a-fresh-take-on-batting-the-pitcher-eighth/'
					}
				]
			},
			{
				name: 'Vihan Lakshman',
				position: 'Co-President',
				joined: 2014,
				image: 'images/portfolio-2.jpg',
				description: 'I was on the champion 2015 SABR Case Competition team!',
				posts: [
					{
						title: 'Examing MLB Postseason Cluster Luck: Or, Why the Playoffs Might Be a Crapshoot',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/03/24/examining-mlb-postseason-cluster-luck-or-why-the-playoffs-might-be-a-crapshoot/'
					}
				]
			},
			{
				name: 'Eli Shayer',
				position: 'Technology Officer',
				joined: 2014,
				image: 'images/portfolio-3.jpg',
				description: 'I like baseball and stuff',
				posts: [
					{
						title: 'The Frictional Cost of a Call to the Bullpen',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/03/24/the-frictional-cost-of-a-call-to-the-bullpen/'
					},
					{
						title: 'A Fresh Take on Batting the Pitcher Eighth',
						link: 'https://stanfordsportsanalytics.wordpress.com/2015/05/06/a-fresh-take-on-batting-the-pitcher-eighth/'
					}
				]
			},
			{
				name: 'Sandy Huang',
				position: 'Financial Officer',
				joined: 2014,
				image: 'images/portfolio-4.jpg',
				description: 'I hold down all the finances',
				posts: [
					{
						title: 'Why We Love Sports Analytics and Richard Sherman',
						link: 'https://stanfordsportsanalytics.wordpress.com/2014/10/08/why-we-love-sports-analytics-and-richard-sherman/'
					}
				]
			},
			{
				name: 'General Member',
				joined: 2015,
				description: 'I like sports. My favorite team is the Stanford Cardinal.'
			}
		]
	};

	var membersTemplate = [
	'{{#with pageData}}',
	    '{{#if members}}',
	        '{{#each members}}',
	            '
',
	                '
',
	                    '
{{ name }}
',
	                    '{{#if position}}
{{ position }}
 {{/if}}',
	                    '{{#if joined}}
Member since {{ joined }}
 {{/if}}',
	                '
',
	                '
',
	                    '{{#if image}}  {{/if}}',
	                '
',
	                '
',
	                    '
{{ description }}
',
	                    '{{#if posts}}',
	                        '
Blog posts:
',
	                        '
',
	                            '{{#each posts}}',
	                                '
{{title}}
',
	                            '{{/each}}',
	                        '
',
	                    '{{/if}}',
	                '
',
	            '
',
	            '
',
	        '{{/each}}',
	    '{{else}}',
	        'No members found.',
	    '{{/if}}',
	'{{/with}}'
	].join('\n');

	// populate page with the above data
	populatePage(membersTemplate, membersData, "#members");

})(this, this.document);
<|endoftext|>