<commit_before>// Derived and adapted from
// https://github.com/rwldrn/duino/blob/development/lib/led.js
var Board = require("../lib/board.js"),
    events = require("events"),
    util = require("util"),
    es6 = require("es6-collections"),
    WeakMap = es6.WeakMap;

// Led instance private data
var leds = [],
    led = new WeakMap();

function Led( opts ) {

  if ( !(this instanceof Led) ) {
    return new Led( opts );
  }

  opts = Board.options( opts );

  // Hardware instance properties
  this.board = Board.mount( opts );
  this.firmata = this.board.firmata;

  // TODO: determine pinMode based on pin?
  //       based on type property?
  this.mode = this.firmata.MODES[ opts.type && opts.type.toUpperCase() || "OUTPUT" ];
  this.pin = opts && opts.pin || 9;

  // LED instance properties
  this.value = 0;
  this.interval = null;

  // Set the output mode
  this.firmata.pinMode( this.pin, this.mode );

  // TODO: use pin capability checks for LED value writing.

  // Create a "state" entry for privately
  // storing the state of the led
  leds.push( this );

  led.set( this, {
    isOn: false,
    isRunning: false,
    value: 0
  });

  Object.defineProperties( this, {
    value: {
      get: function() {
        return led.get( this ).value;
      }
    },
    isOn: {
      get: function() {
        return led.get( this ).isOn;
      }
    }
  });
}

// on()
//
// Turn the Led "on"
//
Led.prototype.on = function() {
  // Reset pinMode to OUTPUT
  if ( this.mode !== this.firmata.MODES.OUTPUT ) {
    this.mode = this.firmata.MODES.OUTPUT;
    this.firmata.pinMode( this.pin, this.mode );
  }

  this.firmata.digitalWrite( this.pin, this.firmata.HIGH );

  led.set( this, {
    isOn: true,
    isRunning: false,
    value: 255
  });

  return this;
};

// off()
//
// Turn the Led "off"
//
Led.prototype.off = function() {
  // Reset pinMode to OUTPUT
  if ( this.mode !== this.firmata.MODES.OUTPUT ) {
    this.mode = this.firmata.MODES.OUTPUT;
    this.firmata.pinMode( this.pin, this.mode );
  }

  this.firmata.digitalWrite( this.pin, this.firmata.LOW );

  led.set( this, {
    isOn: false,
    isRunning: false,
    value: 0
  });

  return this;
};

// toggle()
//
// If the Led is off, turn it on; otherwise, turn it off.
//
Led.prototype.toggle = function() {
  // Reset pinMode to OUTPUT
  if ( this.mode !== this.firmata.MODES.OUTPUT ) {
    this.mode = this.firmata.MODES.OUTPUT;
    this.firmata.pinMode( this.pin, this.mode );
  }

  var ref = led.get( this );

  if ( ref.isOn || ref.isRunning ) {
    this.off();
  } else {
    this.on();
  }

  return this;
};

// brightness( val )
//
// Set the brightness of the led
//
Led.prototype.brightness = function( val ) {

  if ( this.mode !== this.firmata.MODES.PWM ) {
    this.mode = this.firmata.MODES.PWM;
    this.firmata.pinMode( this.pin, this.mode );
  }

  this.firmata.analogWrite( this.pin, val );

  led.set( this, {
    isOn: val ? true : false,
    isRunning: val ? true : false,
    value: val
  });

  return this;
};

// pulse( rate )
//
// Continuous fade in/out
// rate defaults to 1000ms
//
Led.prototype.pulse = function( time ) {
  // Reset pinMode to PWM
  // TODO: check if this pin is capable of PWM
  //       log error if not capable
  if ( this.mode !== this.firmata.MODES.PWM ) {
    this.mode = this.firmata.MODES.PWM;
    this.firmata.pinMode( this.pin, this.mode );
  }

  var to = ( time || 1000 ) / ( 255 * 2 ),
      ref = led.get( this );

  // Avoid traffic jams
  if ( ref.isRunning ) {
    return;
  }

  led.set( this, {
    isOn: true,
    isRunning: true,
    value: ref.value
  });

  this.interval = setInterval(function() {
    var valueAt = led.get( this ).value;

    if ( valueAt === 0 ) {
      direction = 1;
    }

    if ( valueAt === 255 ) {
      direction = -1;
    }

    this.brightness( valueAt + direction );

  }.bind(this), to);

  return this;
};

// fade( val, time )
//
// Fade led brightness value over given time.
//
Led.prototype.fade = function( val, time ) {
  // Reset pinMode to PWM
  // TODO: check if this pin is capable of PWM
  //       log error if not capable
  if ( this.mode !== this.firmata.MODES.PWM ) {
    this.mode = this.firmata.MODES.PWM;
    this.firmata.pinMode( this.pin, this.mode );
  }

  var to = ( time || 1000 ) / ( (val || 255) * 2 ),
      direction = led.get( this ).value <= val ? 1 : -1;

  this.interval = setInterval(function() {
    var valueAt = led.get( this ).value;

    if ( (direction > 0 && valueAt === 255) ||
          (direction < 0 && valueAt === 0) ||
            valueAt === val ) {

      clearInterval( this.interval );
    } else {
      this.brightness( valueAt + direction );
    }
  }.bind(this), to);

  return this;
};

Led.prototype.fadeIn = function( time ) {
  return this.fade( 255, time || 1000 );
};

Led.prototype.fadeOut = function( time ) {
  return this.fade( 0, time || 1000 );
};

// strobe( rate )
//
// Flash led repeatedly, aka. "Blink"
//
Led.prototype.strobe = function( rate ) {
  // Reset pinMode to OUTPUT
  if ( this.mode !== this.firmata.MODES.OUTPUT ) {
    this.mode = this.firmata.MODES.OUTPUT;
    this.firmata.pinMode( this.pin, this.mode );
  }

  // Avoid traffic jams
  if ( led.get(this).isRunning ) {
    return;
  }

  led.set( this, {
    isOn: true,
    isRunning: true,
    value: this.value
  });

  this.interval = setInterval(function() {

    this.toggle();

  }.bind(this), rate || 100 );

  return this;
};

Led.prototype.stop = function() {
  clearInterval( this.interval );
  return this;
};

// TODO:
// Led.prototype.color = function() {
//   ...
//   return this;
// };

// Static API

// Led.Array()
// new Led.Array()
//
// Return Array-like object instance of leds
//
Led.Array = function() {
  if ( !(this instanceof Led.Array) ) {
    return new Led.Array();
  }

  this.length = 0;

  leds.forEach(function( led, index ) {
    this[ index ] = led;

    this.length++;
  }, this );
};

// Led.Array, each( callbackFn )
//
// Execute callbackFn for each active led instance
//
// eg.
// array.each(function( led, index ) {
//
//  `this` refers to the current led instance
//
// });

Led.Array.prototype.each = function( callbackFn ) {
  var led, i, length;

  length = this.length;

  for ( i = 0; i < length; i++ ) {
    led = this[i];
    callbackFn.call( led, led, i );
  }

  return this;
};

// Led.Array, pulse()
//
// pulse all Leds
//
// eg. array.pulse();

// Led.Array, strobe()
//
// strobe all Leds
//
// eg. array.strobe();

[ "pulse", "strobe" ].forEach(function( method ) {
  // Create Led.Array wrappers for each method listed.
  // This will allow us control over all Led instances
  // simultaneously.
  Led.Array.prototype[ method ] = function() {
    var args = [].slice.call( arguments );

    this.each(function( led ) {
      Led.prototype[ method ].apply( led, args );
    });
    return this;
  };
});

module.exports = Led;
<commit_msg>"led"=>"ledMap"<commit_after>// Derived and adapted from
// https://github.com/rwldrn/duino/blob/development/lib/led.js
var Board = require("../lib/board.js"),
    events = require("events"),
    util = require("util"),
    es6 = require("es6-collections"),
    WeakMap = es6.WeakMap;

// Led instance private data
var leds = [],
    ledMap = new WeakMap();

function Led( opts ) {

  if ( !(this instanceof Led) ) {
    return new Led( opts );
  }

  opts = Board.options( opts );

  // Hardware instance properties
  this.board = Board.mount( opts );
  this.firmata = this.board.firmata;

  // TODO: determine pinMode based on pin?
  //       based on type property?
  this.mode = this.firmata.MODES[ opts.type && opts.type.toUpperCase() || "OUTPUT" ];
  this.pin = opts && opts.pin || 9;

  // LED instance properties
  this.value = 0;
  this.interval = null;

  // Set the output mode
  this.firmata.pinMode( this.pin, this.mode );

  // TODO: use pin capability checks for LED value writing.

  // Create a "state" entry for privately
  // storing the state of the led
  leds.push( this );

  ledMap.set( this, {
    isOn: false,
    isRunning: false,
    value: 0
  });

  Object.defineProperties( this, {
    value: {
      get: function() {
        return ledMap.get( this ).value;
      }
    },
    isOn: {
      get: function() {
        return ledMap.get( this ).isOn;
      }
    }
  });
}

// on()
//
// Turn the Led "on"
//
Led.prototype.on = function() {
  // Reset pinMode to OUTPUT
  if ( this.mode !== this.firmata.MODES.OUTPUT ) {
    this.mode = this.firmata.MODES.OUTPUT;
    this.firmata.pinMode( this.pin, this.mode );
  }

  this.firmata.digitalWrite( this.pin, this.firmata.HIGH );

  ledMap.set( this, {
    isOn: true,
    isRunning: false,
    value: 255
  });

  return this;
};

// off()
//
// Turn the Led "off"
//
Led.prototype.off = function() {
  // Reset pinMode to OUTPUT
  if ( this.mode !== this.firmata.MODES.OUTPUT ) {
    this.mode = this.firmata.MODES.OUTPUT;
    this.firmata.pinMode( this.pin, this.mode );
  }

  this.firmata.digitalWrite( this.pin, this.firmata.LOW );

  ledMap.set( this, {
    isOn: false,
    isRunning: false,
    value: 0
  });

  clearInterval( this.interval );

  return this;
};

// toggle()
//
// If the Led is off, turn it on; otherwise, turn it off.
//
Led.prototype.toggle = function() {
  // Reset pinMode to OUTPUT
  if ( this.mode !== this.firmata.MODES.OUTPUT ) {
    this.mode = this.firmata.MODES.OUTPUT;
    this.firmata.pinMode( this.pin, this.mode );
  }

  var ref = ledMap.get( this );

  if ( ref.isOn || ref.isRunning ) {
    this.off();
  } else {
    this.on();
  }

  return this;
};

// brightness( val )
//
// Set the brightness of the led
//
Led.prototype.brightness = function( val ) {

  if ( this.mode !== this.firmata.MODES.PWM ) {
    this.mode = this.firmata.MODES.PWM;
    this.firmata.pinMode( this.pin, this.mode );
  }

  this.firmata.analogWrite( this.pin, val );

  ledMap.set( this, {
    isOn: val ? true : false,
    isRunning: val ? true : false,
    value: val
  });

  return this;
};

// pulse( rate )
//
// Continuous fade in/out
// rate defaults to 1000ms
//
Led.prototype.pulse = function( time ) {
  // Reset pinMode to PWM
  // TODO: check if this pin is capable of PWM
  //       log error if not capable
  if ( this.mode !== this.firmata.MODES.PWM ) {
    this.mode = this.firmata.MODES.PWM;
    this.firmata.pinMode( this.pin, this.mode );
  }

  var to = ( time || 1000 ) / ( 255 * 2 ),
      ref = ledMap.get( this );

  // Avoid traffic jams
  if ( ref.isRunning ) {
    return;
  }

  ledMap.set( this, {
    isOn: true,
    isRunning: true,
    value: ref.value
  });

  this.interval = setInterval(function() {
    var valueAt = ledMap.get( this ).value;

    if ( valueAt === 0 ) {
      direction = 1;
    }

    if ( valueAt === 255 ) {
      direction = -1;
    }

    this.brightness( valueAt + direction );

  }.bind(this), to);

  return this;
};

// fade( val, time )
//
// Fade led brightness value over given time.
//
Led.prototype.fade = function( val, time ) {
  // Reset pinMode to PWM
  // TODO: check if this pin is capable of PWM
  //       log error if not capable
  if ( this.mode !== this.firmata.MODES.PWM ) {
    this.mode = this.firmata.MODES.PWM;
    this.firmata.pinMode( this.pin, this.mode );
  }

  var to = ( time || 1000 ) / ( (val || 255) * 2 ),
      direction = ledMap.get( this ).value <= val ? 1 : -1;

  this.interval = setInterval(function() {
    var valueAt = ledMap.get( this ).value;

    if ( (direction > 0 && valueAt === 255) ||
          (direction < 0 && valueAt === 0) ||
            valueAt === val ) {

      clearInterval( this.interval );
    } else {
      this.brightness( valueAt + direction );
    }
  }.bind(this), to);

  return this;
};

Led.prototype.fadeIn = function( time ) {
  return this.fade( 255, time || 1000 );
};

Led.prototype.fadeOut = function( time ) {
  return this.fade( 0, time || 1000 );
};

// strobe( rate )
//
// Flash led repeatedly, aka. "Blink"
//
Led.prototype.strobe = function( rate ) {
  // Reset pinMode to OUTPUT
  if ( this.mode !== this.firmata.MODES.OUTPUT ) {
    this.mode = this.firmata.MODES.OUTPUT;
    this.firmata.pinMode( this.pin, this.mode );
  }

  // Avoid traffic jams
  // TODO: ensure that
  if ( ledMap.get(this).isRunning ) {
    return;
  }

  ledMap.set( this, {
    isOn: true,
    isRunning: true,
    value: this.value
  });

  this.interval = setInterval(function() {

    this.toggle();

  }.bind(this), rate || 100 );

  return this;
};

Led.prototype.stop = function() {
  var ref = ledMap.get( this );

  clearInterval( this.interval );

  ledMap.set( this, {
    isOn: ref.isOn,
    isRunning: false,
    value: ref.value
  });

  return this;
};

// TODO:
// Led.prototype.color = function() {
//   ...
//   return this;
// };

// Static API

// Led.Array()
// new Led.Array()
//
// Return Array-like object instance of leds
//
Led.Array = function() {
  if ( !(this instanceof Led.Array) ) {
    return new Led.Array();
  }

  this.length = 0;

  leds.forEach(function( led, index ) {
    this[ index ] = led;

    this.length++;
  }, this );
};

// Led.Array, each( callbackFn )
//
// Execute callbackFn for each active led instance
//
// eg.
// array.each(function( led, index ) {
//
//  `this` refers to the current led instance
//
// });

Led.Array.prototype.each = function( callbackFn ) {
  var led, i, length;

  length = this.length;

  for ( i = 0; i < length; i++ ) {
    led = this[i];
    callbackFn.call( led, led, i );
  }

  return this;
};

// Led.Array, pulse()
//
// pulse all Leds
//
// eg. array.pulse();

// Led.Array, strobe()
//
// strobe all Leds
//
// eg. array.strobe();

[ "pulse", "strobe" ].forEach(function( method ) {
  // Create Led.Array wrappers for each method listed.
  // This will allow us control over all Led instances
  // simultaneously.
  Led.Array.prototype[ method ] = function() {
    var args = [].slice.call( arguments );

    this.each(function( led ) {
      Led.prototype[ method ].apply( led, args );
    });
    return this;
  };
});

module.exports = Led;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */
'use strict';

var log = require('npmlog');

// cust config
log.addLevel('debug', 999, {fg: 'grey'}, 'debu');

// monkey patch npmlog…
log.heading = '';
log.headingStyle.fg = 'blue';
log.disp.verbose = 'verbose';
log.disp.error = 'err!';
log.disp.warn = 'warn';
log.style.error.bold = true;
log.style.warn.bold = true;
log.style.warn.fg = 'yellow';

// no bg colors
log.headingStyle.bg =
log.style.verbose.bg =
log.style.warn.bg =
log.style.error.bg =
log.style.http.bg = null;

// disable prefixing
Object.keys(log.levels).forEach(function(level) {
	log[level] = log[level].bind(log, '');
});

module.exports = log;
<commit_msg>normalize verbose level output to 4 char<commit_after>/*
 * Copyright (c) 2011-2013, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */
'use strict';

var log = require('npmlog');

// cust config
log.addLevel('debug', 999, {fg: 'grey'}, 'debu');

// monkey patch npmlog…
log.heading = '';
log.headingStyle.fg = 'blue';
log.disp.verbose = 'verb';
log.disp.error = 'err!';
log.disp.warn = 'warn';
log.style.error.bold = true;
log.style.warn.bold = true;
log.style.warn.fg = 'yellow';

// no bg colors
log.headingStyle.bg =
log.style.verbose.bg =
log.style.warn.bg =
log.style.error.bg =
log.style.http.bg = null;

// disable prefixing
Object.keys(log.levels).forEach(function(level) {
	log[level] = log[level].bind(log, '');
});

module.exports = log;
<|endoftext|>


<commit_before>var fs = require('fs');
var assert = require('assert');
var debug = require('debug')('mmu');

function Mmu(gpu) {

    this.gpu = gpu;

    // Docs
    //
    // - http://imrannazar.com/GameBoy-Emulation-in-JavaScript:-Memory
    // - http://gbdev.gg8.se/wiki/articles/Gameboy_Bootstrap_ROM#Contents_of_the_ROM
    // - http://gameboy.mongenel.com/dmg/asmmemmap.html

    this._hasRunBios = false;
    this._isCartLoaded = false;

    // Memory map
    //
    // $FFFF        Interrupt Enable Flag
    // $FF80-$FFFE  Zero Page - 127 bytes
    // $FF00-$FF7F  Hardware I/O Registers
    // $FEA0-$FEFF  Unusable Memory
    // $FE00-$FE9F  OAM - Object Attribute Memory
    // $E000-$FDFF  Echo RAM - Reserved, Do Not Use
    // $D000-$DFFF  Internal RAM - Bank 1-7 (switchable - CGB only)
    // $C000-$CFFF  Internal RAM - Bank 0 (fixed)
    // $A000-$BFFF  Cartridge RAM (If Available)
    // $9C00-$9FFF  BG Map Data 2
    // $9800-$9BFF  BG Map Data 1
    // $8000-$97FF  Character RAM
    // $4000-$7FFF  Cartridge ROM - Switchable Banks 1-xx
    // $0150-$3FFF  Cartridge ROM - Bank 0 (fixed)
    // $0100-$014F  Cartridge Header Area
    // $0000-$00FF  Restart and Interrupt Vectors

    this._bios = null;

    this._bank0 = null;
    this._eram = null;
    this._wram = null;
    this._zram = null;

    // Interrupts Flags

    // Interrupt Enable Flag
    //
    // Location: $FFFF
    //
    // Notes: When bits are set, the corresponding interrupt can be triggered
    //
    // Details:
    //
    // +-----+--------------+-------------+
    // | Bit | When 0       | When 1      |
    // +-----+--------------+-------------+
    // |  0  | Vblank off   | Vblank on   |
    // |  1  | LCD stat off | LCD stat on |
    // |  2  | Timer off    | Timer on    |
    // |  3  | Serial off   | Serial on   |
    // |  4  | Joypad off   | Joypad on   |
    // +-----+--------------+-------------+

    this._ie = 0;

    // Interrupt flags
    //
    // Location: $FF0F
    //
    // Notes: When bits are set, an interrupt has happened
    //
    // Details: Bits in the same order as FFFF

    this._if = 0;
}

Mmu.prototype.powerOn = function () {

    debug('power on');

    if (!this._isCartLoaded) {
        debug('cannot start without any cart loaded. stop');
        process.exit(1);
    }

    // Load BIOS

    this._bios = new Uint8Array(fs.readFileSync('./support/bios.bin'), 0, 0xFF);

    this._eram = new Uint8Array(0x1FFF);
    this._wram = new Uint8Array(0x03FF);
    this._zram = new Uint8Array(0x7F);
};

Mmu.prototype.loadCart = function (cart) {

    if (!(cart && cart.data)) {
        debug('trying to load cart without being selected. stop');
        process.exit(1);
    }
    debug('load cart');

    this._bank0 = new Uint8Array(cart.data, 0, 0x3FFF);
    this._isCartLoaded = true;
};

Mmu.prototype.readByte = function (addr) {

    assert(!isNaN(addr), 'Invalid address');

    debug('read byte 0x%s', addr.toString(16));

    switch (addr & 0xF000) {

        // $0000-$00FF  Restart and Interrupt Vectors
        // $0100-$014F  Cartridge Header Area
        // $0150-$3FFF  Cartridge ROM - Bank 0 (fixed)

        case 0x0000:
        case 0x1000:
        case 0x2000:
        case 0x3000:

            // BIOS

            if (addr < 0x100 && !this._hasRunBios) return this._bios[addr];
            else if (!this._hasRunBios) {
                debug('leaving BIOS. mapping to bank 0 from now on');
                this._hasRunBios = true;
            }

            // $0150-$3FFF  Cartridge ROM - Bank 0 (fixed)

            return this._bank0[addr];

        default:
            debug('0x%s reading unmapped address. stop', addr.toString(16));
            process.exit(1);
    }
};

Mmu.prototype.writeByte = function (addr, value) {

    assert(!isNaN(addr), 'Invalid address');

    value &= 0xFF;

    debug('write byte 0x%s=0x%s', addr.toString(16), value.toString(16));

    switch (addr & 0xF000) {

        // - [8000-9FFF] Graphics RAM

        case 0x8000: case 0x9000:
            return this.gpu.vram[addr - 0x8000] = value;

        // - [A000-BFFF] Cartridge (External) RAM

        case 0xA000: case 0xB000:
            return this._eram[addr - 0xA000] = value;

        // - [C000-DFFF] Working RAM
        // - [E000-FDFF] Working RAM (shadow)

        case 0xC000: case 0xD000: case 0xE000:
            return this._wram[addr - 0xC000] = value;

        // - [E000-FDFF] Working RAM (shadow)
        // - [FE00-FE9F] Graphics: sprite information
        // - [FF00-FF7F] Memory-mapped I/O
        // - [FF80-FFFE] Zero-page RAM

        case 0xF000:

            // - [E000-FDFF] Working RAM (shadow)

            if (addr <= 0xFDFF) return this._wram[addr - 0xFDFF] = value;

            // - [FE00-FE9F] Graphics: sprite information
            // - [FF00-FF7F] Memory-mapped I/O
            // - [FF80-FFFE] Zero-page RAM

            switch (addr & 0xFF00) {

                // - [FE00-FE9F] Graphics: sprite information

                case 0xFE00: return this.gpu.oam[addr - 0xFE00] = value;

                case 0xFF00:

                    // - [FF0F] Interrupt flags

                    if (addr === 0xFF0F) return this._if = value;

                    // - [FF00-FF7F] Memory-mapped I/O

                    else if (addr < 0xFF80) return 0;

                    // - [FF80-FFFE] Zero-page RAM

                    else if (addr < 0xFFFE) {
                        return this._zram[addr - 0xFE00] = value;
                    }

                default: break
            }

            // - [FFFF] Interrupt enable flag

            if (addr === 0xFFFF) return this._ie = value;

        default:
            debug('0x%s writing unmapped address. stop', addr.toString(16));
            process.exit(1);
    }
};

Mmu.prototype.readWord = function (addr) {

    assert(!isNaN(addr), 'Invalid address');

    debug('read word');
    return this.readByte(addr) | this.readByte(addr + 1) << 8;
};

Mmu.prototype.writeWord = function (addr, value) {

    assert(!isNaN(addr), 'Invalid address');

    debug('write word');
    return this.writeByte(addr, value) |
           this.writeByte(addr + 1, (value & 0xFF00) >> 8) << 8;
};

module.exports = Mmu;
<commit_msg>moar seal<commit_after>'use strict';

var fs = require('fs');
var assert = require('assert');
var debug = require('debug')('mmu');

function Mmu(gpu) {

    this.gpu = gpu;

    // Docs
    //
    // - http://imrannazar.com/GameBoy-Emulation-in-JavaScript:-Memory
    // - http://gbdev.gg8.se/wiki/articles/Gameboy_Bootstrap_ROM#Contents_of_the_ROM
    // - http://gameboy.mongenel.com/dmg/asmmemmap.html

    this._hasRunBios = false;
    this._isCartLoaded = false;

    // Memory map
    //
    // $FFFF        Interrupt Enable Flag
    // $FF80-$FFFE  Zero Page - 127 bytes
    // $FF00-$FF7F  Hardware I/O Registers
    // $FEA0-$FEFF  Unusable Memory
    // $FE00-$FE9F  OAM - Object Attribute Memory
    // $E000-$FDFF  Echo RAM - Reserved, Do Not Use
    // $D000-$DFFF  Internal RAM - Bank 1-7 (switchable - CGB only)
    // $C000-$CFFF  Internal RAM - Bank 0 (fixed)
    // $A000-$BFFF  Cartridge RAM (If Available)
    // $9C00-$9FFF  BG Map Data 2
    // $9800-$9BFF  BG Map Data 1
    // $8000-$97FF  Character RAM
    // $4000-$7FFF  Cartridge ROM - Switchable Banks 1-xx
    // $0150-$3FFF  Cartridge ROM - Bank 0 (fixed)
    // $0100-$014F  Cartridge Header Area
    // $0000-$00FF  Restart and Interrupt Vectors

    this._bios = null;

    this._bank0 = null;
    this._eram = null;
    this._wram = null;
    this._zram = null;

    // Interrupts Flags

    // Interrupt Enable Flag
    //
    // Location: $FFFF
    //
    // Notes: When bits are set, the corresponding interrupt can be triggered
    //
    // Details:
    //
    // +-----+--------------+-------------+
    // | Bit | When 0       | When 1      |
    // +-----+--------------+-------------+
    // |  0  | Vblank off   | Vblank on   |
    // |  1  | LCD stat off | LCD stat on |
    // |  2  | Timer off    | Timer on    |
    // |  3  | Serial off   | Serial on   |
    // |  4  | Joypad off   | Joypad on   |
    // +-----+--------------+-------------+

    this._ie = 0;

    // Interrupt flags
    //
    // Location: $FF0F
    //
    // Notes: When bits are set, an interrupt has happened
    //
    // Details: Bits in the same order as FFFF

    this._if = 0;

    Object.seal(this);
}

Mmu.prototype.powerOn = function () {

    debug('power on');

    if (!this._isCartLoaded) {
        debug('cannot start without any cart loaded. stop');
        process.exit(1);
    }

    // Load BIOS

    this._bios = new Uint8Array(fs.readFileSync('./support/bios.bin'), 0, 0xFF);

    this._eram = new Uint8Array(0x1FFF);
    this._wram = new Uint8Array(0x03FF);
    this._zram = new Uint8Array(0x7F);
};

Mmu.prototype.loadCart = function (cart) {

    if (!(cart && cart.data)) {
        debug('trying to load cart without being selected. stop');
        process.exit(1);
    }
    debug('load cart');

    this._bank0 = new Uint8Array(cart.data, 0, 0x3FFF);
    this._isCartLoaded = true;
};

Mmu.prototype.readByte = function (addr) {

    assert(!isNaN(addr), 'Invalid address');

    debug('read byte 0x%s', addr.toString(16));

    switch (addr & 0xF000) {

        // $0000-$00FF  Restart and Interrupt Vectors
        // $0100-$014F  Cartridge Header Area
        // $0150-$3FFF  Cartridge ROM - Bank 0 (fixed)

        case 0x0000:
        case 0x1000:
        case 0x2000:
        case 0x3000:

            // BIOS

            if (addr < 0x100 && !this._hasRunBios) return this._bios[addr];
            else if (!this._hasRunBios) {
                debug('leaving BIOS. mapping to bank 0 from now on');
                this._hasRunBios = true;
            }

            // $0150-$3FFF  Cartridge ROM - Bank 0 (fixed)

            return this._bank0[addr];

        default:
            debug('0x%s reading unmapped address. stop', addr.toString(16));
            process.exit(1);
    }
};

Mmu.prototype.writeByte = function (addr, value) {

    assert(!isNaN(addr), 'Invalid address');

    value &= 0xFF;

    debug('write byte 0x%s=0x%s', addr.toString(16), value.toString(16));

    switch (addr & 0xF000) {

        // - [8000-9FFF] Graphics RAM

        case 0x8000: case 0x9000:
            return this.gpu.vram[addr - 0x8000] = value;

        // - [A000-BFFF] Cartridge (External) RAM

        case 0xA000: case 0xB000:
            return this._eram[addr - 0xA000] = value;

        // - [C000-DFFF] Working RAM
        // - [E000-FDFF] Working RAM (shadow)

        case 0xC000: case 0xD000: case 0xE000:
            return this._wram[addr - 0xC000] = value;

        // - [E000-FDFF] Working RAM (shadow)
        // - [FE00-FE9F] Graphics: sprite information
        // - [FF00-FF7F] Memory-mapped I/O
        // - [FF80-FFFE] Zero-page RAM

        case 0xF000:

            // - [E000-FDFF] Working RAM (shadow)

            if (addr <= 0xFDFF) return this._wram[addr - 0xFDFF] = value;

            // - [FE00-FE9F] Graphics: sprite information
            // - [FF00-FF7F] Memory-mapped I/O
            // - [FF80-FFFE] Zero-page RAM

            switch (addr & 0xFF00) {

                // - [FE00-FE9F] Graphics: sprite information

                case 0xFE00: return this.gpu.oam[addr - 0xFE00] = value;

                case 0xFF00:

                    // - [FF0F] Interrupt flags

                    if (addr === 0xFF0F) return this._if = value;

                    // - [FF00-FF7F] Memory-mapped I/O

                    else if (addr < 0xFF80) return 0;

                    // - [FF80-FFFE] Zero-page RAM

                    else if (addr < 0xFFFE) {
                        return this._zram[addr - 0xFE00] = value;
                    }

                default: break
            }

            // - [FFFF] Interrupt enable flag

            if (addr === 0xFFFF) return this._ie = value;

        default:
            debug('0x%s writing unmapped address. stop', addr.toString(16));
            process.exit(1);
    }
};

Mmu.prototype.readWord = function (addr) {

    assert(!isNaN(addr), 'Invalid address');

    debug('read word');
    return this.readByte(addr) | this.readByte(addr + 1) << 8;
};

Mmu.prototype.writeWord = function (addr, value) {

    assert(!isNaN(addr), 'Invalid address');

    debug('write word');
    return this.writeByte(addr, value) |
           this.writeByte(addr + 1, (value & 0xFF00) >> 8) << 8;
};

module.exports = Mmu;
<|endoftext|>


<commit_before>var util = require('util');
var CONST = require('./gpio_defines');
var GPIO_PATH = CONST.GPIO_PATH;
var NOOP = function(){};
var utils = require('./utils');
var _export = utils.export;
var _unexport = utils.unexport;
var _read = utils.read;
var _write = utils.write;
var EventEmitter = require('events').EventEmitter;

var isNumeric = function(n){
  return !isNaN(parseFloat(n)) && isFinite(n);
};

var pinEmitter = new EventEmitter();

var checkChanged = (function(){
  var values = {};
  return function(pinNumber, callback){
    var path = GPIO_PATH + 'gpio'+ pinNumber + '/value';
    var now = (new Date()).getTime();
    var old = values[pinNumber]|| (values[pinNumber] = {
      value: null,
      lastChecked: false
    });
    try{
      if(!old.lastChecked || (old.lastChecked-now > CONST.PIN_SCAN_TIME||10)){
        return _read(path, function(err, value){
          if(err){
            return callback(err);
          }
          if(value!==old.value){
            pinEmitter.emit('pin'+pinNumber+':change', value, old.value);
            pinEmitter.emit('pin:change', pinNumber, value, old.value);
            console.log('changed: ', pinNumber, value);
            old.value = value;
          }
          old.lastChecked = (new Date()).getTime();
          callback();
        });
      }
      return callback();
    }catch(e){
      old.lastChecked = (new Date()).getTime();
      callback(e);
    }
  };
})();

var haltScanner = (function(){
  var min = Number.MAX_VALUE, max=0, curr = 0;
  var keys = Object.keys(CONST);
  var reIsPort = /^J\d{1,2}_P\d{1,2}$/;
  var halt = false;

  keys.forEach(function(key){
    val = CONST[key];
    if(isNumeric(val) && val > 0 && key.match(reIsPort)){
      if(val < min){
        min = val;
      }
      if(val > max){
        max = val;
      }
    }
  });

  curr = min;
  var scanner = function _scanner(){
    checkChanged(curr, function(){
      curr++;
      if(curr>max){
        curr = min;
      }
      if(!halt){
        process.nextTick(scanner);
      }
    });
  };
  scanner();
  return function(){
    halt = true;
  };
})();

var Pin = function(opts){
  var self = this;
  var options = isNumeric(opts)?{pin: opts}:opts;
  var pinNumber = options.pin;
  if(!pinNumber){
    throw new Error('No pin number supplied!');
  }
  self._pin = pinNumber;
  self._gpioPath = GPIO_PATH + 'gpio'+ pinNumber;
  if(options.mode){
    self.setMode(options.mode);
  }
};

Pin.prototype.on = function(event, callback){
  var self = this;
  pinEmitter.on('pin'+self.pin+':'+event, callback);
};

Pin.prototype.once = function(event, callback){
  var self = this;
  pinEmitter.once('pin'+self.pin+':'+event, callback);
};

Pin.prototype.removeListener = function(event, callback){
  var self = this;
  pinEmitter.removeListener('pin'+self.pin+':'+event, callback);
};

Pin.prototype.emit = function(event, arg){
  var self = this, args = Array.prototype.slice.call(arguments);
  args.unshift('pin'+self.pin+':'+event);
  EventEmitter.prototype.emit.apply(pinEmitter, args);
};

Pin.prototype.export = function(callback){
  var self = this;
  _export(self._pin, callback);
};

Pin.prototype.unexport = function(pinNumber, callback){
  var self = this;
  _unexport(self._pin, callback);
};

Pin.prototype.getMode = function(callback){
  var self = this;
  var path = self._gpioPath + '/direction';
  try{
    if(callback){
      return _read(path, function(err, dir){
        return callback(null, (dir||'undefined').trim());
      });
    }
    return _read(path);
  }catch(e){
    return 'undefined';
  }
};

Pin.prototype.setMode = function(direction, callback){
  var self = this;
  var mode = direction === 'in' || direction === 'input' ? 'in':'out';
  var path = self._gpioPath + '/direction';
  var checkErrorSendMode = function(err){
    if(err){
      return (callback||NOOP)(err);
    }
    return _read(path, function(err, dir){
      return (callback||function(err, val){
        return val;
      })(null, (dir||'undefined').trim());
    });
  };
  return _read(path, function(err, dir){
    if(err){
      return self.export(function(err){
        if(err){
          return callback(err);
        }
        return _write(path, mode, checkErrorSendMode);
      });
    }
    if(dir.indexOf(mode)===-1){
      return _write(path, mode, checkErrorSendMode);
    }
    return checkErrorSendMode();
  });
};

Pin.prototype.mode = function(newMode, callback){
  var self = this;
  if(typeof(newMode)==='function' || typeof(newMode) === 'undefined'){
    return self.getMode(newMode||callback);
  }
  return self.setMode(newMode, callback);
};

Pin.prototype.get = function(callback){
  var self = this;
  var path = self._gpioPath + '/value';
  return _read(path, callback);
};

Pin.prototype.set = function(value, callback){
  var self = this;
  var path = self._gpioPath + '/value';
  return _write(path, value, function(err){
    if(err){
      self.emit('error', err);
      return (callback||NOOP)(err);
    }
    return (callback||NOOP)(null, value);
  });
};

Pin.prototype.val = function(value, callback){
  var self = this;
  if(typeof(value)==='function' || typeof(value) === 'undefined'){
    return self.get(value||callback);
  }
  return self.set(value, callback);
};

module.exports = Pin;
module.exports.emitter = pinEmitter;
module.exports.haltScanner = haltScanner;
<commit_msg>Remove debug console.log<commit_after>var util = require('util');
var CONST = require('./gpio_defines');
var GPIO_PATH = CONST.GPIO_PATH;
var NOOP = function(){};
var utils = require('./utils');
var _export = utils.export;
var _unexport = utils.unexport;
var _read = utils.read;
var _write = utils.write;
var EventEmitter = require('events').EventEmitter;

var isNumeric = function(n){
  return !isNaN(parseFloat(n)) && isFinite(n);
};

var pinEmitter = new EventEmitter();

var checkChanged = (function(){
  var values = {};
  return function(pinNumber, callback){
    var path = GPIO_PATH + 'gpio'+ pinNumber + '/value';
    var now = (new Date()).getTime();
    var old = values[pinNumber]|| (values[pinNumber] = {
      value: null,
      lastChecked: false
    });
    try{
      if(!old.lastChecked || (old.lastChecked-now > CONST.PIN_SCAN_TIME||10)){
        return _read(path, function(err, value){
          if(err){
            return callback(err);
          }
          if(value!==old.value){
            pinEmitter.emit('pin'+pinNumber+':change', value, old.value);
            pinEmitter.emit('pin:change', pinNumber, value, old.value);
            old.value = value;
          }
          old.lastChecked = (new Date()).getTime();
          callback();
        });
      }
      return callback();
    }catch(e){
      old.lastChecked = (new Date()).getTime();
      callback(e);
    }
  };
})();

var haltScanner = (function(){
  var min = Number.MAX_VALUE, max=0, curr = 0;
  var keys = Object.keys(CONST);
  var reIsPort = /^J\d{1,2}_P\d{1,2}$/;
  var halt = false;

  keys.forEach(function(key){
    val = CONST[key];
    if(isNumeric(val) && val > 0 && key.match(reIsPort)){
      if(val < min){
        min = val;
      }
      if(val > max){
        max = val;
      }
    }
  });

  curr = min;
  var scanner = function _scanner(){
    checkChanged(curr, function(){
      curr++;
      if(curr>max){
        curr = min;
      }
      if(!halt){
        process.nextTick(scanner);
      }
    });
  };
  scanner();
  return function(){
    halt = true;
  };
})();

var Pin = function(opts){
  var self = this;
  var options = isNumeric(opts)?{pin: opts}:opts;
  var pinNumber = options.pin;
  if(!pinNumber){
    throw new Error('No pin number supplied!');
  }
  self._pin = pinNumber;
  self._gpioPath = GPIO_PATH + 'gpio'+ pinNumber;
  if(options.mode){
    self.setMode(options.mode);
  }
};

Pin.prototype.on = function(event, callback){
  var self = this;
  pinEmitter.on('pin'+self.pin+':'+event, callback);
};

Pin.prototype.once = function(event, callback){
  var self = this;
  pinEmitter.once('pin'+self.pin+':'+event, callback);
};

Pin.prototype.removeListener = function(event, callback){
  var self = this;
  pinEmitter.removeListener('pin'+self.pin+':'+event, callback);
};

Pin.prototype.emit = function(event, arg){
  var self = this, args = Array.prototype.slice.call(arguments);
  args.unshift('pin'+self.pin+':'+event);
  EventEmitter.prototype.emit.apply(pinEmitter, args);
};

Pin.prototype.export = function(callback){
  var self = this;
  _export(self._pin, callback);
};

Pin.prototype.unexport = function(pinNumber, callback){
  var self = this;
  _unexport(self._pin, callback);
};

Pin.prototype.getMode = function(callback){
  var self = this;
  var path = self._gpioPath + '/direction';
  try{
    if(callback){
      return _read(path, function(err, dir){
        return callback(null, (dir||'undefined').trim());
      });
    }
    return _read(path);
  }catch(e){
    return 'undefined';
  }
};

Pin.prototype.setMode = function(direction, callback){
  var self = this;
  var mode = direction === 'in' || direction === 'input' ? 'in':'out';
  var path = self._gpioPath + '/direction';
  var checkErrorSendMode = function(err){
    if(err){
      return (callback||NOOP)(err);
    }
    return _read(path, function(err, dir){
      return (callback||function(err, val){
        return val;
      })(null, (dir||'undefined').trim());
    });
  };
  return _read(path, function(err, dir){
    if(err){
      return self.export(function(err){
        if(err){
          return callback(err);
        }
        return _write(path, mode, checkErrorSendMode);
      });
    }
    if(dir.indexOf(mode)===-1){
      return _write(path, mode, checkErrorSendMode);
    }
    return checkErrorSendMode();
  });
};

Pin.prototype.mode = function(newMode, callback){
  var self = this;
  if(typeof(newMode)==='function' || typeof(newMode) === 'undefined'){
    return self.getMode(newMode||callback);
  }
  return self.setMode(newMode, callback);
};

Pin.prototype.get = function(callback){
  var self = this;
  var path = self._gpioPath + '/value';
  return _read(path, callback);
};

Pin.prototype.set = function(value, callback){
  var self = this;
  var path = self._gpioPath + '/value';
  return _write(path, value, function(err){
    if(err){
      self.emit('error', err);
      return (callback||NOOP)(err);
    }
    return (callback||NOOP)(null, value);
  });
};

Pin.prototype.val = function(value, callback){
  var self = this;
  if(typeof(value)==='function' || typeof(value) === 'undefined'){
    return self.get(value||callback);
  }
  return self.set(value, callback);
};

module.exports = Pin;
module.exports.emitter = pinEmitter;
module.exports.haltScanner = haltScanner;
<|endoftext|>


<commit_before>/*doc
---
title: Tabs
name: tabs_react
categories:
 - react_components_tabs
 - react_all
---

npm install pui-react-tabs --save

Require the subcomponents:

```
var Tabs = require('pui-react-tabs').Tabs;
var LeftTabs = require('pui-react-tabs').LeftTabs;
var Tab = require('pui-react-tabs').Tab;
```

Using Tab components in React consists of a parent element for the desired Tab type (for example,
`Tabs` or `LeftTabs`). Each `Tab` is a child of this and has a `tab` property for the
string value a Tab should display. Additionally, each `Tab` must define an `eventKey` property
for uniquely identifying this tab to its parent component.

Property   | Required? | Type             | Description
-----------| ----------|------------------| --------------------------------------------------------------------------
`responsiveBreakpoint` | no        | one of: `"xs"`, `"sm"`, `"md"`, `lg`,          | The size at which the small-screen tabs (accordion-style) should switch to large-screen tabs (folder-style)
`defaultActiveKey` | no            | should equal one of your tab's event keys | The tab which will start out open
`smallScreenClassName` | no  | css class | Will be applied to small screen tabs only
`largeScreenClassName` | no  | css class | Will be applied to large screen tabs only
`onSelect` | no | function | Will override default behavior when clicking on a tab. If you want to retain the default behavior as well as add new functionality, change default active key in the function you provide
`tabType` | no | one of: `"simple"`, `"simple-alt"` | Change the styling of your tabs, mostly whether the selected tab is transparent
`actions` | no | node | an element or text that will display in the upper right

*/

/*doc
---
title: Tabs
name: 01_tabs_react
parent: tabs_react
---

```react_example
<Tabs defaultActiveKey={1} actions={<a>Action!</a>}>
  <Tab eventKey={1} title="Tab 1">Wow!</Tab>
  <Tab eventKey={2} title="Tab 2">
    <h2>Neat!</h2>
    <span>So much content.</span>
  </Tab>
</Tabs>
```
*/

/*doc
---
title: Alt
name: 02_alt_tabs_react
parent: tabs_react
---

```react_example
<Tabs tabType="simple-alt" defaultActiveKey={2}>
  <Tab eventKey={1} title="Tab 1">Wow!</Tab>
  <Tab eventKey={2} title="Tab 2">
    <h2>Neat!</h2>
    <span>So much content.</span>
  </Tab>
</Tabs>
```
*/

/*doc
 ---
 title: Left
 name: 03_left_tabs_react
 parent: tabs_react
 ---

 `LeftTabs` can be used to create tabs where the nav is stacked on the left. They
 take a few optional special properties in addition to the properties in Tabs.

 Property   | Required? | Type             | Description                                  | Default
 -----------| ----------|------------------| ---------------------------------------------|------------------------
 `tabWidth` | no        |  `number`        | The number of bs columns for the tabs        | 6
 `paneWidth` | no       | `number`         | The number of bs columns for the tab content | 24 - `tabWidth`

```react_example
<LeftTabs defaultActiveKey={1} tabWidth={3} paneWidth={9}>
  <Tab eventKey={1} title="Tab 1">Wow!</Tab>
  <Tab eventKey={2} title="Tab 2">
    Neat!
    <span>So much content.</span>
  </Tab>
</LeftTabs>
```

 */

/*doc
---
title: Responsive Breakpoints
name: 04_responsive_tabs_react
parent: tabs_react
---

 Tabs can be responsive, and will display accordion-style on small screens and folder-style on large
 screens.

```react_example
<Tabs defaultActiveKey={1} responsiveBreakpoint="md">
  <Tab eventKey={1} title="Tab 1"> I'm so responsive </Tab>
  <Tab eventKey={2} title="Tab 2"> Me too </Tab>
</Tabs>
```

 */
<commit_msg>chore(Styleguide): Add documentation for new Tabs/Tab properties<commit_after>/*doc
---
title: Tabs
name: tabs_react
categories:
 - react_components_tabs
 - react_all
---

npm install pui-react-tabs --save

Require the subcomponents:

```
var Tabs = require('pui-react-tabs').Tabs;
var LeftTabs = require('pui-react-tabs').LeftTabs;
var Tab = require('pui-react-tabs').Tab;
```

Using Tab components in React consists of a parent element for the desired Tab type (for example,
`Tabs` or `LeftTabs`). Each `Tab` is a child of this and has a `tab` property for the
string value a Tab should display. Additionally, each `Tab` must define an `eventKey` property
for uniquely identifying this tab to its parent component.

##Tabs Properties

Property   | Required? | Type             | Description
-----------| ----------|------------------| --------------------------------------------------------------------------
`actions` | no | node | an element or text that will display in the upper right
`animation` | no | boolean | Whether to animate when moving between tabs, defaults to true
`defaultActiveKey` | no            | should equal one of your tab's event keys | The tab which will start out open
`largeScreenClassName` | no  | css class | Will be applied to large screen tabs only
`onSelect` | no | function | Will override default behavior when clicking on a tab. If you want to retain the default behavior as well as add new functionality, change default active key in the function you provide
`responsiveBreakpoint` | no        | one of: `"xs"`, `"sm"`, `"md"`, `lg`,          | The size at which the small-screen tabs (accordion-style) should switch to large-screen tabs (folder-style)
`smallScreenClassName` | no  | css class | Will be applied to small screen tabs only
`tabType` | no | one of: `"simple"`, `"simple-alt"` | Change the styling of your tabs, mostly whether the selected tab is transparent

##Tab Properties
 Property   | Required? | Type             | Description
 -----------| ----------|------------------| --------------------------------------------------------------------------
 `eventKey` | no | anything | data representing the tab, to be used with `defaultActiveKey` or `onSelect`
 `title` | yes | node | Html rendered in the tab link
 `tabClassName` | no | string | optional className to add to the tab link

*/

/*doc
---
title: Tabs
name: 01_tabs_react
parent: tabs_react
---

```react_example
<Tabs defaultActiveKey={1} actions={<a>Action!</a>}>
  <Tab eventKey={1} title="Tab 1">Wow!</Tab>
  <Tab eventKey={2} title="Tab 2">
    <h2>Neat!</h2>
    <span>So much content.</span>
  </Tab>
</Tabs>
```
*/

/*doc
---
title: Alt
name: 02_alt_tabs_react
parent: tabs_react
---

```react_example
<Tabs tabType="simple-alt" defaultActiveKey={2}>
  <Tab eventKey={1} title="Tab 1">Wow!</Tab>
  <Tab eventKey={2} title="Tab 2">
    <h2>Neat!</h2>
    <span>So much content.</span>
  </Tab>
</Tabs>
```
*/

/*doc
 ---
 title: Left
 name: 03_left_tabs_react
 parent: tabs_react
 ---

 `LeftTabs` can be used to create tabs where the nav is stacked on the left. They
 take a few optional special properties in addition to the properties in Tabs.

 Property   | Required? | Type             | Description                                  | Default
 -----------| ----------|------------------| ---------------------------------------------|------------------------
 `tabWidth` | no        |  `number`        | The number of bs columns for the tabs        | 6
 `paneWidth` | no       | `number`         | The number of bs columns for the tab content | 24 - `tabWidth`

```react_example
<LeftTabs defaultActiveKey={1} tabWidth={3} paneWidth={9}>
  <Tab eventKey={1} title="Tab 1">Wow!</Tab>
  <Tab eventKey={2} title="Tab 2">
    Neat!
    <span>So much content.</span>
  </Tab>
</LeftTabs>
```

 */

/*doc
---
title: Responsive Breakpoints
name: 04_responsive_tabs_react
parent: tabs_react
---

 Tabs can be responsive, and will display accordion-style on small screens and folder-style on large
 screens.

```react_example
<Tabs defaultActiveKey={1} responsiveBreakpoint="md">
  <Tab eventKey={1} title="Tab 1"> I'm so responsive </Tab>
  <Tab eventKey={2} title="Tab 2"> Me too </Tab>
</Tabs>
```

 */
<|endoftext|>


<commit_before>/*!
 * Pop - Main file used by the `pop` binary.
 * Copyright 2011 Alex R. Young
 * MIT Licensed
 */

/**
 * Module dependencies and local variables.
 */
var path = require('path')
  , FileMap = require(__dirname + '/file_map')
  , SiteBuilder = require(__dirname + '/site_builder')
  , cliTools = require(__dirname + '/cli_tools')
  , readConfig = require(__dirname + '/config')
  , usage
  , args = process.argv.slice(2)
  , version = '0.0.1';

usage  = 'pop is a static site builder.\n\n';
usage += 'Usage: pop [command] [options]\n';
usage += 'new    path           Generates a new site at path/\n';
usage += 'post   "Post Title"   Writes a new post file\n';
usage += 'server                Create a server on port 4000 for _site/\n\n';
usage += '-v, --version         Display version and exit\n';
usage += '-h, --help            Shows this message\n';

/**
 * Loads the config script and sets the local variable.
 *
 * @return {Object} Config object
 */
function loadConfig() {
  var root = process.cwd()
    , config = readConfig(path.join(root, '_config.json'));
  config.root = root;
  return config;
}

/**
 * Loads configuration then runs `generateSite`.
 *
 * @params {Boolean} Use a HTTP sever?
 */
function loadConfigAndGenerateSite(useServer) {
  generateSite(loadConfig(), useServer);
}

/**
 * Runs `FileMap` and `SiteBuilder` based on the config.
 *
 * @params {Object} Configuration options
 * @params {Boolean} Use a HTTP sever?
 * @return {SiteBuilder} A `SiteBuilder` instance
 */
function generateSite(config, useServer) {
  var fileMap = new FileMap(config)
    , siteBuilder = new SiteBuilder(config)
    , server = require(__dirname + '/server')(siteBuilder);

  fileMap.walk();
  fileMap.on('ready', function() {
    siteBuilder.fileMap = fileMap;
    siteBuilder.build();
  });

  siteBuilder.on('ready', function() {
    if (useServer) {
      server.run();
      server.watch();
    }
  });

  return siteBuilder;
}

module.exports = function() {
  if (args.length === 0) return loadConfigAndGenerateSite();

  while (args.length) {
    arg = args.shift();
    switch (arg) {
      case 'server':
        loadConfigAndGenerateSite(true);
      break;
      case 'post':
        cliTools.makePost(loadConfig(), args.shift(), function() { process.exit(0); });
      break;
      case 'new':
        cliTools.makeSite(args.shift(), function() { process.exit(0); });
      break;
      case '-v':
      case '--version':
        console.log('pop version:', version);
        process.exit(0);
      break;
      case '-h':
      case '--help':
        console.log(usage);
        process.exit(1);
      default:
        loadConfigAndGenerateSite();
    }
  }
};

module.exports.SiteBuilder = SiteBuilder;
module.exports.FileMap = FileMap;
module.exports.generateSite = generateSite;
module.exports.cliTools = cliTools;
<commit_msg>Updated version<commit_after>/*!
 * Pop - Main file used by the `pop` binary.
 * Copyright 2011 Alex R. Young
 * MIT Licensed
 */

/**
 * Module dependencies and local variables.
 */
var path = require('path')
  , FileMap = require(__dirname + '/file_map')
  , SiteBuilder = require(__dirname + '/site_builder')
  , cliTools = require(__dirname + '/cli_tools')
  , readConfig = require(__dirname + '/config')
  , usage
  , args = process.argv.slice(2)
  , version = '0.0.4';

usage  = 'pop is a static site builder.\n\n';
usage += 'Usage: pop [command] [options]\n';
usage += 'new    path           Generates a new site at path/\n';
usage += 'post   "Post Title"   Writes a new post file\n';
usage += 'server                Create a server on port 4000 for _site/\n\n';
usage += '-v, --version         Display version and exit\n';
usage += '-h, --help            Shows this message\n';

/**
 * Loads the config script and sets the local variable.
 *
 * @return {Object} Config object
 */
function loadConfig() {
  var root = process.cwd()
    , config = readConfig(path.join(root, '_config.json'));
  config.root = root;
  return config;
}

/**
 * Loads configuration then runs `generateSite`.
 *
 * @params {Boolean} Use a HTTP sever?
 */
function loadConfigAndGenerateSite(useServer) {
  generateSite(loadConfig(), useServer);
}

/**
 * Runs `FileMap` and `SiteBuilder` based on the config.
 *
 * @params {Object} Configuration options
 * @params {Boolean} Use a HTTP sever?
 * @return {SiteBuilder} A `SiteBuilder` instance
 */
function generateSite(config, useServer) {
  var fileMap = new FileMap(config)
    , siteBuilder = new SiteBuilder(config)
    , server = require(__dirname + '/server')(siteBuilder);

  fileMap.walk();
  fileMap.on('ready', function() {
    siteBuilder.fileMap = fileMap;
    siteBuilder.build();
  });

  siteBuilder.on('ready', function() {
    if (useServer) {
      server.run();
      server.watch();
    }
  });

  return siteBuilder;
}

module.exports = function() {
  if (args.length === 0) return loadConfigAndGenerateSite();

  while (args.length) {
    arg = args.shift();
    switch (arg) {
      case 'server':
        loadConfigAndGenerateSite(true);
      break;
      case 'post':
        cliTools.makePost(loadConfig(), args.shift(), function() { process.exit(0); });
      break;
      case 'new':
        cliTools.makeSite(args.shift(), function() { process.exit(0); });
      break;
      case '-v':
      case '--version':
        console.log('pop version:', version);
        process.exit(0);
      break;
      case '-h':
      case '--help':
        console.log(usage);
        process.exit(1);
      default:
        loadConfigAndGenerateSite();
    }
  }
};

module.exports.SiteBuilder = SiteBuilder;
module.exports.FileMap = FileMap;
module.exports.generateSite = generateSite;
module.exports.cliTools = cliTools;
<|endoftext|>


<commit_before>(function() {
    'use strict';

    var fs          = require('fs'),
        mkdir       = require('mkdirp');

    module.exports = function(args, fn) {
        if (!args.type)
            fn(Error('"type" could not be empty"'));
        else if (!args.path)
            fn(Error('"path" could not be empty"'));
        else if (args.type === 'file' && !args.format)
            fn(Error('"format" could not be empty"'));
        else if (args.type === 'file' && !args.data)
            fn(Error('"data" could not be empty"'));
        else
            processing(args.type, args.path, args.format, args.data, fn);
    };

    function processing(type, path, format, data, fn) {
        var buffer;

        switch(type) {
        case 'directory':
            mkdir(path, fn);
            break;

        case 'file':
            if (format !== 'base64') {
                fn(Error('format could be base64 only'));
            } else {
                buffer = new Buffer(data, 'base64');
                fs.writeFile(path, buffer, fn);
            }

            break;
        }
    }
})();
<commit_msg>chore(put) rm iife<commit_after>'use strict';

var fs          = require('fs'),
    mkdir       = require('mkdirp');

module.exports = function(args, fn) {
    if (!args.type)
        fn(Error('"type" could not be empty"'));
    else if (!args.path)
        fn(Error('"path" could not be empty"'));
    else if (args.type === 'file' && !args.format)
        fn(Error('"format" could not be empty"'));
    else if (args.type === 'file' && !args.data)
        fn(Error('"data" could not be empty"'));
    else
        processing(args.type, args.path, args.format, args.data, fn);
};

function processing(type, path, format, data, fn) {
    var buffer;

    switch(type) {
    case 'directory':
        mkdir(path, fn);
        break;

    case 'file':
        if (format !== 'base64') {
            fn(Error('format could be base64 only'));
        } else {
            buffer = new Buffer(data, 'base64');
            fs.writeFile(path, buffer, fn);
        }

        break;
    }
}
<|endoftext|>


<commit_before>const url     = require('url');
const request = require('miniget');
const cache   = require('./cache');

/**
 * Extract signature deciphering tokens from html5player file.
 *
 * @param {String} html5playerfile
 * @param {Object} options
 * @param {Function(!Error, Array.<String>)} callback
 */
exports.getTokens = function(html5playerfile, options, callback) {
  var key, cachedTokens;
  var rs = /(?:html5)?player[-_]([a-zA-Z0-9\-_]+)(?:\.js|\/)/
    .exec(html5playerfile);
  if (rs) {
    key = rs[1];
    cachedTokens = cache.get(key);
  } else {
    console.warn('Could not extract html5player key:', html5playerfile);
  }
  if (cachedTokens) {
    callback(null, cachedTokens);
  } else {
    request(html5playerfile, options.requestOptions, function(err, res, body) {
      if (err) return callback(err);

      var tokens = exports.extractActions(body);
      if (key && (!tokens || !tokens.length)) {
        callback(new Error('Could not extract signature deciphering actions'));
        return;
      }

      cache.set(key, tokens);
      callback(null, tokens);
    });
  }
};

/**
 * Decipher a signature based on action tokens.
 *
 * @param {Array.<String>} tokens
 * @param {String} sig
 * @return {String}
 */
exports.decipher = function(tokens, sig) {
  sig = sig.split('');
  var pos;
  for (var i = 0, len = tokens.length; i < len; i++) {
    var token = tokens[i];
    switch (token[0]) {
      case 'r':
        sig = sig.reverse();
        break;
      case 'w':
        pos = ~~token.slice(1);
        sig = swapHeadAndPosition(sig, pos);
        break;
      case 's':
        pos = ~~token.slice(1);
        sig = sig.slice(pos);
        break;
      case 'p':
        pos = ~~token.slice(1);
        sig.splice(0, pos);
        break;
    }
  }
  return sig.join('');
};

/**
 * Swaps the first element of an array with one of given position.
 *
 * @param {Array.<Object>} arr
 * @param {Number} position
 * @return {Array.<Object>}
 */
function swapHeadAndPosition(arr, position) {
  var first = arr[0];
  arr[0] = arr[position % arr.length];
  arr[position] = first;
  return arr;
}

var jsVarStr = '[a-zA-Z_\\$][a-zA-Z_0-9]*';
var jsSingleQuoteStr = '\'[^\'\\\\]*(:?\\\\[\\s\\S][^\'\\\\]*)*\'';
var jsDoubleQuoteStr = '"[^"\\\\]*(:?\\\\[\\s\\S][^"\\\\]*)*"';
var jsQuoteStr = '(?:' + jsSingleQuoteStr + '|' + jsDoubleQuoteStr + ')';
var jsKeyStr = '(?:' + jsVarStr + '|' + jsQuoteStr + ')';
var jsPropStr = '(?:\\.' + jsVarStr + '|\\[' + jsQuoteStr + '\\])';
var jsEmptyStr = '(?:\'\'|"")';
var reverseStr = ':function\\(a\\)\\{' +
  '(?:return )?a\\.reverse\\(\\)' +
'\\}';
var sliceStr = ':function\\(a,b\\)\\{' +
  'return a\\.slice\\(b\\)' +
'\\}';
var spliceStr = ':function\\(a,b\\)\\{' +
  'a\\.splice\\(0,b\\)' +
'\\}';
var swapStr = ':function\\(a,b\\)\\{' +
  'var c=a\\[0\\];a\\[0\\]=a\\[b%a\\.length\\];a\\[b\\]=c(?:;return a)?' +
'\\}';
var actionsObjRegexp = new RegExp(
  'var (' + jsVarStr + ')=\\{((?:(?:' +
    jsKeyStr + reverseStr + '|' +
    jsKeyStr + sliceStr   + '|' +
    jsKeyStr + spliceStr  + '|' +
    jsKeyStr + swapStr +
  '),?\\n?)+)\\};'
);
var actionsFuncRegexp = new RegExp('function(?: ' + jsVarStr + ')?\\(a\\)\\{' +
    'a=a\\.split\\(' + jsEmptyStr + '\\);\\s*' +
    '((?:(?:a=)?' + jsVarStr +
    jsPropStr +
    '\\(a,\\d+\\);)+)' +
    'return a\\.join\\(' + jsEmptyStr + '\\)' +
  '\\}'
);
var reverseRegexp = new RegExp('(?:^|,)(' + jsKeyStr + ')' + reverseStr, 'm');
var sliceRegexp   = new RegExp('(?:^|,)(' + jsKeyStr + ')' + sliceStr, 'm');
var spliceRegexp  = new RegExp('(?:^|,)(' + jsKeyStr + ')' + spliceStr, 'm');
var swapRegexp    = new RegExp('(?:^|,)(' + jsKeyStr + ')' + swapStr, 'm');

/**
 * Extracts the actions that should be taken to decipher a signature.
 *
 * This searches for a function that performs string manipulations on
 * the signature. We already know what the 3 possible changes to a signature
 * are in order to decipher it. There is
 *
 * * Reversing the string.
 * * Removing a number of characters from the beginning.
 * * Swapping the first character with another position.
 *
 * Note, `Array#slice()` used to be used instead of `Array#splice()`,
 * it's kept in case we encounter any older html5player files.
 *
 * After retrieving the function that does this, we can see what actions
 * it takes on a signature.
 *
 * @param {String} body
 * @return {Array.<String>}
 */
exports.extractActions = function(body) {
  var objResult = actionsObjRegexp.exec(body);
  var funcResult = actionsFuncRegexp.exec(body);
  objResult && delete objResult.input;
  funcResult && delete funcResult.input;
  if (!objResult || !funcResult) { return null; }

  var obj      = objResult[1].replace(/\$/g, '\\$');
  var objBody  = objResult[2].replace(/\$/g, '\\$');
  var funcbody = funcResult[1].replace(/\$/g, '\\$');

  var result = reverseRegexp.exec(objBody);
  var reverseKey = result && result[1]
    .replace(/\$/g, '\\$')
    .replace(/\$|^'|^"|'$|"$/g, '');
  result = sliceRegexp.exec(objBody);
  var sliceKey = result && result[1]
    .replace(/\$/g, '\\$')
    .replace(/\$|^'|^"|'$|"$/g, '');
  result = spliceRegexp.exec(objBody);
  var spliceKey = result && result[1]
    .replace(/\$/g, '\\$')
    .replace(/\$|^'|^"|'$|"$/g, '');
  result = swapRegexp.exec(objBody);
  var swapKey = result && result[1]
    .replace(/\$/g, '\\$')
    .replace(/\$|^'|^"|'$|"$/g, '');

  var keys = '(' + [reverseKey, sliceKey, spliceKey, swapKey].join('|') + ')';
  var myreg = '(?:a=)?' + obj +
    '(?:\\.' + keys + '|\\[\'' + keys + '\'\\]|\\["' + keys + '"\\])' +
    '\\(a,(\\d+)\\)';
  var tokenizeRegexp = new RegExp(myreg, 'g');
  var tokens = [];
  while ((result = tokenizeRegexp.exec(funcbody)) !== null) {
    var key = result[1] || result[2] || result[3];
    switch (key) {
      case swapKey:
        tokens.push('w' + result[4]);
        break;
      case reverseKey:
        tokens.push('r');
        break;
      case sliceKey:
        tokens.push('s' + result[4]);
        break;
      case spliceKey:
        tokens.push('p' + result[4]);
        break;
    }
  }
  return tokens;
};

/**
 * @param {Object} format
 * @param {String} sig
 * @param {Boolean} debug
 */
exports.setDownloadURL = function(format, sig, debug) {
  var decodedUrl;
  if (format.url) {
    decodedUrl = format.url;
  } else {
    if (debug) {
      console.warn('Download url not found for itag ' + format.itag);
    }
    return;
  }

  try {
    decodedUrl = decodeURIComponent(decodedUrl);
  } catch (err) {
    if (debug) {
      console.warn('Could not decode url: ' + err.message);
    }
    return;
  }

  // Make some adjustments to the final url.
  var parsedUrl = url.parse(decodedUrl, true);

  // Deleting the `search` part is necessary otherwise changes to
  // `query` won't reflect when running `url.format()`
  delete parsedUrl.search;

  var query = parsedUrl.query;

  // This is needed for a speedier download.
  // See https://github.com/fent/node-ytdl-core/issues/127
  query.ratebypass = 'yes';
  if (sig) {
    query.signature = sig;
  }

  format.url = url.format(parsedUrl);
};

/**
 * Applies `sig.decipher()` to all format URL's.
 *
 * @param {Array.<Object>} formats
 * @param {Array.<String>} tokens
 * @param {Boolean} debug
 */
exports.decipherFormats = function(formats, tokens, debug) {
  formats.forEach(function(format) {
    var sig = tokens && format.s ? exports.decipher(tokens, format.s) : null;
    exports.setDownloadURL(format, sig, debug);
  });
};
<commit_msg>make regexp match more newline types (#195)<commit_after>const url     = require('url');
const request = require('miniget');
const cache   = require('./cache');

/**
 * Extract signature deciphering tokens from html5player file.
 *
 * @param {String} html5playerfile
 * @param {Object} options
 * @param {Function(!Error, Array.<String>)} callback
 */
exports.getTokens = function(html5playerfile, options, callback) {
  var key, cachedTokens;
  var rs = /(?:html5)?player[-_]([a-zA-Z0-9\-_]+)(?:\.js|\/)/
    .exec(html5playerfile);
  if (rs) {
    key = rs[1];
    cachedTokens = cache.get(key);
  } else {
    console.warn('Could not extract html5player key:', html5playerfile);
  }
  if (cachedTokens) {
    callback(null, cachedTokens);
  } else {
    request(html5playerfile, options.requestOptions, function(err, res, body) {
      if (err) return callback(err);

      var tokens = exports.extractActions(body);
      if (key && (!tokens || !tokens.length)) {
        callback(new Error('Could not extract signature deciphering actions'));
        return;
      }

      cache.set(key, tokens);
      callback(null, tokens);
    });
  }
};

/**
 * Decipher a signature based on action tokens.
 *
 * @param {Array.<String>} tokens
 * @param {String} sig
 * @return {String}
 */
exports.decipher = function(tokens, sig) {
  sig = sig.split('');
  var pos;
  for (var i = 0, len = tokens.length; i < len; i++) {
    var token = tokens[i];
    switch (token[0]) {
      case 'r':
        sig = sig.reverse();
        break;
      case 'w':
        pos = ~~token.slice(1);
        sig = swapHeadAndPosition(sig, pos);
        break;
      case 's':
        pos = ~~token.slice(1);
        sig = sig.slice(pos);
        break;
      case 'p':
        pos = ~~token.slice(1);
        sig.splice(0, pos);
        break;
    }
  }
  return sig.join('');
};

/**
 * Swaps the first element of an array with one of given position.
 *
 * @param {Array.<Object>} arr
 * @param {Number} position
 * @return {Array.<Object>}
 */
function swapHeadAndPosition(arr, position) {
  var first = arr[0];
  arr[0] = arr[position % arr.length];
  arr[position] = first;
  return arr;
}

var jsVarStr = '[a-zA-Z_\\$][a-zA-Z_0-9]*';
var jsSingleQuoteStr = '\'[^\'\\\\]*(:?\\\\[\\s\\S][^\'\\\\]*)*\'';
var jsDoubleQuoteStr = '"[^"\\\\]*(:?\\\\[\\s\\S][^"\\\\]*)*"';
var jsQuoteStr = '(?:' + jsSingleQuoteStr + '|' + jsDoubleQuoteStr + ')';
var jsKeyStr = '(?:' + jsVarStr + '|' + jsQuoteStr + ')';
var jsPropStr = '(?:\\.' + jsVarStr + '|\\[' + jsQuoteStr + '\\])';
var jsEmptyStr = '(?:\'\'|"")';
var reverseStr = ':function\\(a\\)\\{' +
  '(?:return )?a\\.reverse\\(\\)' +
'\\}';
var sliceStr = ':function\\(a,b\\)\\{' +
  'return a\\.slice\\(b\\)' +
'\\}';
var spliceStr = ':function\\(a,b\\)\\{' +
  'a\\.splice\\(0,b\\)' +
'\\}';
var swapStr = ':function\\(a,b\\)\\{' +
  'var c=a\\[0\\];a\\[0\\]=a\\[b%a\\.length\\];a\\[b\\]=c(?:;return a)?' +
'\\}';
var actionsObjRegexp = new RegExp(
  'var (' + jsVarStr + ')=\\{((?:(?:' +
    jsKeyStr + reverseStr + '|' +
    jsKeyStr + sliceStr   + '|' +
    jsKeyStr + spliceStr  + '|' +
    jsKeyStr + swapStr +
  '),?\\r?\\n?)+)\\};'
);
var actionsFuncRegexp = new RegExp('function(?: ' + jsVarStr + ')?\\(a\\)\\{' +
    'a=a\\.split\\(' + jsEmptyStr + '\\);\\s*' +
    '((?:(?:a=)?' + jsVarStr +
    jsPropStr +
    '\\(a,\\d+\\);)+)' +
    'return a\\.join\\(' + jsEmptyStr + '\\)' +
  '\\}'
);
var reverseRegexp = new RegExp('(?:^|,)(' + jsKeyStr + ')' + reverseStr, 'm');
var sliceRegexp   = new RegExp('(?:^|,)(' + jsKeyStr + ')' + sliceStr, 'm');
var spliceRegexp  = new RegExp('(?:^|,)(' + jsKeyStr + ')' + spliceStr, 'm');
var swapRegexp    = new RegExp('(?:^|,)(' + jsKeyStr + ')' + swapStr, 'm');

/**
 * Extracts the actions that should be taken to decipher a signature.
 *
 * This searches for a function that performs string manipulations on
 * the signature. We already know what the 3 possible changes to a signature
 * are in order to decipher it. There is
 *
 * * Reversing the string.
 * * Removing a number of characters from the beginning.
 * * Swapping the first character with another position.
 *
 * Note, `Array#slice()` used to be used instead of `Array#splice()`,
 * it's kept in case we encounter any older html5player files.
 *
 * After retrieving the function that does this, we can see what actions
 * it takes on a signature.
 *
 * @param {String} body
 * @return {Array.<String>}
 */
exports.extractActions = function(body) {
  var objResult = actionsObjRegexp.exec(body);
  var funcResult = actionsFuncRegexp.exec(body);
  objResult && delete objResult.input;
  funcResult && delete funcResult.input;
  if (!objResult || !funcResult) { return null; }

  var obj      = objResult[1].replace(/\$/g, '\\$');
  var objBody  = objResult[2].replace(/\$/g, '\\$');
  var funcbody = funcResult[1].replace(/\$/g, '\\$');

  var result = reverseRegexp.exec(objBody);
  var reverseKey = result && result[1]
    .replace(/\$/g, '\\$')
    .replace(/\$|^'|^"|'$|"$/g, '');
  result = sliceRegexp.exec(objBody);
  var sliceKey = result && result[1]
    .replace(/\$/g, '\\$')
    .replace(/\$|^'|^"|'$|"$/g, '');
  result = spliceRegexp.exec(objBody);
  var spliceKey = result && result[1]
    .replace(/\$/g, '\\$')
    .replace(/\$|^'|^"|'$|"$/g, '');
  result = swapRegexp.exec(objBody);
  var swapKey = result && result[1]
    .replace(/\$/g, '\\$')
    .replace(/\$|^'|^"|'$|"$/g, '');

  var keys = '(' + [reverseKey, sliceKey, spliceKey, swapKey].join('|') + ')';
  var myreg = '(?:a=)?' + obj +
    '(?:\\.' + keys + '|\\[\'' + keys + '\'\\]|\\["' + keys + '"\\])' +
    '\\(a,(\\d+)\\)';
  var tokenizeRegexp = new RegExp(myreg, 'g');
  var tokens = [];
  while ((result = tokenizeRegexp.exec(funcbody)) !== null) {
    var key = result[1] || result[2] || result[3];
    switch (key) {
      case swapKey:
        tokens.push('w' + result[4]);
        break;
      case reverseKey:
        tokens.push('r');
        break;
      case sliceKey:
        tokens.push('s' + result[4]);
        break;
      case spliceKey:
        tokens.push('p' + result[4]);
        break;
    }
  }
  return tokens;
};

/**
 * @param {Object} format
 * @param {String} sig
 * @param {Boolean} debug
 */
exports.setDownloadURL = function(format, sig, debug) {
  var decodedUrl;
  if (format.url) {
    decodedUrl = format.url;
  } else {
    if (debug) {
      console.warn('Download url not found for itag ' + format.itag);
    }
    return;
  }

  try {
    decodedUrl = decodeURIComponent(decodedUrl);
  } catch (err) {
    if (debug) {
      console.warn('Could not decode url: ' + err.message);
    }
    return;
  }

  // Make some adjustments to the final url.
  var parsedUrl = url.parse(decodedUrl, true);

  // Deleting the `search` part is necessary otherwise changes to
  // `query` won't reflect when running `url.format()`
  delete parsedUrl.search;

  var query = parsedUrl.query;

  // This is needed for a speedier download.
  // See https://github.com/fent/node-ytdl-core/issues/127
  query.ratebypass = 'yes';
  if (sig) {
    query.signature = sig;
  }

  format.url = url.format(parsedUrl);
};

/**
 * Applies `sig.decipher()` to all format URL's.
 *
 * @param {Array.<Object>} formats
 * @param {Array.<String>} tokens
 * @param {Boolean} debug
 */
exports.decipherFormats = function(formats, tokens, debug) {
  formats.forEach(function(format) {
    var sig = tokens && format.s ? exports.decipher(tokens, format.s) : null;
    exports.setDownloadURL(format, sig, debug);
  });
};
<|endoftext|>


<commit_before>

var compose = require('koa-compose'),
	socketio = require('socket.io'),
	co = require('co'),
	debug = require('debug')('koala-puree:sio'),
	ServerResponse = require('mock-res'), IncomingMessage = require('mock-req'),
	EventEmitter = require('events').EventEmitter,
	util = require('util'),
	Cookies = require('cookies'),
	extend = require('extend');
debug("koala-puree:sio is included")
require('./passport-req')(IncomingMessage.prototype);

exports = module.exports = function(){
	return {
		setup: function *setupSIO(next) {
			console.log("setting up SIO");
			puree = this;
			yield (new Promise(function(resolve, reject){
				var callback = puree._app.callback();
				function handler(origHeaders) {

					delete origHeaders['accept-encoding']
					console.log("handler with origHeader");
					return function _handler(method, route, data,headers, cb) {
						console.log("handler here");
						debug(`entering into sio handler with (${method}, ${route}, ${data}, ${headers})`);
						if ( undefined === cb ) { cb = headers; headers = data; }
						if ( undefined === headers ) { cb = data; }
						var downstream = koaApp.middleware ? koaApp.middleware : koaApp;
						headers = headers || {};

						headers['content-type'] = headers['content-type'] || "application/json";
						headers = extend(origHeaders, headers);

						if ('get head delete'.split(' ').indexOf(method.toLowerCase()) >= 0 && data) {
							route += "?"+require('querystring').stringify(data);
						}
						var req = new IncomingMessage({
							method: method.toUpperCase(),
							url: route,
							headers: headers || {}
						});
						req.connection = this.conn.request.connection;
						// require('extend')(req, this.conn.request);
						if (('get head delete'.split(' ').indexOf(method.toLowerCase()) < 0) && data) {
							req.write(data); req.end();
						}
						var res = new ServerResponse();

						// filling up the headersSent problem
						// res.headersSent = false;
						// res.socket = this.conn.transport;

						// callback.call(puree.app, req, res);

						var context = koaApp.createContext(req, res);
						var fn = co.wrap(compose(downstream));
						debug("attempting to call fn");
						fn.call(context).then(function(){

							var res = context.response;
							debug(`completed ${method} ${route} with ${res.status}, ${res.header}, ${res.body}`);
							if ( util.isFunction(cb) ) {
								if ( res.body && res.body.on ) {
									var buf = [];
									res.body.on('data', function(chunk){
										buf.push(chunk.toString('utf8'));
									})
									res.body.on('end', function(chunk){
										if ( chunk) {
											buf.push(chunk.toString('utf8'));
										}
										console.log('calling here^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^')
										cb(res.status, res.header, buf.join(""));
									})
								} else {
									console.log('calling here^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^2')
									cb(res.status, res.header,res.body);
								}
							}
						}).catch(context.onerror);
					}
				}
				debug("Adding sio code into the puree")
				var koaApp = puree.app;
				var nsp = puree.ns || '/';
				// if ( nsp[0] !== "/" ) {
				// 	nsp = "/"+nsp
				// }
				puree.on('listening', function(){
					puree.on('namespace', function(){
						var nsp = puree._ns || '/';
						// puree._sioInstance().close();
						// puree._sioInstance = socketio(puree._server, {transports: ['websocket','polling']});
						puree._sio.close();
						puree._sio = puree._sioInstance.of(nsp);
						puree._sio.on('connection', function(socket){
							debug("socket connected")
							socket.on('s', handler(socket.request.headers));
						});
					})
					if ( !puree._sioInstance ) {
						puree._sioInstance = socketio(puree._server);
					}
					puree._sio = puree._sioInstance.of(nsp);
					// socketio.start(koaApp);
					console.log("arrives here??");
					puree._sio.on('connection', function(socket){
						console.log("socket connected");
						debug("socket connected")
						socket.on('s', handler(socket.request.headers));
					});
				})

				resolve();
			}));
            debug("Completing sio setup");
			yield* next;
			debug("Completing 2nd part setup");
		},
		teardown: function(app) {
			var self = this;
			return new Promise(function(resolve, reject){
				if ( !self._mounted && app._sio.close ) {
					app._sio.close();
				}
				debug("closing sio middleware");
				resolve();
			})
		}
	}
}
<commit_msg>exposing handlers earlier<commit_after>

var compose = require('koa-compose'),
	socketio = require('socket.io'),
	co = require('co'),
	debug = require('debug')('koala-puree:sio'),
	ServerResponse = require('mock-res'), IncomingMessage = require('mock-req'),
	EventEmitter = require('events').EventEmitter,
	util = require('util'),
	Cookies = require('cookies'),
	extend = require('extend');
debug("koala-puree:sio is included")
require('./passport-req')(IncomingMessage.prototype);

exports = module.exports = function(){
	return {
		setup: function *setupSIO(next) {
			console.log("setting up SIO");
			puree = this;
			yield (new Promise(function(resolve, reject){
				var callback = puree._app.callback();
				function handler(origHeaders) {

					delete origHeaders['accept-encoding']
					console.log("handler with origHeader");
					return function _handler(method, route, data,headers, cb) {
						console.log("handler here");
						debug(`entering into sio handler with (${method}, ${route}, ${data}, ${headers})`);
						if ( undefined === cb ) { cb = headers; headers = data; }
						if ( undefined === headers ) { cb = data; }
						var downstream = koaApp.middleware ? koaApp.middleware : koaApp;
						headers = headers || {};

						headers['content-type'] = headers['content-type'] || "application/json";
						headers = extend(origHeaders, headers);

						if ('get head delete'.split(' ').indexOf(method.toLowerCase()) >= 0 && data) {
							route += "?"+require('querystring').stringify(data);
						}
						var req = new IncomingMessage({
							method: method.toUpperCase(),
							url: route,
							headers: headers || {}
						});
						req.connection = this.conn.request.connection;
						// require('extend')(req, this.conn.request);
						if (('get head delete'.split(' ').indexOf(method.toLowerCase()) < 0) && data) {
							req.write(data); req.end();
						}
						var res = new ServerResponse();

						// filling up the headersSent problem
						// res.headersSent = false;
						// res.socket = this.conn.transport;

						// callback.call(puree.app, req, res);

						var context = koaApp.createContext(req, res);
						var fn = co.wrap(compose(downstream));
						debug("attempting to call fn");
						fn.call(context).then(function(){

							var res = context.response;
							debug(`completed ${method} ${route} with ${res.status}, ${res.header}, ${res.body}`);
							if ( util.isFunction(cb) ) {
								if ( res.body && res.body.on ) {
									var buf = [];
									res.body.on('data', function(chunk){
										buf.push(chunk.toString('utf8'));
									})
									res.body.on('end', function(chunk){
										if ( chunk) {
											buf.push(chunk.toString('utf8'));
										}
										console.log('calling here^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^')
										cb(res.status, res.header, buf.join(""));
									})
								} else {
									console.log('calling here^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^2')
									cb(res.status, res.header,res.body);
								}
							}
						}).catch(context.onerror);
					}
				}
				debug("Adding sio code into the puree")
				var koaApp = puree.app;
				var nsp = puree.ns || '/';
				// if ( nsp[0] !== "/" ) {
				// 	nsp = "/"+nsp
				// }
				puree.on('listening', function(){
					puree.on('namespace', function(){
						var nsp = puree._ns || '/';
						// puree._sioInstance().close();
						// puree._sioInstance = socketio(puree._server, {transports: ['websocket','polling']});
						puree._sio.close();
						puree._sio = puree._sioInstance.of(nsp);
						puree._sio.on('connection', function(socket){
							debug("socket connected")
								puree.sio.emit('connection', socket);
						});
					})
					if ( !puree._sioInstance ) {
						puree._sioInstance = socketio(puree._server);
					}
					puree._sio = puree._sioInstance.of(nsp);
					// socketio.start(koaApp);
					console.log("arrives here??");
					puree._sio.on('connection', function(socket){
						console.log("socket connected");
						debug("socket connected")
						puree.sio.emit('connection', socket);
					});
				})

				resolve();
			}));
            debug("Completing sio setup");
			puree.sio = new EventEmitter();
			puree.sio.on('connection', function(socket){
				socket.on('s', handler(socket.request.headers));
			});
			yield* next;
			debug("Completing 2nd part setup");
		},
		teardown: function(app) {
			var self = this;
			return new Promise(function(resolve, reject){
				if ( !self._mounted && app._sio.close ) {
					app._sio.close();
				}
				debug("closing sio middleware");
				resolve();
			})
		}
	}
}
<|endoftext|>


<commit_before>var glm = require('gl-matrix'),
    vec3 = glm.vec3,
    vec4 = glm.vec4,
    mat4 = glm.mat4,
    quat = glm.quat;
var scratch = require('./scratch');
var Shapes = require('./shapes');

var Weather = function(gl, shader, textures) {
    this.gl = gl;
    this.shader = shader;
    this.textures = textures;

    /*
    this.lightTypes = {
        dark: vec3.fromValues(0, 0, 0),
        dawn: vec3.fromValues(0.8, 0.5, 0.5),
        full: vec3.fromValues(0.8, 0.8, 0.75),
        dusk: vec3.fromValues(0.8, 0.5, 0.5)
    };
    */

    // HELPERS
    // be mindful of the ambient light value and it's affect with full sun
    this.lightTypes = {
        dark: vec3.fromValues(0, 0, 0),
        dawn: vec3.fromValues(0.2, 0.1, 0.1),
        full: vec3.fromValues(0.4, 0.4, 0.4),
        dusk: vec3.fromValues(0.2, 0.1, 0.1)
    };
    this.ambientLightTypes = {
        dark: vec3.fromValues(0.5, 0.5, 0.5),
        dawn: vec3.fromValues(0.55, 0.55, 0.55),
        full: vec3.fromValues(0.6, 0.6, 0.6),
        dusk: vec3.fromValues(0.55, 0.55, 0.55)
    };
    this.rotationPerSecond = (2 * Math.PI) / 86400;
    this._sunLightVector = vec3.fromValues(0.0, -1, 0.2);

    // Seconds from 12 noon
    this.time = 12 * 3600;
    this.light = this.lightTypes.full;
    this.lightAdjustment = vec3.fromValues(0, 0, 0);
    this.ambientLight = this.ambientLightTypes.full;
    this.ambientLightAdjustment = vec3.fromValues(0, 0, 0);

    this.directionalLight = {
        color: vec3.create(),
        vector: vec3.create()
    };
    this.ambientLightColor = vec3.create();
    // Initial setup
    vec3.copy(this.directionalLight.color, this.light);
    vec3.copy(this.ambientLightColor, this.ambientLight);

    var d = 6;
    var uv = [
        0, 0, d, d,
        0, 0, d, d,
        0, 0, d, d,
        0, 0, d, d,
        0, 0, d, d,
        0, 0, d, d
    ];
    this.sun = Shapes.three.rectangle(d, d, d, uv, 1);
    //mat4.translate(this.sun.view, this.sun.view, [0, 100, 0]);
    this.meshes = [this.sun];

    this.initMeshes();
};

Weather.prototype.initMeshes = function() {
    var gl = this.gl;
    var meshes = this.meshes;

    for (var i = 0; i < meshes.length; i++) {
        var mesh = meshes[i];
        mesh.buffers = {
            vertices: gl.createBuffer(),
            //indices: gl.createBuffer(),
            normal: gl.createBuffer(),
            texcoord: gl.createBuffer()
        };

        // Fill with points that we'll translate per player
        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertices);
        gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW);

        //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.buffers.indices);
        //gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.normal);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(mesh.normals), gl.STATIC_DRAW);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.texcoord);
        gl.bufferData(gl.ARRAY_BUFFER, mesh.texcoords, gl.STATIC_DRAW);

        mesh.tuples = 36;
    }
};

Weather.prototype.setLight = function(seconds) {
    var light, ambientLight;
    // Darkness
    if (this.time >= 20 * 3600) {
        // Directional
        this.light = light = this.lightTypes.dark;
        vec3.copy(this.directionalLight.color, light);
        this.lightAdjustment[0] = 0.0;
        this.lightAdjustment[1] = 0.0;
        this.lightAdjustment[2] = 0.0;
        // Ambient
        this.ambientLight = ambientLight = this.ambientLightTypes.dark;
        vec3.copy(this.ambientLightColor, ambientLight);
        this.ambientLightAdjustment[0] = 0.0;
        this.ambientLightAdjustment[1] = 0.0;
        this.ambientLightAdjustment[2] = 0.0;
    } else
    // Transition to dark
    if (this.time >= 19 * 3600) {
        light = this.lightTypes.dark;
        ambientLight = this.ambientLightTypes.dark;
    } else
    // Transition to dusk
    if (this.time >= 18 * 3600) {
        light = this.lightTypes.dusk;
        ambientLight = this.ambientLightTypes.dusk;
    } else
    // Full sunlight
    if (this.time >= 8 * 3600) {
        this.light = light = this.lightTypes.full;
        vec3.copy(this.directionalLight.color, light);
        this.lightAdjustment[0] = 0.0;
        this.lightAdjustment[1] = 0.0;
        this.lightAdjustment[2] = 0.0;
        // Ambient
        this.ambientLight = ambientLight = this.ambientLightTypes.full;
        vec3.copy(this.ambientLightColor, ambientLight);
        this.ambientLightAdjustment[0] = 0.0;
        this.ambientLightAdjustment[1] = 0.0;
        this.ambientLightAdjustment[2] = 0.0;
    } else
    // Transition to full
    if (this.time >= 7 * 3600) {
        light = this.lightTypes.full;
        ambientLight = this.ambientLightTypes.full;
    } else
    // Transition to dawn
    if (this.time >= 6 * 3600) {
        light = this.lightTypes.dawn;
        ambientLight = this.ambientLightTypes.dawn;
    } else {
        light = this.lightTypes.dark;
        ambientLight = this.ambientLightTypes.dark;
    }

    if (light != this.light) {
        // Calculate the adjustment
        vec3.sub(this.lightAdjustment, light, this.directionalLight.color);
        vec3.divide(this.lightAdjustment, this.lightAdjustment, [3600, 3600, 3600]);
        vec3.multiply(this.lightAdjustment, this.lightAdjustment, [seconds, seconds, seconds]);
        //vec3.copy(this.directionalLight.color, light);
        this.light = light;
    }
    if (ambientLight != this.ambientLight) {
        // Ambient
        vec3.sub(this.ambientLightAdjustment, ambientLight, this.ambientLightColor);
        vec3.divide(this.ambientLightAdjustment, this.ambientLightAdjustment, [3600, 3600, 3600]);
        vec3.multiply(this.ambientLightAdjustment, this.ambientLightAdjustment, [seconds, seconds, seconds]);
        //vec3.copy(this.directionalLight.color, light);
        this.ambientLight = ambientLight;
    }
    // Do the adjustment
    vec3.add(this.directionalLight.color, this.directionalLight.color, this.lightAdjustment);
    vec3.add(this.ambientLightColor, this.ambientLightColor, this.ambientLightAdjustment);
};

// Currently runs every second
Weather.prototype.tick = function(seconds) {
    // Need to accompany this with a large cube sun travelling overhead
    this.time += seconds;
    if (this.time >= 86400) {
        this.time -= 86400;
    }
    this.setLight(seconds);

    var sunRotation = this.rotationPerSecond * this.time;

    // Rotate light source
    quat.rotateZ(scratch.quat, scratch.identityQuat, sunRotation);
    vec3.transformQuat(this.directionalLight.vector, this._sunLightVector, scratch.quat);

    // Move sun's position
    mat4.rotateZ(this.sun.view, scratch.identityMat4, sunRotation);
    mat4.translate(this.sun.view, this.sun.view, [0, -200, 0]);
};

var full = vec3.fromValues(1.1, 1.1, 1.1);
Weather.prototype.render = function(projection, ts) {
    var gl = this.gl;

    gl.useProgram(this.shader.program);

    gl.uniform1f(this.shader.uniforms.textureOffset, 0);
    // To simulate brightness, make the sun washed out for now
    gl.uniform3fv(this.shader.uniforms.ambientLightColor, full);
    gl.uniformMatrix4fv(this.shader.uniforms.projection, false, projection);
    //gl.uniformMatrix4fv(this.shaderUniforms.player, false, model);
    //gl.uniform4fv(this.shaderUniforms.color, [ 0, 255, 255, 1 ]);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, this.textures.byName.sandstone.glTexture);
    // bind the texture to this handle
    gl.uniform1i(this.shader.uniforms.texture, 0);

    var meshes = this.meshes;
    for (var i = 0; i < meshes.length; i++) {
        var mesh = meshes[i];

        gl.uniformMatrix4fv(this.shader.uniforms.view, false, mesh.view);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertices);
        gl.enableVertexAttribArray(this.shader.attributes.position);
        gl.vertexAttribPointer(this.shader.attributes.position, 3, gl.FLOAT, false, 0, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.normal);
        gl.enableVertexAttribArray(this.shader.attributes.normal);
        gl.vertexAttribPointer(this.shader.attributes.normal, 3, gl.FLOAT, false, 0, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.texcoord);
        gl.enableVertexAttribArray(this.shader.attributes.texcoord);
        gl.vertexAttribPointer(this.shader.attributes.texcoord, 2, gl.FLOAT, false, 0, 0);

        //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.buffers.indices);
        //gl.drawElements(gl.TRIANGLES, mesh.tuples, gl.UNSIGNED_SHORT, 0);
        gl.drawArrays(gl.TRIANGLES, 0, mesh.tuples);

    }
};

module.exports = Weather;
<commit_msg>make nighttime a bit darker<commit_after>var glm = require('gl-matrix'),
    vec3 = glm.vec3,
    vec4 = glm.vec4,
    mat4 = glm.mat4,
    quat = glm.quat;
var scratch = require('./scratch');
var Shapes = require('./shapes');

var Weather = function(gl, shader, textures) {
    this.gl = gl;
    this.shader = shader;
    this.textures = textures;

    /*
    this.lightTypes = {
        dark: vec3.fromValues(0, 0, 0),
        dawn: vec3.fromValues(0.8, 0.5, 0.5),
        full: vec3.fromValues(0.8, 0.8, 0.75),
        dusk: vec3.fromValues(0.8, 0.5, 0.5)
    };
    */

    // HELPERS
    // be mindful of the ambient light value and it's affect with full sun
    this.lightTypes = {
        dark: vec3.fromValues(0, 0, 0),
        dawn: vec3.fromValues(0.2, 0.1, 0.1),
        full: vec3.fromValues(0.4, 0.4, 0.4),
        dusk: vec3.fromValues(0.2, 0.1, 0.1)
    };
    this.ambientLightTypes = {
        dark: vec3.fromValues(0.4, 0.4, 0.4),
        dawn: vec3.fromValues(0.5, 0.5, 0.5),
        full: vec3.fromValues(0.6, 0.6, 0.6),
        dusk: vec3.fromValues(0.5, 0.5, 0.5)
    };
    this.rotationPerSecond = (2 * Math.PI) / 86400;
    this._sunLightVector = vec3.fromValues(0.0, -1, 0.2);

    // Seconds from 12 noon
    this.time = 12 * 3600;
    this.light = this.lightTypes.full;
    this.lightAdjustment = vec3.fromValues(0, 0, 0);
    this.ambientLight = this.ambientLightTypes.full;
    this.ambientLightAdjustment = vec3.fromValues(0, 0, 0);

    this.directionalLight = {
        color: vec3.create(),
        vector: vec3.create()
    };
    this.ambientLightColor = vec3.create();
    // Initial setup
    vec3.copy(this.directionalLight.color, this.light);
    vec3.copy(this.ambientLightColor, this.ambientLight);

    var d = 6;
    var uv = [
        0, 0, d, d,
        0, 0, d, d,
        0, 0, d, d,
        0, 0, d, d,
        0, 0, d, d,
        0, 0, d, d
    ];
    this.sun = Shapes.three.rectangle(d, d, d, uv, 1);
    //mat4.translate(this.sun.view, this.sun.view, [0, 100, 0]);
    this.meshes = [this.sun];

    this.initMeshes();
};

Weather.prototype.initMeshes = function() {
    var gl = this.gl;
    var meshes = this.meshes;

    for (var i = 0; i < meshes.length; i++) {
        var mesh = meshes[i];
        mesh.buffers = {
            vertices: gl.createBuffer(),
            //indices: gl.createBuffer(),
            normal: gl.createBuffer(),
            texcoord: gl.createBuffer()
        };

        // Fill with points that we'll translate per player
        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertices);
        gl.bufferData(gl.ARRAY_BUFFER, mesh.vertices, gl.STATIC_DRAW);

        //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.buffers.indices);
        //gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, mesh.indices, gl.STATIC_DRAW);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.normal);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(mesh.normals), gl.STATIC_DRAW);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.texcoord);
        gl.bufferData(gl.ARRAY_BUFFER, mesh.texcoords, gl.STATIC_DRAW);

        mesh.tuples = 36;
    }
};

Weather.prototype.setLight = function(seconds) {
    var light, ambientLight;
    // Darkness
    if (this.time >= 20 * 3600) {
        // Directional
        this.light = light = this.lightTypes.dark;
        vec3.copy(this.directionalLight.color, light);
        this.lightAdjustment[0] = 0.0;
        this.lightAdjustment[1] = 0.0;
        this.lightAdjustment[2] = 0.0;
        // Ambient
        this.ambientLight = ambientLight = this.ambientLightTypes.dark;
        vec3.copy(this.ambientLightColor, ambientLight);
        this.ambientLightAdjustment[0] = 0.0;
        this.ambientLightAdjustment[1] = 0.0;
        this.ambientLightAdjustment[2] = 0.0;
    } else
    // Transition to dark
    if (this.time >= 19 * 3600) {
        light = this.lightTypes.dark;
        ambientLight = this.ambientLightTypes.dark;
    } else
    // Transition to dusk
    if (this.time >= 18 * 3600) {
        light = this.lightTypes.dusk;
        ambientLight = this.ambientLightTypes.dusk;
    } else
    // Full sunlight
    if (this.time >= 8 * 3600) {
        this.light = light = this.lightTypes.full;
        vec3.copy(this.directionalLight.color, light);
        this.lightAdjustment[0] = 0.0;
        this.lightAdjustment[1] = 0.0;
        this.lightAdjustment[2] = 0.0;
        // Ambient
        this.ambientLight = ambientLight = this.ambientLightTypes.full;
        vec3.copy(this.ambientLightColor, ambientLight);
        this.ambientLightAdjustment[0] = 0.0;
        this.ambientLightAdjustment[1] = 0.0;
        this.ambientLightAdjustment[2] = 0.0;
    } else
    // Transition to full
    if (this.time >= 7 * 3600) {
        light = this.lightTypes.full;
        ambientLight = this.ambientLightTypes.full;
    } else
    // Transition to dawn
    if (this.time >= 6 * 3600) {
        light = this.lightTypes.dawn;
        ambientLight = this.ambientLightTypes.dawn;
    } else {
        light = this.lightTypes.dark;
        ambientLight = this.ambientLightTypes.dark;
    }

    if (light != this.light) {
        // Calculate the adjustment
        vec3.sub(this.lightAdjustment, light, this.directionalLight.color);
        vec3.divide(this.lightAdjustment, this.lightAdjustment, [3600, 3600, 3600]);
        vec3.multiply(this.lightAdjustment, this.lightAdjustment, [seconds, seconds, seconds]);
        //vec3.copy(this.directionalLight.color, light);
        this.light = light;
    }
    if (ambientLight != this.ambientLight) {
        // Ambient
        vec3.sub(this.ambientLightAdjustment, ambientLight, this.ambientLightColor);
        vec3.divide(this.ambientLightAdjustment, this.ambientLightAdjustment, [3600, 3600, 3600]);
        vec3.multiply(this.ambientLightAdjustment, this.ambientLightAdjustment, [seconds, seconds, seconds]);
        //vec3.copy(this.directionalLight.color, light);
        this.ambientLight = ambientLight;
    }
    // Do the adjustment
    vec3.add(this.directionalLight.color, this.directionalLight.color, this.lightAdjustment);
    vec3.add(this.ambientLightColor, this.ambientLightColor, this.ambientLightAdjustment);
};

// Currently runs every second
Weather.prototype.tick = function(seconds) {
    // Need to accompany this with a large cube sun travelling overhead
    this.time += seconds;
    if (this.time >= 86400) {
        this.time -= 86400;
    }
    this.setLight(seconds);

    var sunRotation = this.rotationPerSecond * this.time;

    // Rotate light source
    quat.rotateZ(scratch.quat, scratch.identityQuat, sunRotation);
    vec3.transformQuat(this.directionalLight.vector, this._sunLightVector, scratch.quat);

    // Move sun's position
    mat4.rotateZ(this.sun.view, scratch.identityMat4, sunRotation);
    mat4.translate(this.sun.view, this.sun.view, [0, -200, 0]);
};

var full = vec3.fromValues(1.1, 1.1, 1.1);
Weather.prototype.render = function(projection, ts) {
    var gl = this.gl;

    gl.useProgram(this.shader.program);

    gl.uniform1f(this.shader.uniforms.textureOffset, 0);
    // To simulate brightness, make the sun washed out for now
    gl.uniform3fv(this.shader.uniforms.ambientLightColor, full);
    gl.uniformMatrix4fv(this.shader.uniforms.projection, false, projection);
    //gl.uniformMatrix4fv(this.shaderUniforms.player, false, model);
    //gl.uniform4fv(this.shaderUniforms.color, [ 0, 255, 255, 1 ]);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, this.textures.byName.sandstone.glTexture);
    // bind the texture to this handle
    gl.uniform1i(this.shader.uniforms.texture, 0);

    var meshes = this.meshes;
    for (var i = 0; i < meshes.length; i++) {
        var mesh = meshes[i];

        gl.uniformMatrix4fv(this.shader.uniforms.view, false, mesh.view);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertices);
        gl.enableVertexAttribArray(this.shader.attributes.position);
        gl.vertexAttribPointer(this.shader.attributes.position, 3, gl.FLOAT, false, 0, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.normal);
        gl.enableVertexAttribArray(this.shader.attributes.normal);
        gl.vertexAttribPointer(this.shader.attributes.normal, 3, gl.FLOAT, false, 0, 0);

        gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.texcoord);
        gl.enableVertexAttribArray(this.shader.attributes.texcoord);
        gl.vertexAttribPointer(this.shader.attributes.texcoord, 2, gl.FLOAT, false, 0, 0);

        //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.buffers.indices);
        //gl.drawElements(gl.TRIANGLES, mesh.tuples, gl.UNSIGNED_SHORT, 0);
        gl.drawArrays(gl.TRIANGLES, 0, mesh.tuples);

    }
};

module.exports = Weather;
<|endoftext|>